diff --git a/source/java/org/alfresco/filesys/alfresco/AlfrescoContext.java b/source/java/org/alfresco/filesys/alfresco/AlfrescoContext.java new file mode 100644 index 0000000000..0c8895a0e7 --- /dev/null +++ b/source/java/org/alfresco/filesys/alfresco/AlfrescoContext.java @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2005-2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.filesys.alfresco; + +import java.util.Enumeration; + +import org.alfresco.filesys.server.filesys.*; +import org.alfresco.filesys.server.pseudo.PseudoFileImpl; +import org.alfresco.filesys.server.pseudo.PseudoFileInterface; +import org.alfresco.filesys.server.state.FileStateReaper; +import org.alfresco.filesys.server.state.FileStateTable; + +/** + * Alfresco Filesystem Context Class + * + *

Contains per filesystem context. + * + * @author GKSpencer + */ +public abstract class AlfrescoContext extends DiskDeviceContext +{ + // File state table and associated file state reaper + + private FileStateTable m_stateTable; + private FileStateReaper m_stateReaper; + + // URL pseudo file web path prefix (server/port/webapp) and link file name + + private String m_urlPathPrefix; + private String m_urlFileName; + + // Pseudo file interface + + private PseudoFileInterface m_pseudoFileInterface; + + // Desktop actions + + private DesktopActionTable m_desktopActions; + + // I/O control handler + + private IOControlHandler m_ioHandler; + + /** + * Class constructor + * + * @param filesysName String + * @param devName String + */ + public AlfrescoContext(String filesysName, String devName) + { + super(filesysName, devName); + + // Default the filesystem to look like an 80Gb sized disk with 90% free space + + setDiskInformation(new SrvDiskInfo(2560000, 64, 512, 2304000)); + + // Set parameters + + setFilesystemAttributes(FileSystem.CasePreservedNames + FileSystem.UnicodeOnDisk + + FileSystem.CaseSensitiveSearch); + } + + /** + * Return the filesystem type, either FileSystem.TypeFAT or FileSystem.TypeNTFS. + * + * @return String + */ + public String getFilesystemType() + { + return FileSystem.TypeNTFS; + } + + /** + * Determine if the file state table is enabled + * + * @return boolean + */ + public final boolean hasStateTable() + { + return m_stateTable != null ? true : false; + } + + /** + * Return the file state table + * + * @return FileStateTable + */ + public final FileStateTable getStateTable() + { + return m_stateTable; + } + + /** + * Enable/disable the file state table + * + * @param ena boolean + * @param stateReaper FileStateReaper + */ + public final void enableStateTable(boolean ena, FileStateReaper stateReaper) + { + if ( ena == false) + { + // Remove the state table from the reaper + + stateReaper.removeStateTable( getFilesystemName()); + m_stateTable = null; + } + else if ( m_stateTable == null) + { + // Create the file state table + + m_stateTable = new FileStateTable(); + + // Register with the file state reaper + + stateReaper.addStateTable( getFilesystemName(), m_stateTable); + } + + // Save the reaper, for deregistering when the filesystem is closed + + m_stateReaper = stateReaper; + } + + /** + * Determine if the pseudo file interface is enabled + * + * @return boolean + */ + public final boolean hasPseudoFileInterface() + { + return m_pseudoFileInterface != null ? true : false; + } + + /** + * Return the pseudo file interface + * + * @return PseudoFileInterface + */ + public final PseudoFileInterface getPseudoFileInterface() + { + return m_pseudoFileInterface; + } + + /** + * Enable the pseudo file interface for this filesystem + */ + public final void enabledPseudoFileInterface() + { + if ( m_pseudoFileInterface == null) + m_pseudoFileInterface = new PseudoFileImpl(); + } + + /** + * Determine if there are desktop actins configured + * + * @return boolean + */ + public final boolean hasDesktopActions() + { + return m_desktopActions != null ? true : false; + } + + /** + * Return the desktop actions table + * + * @return DesktopActionTable + */ + public final DesktopActionTable getDesktopActions() + { + return m_desktopActions; + } + + /** + * Return the count of desktop actions + * + * @return int + */ + public final int numberOfDesktopActions() + { + return m_desktopActions != null ? m_desktopActions.numberOfActions() : 0; + } + + /** + * Add a desktop action + * + * @param action DesktopAction + * @return boolean + */ + public final boolean addDesktopAction(DesktopAction action) + { + // Check if the desktop actions table has been created + + if ( m_desktopActions == null) + { + m_desktopActions = new DesktopActionTable(); + + // Enable pseudo files + + enabledPseudoFileInterface(); + } + + // Add the action + + return m_desktopActions.addAction(action); + } + + /** + * Determine if custom I/O control handling is enabled for this filesystem + * + * @return boolean + */ + public final boolean hasIOHandler() + { + return m_ioHandler != null ? true : false; + } + + /** + * Return the custom I/O control handler + * + * @return IOControlHandler + */ + public final IOControlHandler getIOHandler() + { + return m_ioHandler; + } + + /** + * Determine if the URL pseudo file is enabled + * + * @return boolean + */ + public final boolean hasURLFile() + { + if ( m_urlPathPrefix != null && m_urlFileName != null) + return true; + return false; + } + + /** + * Return the URL pseudo file path prefix + * + * @return String + */ + public final String getURLPrefix() + { + return m_urlPathPrefix; + } + + /** + * Return the URL pseudo file name + * + * @return String + */ + public final String getURLFileName() + { + return m_urlFileName; + } + + /** + * Set the URL path prefix + * + * @param urlPrefix String + */ + public final void setURLPrefix(String urlPrefix) + { + m_urlPathPrefix = urlPrefix; + + if ( urlPrefix != null) + enabledPseudoFileInterface(); + } + + /** + * Set the URL pseudo file name + * + * @param urlFileName String + */ + public final void setURLFileName(String urlFileName) + { + m_urlFileName = urlFileName; + + if ( urlFileName != null) + enabledPseudoFileInterface(); + } + + /** + * Set the desktop actions + * + * @param desktopActions DesktopActionTable + * @param filesysDriver DiskInterface + */ + public final void setDesktopActions(DesktopActionTable desktopActions, DiskInterface filesysDriver) + { + // Enumerate the desktop actions and add to this filesystem + + Enumeration names = desktopActions.enumerateActionNames(); + + while ( names.hasMoreElements()) + { + addDesktopAction( desktopActions.getAction(names.nextElement())); + } + + // If there are desktop actions then create the custom I/O control handler + + if ( numberOfDesktopActions() > 0) + { + // Create the custom I/O control handler + + m_ioHandler = createIOHandler( filesysDriver); + if ( m_ioHandler != null) + m_ioHandler.initialize(( AlfrescoDiskDriver) filesysDriver, this); + } + } + + /** + * Create the I/O control handler for this filesystem type + * + * @param filesysDriver DiskInterface + * @return IOControlHandler + */ + protected abstract IOControlHandler createIOHandler( DiskInterface filesysDriver); + + /** + * Close the filesystem context + */ + public void CloseContext() { + + // Deregister the file state table from the reaper + + if ( m_stateTable != null) + enableStateTable( false, m_stateReaper); + + // Call the base class + + super.CloseContext(); + } +} diff --git a/source/java/org/alfresco/filesys/alfresco/AlfrescoDiskDriver.java b/source/java/org/alfresco/filesys/alfresco/AlfrescoDiskDriver.java new file mode 100644 index 0000000000..ca24429076 --- /dev/null +++ b/source/java/org/alfresco/filesys/alfresco/AlfrescoDiskDriver.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.filesys.alfresco; + +import org.alfresco.filesys.server.SrvSession; +import org.alfresco.filesys.server.filesys.IOControlNotImplementedException; +import org.alfresco.filesys.server.filesys.IOCtlInterface; +import org.alfresco.filesys.server.filesys.NetworkFile; +import org.alfresco.filesys.server.filesys.TreeConnection; +import org.alfresco.filesys.server.state.FileStateReaper; +import org.alfresco.filesys.smb.SMBException; +import org.alfresco.filesys.smb.SMBStatus; +import org.alfresco.filesys.util.DataBuffer; +import org.alfresco.service.ServiceRegistry; + +/** + * Alfresco Disk Driver Base Class + * + *

Provides common code to the Alfresco filesystem implementations. + * + * @author gkspencer + */ +public class AlfrescoDiskDriver implements IOCtlInterface { + + // Service registry for desktop actions + + private ServiceRegistry serviceRegistry; + + // File state reaper + + private FileStateReaper m_stateReaper; + + /** + * Return the service registry + * + * @return ServiceRegistry + */ + public final ServiceRegistry getServiceRegistry() + { + return this.serviceRegistry; + } + + /** + * Return the file state reaper + * + * @return FileStateReaper + */ + public final FileStateReaper getStateReaper() + { + return m_stateReaper; + } + + /** + * Set the service registry + * + * @param serviceRegistry + */ + public void setServiceRegistry(ServiceRegistry serviceRegistry) + { + this.serviceRegistry = serviceRegistry; + } + + /** + * Set the file state reaper + * + * @param stateReaper FileStateReaper + */ + public final void setStateReaper(FileStateReaper stateReaper) + { + m_stateReaper = stateReaper; + } + + /** + * Process a filesystem I/O control request + * + * @param sess Server session + * @param tree Tree connection. + * @param ctrlCode I/O control code + * @param fid File id + * @param dataBuf I/O control specific input data + * @param isFSCtrl true if this is a filesystem control, or false for a device control + * @param filter if bit0 is set indicates that the control applies to the share root handle + * @return DataBuffer + * @exception IOControlNotImplementedException + * @exception SMBException + */ + public DataBuffer processIOControl(SrvSession sess, TreeConnection tree, int ctrlCode, int fid, DataBuffer dataBuf, + boolean isFSCtrl, int filter) + throws IOControlNotImplementedException, SMBException + { + // Validate the file id + + NetworkFile netFile = tree.findFile(fid); + if ( netFile == null || netFile.isDirectory() == false) + throw new SMBException(SMBStatus.NTErr, SMBStatus.NTInvalidParameter); + + // Check if the I/O control handler is enabled + + AlfrescoContext ctx = (AlfrescoContext) tree.getContext(); + if ( ctx.hasIOHandler()) + return ctx.getIOHandler().processIOControl( sess, tree, ctrlCode, fid, dataBuf, isFSCtrl, filter); + else + throw new IOControlNotImplementedException(); + } +} diff --git a/source/java/org/alfresco/filesys/smb/server/repo/DesktopAction.java b/source/java/org/alfresco/filesys/alfresco/DesktopAction.java similarity index 83% rename from source/java/org/alfresco/filesys/smb/server/repo/DesktopAction.java rename to source/java/org/alfresco/filesys/alfresco/DesktopAction.java index e5ca0a28e7..43ef0b8f41 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/DesktopAction.java +++ b/source/java/org/alfresco/filesys/alfresco/DesktopAction.java @@ -15,7 +15,7 @@ * License. */ -package org.alfresco.filesys.smb.server.repo; +package org.alfresco.filesys.alfresco; import java.io.File; import java.io.UnsupportedEncodingException; @@ -24,16 +24,10 @@ import java.net.URL; import java.net.URLDecoder; import org.alfresco.config.ConfigElement; -import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.filesys.server.filesys.DiskSharedDevice; -import org.alfresco.filesys.smb.server.repo.pseudo.LocalPseudoFile; -import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFile; +import org.alfresco.filesys.server.pseudo.LocalPseudoFile; +import org.alfresco.filesys.server.pseudo.PseudoFile; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.transaction.TransactionService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -112,8 +106,8 @@ public abstract class DesktopAction { // Filesystem driver and context - private ContentDiskDriver m_contentDriver; - private ContentContext m_contentContext; + private AlfrescoDiskDriver m_filesysDriver; + private AlfrescoContext m_filesysContext; // Webapp URL @@ -225,23 +219,23 @@ public abstract class DesktopAction { } /** - * Return the content filesystem driver + * Return the filesystem driver * - * @return ContentDiskDriver + * @return AlfrescoDiskDriver */ - public final ContentDiskDriver getDriver() + public final AlfrescoDiskDriver getDriver() { - return m_contentDriver; + return m_filesysDriver; } /** * Return the filesystem context * - * @return ContentContext + * @return AlfrescoContext */ - public final ContentContext getContext() + public final AlfrescoContext getContext() { - return m_contentContext; + return m_filesysContext; } /** @@ -254,6 +248,16 @@ public abstract class DesktopAction { return null; } + /** + * Return the service registry + * + * @return ServiceRegistry + */ + public final ServiceRegistry getServiceRegistry() + { + return m_filesysDriver.getServiceRegistry(); + } + /** * Check if debug output is enabled * @@ -313,13 +317,13 @@ public abstract class DesktopAction { { // Save the filesystem device and I/O handler - if ( fileSys.getDiskInterface() instanceof ContentDiskDriver) + if ( fileSys.getContext() instanceof AlfrescoContext) { - m_contentDriver = (ContentDiskDriver) fileSys.getDiskInterface(); - m_contentContext = (ContentContext) fileSys.getDiskContext(); + m_filesysDriver = (AlfrescoDiskDriver) fileSys.getDiskInterface(); + m_filesysContext = (AlfrescoContext) fileSys.getDiskContext(); } else - throw new DesktopActionException("Desktop action requires content filesystem driver"); + throw new DesktopActionException("Desktop action requires an Alfresco filesystem driver"); // Check for standard config values @@ -463,77 +467,6 @@ public abstract class DesktopAction { public abstract DesktopResponse runAction(DesktopParams params) throws DesktopActionException; - /** - * Return the CIFS helper - * - * @return CifsHelper - */ - protected final CifsHelper getCifsHelper() - { - return m_contentDriver.getCifsHelper(); - } - - /** - * Return the transaction service - * - * @return TransactionService - */ - protected final TransactionService getTransactionService() - { - return m_contentDriver.getTransactionService(); - } - - /** - * Return the node service - * - * @return NodeService - */ - protected final NodeService getNodeService() - { - return m_contentDriver.getNodeService(); - } - - - /** - * Return the content service - * - * @return ContentService - */ - public final ContentService getContentService() - { - return m_contentDriver.getContentService(); - } - - /** - * Return the namespace service - * - * @return NamespaceService - */ - public final NamespaceService getNamespaceService() - { - return m_contentDriver.getNamespaceService(); - } - - /** - * Return the search service - * - * @return SearchService - */ - public final SearchService getSearchService() - { - return m_contentDriver.getSearchService(); - } - - /** - * Return the service registry - * - * @return ServiceRegistry - */ - public final ServiceRegistry getServiceRegistry() - { - return m_contentDriver.getServiceRegistry(); - } - /** * Set the action attributes * diff --git a/source/java/org/alfresco/filesys/smb/server/repo/DesktopActionException.java b/source/java/org/alfresco/filesys/alfresco/DesktopActionException.java similarity index 96% rename from source/java/org/alfresco/filesys/smb/server/repo/DesktopActionException.java rename to source/java/org/alfresco/filesys/alfresco/DesktopActionException.java index 1bcda21484..db25c3cbc5 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/DesktopActionException.java +++ b/source/java/org/alfresco/filesys/alfresco/DesktopActionException.java @@ -15,7 +15,7 @@ * License. */ -package org.alfresco.filesys.smb.server.repo; +package org.alfresco.filesys.alfresco; /** * Desktop Action Exception Class diff --git a/source/java/org/alfresco/filesys/smb/server/repo/DesktopActionTable.java b/source/java/org/alfresco/filesys/alfresco/DesktopActionTable.java similarity index 98% rename from source/java/org/alfresco/filesys/smb/server/repo/DesktopActionTable.java rename to source/java/org/alfresco/filesys/alfresco/DesktopActionTable.java index 2bbf452fc4..d3746adbd8 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/DesktopActionTable.java +++ b/source/java/org/alfresco/filesys/alfresco/DesktopActionTable.java @@ -15,7 +15,7 @@ * License. */ -package org.alfresco.filesys.smb.server.repo; +package org.alfresco.filesys.alfresco; import java.util.Enumeration; import java.util.Hashtable; diff --git a/source/java/org/alfresco/filesys/smb/server/repo/DesktopParams.java b/source/java/org/alfresco/filesys/alfresco/DesktopParams.java similarity index 98% rename from source/java/org/alfresco/filesys/smb/server/repo/DesktopParams.java rename to source/java/org/alfresco/filesys/alfresco/DesktopParams.java index 6a45926dc2..73938a0dc7 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/DesktopParams.java +++ b/source/java/org/alfresco/filesys/alfresco/DesktopParams.java @@ -14,7 +14,7 @@ * language governing permissions and limitations under the * License. */ -package org.alfresco.filesys.smb.server.repo; +package org.alfresco.filesys.alfresco; import java.util.ArrayList; import java.util.List; diff --git a/source/java/org/alfresco/filesys/smb/server/repo/DesktopResponse.java b/source/java/org/alfresco/filesys/alfresco/DesktopResponse.java similarity index 98% rename from source/java/org/alfresco/filesys/smb/server/repo/DesktopResponse.java rename to source/java/org/alfresco/filesys/alfresco/DesktopResponse.java index 11ae1b9c94..3b65bd89ae 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/DesktopResponse.java +++ b/source/java/org/alfresco/filesys/alfresco/DesktopResponse.java @@ -14,7 +14,7 @@ * language governing permissions and limitations under the * License. */ -package org.alfresco.filesys.smb.server.repo; +package org.alfresco.filesys.alfresco; import java.util.ArrayList; import java.util.List; diff --git a/source/java/org/alfresco/filesys/smb/server/repo/DesktopTarget.java b/source/java/org/alfresco/filesys/alfresco/DesktopTarget.java similarity index 98% rename from source/java/org/alfresco/filesys/smb/server/repo/DesktopTarget.java rename to source/java/org/alfresco/filesys/alfresco/DesktopTarget.java index 877999c556..84800f8ab3 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/DesktopTarget.java +++ b/source/java/org/alfresco/filesys/alfresco/DesktopTarget.java @@ -14,7 +14,7 @@ * language governing permissions and limitations under the * License. */ -package org.alfresco.filesys.smb.server.repo; +package org.alfresco.filesys.alfresco; import org.alfresco.service.cmr.repository.NodeRef; diff --git a/source/java/org/alfresco/filesys/smb/server/repo/IOControl.java b/source/java/org/alfresco/filesys/alfresco/IOControl.java similarity index 94% rename from source/java/org/alfresco/filesys/smb/server/repo/IOControl.java rename to source/java/org/alfresco/filesys/alfresco/IOControl.java index 75d7009328..164a162ff5 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/IOControl.java +++ b/source/java/org/alfresco/filesys/alfresco/IOControl.java @@ -14,7 +14,7 @@ * language governing permissions and limitations under the * License. */ -package org.alfresco.filesys.smb.server.repo; +package org.alfresco.filesys.alfresco; import org.alfresco.filesys.smb.NTIOCtl; diff --git a/source/java/org/alfresco/filesys/smb/server/repo/IOControlHandler.java b/source/java/org/alfresco/filesys/alfresco/IOControlHandler.java similarity index 67% rename from source/java/org/alfresco/filesys/smb/server/repo/IOControlHandler.java rename to source/java/org/alfresco/filesys/alfresco/IOControlHandler.java index 255f0c5909..35dd12740b 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/IOControlHandler.java +++ b/source/java/org/alfresco/filesys/alfresco/IOControlHandler.java @@ -15,11 +15,9 @@ * License. */ -package org.alfresco.filesys.smb.server.repo; +package org.alfresco.filesys.alfresco; import org.alfresco.filesys.server.filesys.IOCtlInterface; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.transaction.TransactionService; /** * I/O Control Handler Interface @@ -30,10 +28,9 @@ public interface IOControlHandler extends IOCtlInterface { /** * Initialize the I/O control handler - * * - * @param contentDriver ContentDiskDriver - * @param contentContext ContentContext + * @param filesysDriver AlfrescoDiskDriver + * @param filesysContext AlfrescoContext */ - public void initialize( ContentDiskDriver contentDriver, ContentContext contentContext); + public void initialize( AlfrescoDiskDriver filesysDriver, AlfrescoContext filesysContext); } diff --git a/source/java/org/alfresco/filesys/avm/AVMContext.java b/source/java/org/alfresco/filesys/avm/AVMContext.java index 801b6aa46f..aba6423260 100644 --- a/source/java/org/alfresco/filesys/avm/AVMContext.java +++ b/source/java/org/alfresco/filesys/avm/AVMContext.java @@ -17,11 +17,10 @@ package org.alfresco.filesys.avm; -import org.alfresco.filesys.server.filesys.DiskDeviceContext; +import org.alfresco.filesys.alfresco.AlfrescoContext; +import org.alfresco.filesys.alfresco.IOControlHandler; +import org.alfresco.filesys.server.filesys.DiskInterface; import org.alfresco.filesys.server.filesys.FileSystem; -import org.alfresco.filesys.server.filesys.SrvDiskInfo; -import org.alfresco.filesys.server.state.FileStateReaper; -import org.alfresco.filesys.server.state.FileStateTable; /** * AVM Filesystem Context Class @@ -30,7 +29,7 @@ import org.alfresco.filesys.server.state.FileStateTable; * * @author GKSpencer */ -public class AVMContext extends DiskDeviceContext { +public class AVMContext extends AlfrescoContext { // Constants // @@ -43,14 +42,18 @@ public class AVMContext extends DiskDeviceContext { private String m_storePath; private int m_version = VERSION_HEAD; - // File state table and associated file state reaper - - private FileStateTable m_stateTable; - private FileStateReaper m_stateReaper; + // Flag to indicate if the virtualization view is enabled + // + // The first set of folders then map to the stores and the second layer map to the versions with + // paths below. + + private boolean m_virtualView; /** * Class constructor * + *

Construct a context for a normal view onto a single store/version within AVM. + * * @param filesysName String * @param storePath String * @param version int @@ -68,17 +71,24 @@ public class AVMContext extends DiskDeviceContext { // Set the store version to use m_version = version; - - // Default the filesystem to look like an 80Gb sized disk with 90% free space - - setDiskInformation(new SrvDiskInfo(2560000, 64, 512, 2304000)); - - // Set filesystem parameters - - setFilesystemAttributes(FileSystem.CasePreservedNames + FileSystem.UnicodeOnDisk + - FileSystem.CaseSensitiveSearch); } + /** + * Class constructor + * + *

Construct a context for a virtualization view onto all stores/versions within AVM. + * + * @param filesysName String + */ + public AVMContext( String filesysName) + { + super( filesysName, "VirtualView"); + + // Enable the virtualization view + + m_virtualView = true; + } + /** * Return the filesystem type, either FileSystem.TypeFAT or FileSystem.TypeNTFS. * @@ -109,69 +119,34 @@ public class AVMContext extends DiskDeviceContext { return m_version; } + /** + * Check if the virtualization view is enabled + * + * @return boolean + */ + public final boolean isVirtualizationView() + { + return m_virtualView; + } + /** * Close the filesystem context */ public void CloseContext() { - // Deregister the file state table from the reaper - - if ( m_stateTable != null) - enableStateTable( false, m_stateReaper); - // Call the base class super.CloseContext(); } /** - * Determine if the file state table is enabled + * Create the I/O control handler for this filesystem type * - * @return boolean + * @param filesysDriver DiskInterface + * @return IOControlHandler */ - public final boolean hasStateTable() + protected IOControlHandler createIOHandler( DiskInterface filesysDriver) { - return m_stateTable != null ? true : false; - } - - /** - * Return the file state table - * - * @return FileStateTable - */ - public final FileStateTable getStateTable() - { - return m_stateTable; - } - - /** - * Enable/disable the file state table - * - * @param ena boolean - * @param stateReaper FileStateReaper - */ - public final void enableStateTable(boolean ena, FileStateReaper stateReaper) - { - if ( ena == false) - { - // Remove the state table from the reaper - - stateReaper.removeStateTable( getFilesystemName()); - m_stateTable = null; - } - else if ( m_stateTable == null) - { - // Create the file state table - - m_stateTable = new FileStateTable(); - - // Register with the file state reaper - - stateReaper.addStateTable( getFilesystemName(), m_stateTable); - } - - // Save the reaper, for deregistering when the filesystem is closed - - m_stateReaper = stateReaper; + return null; } } diff --git a/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java b/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java index 77ab5e1187..8edfc9bcc8 100644 --- a/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java +++ b/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java @@ -21,10 +21,12 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.util.List; import java.util.SortedMap; +import java.util.StringTokenizer; import javax.transaction.UserTransaction; import org.alfresco.config.ConfigElement; +import org.alfresco.filesys.alfresco.AlfrescoDiskDriver; import org.alfresco.filesys.server.SrvSession; import org.alfresco.filesys.server.core.DeviceContext; import org.alfresco.filesys.server.core.DeviceContextException; @@ -39,19 +41,23 @@ import org.alfresco.filesys.server.filesys.FileName; import org.alfresco.filesys.server.filesys.FileOpenParams; import org.alfresco.filesys.server.filesys.FileStatus; import org.alfresco.filesys.server.filesys.NetworkFile; +import org.alfresco.filesys.server.filesys.PathNotFoundException; import org.alfresco.filesys.server.filesys.SearchContext; import org.alfresco.filesys.server.filesys.TreeConnection; -import org.alfresco.filesys.server.state.FileStateReaper; +import org.alfresco.filesys.server.pseudo.PseudoFile; +import org.alfresco.filesys.server.pseudo.PseudoFileList; +import org.alfresco.filesys.server.pseudo.PseudoFolderNetworkFile; +import org.alfresco.filesys.server.state.FileState; import org.alfresco.filesys.util.StringList; import org.alfresco.filesys.util.WildCard; import org.alfresco.repo.security.authentication.AuthenticationComponent; -import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.avm.AVMExistsException; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMNotFoundException; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avm.AVMStoreDescriptor; import org.alfresco.service.cmr.avm.AVMWrongTypeException; +import org.alfresco.service.cmr.avm.VersionDescriptor; import org.alfresco.service.cmr.repository.MimetypeService; import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.transaction.TransactionService; @@ -65,7 +71,7 @@ import org.apache.commons.logging.LogFactory; * * @author GKSpencer */ -public class AVMDiskDriver implements DiskInterface { +public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { // Logging @@ -91,14 +97,6 @@ public class AVMDiskDriver implements DiskInterface { private AuthenticationComponent m_authComponent; private AuthenticationService m_authService; - // Service registry for desktop actions - - private ServiceRegistry m_serviceRegistry; - - // File state reaper - - private FileStateReaper m_stateReaper; - /** * Default constructor */ @@ -136,26 +134,6 @@ public class AVMDiskDriver implements DiskInterface { return m_transactionService; } - /** - * Return the service registry - * - * @return ServiceRegistry - */ - public final ServiceRegistry getServiceRegistry() - { - return m_serviceRegistry; - } - - /** - * Return the file state reaper - * - * @return FileStateReaper - */ - public final FileStateReaper getStateReaper() - { - return m_stateReaper; - } - /** * Set the AVM service * @@ -176,16 +154,6 @@ public class AVMDiskDriver implements DiskInterface { m_transactionService = transactionService; } - /** - * Set the service registry - * - * @param serviceRegistry - */ - public void setServiceRegistry(ServiceRegistry serviceRegistry) - { - m_serviceRegistry = serviceRegistry; - } - /** * Set the authentication component * @@ -216,16 +184,6 @@ public class AVMDiskDriver implements DiskInterface { m_mimetypeService = mimetypeService; } - /** - * Set the file state reaper - * - * @param stateReaper FileStateReaper - */ - public final void setStateReaper(FileStateReaper stateReaper) - { - m_stateReaper = stateReaper; - } - /** * Parse and validate the parameter string and create a device context object for this instance * of the shared device. @@ -256,94 +214,201 @@ public class AVMDiskDriver implements DiskInterface { if ( tx != null) tx.begin(); - // Get the store path + // Check if the share is a virtualization view - ConfigElement storeElement = cfg.getChild(KEY_STORE); - if (storeElement == null || storeElement.getValue() == null || storeElement.getValue().length() == 0) - throw new DeviceContextException("Device missing init value: " + KEY_STORE); - String storePath = storeElement.getValue(); + ConfigElement virtElem = cfg.getChild( "virtualView"); + if ( virtElem != null) + { + // Create the context + + context = new AVMContext( name); + + // Enable file state caching + + context.enableStateTable( true, getStateReaper()); + + // Get a list of the available AVM stores + + List storeList = m_avmService.getAVMStores(); + + if ( storeList != null && storeList.size() > 0) + { + // Create a file state for the root folder that does not expire, and add pseudo files + // for the stores - // Get the version if specified, or default to the head version - - int version = AVMContext.VERSION_HEAD; - - ConfigElement versionElem = cfg.getChild(KEY_VERSION); - if ( versionElem != null) - { - // Check if the version is valid - - if ( versionElem.getValue() == null || versionElem.getValue().length() == 0) - throw new DeviceContextException("Store version not specified"); - - // Validate the version id - - try - { - version = Integer.parseInt( versionElem.getValue()); - } - catch ( NumberFormatException ex) - { - throw new DeviceContextException("Invalid store version specified, " + versionElem.getValue()); - } - - // Range check the version id - - if ( version < 0 && version != AVMContext.VERSION_HEAD) - throw new DeviceContextException("Invalid store version id specified, " + version); + FileState rootState = context.getStateTable().findFileState( FileName.DOS_SEPERATOR_STR, true, true); + rootState.setExpiryTime( FileState.NoTimeout); + + // Add pseudo files for the stores + + for ( AVMStoreDescriptor storeDesc : storeList) + { + // Add a pseudo file for the current store + + rootState.addPseudoFile( new StorePseudoFile( storeDesc)); + } + } } - - // Check if the create flag is enabled - - ConfigElement createStore = cfg.getChild( KEY_CREATE); - - // Validate the store path - - AVMNodeDescriptor rootNode = m_avmService.lookup( version, storePath); - if ( rootNode == null) + else { - // Check if the store should be created - - if ( createStore == null || version != AVMContext.VERSION_HEAD) - throw new DeviceContextException("Invalid store path/version, " + storePath + " (" + version + ")"); - - // Parse the store path - - String storeName = null; - String path = null; - - int pos = storePath.indexOf(":/"); - if ( pos != -1) - { - storeName = storePath.substring(0, pos); - if ( storePath.length() > pos) - path = storePath.substring(pos + 2); - } - else - storeName = storePath; - - // Create a new store, and the path if specified - - m_avmService.createAVMStore( storeName); - if ( path != null) - { - // TODO: - } - - // Validate the store path again - - rootNode = m_avmService.lookup( version, storePath); - if ( rootNode == null) - throw new DeviceContextException("Failed to create new store " + storePath); + // Get the store path + + ConfigElement storeElement = cfg.getChild(KEY_STORE); + if (storeElement == null || storeElement.getValue() == null || storeElement.getValue().length() == 0) + throw new DeviceContextException("Device missing init value: " + KEY_STORE); + + String storePath = storeElement.getValue(); + + // Get the version if specified, or default to the head version + + int version = AVMContext.VERSION_HEAD; + + ConfigElement versionElem = cfg.getChild(KEY_VERSION); + if ( versionElem != null) + { + // Check if the version is valid + + if ( versionElem.getValue() == null || versionElem.getValue().length() == 0) + throw new DeviceContextException("Store version not specified"); + + // Validate the version id + + try + { + version = Integer.parseInt( versionElem.getValue()); + } + catch ( NumberFormatException ex) + { + throw new DeviceContextException("Invalid store version specified, " + versionElem.getValue()); + } + + // Range check the version id + + if ( version < 0 && version != AVMContext.VERSION_HEAD) + throw new DeviceContextException("Invalid store version id specified, " + version); + } + + // Check if the create flag is enabled + + ConfigElement createStore = cfg.getChild( KEY_CREATE); + + // Validate the store path + + AVMNodeDescriptor rootNode = m_avmService.lookup( version, storePath); + if ( rootNode == null) + { + // Check if the store should be created + + if ( createStore == null || version != AVMContext.VERSION_HEAD) + throw new DeviceContextException("Invalid store path/version, " + storePath + " (" + version + ")"); + + // Parse the store path + + String storeName = null; + String path = null; + + int pos = storePath.indexOf(":/"); + if ( pos != -1) + { + storeName = storePath.substring(0, pos); + if ( storePath.length() > pos) + path = storePath.substring(pos + 2); + } + else + storeName = storePath; + + // Check if the store exists + + AVMStoreDescriptor storeDesc = null; + + try + { + storeDesc = m_avmService.getAVMStore( storeName); + } + catch (AVMNotFoundException ex) + { + } + + // Create a new store if it does not exist + + if ( storeDesc == null) + m_avmService.createAVMStore( storeName); + + // Check if there is an optional path + + if ( path != null) + { + // Split the path + + StringTokenizer tokens = new StringTokenizer( path, AVMPath.AVM_SEPERATOR_STR); + StringList paths = new StringList(); + + while ( tokens.hasMoreTokens()) + paths.addString( tokens.nextToken()); + + // Create the path, or folders that do not exist + + AVMPath curPath = new AVMPath( storeName, version, FileName.DOS_SEPERATOR_STR); + AVMNodeDescriptor curDesc = m_avmService.lookup( curPath.getVersion(), curPath.getAVMPath()); + + // Walk the path checking creating each folder as required + + for ( int i = 0; i < paths.numberOfStrings(); i++) + { + AVMNodeDescriptor nextDesc = null; + + try + { + // Check if the child folder exists + + nextDesc = m_avmService.lookup( curDesc, paths.getStringAt( i)); + } + catch ( AVMNotFoundException ex) + { + } + + // Check if the folder exists + + if ( nextDesc == null) + { + // Create the new folder + + m_avmService.createDirectory( curPath.getAVMPath(), paths.getStringAt( i)); + + // Get the details of the new folder + + nextDesc = m_avmService.lookup( curDesc, paths.getStringAt( i)); + } + else if ( nextDesc.isFile()) + throw new DeviceContextException("Path element error, not a folder, " + paths.getStringAt( i)); + + // Step to the next level + + curPath.parsePath( storeName, version, curPath.getRelativePath() + paths.getStringAt( i) + FileName.DOS_SEPERATOR_STR); + curDesc = nextDesc; + } + } + + // Validate the store path again + + rootNode = m_avmService.lookup( version, storePath); + if ( rootNode == null) + throw new DeviceContextException("Failed to create new store " + storePath); + } + + // Create the context + + context = new AVMContext( name, storePath, version); + + // Enable file state caching + + context.enableStateTable( true, getStateReaper()); } // Commit the transaction tx.commit(); tx = null; - - // Create the context - - context = new AVMContext( name, storePath, version); } catch (Exception ex) { @@ -370,10 +435,6 @@ public class AVMDiskDriver implements DiskInterface { } } - // Enable file state caching - - context.enableStateTable( true, getStateReaper()); - // Return the context for this shared filesystem return context; @@ -449,28 +510,34 @@ public class AVMDiskDriver implements DiskInterface { * * @param ctx AVMContext * @param path String - * @return String + * @return AVMPath */ - protected final String buildStorePath( AVMContext ctx, String path) + protected final AVMPath buildStorePath( AVMContext ctx, String path) { - // Build the store path + // Check if the AVM filesystem is a normal or virtualization view + + AVMPath avmPath = null; - StringBuilder storePath = new StringBuilder(); - - storePath.append( ctx.getStorePath()); - if ( path == null || path.length() == 0) + if ( ctx.isVirtualizationView()) { - storePath.append( AVM_SEPERATOR); + // Create a path for the virtualization view + + avmPath = new AVMPath( path); + + // Validate that the store and version, if specified + + } else { - if ( path.startsWith( FileName.DOS_SEPERATOR_STR) == false) - storePath.append( AVM_SEPERATOR); - - storePath.append( path.replace( FileName.DOS_SEPERATOR, AVM_SEPERATOR)); + // Create a path to a single store/version + + avmPath = new AVMPath( ctx.getStorePath(), ctx.isVersion(), path); } - return storePath.toString(); + // Return the path + + return avmPath; } /** @@ -504,7 +571,6 @@ public class AVMDiskDriver implements DiskInterface { else deleteFile(sess, tree, file.getFullName()); } - } /** @@ -530,13 +596,20 @@ public class AVMDiskDriver implements DiskInterface { // Convert the relative path to a store path - String storePath = buildStorePath( ctx, paths[0]); + AVMPath storePath = buildStorePath( ctx, paths[0]); // DEBUG if ( logger.isDebugEnabled()) logger.debug("Create directory params=" + params + ", storePath=" + storePath + ", name=" + paths[1]); + // Check if the filesystem is the virtualization view + + if ( ctx.isVirtualizationView() && storePath.isPseudoPath()) + { + throw new AccessDeniedException( "Cannot create folder in store/version layer, " + params.getPath()); + } + // Create a new file sess.beginTransaction( m_transactionService, false); @@ -545,7 +618,7 @@ public class AVMDiskDriver implements DiskInterface { { // Create the new file entry - m_avmService.createDirectory( storePath, paths[1]); + m_avmService.createDirectory( storePath.getAVMPath(), paths[1]); } catch ( AVMExistsException ex) { @@ -585,13 +658,20 @@ public class AVMDiskDriver implements DiskInterface { // Convert the relative path to a store path - String storePath = buildStorePath( ctx, paths[0]); + AVMPath storePath = buildStorePath( ctx, paths[0]); // DEBUG if ( logger.isDebugEnabled()) logger.debug("Create file params=" + params + ", storePath=" + storePath + ", name=" + paths[1]); + // Check if the filesystem is the virtualization view + + if ( ctx.isVirtualizationView() && storePath.isPseudoPath()) + { + throw new AccessDeniedException( "Cannot create file in store/version layer, " + params.getPath()); + } + // Create a new file sess.beginTransaction( m_transactionService, false); @@ -602,18 +682,18 @@ public class AVMDiskDriver implements DiskInterface { { // Create the new file entry - m_avmService.createFile( storePath, paths[1]).close(); + m_avmService.createFile( storePath.getAVMPath(), paths[1]).close(); // Get the new file details - String fileStorePath = buildStorePath( ctx, params.getPath()); - AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), fileStorePath); + AVMPath fileStorePath = buildStorePath( ctx, params.getPath()); + AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), fileStorePath.getAVMPath()); if ( nodeDesc != null) { // Create the network file object for the new file - netFile = new AVMNetworkFile( nodeDesc, fileStorePath, ctx.isVersion(), m_avmService); + netFile = new AVMNetworkFile( nodeDesc, fileStorePath.getAVMPath(), ctx.isVersion(), m_avmService); netFile.setGrantedAccess(NetworkFile.READWRITE); netFile.setFullName(params.getPath()); @@ -654,20 +734,27 @@ public class AVMDiskDriver implements DiskInterface { // Convert the relative path to a store path AVMContext ctx = (AVMContext) tree.getContext(); - String storePath = buildStorePath( ctx, dir); + AVMPath storePath = buildStorePath( ctx, dir); // DEBUG if ( logger.isDebugEnabled()) logger.debug("Delete directory, path=" + dir + ", storePath=" + storePath); + // Check if the filesystem is the virtualization view + + if ( ctx.isVirtualizationView() && storePath.isPseudoPath()) + { + throw new AccessDeniedException( "Cannot delete pseudo folder, " + dir); + } + // Make sure the path is to a folder before deleting it sess.beginTransaction( m_transactionService, false); try { - AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), storePath); + AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), storePath.getAVMPath()); if ( nodeDesc != null) { // Check that we are deleting a folder @@ -682,7 +769,7 @@ public class AVMDiskDriver implements DiskInterface { // Delete the folder - m_avmService.removeNode( storePath); + m_avmService.removeNode( storePath.getAVMPath()); } else throw new IOException( "Delete directory path is not a directory, " + dir); @@ -712,20 +799,27 @@ public class AVMDiskDriver implements DiskInterface { // Convert the relative path to a store path AVMContext ctx = (AVMContext) tree.getContext(); - String storePath = buildStorePath( ctx, name); + AVMPath storePath = buildStorePath( ctx, name); // DEBUG if ( logger.isDebugEnabled()) logger.debug("Delete file, path=" + name + ", storePath=" + storePath); + // Check if the filesystem is the virtualization view + + if ( ctx.isVirtualizationView() && storePath.isPseudoPath()) + { + throw new AccessDeniedException( "Cannot delete pseudo file, " + name); + } + // Make sure the path is to a file before deleting it sess.beginTransaction( m_transactionService, false); try { - AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), storePath); + AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), storePath.getAVMPath()); if ( nodeDesc != null) { // Check that we are deleting a file @@ -734,7 +828,7 @@ public class AVMDiskDriver implements DiskInterface { { // Delete the file - m_avmService.removeNode( storePath); + m_avmService.removeNode( storePath.getAVMPath()); } else throw new IOException( "Delete file path is not a file, " + name); @@ -764,19 +858,49 @@ public class AVMDiskDriver implements DiskInterface { // Convert the relative path to a store path AVMContext ctx = (AVMContext) tree.getContext(); - String storePath = buildStorePath( ctx, name); + AVMPath storePath = buildStorePath( ctx, name); // DEBUG if ( logger.isDebugEnabled()) logger.debug("File exists check, path=" + name + ", storePath=" + storePath); + // Check if the filesystem is the virtualization view + + int status = FileStatus.NotExist; + + if ( ctx.isVirtualizationView() && storePath.isPseudoPath()) + { + // Check if the search path is for the root or a store folder + + if ( storePath.isRootPath()) + { + return FileStatus.DirectoryExists; + } + else + { + // Get the pseudo file for the store/version folder + + PseudoFile psFile = findPseudoFolder( storePath, ctx); + if ( psFile != null) + { + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug( " Found pseudo file " + psFile); + + return FileStatus.DirectoryExists; + } + else + return FileStatus.NotExist; + } + } + // Search for the file/folder sess.beginTransaction( m_transactionService, true); - int status = FileStatus.NotExist; - AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), storePath); + AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), storePath.getAVMPath()); if ( nodeDesc != null) { @@ -824,63 +948,105 @@ public class AVMDiskDriver implements DiskInterface { // Convert the relative path to a store path AVMContext ctx = (AVMContext) tree.getContext(); - String storePath = buildStorePath( ctx, name); + AVMPath storePath = buildStorePath( ctx, name); // DEBUG if ( logger.isDebugEnabled()) logger.debug("Get file information, path=" + name + ", storePath=" + storePath); + // Check if the filesystem is the virtualization view + + if ( ctx.isVirtualizationView() && storePath.isPseudoPath()) + { + // Check if the search path is for the root, a store or version folder + + if ( storePath.isRootPath()) + { + // Return dummy file informatiom for the root folder + + return new FileInfo( name,0L, FileAttribute.Directory); + } + else + { + // Find the pseudo file for the store/version folder + + PseudoFile psFile = findPseudoFolder( storePath, ctx); + if ( psFile != null) + { + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug( " Found pseudo file " + psFile); + return psFile.getFileInfo(); + } + else + return null; + } + } + // Search for the file/folder sess.beginTransaction( m_transactionService, true); FileInfo info = null; - AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), storePath); - if ( nodeDesc != null) + try { - // Create, and fill in, the file information - - info = new FileInfo(); - - info.setFileName( nodeDesc.getName()); - - if ( nodeDesc.isFile()) - { - info.setFileSize( nodeDesc.getLength()); - info.setAllocationSize((nodeDesc.getLength() + 512L) & 0xFFFFFFFFFFFFFE00L); - } - else - info.setFileSize( 0L); - - info.setAccessDateTime( nodeDesc.getAccessDate()); - info.setCreationDateTime( nodeDesc.getCreateDate()); - info.setModifyDateTime( nodeDesc.getModDate()); - - // Build the file attributes - - int attr = 0; - - if ( nodeDesc.isDirectory()) - attr += FileAttribute.Directory; - - if ( nodeDesc.getName().startsWith( ".") || - nodeDesc.getName().equalsIgnoreCase( "Desktop.ini") || - nodeDesc.getName().equalsIgnoreCase( "Thumbs.db")) - attr += FileAttribute.Hidden; - - // Mark the file/folder as read-only if not the head version - - if ( ctx.isVersion() != AVMContext.VERSION_HEAD) - attr += FileAttribute.ReadOnly; - - info.setFileAttributes( attr); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug(" File info=" + info); + AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), storePath.getAVMPath()); + + if ( nodeDesc != null) + { + // Create, and fill in, the file information + + info = new FileInfo(); + + info.setFileName( nodeDesc.getName()); + + if ( nodeDesc.isFile()) + { + info.setFileSize( nodeDesc.getLength()); + info.setAllocationSize((nodeDesc.getLength() + 512L) & 0xFFFFFFFFFFFFFE00L); + } + else + info.setFileSize( 0L); + + info.setAccessDateTime( nodeDesc.getAccessDate()); + info.setCreationDateTime( nodeDesc.getCreateDate()); + info.setModifyDateTime( nodeDesc.getModDate()); + + // Build the file attributes + + int attr = 0; + + if ( nodeDesc.isDirectory()) + attr += FileAttribute.Directory; + + if ( nodeDesc.getName().startsWith( ".") || + nodeDesc.getName().equalsIgnoreCase( "Desktop.ini") || + nodeDesc.getName().equalsIgnoreCase( "Thumbs.db")) + attr += FileAttribute.Hidden; + + // Mark the file/folder as read-only if not the head version + + if ( ctx.isVersion() != AVMContext.VERSION_HEAD) + attr += FileAttribute.ReadOnly; + + info.setFileAttributes( attr); + + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug(" File info=" + info); + } + } + catch ( AVMNotFoundException ex) + { + throw new FileNotFoundException( name); + } + catch ( AVMWrongTypeException ex) + { + throw new PathNotFoundException( name); } // Return the file information @@ -920,13 +1086,43 @@ public class AVMDiskDriver implements DiskInterface { // Convert the relative path to a store path AVMContext ctx = (AVMContext) tree.getContext(); - String storePath = buildStorePath( ctx, params.getPath()); + AVMPath storePath = buildStorePath( ctx, params.getPath()); // DEBUG if ( logger.isDebugEnabled()) logger.debug("Open file params=" + params + ", storePath=" + storePath); + // Check if the filesystem is the virtualization view + + if ( ctx.isVirtualizationView() && storePath.isPseudoPath()) + { + // Check if the path is for the root, a store or version folder + + if ( storePath.isRootPath()) + { + // Return a dummy file for the root folder + + return new PseudoFolderNetworkFile( FileName.DOS_SEPERATOR_STR); + } + else + { + // Find the pseudo file for the store/version folder + + PseudoFile psFile = findPseudoFolder( storePath, ctx); + if ( psFile != null) + { + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug( " Found pseudo file " + psFile); + return psFile.getFile( params.getPath()); + } + else + return null; + } + } + // Search for the file/folder sess.beginTransaction( m_transactionService, true); @@ -937,7 +1133,7 @@ public class AVMDiskDriver implements DiskInterface { { // Get the details of the file/folder - AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), storePath); + AVMNodeDescriptor nodeDesc = m_avmService.lookup( ctx.isVersion(), storePath.getAVMPath()); if ( nodeDesc != null) { @@ -948,7 +1144,7 @@ public class AVMDiskDriver implements DiskInterface { // Create the network file object for the opened file/folder - netFile = new AVMNetworkFile( nodeDesc, storePath, ctx.isVersion(), m_avmService); + netFile = new AVMNetworkFile( nodeDesc, storePath.getAVMPath(), ctx.isVersion(), m_avmService); if ( params.isReadOnlyAccess() || ctx.isVersion() != AVMContext.VERSION_HEAD) netFile.setGrantedAccess(NetworkFile.READONLY); @@ -1043,8 +1239,8 @@ public class AVMDiskDriver implements DiskInterface { // Convert the parent paths to store paths - oldPaths[0] = buildStorePath( ctx, oldPaths[0]); - newPaths[0] = buildStorePath( ctx, newPaths[0]); + AVMPath oldAVMPath = buildStorePath( ctx, oldPaths[0]); + AVMPath newAVMPath = buildStorePath( ctx, newPaths[0]); // DEBUG @@ -1054,6 +1250,13 @@ public class AVMDiskDriver implements DiskInterface { logger.debug(" new path=" + newPaths[0] + ", name=" + newPaths[1]); } + // Check if the filesystem is the virtualization view + + if ( ctx.isVirtualizationView() && oldAVMPath.isPseudoPath()) + { + throw new AccessDeniedException( "Cannot rename folder in store/version layer, " + oldName); + } + // Start a transaction for the rename sess.beginTransaction( m_transactionService, false); @@ -1062,7 +1265,7 @@ public class AVMDiskDriver implements DiskInterface { { // Rename the file/folder - m_avmService.rename( oldPaths[0], oldPaths[1], newPaths[0], newPaths[1]); + m_avmService.rename( oldAVMPath.getAVMPath(), oldPaths[1], newAVMPath.getAVMPath(), newPaths[1]); } catch ( AVMNotFoundException ex) { @@ -1155,6 +1358,60 @@ public class AVMDiskDriver implements DiskInterface { if ( logger.isDebugEnabled()) logger.debug("Start search path=" + searchPath); + // Split the search path into relative path and search name + + String[] paths = FileName.splitPath( searchPath); + + // Build the store path to the folder being searched + + AVMPath storePath = buildStorePath( avmCtx, paths[0]); + + // Check if the filesystem is the virtualization view + + if ( avmCtx.isVirtualizationView() && storePath.isPseudoPath()) + { + // Check if the search path is for the root or a store folder + + FileState fstate = findPseudoState( storePath, avmCtx); + + if ( fstate != null) + { + // Get the pseudo file list for the parent directory + + PseudoFileList searchList = fstate.getPseudoFileList(); + + // Check if this is a single file or wildcard search + + if ( WildCard.containsWildcards( searchPath)) + { + // Create the search context, wildcard filter will take care of secondary filtering of the + // folder listing + + WildCard wildCardFilter = new WildCard( paths[1], false); + return new PseudoFileListSearchContext( searchList, attrib, wildCardFilter); + } + else + { + // Search the pseudo file list for the required file + + PseudoFile pseudoFile = searchList.findFile( paths[1], false); + if ( pseudoFile != null) + { + // Create a search context using the single file details + + PseudoFileList singleList = new PseudoFileList(); + singleList.addFile( pseudoFile); + + return new PseudoFileListSearchContext( singleList, attrib, null); + } + } + } + + // File not found + + throw new FileNotFoundException( searchPath); + } + // Check if the path is a wildcard search sess.beginTransaction( m_transactionService, true); @@ -1162,17 +1419,9 @@ public class AVMDiskDriver implements DiskInterface { if ( WildCard.containsWildcards( searchPath)) { - // Split the search path into relative path and search name - - String[] paths = FileName.splitPath( searchPath); - - // Build the store path to the folder being searched - - String storePath = buildStorePath( avmCtx, paths[0]); - // Get the file listing for the folder - AVMNodeDescriptor[] fileList = m_avmService.getDirectoryListingArray( avmCtx.isVersion(), storePath, false); + AVMNodeDescriptor[] fileList = m_avmService.getDirectoryListingArray( avmCtx.isVersion(), storePath.getAVMPath(), false); // Create the search context @@ -1194,11 +1443,11 @@ public class AVMDiskDriver implements DiskInterface { { // Single file/folder search, convert the path to a store path - String storePath = buildStorePath( avmCtx, searchPath); + storePath = buildStorePath( avmCtx, searchPath); // Get the single file/folder details - AVMNodeDescriptor nodeDesc = m_avmService.lookup( avmCtx.isVersion(), storePath); + AVMNodeDescriptor nodeDesc = m_avmService.lookup( avmCtx.isVersion(), storePath.getAVMPath()); if ( nodeDesc != null) { @@ -1298,4 +1547,174 @@ public class AVMDiskDriver implements DiskInterface { { // Nothing to do } + + /** + * Find the pseudo file for a virtual path + * + * @param avmPath AVMPath + * @param avmCtx AVMContext + * @return PseudoFile + */ + private final PseudoFile findPseudoFolder( AVMPath avmPath, AVMContext avmCtx) + { + // Check if the path is to a store pseudo folder + + PseudoFile psFile = null; + + if ( avmPath.hasVersion() == false) + { + // Check for the path within the store layer + + FileState fstate = avmCtx.getStateTable().findFileState( FileName.DOS_SEPERATOR_STR); + PseudoFileList pseudoList = fstate.getPseudoFileList(); + + psFile = pseudoList.findFile( avmPath.getStoreName(), false); + } + else if ( avmPath.hasRelativePath() == false) + { + // Build the path to the parent store folder + + StringBuilder storeStr = new StringBuilder(); + + storeStr.append( FileName.DOS_SEPERATOR); + storeStr.append( avmPath.getStoreName()); + + // Search for the file state for the store pseudo folder + + FileState storeState = avmCtx.getStateTable().findFileState( storeStr.toString()); + if ( storeState != null) + { + // Search the store pseudo folder file list for the required version + + psFile = storeState.getPseudoFileList().findFile( avmPath.getVersionString(), false); + } + else + { + // Get the list of AVM store versions + + try + { + // Get the list of versions for the store + + List verList = m_avmService.getAVMStoreVersions( avmPath.getStoreName()); + + // Create a file state for the store path + + storeState = avmCtx.getStateTable().findFileState( storeStr.toString(), true, true); + + // Add pseudo files for the versions to the store state + + for ( VersionDescriptor verDesc : verList) + { + // Add the version pseudo folder + + storeState.addPseudoFile( new VersionPseudoFile ( avmPath.getVersionString(), verDesc)); + } + + // Search for the required version pseudo folder + + psFile = storeState.getPseudoFileList().findFile( avmPath.getVersionString(), false); + } + catch ( AVMNotFoundException ex) + { + // Invalid store name + } + } + } + + // Return the pseudo file, or null if not found + + return psFile; + } + + /** + * Find the file state for a pseudo folder path + * + * @param avmPath AVMPath + * @param avmCtx AVMContext + * @return FileState + */ + private final FileState findPseudoState( AVMPath avmPath, AVMContext avmCtx) + { + // Check if the path is to a store pseudo folder + + FileState fstate = null; + + if ( avmPath.isRootPath()) + { + // Get the root path file state + + fstate = avmCtx.getStateTable().findFileState( FileName.DOS_SEPERATOR_STR); + } + else if ( avmPath.hasVersion() == false) + { + // Build the path to the parent store folder + + StringBuilder storeStr = new StringBuilder(); + + storeStr.append( FileName.DOS_SEPERATOR); + storeStr.append( avmPath.getStoreName()); + + // Search for the file state for the store pseudo folder + + fstate = avmCtx.getStateTable().findFileState( storeStr.toString()); + + if ( fstate == null) + { + // Get the list of AVM store versions + + try + { + // Get the list of versions for the store + + List verList = m_avmService.getAVMStoreVersions( avmPath.getStoreName()); + + // Create a file state for the store path + + fstate = avmCtx.getStateTable().findFileState( storeStr.toString(), true, true); + + // Add a pseudo file for the head version + + fstate.addPseudoFile( new VersionPseudoFile( AVMPath.VersionNameHead)); + + // Add pseudo files for the versions to the store state + + if ( verList.size() > 0) + { + StringBuilder verStr = new StringBuilder(); + + for ( VersionDescriptor verDesc : verList) + { + // Generate the version string + + String verName = null; + + if ( verDesc.getVersionID() == -1) + verName = AVMPath.VersionNameHead; + else + { + verStr.setLength( 0); + verStr.append( verDesc.getVersionID()); + + verName = verStr.toString(); + } + + // Add the version pseudo folder + + fstate.addPseudoFile( new VersionPseudoFile ( verName, verDesc)); + } + } + } + catch ( AVMNotFoundException ex) + { + // Invalid store name + } + + } + } + + // Return the file state + + return fstate; + } } diff --git a/source/java/org/alfresco/filesys/avm/AVMNetworkFile.java b/source/java/org/alfresco/filesys/avm/AVMNetworkFile.java index 068b31541d..573b2d7485 100644 --- a/source/java/org/alfresco/filesys/avm/AVMNetworkFile.java +++ b/source/java/org/alfresco/filesys/avm/AVMNetworkFile.java @@ -28,7 +28,6 @@ import org.alfresco.filesys.server.filesys.NetworkFile; import org.alfresco.filesys.smb.SeekType; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMService; -import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.apache.commons.logging.Log; diff --git a/source/java/org/alfresco/filesys/avm/AVMPath.java b/source/java/org/alfresco/filesys/avm/AVMPath.java index f79e003449..a6da5eb5dc 100644 --- a/source/java/org/alfresco/filesys/avm/AVMPath.java +++ b/source/java/org/alfresco/filesys/avm/AVMPath.java @@ -36,11 +36,12 @@ public class AVMPath { // Version id string for the head version - private static final String VersionNameHead = "Head"; + public static final String VersionNameHead = "Head"; // AVM path seperator - public static final char AVM_SEPERATOR = '/'; + public static final char AVM_SEPERATOR = '/'; + public static final String AVM_SEPERATOR_STR = "/"; // Store name @@ -57,9 +58,18 @@ public class AVMPath { // AVM style path private String m_avmPath; + + /** + * Default constructor + */ + public AVMPath() + { + } /** * Class constructor + * + *

Construct an AVM path for the virtualization view, with store and version folders * * @param shrPath String */ @@ -69,6 +79,22 @@ public class AVMPath { parsePath( shrPath); } + + /** + * Class constructor + * + *

Construct an AVM path for a standard view onto a store/version + * + * @param storeName String + * @param version int + * @param path String + */ + public AVMPath(String storeName, int version, String path) + { + // Parse the path + + parsePath( storeName, version, path); + } /** * Return the store name @@ -100,6 +126,28 @@ public class AVMPath { return m_version; } + /** + * Return the version as a string + * + * @return String + */ + public final String getVersionString() + { + if ( m_version == -1) + return VersionNameHead; + return "" + m_version; + } + + /** + * Check if there is a share relative path + * + * @return boolean + */ + public final boolean hasRelativePath() + { + return m_path != null ? true : false; + } + /** * Return the share relative path * @@ -127,22 +175,54 @@ public class AVMPath { */ public final boolean isValid() { - return m_storeName == null ? false : true; + return m_storeName == null && m_path == null ? false : true; } /** - * Parse the path + * Check if the path is to a pseudo folder in the virtualization view + * + * @return boolean + */ + public final boolean isPseudoPath() + { + return m_version == InvalidVersionId || m_path == null ? true : false; + } + + /** + * Check if the path is the root path + * + * @return boolean + */ + public final boolean isRootPath() + { + if ( m_path != null && m_path.equals( FileName.DOS_SEPERATOR_STR)) + return true; + return false; + } + + /** + * Parse the path, for the virtualization view onto all stores/versions * * @param path String */ - private final void parsePath( String path) + public final void parsePath( String path) { + // Clear current settings + + m_storeName = null; + m_version = InvalidVersionId; + m_path = null; + m_avmPath = null; + // Split the path String[] paths = FileName.splitAllPaths(path); if ( paths == null || paths.length == 0) + { + m_path = FileName.DOS_SEPERATOR_STR; return; + } // Set the store name @@ -204,11 +284,78 @@ public class AVMPath { pathStr.append( ":"); pathStr.append( m_path.replace( FileName.DOS_SEPERATOR, AVM_SEPERATOR)); + m_avmPath = pathStr.toString(); + } + else + { + // Share relative path is the root of the share + + m_path = FileName.DOS_SEPERATOR_STR; + + // Build the AVM path + + StringBuilder pathStr = new StringBuilder(); + + pathStr.append( m_storeName); + pathStr.append( ":/"); + m_avmPath = pathStr.toString(); } } } + /** + * Parse the path, to generate a path for a single store/version + * + * @param storeName String + * @param version int + * @param path String + */ + public final void parsePath( String storeName, int version, String path) + { + // Clear current settings + + m_storeName = null; + m_version = InvalidVersionId; + m_path = null; + m_avmPath = null; + + // Set the store/version + + m_storeName = storeName; + m_version = version; + + // Save the relative path + + m_path = path; + + // Build the store path + + StringBuilder avmPath = new StringBuilder(); + avmPath.append( m_storeName); + + if ( storeName.indexOf( ":") == -1) + avmPath.append( ":"); + + if ( path == null || path.length() == 0) + { + avmPath.append( AVM_SEPERATOR); + + // Set the share relative path as the root path + + m_path = FileName.DOS_SEPERATOR_STR; + } + else + { + if ( path.startsWith( FileName.DOS_SEPERATOR_STR) == false) + avmPath.append( AVM_SEPERATOR); + + avmPath.append( path.replace( FileName.DOS_SEPERATOR, AVM_SEPERATOR)); + } + + m_avmPath = avmPath.toString(); + } + /** * Return the AVM path details as a string * diff --git a/source/java/org/alfresco/filesys/avm/AVMSearchContext.java b/source/java/org/alfresco/filesys/avm/AVMSearchContext.java index 5af6e6c81c..1767f4e3bd 100644 --- a/source/java/org/alfresco/filesys/avm/AVMSearchContext.java +++ b/source/java/org/alfresco/filesys/avm/AVMSearchContext.java @@ -17,9 +17,6 @@ package org.alfresco.filesys.avm; -import java.util.Collection; -import java.util.SortedMap; - import org.alfresco.filesys.server.filesys.FileAttribute; import org.alfresco.filesys.server.filesys.FileInfo; import org.alfresco.filesys.server.filesys.SearchContext; diff --git a/source/java/org/alfresco/filesys/avm/AVMShareMapper.java b/source/java/org/alfresco/filesys/avm/AVMShareMapper.java index dca26255f6..b7d4360b3e 100644 --- a/source/java/org/alfresco/filesys/avm/AVMShareMapper.java +++ b/source/java/org/alfresco/filesys/avm/AVMShareMapper.java @@ -29,9 +29,7 @@ import org.alfresco.filesys.server.core.ShareMapper; import org.alfresco.filesys.server.core.ShareType; import org.alfresco.filesys.server.core.SharedDevice; import org.alfresco.filesys.server.core.SharedDeviceList; -import org.alfresco.filesys.server.filesys.DiskDeviceContext; import org.alfresco.filesys.server.filesys.DiskSharedDevice; -import org.alfresco.filesys.server.filesys.SrvDiskInfo; import org.alfresco.filesys.util.StringList; import org.alfresco.service.cmr.avm.AVMNotFoundException; import org.alfresco.service.cmr.avm.AVMService; diff --git a/source/java/org/alfresco/filesys/avm/PseudoFileListSearchContext.java b/source/java/org/alfresco/filesys/avm/PseudoFileListSearchContext.java new file mode 100644 index 0000000000..b3f1c4d95d --- /dev/null +++ b/source/java/org/alfresco/filesys/avm/PseudoFileListSearchContext.java @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.filesys.avm; + +import org.alfresco.filesys.server.filesys.FileAttribute; +import org.alfresco.filesys.server.filesys.FileInfo; +import org.alfresco.filesys.server.filesys.SearchContext; +import org.alfresco.filesys.server.pseudo.PseudoFile; +import org.alfresco.filesys.server.pseudo.PseudoFileList; +import org.alfresco.filesys.util.WildCard; + +/** + * Pseudo File List Search Context Class + * + *

Returns files from a pseudo file list for a wildcard search. + * + * @author gkspencer + */ +public class PseudoFileListSearchContext extends SearchContext { + + // Pseudo file list and current index + + private PseudoFileList m_fileList; + private int m_fileIdx; + + // File attributes + + private int m_attrib; + + // Optional wildcard filter + + private WildCard m_filter; + + /** + * Class constructor + * + * @param fileList PseudoFileList + * @param attrib int + * @param filter WildCard + */ + public PseudoFileListSearchContext( PseudoFileList fileList, int attrib, WildCard filter) + { + m_attrib = attrib; + m_filter = filter; + m_fileList = fileList; + } + + /** + * Determine if there are more files for the active search. + * + * @return boolean + */ + public boolean hasMoreFiles() + { + return m_fileIdx < m_fileList.numberOfFiles() ? true : false; + } + + /** + * Return file information for the next file in the active search. Returns false if the search + * is complete. + * + * @param info FileInfo to return the file information. + * @return true if the file information is valid, else false + */ + public boolean nextFileInfo(FileInfo info) + { + // Check if there is another file record to return + + if ( m_fileIdx >= m_fileList.numberOfFiles()) + return false; + + // Search for the next valid file + + boolean foundMatch = false; + PseudoFile curFile = null; + + while (foundMatch == false && m_fileIdx < m_fileList.numberOfFiles()) + { + // Get the next file from the list + + curFile = m_fileList.getFileAt( m_fileIdx++); + + // Check if the file name matches the search pattern + + if ( m_filter != null) + { + // Check if the current file matches the wildcard pattern + + if ( m_filter.matchesPattern(curFile.getFileName()) == true) + { + // Check if the file matches the search attributes + + if (FileAttribute.hasAttribute(m_attrib, FileAttribute.Directory) && + curFile.isDirectory()) + { + + // Found a match + + foundMatch = true; + } + else if ( curFile.isFile()) + { + + // Found a match + + foundMatch = true; + } + + // Check if we found a match + + if ( foundMatch == false) + { + + // Get the next file from the list + + if ( ++m_fileIdx < m_fileList.numberOfFiles()) + curFile = m_fileList.getFileAt( m_fileIdx); + } + } + } + else + foundMatch = true; + } + + // If we found a match then fill in the file information + + if ( foundMatch) + { + // Fill in the file information + + info.setFileName( curFile.getFileName()); + + // Get the file information from the pseudo file + + FileInfo pfInfo = curFile.getFileInfo(); + + if ( curFile.isFile()) + { + info.setFileSize( pfInfo.getSize()); + info.setAllocationSize( pfInfo.getAllocationSize()); + } + else + info.setFileSize( 0L); + + info.setAccessDateTime( pfInfo.getAccessDateTime()); + info.setCreationDateTime( pfInfo.getCreationDateTime()); + info.setModifyDateTime( pfInfo.getModifyDateTime()); + + // Build the file attributes + + int attr = pfInfo.getFileAttributes(); + + if ( pfInfo.isHidden() == false && + curFile.getFileName().startsWith( ".") || + curFile.getFileName().equalsIgnoreCase( "Desktop.ini") || + curFile.getFileName().equalsIgnoreCase( "Thumbs.db")) + attr += FileAttribute.Hidden; + + info.setFileAttributes( attr); + } + + // Indicate if the file information is valid + + return foundMatch; + } + + /** + * Return the file name of the next file in the active search. Returns null is the search is + * complete. + * + * @return String + */ + public String nextFileName() + { + // Check if there is another file record to return + + // Find the next matching file name + + while ( m_fileIdx < m_fileList.numberOfFiles()) { + + // Check if the current file name matches the search pattern + + String fname = m_fileList.getFileAt( m_fileIdx++).getFileName(); + + if ( m_filter.matchesPattern(fname)) + return fname; + } + + // No more matching file names + + return null; + } + + /** + * Return the total number of file entries for this search if known, else return -1 + * + * @return int + */ + public int numberOfEntries() + { + return m_fileList.numberOfFiles(); + } + + /** + * Return the resume id for the current file/directory in the search. + * + * @return int + */ + public int getResumeId() + { + return m_fileIdx; + } + + /** + * Restart a search at the specified resume point. + * + * @param resumeId Resume point id. + * @return true if the search can be restarted, else false. + */ + public boolean restartAt(int resumeId) + { + // Range check the resume id + + int resId = resumeId - 1; + + if ( resId < 0 || resId >= m_fileList.numberOfFiles()) + return false; + + // Reset the current file index + + m_fileIdx = resId; + return true; + } + + /** + * Restart the current search at the specified file. + * + * @param info File to restart the search at. + * @return true if the search can be restarted, else false. + */ + public boolean restartAt(FileInfo info) + { + // Search backwards from the current file + + int curFileIdx = m_fileIdx; + + if (m_fileIdx >= m_fileList.numberOfFiles()) + { + m_fileIdx = m_fileList.numberOfFiles() - 1; + } + + while ( m_fileIdx > 0) { + + // Check if the current file is the required search restart point + + if ( m_fileList.getFileAt( m_fileIdx).getFileName().equals( info.getFileName())) + return true; + else + m_fileIdx--; + } + + // Failed to find the restart file + + m_fileIdx = curFileIdx; + return false; + } +} diff --git a/source/java/org/alfresco/filesys/avm/StorePseudoFile.java b/source/java/org/alfresco/filesys/avm/StorePseudoFile.java new file mode 100644 index 0000000000..d9097d59dd --- /dev/null +++ b/source/java/org/alfresco/filesys/avm/StorePseudoFile.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.filesys.avm; + +import org.alfresco.filesys.server.filesys.FileAttribute; +import org.alfresco.filesys.server.filesys.FileInfo; +import org.alfresco.filesys.server.filesys.FileName; +import org.alfresco.filesys.server.filesys.NetworkFile; +import org.alfresco.filesys.server.pseudo.PseudoFile; +import org.alfresco.filesys.server.pseudo.PseudoFolderNetworkFile; +import org.alfresco.service.cmr.avm.AVMStoreDescriptor; + +/** + * Store Pseudo File Class + * + *

Represents an AVM store as a folder. + * + * @author gkspencer + */ +public class StorePseudoFile extends PseudoFile { + + /** + * Class constructor + * + * @param storeDesc AVMStoreDescriptor + */ + public StorePseudoFile( AVMStoreDescriptor storeDesc) + { + super( storeDesc.getName(), FileAttribute.Directory + FileAttribute.ReadOnly); + + // Create static file information from the store details + + FileInfo fInfo = new FileInfo( storeDesc.getName(), 0L, FileAttribute.Directory + FileAttribute.ReadOnly); + fInfo.setCreationDateTime( storeDesc.getCreateDate()); + + setFileInfo( fInfo); + } + + /** + * Return a network file for reading/writing the pseudo file + * + * @param netPath String + * @return NetworkFile + */ + @Override + public NetworkFile getFile(String netPath) { + + // Split the path to get the name + + String[] paths = FileName.splitPath( netPath); + + // Create a network file for the folder + + return new PseudoFolderNetworkFile( paths[1], netPath); + } + + /** + * Return the file information for the pseudo file + * + * @return FileInfo + */ + @Override + public FileInfo getFileInfo() { + return getInfo(); + } +} diff --git a/source/java/org/alfresco/filesys/avm/VersionPseudoFile.java b/source/java/org/alfresco/filesys/avm/VersionPseudoFile.java new file mode 100644 index 0000000000..098d302d04 --- /dev/null +++ b/source/java/org/alfresco/filesys/avm/VersionPseudoFile.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.filesys.avm; + +import org.alfresco.filesys.server.filesys.FileAttribute; +import org.alfresco.filesys.server.filesys.FileInfo; +import org.alfresco.filesys.server.filesys.FileName; +import org.alfresco.filesys.server.filesys.NetworkFile; +import org.alfresco.filesys.server.pseudo.PseudoFile; +import org.alfresco.filesys.server.pseudo.PseudoFolderNetworkFile; +import org.alfresco.service.cmr.avm.VersionDescriptor; + +/** + * Version Pseudo File Class + * + *

Represents an AVM store version as a folder. + * + * @author gkspencer + */ +public class VersionPseudoFile extends PseudoFile { + + /** + * Class constructor + * + * @param name String + */ + public VersionPseudoFile( String name) + { + super( name, FileAttribute.Directory + FileAttribute.ReadOnly); + + // Create static file information from the store details + + FileInfo fInfo = new FileInfo( name, 0L, FileAttribute.Directory + FileAttribute.ReadOnly); + + setFileInfo( fInfo); + } + + /** + * Class constructor + * + * @param name String + * @param verDesc VersionDescriptor + */ + public VersionPseudoFile( String name, VersionDescriptor verDesc) + { + super( name, FileAttribute.Directory + FileAttribute.ReadOnly); + + // Create static file information from the store details + + FileInfo fInfo = new FileInfo( name, 0L, FileAttribute.Directory + FileAttribute.ReadOnly); + fInfo.setCreationDateTime( verDesc.getCreateDate()); + + setFileInfo( fInfo); + } + + /** + * Return a network file for reading/writing the pseudo file + * + * @param netPath String + * @return NetworkFile + */ + @Override + public NetworkFile getFile(String netPath) { + + // Split the path to get the name + + String[] paths = FileName.splitPath( netPath); + + // Create a network file for the folder + + return new PseudoFolderNetworkFile( paths[1], netPath); + } + + /** + * Return the file information for the pseudo file + * + * @return FileInfo + */ + @Override + public FileInfo getFileInfo() { + return getInfo(); + } +} diff --git a/source/java/org/alfresco/filesys/server/config/ServerConfiguration.java b/source/java/org/alfresco/filesys/server/config/ServerConfiguration.java index 0bb0ce20a7..70d1e904a0 100644 --- a/source/java/org/alfresco/filesys/server/config/ServerConfiguration.java +++ b/source/java/org/alfresco/filesys/server/config/ServerConfiguration.java @@ -40,6 +40,9 @@ import org.alfresco.config.ConfigElement; import org.alfresco.config.ConfigLookupContext; import org.alfresco.config.ConfigService; import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.filesys.alfresco.DesktopAction; +import org.alfresco.filesys.alfresco.DesktopActionException; +import org.alfresco.filesys.alfresco.DesktopActionTable; import org.alfresco.filesys.avm.AVMContext; import org.alfresco.filesys.avm.AVMDiskDriver; import org.alfresco.filesys.avm.AVMShareMapper; @@ -72,9 +75,6 @@ import org.alfresco.filesys.server.filesys.DiskSharedDevice; import org.alfresco.filesys.smb.ServerType; import org.alfresco.filesys.smb.TcpipSMB; import org.alfresco.filesys.smb.server.repo.ContentContext; -import org.alfresco.filesys.smb.server.repo.DesktopAction; -import org.alfresco.filesys.smb.server.repo.DesktopActionException; -import org.alfresco.filesys.smb.server.repo.DesktopActionTable; import org.alfresco.filesys.smb.server.repo.HomeShareMapper; import org.alfresco.filesys.util.IPAddress; import org.alfresco.filesys.util.StringList; @@ -1810,6 +1810,7 @@ public class ServerConfiguration extends AbstractLifecycleBean // Create the new share for the store AVMContext avmContext = new AVMContext( storeName, storeName + ":/", AVMContext.VERSION_HEAD); + avmContext.enableStateTable( true, avmDriver.getStateReaper()); // Create the shared filesystem diff --git a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/LocalPseudoFile.java b/source/java/org/alfresco/filesys/server/pseudo/LocalPseudoFile.java similarity index 78% rename from source/java/org/alfresco/filesys/smb/server/repo/pseudo/LocalPseudoFile.java rename to source/java/org/alfresco/filesys/server/pseudo/LocalPseudoFile.java index 11a0d99370..032993201f 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/LocalPseudoFile.java +++ b/source/java/org/alfresco/filesys/server/pseudo/LocalPseudoFile.java @@ -15,7 +15,7 @@ * License. */ -package org.alfresco.filesys.smb.server.repo.pseudo; +package org.alfresco.filesys.server.pseudo; import java.io.File; @@ -67,7 +67,7 @@ public class LocalPseudoFile extends PseudoFile { // Check if the file information is valid - if ( m_fileInfo == null) { + if ( getInfo() == null) { // Get the file details @@ -76,23 +76,25 @@ public class LocalPseudoFile extends PseudoFile { // Create the file information - m_fileInfo = new FileInfo( getFileName(), localFile.length(), getAttributes()); + FileInfo fInfo = new FileInfo( getFileName(), localFile.length(), getAttributes()); // Set the file creation/modification times - m_fileInfo.setModifyDateTime( localFile.lastModified()); - m_fileInfo.setCreationDateTime( _creationDateTime); - m_fileInfo.setChangeDateTime( _creationDateTime); + fInfo.setModifyDateTime( localFile.lastModified()); + fInfo.setCreationDateTime( _creationDateTime); + fInfo.setChangeDateTime( _creationDateTime); // Set the allocation size, round up the actual length - m_fileInfo.setAllocationSize(( localFile.length() + 512L) & 0xFFFFFFFFFFFFFE00L); + fInfo.setAllocationSize(( localFile.length() + 512L) & 0xFFFFFFFFFFFFFE00L); + + setFileInfo( fInfo); } } // Return the file information - return m_fileInfo; + return getInfo(); } /** diff --git a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/MemoryNetworkFile.java b/source/java/org/alfresco/filesys/server/pseudo/MemoryNetworkFile.java similarity index 93% rename from source/java/org/alfresco/filesys/smb/server/repo/pseudo/MemoryNetworkFile.java rename to source/java/org/alfresco/filesys/server/pseudo/MemoryNetworkFile.java index 8eb403b31f..e90124755e 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/MemoryNetworkFile.java +++ b/source/java/org/alfresco/filesys/server/pseudo/MemoryNetworkFile.java @@ -15,7 +15,7 @@ * License. */ -package org.alfresco.filesys.smb.server.repo.pseudo; +package org.alfresco.filesys.server.pseudo; import java.io.IOException; @@ -40,10 +40,6 @@ public class MemoryNetworkFile extends NetworkFile private byte[] m_data; - // End of file flag - - private boolean m_eof; - /** * Class constructor. * @@ -64,7 +60,6 @@ public class MemoryNetworkFile extends NetworkFile // Set the file size setFileSize( m_data.length); - m_eof = false; // Set the creation and modification date/times diff --git a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/MemoryPseudoFile.java b/source/java/org/alfresco/filesys/server/pseudo/MemoryPseudoFile.java similarity index 77% rename from source/java/org/alfresco/filesys/smb/server/repo/pseudo/MemoryPseudoFile.java rename to source/java/org/alfresco/filesys/server/pseudo/MemoryPseudoFile.java index c1733e71f2..d03d5f154f 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/MemoryPseudoFile.java +++ b/source/java/org/alfresco/filesys/server/pseudo/MemoryPseudoFile.java @@ -15,7 +15,7 @@ * License. */ -package org.alfresco.filesys.smb.server.repo.pseudo; +package org.alfresco.filesys.server.pseudo; import org.alfresco.filesys.server.filesys.FileInfo; import org.alfresco.filesys.server.filesys.NetworkFile; @@ -55,26 +55,28 @@ public class MemoryPseudoFile extends PseudoFile { // Check if the file information is valid - if ( m_fileInfo == null) { + if ( getInfo() == null) { // Create the file information - m_fileInfo = new FileInfo( getFileName(), m_data != null ? m_data.length : 0, getAttributes()); + FileInfo fInfo = new FileInfo( getFileName(), m_data != null ? m_data.length : 0, getAttributes()); // Set the file creation/modification times - m_fileInfo.setCreationDateTime( _creationDateTime); - m_fileInfo.setModifyDateTime( _creationDateTime); - m_fileInfo.setChangeDateTime( _creationDateTime); + fInfo.setCreationDateTime( _creationDateTime); + fInfo.setModifyDateTime( _creationDateTime); + fInfo.setChangeDateTime( _creationDateTime); // Set the allocation size, round up the actual length - m_fileInfo.setAllocationSize(( m_fileInfo.getSize() + 512L) & 0xFFFFFFFFFFFFFE00L); + fInfo.setAllocationSize(( fInfo.getSize() + 512L) & 0xFFFFFFFFFFFFFE00L); + + setFileInfo( fInfo); } // Return the file information - return m_fileInfo; + return getInfo(); } /** diff --git a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoFile.java b/source/java/org/alfresco/filesys/server/pseudo/PseudoFile.java similarity index 65% rename from source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoFile.java rename to source/java/org/alfresco/filesys/server/pseudo/PseudoFile.java index 7ce7d11a05..41949fd5ff 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoFile.java +++ b/source/java/org/alfresco/filesys/server/pseudo/PseudoFile.java @@ -15,9 +15,7 @@ * License. */ -package org.alfresco.filesys.smb.server.repo.pseudo; - -import java.io.File; +package org.alfresco.filesys.server.pseudo; import org.alfresco.filesys.server.filesys.FileAttribute; import org.alfresco.filesys.server.filesys.FileInfo; @@ -47,7 +45,7 @@ public abstract class PseudoFile // File information, used for file information/folder searches - protected FileInfo m_fileInfo; + private FileInfo m_fileInfo; /** * Class constructor @@ -91,6 +89,46 @@ public abstract class PseudoFile return m_fileFlags; } + /** + * Check if the pseudo file is a file + * + * @return boolean + */ + public final boolean isFile() + { + return (m_fileFlags & FileAttribute.Directory) != 0 ? false : true; + } + + /** + * Check if the pseudo file is a folder + * + * @return boolean + */ + public final boolean isDirectory() + { + return (m_fileFlags & FileAttribute.Directory) != 0 ? true : false; + } + + /** + * Check if the pseudo file is read-only + * + * @return boolean + */ + public final boolean isReadOnly() + { + return (m_fileFlags & FileAttribute.ReadOnly) != 0 ? true : false; + } + + /** + * Check if the pseudo file is hidden + * + * @return boolean + */ + public final boolean isHidden() + { + return (m_fileFlags & FileAttribute.Hidden) != 0 ? true : false; + } + /** * Return the file information for the pseudo file * @@ -106,6 +144,26 @@ public abstract class PseudoFile */ public abstract NetworkFile getFile(String netPath); + /** + * Set the file information + * + * @param fileInfo FileInfo + */ + protected final void setFileInfo( FileInfo finfo) + { + m_fileInfo = finfo; + } + + /** + * Return the file information + * + * @return FileInfo + */ + protected final FileInfo getInfo() + { + return m_fileInfo; + } + /** * Return the pseudo file as a string * diff --git a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/ContentPseudoFileImpl.java b/source/java/org/alfresco/filesys/server/pseudo/PseudoFileImpl.java similarity index 90% rename from source/java/org/alfresco/filesys/smb/server/repo/pseudo/ContentPseudoFileImpl.java rename to source/java/org/alfresco/filesys/server/pseudo/PseudoFileImpl.java index e2e6f8c4da..354797c01f 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/ContentPseudoFileImpl.java +++ b/source/java/org/alfresco/filesys/server/pseudo/PseudoFileImpl.java @@ -14,33 +14,36 @@ * language governing permissions and limitations under the * License. */ -package org.alfresco.filesys.smb.server.repo.pseudo; +package org.alfresco.filesys.server.pseudo; import java.util.Enumeration; +import org.alfresco.filesys.alfresco.DesktopAction; +import org.alfresco.filesys.alfresco.DesktopActionTable; import org.alfresco.filesys.server.SrvSession; import org.alfresco.filesys.server.filesys.FileName; import org.alfresco.filesys.server.filesys.TreeConnection; +import org.alfresco.filesys.server.pseudo.MemoryPseudoFile; +import org.alfresco.filesys.server.pseudo.PseudoFile; +import org.alfresco.filesys.server.pseudo.PseudoFileInterface; import org.alfresco.filesys.server.state.FileState; import org.alfresco.filesys.smb.server.SMBSrvSession; import org.alfresco.filesys.smb.server.repo.ContentContext; -import org.alfresco.filesys.smb.server.repo.DesktopAction; -import org.alfresco.filesys.smb.server.repo.DesktopActionTable; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** - * Content Filesystem Driver Pseudo File Implementation + * Alfresco Filesystem Driver Pseudo File Implementation * - *

Pseudo file implementation for the content disk driver. + *

Pseudo file implementation for the Alfresco filesystem drivers. * * @author gkspencer */ -public class ContentPseudoFileImpl implements PseudoFileInterface +public class PseudoFileImpl implements PseudoFileInterface { // Logging - private static final Log logger = LogFactory.getLog(ContentPseudoFileImpl.class); + private static final Log logger = LogFactory.getLog(PseudoFileImpl.class); /** * Check if the specified path refers to a pseudo file diff --git a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoFileInterface.java b/source/java/org/alfresco/filesys/server/pseudo/PseudoFileInterface.java similarity index 94% rename from source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoFileInterface.java rename to source/java/org/alfresco/filesys/server/pseudo/PseudoFileInterface.java index cf95c41d78..0bcde1c545 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoFileInterface.java +++ b/source/java/org/alfresco/filesys/server/pseudo/PseudoFileInterface.java @@ -15,7 +15,7 @@ * License. */ -package org.alfresco.filesys.smb.server.repo.pseudo; +package org.alfresco.filesys.server.pseudo; import org.alfresco.filesys.server.SrvSession; import org.alfresco.filesys.server.filesys.TreeConnection; diff --git a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoFileList.java b/source/java/org/alfresco/filesys/server/pseudo/PseudoFileList.java similarity index 94% rename from source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoFileList.java rename to source/java/org/alfresco/filesys/server/pseudo/PseudoFileList.java index 4ae2983cbf..660f9d213d 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoFileList.java +++ b/source/java/org/alfresco/filesys/server/pseudo/PseudoFileList.java @@ -15,7 +15,7 @@ * License. */ -package org.alfresco.filesys.smb.server.repo.pseudo; +package org.alfresco.filesys.server.pseudo; import java.util.ArrayList; import java.util.List; diff --git a/source/java/org/alfresco/filesys/server/pseudo/PseudoFolderNetworkFile.java b/source/java/org/alfresco/filesys/server/pseudo/PseudoFolderNetworkFile.java new file mode 100644 index 0000000000..c8a60bfbf9 --- /dev/null +++ b/source/java/org/alfresco/filesys/server/pseudo/PseudoFolderNetworkFile.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.filesys.server.pseudo; + +import java.io.IOException; + +import org.alfresco.filesys.server.filesys.AccessDeniedException; +import org.alfresco.filesys.server.filesys.FileAttribute; +import org.alfresco.filesys.server.filesys.NetworkFile; + +/** + * Pseudo Folder Network File Class + * + *

Represents an open pseudo folder. + * + * @author gkspencer + */ +public class PseudoFolderNetworkFile extends NetworkFile { + + /** + * Class constructor. + * + * @param name String + */ + public PseudoFolderNetworkFile(String name) + { + super( name); + + setAttributes( FileAttribute.Directory); + } + + /** + * Class constructor. + * + * @param name String + * @param relPath String + */ + public PseudoFolderNetworkFile(String name, String relPath) + { + super( name); + + setFullName( relPath); + setAttributes( FileAttribute.Directory); + } + + /** + * Close the network file. + */ + public void closeFile() throws java.io.IOException + { + // Nothing to do + } + + /** + * Return the current file position. + * + * @return long + */ + public long currentPosition() + { + return 0L; + } + + /** + * Flush the file. + * + * @exception IOException + */ + public void flushFile() throws IOException + { + // Nothing to do + } + + /** + * Determine if the end of file has been reached. + * + * @return boolean + */ + public boolean isEndOfFile() throws java.io.IOException + { + return true; + } + + /** + * Open the file. + * + * @param createFlag boolean + * @exception IOException + */ + public void openFile(boolean createFlag) throws java.io.IOException + { + } + + /** + * Read from the file. + * + * @param buf byte[] + * @param len int + * @param pos int + * @param fileOff long + * @return Length of data read. + * @exception IOException + */ + public int readFile(byte[] buf, int len, int pos, long fileOff) throws java.io.IOException + { + throw new AccessDeniedException( "Attempt to read/write folder file"); + } + + /** + * Seek to the specified file position. + * + * @param pos long + * @param typ int + * @return long + * @exception IOException + */ + public long seekFile(long pos, int typ) throws IOException + { + throw new AccessDeniedException( "Attempt to read/write folder file"); + } + + /** + * Truncate the file + * + * @param siz long + * @exception IOException + */ + public void truncateFile(long siz) throws IOException + { + throw new AccessDeniedException( "Attempt to read/write folder file"); + } + + /** + * Write a block of data to the file. + * + * @param buf byte[] + * @param len int + * @exception IOException + */ + public void writeFile(byte[] buf, int len, int pos) throws java.io.IOException + { + throw new AccessDeniedException( "Attempt to read/write folder file"); + } + + /** + * Write a block of data to the file. + * + * @param buf byte[] + * @param len int + * @param pos int + * @param offset long + * @exception IOException + */ + public void writeFile(byte[] buf, int len, int pos, long offset) throws java.io.IOException + { + throw new AccessDeniedException( "Attempt to read/write folder file"); + } +} diff --git a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoNetworkFile.java b/source/java/org/alfresco/filesys/server/pseudo/PseudoNetworkFile.java similarity index 93% rename from source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoNetworkFile.java rename to source/java/org/alfresco/filesys/server/pseudo/PseudoNetworkFile.java index 4bcd2cefe0..7ea024c62e 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/pseudo/PseudoNetworkFile.java +++ b/source/java/org/alfresco/filesys/server/pseudo/PseudoNetworkFile.java @@ -15,7 +15,7 @@ * License. */ -package org.alfresco.filesys.smb.server.repo.pseudo; +package org.alfresco.filesys.server.pseudo; import java.io.File; import java.io.IOException; @@ -26,8 +26,8 @@ import org.alfresco.filesys.smb.SeekType; /** * Pseudo File Network File Class - *

- * Represents an open pseudo file and provides access to the file data. + * + *

Represents an open pseudo file and provides access to the file data. * * @author gkspencer */ diff --git a/source/java/org/alfresco/filesys/server/state/FileState.java b/source/java/org/alfresco/filesys/server/state/FileState.java index 1ebc55434b..a378196253 100644 --- a/source/java/org/alfresco/filesys/server/state/FileState.java +++ b/source/java/org/alfresco/filesys/server/state/FileState.java @@ -22,9 +22,9 @@ import org.alfresco.filesys.locking.LockConflictException; import org.alfresco.filesys.locking.NotLockedException; import org.alfresco.filesys.server.filesys.FileOpenParams; import org.alfresco.filesys.server.filesys.FileStatus; +import org.alfresco.filesys.server.pseudo.PseudoFile; +import org.alfresco.filesys.server.pseudo.PseudoFileList; import org.alfresco.filesys.smb.SharingMode; -import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFile; -import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFileList; import org.alfresco.service.cmr.repository.NodeRef; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/source/java/org/alfresco/filesys/smb/server/repo/ContentContext.java b/source/java/org/alfresco/filesys/smb/server/repo/ContentContext.java index ac6b372855..3c536420f1 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/ContentContext.java +++ b/source/java/org/alfresco/filesys/smb/server/repo/ContentContext.java @@ -16,13 +16,9 @@ */ package org.alfresco.filesys.smb.server.repo; -import java.util.Enumeration; - +import org.alfresco.filesys.alfresco.AlfrescoContext; +import org.alfresco.filesys.alfresco.IOControlHandler; import org.alfresco.filesys.server.filesys.*; -import org.alfresco.filesys.server.state.FileStateReaper; -import org.alfresco.filesys.server.state.FileStateTable; -import org.alfresco.filesys.smb.server.repo.pseudo.ContentPseudoFileImpl; -import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFileInterface; import org.alfresco.service.cmr.repository.*; /** @@ -32,7 +28,7 @@ import org.alfresco.service.cmr.repository.*; * * @author GKSpencer */ -public class ContentContext extends DiskDeviceContext +public class ContentContext extends AlfrescoContext { // Store and root path @@ -43,28 +39,6 @@ public class ContentContext extends DiskDeviceContext private NodeRef m_rootNodeRef; - // File state table and associated file state reaper - - private FileStateTable m_stateTable; - private FileStateReaper m_stateReaper; - - // URL pseudo file web path prefix (server/port/webapp) and link file name - - private String m_urlPathPrefix; - private String m_urlFileName; - - // Pseudo file interface - - private PseudoFileInterface m_pseudoFileInterface; - - // Desktop actions - - private DesktopActionTable m_desktopActions; - - // I/O control handler - - private IOControlHandler m_ioHandler; - /** * Class constructor * @@ -81,10 +55,6 @@ public class ContentContext extends DiskDeviceContext m_rootPath = rootPath; m_rootNodeRef = rootNodeRef; - - // Create the file state table - - m_stateTable = new FileStateTable(); } /** @@ -127,263 +97,24 @@ public class ContentContext extends DiskDeviceContext return m_rootNodeRef; } - /** - * Determine if the file state table is enabled - * - * @return boolean - */ - public final boolean hasStateTable() - { - return m_stateTable != null ? true : false; - } - - /** - * Return the file state table - * - * @return FileStateTable - */ - public final FileStateTable getStateTable() - { - return m_stateTable; - } - - /** - * Enable/disable the file state table - * - * @param ena boolean - * @param stateReaper FileStateReaper - */ - public final void enableStateTable(boolean ena, FileStateReaper stateReaper) - { - if ( ena == false) - { - // Remove the state table from the reaper - - stateReaper.removeStateTable( getFilesystemName()); - m_stateTable = null; - } - else if ( m_stateTable == null) - { - // Create the file state table - - m_stateTable = new FileStateTable(); - - // Register with the file state reaper - - stateReaper.addStateTable( getFilesystemName(), m_stateTable); - } - - // Save the reaper, for deregistering when the filesystem is closed - - m_stateReaper = stateReaper; - } - - /** - * Determine if the pseudo file interface is enabled - * - * @return boolean - */ - public final boolean hasPseudoFileInterface() - { - return m_pseudoFileInterface != null ? true : false; - } - - /** - * Return the pseudo file interface - * - * @return PseudoFileInterface - */ - public final PseudoFileInterface getPseudoFileInterface() - { - return m_pseudoFileInterface; - } - - /** - * Enable the pseudo file interface for this filesystem - */ - public final void enabledPseudoFileInterface() - { - if ( m_pseudoFileInterface == null) - m_pseudoFileInterface = new ContentPseudoFileImpl(); - } - - /** - * Determine if there are desktop actins configured - * - * @return boolean - */ - public final boolean hasDesktopActions() - { - return m_desktopActions != null ? true : false; - } - - /** - * Return the desktop actions table - * - * @return DesktopActionTable - */ - public final DesktopActionTable getDesktopActions() - { - return m_desktopActions; - } - - /** - * Return the count of desktop actions - * - * @return int - */ - public final int numberOfDesktopActions() - { - return m_desktopActions != null ? m_desktopActions.numberOfActions() : 0; - } - - /** - * Add a desktop action - * - * @param action DesktopAction - * @return boolean - */ - public final boolean addDesktopAction(DesktopAction action) - { - // Check if the desktop actions table has been created - - if ( m_desktopActions == null) - { - m_desktopActions = new DesktopActionTable(); - - // Enable pseudo files - - enabledPseudoFileInterface(); - } - - // Add the action - - return m_desktopActions.addAction(action); - } - - /** - * Determine if custom I/O control handling is enabled for this filesystem - * - * @return boolean - */ - public final boolean hasIOHandler() - { - return m_ioHandler != null ? true : false; - } - - /** - * Return the custom I/O control handler - * - * @return IOControlHandler - */ - public final IOControlHandler getIOHandler() - { - return m_ioHandler; - } - - /** - * Determine if the URL pseudo file is enabled - * - * @return boolean - */ - public final boolean hasURLFile() - { - if ( m_urlPathPrefix != null && m_urlFileName != null) - return true; - return false; - } - - /** - * Return the URL pseudo file path prefix - * - * @return String - */ - public final String getURLPrefix() - { - return m_urlPathPrefix; - } - - /** - * Return the URL pseudo file name - * - * @return String - */ - public final String getURLFileName() - { - return m_urlFileName; - } - - /** - * Set the URL path prefix - * - * @param urlPrefix String - */ - public final void setURLPrefix(String urlPrefix) - { - m_urlPathPrefix = urlPrefix; - - if ( urlPrefix != null) - enabledPseudoFileInterface(); - } - - /** - * Set the URL pseudo file name - * - * @param urlFileName String - */ - public final void setURLFileName(String urlFileName) - { - m_urlFileName = urlFileName; - - if ( urlFileName != null) - enabledPseudoFileInterface(); - } - - /** - * Set the desktop actions - * - * @param desktopActions DesktopActionTable - * @param filesysDriver DiskInterface - */ - public final void setDesktopActions(DesktopActionTable desktopActions, DiskInterface filesysDriver) - { - // Enumerate the desktop actions and add to this filesystem - - Enumeration names = desktopActions.enumerateActionNames(); - - while ( names.hasMoreElements()) - { - addDesktopAction( desktopActions.getAction(names.nextElement())); - } - - // If there are desktop actions then create the custom I/O control handler - - if ( numberOfDesktopActions() > 0) - { - // Access the filesystem driver - - ContentDiskDriver contentDriver = (ContentDiskDriver) filesysDriver; - - // Create the custom I/O control handler - - m_ioHandler = new ContentIOControlHandler(); - m_ioHandler.initialize(contentDriver, this); - } - } - /** * Close the filesystem context */ public void CloseContext() { - // Deregister the file state table from the reaper - - if ( m_stateTable != null) - enableStateTable( false, m_stateReaper); - // Call the base class super.CloseContext(); } + /** + * Create the I/O control handler for this filesystem type + * + * @param filesysDriver DiskInterface + * @return IOControlHandler + */ + protected IOControlHandler createIOHandler( DiskInterface filesysDriver) + { + return new ContentIOControlHandler(); + } } diff --git a/source/java/org/alfresco/filesys/smb/server/repo/ContentDiskDriver.java b/source/java/org/alfresco/filesys/smb/server/repo/ContentDiskDriver.java index 983cba5a49..66fb6e83c5 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/ContentDiskDriver.java +++ b/source/java/org/alfresco/filesys/smb/server/repo/ContentDiskDriver.java @@ -25,6 +25,7 @@ import javax.transaction.UserTransaction; import org.alfresco.config.ConfigElement; import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.filesys.alfresco.AlfrescoDiskDriver; import org.alfresco.filesys.server.SrvSession; import org.alfresco.filesys.server.core.DeviceContext; import org.alfresco.filesys.server.core.DeviceContextException; @@ -38,30 +39,21 @@ import org.alfresco.filesys.server.filesys.FileName; import org.alfresco.filesys.server.filesys.FileOpenParams; import org.alfresco.filesys.server.filesys.FileSharingException; import org.alfresco.filesys.server.filesys.FileStatus; -import org.alfresco.filesys.server.filesys.FileSystem; -import org.alfresco.filesys.server.filesys.IOControlNotImplementedException; -import org.alfresco.filesys.server.filesys.IOCtlInterface; import org.alfresco.filesys.server.filesys.NetworkFile; import org.alfresco.filesys.server.filesys.SearchContext; -import org.alfresco.filesys.server.filesys.SrvDiskInfo; import org.alfresco.filesys.server.filesys.TreeConnection; +import org.alfresco.filesys.server.pseudo.MemoryNetworkFile; +import org.alfresco.filesys.server.pseudo.PseudoFile; +import org.alfresco.filesys.server.pseudo.PseudoFileInterface; +import org.alfresco.filesys.server.pseudo.PseudoFileList; +import org.alfresco.filesys.server.pseudo.PseudoNetworkFile; import org.alfresco.filesys.server.state.FileState; -import org.alfresco.filesys.server.state.FileStateReaper; import org.alfresco.filesys.server.state.FileState.FileStateStatus; -import org.alfresco.filesys.smb.SMBException; -import org.alfresco.filesys.smb.SMBStatus; import org.alfresco.filesys.smb.SharingMode; import org.alfresco.filesys.smb.server.SMBSrvSession; -import org.alfresco.filesys.smb.server.repo.pseudo.MemoryNetworkFile; -import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFile; -import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFileInterface; -import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFileList; -import org.alfresco.filesys.smb.server.repo.pseudo.PseudoNetworkFile; -import org.alfresco.filesys.util.DataBuffer; import org.alfresco.filesys.util.WildCard; import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationComponent; -import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.lock.NodeLockedException; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.NodeRef; @@ -83,7 +75,7 @@ import org.apache.commons.logging.LogFactory; * * @author Derek Hulley */ -public class ContentDiskDriver implements DiskInterface, IOCtlInterface +public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterface { // Logging @@ -112,14 +104,6 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface private AuthenticationComponent authComponent; private AuthenticationService authService; - // Service registry for desktop actions - - private ServiceRegistry serviceRegistry; - - // File state reaper - - private FileStateReaper m_stateReaper; - /** * Class constructor * @@ -199,26 +183,6 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface return this.searchService; } - /** - * Return the service registry - * - * @return ServiceRegistry - */ - public final ServiceRegistry getServiceRegistry() - { - return this.serviceRegistry; - } - - /** - * Return the file state reaper - * - * @return FileStateReaper - */ - public final FileStateReaper getStateReaper() - { - return m_stateReaper; - } - /** * @param contentService the content service */ @@ -269,16 +233,6 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface this.permissionService = permissionService; } - /** - * Set the service registry - * - * @param serviceRegistry - */ - public void setServiceRegistry(ServiceRegistry serviceRegistry) - { - this.serviceRegistry = serviceRegistry; - } - /** * Set the authentication component * @@ -299,16 +253,6 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface this.authService = authService; } - /** - * Set the file state reaper - * - * @param stateReaper FileStateReaper - */ - public final void setStateReaper(FileStateReaper stateReaper) - { - m_stateReaper = stateReaper; - } - /** * Parse and validate the parameter string and create a device context object for this instance * of the shared device. The same DeviceInterface implementation may be used for multiple @@ -419,15 +363,6 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface // Create the context context = new ContentContext(name, storeValue, rootPath, rootNodeRef); - - // Default the filesystem to look like an 80Gb sized disk with 90% free space - - context.setDiskInformation(new SrvDiskInfo(2560000, 64, 512, 2304000)); - - // Set parameters - - context.setFilesystemAttributes(FileSystem.CasePreservedNames + FileSystem.UnicodeOnDisk + - FileSystem.CaseSensitiveSearch); } catch (Exception ex) { @@ -2198,37 +2133,4 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface { // Nothing to do } - - /** - * Process a filesystem I/O control request - * - * @param sess Server session - * @param tree Tree connection. - * @param ctrlCode I/O control code - * @param fid File id - * @param dataBuf I/O control specific input data - * @param isFSCtrl true if this is a filesystem control, or false for a device control - * @param filter if bit0 is set indicates that the control applies to the share root handle - * @return DataBuffer - * @exception IOControlNotImplementedException - * @exception SMBException - */ - public DataBuffer processIOControl(SrvSession sess, TreeConnection tree, int ctrlCode, int fid, DataBuffer dataBuf, - boolean isFSCtrl, int filter) - throws IOControlNotImplementedException, SMBException - { - // Validate the file id - - NetworkFile netFile = tree.findFile(fid); - if ( netFile == null || netFile.isDirectory() == false) - throw new SMBException(SMBStatus.NTErr, SMBStatus.NTInvalidParameter); - - // Check if the I/O control handler is enabled - - ContentContext ctx = (ContentContext) tree.getContext(); - if ( ctx.hasIOHandler()) - return ctx.getIOHandler().processIOControl( sess, tree, ctrlCode, fid, dataBuf, isFSCtrl, filter); - else - throw new IOControlNotImplementedException(); - } } diff --git a/source/java/org/alfresco/filesys/smb/server/repo/ContentIOControlHandler.java b/source/java/org/alfresco/filesys/smb/server/repo/ContentIOControlHandler.java index f83cad068a..669f48f200 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/ContentIOControlHandler.java +++ b/source/java/org/alfresco/filesys/smb/server/repo/ContentIOControlHandler.java @@ -18,6 +18,15 @@ package org.alfresco.filesys.smb.server.repo; import java.io.FileNotFoundException; +import org.alfresco.filesys.alfresco.AlfrescoContext; +import org.alfresco.filesys.alfresco.AlfrescoDiskDriver; +import org.alfresco.filesys.alfresco.DesktopAction; +import org.alfresco.filesys.alfresco.DesktopActionTable; +import org.alfresco.filesys.alfresco.DesktopParams; +import org.alfresco.filesys.alfresco.DesktopResponse; +import org.alfresco.filesys.alfresco.DesktopTarget; +import org.alfresco.filesys.alfresco.IOControl; +import org.alfresco.filesys.alfresco.IOControlHandler; import org.alfresco.filesys.server.SrvSession; import org.alfresco.filesys.server.auth.ClientInfo; import org.alfresco.filesys.server.filesys.IOControlNotImplementedException; @@ -28,7 +37,6 @@ import org.alfresco.filesys.smb.SMBException; import org.alfresco.filesys.smb.SMBStatus; import org.alfresco.filesys.smb.server.repo.CifsHelper; import org.alfresco.filesys.smb.server.repo.ContentDiskDriver; -import org.alfresco.filesys.smb.server.repo.IOControlHandler; import org.alfresco.filesys.util.DataBuffer; import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationException; @@ -69,13 +77,13 @@ public class ContentIOControlHandler implements IOControlHandler /** * Initalize the I/O control handler * - * @param contentDriver ContentDiskDriver - * @param contentContext ContentContext + * @param filesysDriver AlfrescoDiskDriver + * @param context AlfrescoContext */ - public void initialize( ContentDiskDriver contentDriver, ContentContext contentContext) + public void initialize( AlfrescoDiskDriver filesysDriver, AlfrescoContext context) { - this.contentDriver = contentDriver; - this.contentContext = contentContext; + this.contentDriver = (ContentDiskDriver) filesysDriver; + this.contentContext = (ContentContext) context; } /** diff --git a/source/java/org/alfresco/filesys/smb/server/repo/ContentSearchContext.java b/source/java/org/alfresco/filesys/smb/server/repo/ContentSearchContext.java index 3bec09cebf..b64770332d 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/ContentSearchContext.java +++ b/source/java/org/alfresco/filesys/smb/server/repo/ContentSearchContext.java @@ -21,8 +21,8 @@ import java.util.List; import org.alfresco.filesys.server.filesys.FileInfo; import org.alfresco.filesys.server.filesys.SearchContext; -import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFile; -import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFileList; +import org.alfresco.filesys.server.pseudo.PseudoFile; +import org.alfresco.filesys.server.pseudo.PseudoFileList; import org.alfresco.service.cmr.repository.NodeRef; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/source/java/org/alfresco/filesys/smb/server/repo/desk/CheckInOutDesktopAction.java b/source/java/org/alfresco/filesys/smb/server/repo/desk/CheckInOutDesktopAction.java index 45f535f229..fe81a52957 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/desk/CheckInOutDesktopAction.java +++ b/source/java/org/alfresco/filesys/smb/server/repo/desk/CheckInOutDesktopAction.java @@ -20,15 +20,17 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Map; +import org.alfresco.filesys.alfresco.DesktopAction; +import org.alfresco.filesys.alfresco.DesktopParams; +import org.alfresco.filesys.alfresco.DesktopResponse; +import org.alfresco.filesys.alfresco.DesktopTarget; import org.alfresco.filesys.server.filesys.FileName; import org.alfresco.filesys.server.filesys.NotifyChange; -import org.alfresco.filesys.smb.server.repo.DesktopAction; -import org.alfresco.filesys.smb.server.repo.DesktopParams; -import org.alfresco.filesys.smb.server.repo.DesktopResponse; -import org.alfresco.filesys.smb.server.repo.DesktopTarget; import org.alfresco.model.ContentModel; import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.transaction.TransactionService; /** * Check In/Out Desktop Action Class @@ -75,9 +77,14 @@ public class CheckInOutDesktopAction extends DesktopAction { if ( params.numberOfTargetNodes() == 0) return new DesktopResponse(StsSuccess); + // Get required services + + TransactionService transService = getServiceRegistry().getTransactionService(); + NodeService nodeService = getServiceRegistry().getNodeService(); + // Start a transaction - params.getSession().beginTransaction(getTransactionService(), false); + params.getSession().beginTransaction( transService, false); // Process the list of target nodes @@ -91,7 +98,7 @@ public class CheckInOutDesktopAction extends DesktopAction { // Check if the node is a working copy - if ( getNodeService().hasAspect( target.getNode(), ContentModel.ASPECT_WORKING_COPY)) + if ( nodeService.hasAspect( target.getNode(), ContentModel.ASPECT_WORKING_COPY)) { try { @@ -144,11 +151,11 @@ public class CheckInOutDesktopAction extends DesktopAction { { // Check if the file is locked - if ( getNodeService().hasAspect( target.getNode(), ContentModel.ASPECT_LOCKABLE)) { + if ( nodeService.hasAspect( target.getNode(), ContentModel.ASPECT_LOCKABLE)) { // Get the lock type - String lockTypeStr = (String) getNodeService().getProperty( target.getNode(), ContentModel.PROP_LOCK_TYPE); + String lockTypeStr = (String) nodeService.getProperty( target.getNode(), ContentModel.PROP_LOCK_TYPE); if ( lockTypeStr != null) { response.setStatus(StsError, "Checkout failed, file is locked"); return response; @@ -161,7 +168,7 @@ public class CheckInOutDesktopAction extends DesktopAction { // Get the working copy file name - String workingCopyName = (String) getNodeService().getProperty( workingCopyNode, ContentModel.PROP_NAME); + String workingCopyName = (String) nodeService.getProperty( workingCopyNode, ContentModel.PROP_NAME); // Check out was successful, pack the working copy name diff --git a/source/java/org/alfresco/filesys/smb/server/repo/desk/CmdLineDesktopAction.java b/source/java/org/alfresco/filesys/smb/server/repo/desk/CmdLineDesktopAction.java index 42625ea6a2..e307dabe47 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/desk/CmdLineDesktopAction.java +++ b/source/java/org/alfresco/filesys/smb/server/repo/desk/CmdLineDesktopAction.java @@ -16,9 +16,9 @@ */ package org.alfresco.filesys.smb.server.repo.desk; -import org.alfresco.filesys.smb.server.repo.DesktopAction; -import org.alfresco.filesys.smb.server.repo.DesktopParams; -import org.alfresco.filesys.smb.server.repo.DesktopResponse; +import org.alfresco.filesys.alfresco.DesktopAction; +import org.alfresco.filesys.alfresco.DesktopParams; +import org.alfresco.filesys.alfresco.DesktopResponse; /** * Command Line Desktop Action Class diff --git a/source/java/org/alfresco/filesys/smb/server/repo/desk/EchoDesktopAction.java b/source/java/org/alfresco/filesys/smb/server/repo/desk/EchoDesktopAction.java index 2293d3efff..72c73ef9ac 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/desk/EchoDesktopAction.java +++ b/source/java/org/alfresco/filesys/smb/server/repo/desk/EchoDesktopAction.java @@ -18,9 +18,9 @@ package org.alfresco.filesys.smb.server.repo.desk; import java.util.Date; -import org.alfresco.filesys.smb.server.repo.DesktopAction; -import org.alfresco.filesys.smb.server.repo.DesktopParams; -import org.alfresco.filesys.smb.server.repo.DesktopResponse; +import org.alfresco.filesys.alfresco.DesktopAction; +import org.alfresco.filesys.alfresco.DesktopParams; +import org.alfresco.filesys.alfresco.DesktopResponse; /** * Echo Desktop Action Class diff --git a/source/java/org/alfresco/filesys/smb/server/repo/desk/JavaScriptDesktopAction.java b/source/java/org/alfresco/filesys/smb/server/repo/desk/JavaScriptDesktopAction.java index 1a361e62f2..ebf193a8bd 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/desk/JavaScriptDesktopAction.java +++ b/source/java/org/alfresco/filesys/smb/server/repo/desk/JavaScriptDesktopAction.java @@ -29,13 +29,14 @@ import java.util.Map; import java.util.StringTokenizer; import org.alfresco.config.ConfigElement; +import org.alfresco.filesys.alfresco.DesktopAction; +import org.alfresco.filesys.alfresco.DesktopActionException; +import org.alfresco.filesys.alfresco.DesktopParams; +import org.alfresco.filesys.alfresco.DesktopResponse; import org.alfresco.filesys.server.filesys.DiskSharedDevice; -import org.alfresco.filesys.smb.server.repo.DesktopAction; -import org.alfresco.filesys.smb.server.repo.DesktopActionException; -import org.alfresco.filesys.smb.server.repo.DesktopParams; -import org.alfresco.filesys.smb.server.repo.DesktopResponse; import org.alfresco.service.cmr.repository.ScriptException; import org.alfresco.service.cmr.repository.ScriptService; +import org.alfresco.service.transaction.TransactionService; /** * Javascript Desktop Action Class @@ -272,7 +273,8 @@ public class JavaScriptDesktopAction extends DesktopAction { // Start a transaction - params.getSession().beginTransaction(getTransactionService(), false); + TransactionService transService = getServiceRegistry().getTransactionService(); + params.getSession().beginTransaction( transService, false); // Access the script service @@ -291,7 +293,7 @@ public class JavaScriptDesktopAction extends DesktopAction { // Start a transaction - params.getSession().beginTransaction(getTransactionService(), false); + params.getSession().beginTransaction( transService, false); // Run the script diff --git a/source/java/org/alfresco/filesys/smb/server/repo/desk/URLDesktopAction.java b/source/java/org/alfresco/filesys/smb/server/repo/desk/URLDesktopAction.java index 2a91523ae7..a40e85c5d5 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/desk/URLDesktopAction.java +++ b/source/java/org/alfresco/filesys/smb/server/repo/desk/URLDesktopAction.java @@ -19,9 +19,10 @@ package org.alfresco.filesys.smb.server.repo.desk; import java.net.InetAddress; import java.net.UnknownHostException; -import org.alfresco.filesys.smb.server.repo.DesktopAction; -import org.alfresco.filesys.smb.server.repo.DesktopParams; -import org.alfresco.filesys.smb.server.repo.DesktopResponse; +import org.alfresco.filesys.alfresco.DesktopAction; +import org.alfresco.filesys.alfresco.DesktopParams; +import org.alfresco.filesys.alfresco.DesktopResponse; + /** * URL Desktop Action Class