KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > filesys > smb > server > repo > FileState


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.filesys.smb.server.repo;
18
19 import org.alfresco.filesys.locking.FileLock;
20 import org.alfresco.filesys.locking.FileLockList;
21 import org.alfresco.filesys.locking.LockConflictException;
22 import org.alfresco.filesys.locking.NotLockedException;
23 import org.alfresco.filesys.server.filesys.FileName;
24 import org.alfresco.filesys.server.filesys.FileOpenParams;
25 import org.alfresco.filesys.server.filesys.FileStatus;
26 import org.alfresco.filesys.smb.SharingMode;
27 import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFile;
28 import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFileList;
29 import org.alfresco.service.cmr.repository.NodeRef;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32
33 /**
34  * File State Class
35  *
36  * <p>Keeps track of file state across all sessions on the server, to keep track of file sharing modes,
37  * file locks and also for synchronizing access to files/folders.
38  *
39  * @author gkspencer
40  */

41 public class FileState
42 {
43     private static final Log logger = LogFactory.getLog(FileState.class);
44
45     // File state constants
46

47     public final static long NoTimeout = -1L;
48     public final static long DefTimeout = 2 * 60000L; // 2 minutes
49
public final static long RenameTimeout = 1 * 60000L; // 1 minute
50

51     // File status
52

53     public enum FileStateStatus { NotExist, FileExists, FolderExists, Renamed };
54     
55     // File name/path
56

57     private String JavaDoc m_path;
58
59     // File state timeout, -1 indicates no timeout
60

61     private long m_tmo;
62
63     // File status, indicates if the file/folder exists and if it is a file or folder.
64

65     private FileStateStatus m_fileStatus = FileStateStatus.NotExist;
66
67     // Open file count
68

69     private int m_openCount;
70
71     // Sharing mode
72

73     private int m_sharedAccess = SharingMode.READWRITE;
74
75     // File lock list, allocated once there are active locks on this file
76

77     private FileLockList m_lockList;
78     
79     // Node for this file
80

81     private NodeRef m_nodeRef;
82     
83     // Link to the new file state when a file is renamed
84

85     private FileState m_newNameState;
86     
87     // Pseudo file list
88

89     private PseudoFileList m_pseudoFiles;
90     
91     /**
92      * Class constructor
93      *
94      * @param fname String
95      * @param isdir boolean
96      */

97     public FileState(String JavaDoc fname, boolean isdir)
98     {
99
100         // Normalize the file path
101

102         setPath(fname);
103         setExpiryTime(System.currentTimeMillis() + DefTimeout);
104         
105         // Set the file/folder status
106

107         setFileStatus( isdir ? FileStateStatus.FolderExists : FileStateStatus.FileExists);
108     }
109
110     /**
111      * Return the file name/path
112      *
113      * @return String
114      */

115     public final String JavaDoc getPath()
116     {
117         return m_path;
118     }
119
120     /**
121      * Return the file status
122      *
123      * @return FileStateStatus
124      */

125     public final FileStateStatus getFileStatus()
126     {
127         return m_fileStatus;
128     }
129
130     /**
131      * Determine if the file/folder exists
132      *
133      * @return boolen
134      */

135     public final boolean exists()
136     {
137         if ( m_fileStatus == FileStateStatus.FileExists ||
138                 m_fileStatus == FileStateStatus.FolderExists)
139             return true;
140         return false;
141     }
142
143     /**
144      * Return the directory state
145      *
146      * @return boolean
147      */

148     public final boolean isDirectory()
149     {
150         return m_fileStatus == FileStateStatus.FolderExists ? true : false;
151     }
152
153     /**
154      * Determine if the associated node has been set
155      *
156      * @return boolean
157      */

158     public final boolean hasNodeRef()
159     {
160         return m_nodeRef != null ? true : false;
161     }
162     
163     /**
164      * Return the associated node
165      *
166      * @return NodeRef
167      */

168     public final NodeRef getNodeRef()
169     {
170         return m_nodeRef;
171     }
172     
173     /**
174      * Return the file open count
175      *
176      * @return int
177      */

178     public final int getOpenCount()
179     {
180         return m_openCount;
181     }
182
183     /**
184      * Return the shared access mode
185      *
186      * @return int
187      */

188     public final int getSharedAccess()
189     {
190         return m_sharedAccess;
191     }
192
193     /**
194      * Check if there are active locks on this file
195      *
196      * @return boolean
197      */

198     public final boolean hasActiveLocks()
199     {
200         if (m_lockList != null && m_lockList.numberOfLocks() > 0)
201             return true;
202         return false;
203     }
204
205     /**
206      * Check if this file state does not expire
207      *
208      * @return boolean
209      */

210     public final boolean hasNoTimeout()
211     {
212         return m_tmo == NoTimeout ? true : false;
213     }
214
215     /**
216      * Check if the file can be opened depending on any current file opens and the sharing mode of
217      * the first file open
218      *
219      * @param params FileOpenParams
220      * @return boolean
221      */

222     public final boolean allowsOpen(FileOpenParams params)
223     {
224
225         // If the file is not currently open then allow the file open
226

227         if (getOpenCount() == 0)
228             return true;
229
230         // Check the shared access mode
231

232         if (getSharedAccess() == SharingMode.READWRITE && params.getSharedAccess() == SharingMode.READWRITE)
233             return true;
234         else if ((getSharedAccess() & SharingMode.READ) != 0 && params.isReadOnlyAccess())
235             return true;
236         else if ((getSharedAccess() & SharingMode.WRITE) != 0 && params.isWriteOnlyAccess())
237             return true;
238
239         // Sharing violation, do not allow the file open
240

241         return false;
242     }
243
244     /**
245      * Increment the file open count
246      *
247      * @return int
248      */

249     public final synchronized int incrementOpenCount()
250     {
251         return m_openCount++;
252     }
253
254     /**
255      * Decrement the file open count
256      *
257      * @return int
258      */

259     public final synchronized int decrementOpenCount()
260     {
261
262         // Debug
263

264         if (m_openCount <= 0)
265             logger.debug("@@@@@ File close name=" + getPath() + ", count=" + m_openCount + " <<ERROR>>");
266         else
267             m_openCount--;
268
269         return m_openCount;
270     }
271
272     /**
273      * Check if the file state has expired
274      *
275      * @param curTime long
276      * @return boolean
277      */

278     public final boolean hasExpired(long curTime)
279     {
280         if (m_tmo == NoTimeout)
281             return false;
282         if (curTime > m_tmo)
283             return true;
284         return false;
285     }
286
287     /**
288      * Return the number of seconds left before the file state expires
289      *
290      * @param curTime long
291      * @return long
292      */

293     public final long getSecondsToExpire(long curTime)
294     {
295         if (m_tmo == NoTimeout)
296             return -1;
297         return (m_tmo - curTime) / 1000L;
298     }
299
300     /**
301      * Determine if the file state has an associated rename state
302      *
303      * @return boolean
304      */

305     public final boolean hasRenameState()
306     {
307         return m_newNameState != null ? true : false;
308     }
309     
310     /**
311      * Return the associated rename state
312      *
313      * @return FileState
314      */

315     public final FileState getRenameState()
316     {
317         return m_newNameState;
318     }
319
320     /**
321      * Determine if a folder has pseudo files associated with it
322      *
323      * @return boolean
324      */

325     public final boolean hasPseudoFiles()
326     {
327         if ( m_pseudoFiles != null)
328             return m_pseudoFiles.numberOfFiles() > 0;
329         return false;
330     }
331     
332     /**
333      * Return the pseudo file list
334      *
335      * @return PseudoFileList
336      */

337     public final PseudoFileList getPseudoFileList()
338     {
339         return m_pseudoFiles;
340     }
341     
342     /**
343      * Add a pseudo file to this folder
344      *
345      * @param pfile PseudoFile
346      */

347     public final void addPseudoFile(PseudoFile pfile)
348     {
349         if ( m_pseudoFiles == null)
350             m_pseudoFiles = new PseudoFileList();
351         m_pseudoFiles.addFile( pfile);
352     }
353     
354     /**
355      * Set the file status
356      *
357      * @param status FileStateStatus
358      */

359     public final void setFileStatus(FileStateStatus status)
360     {
361         m_fileStatus = status;
362     }
363
364     /**
365      * Set the file status
366      *
367      * @param fsts int
368      */

369     public final void setFileStatus(int fsts)
370     {
371         if ( fsts == FileStatus.FileExists)
372             m_fileStatus = FileStateStatus.FileExists;
373         else if ( fsts == FileStatus.DirectoryExists)
374             m_fileStatus = FileStateStatus.FolderExists;
375         else if ( fsts == FileStatus.NotExist)
376             m_fileStatus = FileStateStatus.NotExist;
377     }
378     
379     /**
380      * Set the file state expiry time
381      *
382      * @param expire long
383      */

384     public final void setExpiryTime(long expire)
385     {
386         m_tmo = expire;
387     }
388
389     /**
390      * Set the node ref for the file/folder
391      *
392      * @param nodeRef NodeRef
393      */

394     public final void setNodeRef(NodeRef nodeRef)
395     {
396         m_nodeRef = nodeRef;
397     }
398
399     /**
400      * Set the associated file state when a file is renamed, this is the link to the new file state
401      *
402      * @param fstate FileState
403      */

404     public final void setRenameState(FileState fstate)
405     {
406         m_newNameState = fstate;
407     }
408     
409     /**
410      * Set the shared access mode, from the first file open
411      *
412      * @param mode int
413      */

414     public final void setSharedAccess(int mode)
415     {
416         if (getOpenCount() == 0)
417             m_sharedAccess = mode;
418     }
419
420     /**
421      * Set the file path
422      *
423      * @param path String
424      */

425     public final void setPath(String JavaDoc path)
426     {
427
428         // Split the path into directories and file name, only uppercase the directories to
429
// normalize the path.
430

431         m_path = normalizePath(path);
432     }
433
434     /**
435      * Return the count of active locks on this file
436      *
437      * @return int
438      */

439     public final int numberOfLocks()
440     {
441         if (m_lockList != null)
442             return m_lockList.numberOfLocks();
443         return 0;
444     }
445
446     /**
447      * Add a lock to this file
448      *
449      * @param lock FileLock
450      * @exception LockConflictException
451      */

452     public final void addLock(FileLock lock) throws LockConflictException
453     {
454
455         // Check if the lock list has been allocated
456

457         if (m_lockList == null)
458         {
459
460             synchronized (this)
461             {
462
463                 // Allocate the lock list, check if the lock list has been allocated elsewhere
464
// as we may have been waiting for the lock
465

466                 if (m_lockList == null)
467                     m_lockList = new FileLockList();
468             }
469         }
470
471         // Add the lock to the list, check if there are any lock conflicts
472

473         synchronized (m_lockList)
474         {
475
476             // Check if the new lock overlaps with any existing locks
477

478             if (m_lockList.allowsLock(lock))
479             {
480
481                 // Add the new lock to the list
482

483                 m_lockList.addLock(lock);
484             }
485             else
486                 throw new LockConflictException();
487         }
488     }
489
490     /**
491      * Remove a lock on this file
492      *
493      * @param lock FileLock
494      * @exception NotLockedException
495      */

496     public final void removeLock(FileLock lock) throws NotLockedException
497     {
498
499         // Check if the lock list has been allocated
500

501         if (m_lockList == null)
502             throw new NotLockedException();
503
504         // Remove the lock from the active list
505

506         synchronized (m_lockList)
507         {
508
509             // Remove the lock, check if we found the matching lock
510

511             if (m_lockList.removeLock(lock) == null)
512                 throw new NotLockedException();
513         }
514     }
515
516     /**
517      * Check if the file is readable for the specified section of the file and process id
518      *
519      * @param offset long
520      * @param len long
521      * @param pid int
522      * @return boolean
523      */

524     public final boolean canReadFile(long offset, long len, int pid)
525     {
526
527         // Check if the lock list is valid
528

529         if (m_lockList == null)
530             return true;
531
532         // Check if the file section is readable by the specified process
533

534         boolean readOK = false;
535
536         synchronized (m_lockList)
537         {
538
539             // Check if the file section is readable
540

541             readOK = m_lockList.canReadFile(offset, len, pid);
542         }
543
544         // Return the read status
545

546         return readOK;
547     }
548
549     /**
550      * Check if the file is writeable for the specified section of the file and process id
551      *
552      * @param offset long
553      * @param len long
554      * @param pid int
555      * @return boolean
556      */

557     public final boolean canWriteFile(long offset, long len, int pid)
558     {
559
560         // Check if the lock list is valid
561

562         if (m_lockList == null)
563             return true;
564
565         // Check if the file section is writeable by the specified process
566

567         boolean writeOK = false;
568
569         synchronized (m_lockList)
570         {
571
572             // Check if the file section is writeable
573

574             writeOK = m_lockList.canWriteFile(offset, len, pid);
575         }
576
577         // Return the write status
578

579         return writeOK;
580     }
581
582     /**
583      * Normalize the path to uppercase the directory names and keep the case of the file name.
584      *
585      * @param path String
586      * @return String
587      */

588     public final static String JavaDoc normalizePath(String JavaDoc path)
589     {
590
591         // Split the path into directories and file name, only uppercase the directories to
592
// normalize the path.
593

594         String JavaDoc normPath = path;
595
596         if (path.length() > 3)
597         {
598
599             // Split the path to seperate the folders/file name
600

601             int pos = path.lastIndexOf(FileName.DOS_SEPERATOR);
602             if (pos != -1)
603             {
604
605                 // Get the path and file name parts, normalize the path
606

607                 String JavaDoc pathPart = path.substring(0, pos).toUpperCase();
608                 String JavaDoc namePart = path.substring(pos);
609
610                 // Rebuild the path string
611

612                 normPath = pathPart + namePart;
613             }
614         }
615
616         // Return the normalized path
617

618         return normPath;
619     }
620
621     /**
622      * Return the file state as a string
623      *
624      * @return String
625      */

626     public String JavaDoc toString()
627     {
628         StringBuffer JavaDoc str = new StringBuffer JavaDoc();
629
630         str.append("[");
631         str.append(getPath());
632         str.append(",");
633         str.append(getFileStatus());
634         str.append(":Opn=");
635         str.append(getOpenCount());
636
637         str.append(",Expire=");
638         str.append(getSecondsToExpire(System.currentTimeMillis()));
639
640         str.append(",Locks=");
641         str.append(numberOfLocks());
642
643         str.append(",Ref=");
644         if ( hasNodeRef())
645             str.append(getNodeRef().getId());
646         else
647             str.append("Null");
648         
649         if ( isDirectory())
650         {
651             str.append(",Pseudo=");
652             if ( hasPseudoFiles())
653                 str.append(getPseudoFileList().numberOfFiles());
654             else
655                 str.append(0);
656         }
657         str.append("]");
658
659         return str.toString();
660     }
661 }
662
Popular Tags