package com.arcusys.liferay.smb;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.alfresco.jlan.server.SrvSession;
import org.alfresco.jlan.server.core.DeviceContext;
import org.alfresco.jlan.server.core.DeviceContextException;
import org.alfresco.jlan.server.filesys.AccessDeniedException;
import org.alfresco.jlan.server.filesys.DiskDeviceContext;
import org.alfresco.jlan.server.filesys.DiskInterface;
import org.alfresco.jlan.server.filesys.FileAttribute;
import org.alfresco.jlan.server.filesys.FileInfo;
import org.alfresco.jlan.server.filesys.FileOpenParams;
import org.alfresco.jlan.server.filesys.NetworkFile;
import org.alfresco.jlan.server.filesys.SearchContext;
import org.alfresco.jlan.server.filesys.TreeConnection;
import org.springframework.extensions.config.ConfigElement;
/**
* The implementation of DiskInterface utilizing a Liferay document library folder
* as the underlying share storage
*/
public class DocumentLibraryDiskDriver implements DiskInterface {
/**
* Liferay shared folder name
*/
private String m_liferaySharedFolder;
/**
* Get full path to file or folder in Liferay from share-relative name
* @param shareRelativePath
* @return
*/
private String getLiferayFullPath(String shareRelativePath) {
String liferayFullPath = "";
if (shareRelativePath.startsWith("\\") || shareRelativePath.equals("")) {
liferayFullPath = m_liferaySharedFolder + shareRelativePath;
} else {
liferayFullPath = shareRelativePath;
}
if (liferayFullPath.startsWith("\\")) {
liferayFullPath = liferayFullPath.substring(1);
}
return liferayFullPath;
}
/**
* Initialize a disk share. This method is called by JLAN at startup once for each share.
* @param name The name of the share
* @param args The configuration files section corresponding to a share
* @return The device context with root path in document library used as device name
* @throws DeviceContextException
*/
public DeviceContext createContext(String name, ConfigElement args) throws DeviceContextException {
//The LiferaySharedFolder share configuration parameter stores the name of the
//Liferay folder we wish to share together with all its content
//It should start with the topmost folder name, no leading backslash or point allowed
//One tailing backslash is allowed
ConfigElement path = args.getChild("LiferaySharedFolder");
m_liferaySharedFolder = path.getValue();
//Trim tailing backslash if there is one
if (m_liferaySharedFolder.endsWith("\\")) {
m_liferaySharedFolder = m_liferaySharedFolder.substring(0, m_liferaySharedFolder.length() - 1);
}
//Use Liferay shared folder name as device name
DiskDeviceContext context = new DiskDeviceContext(m_liferaySharedFolder);
//Detect the group ID to access Liferay and remember the URL, username and password
LiferayStorage.initStorage(args.getChild("LiferayURL").getValue(), args.getChild("LiferayUser").getValue(), args.getChild("LiferayUserId").getValue(), args.getChild("LiferayPassword").getValue());
return context;
}
/**
* Nothing special is done when connection opened to the device. This method is called by JLAN.
* @param sess Session details
* @param tree Tree connection
*/
public void treeOpened(SrvSession sess, TreeConnection tree) {
}
/**
* Nothing special is done when connection closed to the device. This method is called by JLAN.
* @param sess Session details
* @param tree Tree connection
*/
public void treeClosed(SrvSession sess, TreeConnection tree) {
}
/**
* Check if a file or directory exists in the Liferay-based share.
* This method is called by JLAN when the SBM client checks file existance.
* @param sess Session details
* @param tree Tree connection
* @param name Full file name starting with a backslash relative to share root
* @return FileStatus.DirectoryExists if a directory with such a name exists,
* FileStatus.FileExists if a file with such a name exists,
* or FileStatus.NotExist otherwise
*/
public int fileExists(SrvSession sess, TreeConnection tree, String name) {
return LiferayStorage.fileExists(getLiferayFullPath(name));
}
/**
* Initiate the search (prepare the file list)
* This method is called by JLAN when the SBM client initiates
* a file or directoty search or when it gets directory content.
* The SearchContext class methods will later be invoked by JLAN
* to retrieve each file record in the result set
* @param sess Session details
* @param tree Tree connection
* @param searchPath Search path starts with a backslash and may contain
* a single file/folder full name (with path) or wildcards (also with path)
* @param attrib
* @return The search context for the initiated search
* @throws FileNotFoundException
*/
public SearchContext startSearch(SrvSession sess, TreeConnection tree, String searchPath, int attrib) throws FileNotFoundException {
DocumentLibrarySearchContext searchContext = new DocumentLibrarySearchContext();
searchContext.initSearch(getLiferayFullPath(searchPath), attrib);
return searchContext;
}
/**
* Get file or directory information by name
* @param sess Session details
* @param tree Tree connection
* @param name Full path to file relative to share root, starts with a backslash
* @return FileInfo object with information regarding file or null if file was not found
* @throws IOException
*/
public FileInfo getFileInformation(SrvSession sess, TreeConnection tree, String name) throws IOException {
FileInfo fileInfo = null;
try {
if (name.equals("\\") || name.equals("")) {
fileInfo = new FileInfo();
fileInfo.setFileName(m_liferaySharedFolder);
fileInfo.setFileAttributes(FileAttribute.Directory);
} else {
fileInfo = LiferayStorage.getFileInfo(getLiferayFullPath(name));
}
return fileInfo;
} catch (Exception ex) {
return null;
}
}
/**
* The operation for checking if file is read-only cannot be applied to
* Liferay document libaries. This method always returned false.
* @param sess Session details
* @param ctx Device context
* @return True if file is readonly, false otherwise
* @throws IOException
*/
public boolean isReadOnly(SrvSession sess, DeviceContext ctx) throws IOException {
return false;
}
/**
* Create a directory in Liferay
* @param sess Session details
* @param tree Tree connection
* @param params File open parameters
* @throws IOException
*/
public void createDirectory(SrvSession sess, TreeConnection tree, FileOpenParams params) throws IOException {
LiferayStorage.createFolder(getLiferayFullPath(params.getFullPath()));
}
/**
* Create file in Liferay
* @param sess Session details
* @param tree Tree connection
* @param params File open parameters
* @return
* @throws IOException
*/
public NetworkFile createFile(SrvSession sess, TreeConnection tree, FileOpenParams params) throws IOException {
FileInfo info = LiferayStorage.createFile(getLiferayFullPath(params.getFullPath()),params.getAllocationSize());
String liferayFullPath = getLiferayFullPath(params.getPath());
if (info == null) {
throw new UnsupportedOperationException("CreateFileError");
}
NetworkFile networkFile = new DocumentLibraryNetworkFile(info);
networkFile.setFullName(liferayFullPath);
return networkFile;
}
/**
* Delete folder in Liferay
* @param sess Session details
* @param tree Tree connection
* @param dir Share-relative path to folder
* @throws IOException
*/
public void deleteDirectory(SrvSession sess, TreeConnection tree, String dir) throws IOException {
LiferayStorage.deleteFolder(getLiferayFullPath(dir));
}
/**
* Delete file in Liferay
* @param sess Session details
* @param tree Tree connection
* @param name Share-relative path to file
* @throws IOException
*/
public void deleteFile(SrvSession sess, TreeConnection tree, String name) throws IOException {
LiferayStorage.deleteFile(getLiferayFullPath(name));
}
/**
* Rename/move file in Liferay
* @param sess Session details
* @param tree Tree connection
* @param oldName Share-relative path to file
* @param newName New share-relative path
* @throws IOException
*/
public void renameFile(SrvSession sess, TreeConnection tree, String oldName, String newName) throws IOException {
if (LiferayStorage.getFileInfo(getLiferayFullPath(oldName)).isDirectory()) {
LiferayStorage.renameFolder(getLiferayFullPath(oldName), getLiferayFullPath(newName));
} else {
LiferayStorage.renameFile(getLiferayFullPath(oldName), getLiferayFullPath(newName));
}
}
/**
* The operation for setting file properties is not applicable to Liferay document libraries.
* This method does nothing
* @param sess
* @param tree
* @param name
* @param info
* @throws IOException
*/
public void setFileInformation(SrvSession sess, TreeConnection tree, String name, FileInfo info) throws IOException {
}
/**
* The operation for truncating the file to a given size is not applicable
* to Liferay document libraries and does not seem to be utilized by clients.
* This method does nothing.
* @param sess
* @param tree
* @param file
* @param siz
* @throws IOException
*/
public void truncateFile(SrvSession sess, TreeConnection tree, NetworkFile file, long siz) throws IOException {
}
/**
* Open a file (get the NetworkFile instance for a file)
* @param sess Session details
* @param tree Tree connection
* @param params File open parameters
* @return The NetworkFile class descibing the file being opened
* @throws IOException
*/
public NetworkFile openFile(SrvSession sess, TreeConnection tree, FileOpenParams params) throws IOException {
String liferayFullPath = getLiferayFullPath(params.getPath());
//Check if a file exists
FileInfo info = getFileInformation(sess, tree, params.getPath());
if (info != null && info.getFileName() != null) {
NetworkFile networkFile = new DocumentLibraryNetworkFile(info);
networkFile.setFullName(liferayFullPath);
return networkFile;
} else {
throw new UnsupportedOperationException("Error: info is null-" + (info == null) + "params.GetPath:" + params.getPath());
}
}
/**
* Close the previously opened file. This method actually deletes a file if needed
* (hasDeleteOnClose() return true on the param NetworkFile)
* @param sess Session details
* @param tree Tree connection
* @param param The network file to close
* @throws IOException
*/
public void closeFile(SrvSession sess, TreeConnection tree, NetworkFile param) throws IOException {
if (param.hasDeleteOnClose()) {
if (param.isDirectory()) {
LiferayStorage.deleteFolder(param.getFullName());
} else {
LiferayStorage.deleteFile(param.getFullName());
}
}
param.closeFile();
}
/**
* The operation for positioning in a file is not utilized by clients.
* This method does nothing and returns 0.
* @param sess
* @param tree
* @param file
* @param pos
* @param typ
* @return
* @throws IOException
*/
public long seekFile(SrvSession sess, TreeConnection tree, NetworkFile file, long pos, int typ) throws IOException {
return 0;
}
/**
* Read Liferay file data.
* Reading directories leads to an AccessDeniedException
* @param sess Session details
* @param tree Tree connection
* @param file NetworkFile object desribing the file to read
* @param buf Buffer to receive file data
* @param bufPos Position in buffer where to start putting data
* @param siz Number of bytes to read
* @param filePos Position in file where to start reading
* @return Number of bytes actually read
* @throws IOException
*/
public int readFile(SrvSession sess, TreeConnection tree, NetworkFile file, byte[] buf, int bufPos, int siz, long filePos) throws IOException {
if (file.isDirectory()) {
throw new AccessDeniedException();
}
int rdlen = file.readFile(buf, siz, bufPos, filePos);
// If we have reached end of file return a zero length read
if (rdlen == -1) {
rdlen = 0;
}
// Return the actual read length
return rdlen;
}
/**
* Write data to a Liferay file. This method actually writes data to a temporary
* file on local disk. Data gets to Liferay on file close.
* @param sess Session details
* @param tree Tree connection
* @param file NetworkFile object describing the file to write to
* @param buf Buffer with data to write
* @param bufoff Position in buffer where to start reading from
* @param siz Number of bytes to write
* @param fileoff Position in file where to start writing to
* @return Number of bytes actually written
* @throws IOException
*/
public int writeFile(SrvSession sess, TreeConnection tree, NetworkFile file, byte[] buf, int bufoff, int siz, long fileoff) throws IOException {
file.writeFile(buf, siz, bufoff, fileoff);
return siz;
}
/**
* The operation for flushing the buffered output to the file is not applicable.
* This method does nothing.
* @param sess Session details
* @param tree Tree connection
* @param file The NetworkFile object describing the file to flush
* @throws IOException
*/
public void flushFile(SrvSession sess, TreeConnection tree, NetworkFile file) throws IOException {
}
}