package com.arcusys.liferay.smb; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import org.alfresco.jlan.server.filesys.FileInfo; import org.alfresco.jlan.server.filesys.NetworkFile; import org.alfresco.jlan.smb.SeekType; /** * Implementation of the NetworkFile abstract class used with the DocumentLibraryDiskDriver */ public class DocumentLibraryNetworkFile extends NetworkFile { protected RandomAccessFile cachedFile; protected String cachedFileName; /** * Create a DocumentLibraryNetworkFile instance based on a FileInfo object * @param info FileInfo object to get infomation from */ public DocumentLibraryNetworkFile(FileInfo info) { super(info.getFileName()); this.setFileSize(info.getSize()); this.setAttributes(info.getFileAttributes()); } /** * Mark the file as open * @param createFlag This parameter is currently ignored * @throws IOException */ @Override public void openFile(boolean createFlag) throws IOException { setClosed(false); } /** * Read file content * Invoked by the implementation of DiskDriver * @param buf Buffer to read content to * @param len Number of bytes to read * @param pos Position in buffer to start writing to * @param fileOff Offset of file to read from * @return Number of bytes actually read. * @throws IOException */ @Override public int readFile(byte[] buf, int len, int pos, long fileOff) throws IOException { if (cachedFile == null) { File fileForRead = LiferayStorage.readFile(this.getFullName()); if (fileForRead == null) { return 0; } cachedFile = new RandomAccessFile(fileForRead, "r"); cachedFileName = fileForRead.getName(); } if (currentPosition() != fileOff) { seekFile(fileOff, SeekType.StartOfFile); } // Read from the file if (cachedFile != null) { return cachedFile.read(buf, pos, len); } else { return 0; } } /** * Get current pointer position of cached file * @return File pointer position of cached file * @throws IOException */ protected long currentPosition() throws IOException { // Check if the file is open if (cachedFile != null) { return cachedFile.getFilePointer(); } return 0; } /** * Write content to file in local disk cache * Invoked by the implementation of DiskDriver * @param buf Buffer for content * @param len Number of bytes to write * @param pos Start from this byte in buffer * @param fileOff Offset from file start to write to * @throws IOException */ @Override public void writeFile(byte[] buf, int len, int pos, long offset) throws IOException { if (cachedFile == null) { cachedFileName = LiferayStorage.getFileNameForWrite(this.getFullName()); cachedFile = new RandomAccessFile(cachedFileName, "rw"); if (cachedFile == null) { return; } } long fileLen = cachedFile.length(); if (offset > fileLen) { //Extend the file cachedFile.setLength(offset + len); } //Check for a zero length write if (len == 0) { return; } //Seek to the write position cachedFile.seek(offset); //Write to the file cachedFile.write(buf, pos, len); //Update the write count for the file incrementWriteCount(); } /** * Seek to a position in a file in local disk cache * Invoked by the implementation of DiskDriver * and by PseudoNetworkFile class (if it is used) * @param pos Position to seek to * @param typ Type of seek to do (SeekType enumeration) * @return new position * @throws IOException */ @Override public long seekFile(long pos, int typ) throws IOException { if (cachedFile == null) { throw new IOException(); //openFile(false); } // Check if the current file position is the required file position switch (typ) { case SeekType.StartOfFile: if (currentPosition() != pos) { cachedFile.seek(pos); } break; case SeekType.CurrentPos: cachedFile.seek(currentPosition() + pos); break; case SeekType.EndOfFile: { long newPos = cachedFile.length() + pos; cachedFile.seek(newPos); } break; } return currentPosition(); } /** * Flush the buffered output to the file in the local disk cache. * Invoked by the implementation of DiskDriver * @throws IOException */ @Override public void flushFile() throws IOException { if (cachedFile != null) { cachedFile.getFD().sync(); } } /** * Truncate file to a given size * The operation seems not to be utilized by clients. Stubbed. * Invoked by the implementation of DiskDriver * @param siz * @throws IOException */ @Override public void truncateFile(long siz) throws IOException { } /** * Nothing special happens yet when file is closed. This is a stub. * Invoked both by JLAN and the implementation of DiskDriver */ @Override public void closeFile() throws IOException { if (cachedFile != null) { //Close the file in local disk cache cachedFile.close(); cachedFile = null; } if (cachedFileName != null) { File file = new File(cachedFileName); //If the file was open for writing if (cachedFileName.startsWith("write")) { //Update its content in Liferay LiferayStorage.updateFile(this.getFullName(), file); } // delete file from local disk cache if (file.exists()) { System.gc(); file.delete(); } } //Mark the file as closed setClosed(true); } }