mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged HEAD-BUG-FIX (5.0/Cloud) to HEAD (5.0/Cloud)
78403: Merged EOL (5.0/Cloud) to HEAD-BUG-FIX (5.0/Cloud) 75700: ACE-2149: EOL AVM / WCM - Remove most of the AVM and WCM beans, scripts, classes, patches, etc - The Explorer client is very broken for compilation - TODO: Remove all WCM-related functionality, which I thought would be best left to a UI dev I've murdered many of the classes and beans but there's more to do - The repository compiles TODO: Get it running again - TODO: Check if we can wipe the 'deployment' project as well git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@82540 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1,667 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.filesys.alfresco.AlfrescoContext;
|
||||
import org.alfresco.filesys.alfresco.AlfrescoDiskDriver;
|
||||
import org.alfresco.filesys.alfresco.IOControlHandler;
|
||||
import org.alfresco.jlan.server.filesys.DiskInterface;
|
||||
import org.alfresco.jlan.server.filesys.FileName;
|
||||
import org.alfresco.jlan.server.filesys.FileSystem;
|
||||
import org.alfresco.jlan.server.filesys.NotifyChange;
|
||||
import org.alfresco.jlan.server.filesys.cache.FileState;
|
||||
import org.alfresco.jlan.server.filesys.cache.FileStateCache;
|
||||
import org.alfresco.jlan.util.StringList;
|
||||
import org.alfresco.repo.avm.CreateStoreCallback;
|
||||
import org.alfresco.repo.avm.CreateVersionCallback;
|
||||
import org.alfresco.repo.avm.PurgeStoreCallback;
|
||||
import org.alfresco.repo.avm.PurgeVersionCallback;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* AVM Filesystem Context Class
|
||||
*
|
||||
* <p>Contains per filesystem context.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class AVMContext extends AlfrescoContext
|
||||
implements CreateStoreCallback, PurgeStoreCallback, CreateVersionCallback, PurgeVersionCallback {
|
||||
|
||||
// Logging
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AVMContext.class);
|
||||
|
||||
// Constants
|
||||
//
|
||||
// Version id that indicates the head version
|
||||
|
||||
public static final int VERSION_HEAD = -1;
|
||||
|
||||
// Store types to show in the virtualization view
|
||||
|
||||
public static final int ShowNormalStores = 0x0001;
|
||||
public static final int ShowSiteStores = 0x0002;
|
||||
public static final int ShowStagingStores = 0x0004;
|
||||
public static final int ShowAuthorStores = 0x0008;
|
||||
public static final int ShowPreviewStores = 0x0010;
|
||||
|
||||
// Store, root path and version
|
||||
|
||||
private String m_storePath;
|
||||
private int m_version = VERSION_HEAD;
|
||||
|
||||
// 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;
|
||||
|
||||
// Virtualization view filtering options
|
||||
|
||||
private int m_showOptions = ShowStagingStores + ShowAuthorStores;
|
||||
|
||||
// List of newly created store names that need adding into the virtualization view
|
||||
|
||||
private StringList m_newStores;
|
||||
private Object m_newStoresLock;
|
||||
|
||||
// Allow admin user to write to web project staging stores
|
||||
|
||||
private boolean m_allowAdminStagingWrites;
|
||||
|
||||
// Auto create the store if it doesn't exist?
|
||||
|
||||
private boolean m_createStore;
|
||||
|
||||
/**
|
||||
* Default constructor allowing initialization by container.
|
||||
*/
|
||||
public AVMContext()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* <p>Construct a context for a normal view onto a single store/version within AVM.
|
||||
*
|
||||
* @param filesysName String
|
||||
* @param storePath String
|
||||
* @param version int
|
||||
*/
|
||||
public AVMContext( String filesysName, String storePath, int version)
|
||||
{
|
||||
setDeviceName(filesysName);
|
||||
|
||||
// Set the store root path
|
||||
setStorePath(storePath);
|
||||
|
||||
// Set the store version to use
|
||||
setVersion(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* <p>Construct a context for a virtualization view onto all stores/versions within AVM.
|
||||
*
|
||||
* @param filesysName String
|
||||
* @param showOptions int
|
||||
* @param avmDriver AVMDiskDriver
|
||||
*/
|
||||
public AVMContext( String filesysName, int showOptions, AVMDiskDriver avmDriver)
|
||||
{
|
||||
setDeviceName(filesysName);
|
||||
|
||||
// Enable the virtualization view
|
||||
setVirtualView(true);
|
||||
setShowOptions(showOptions);
|
||||
}
|
||||
|
||||
public void setStorePath(String path)
|
||||
{
|
||||
this.m_storePath = path;
|
||||
}
|
||||
|
||||
public void setVersion(int version)
|
||||
{
|
||||
this.m_version = version;
|
||||
}
|
||||
|
||||
public void setShowOptions(int showOptions)
|
||||
{
|
||||
this.m_showOptions = showOptions;
|
||||
}
|
||||
|
||||
public void setStores(String showAttr)
|
||||
{
|
||||
if ( showAttr != null)
|
||||
{
|
||||
// Split the show options string
|
||||
|
||||
StringTokenizer tokens = new StringTokenizer( showAttr, ",");
|
||||
StringList optList = new StringList();
|
||||
|
||||
while ( tokens.hasMoreTokens())
|
||||
optList.addString( tokens.nextToken().trim().toLowerCase());
|
||||
|
||||
// Build the show options mask
|
||||
|
||||
this.m_showOptions = 0;
|
||||
|
||||
if ( optList.containsString("normal"))
|
||||
this.m_showOptions += ShowNormalStores;
|
||||
|
||||
if ( optList.containsString("site"))
|
||||
this.m_showOptions += ShowSiteStores;
|
||||
|
||||
if ( optList.containsString("author"))
|
||||
this.m_showOptions += ShowAuthorStores;
|
||||
|
||||
if ( optList.containsString("preview"))
|
||||
this.m_showOptions += ShowPreviewStores;
|
||||
|
||||
if ( optList.containsString("staging"))
|
||||
this.m_showOptions += ShowStagingStores;
|
||||
}
|
||||
}
|
||||
|
||||
public void setVirtualView(boolean isVirtualView)
|
||||
{
|
||||
this.m_virtualView = isVirtualView;
|
||||
}
|
||||
|
||||
public boolean getCreateStore()
|
||||
{
|
||||
return m_createStore;
|
||||
}
|
||||
|
||||
public void setCreateStore(boolean createStore)
|
||||
{
|
||||
m_createStore = createStore;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(AlfrescoDiskDriver filesysDriver)
|
||||
{
|
||||
if (m_virtualView)
|
||||
{
|
||||
// A context for a view onto all stores/versions within AVM.
|
||||
m_newStoresLock = new Object();
|
||||
m_newStores = new StringList();
|
||||
|
||||
setShareName("VirtualView");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_storePath == null
|
||||
|| m_storePath.length() == 0)
|
||||
throw new AlfrescoRuntimeException("Device missing init value: storePath");
|
||||
|
||||
// A context for a normal view onto a single store/version within AVM.
|
||||
if (m_storePath.endsWith("/"))
|
||||
m_storePath = m_storePath.substring(0, m_storePath.length() - 1);
|
||||
|
||||
// Range check the version id
|
||||
if (m_version < 0 && m_version != AVMContext.VERSION_HEAD)
|
||||
throw new AlfrescoRuntimeException("Invalid store version id specified, " + m_version);
|
||||
|
||||
setShareName(m_storePath + "(" + m_version + ")");
|
||||
}
|
||||
super.initialize(filesysDriver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filesystem type, either FileSystem.TypeFAT or FileSystem.TypeNTFS.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getFilesystemType()
|
||||
{
|
||||
return FileSystem.TypeNTFS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the store path
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public final String getStorePath()
|
||||
{
|
||||
return m_storePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the version
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int isVersion()
|
||||
{
|
||||
return m_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the virtualization view is enabled
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean isVirtualizationView()
|
||||
{
|
||||
return m_virtualView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the admin user is allowed to write to web project staging stores
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean allowAdminStagingWrites() {
|
||||
return m_allowAdminStagingWrites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the admin web project staging store writeable status
|
||||
*
|
||||
* @param writeable boolean
|
||||
*/
|
||||
public final void setAllowAdminStagingWrites(boolean writeable) {
|
||||
m_allowAdminStagingWrites = writeable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are any new stores queued for adding to the virtualization view
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected final boolean hasNewStoresQueued() {
|
||||
if ( m_newStores == null || m_newStores.numberOfStrings() == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the new stores queue, and reset the current queue
|
||||
*
|
||||
* @return StringList
|
||||
*/
|
||||
protected StringList getNewStoresQueue() {
|
||||
|
||||
StringList storesQueue = null;
|
||||
|
||||
synchronized ( m_newStoresLock) {
|
||||
storesQueue = m_newStores;
|
||||
m_newStores = new StringList();
|
||||
}
|
||||
|
||||
return storesQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if normal stores should be shown in the virtualization view
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean showNormalStores()
|
||||
{
|
||||
return (m_showOptions & ShowNormalStores) != 0 ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if site data stores should be shown in the virtualization view
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean showSiteStores()
|
||||
{
|
||||
return (m_showOptions & ShowSiteStores) != 0 ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if author stores should be shown in the virtualization view
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean showAuthorStores()
|
||||
{
|
||||
return (m_showOptions & ShowAuthorStores) != 0 ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if preview stores should be shown in the virtualization view
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean showPreviewStores()
|
||||
{
|
||||
return (m_showOptions & ShowPreviewStores) != 0 ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if staging stores should be shown in the virtualization view
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean showStagingStores()
|
||||
{
|
||||
return (m_showOptions & ShowStagingStores) != 0 ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the specified store type should be visible
|
||||
*
|
||||
* @param storeType int
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean showStoreType(int storeType)
|
||||
{
|
||||
boolean showStore = false;
|
||||
|
||||
switch (storeType)
|
||||
{
|
||||
case StoreType.Normal:
|
||||
showStore = showNormalStores();
|
||||
break;
|
||||
case StoreType.SiteStore:
|
||||
showStore = showSiteStores();
|
||||
break;
|
||||
case StoreType.WebAuthorMain:
|
||||
showStore = showAuthorStores();
|
||||
break;
|
||||
case StoreType.WebStagingMain:
|
||||
showStore = showStagingStores();
|
||||
break;
|
||||
case StoreType.WebAuthorPreview:
|
||||
case StoreType.WebStagingPreview:
|
||||
showStore = showPreviewStores();
|
||||
break;
|
||||
}
|
||||
|
||||
return showStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the filesystem context
|
||||
*/
|
||||
public void CloseContext() {
|
||||
|
||||
// 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 null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create store call back handler
|
||||
*
|
||||
* @param storeName String
|
||||
* @param versionID int
|
||||
*/
|
||||
public void storeCreated(String storeName)
|
||||
{
|
||||
// Not interested if the virtualization view is not enabled
|
||||
|
||||
if ( isVirtualizationView() == false)
|
||||
return;
|
||||
|
||||
// Make sure the file state cache is enabled
|
||||
|
||||
FileStateCache fsTable = getStateCache();
|
||||
if ( fsTable == null)
|
||||
return;
|
||||
|
||||
// Find the file state for the root folder
|
||||
|
||||
FileState rootState = fsTable.findFileState( FileName.DOS_SEPERATOR_STR, true);
|
||||
|
||||
if ( rootState != null)
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Queueing new store " + storeName + " for addition to virtualization view");
|
||||
|
||||
// Add the new store name to the list to be picked up by the next file server access
|
||||
// to the filesystem
|
||||
|
||||
synchronized ( m_newStoresLock) {
|
||||
|
||||
// Add the new store name
|
||||
|
||||
m_newStores.addString( storeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge store call back handler
|
||||
*
|
||||
* @param storeName String
|
||||
*/
|
||||
public void storePurged(String storeName)
|
||||
{
|
||||
// Not interested if the virtualization view is not enabled
|
||||
|
||||
if ( isVirtualizationView() == false)
|
||||
return;
|
||||
|
||||
// Make sure the file state cache is enabled
|
||||
|
||||
FileStateCache fsTable = getStateCache();
|
||||
if ( fsTable == null)
|
||||
return;
|
||||
|
||||
// Find the file state for the root folder
|
||||
|
||||
FileState rootState = fsTable.findFileState( FileName.DOS_SEPERATOR_STR);
|
||||
|
||||
if ( rootState != null && rootState.hasPseudoFiles())
|
||||
{
|
||||
// Remove the pseudo folder for the store
|
||||
|
||||
rootState.getPseudoFileList().removeFile( storeName, false);
|
||||
|
||||
// Build the filesystem relative path to the deleted store folder
|
||||
|
||||
StringBuilder pathStr = new StringBuilder();
|
||||
|
||||
pathStr.append( FileName.DOS_SEPERATOR);
|
||||
pathStr.append( storeName);
|
||||
|
||||
// Remove the file state for the deleted store
|
||||
|
||||
String storePath = pathStr.toString();
|
||||
fsTable.removeFileState( storePath);
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug( "Removed pseudo folder for purged store " + storeName);
|
||||
|
||||
// Update the file state modify time
|
||||
|
||||
rootState.updateModifyDateTime();
|
||||
|
||||
// Send a change notification for the deleted folder
|
||||
|
||||
if ( hasChangeHandler())
|
||||
{
|
||||
// Send the change notification
|
||||
|
||||
getChangeHandler().notifyDirectoryChanged(NotifyChange.ActionRemoved, storePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create version call back handler
|
||||
*
|
||||
* @param storeName String
|
||||
* @param versionID int
|
||||
*/
|
||||
public void versionCreated(String storeName, int versionID)
|
||||
{
|
||||
// Not interested if the virtualization view is not enabled
|
||||
|
||||
if ( isVirtualizationView() == false)
|
||||
return;
|
||||
|
||||
// Make sure the file state cache is enabled
|
||||
|
||||
FileStateCache fsTable = getStateCache();
|
||||
if ( fsTable == null)
|
||||
return;
|
||||
|
||||
// Build the path to the store version folder
|
||||
|
||||
StringBuilder pathStr = new StringBuilder();
|
||||
|
||||
pathStr.append( FileName.DOS_SEPERATOR);
|
||||
pathStr.append( storeName);
|
||||
pathStr.append( FileName.DOS_SEPERATOR);
|
||||
pathStr.append( AVMPath.VersionsFolder);
|
||||
|
||||
// Find the file state for the store versions folder
|
||||
|
||||
FileState verState = fsTable.findFileState( pathStr.toString());
|
||||
|
||||
if ( verState != null)
|
||||
{
|
||||
// Create the version folder name
|
||||
|
||||
StringBuilder verStr = new StringBuilder();
|
||||
|
||||
verStr.append( AVMPath.VersionFolderPrefix);
|
||||
verStr.append( versionID);
|
||||
|
||||
String verName = verStr.toString();
|
||||
|
||||
// Add a pseudo folder for the new version
|
||||
|
||||
pathStr.append( FileName.DOS_SEPERATOR);
|
||||
pathStr.append( verName);
|
||||
|
||||
verState.addPseudoFile( new VersionPseudoFile( verName, pathStr.toString()));
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug( "Added pseudo folder for new version " + storeName + ":/" + verName);
|
||||
|
||||
// Send a change notification for the new folder
|
||||
|
||||
if ( hasChangeHandler())
|
||||
{
|
||||
// Build the filesystem relative path to the new version folder
|
||||
|
||||
pathStr.append( FileName.DOS_SEPERATOR);
|
||||
pathStr.append( verName);
|
||||
|
||||
// Send the change notification
|
||||
|
||||
getChangeHandler().notifyDirectoryChanged(NotifyChange.ActionAdded, pathStr.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge version call back handler
|
||||
*
|
||||
* @param storeName String
|
||||
*/
|
||||
public void versionPurged(String storeName, int versionID)
|
||||
{
|
||||
// Not interested if the virtualization view is not enabled
|
||||
|
||||
if ( isVirtualizationView() == false)
|
||||
return;
|
||||
|
||||
// Make sure the file state cache is enabled
|
||||
|
||||
FileStateCache fsTable = getStateCache();
|
||||
if ( fsTable == null)
|
||||
return;
|
||||
|
||||
// Build the path to the store version folder
|
||||
|
||||
StringBuilder pathStr = new StringBuilder();
|
||||
|
||||
pathStr.append( FileName.DOS_SEPERATOR);
|
||||
pathStr.append( storeName);
|
||||
pathStr.append( FileName.DOS_SEPERATOR);
|
||||
pathStr.append( AVMPath.VersionsFolder);
|
||||
|
||||
// Find the file state for the store versions folder
|
||||
|
||||
FileState verState = fsTable.findFileState( pathStr.toString());
|
||||
|
||||
if ( verState != null && verState.hasPseudoFiles())
|
||||
{
|
||||
// Create the version folder name
|
||||
|
||||
StringBuilder verStr = new StringBuilder();
|
||||
|
||||
verStr.append( AVMPath.VersionFolderPrefix);
|
||||
verStr.append( versionID);
|
||||
|
||||
String verName = verStr.toString();
|
||||
|
||||
// Remove the pseudo folder for the purged version
|
||||
|
||||
verState.getPseudoFileList().removeFile( verName, true);
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug( "Removed pseudo folder for purged version " + storeName + ":/" + verName);
|
||||
|
||||
// Send a change notification for the deleted folder
|
||||
|
||||
if ( hasChangeHandler())
|
||||
{
|
||||
// Build the filesystem relative path to the deleted version folder
|
||||
|
||||
pathStr.append( FileName.DOS_SEPERATOR);
|
||||
pathStr.append( verName);
|
||||
|
||||
// Send the change notification
|
||||
|
||||
getChangeHandler().notifyDirectoryChanged(NotifyChange.ActionRemoved, pathStr.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,565 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.filesys.alfresco.AlfrescoNetworkFile;
|
||||
import org.alfresco.jlan.server.filesys.AccessDeniedException;
|
||||
import org.alfresco.jlan.server.filesys.DiskFullException;
|
||||
import org.alfresco.jlan.server.filesys.FileAttribute;
|
||||
import org.alfresco.jlan.server.filesys.NetworkFile;
|
||||
import org.alfresco.jlan.smb.SeekType;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.TransactionListenerAdapter;
|
||||
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.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.usage.ContentQuotaException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* AVM Network File Class
|
||||
*
|
||||
* <p>Holds the details of an open file, and provides access to the file data.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class AVMNetworkFile extends AlfrescoNetworkFile {
|
||||
|
||||
// Logging
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AVMNetworkFile.class);
|
||||
|
||||
// Node Service
|
||||
|
||||
private NodeService m_nodeService;
|
||||
|
||||
// AVM service
|
||||
|
||||
private AVMService m_avmService;
|
||||
|
||||
// AVM path to the file/folder and store version
|
||||
|
||||
private String m_avmPath;
|
||||
private int m_avmVersion;
|
||||
|
||||
// Flag to indicate if the file has been modified
|
||||
|
||||
private boolean m_modified;
|
||||
|
||||
// Access to the file data, flag to indicate if the file channel is writable
|
||||
|
||||
private FileChannel m_channel;
|
||||
private ContentWriter m_content;
|
||||
|
||||
private boolean m_writable;
|
||||
|
||||
// Mime type, if a writer is opened
|
||||
|
||||
private String m_mimeType;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param details AVMNodeDescriptor
|
||||
* @param avmPath String
|
||||
* @param avmVersion int
|
||||
* @param nodeService NodeService
|
||||
* @param avmService AVMService
|
||||
*/
|
||||
public AVMNetworkFile( AVMNodeDescriptor details, String avmPath, int avmVersion, NodeService nodeService, AVMService avmService)
|
||||
{
|
||||
super( details.getName());
|
||||
|
||||
// Save the service, apth and version
|
||||
|
||||
m_nodeService = nodeService;
|
||||
m_avmService = avmService;
|
||||
m_avmPath = avmPath;
|
||||
m_avmVersion = avmVersion;
|
||||
|
||||
// Copy the file details
|
||||
|
||||
setAccessDate( details.getAccessDate());
|
||||
setCreationDate( details.getCreateDate());
|
||||
setModifyDate( details.getModDate());
|
||||
|
||||
if ( details.isFile())
|
||||
setFileSize( details.getLength());
|
||||
else
|
||||
setFileSize( 0L);
|
||||
|
||||
int attr = 0;
|
||||
|
||||
if ( details.isDirectory())
|
||||
attr += FileAttribute.Directory;
|
||||
|
||||
if ( avmVersion != AVMContext.VERSION_HEAD)
|
||||
attr += FileAttribute.ReadOnly;
|
||||
|
||||
setAttributes( attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is an open file channel to the content
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasContentChannel()
|
||||
{
|
||||
return m_channel != null ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mime type
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public final String getMimeType()
|
||||
{
|
||||
return m_mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mime type
|
||||
*
|
||||
* @param mimeType String
|
||||
*/
|
||||
public final void setMimeType(String mimeType)
|
||||
{
|
||||
m_mimeType = mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the file
|
||||
*
|
||||
* @param createFlag boolean
|
||||
* @exception IOException
|
||||
*/
|
||||
public void openFile(boolean createFlag)
|
||||
throws IOException
|
||||
{
|
||||
// Nothing to do, content is opened on first read/write
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Read file " + getName() + ", len=" + len + ", offset=" + fileOff);
|
||||
|
||||
// Open the channel for reading
|
||||
|
||||
openContent(false, false);
|
||||
|
||||
// Read from the channel
|
||||
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(buf, pos, len);
|
||||
int count = m_channel.read(byteBuffer, fileOff);
|
||||
if (count < 0)
|
||||
{
|
||||
// Return a zero count at end of file
|
||||
|
||||
count = 0;
|
||||
}
|
||||
|
||||
// Return the length of data read
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a block of data to the file.
|
||||
*
|
||||
* @param buf byte[]
|
||||
* @param len int
|
||||
* @param pos int
|
||||
* @param fileOff long
|
||||
* @exception IOException
|
||||
*/
|
||||
public void writeFile(byte[] buf, int len, int pos, long fileOff)
|
||||
throws java.io.IOException
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Write file " + getName() + ", len=" + len + ", offset=" + fileOff);
|
||||
|
||||
// Open the channel for writing
|
||||
|
||||
openContent(true, false);
|
||||
|
||||
// Write to the channel
|
||||
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(buf, pos, len);
|
||||
m_channel.write(byteBuffer, fileOff);
|
||||
|
||||
// Set modification flag
|
||||
|
||||
m_modified = true;
|
||||
incrementWriteCount();
|
||||
|
||||
// Update the current file size
|
||||
|
||||
setFileSize( m_channel.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to the specified file position.
|
||||
*
|
||||
* @param pos long
|
||||
* @param typ int
|
||||
* @return int
|
||||
* @exception IOException
|
||||
*/
|
||||
public long seekFile(long pos, int typ)
|
||||
throws IOException
|
||||
{
|
||||
// Open the file, if not already open
|
||||
|
||||
openContent( false, false);
|
||||
|
||||
// Check if the current file position is the required file position
|
||||
|
||||
long curPos = m_channel.position();
|
||||
|
||||
switch (typ) {
|
||||
|
||||
// From start of file
|
||||
|
||||
case SeekType.StartOfFile :
|
||||
if (curPos != pos)
|
||||
m_channel.position( pos);
|
||||
break;
|
||||
|
||||
// From current position
|
||||
|
||||
case SeekType.CurrentPos :
|
||||
m_channel.position( curPos + pos);
|
||||
break;
|
||||
|
||||
// From end of file
|
||||
|
||||
case SeekType.EndOfFile :
|
||||
{
|
||||
long newPos = m_channel.size() + pos;
|
||||
m_channel.position(newPos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Return the new file position
|
||||
|
||||
return m_channel.position();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush any buffered output to the file
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void flushFile()
|
||||
throws IOException
|
||||
{
|
||||
// If the file channel is open for write then flush the channel
|
||||
|
||||
if ( m_channel != null && m_writable)
|
||||
m_channel.force( false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate the file to the specified file size
|
||||
*
|
||||
* @param siz long
|
||||
* @exception IOException
|
||||
*/
|
||||
public void truncateFile(long siz)
|
||||
throws IOException
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Truncate file " + getName() + ", size=" + siz);
|
||||
|
||||
// If the content data channel has not been opened yet and the requested size is zero
|
||||
// then this is an open for overwrite so the existing content data is not copied
|
||||
|
||||
if ( m_channel == null && siz == 0L)
|
||||
{
|
||||
// Open content for overwrite, no need to copy existing content data
|
||||
|
||||
openContent(true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal open for write
|
||||
|
||||
openContent(true, false);
|
||||
|
||||
// Truncate or extend the channel
|
||||
|
||||
m_channel.truncate(siz);
|
||||
}
|
||||
|
||||
// Set modification flag
|
||||
|
||||
m_modified = true;
|
||||
incrementWriteCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the database file
|
||||
*/
|
||||
public void closeFile()
|
||||
throws IOException
|
||||
{
|
||||
// If the file is a directory or the file channel has not been opened then there is nothing to do
|
||||
|
||||
if ( isDirectory() || m_channel == null && m_content == null)
|
||||
return;
|
||||
|
||||
// We may be in a retry block, in which case this section will already have executed and channel will be null
|
||||
if (m_channel != null)
|
||||
{
|
||||
// Close the file channel
|
||||
|
||||
try
|
||||
{
|
||||
m_channel.close();
|
||||
m_channel = null;
|
||||
}
|
||||
catch ( IOException ex)
|
||||
{
|
||||
if (RetryingTransactionHelper.extractRetryCause(ex) != null)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
logger.error("Failed to close file channel for " + getName(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (m_content != null)
|
||||
{
|
||||
// Retrieve the content data and stop the content URL from being 'eagerly deleted', in case we need to
|
||||
// retry the transaction
|
||||
|
||||
final ContentData contentData = m_content.getContentData();
|
||||
|
||||
try
|
||||
{
|
||||
NodeRef nodeRef = AVMNodeConverter.ToNodeRef(-1, m_avmPath);
|
||||
m_nodeService.setProperty(nodeRef, ContentModel.PROP_CONTENT, contentData);
|
||||
}
|
||||
catch (ContentQuotaException qe)
|
||||
{
|
||||
throw new DiskFullException(qe.getMessage());
|
||||
}
|
||||
|
||||
// Tidy up after ourselves after a successful commit. Otherwise leave things to allow a
|
||||
AlfrescoTransactionSupport.bindListener(new TransactionListenerAdapter()
|
||||
{
|
||||
@Override
|
||||
public void afterCommit()
|
||||
{
|
||||
m_content = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a file channel to the file content, switching to a writable file channel if required.
|
||||
*
|
||||
* @param write boolean
|
||||
* @param trunc boolean
|
||||
* @throws AccessDeniedException If this network file is read only
|
||||
* @throws AlfrescoRuntimeException If this network file represents a directory
|
||||
*/
|
||||
private void openContent(boolean write, boolean trunc)
|
||||
throws AccessDeniedException, AlfrescoRuntimeException
|
||||
{
|
||||
// Check if this network file is a directory, no content to open
|
||||
|
||||
if ( isDirectory())
|
||||
throw new AlfrescoRuntimeException("Unable to open channel for a directory network file: " + this);
|
||||
|
||||
// Check if write access is required and the current channel is read-only
|
||||
|
||||
long curPos = 0L;
|
||||
|
||||
if ( write && m_writable == false && m_channel != null)
|
||||
{
|
||||
// Close the existing read-only channel
|
||||
|
||||
try
|
||||
{
|
||||
// Save the current file position
|
||||
|
||||
curPos = m_channel.position();
|
||||
|
||||
// Close the read-only file channel
|
||||
|
||||
m_channel.close();
|
||||
m_channel = null;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("Error closing read-only channel", ex);
|
||||
}
|
||||
|
||||
// Debug
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Switching to writable channel for " + getName());
|
||||
}
|
||||
else if ( m_channel != null)
|
||||
{
|
||||
// File channel already open
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to create the channel
|
||||
|
||||
if (write && getGrantedAccess() <= NetworkFile.READONLY)
|
||||
throw new AccessDeniedException("The network file was created for read-only: " + this);
|
||||
|
||||
// Access the content data and get a file channel to the data
|
||||
|
||||
if ( write )
|
||||
{
|
||||
// Access the content data for write
|
||||
|
||||
m_content = null;
|
||||
|
||||
try {
|
||||
|
||||
// Create a writer to access the file data
|
||||
|
||||
m_content = m_avmService.getContentWriter(m_avmPath, false);
|
||||
|
||||
// Set the mime-type
|
||||
|
||||
m_content.setMimetype( getMimeType());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.debug( ex);
|
||||
ex.printStackTrace();
|
||||
|
||||
// Rethrow exception, convert to access denied
|
||||
|
||||
throw new AccessDeniedException("Failed to open file for write access, " + m_avmPath);
|
||||
}
|
||||
|
||||
// Indicate that we have a writable channel to the file
|
||||
|
||||
m_writable = true;
|
||||
|
||||
// Get the writable channel, do not copy existing content data if the file is to be truncated
|
||||
|
||||
m_channel = m_content.getFileChannel( trunc);
|
||||
|
||||
// Reset the file position to match the read-only file channel position, unless we truncated the file
|
||||
|
||||
if ( curPos != 0L && trunc == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_channel.position( curPos);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("Failed to set file position for " + getName(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Access the content data for read
|
||||
|
||||
ContentReader cReader = m_avmService.getContentReader( m_avmVersion, m_avmPath);
|
||||
|
||||
// Indicate that we only have a read-only channel to the data
|
||||
|
||||
m_writable = false;
|
||||
|
||||
// Get the read-only channel
|
||||
|
||||
m_channel = cReader.getFileChannel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the writable state of the content channel
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean isWritable()
|
||||
{
|
||||
return m_writable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the network file details as a string
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder str = new StringBuilder();
|
||||
|
||||
str.append( "[");
|
||||
str.append( getName());
|
||||
str.append( ":");
|
||||
str.append( isDirectory() ? "Dir," : "File,");
|
||||
str.append( getFileSize());
|
||||
str.append( "-Channel=");
|
||||
str.append( m_channel);
|
||||
str.append( m_writable ? ",Write" : ",Read");
|
||||
str.append( m_modified ? ",Modified" : "");
|
||||
str.append( "]");
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
}
|
@@ -1,727 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
import org.alfresco.jlan.server.filesys.FileName;
|
||||
|
||||
/**
|
||||
* AVM Path Class
|
||||
*
|
||||
* <p>Parses a share relative path into store, version and remaining path values.
|
||||
*
|
||||
* @author gkspencer
|
||||
*/
|
||||
public class AVMPath {
|
||||
|
||||
// Constants
|
||||
//
|
||||
// Invalid version id value
|
||||
|
||||
private static final int InvalidVersionId = -2;
|
||||
|
||||
// Version id string for the head version
|
||||
|
||||
public static final String VersionNameHead = "HEAD";
|
||||
|
||||
// Folder name for the versions folder
|
||||
|
||||
public static final String VersionsFolder = "VERSION";
|
||||
|
||||
// Head and version sub-folders
|
||||
|
||||
public static final String DataFolder = "DATA";
|
||||
public static final String MetaDataFolder = "METADATA";
|
||||
|
||||
// Version folder prefix
|
||||
|
||||
public static final String VersionFolderPrefix = "v";
|
||||
|
||||
// AVM path seperator
|
||||
|
||||
public static final char AVM_SEPERATOR = '/';
|
||||
public static final String AVM_SEPERATOR_STR = "/";
|
||||
|
||||
// Level identifiers
|
||||
|
||||
public enum LevelId { Invalid, Root, StoreRoot, Head, HeadData, HeadMetaData, VersionRoot, Version, VersionData, VersionMetaData, StoreRootPath, StorePath };
|
||||
|
||||
// Level identifier for this path
|
||||
|
||||
private LevelId m_levelId = LevelId.Invalid;
|
||||
|
||||
// Store name
|
||||
|
||||
private String m_storeName;
|
||||
|
||||
// Version id
|
||||
|
||||
private int m_version = InvalidVersionId;
|
||||
|
||||
// Remaining path
|
||||
|
||||
private String m_path;
|
||||
|
||||
// AVM style path
|
||||
|
||||
private String m_avmPath;
|
||||
|
||||
// Path is read-only access
|
||||
|
||||
private boolean m_readOnly;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public AVMPath()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* <p>Construct an AVM path for the virtualization view, with store and version folders
|
||||
*
|
||||
* @param shrPath String
|
||||
*/
|
||||
public AVMPath(String shrPath)
|
||||
{
|
||||
// Parse the path
|
||||
|
||||
parsePath( shrPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* <p>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 level id for the path
|
||||
*
|
||||
* @return LevelId
|
||||
*/
|
||||
public LevelId isLevel()
|
||||
{
|
||||
return m_levelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the path is read-only
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean isReadOnlyAccess() {
|
||||
return m_readOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the store name
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public final String getStoreName()
|
||||
{
|
||||
return m_storeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the version id was specified in the path
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasVersion()
|
||||
{
|
||||
return m_version != InvalidVersionId ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the version id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getVersion()
|
||||
{
|
||||
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
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public final String getRelativePath()
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the AVM style path, in <store>:/<path> format
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public final String getAVMPath()
|
||||
{
|
||||
return m_avmPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the path is valid
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean isValid()
|
||||
{
|
||||
return m_levelId == LevelId.Invalid ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the path is to a pseudo folder in the virtualization view
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean isPseudoPath()
|
||||
{
|
||||
return m_levelId == LevelId.Invalid || m_levelId == LevelId.StorePath || m_levelId == LevelId.StoreRootPath ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if hte path is a read-only part of the pseudo folder tree
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean isReadOnlyPseudoPath()
|
||||
{
|
||||
if ( isLevel() == LevelId.Root || isLevel() == LevelId.StoreRoot || isLevel() == LevelId.VersionRoot ||
|
||||
isLevel() == LevelId.Head || isLevel() == LevelId.Version)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the path is the root path
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean isRootPath()
|
||||
{
|
||||
return m_levelId == LevelId.Root ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the path, for the virtualization view onto all stores/versions
|
||||
*
|
||||
* @param path String
|
||||
*/
|
||||
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;
|
||||
m_levelId = LevelId.Root;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the store name
|
||||
|
||||
m_storeName = paths[0];
|
||||
m_levelId = LevelId.StoreRoot;
|
||||
|
||||
if ( paths.length > 1)
|
||||
{
|
||||
// Validate the next element, should be either the HEAD or VERSIONS folder
|
||||
|
||||
String levelStr = paths[1];
|
||||
|
||||
if ( levelStr.equalsIgnoreCase( VersionNameHead))
|
||||
{
|
||||
m_version = -1;
|
||||
m_levelId = LevelId.Head;
|
||||
}
|
||||
else if ( levelStr.equalsIgnoreCase( VersionsFolder))
|
||||
{
|
||||
m_levelId = LevelId.VersionRoot;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid folder at the current level
|
||||
|
||||
m_levelId = LevelId.Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the next level, if available
|
||||
|
||||
if ( paths.length > 2)
|
||||
{
|
||||
// If the previous level is the versions root then the next level should be a
|
||||
// version id folder
|
||||
|
||||
String folderName = paths[2];
|
||||
int pathIdx = 3;
|
||||
|
||||
if ( isLevel() == LevelId.VersionRoot)
|
||||
{
|
||||
// Check that the folder name starts with the version folder prefix
|
||||
|
||||
if ( folderName != null && folderName.startsWith( VersionFolderPrefix) &&
|
||||
folderName.length() > VersionFolderPrefix.length())
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse the version id
|
||||
|
||||
m_version = Integer.parseInt( folderName.substring( VersionFolderPrefix.length()));
|
||||
m_levelId = LevelId.Version;
|
||||
|
||||
// Validate the version id
|
||||
|
||||
if ( m_version < -1)
|
||||
{
|
||||
// Invalid version id
|
||||
|
||||
m_levelId = LevelId.Invalid;
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch ( NumberFormatException ex)
|
||||
{
|
||||
m_levelId = LevelId.Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for the next level
|
||||
|
||||
if ( paths.length > 3)
|
||||
{
|
||||
// Get the next level name
|
||||
|
||||
folderName = paths[3];
|
||||
pathIdx++;
|
||||
|
||||
// Check for the data folder
|
||||
|
||||
if ( folderName.equalsIgnoreCase( DataFolder))
|
||||
{
|
||||
m_levelId = LevelId.VersionData;
|
||||
|
||||
// Set the path to the root of the store
|
||||
|
||||
m_path = FileName.DOS_SEPERATOR_STR;
|
||||
}
|
||||
else if ( folderName.equalsIgnoreCase( MetaDataFolder))
|
||||
{
|
||||
m_levelId = LevelId.VersionMetaData;
|
||||
|
||||
// Set the path to the root of the metadata
|
||||
|
||||
m_path = FileName.DOS_SEPERATOR_STR;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_levelId = LevelId.Invalid;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_levelId = LevelId.Invalid;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If the previous level is head the next level should be the data or metadata folder
|
||||
|
||||
else if ( isLevel() == LevelId.Head)
|
||||
{
|
||||
// Check for the data folder
|
||||
|
||||
if ( folderName.equalsIgnoreCase( DataFolder))
|
||||
{
|
||||
m_levelId = LevelId.HeadData;
|
||||
|
||||
// Set the path to the root of the store
|
||||
|
||||
m_path = FileName.DOS_SEPERATOR_STR;
|
||||
}
|
||||
else if ( folderName.equalsIgnoreCase( MetaDataFolder))
|
||||
{
|
||||
m_levelId = LevelId.HeadMetaData;
|
||||
|
||||
// Set the path to the root of the metadata
|
||||
|
||||
m_path = FileName.DOS_SEPERATOR_STR;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_levelId = LevelId.Invalid;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are remaining paths then build a relative path
|
||||
if ( paths.length > pathIdx)
|
||||
{
|
||||
StringBuilder pathStr = new StringBuilder();
|
||||
|
||||
for ( int i = pathIdx; i < paths.length; i++)
|
||||
{
|
||||
pathStr.append( FileName.DOS_SEPERATOR);
|
||||
pathStr.append( paths[i]);
|
||||
}
|
||||
|
||||
m_path = pathStr.toString();
|
||||
|
||||
// ALF-1719: make "www" and "avm_webapps" read only by setting their level to
|
||||
// StoreRootPath (which is checked in AVMDiskDriver.checkPathAccess).
|
||||
String lastPath = paths[paths.length-1].toLowerCase();
|
||||
if(lastPath.equals("www") || lastPath.equals("avm_webapps"))
|
||||
{
|
||||
// Set the level to indicate a store root path i.e. "www",
|
||||
// "avm_webapps"
|
||||
m_levelId = LevelId.StoreRootPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the level to indicate a store relative path
|
||||
m_levelId = LevelId.StorePath;
|
||||
}
|
||||
}
|
||||
|
||||
// Build the AVM path, in <store>:/<path> format
|
||||
|
||||
if ( m_path != null)
|
||||
{
|
||||
StringBuilder pathStr = new StringBuilder();
|
||||
|
||||
pathStr.append( m_storeName);
|
||||
pathStr.append( ":");
|
||||
pathStr.append( m_path.replace( FileName.DOS_SEPERATOR, AVM_SEPERATOR));
|
||||
|
||||
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_levelId = LevelId.Invalid;
|
||||
|
||||
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();
|
||||
|
||||
// Indicate that the path is to a store relative path
|
||||
|
||||
String lowerPath = path.toLowerCase();
|
||||
String[] paths = FileName.splitAllPaths(lowerPath);
|
||||
if(paths[paths.length - 1].equals("www") || paths[paths.length - 1].equals("avm_webapps"))
|
||||
{
|
||||
// Set the level to indicate a store root path i.e. "www",
|
||||
// "avm_webapps"
|
||||
m_levelId = LevelId.StoreRootPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_levelId = LevelId.StorePath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a file id for the path
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int generateFileId()
|
||||
{
|
||||
// Check if the path is a store path or pseudo path
|
||||
|
||||
int fid = -1;
|
||||
|
||||
if ( isLevel() == LevelId.StorePath || isLevel() == LevelId.StoreRootPath)
|
||||
{
|
||||
// Use the share relative path to generate the file id
|
||||
|
||||
fid = getRelativePath().hashCode();
|
||||
}
|
||||
else if ( isPseudoPath())
|
||||
{
|
||||
// Create a relative path to the pseudo folder
|
||||
|
||||
StringBuilder relStr = new StringBuilder();
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
|
||||
switch( isLevel())
|
||||
{
|
||||
case StoreRoot:
|
||||
relStr.append( getStoreName());
|
||||
break;
|
||||
case Head:
|
||||
relStr.append( getStoreName());
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.VersionNameHead);
|
||||
break;
|
||||
case HeadData:
|
||||
relStr.append( getStoreName());
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.VersionNameHead);
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.DataFolder);
|
||||
break;
|
||||
case HeadMetaData:
|
||||
relStr.append( getStoreName());
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.VersionNameHead);
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.MetaDataFolder);
|
||||
break;
|
||||
case VersionRoot:
|
||||
relStr.append( getStoreName());
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.VersionsFolder);
|
||||
break;
|
||||
case Version:
|
||||
relStr.append( getStoreName());
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.VersionsFolder);
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.VersionFolderPrefix);
|
||||
relStr.append( getVersion());
|
||||
break;
|
||||
case VersionData:
|
||||
relStr.append( getStoreName());
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.VersionsFolder);
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.VersionFolderPrefix);
|
||||
relStr.append( getVersion());
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.DataFolder);
|
||||
break;
|
||||
case VersionMetaData:
|
||||
relStr.append( getStoreName());
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.VersionsFolder);
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.VersionFolderPrefix);
|
||||
relStr.append( getVersion());
|
||||
relStr.append( FileName.DOS_SEPERATOR);
|
||||
relStr.append( AVMPath.MetaDataFolder);
|
||||
break;
|
||||
}
|
||||
|
||||
// Generate the file id using the pseudo folder relative path
|
||||
|
||||
fid = relStr.toString().hashCode();
|
||||
}
|
||||
|
||||
// Return the file id
|
||||
|
||||
return fid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path access, true for read-only access
|
||||
*
|
||||
* @param access boolean
|
||||
*/
|
||||
public final void setReadOnlyAccess( boolean readOnly)
|
||||
{
|
||||
m_readOnly = readOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the AVM path details as a string
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder str = new StringBuilder();
|
||||
|
||||
switch ( m_levelId)
|
||||
{
|
||||
case Invalid:
|
||||
str.append("[Invalid");
|
||||
break;
|
||||
case Root:
|
||||
str.append("[Root");
|
||||
break;
|
||||
case StoreRoot:
|
||||
str.append("[StoresRoot");
|
||||
break;
|
||||
case Head:
|
||||
str.append("[");
|
||||
str.append(getStoreName());
|
||||
str.append(":HEAD");
|
||||
break;
|
||||
case HeadData:
|
||||
str.append("[");
|
||||
str.append(getStoreName());
|
||||
str.append(":HEAD\\");
|
||||
str.append( DataFolder);
|
||||
break;
|
||||
case HeadMetaData:
|
||||
str.append("[");
|
||||
str.append(getStoreName());
|
||||
str.append(":HEAD\\");
|
||||
str.append( MetaDataFolder);
|
||||
break;
|
||||
case VersionRoot:
|
||||
str.append("[");
|
||||
str.append(getStoreName());
|
||||
str.append(":Versions");
|
||||
break;
|
||||
case Version:
|
||||
str.append("[");
|
||||
str.append(getStoreName());
|
||||
str.append(":");
|
||||
str.append(VersionFolderPrefix);
|
||||
str.append(getVersion());
|
||||
break;
|
||||
case VersionData:
|
||||
str.append("[");
|
||||
str.append(getStoreName());
|
||||
str.append(":");
|
||||
str.append(VersionFolderPrefix);
|
||||
str.append(getVersion());
|
||||
str.append("\\");
|
||||
str.append( DataFolder);
|
||||
break;
|
||||
case VersionMetaData:
|
||||
str.append("[");
|
||||
str.append(getStoreName());
|
||||
str.append(":");
|
||||
str.append(VersionFolderPrefix);
|
||||
str.append(getVersion());
|
||||
str.append("\\");
|
||||
str.append( MetaDataFolder);
|
||||
break;
|
||||
case StoreRootPath:
|
||||
case StorePath:
|
||||
str.append("[");
|
||||
str.append(getStoreName());
|
||||
str.append(":");
|
||||
str.append(VersionFolderPrefix);
|
||||
str.append(getVersion());
|
||||
str.append(",");
|
||||
str.append(getRelativePath());
|
||||
str.append(":");
|
||||
str.append(getAVMPath());
|
||||
break;
|
||||
}
|
||||
|
||||
if ( isReadOnlyAccess())
|
||||
str.append("-ReadOnly");
|
||||
|
||||
str.append("]");
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
}
|
@@ -1,324 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
import org.alfresco.jlan.server.filesys.FileAttribute;
|
||||
import org.alfresco.jlan.server.filesys.FileInfo;
|
||||
import org.alfresco.jlan.server.filesys.FileName;
|
||||
import org.alfresco.jlan.server.filesys.SearchContext;
|
||||
import org.alfresco.jlan.util.WildCard;
|
||||
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
||||
|
||||
/**
|
||||
* AVM Filesystem Search Context Class
|
||||
*
|
||||
* <p>Contains the details of a wildcard folder search.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class AVMSearchContext extends SearchContext {
|
||||
|
||||
// File list and current index
|
||||
|
||||
private AVMNodeDescriptor[] m_fileList;
|
||||
private int m_fileIdx;
|
||||
|
||||
// File attributes
|
||||
|
||||
private int m_attrib;
|
||||
|
||||
// Optional wildcard filter
|
||||
|
||||
private WildCard m_filter;
|
||||
|
||||
// Relative path to the parent folder being searched
|
||||
|
||||
private String m_parentPath;
|
||||
|
||||
// Mark all files/folders as read-only
|
||||
|
||||
private boolean m_readOnly;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param fileList SortedMap<String, AVMNodeDescriptor>
|
||||
* @param attrib int
|
||||
* @param filter WildCard
|
||||
* @param parentPath String
|
||||
* @param readOnly boolean
|
||||
*/
|
||||
public AVMSearchContext( AVMNodeDescriptor[] fileList, int attrib, WildCard filter, String parentPath, boolean readOnly)
|
||||
{
|
||||
m_attrib = attrib;
|
||||
m_filter = filter;
|
||||
m_fileList = fileList;
|
||||
|
||||
m_parentPath = parentPath;
|
||||
if ( m_parentPath != null && m_parentPath.endsWith( FileName.DOS_SEPERATOR_STR) == false)
|
||||
m_parentPath = m_parentPath + FileName.DOS_SEPERATOR_STR;
|
||||
|
||||
m_readOnly = readOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if there are more files for the active search.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean hasMoreFiles()
|
||||
{
|
||||
return m_fileIdx < m_fileList.length ? 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.length)
|
||||
return false;
|
||||
|
||||
// Search for the next valid file
|
||||
|
||||
boolean foundMatch = false;
|
||||
AVMNodeDescriptor curFile = null;
|
||||
|
||||
while (foundMatch == false && m_fileIdx < m_fileList.length)
|
||||
{
|
||||
// Get the next file from the list
|
||||
|
||||
curFile = m_fileList[ m_fileIdx++];
|
||||
|
||||
// Check if the file name matches the search pattern
|
||||
|
||||
if ( m_filter.matchesPattern(curFile.getName()) == 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.length)
|
||||
curFile = m_fileList[ m_fileIdx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we found a match then fill in the file information
|
||||
|
||||
if ( foundMatch)
|
||||
{
|
||||
// Fill in the file information
|
||||
|
||||
info.setFileName( curFile.getName());
|
||||
|
||||
if ( curFile.isFile())
|
||||
{
|
||||
info.setFileSize( curFile.getLength());
|
||||
info.setAllocationSize((curFile.getLength() + 512L) & 0xFFFFFFFFFFFFFE00L);
|
||||
}
|
||||
else
|
||||
info.setFileSize( 0L);
|
||||
|
||||
info.setAccessDateTime( curFile.getAccessDate());
|
||||
info.setCreationDateTime( curFile.getCreateDate());
|
||||
info.setModifyDateTime( curFile.getModDate());
|
||||
|
||||
// Build the file attributes
|
||||
|
||||
int attr = 0;
|
||||
|
||||
if ( curFile.isDirectory())
|
||||
attr += FileAttribute.Directory;
|
||||
|
||||
if ( curFile.getName().startsWith( ".") ||
|
||||
curFile.getName().equalsIgnoreCase( "Desktop.ini") ||
|
||||
curFile.getName().equalsIgnoreCase( "Thumbs.db"))
|
||||
attr += FileAttribute.Hidden;
|
||||
|
||||
if ( isReadOnly())
|
||||
attr += FileAttribute.ReadOnly;
|
||||
|
||||
if ( attr == 0)
|
||||
attr = FileAttribute.NTNormal;
|
||||
|
||||
info.setFileAttributes( attr);
|
||||
|
||||
// Generate a file id for the current file
|
||||
|
||||
StringBuilder pathStr = new StringBuilder( m_parentPath);
|
||||
pathStr.append ( curFile.getName());
|
||||
|
||||
info.setFileId( pathStr.toString().hashCode());
|
||||
}
|
||||
|
||||
// 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.length) {
|
||||
|
||||
// Check if the current file name matches the search pattern
|
||||
|
||||
String fname = m_fileList[m_fileIdx++].getName();
|
||||
|
||||
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.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.length)
|
||||
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.length)
|
||||
{
|
||||
m_fileIdx = m_fileList.length - 1;
|
||||
}
|
||||
|
||||
while ( m_fileIdx > 0) {
|
||||
|
||||
// Check if the current file is the required search restart point
|
||||
|
||||
if ( m_fileList[ m_fileIdx].getName().equals( info.getFileName()))
|
||||
return true;
|
||||
else
|
||||
m_fileIdx--;
|
||||
}
|
||||
|
||||
// Failed to find the restart file
|
||||
|
||||
m_fileIdx = curFileIdx;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if all files/folders returned by the search should be marked as read-only
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean isReadOnly()
|
||||
{
|
||||
return m_readOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all files/folders returned by the search as read-only
|
||||
*
|
||||
* @param readOnly boolean
|
||||
*/
|
||||
public final void setReadOnly( boolean readOnly)
|
||||
{
|
||||
m_readOnly = readOnly;
|
||||
}
|
||||
}
|
@@ -1,393 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.springframework.extensions.config.ConfigElement;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.filesys.config.ServerConfigurationBean;
|
||||
import org.alfresco.jlan.server.SrvSession;
|
||||
import org.alfresco.jlan.server.config.InvalidConfigurationException;
|
||||
import org.alfresco.jlan.server.config.ServerConfiguration;
|
||||
import org.alfresco.jlan.server.core.InvalidDeviceInterfaceException;
|
||||
import org.alfresco.jlan.server.core.ShareMapper;
|
||||
import org.alfresco.jlan.server.core.ShareType;
|
||||
import org.alfresco.jlan.server.core.SharedDevice;
|
||||
import org.alfresco.jlan.server.core.SharedDeviceList;
|
||||
import org.alfresco.jlan.server.filesys.DiskSharedDevice;
|
||||
import org.alfresco.jlan.server.filesys.FilesystemsConfigSection;
|
||||
import org.alfresco.jlan.util.StringList;
|
||||
import org.alfresco.service.cmr.avm.AVMNotFoundException;
|
||||
import org.alfresco.service.cmr.avm.AVMService;
|
||||
import org.alfresco.service.cmr.avm.AVMWrongTypeException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* AVM Filesystem Share Mapper Class
|
||||
*
|
||||
* <p>Provides access to store versions using the share name '<storename>_<version>'.
|
||||
*
|
||||
* @author gkspencer
|
||||
*/
|
||||
public class AVMShareMapper implements ShareMapper, InitializingBean {
|
||||
|
||||
// Logging
|
||||
|
||||
private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol");
|
||||
|
||||
// Regular expression to test for AVM versioned share name
|
||||
|
||||
private static final String AVM_SHAREPATTERN = "[a-zA-Z0-9-]*_[0-9]+";
|
||||
|
||||
// Server configuration
|
||||
|
||||
private ServerConfiguration m_config;
|
||||
private FilesystemsConfigSection m_filesysConfig;
|
||||
|
||||
// List of available AVM shares
|
||||
|
||||
private StringList m_avmShareNames;
|
||||
|
||||
// Filesystem driver to be used to create home shares
|
||||
|
||||
private AVMDiskDriver m_driver;
|
||||
|
||||
// Debug enable flag
|
||||
|
||||
private boolean m_debug;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public AVMShareMapper()
|
||||
{
|
||||
}
|
||||
|
||||
public void setServerConfiguration(ServerConfiguration config)
|
||||
{
|
||||
this.m_config = config;
|
||||
}
|
||||
|
||||
public void setDebug(boolean debug)
|
||||
{
|
||||
this.m_debug = debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the share mapper
|
||||
*
|
||||
* @param config ServerConfiguration
|
||||
* @param params ConfigElement
|
||||
* @exception InvalidConfigurationException
|
||||
*/
|
||||
public void initializeMapper(ServerConfiguration config, ConfigElement params) throws InvalidConfigurationException
|
||||
{
|
||||
// Save the server configuration
|
||||
|
||||
setServerConfiguration(config);
|
||||
|
||||
// Check if debug is enabled
|
||||
|
||||
if (params != null && params.getChild("debug") != null)
|
||||
setDebug(true);
|
||||
|
||||
// Complete the initialization
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
public void afterPropertiesSet()
|
||||
{
|
||||
// Save the server configuration
|
||||
|
||||
m_filesysConfig = (FilesystemsConfigSection) m_config.getConfigSection(FilesystemsConfigSection.SectionName);
|
||||
|
||||
|
||||
// Build the list of available AVM share names
|
||||
|
||||
m_avmShareNames = new StringList();
|
||||
|
||||
SharedDeviceList shrList = m_filesysConfig.getShares();
|
||||
Enumeration<SharedDevice> shrEnum = shrList.enumerateShares();
|
||||
|
||||
while ( shrEnum.hasMoreElements())
|
||||
{
|
||||
// Get the current shared device and check if it is an AVM filesystem device
|
||||
|
||||
SharedDevice curShare = shrEnum.nextElement();
|
||||
|
||||
try
|
||||
{
|
||||
if ( curShare.getInterface() instanceof AVMDiskDriver)
|
||||
{
|
||||
// Add the shared filesystem name to the list of AVM shares
|
||||
|
||||
m_avmShareNames.addString( curShare.getName());
|
||||
|
||||
// Set the AVM filesystem driver to be used when creating dynamic shares
|
||||
|
||||
if ( m_driver == null)
|
||||
m_driver = (AVMDiskDriver) curShare.getInterface();
|
||||
}
|
||||
}
|
||||
catch ( InvalidDeviceInterfaceException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if debug output is enabled
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasDebug()
|
||||
{
|
||||
return m_debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of available shares.
|
||||
*
|
||||
* @param host String
|
||||
* @param sess SrvSession
|
||||
* @param allShares boolean
|
||||
* @return SharedDeviceList
|
||||
*/
|
||||
public SharedDeviceList getShareList(String host, SrvSession sess, boolean allShares)
|
||||
{
|
||||
// Make a copy of the global share list and add the per session dynamic shares
|
||||
|
||||
SharedDeviceList shrList = new SharedDeviceList(m_filesysConfig.getShares());
|
||||
|
||||
if ( sess != null && sess.hasDynamicShares()) {
|
||||
|
||||
// Add the per session dynamic shares
|
||||
|
||||
shrList.addShares(sess.getDynamicShareList());
|
||||
}
|
||||
|
||||
// Remove unavailable shares from the list and return the list
|
||||
|
||||
if ( allShares == false)
|
||||
shrList.removeUnavailableShares();
|
||||
return shrList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a share using the name and type for the specified client.
|
||||
*
|
||||
* @param host String
|
||||
* @param name String
|
||||
* @param typ int
|
||||
* @param sess SrvSession
|
||||
* @param create boolean
|
||||
* @return SharedDevice
|
||||
* @exception InvalidUserException
|
||||
*/
|
||||
public SharedDevice findShare(String tohost, String name, int typ, SrvSession sess, boolean create)
|
||||
throws Exception
|
||||
{
|
||||
// Find the required share by name/type. Use a case sensitive search first, if that fails use a case
|
||||
// insensitive search.
|
||||
|
||||
SharedDevice share = m_filesysConfig.getShares().findShare(name, typ, false);
|
||||
|
||||
if ( share == null)
|
||||
{
|
||||
|
||||
// Try a case insensitive search for the required share
|
||||
|
||||
share = m_filesysConfig.getShares().findShare(name, typ, true);
|
||||
}
|
||||
|
||||
// If the share was not found then check if the share is in the AVM versioned share format - '<storename>_<version>'
|
||||
|
||||
if ( share == null && ( typ == ShareType.DISK || typ == ShareType.UNKNOWN))
|
||||
{
|
||||
// Check if the share has already been created for the session
|
||||
|
||||
if ( sess.hasDynamicShares())
|
||||
{
|
||||
|
||||
// Check if the required share exists in the sessions dynamic share list
|
||||
|
||||
share = sess.getDynamicShareList().findShare(name, typ, false);
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug(" Reusing existing dynamic share for " + name);
|
||||
}
|
||||
|
||||
// Check if the share name matches the AVM versioned share name pattern
|
||||
|
||||
if ( share == null && create == true && name.matches( AVM_SHAREPATTERN))
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Map dynamic share " + name + ", type=" + ShareType.TypeAsString(typ));
|
||||
|
||||
// Split the store name and version id from the share name
|
||||
|
||||
int pos = name.indexOf( '_');
|
||||
|
||||
String storePath = name.substring(0, pos) + ":/";
|
||||
int storeVersion = -1;
|
||||
|
||||
try
|
||||
{
|
||||
String storeVer = name.substring( pos + 1);
|
||||
storeVersion = Integer.parseInt( storeVer);
|
||||
|
||||
if ( storeVersion < 0)
|
||||
storeVersion = -1;
|
||||
}
|
||||
catch ( NumberFormatException ex)
|
||||
{
|
||||
logger.error( "Invalid store version id, name=" + name);
|
||||
}
|
||||
|
||||
// Create the disk driver and context
|
||||
|
||||
if ( storePath.length() > 0 && storeVersion != -1)
|
||||
{
|
||||
// Validate the store name and version
|
||||
|
||||
AVMService avmService = m_driver.getAvmService();
|
||||
|
||||
m_driver.beginReadTransaction( sess);
|
||||
|
||||
try
|
||||
{
|
||||
// Validate the store name/version
|
||||
|
||||
avmService.lookup( storeVersion, storePath);
|
||||
|
||||
// Create a dynamic share mapped to the AVM store/version
|
||||
|
||||
AVMContext avmCtx = new AVMContext( name, storePath, storeVersion);
|
||||
|
||||
if(m_config instanceof ServerConfigurationBean)
|
||||
{
|
||||
ServerConfigurationBean config = (ServerConfigurationBean)m_config;
|
||||
|
||||
config.initialiseRuntimeContext("cifs.avm" + name, avmCtx);
|
||||
|
||||
// Enable file state caching
|
||||
// diskCtx.enableStateCache(serverConfigurationBean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("configuration error, unknown configuration bean");
|
||||
}
|
||||
|
||||
// Create a dynamic shared device for the store version
|
||||
|
||||
DiskSharedDevice diskShare = new DiskSharedDevice( name, m_driver, avmCtx, SharedDevice.Temporary);
|
||||
|
||||
// Add the new share to the sessions dynamic share list
|
||||
|
||||
sess.addDynamicShare(diskShare);
|
||||
share = diskShare;
|
||||
|
||||
// DEBUG
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug(" Mapped share " + name + " - " + diskShare);
|
||||
}
|
||||
catch ( AVMNotFoundException ex)
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug( "Failed to map share to " + name + ", not such store/version");
|
||||
}
|
||||
catch ( AVMWrongTypeException ex)
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug( "Failed to map share to " + name + ", wrong type");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the share is available
|
||||
|
||||
if ( share != null && share.getContext() != null && share.getContext().isAvailable() == false)
|
||||
share = null;
|
||||
|
||||
// Return the shared device, or null if no matching device was found
|
||||
|
||||
return share;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete temporary shares for the specified session
|
||||
*
|
||||
* @param sess SrvSession
|
||||
*/
|
||||
public void deleteShares(SrvSession sess)
|
||||
{
|
||||
|
||||
// Check if the session has any dynamic shares
|
||||
|
||||
if ( sess.hasDynamicShares() == false)
|
||||
return;
|
||||
|
||||
// Delete the dynamic shares
|
||||
|
||||
SharedDeviceList shares = sess.getDynamicShareList();
|
||||
Enumeration<SharedDevice> enm = shares.enumerateShares();
|
||||
|
||||
while ( enm.hasMoreElements()) {
|
||||
|
||||
// Get the current share from the list
|
||||
|
||||
SharedDevice shr = (SharedDevice) enm.nextElement();
|
||||
|
||||
// Close the shared device
|
||||
|
||||
shr.getContext().CloseContext();
|
||||
|
||||
// DEBUG
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Deleted dynamic share " + shr);
|
||||
}
|
||||
|
||||
// Clear the dynamic share list
|
||||
|
||||
shares.removeAllShares();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the share mapper, release any resources.
|
||||
*/
|
||||
public void closeMapper()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
import org.alfresco.jlan.server.filesys.FileAttribute;
|
||||
import org.alfresco.jlan.server.filesys.FileInfo;
|
||||
import org.alfresco.jlan.server.filesys.SearchContext;
|
||||
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
||||
|
||||
/**
|
||||
* AVM Filesystem Single File Search Context Class
|
||||
*
|
||||
* <p>Contains the details of a non-wildcard file/folder search, where there is only one result to return.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class AVMSingleFileSearchContext extends SearchContext {
|
||||
|
||||
// Details of the single file/folder
|
||||
|
||||
private AVMNodeDescriptor m_fileDetails;
|
||||
|
||||
// Flag to indicate file details have been returned
|
||||
|
||||
private boolean m_endOfSearch;
|
||||
|
||||
// Relative path to the file/folder
|
||||
|
||||
private String m_relativePath;
|
||||
|
||||
// Mark thel file/folder as read-only
|
||||
|
||||
private boolean m_readOnly;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param fileDetails AVMNodeDescriptor
|
||||
* @param relPath String
|
||||
* @param readOnly boolean
|
||||
*/
|
||||
public AVMSingleFileSearchContext( AVMNodeDescriptor fileDetails, String relPath, boolean readOnly)
|
||||
{
|
||||
m_fileDetails = fileDetails;
|
||||
m_relativePath = relPath;
|
||||
|
||||
m_readOnly = readOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if there are more files for the active search.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean hasMoreFiles()
|
||||
{
|
||||
return m_endOfSearch == false ? 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 the file details have been returned
|
||||
|
||||
if ( m_endOfSearch == true)
|
||||
return false;
|
||||
|
||||
// Fill in the file information details
|
||||
|
||||
info.setFileName( m_fileDetails.getName());
|
||||
|
||||
if ( m_fileDetails.isFile())
|
||||
{
|
||||
info.setFileSize( m_fileDetails.getLength());
|
||||
info.setAllocationSize((m_fileDetails.getLength() + 512L) & 0xFFFFFFFFFFFFFE00L);
|
||||
}
|
||||
else
|
||||
info.setFileSize( 0L);
|
||||
|
||||
info.setAccessDateTime( m_fileDetails.getAccessDate());
|
||||
info.setCreationDateTime( m_fileDetails.getCreateDate());
|
||||
info.setModifyDateTime( m_fileDetails.getModDate());
|
||||
|
||||
// Build the file attributes
|
||||
|
||||
int attr = 0;
|
||||
|
||||
if ( m_fileDetails.isDirectory())
|
||||
attr += FileAttribute.Directory;
|
||||
|
||||
if ( m_fileDetails.getName().startsWith( ".") ||
|
||||
m_fileDetails.getName().equalsIgnoreCase( "Desktop.ini") ||
|
||||
m_fileDetails.getName().equalsIgnoreCase( "Thumbs.db"))
|
||||
attr += FileAttribute.Hidden;
|
||||
|
||||
if ( m_readOnly == true)
|
||||
attr += FileAttribute.ReadOnly;
|
||||
|
||||
info.setFileAttributes( attr);
|
||||
info.setFileId( m_relativePath.hashCode());
|
||||
|
||||
// Set the end of search flag, indicate that the file informatin is valid
|
||||
|
||||
m_endOfSearch = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 the file details have been returned
|
||||
|
||||
if ( m_endOfSearch == true)
|
||||
return null;
|
||||
|
||||
// Return the file/folder name, set the end of search flag
|
||||
|
||||
m_endOfSearch = true;
|
||||
return m_fileDetails.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the total number of file entries for this search if known, else return -1
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int numberOfEntries()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the resume id for the current file/directory in the search.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getResumeId()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
// Validate the resume id and clear the end of search flag
|
||||
|
||||
if ( resumeId == 1)
|
||||
m_endOfSearch = false;
|
||||
else
|
||||
return false;
|
||||
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)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
import org.alfresco.jlan.server.filesys.FileAttribute;
|
||||
import org.alfresco.jlan.server.filesys.FileInfo;
|
||||
import org.alfresco.jlan.server.filesys.FileName;
|
||||
import org.alfresco.jlan.server.filesys.NetworkFile;
|
||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
|
||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFolderNetworkFile;
|
||||
|
||||
|
||||
/**
|
||||
* Dummy Folder Pseudo File Class
|
||||
*
|
||||
* <p>Represents a dummy folder within the virtualization filesystem view.
|
||||
*
|
||||
* @author gkspencer
|
||||
*/
|
||||
public class DummyFolderPseudoFile extends PseudoFile {
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param fname String
|
||||
* @param relPath String
|
||||
*/
|
||||
public DummyFolderPseudoFile( String fname, String relPath)
|
||||
{
|
||||
super( fname, FileAttribute.Directory + FileAttribute.ReadOnly);
|
||||
|
||||
// Create static file information from the folder details
|
||||
|
||||
FileInfo fInfo = new FileInfo( fname, 0L, FileAttribute.Directory + FileAttribute.ReadOnly);
|
||||
fInfo.setCreationDateTime( System.currentTimeMillis());
|
||||
|
||||
fInfo.setPath( relPath);
|
||||
fInfo.setFileId( relPath.hashCode());
|
||||
|
||||
long timeNow = System.currentTimeMillis();
|
||||
fInfo.setCreationDateTime( timeNow);
|
||||
fInfo.setModifyDateTime( timeNow);
|
||||
fInfo.setAccessDateTime( timeNow);
|
||||
fInfo.setChangeDateTime( timeNow);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
@@ -1,296 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
import org.alfresco.jlan.server.filesys.FileAttribute;
|
||||
import org.alfresco.jlan.server.filesys.FileInfo;
|
||||
import org.alfresco.jlan.server.filesys.SearchContext;
|
||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
|
||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileList;
|
||||
import org.alfresco.jlan.util.WildCard;
|
||||
|
||||
|
||||
/**
|
||||
* Pseudo File List Search Context Class
|
||||
*
|
||||
* <p>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;
|
||||
|
||||
// Mark all files/folders as read-only
|
||||
|
||||
private boolean m_readOnly;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param fileList PseudoFileList
|
||||
* @param attrib int
|
||||
* @param filter WildCard
|
||||
* @param readOnly boolean
|
||||
*/
|
||||
public PseudoFileListSearchContext( PseudoFileList fileList, int attrib, WildCard filter, boolean readOnly)
|
||||
{
|
||||
m_attrib = attrib;
|
||||
m_filter = filter;
|
||||
m_fileList = fileList;
|
||||
m_readOnly = readOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
// Check if the file/folder should be marked as read-only
|
||||
|
||||
if ( m_readOnly && pfInfo.isReadOnly() == false)
|
||||
attr += FileAttribute.ReadOnly;
|
||||
|
||||
info.setFileAttributes( attr);
|
||||
info.setFileId( pfInfo.getFileId());
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
import org.alfresco.jlan.server.filesys.FileAttribute;
|
||||
import org.alfresco.jlan.server.filesys.FileInfo;
|
||||
import org.alfresco.jlan.server.filesys.FileName;
|
||||
import org.alfresco.jlan.server.filesys.NetworkFile;
|
||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
|
||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFolderNetworkFile;
|
||||
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
|
||||
|
||||
/**
|
||||
* Store Pseudo File Class
|
||||
*
|
||||
* <p>Represents an AVM store as a folder.
|
||||
*
|
||||
* @author gkspencer
|
||||
*/
|
||||
public class StorePseudoFile extends PseudoFile {
|
||||
|
||||
// Store type
|
||||
|
||||
private int m_storeType = StoreType.Normal;
|
||||
|
||||
// Web project this sandbox links to, or null if this store is not linked
|
||||
|
||||
private String m_webProject;
|
||||
|
||||
// User name if this is an author sandbox for a web project
|
||||
|
||||
private String m_userName;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param storeDesc AVMStoreDescriptor
|
||||
* @param relPath String
|
||||
* @param storeType int
|
||||
*/
|
||||
public StorePseudoFile( AVMStoreDescriptor storeDesc, String relPath, int storeType)
|
||||
{
|
||||
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());
|
||||
fInfo.setModifyDateTime( storeDesc.getCreateDate());
|
||||
fInfo.setAccessDateTime( storeDesc.getCreateDate());
|
||||
fInfo.setChangeDateTime( storeDesc.getCreateDate());
|
||||
|
||||
fInfo.setPath( relPath);
|
||||
fInfo.setFileId( relPath.hashCode());
|
||||
|
||||
setFileInfo( fInfo);
|
||||
|
||||
setStoreType( storeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param storeName String
|
||||
* @param relPath String
|
||||
*/
|
||||
public StorePseudoFile( String storeName, String relPath)
|
||||
{
|
||||
super( storeName, FileAttribute.Directory + FileAttribute.ReadOnly);
|
||||
|
||||
// Create static file information from the store details
|
||||
|
||||
FileInfo fInfo = new FileInfo( storeName, 0L, FileAttribute.Directory + FileAttribute.ReadOnly);
|
||||
|
||||
long timeNow = System.currentTimeMillis();
|
||||
fInfo.setCreationDateTime( timeNow);
|
||||
fInfo.setModifyDateTime( timeNow);
|
||||
fInfo.setAccessDateTime( timeNow);
|
||||
fInfo.setChangeDateTime( timeNow);
|
||||
|
||||
fInfo.setPath( relPath);
|
||||
fInfo.setFileId( relPath.hashCode());
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the store type
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int isStoreType()
|
||||
{
|
||||
return m_storeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this store is linked to a web project
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasWebProject()
|
||||
{
|
||||
return m_webProject != null ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the web project that this store links to, or null if not linked
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public final String getWebProject()
|
||||
{
|
||||
return m_webProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the web project that this store is linked to
|
||||
*
|
||||
* @param webProject String
|
||||
*/
|
||||
public final void setWebProject(String webProject)
|
||||
{
|
||||
m_webProject = webProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this store is an author sandbox
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasUserName()
|
||||
{
|
||||
return m_userName != null ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the owner of this sandbox
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public final String getUserName()
|
||||
{
|
||||
return m_userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the owner of this sandbox
|
||||
*
|
||||
* @param userName String
|
||||
*/
|
||||
public final void setUserName(String userName)
|
||||
{
|
||||
m_userName = userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the store type
|
||||
*
|
||||
* @param storeType int
|
||||
*/
|
||||
public final void setStoreType(int storeType)
|
||||
{
|
||||
m_storeType = storeType;
|
||||
}
|
||||
}
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
/**
|
||||
* Store Types Class
|
||||
*
|
||||
* @author gkspencer
|
||||
*/
|
||||
public class StoreType {
|
||||
|
||||
// Store types
|
||||
|
||||
public static final int Normal = 0;
|
||||
|
||||
// Site data store types
|
||||
|
||||
public static final int SiteStore = 1;
|
||||
|
||||
// Web project store types
|
||||
|
||||
public static final int WebAuthorMain = 2;
|
||||
public static final int WebAuthorPreview = 3;
|
||||
public static final int WebStagingPreview = 4;
|
||||
public static final int WebStagingMain = 5;
|
||||
|
||||
// Store type strings
|
||||
|
||||
private static final String[] _types = { "Normal", "SiteStore", "AuthorMain", "AuthorPreview", "StagingPreview", "StagingMain" };
|
||||
|
||||
/**
|
||||
* Return a store type as a string
|
||||
*
|
||||
* @param typ int
|
||||
* @return String
|
||||
*/
|
||||
public final static String asString( int typ)
|
||||
{
|
||||
if ( typ < 0 || typ > _types.length)
|
||||
return "Invalid";
|
||||
return _types[ typ];
|
||||
}
|
||||
}
|
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
import org.alfresco.jlan.server.filesys.FileAttribute;
|
||||
import org.alfresco.jlan.server.filesys.FileInfo;
|
||||
import org.alfresco.jlan.server.filesys.FileName;
|
||||
import org.alfresco.jlan.server.filesys.NetworkFile;
|
||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
|
||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFolderNetworkFile;
|
||||
import org.alfresco.service.cmr.avm.VersionDescriptor;
|
||||
|
||||
/**
|
||||
* Version Pseudo File Class
|
||||
*
|
||||
* <p>Represents an AVM store version as a folder.
|
||||
*
|
||||
* @author gkspencer
|
||||
*/
|
||||
public class VersionPseudoFile extends PseudoFile {
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param name String
|
||||
* @param relPath String
|
||||
*/
|
||||
public VersionPseudoFile( String name, String relPath)
|
||||
{
|
||||
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.setPath( relPath);
|
||||
fInfo.setFileId( relPath.hashCode());
|
||||
|
||||
long timeNow = System.currentTimeMillis();
|
||||
fInfo.setCreationDateTime( timeNow);
|
||||
fInfo.setModifyDateTime( timeNow);
|
||||
fInfo.setAccessDateTime( timeNow);
|
||||
fInfo.setChangeDateTime( timeNow);
|
||||
|
||||
setFileInfo( fInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param name String
|
||||
* @param verDesc VersionDescriptor
|
||||
* @param relPath String
|
||||
*/
|
||||
public VersionPseudoFile( String name, VersionDescriptor verDesc, String relPath)
|
||||
{
|
||||
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());
|
||||
|
||||
fInfo.setPath( relPath);
|
||||
fInfo.setFileId( relPath.hashCode());
|
||||
|
||||
long timeNow = System.currentTimeMillis();
|
||||
fInfo.setCreationDateTime( timeNow);
|
||||
fInfo.setModifyDateTime( timeNow);
|
||||
fInfo.setAccessDateTime( timeNow);
|
||||
fInfo.setChangeDateTime( timeNow);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.alfresco.filesys.avm;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.alfresco.jlan.server.filesys.FileAttribute;
|
||||
import org.alfresco.jlan.server.filesys.FileInfo;
|
||||
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* Web Project Store Pseudo File Class
|
||||
*
|
||||
* <p>Represents an AVM store as a folder.
|
||||
*
|
||||
* @author gkspencer
|
||||
*/
|
||||
public class WebProjectStorePseudoFile extends StorePseudoFile {
|
||||
|
||||
// Store/web project user access roles
|
||||
|
||||
public static final int RoleNone = 0;
|
||||
public static final int RolePublisher = 1;
|
||||
public static final int RoleContentManager = 2;
|
||||
|
||||
// Node ref for this store
|
||||
|
||||
private NodeRef m_noderef;
|
||||
|
||||
// List of users that are content managers/publishers for this web project store
|
||||
|
||||
private Hashtable<String, Integer> m_users;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param storeDesc AVMStoreDescriptor
|
||||
* @param relPath String
|
||||
* @param nodeRef NodeRef
|
||||
*/
|
||||
public WebProjectStorePseudoFile( AVMStoreDescriptor storeDesc, String relPath, NodeRef nodeRef)
|
||||
{
|
||||
super( storeDesc, relPath, StoreType.WebStagingMain);
|
||||
|
||||
// Create static file information from the store details
|
||||
|
||||
FileInfo fInfo = new FileInfo( storeDesc.getName(), 0L, FileAttribute.Directory + FileAttribute.ReadOnly);
|
||||
|
||||
fInfo.setCreationDateTime( storeDesc.getCreateDate());
|
||||
fInfo.setModifyDateTime( storeDesc.getCreateDate());
|
||||
fInfo.setAccessDateTime( storeDesc.getCreateDate());
|
||||
fInfo.setChangeDateTime( storeDesc.getCreateDate());
|
||||
|
||||
fInfo.setPath( relPath);
|
||||
fInfo.setFileId( relPath.hashCode());
|
||||
|
||||
setFileInfo( fInfo);
|
||||
|
||||
// Set the associated node ref for the web project
|
||||
|
||||
m_noderef = nodeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param storeName String
|
||||
* @param relPath String
|
||||
* @param nodeRef NodeRef
|
||||
*/
|
||||
public WebProjectStorePseudoFile( String storeName, String relPath, NodeRef nodeRef)
|
||||
{
|
||||
super( storeName, relPath);
|
||||
|
||||
// Create static file information from the store details
|
||||
|
||||
FileInfo fInfo = new FileInfo( storeName, 0L, FileAttribute.Directory + FileAttribute.ReadOnly);
|
||||
|
||||
long timeNow = System.currentTimeMillis();
|
||||
fInfo.setCreationDateTime( timeNow);
|
||||
fInfo.setModifyDateTime( timeNow);
|
||||
fInfo.setAccessDateTime( timeNow);
|
||||
fInfo.setChangeDateTime( timeNow);
|
||||
|
||||
fInfo.setPath( relPath);
|
||||
fInfo.setFileId( relPath.hashCode());
|
||||
|
||||
setFileInfo( fInfo);
|
||||
|
||||
// Set the associated node ref for the web project
|
||||
|
||||
m_noderef = nodeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the associated node ref is valid
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasNodeRef()
|
||||
{
|
||||
return m_noderef != null ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated node ref for the store
|
||||
*
|
||||
* @return NodeRef
|
||||
*/
|
||||
public final NodeRef getNodeRef()
|
||||
{
|
||||
return m_noderef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the associated node ref for the store
|
||||
*
|
||||
* @param node NodeRef
|
||||
*/
|
||||
public final void setNodeRef(NodeRef node)
|
||||
{
|
||||
m_noderef = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the role for the specified user within this web project
|
||||
*
|
||||
* @param userName String
|
||||
* @return int
|
||||
*/
|
||||
public final int getUserRole(String userName)
|
||||
{
|
||||
if ( m_users == null)
|
||||
return RoleNone;
|
||||
|
||||
Integer role = m_users.get( userName);
|
||||
return role != null ? role.intValue() : RoleNone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a user role for this web project
|
||||
*
|
||||
* @param userName String
|
||||
* @param role int
|
||||
*/
|
||||
public final void addUserRole(String userName, int role)
|
||||
{
|
||||
if ( m_users == null)
|
||||
m_users = new Hashtable<String, Integer>();
|
||||
|
||||
m_users.put(userName, Integer.valueOf(role));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a user role for this project
|
||||
*
|
||||
* @param userName String
|
||||
*/
|
||||
public final void removeUserRole(String userName)
|
||||
{
|
||||
if ( m_users != null)
|
||||
m_users.remove(userName);
|
||||
}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
*/
|
||||
@PackageMarker
|
||||
package org.alfresco.filesys.avm;
|
||||
import org.alfresco.util.PackageMarker;
|
@@ -40,8 +40,6 @@ import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.filesys.AbstractServerConfigurationBean;
|
||||
import org.alfresco.filesys.alfresco.AlfrescoContext;
|
||||
import org.alfresco.filesys.alfresco.ExtendedDiskInterface;
|
||||
import org.alfresco.filesys.avm.AVMContext;
|
||||
import org.alfresco.filesys.avm.AVMDiskDriver;
|
||||
import org.alfresco.filesys.config.acl.AccessControlListBean;
|
||||
import org.alfresco.filesys.repo.BufferedContentDiskDriver;
|
||||
import org.alfresco.filesys.repo.ContentContext;
|
||||
@@ -107,7 +105,6 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean imp
|
||||
private FTPConfigBean ftpConfigBean;
|
||||
private NFSConfigBean nfsConfigBean;
|
||||
private List<DeviceContext> filesystemContexts;
|
||||
private boolean avmAllStores;
|
||||
private SecurityConfigBean securityConfigBean;
|
||||
private CoreServerConfigBean coreServerConfigBean;
|
||||
|
||||
@@ -153,11 +150,6 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean imp
|
||||
this.filesystemContexts = filesystemContexts;
|
||||
}
|
||||
|
||||
public void setAvmAllStores(boolean avmAllStores)
|
||||
{
|
||||
this.avmAllStores = avmAllStores;
|
||||
}
|
||||
|
||||
public void setSecurityConfigBean(SecurityConfigBean securityConfigBean)
|
||||
{
|
||||
this.securityConfigBean = securityConfigBean;
|
||||
@@ -1742,133 +1734,86 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean imp
|
||||
|
||||
DiskSharedDevice filesys = null;
|
||||
|
||||
if (filesystem instanceof AVMContext)
|
||||
// Create a new filesystem driver instance and register a context for
|
||||
// the new filesystem
|
||||
|
||||
ExtendedDiskInterface filesysDriver = getRepoDiskInterface();
|
||||
ContentContext filesysContext = (ContentContext) filesystem;
|
||||
|
||||
if(clusterConfigBean != null && clusterConfigBean.getClusterEnabled())
|
||||
{
|
||||
// Create a new filesystem driver instance and register a context for
|
||||
// the new filesystem
|
||||
|
||||
ExtendedDiskInterface filesysDriver = getAvmDiskInterface();
|
||||
DiskDeviceContext diskCtx = (DiskDeviceContext) filesystem;
|
||||
|
||||
if(clusterConfigBean != null && clusterConfigBean.getClusterEnabled())
|
||||
if(logger.isDebugEnabled())
|
||||
{
|
||||
if(logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ diskCtx.getShareName());
|
||||
}
|
||||
GenericConfigElement hazelConfig = createClusterConfig("cifs.avm."+diskCtx.getShareName());
|
||||
HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
|
||||
hazel.initializeCache(hazelConfig, this);
|
||||
diskCtx.setStateCache(hazel);
|
||||
logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ filesysContext.getShareName());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if the filesystem uses the file state cache, if so then add to the file state reaper
|
||||
StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
|
||||
standaloneCache.initializeCache( new GenericConfigElement( ""), this);
|
||||
diskCtx.setStateCache(standaloneCache);
|
||||
}
|
||||
|
||||
if ( diskCtx.hasStateCache()) {
|
||||
|
||||
// Register the state cache with the reaper thread
|
||||
|
||||
fsysConfig.addFileStateCache( filesystem.getDeviceName(), diskCtx.getStateCache());
|
||||
}
|
||||
|
||||
filesysDriver.registerContext(filesystem);
|
||||
|
||||
// Create the shared filesystem
|
||||
|
||||
filesys = new DiskSharedDevice(filesystem.getDeviceName(), filesysDriver, (AVMContext)filesystem);
|
||||
filesys.setConfiguration( this);
|
||||
// Start the filesystem
|
||||
|
||||
((AVMContext)filesystem).startFilesystem(filesys);
|
||||
GenericConfigElement hazelConfig = createClusterConfig("cifs.filesys."+filesysContext.getShareName());
|
||||
HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
|
||||
hazel.initializeCache(hazelConfig, this);
|
||||
filesysContext.setStateCache(hazel);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new filesystem driver instance and register a context for
|
||||
// the new filesystem
|
||||
|
||||
ExtendedDiskInterface filesysDriver = getRepoDiskInterface();
|
||||
ContentContext filesysContext = (ContentContext) filesystem;
|
||||
|
||||
if(clusterConfigBean != null && clusterConfigBean.getClusterEnabled())
|
||||
{
|
||||
if(logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ filesysContext.getShareName());
|
||||
}
|
||||
GenericConfigElement hazelConfig = createClusterConfig("cifs.filesys."+filesysContext.getShareName());
|
||||
HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
|
||||
hazel.initializeCache(hazelConfig, this);
|
||||
filesysContext.setStateCache(hazel);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create state cache here and inject
|
||||
StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
|
||||
standaloneCache.initializeCache( new GenericConfigElement( ""), this);
|
||||
filesysContext.setStateCache(standaloneCache);
|
||||
}
|
||||
|
||||
if ( filesysContext.hasStateCache()) {
|
||||
|
||||
// Register the state cache with the reaper thread
|
||||
// has many side effects including initialisation of the cache
|
||||
fsysConfig.addFileStateCache( filesystem.getDeviceName(), filesysContext.getStateCache());
|
||||
|
||||
// Create the lock manager for the context.
|
||||
FileStateLockManager lockMgr = new FileStateLockManager(filesysContext.getStateCache());
|
||||
filesysContext.setLockManager(lockMgr);
|
||||
filesysContext.setOpLockManager(lockMgr);
|
||||
}
|
||||
|
||||
if ((!cifsConfigBean.getServerEnabled() && !ftpConfigBean.getServerEnabled())
|
||||
&& isContentDiskDriver2(filesysDriver))
|
||||
{
|
||||
((ContentContext) filesystem).setDisableNodeMonitor(true);
|
||||
}
|
||||
|
||||
filesysDriver.registerContext(filesystem);
|
||||
|
||||
// Check if an access control list has been specified
|
||||
|
||||
AccessControlList acls = null;
|
||||
AccessControlListBean accessControls = filesysContext.getAccessControlList();
|
||||
if (accessControls != null)
|
||||
{
|
||||
// Parse the access control list
|
||||
acls = accessControls.toAccessControlList(secConfig);
|
||||
}
|
||||
else if (secConfig.hasGlobalAccessControls())
|
||||
{
|
||||
|
||||
// Use the global access control list for this disk share
|
||||
acls = secConfig.getGlobalAccessControls();
|
||||
}
|
||||
|
||||
// Create the shared filesystem
|
||||
|
||||
filesys = new DiskSharedDevice(filesystem.getDeviceName(), filesysDriver, filesysContext);
|
||||
filesys.setConfiguration( this);
|
||||
|
||||
// Add any access controls to the share
|
||||
|
||||
filesys.setAccessControlList(acls);
|
||||
|
||||
|
||||
|
||||
// Check if change notifications should be enabled
|
||||
|
||||
if ( filesysContext.getDisableChangeNotifications() == false)
|
||||
filesysContext.enableChangeHandler( true);
|
||||
|
||||
// Start the filesystem
|
||||
|
||||
filesysContext.startFilesystem(filesys);
|
||||
// Create state cache here and inject
|
||||
StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
|
||||
standaloneCache.initializeCache( new GenericConfigElement( ""), this);
|
||||
filesysContext.setStateCache(standaloneCache);
|
||||
}
|
||||
|
||||
if ( filesysContext.hasStateCache()) {
|
||||
|
||||
// Register the state cache with the reaper thread
|
||||
// has many side effects including initialisation of the cache
|
||||
fsysConfig.addFileStateCache( filesystem.getDeviceName(), filesysContext.getStateCache());
|
||||
|
||||
// Create the lock manager for the context.
|
||||
FileStateLockManager lockMgr = new FileStateLockManager(filesysContext.getStateCache());
|
||||
filesysContext.setLockManager(lockMgr);
|
||||
filesysContext.setOpLockManager(lockMgr);
|
||||
}
|
||||
|
||||
if ((!cifsConfigBean.getServerEnabled() && !ftpConfigBean.getServerEnabled())
|
||||
&& isContentDiskDriver2(filesysDriver))
|
||||
{
|
||||
((ContentContext) filesystem).setDisableNodeMonitor(true);
|
||||
}
|
||||
|
||||
filesysDriver.registerContext(filesystem);
|
||||
|
||||
// Check if an access control list has been specified
|
||||
|
||||
AccessControlList acls = null;
|
||||
AccessControlListBean accessControls = filesysContext.getAccessControlList();
|
||||
if (accessControls != null)
|
||||
{
|
||||
// Parse the access control list
|
||||
acls = accessControls.toAccessControlList(secConfig);
|
||||
}
|
||||
else if (secConfig.hasGlobalAccessControls())
|
||||
{
|
||||
|
||||
// Use the global access control list for this disk share
|
||||
acls = secConfig.getGlobalAccessControls();
|
||||
}
|
||||
|
||||
// Create the shared filesystem
|
||||
|
||||
filesys = new DiskSharedDevice(filesystem.getDeviceName(), filesysDriver, filesysContext);
|
||||
filesys.setConfiguration( this);
|
||||
|
||||
// Add any access controls to the share
|
||||
|
||||
filesys.setAccessControlList(acls);
|
||||
|
||||
|
||||
|
||||
// Check if change notifications should be enabled
|
||||
|
||||
if ( filesysContext.getDisableChangeNotifications() == false)
|
||||
filesysContext.enableChangeHandler( true);
|
||||
|
||||
// Start the filesystem
|
||||
|
||||
filesysContext.startFilesystem(filesys);
|
||||
|
||||
// Add the new filesystem
|
||||
|
||||
@@ -1891,50 +1836,6 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean imp
|
||||
logger.warn("No filesystems defined");
|
||||
}
|
||||
|
||||
// Check if shares should be added for all AVM stores
|
||||
if (this.avmAllStores && getAvmDiskInterface() != null)
|
||||
{
|
||||
// Get the list of store names
|
||||
|
||||
AVMDiskDriver avmDriver = (AVMDiskDriver) getAvmDiskInterface();
|
||||
StringList storeNames = avmDriver.getAVMStoreNames();
|
||||
|
||||
// Add shares for each of the store names, if the share name does not already exist
|
||||
|
||||
if (storeNames != null && storeNames.numberOfStrings() > 0)
|
||||
{
|
||||
// Add a share for each store
|
||||
|
||||
for (int i = 0; i < storeNames.numberOfStrings(); i++)
|
||||
{
|
||||
String storeName = storeNames.getStringAt(i);
|
||||
|
||||
// Check if a share of the same name already exists
|
||||
|
||||
if (fsysConfig.getShares().findShare(storeName, ShareType.DISK, true) == null)
|
||||
{
|
||||
// Create the new share for the store
|
||||
|
||||
AVMContext avmContext = new AVMContext(storeName, storeName + ":/", AVMContext.VERSION_HEAD);
|
||||
// avmContext.enableStateCache(this, true);
|
||||
|
||||
// Create the shared filesystem
|
||||
|
||||
DiskSharedDevice filesys = new DiskSharedDevice(storeName, avmDriver, avmContext);
|
||||
filesys.setConfiguration( this);
|
||||
|
||||
fsysConfig.addShare( filesys);
|
||||
|
||||
// DEBUG
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Added AVM share " + storeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// home folder share mapper could be declared in security config
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user