Gary Spencer a6eb590cc9 Merge 3.2 to HEAD:
15128: Merge 3.1 to 3.2:
   		15114: Added support for impersonation level sharing mode check, to fix Office2007 file open issue. ETHREEOH-2320.
	15130: Record-only
	15340: Merge 3.1 to 3.2:
   		14359: Fixed native call being used when <disableNative/> was configured. ETHREEOH-2105. (Record-only)
   		14484: Merged HEAD to v3.1: (Record-only)
       	13943 Added FTP IPv6 configuration, via the <IPv6 state="enabled|disabled"/> tag. Added the ftp.ipv6 property. MOB-714.
   		14523: Add trailing 'A' to CIFS server name, removed by recent checkin. (Record-only)
   		14561: Change the file server config bean to use the 'org.alfresco.fileserver' logging level.
   		14916: Fixes for local domain lookup when WINS is configured. ETHREEOH-2263.
   		14922: Merge HEAD to V3.1
       	14626: Fixes for the client side Windows desktop action application. part of ETHREEOH-401
   		15155: Fixes to client side desktop action exe handling of paths that are not mapped to the root of the Alfresco share. ETHREEOH-1613
	15341: Record-only
	15549: Check for null ClientInfo in the setCurrentUser() method and clear the auth context. Part of ETHREEOH-2538.
	15550: Fixed performance issue in the continue search code, add warn level output of folder search timing.
	15564: Merge 3.1 to 3.2:
   		14964: Port fix for convert content I/O exceptions to file server exceptions during write and truncate (part 2). ETWOTWO-1241
   		15233: Ignore nodes that no longer exist during the second stage of a file server folder search.
   		15234: Fixed incorrect length check when buffering MSOffice document writes.
	15565: Record-only
	15568: Fix for cut/paste file between folders on CIFS. ETHREEOH-2323 + ENH-515.
	15569: Record-only
	15644: Changed filesystem debug setting so it works with old and new config styles.
	15786: Record-only
	15787: Port of repo filesystem MS Office document locking fix. ETHREEOH-2579


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@16122 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2009-09-07 13:04:53 +00:00

554 lines
15 KiB
Java

/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.filesys.alfresco;
import java.net.InetAddress;
import java.util.Enumeration;
import java.util.List;
import java.util.StringTokenizer;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.filesys.config.GlobalDesktopActionConfigBean;
import org.alfresco.filesys.state.FileStateReaper;
import org.alfresco.filesys.state.FileStateTable;
import org.alfresco.jlan.server.filesys.DiskDeviceContext;
import org.alfresco.jlan.server.filesys.DiskInterface;
import org.alfresco.jlan.server.filesys.FileSystem;
import org.alfresco.jlan.server.filesys.SrvDiskInfo;
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileInterface;
/**
* Alfresco Filesystem Context Class
*
* <p>Contains per filesystem context.
*
* @author GKSpencer
*/
public abstract class AlfrescoContext extends DiskDeviceContext
{
// Token name to substitute current servers DNS name or TCP/IP address into the webapp URL
private static final String TokenLocalName = "${localname}";
// Debug levels
public final static int DBG_FILE = 0x00000001; // file/folder create/delete
public final static int DBG_FILEIO = 0x00000002; // file read/write/truncate
public final static int DBG_SEARCH = 0x00000004; // folder search
public final static int DBG_INFO = 0x00000008; // file/folder information
public final static int DBG_LOCK = 0x00000010; // file byte range locking
public final static int DBG_PSEUDO = 0x00000020; // pseudo files/folders
public final static int DBG_RENAME = 0x00000040; // rename file/folder
// Filesystem debug flag strings
private static final String m_filesysDebugStr[] = { "FILE", "FILEIO", "SEARCH", "INFO", "LOCK", "PSEUDO", "RENAME" };
// File state table and associated file state reaper
private FileStateTable m_stateTable;
private FileStateReaper m_stateReaper;
// URL pseudo file web path prefix (server/port/webapp) and link file name
private String m_urlPathPrefix;
private String m_urlFileName;
// Pseudo file interface
private PseudoFileInterface m_pseudoFileInterface;
// Desktop actions
private GlobalDesktopActionConfigBean m_globalDesktopActionConfig = new GlobalDesktopActionConfigBean();
private DesktopActionTable m_desktopActions;
private List<DesktopAction> m_desktopActionsToInitialize;
// I/O control handler
private IOControlHandler m_ioHandler;
// Debug flags
//
// Requires the logger to be enabled for debug output
public int m_debug;
public AlfrescoContext()
{
// Default the filesystem to look like an 80Gb sized disk with 90% free space
setDiskInformation(new SrvDiskInfo(2560000, 64, 512, 2304000));
// Set parameters
setFilesystemAttributes(FileSystem.CasePreservedNames + FileSystem.UnicodeOnDisk +
FileSystem.CaseSensitiveSearch);
}
public void setDisableChangeNotification(boolean disableChangeNotification)
{
enableChangeHandler(!disableChangeNotification);
}
/**
* Complete initialization by registering with a disk driver
*/
public void initialize(AlfrescoDiskDriver filesysDriver)
{
if (m_desktopActionsToInitialize != null)
{
for (DesktopAction desktopAction : m_desktopActionsToInitialize)
{
// Initialize the desktop action
try
{
desktopAction.initializeAction(filesysDriver, this);
}
catch (DesktopActionException ex)
{
throw new AlfrescoRuntimeException("Failed to initialize desktop action", ex);
}
addDesktopAction(desktopAction);
}
}
}
/**
* Return the filesystem type, either FileSystem.TypeFAT or FileSystem.TypeNTFS.
*
* @return String
*/
public String getFilesystemType()
{
return FileSystem.TypeNTFS;
}
/**
* Determine if the file state table is enabled
*
* @return boolean
*/
public final boolean hasStateTable()
{
return m_stateTable != null ? true : false;
}
/**
* Return the file state table
*
* @return FileStateTable
*/
public final FileStateTable getStateTable()
{
return m_stateTable;
}
/**
* Enable/disable the file state table
*
* @param ena boolean
* @param stateReaper FileStateReaper
*/
public final void enableStateTable(boolean ena, FileStateReaper stateReaper)
{
if ( ena == false)
{
// Remove the state table from the reaper
stateReaper.removeStateTable( getShareName());
m_stateTable = null;
}
else if ( m_stateTable == null)
{
// Create the file state table
m_stateTable = new FileStateTable();
// Register with the file state reaper
stateReaper.addStateTable( getShareName(), m_stateTable);
}
// Save the reaper, for deregistering when the filesystem is closed
m_stateReaper = stateReaper;
}
/**
* Determine if the pseudo file interface is enabled
*
* @return boolean
*/
public final boolean hasPseudoFileInterface()
{
return m_pseudoFileInterface != null ? true : false;
}
/**
* Return the pseudo file interface
*
* @return PseudoFileInterface
*/
public final PseudoFileInterface getPseudoFileInterface()
{
return m_pseudoFileInterface;
}
/**
* Enable the pseudo file interface for this filesystem
*/
public final void enabledPseudoFileInterface()
{
if ( m_pseudoFileInterface == null)
m_pseudoFileInterface = new PseudoFileImpl();
}
/**
* Determine if there are desktop actins configured
*
* @return boolean
*/
public final boolean hasDesktopActions()
{
return m_desktopActions != null ? true : false;
}
/**
* Return the desktop actions table
*
* @return DesktopActionTable
*/
public final DesktopActionTable getDesktopActions()
{
return m_desktopActions;
}
/**
* Return the count of desktop actions
*
* @return int
*/
public final int numberOfDesktopActions()
{
return m_desktopActions != null ? m_desktopActions.numberOfActions() : 0;
}
/**
* Add a desktop action
*
* @param action DesktopAction
* @return boolean
*/
public final boolean addDesktopAction(DesktopAction action)
{
// Check if the desktop actions table has been created
if ( m_desktopActions == null)
{
m_desktopActions = new DesktopActionTable();
// Enable pseudo files
enabledPseudoFileInterface();
}
// Add the action
return m_desktopActions.addAction(action);
}
/**
* Determine if custom I/O control handling is enabled for this filesystem
*
* @return boolean
*/
public final boolean hasIOHandler()
{
return m_ioHandler != null;
}
/**
* Return the custom I/O control handler
*
* @return IOControlHandler
*/
public final IOControlHandler getIOHandler()
{
return m_ioHandler;
}
/**
* Determine if the URL pseudo file is enabled
*
* @return boolean
*/
public final boolean hasURLFile()
{
if ( m_urlPathPrefix != null && m_urlFileName != null)
return true;
return false;
}
/**
* Return the URL pseudo file path prefix
*
* @return String
*/
public final String getURLPrefix()
{
return m_urlPathPrefix;
}
/**
* Return the URL pseudo file name
*
* @return String
*/
public final String getURLFileName()
{
return m_urlFileName;
}
/**
* Set the URL path prefix
*
* @param urlPrefix String
*/
public final void setURLPrefix(String urlPrefix)
{
m_urlPathPrefix = urlPrefix;
if ( urlPrefix != null)
{
// Make sure the web prefix has a trailing slash
if ( !urlPrefix.endsWith("/"))
urlPrefix = urlPrefix + "/";
// Check if the URL path name contains the local name token
int pos = urlPrefix.indexOf(TokenLocalName);
if (pos != -1)
{
// Get the local server name
String srvName = "localhost";
try
{
srvName = InetAddress.getLocalHost().getHostName();
}
catch ( Exception ex)
{
}
// Rebuild the host name substituting the token with the local server name
StringBuilder hostStr = new StringBuilder();
hostStr.append( urlPrefix.substring(0, pos));
hostStr.append(srvName);
pos += TokenLocalName.length();
if (pos < urlPrefix.length())
hostStr.append( urlPrefix.substring(pos));
m_urlPathPrefix = hostStr.toString();
}
enabledPseudoFileInterface();
}
}
/**
* Set the URL pseudo file name
*
* @param urlFileName String
*/
public final void setURLFileName(String urlFileName)
{
m_urlFileName = urlFileName;
// URL file name must end with .url
if (urlFileName != null)
{
if (!urlFileName.endsWith(".url"))
throw new AlfrescoRuntimeException("URL link file must end with .url, " + urlFileName);
enabledPseudoFileInterface();
}
}
/**
* Set the desktop actions
*
* @param desktopActions DesktopActionTable
* @param filesysDriver DiskInterface
*/
public final void setDesktopActions(DesktopActionTable desktopActions, DiskInterface filesysDriver)
{
// Enumerate the desktop actions and add to this filesystem
Enumeration<String> names = desktopActions.enumerateActionNames();
while ( names.hasMoreElements())
{
addDesktopAction( desktopActions.getAction(names.nextElement()));
}
// If there are desktop actions then create the custom I/O control handler
if ( numberOfDesktopActions() > 0)
{
// Create the custom I/O control handler
m_ioHandler = createIOHandler( filesysDriver);
if ( m_ioHandler != null)
m_ioHandler.initialize(( AlfrescoDiskDriver) filesysDriver, this);
}
}
/**
* Set the desktop actions
*
* @param desktopActions DesktopAction List
*/
public final void setDesktopActionList(List<DesktopAction> desktopActions)
{
m_desktopActionsToInitialize = desktopActions;
}
public void setGlobalDesktopActionConfig(GlobalDesktopActionConfigBean desktopActionConfig)
{
m_globalDesktopActionConfig = desktopActionConfig;
}
protected GlobalDesktopActionConfigBean getGlobalDesktopActionConfig()
{
return m_globalDesktopActionConfig;
}
/**
* Create the I/O control handler for this filesystem type
*
* @param filesysDriver DiskInterface
* @return IOControlHandler
*/
protected abstract IOControlHandler createIOHandler( DiskInterface filesysDriver);
/**
* Set the I/O control handler
*
* @param ioctlHandler IOControlHandler
*/
protected void setIOHandler( IOControlHandler ioctlHandler)
{
m_ioHandler = ioctlHandler;
}
/**
* Set the debug flags, also requires the logger to be enabled for debug output
*
* @param dbg int
*/
public final void setDebug(String flagsStr)
{
int filesysDbg = 0;
if (flagsStr != null)
{
// Parse the flags
StringTokenizer token = new StringTokenizer(flagsStr.toUpperCase(), ",");
while (token.hasMoreTokens())
{
// Get the current debug flag token
String dbg = token.nextToken().trim();
// Find the debug flag name
int idx = 0;
boolean match = false;
while (idx < m_filesysDebugStr.length && match == false)
{
if ( m_filesysDebugStr[idx].equalsIgnoreCase(dbg) == true)
match = true;
else
idx++;
}
if (match == false)
throw new AlfrescoRuntimeException("Invalid filesystem debug flag, " + dbg);
// Set the debug flag
filesysDbg += 1 << idx;
}
// Set the debug flags
m_debug = filesysDbg;
}
}
/**
* Check if a debug flag is enabled
*
* @param flg int
* @return boolean
*/
public final boolean hasDebug(int flg)
{
return (m_debug & flg) != 0 ? true : false;
}
/**
* Close the filesystem context
*/
public void CloseContext() {
// Deregister the file state table from the reaper
if ( m_stateTable != null)
enableStateTable( false, m_stateReaper);
// Call the base class
super.CloseContext();
}
}