Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/neuron/jaffer/OS_Volume.java


1   /* 
2    * Copyright (c) 2003 Stewart Allen <stewart@neuron.com>. All rights reserved.
3    * This program is free software. See the 'License' file for details.
4    */
5   
6   package com.neuron.jaffer;
7   
8   import java.io.*;
9   import java.net.*;
10  import java.util.*;
11  
12  class OS_Volume extends AFP_Volume
13  {
14    private Hashtable allNodes;
15    private String volName;
16    private File rootDir;
17    private int nextID = 32;
18    private boolean readonly;
19    private String passwd;
20  
21    OS_Volume(String vname, File droot)
22    {
23      this.volName = vname;
24      this.rootDir = droot;
25      this.allNodes = new Hashtable();
26  
27      OSNode root = new OSNode(0, 1, "", null);
28      OSNode vol  = new OSNode(1, 2, vname, droot);
29  
30      root.addOffspring(vol);
31      addNode(root);
32    }
33  
34    // custom methods
35    public void setReadOnly(boolean ro)
36    {
37      this.readonly = ro;
38    }
39  
40    public void setPassword(String pwd)
41    {
42      this.passwd = pwd;
43    }
44  
45    private synchronized int getNextID()
46    {
47      return nextID++;
48    }
49  
50    private void addNode(OSNode node)
51    {
52      allNodes.put(new Integer(node.getNodeID()), node);
53    }
54  
55    // abstract methods
56    public String getName()
57    {
58      return volName;
59    }
60  
61    public int getCreateDate()
62    {
63      return 0xa;
64    }
65  
66    public int getModifiedDate()
67    {
68      return 0xb;
69    }
70  
71    public int getBackupDate()
72    {
73      return 0x80000000;
74    }
75  
76    public void setBackupDate(int d)
77    {
78    }
79  
80    public void setModifiedDate(int d)
81    {
82    }
83  
84    public int getAttributes()
85    {
86      return 
87        (readonly              ? VOL_ATTR_READONLY : 0) |
88        (getPassword() != null ? VOL_ATTR_PASSWORD : 0) |
89        0;
90    }
91  
92    public void setAttributes(int attr)
93    {
94    }
95  
96    public int getSignature()
97    {
98      return VOL_SIG_FIXED;
99      //return VOL_SIG_VARIABLE;
100   }
101 
102   public int getBlockSize()
103   {
104     return 0x1000;
105   }
106 
107   public int getBytesFree()
108   {
109     return 0x55555555;
110   }
111 
112   public int getBytesTotal()
113   {
114     return 0x66666666;
115   }
116 
117   public long getExtBytesFree()
118   {
119     return 0x4545454545l;
120   }
121 
122   public long getExtBytesTotal()
123   {
124     return 0x4646464646l;
125   }
126 
127   public boolean hasUnixPrivs()
128   {
129     return false;
130   }
131 
132   public String getPassword()
133   {
134     return passwd;
135   }
136 
137   public AFP_CNode getCNode(int id)
138   {
139     return (AFP_CNode)allNodes.get(new Integer(id));
140   }
141 
142   // utility methods
143   public String flagsToString(int flags)
144   {
145     if (Utility.hasBits(flags, AFP_CNode.MODE_WRITE) && !readonly)
146     {
147       return "rw";
148     }
149     else
150     {
151       return "r";
152     }
153   }
154 
155   private boolean canOpen(File file, int flags)
156   {
157     boolean can = false;
158     if (Utility.hasBits(flags, AFP_CNode.MODE_WRITE))
159     {
160       can = file.exists() ? file.canWrite() : file.getParentFile().canWrite();
161     }
162     else
163     {
164       can = file.exists() && file.canRead();
165     }
166     return can;
167   }
168 
169   // -------------------------------------------------------------------------
170 
171   private class OSNode extends AFP_CNode
172   {
173     private int pid;
174     private Hashtable nodes;
175     private String name;
176     private File file;
177     private byte[] finderInfo;
178     private long resourceLength;
179     private volatile long modDate;
180 
181     OSNode(int pid, int id, String name, File file)
182     {
183       super(id);
184       this.pid = pid;
185       this.file = file;
186       this.name = name;
187       this.nodes = new Hashtable();
188       this.resourceLength = -1;
189     }
190 
191     // -- custom methods --
192     public void setParentID(int id)
193     {
194       this.pid = id;
195     }
196 
197     public synchronized void addOffspring(OSNode nn)
198     {
199       if (nodes == null)
200       {
201         nodes = new Hashtable();
202       }
203       nn.setParentID(getNodeID());
204       nodes.put(nn.getRealName(), nn);
205       addNode(nn);
206     }
207 
208     public synchronized OSNode addOffspring(String name, File file)
209     {
210       if (nodes == null)
211       {
212         nodes = new Hashtable();
213       }
214       OSNode nn = new OSNode(getNodeID(), getNextID(), name, file);
215       nodes.put(name, nn);
216       addNode(nn);
217       return nn;
218     }
219 
220     private void saveResourceInfo()
221     {
222       if (finderInfo == null && resourceLength < 0)
223       {
224         return;
225       }
226       try
227       {
228         ResourceFork rf = getResourceFork(MODE_WRITE);
229         if (rf == null)
230         {
231           return;
232         }
233         if (finderInfo != null)
234         {
235           rf.writeFinderInfo(finderInfo);
236         }
237         /*
238         if (resourceLength >= 0)
239         {
240           rf.setLength(resourceLength);
241         }
242         */
243         rf.close();
244       }
245       catch (Exception ex)
246       {
247         ex.printStackTrace();
248       }
249     }
250 
251     private void cacheResourceInfo()
252     {
253       if (finderInfo != null && resourceLength >= 0)
254       {
255         return;
256       }
257       try
258       {
259         ResourceFork rf = getResourceFork(MODE_READ);
260         if (rf == null)
261         {
262           return;
263         }
264         if (finderInfo == null)
265         {
266           finderInfo = new byte[16];
267         }
268         rf.readFinderInfo(finderInfo);
269         resourceLength = rf.getLength();
270         rf.close();
271       }
272       catch (Exception ex)
273       {
274         ex.printStackTrace();
275       }
276     }
277 
278     public synchronized void scanDir()
279     {
280       if (file == null)
281       {
282         return;
283       }
284       long lm = file.lastModified();
285       if (lm <= modDate)
286       {
287         return;
288       }
289       modDate = lm;
290       String f[] = file.list();
291       if (f == null || f.length == 0)
292       {
293         nodes.clear();
294         return;
295       }
296       Hashtable tmp = new Hashtable(f.length*2);
297       // add nodes for unknown keys
298       for (int i=0; i<f.length; i++)
299       {
300         if (f[i].startsWith("._"))
301         {
302           continue;
303         }
304         File nn = new File(file, f[i]);
305         // skip unknowns
306         if (!(nn.isFile() || nn.isDirectory()))
307         {
308           continue;
309         }
310         if (nodes.get(f[i]) == null)
311         {
312           addOffspring(f[i], nn);
313         }
314         tmp.put(f[i], f[i]);
315       }
316       // remove stale handles
317       for (Enumeration e = nodes.keys(); e.hasMoreElements(); )
318       {
319         Object key = e.nextElement();
320         if (tmp.get(key) == null)
321         {
322           nodes.remove(key);
323         }
324       }
325     }
326 
327     public String getRealName()
328     {
329       return name;
330     }
331 
332 
333     public String toString()
334     {
335       return "'"+name+"' {"+getNodeID()+"} "+nodes+" ";
336     }
337     
338     private ResourceFork getResourceFork(int flags)
339     {
340       return (ResourceFork)openResourceFork(flags);
341     }
342 
343     private File getResourceForkFile()
344     {
345       return new File(file.getParentFile(), "._"+file.getName());
346     }
347 
348     // abstract methods
349     public int getNodeType()
350     {
351       if (getNodeID() < 32)   { return NODE_DIRECTORY; }
352       if (file == null)       { return NODE_UNKNOWN; }
353       if (file.isFile())      { return NODE_FILE; }
354       if (file.isDirectory()) { return NODE_DIRECTORY; }
355       return NODE_UNKNOWN;
356     }
357 
358     public boolean delete()
359     {
360       OSNode parent = (OSNode)getCNode(getParentNodeID());
361       if (parent != null && file.delete())
362       {
363         getResourceForkFile().delete();
364         parent.modDate = 0;
365         return true;
366       }
367       else
368       {
369         return false;
370       }
371     }
372 
373     public int getParentNodeID()
374     {
375       return pid;
376     }
377 
378     public int getOffspringCount()
379     {
380       scanDir();
381       return nodes.size();
382     }
383 
384     public int getAttributes()
385     {
386       return 0;
387     }
388 
389     public void setAttributes(int attr)
390     {
391     }
392 
393     public int getOwnerID()
394     {
395       return 0;
396     }
397 
398     public int getGroupID()
399     {
400       return 0;
401     }
402 
403     public int getCreateDate()
404     {
405       return Utility.unix2afpTime(file.lastModified());
406     }
407 
408     public void setCreateDate(int date)
409     {
410     }
411 
412     public int getModifiedDate()
413     {
414       return Utility.unix2afpTime(file.lastModified());
415     }
416 
417     public void setModifiedDate(int date)
418     {
419       file.setLastModified(Utility.afp2unixTime(date));
420     }
421 
422     public int getBackupDate()
423     {
424       return 0x80000000;
425     }
426 
427     public void setBackupDate(int date)
428     {
429     }
430 
431     public byte[] getFinderInfo()
432     {
433       cacheResourceInfo();
434       return finderInfo;
435     }
436 
437     public void setFinderInfo(byte b[])
438     {
439       finderInfo = b;
440       saveResourceInfo();
441     }
442 
443     public String getLongName()
444     {
445       return name;
446     }
447 
448     public String getShortName()
449     {
450       return name;
451     }
452 
453     public String getUTF8Name()
454     {
455       return name;
456     }
457 
458     public byte[] getUnixPrivs()
459     {
460       return null;
461     }
462 
463     public void setUnixPrivs(byte b[])
464     {
465     }
466 
467     public int getAccessRights()
468     {
469       boolean read = file.canRead();
470       boolean write = file.canWrite();
471       //System.out.println("Access on "+file+" read="+read+" write="+write);
472       return ACCESS_EVERYTHING ^ (
473         (read  ? 0 : ACCESS_OWNER_READ  | ACCESS_GROUP_READ  | ACCESS_ALL_READ  | ACCESS_UA_READ ) |
474         (write ? 0 : ACCESS_OWNER_WRITE | ACCESS_GROUP_WRITE | ACCESS_ALL_WRITE | ACCESS_UA_WRITE)
475       );
476     }
477 
478     public synchronized boolean moveTo(AFP_CNode dir, String name)
479     {
480       if (!dir.isDirectory())
481       {
482         return false;
483       }
484       File targetFile = ((OSNode)dir).file;
485       File newFile = empty(name) ? targetFile : new File(targetFile, name);
486       if (file.renameTo(newFile))
487       {
488         OSNode parent = (OSNode)getCNode(getParentNodeID());
489         if (parent != null)
490         {
491           parent.modDate = 0;
492         }
493         getResourceForkFile().renameTo(new File(newFile.getParentFile(), "._"+newFile.getName()));
494         file = newFile;
495         return true;
496       }
497       else
498       {
499         return false;
500       }
501     }
502 
503     public AFP_CNode createDirectory(String name)
504     {
505       AFP_CNode ndir = getOffspringByName(name);
506       if (ndir != null)
507       {
508         return null;
509       }
510       File nfdir = new File(file, name);
511       if (nfdir.mkdirs())
512       {
513         return addOffspring(name, nfdir);
514       }
515       else
516       {
517         return null;
518       }
519     }
520 
521     public AFP_CNode createFile(String name)
522     {
523       AFP_CNode ndir = getOffspringByName(name);
524       if (ndir != null)
525       {
526         return null;
527       }
528       File nfile = new File(file, name);
529       try
530       {
531         if (nfile.createNewFile())
532         {
533           return addOffspring(name, nfile);
534         }
535         else
536         {
537           return null;
538         }
539       }
540       catch (Exception ex)
541       {
542         return null;
543       }
544     }
545 
546     public AFP_CNode getOffspringByName(String name)
547     {
548       scanDir();
549       return (AFP_CNode)nodes.get(name);
550     }
551 
552     public Enumeration getOffspringEnumeration()
553     {
554       scanDir();
555       return nodes.elements();
556     }
557 
558     public int getLaunchLimit()
559     {
560       return 0;
561     }
562 
563     public int getDataForkLen()
564     {
565       return (int)Math.min(file.length(), 0xffffffffl);
566     }
567 
568     public int getResourceForkLen()
569     {
570       cacheResourceInfo();
571       return (int)Math.min(resourceLength, 0xffffffffl);
572     }
573 
574     public long getExtDataForkLen()
575     {
576       return file.length();
577     }
578 
579     public long getExtResourceForkLen()
580     {
581       cacheResourceInfo();
582       return resourceLength;
583     }
584 
585     public AFP_Fork openFileFork(int flags)
586     {
587       if (!canOpen(file, flags))
588       {
589         return null;
590       }
591       try
592       {
593         return new DataFork(file, flags);
594       }
595       catch (Exception ex)
596       {
597         ex.printStackTrace();
598         return null;
599       }
600     }
601 
602     public AFP_Fork openResourceFork(int flags)
603     {
604       // you can't create a resource fork if you don't have
605       // the same priviledges on the data fork
606       if (getNodeID() < 32 || !canOpen(getResourceForkFile(), flags) || !canOpen(file, flags))
607       {
608         return null;
609       }
610       try
611       {
612         return new ResourceFork(getResourceForkFile(), flags);
613       }
614       catch (Exception ex)
615       {
616         ex.printStackTrace();
617         return null;
618       }
619     }
620   }
621 
622   // -------------------------------------------------------------------------
623 
624   private class ResourceFork extends DataFork
625   {
626     private File file;
627 
628     ResourceFork(File file, int flags)
629       throws IOException
630     {
631       super(new AppleDouble(file, flagsToString(flags)));
632       this.file = file;
633     }
634 
635     public File file()
636     {
637       return file;
638     }
639 
640     public void renameTo(File dst)
641     {
642       if (file.renameTo(dst))
643       {
644         file = dst;
645       }
646     }
647 
648     public int getForkType()
649     {
650       return FORK_RESOURCE;
651     }
652 
653     public void readFinderInfo(byte b[])
654       throws IOException
655     {
656       ((AppleDouble)nativeFile()).readFinderInfo(b);
657     }
658 
659     public void writeFinderInfo(byte b[])
660       throws IOException
661     {
662       ((AppleDouble)nativeFile()).writeFinderInfo(b);
663     }
664   }
665 
666   // -------------------------------------------------------------------------
667 
668   private class DataFork extends AFP_Fork
669   {
670     private RandomAccessFile file;
671 
672     DataFork(File file, int flags)
673       throws IOException
674     {
675       this(new RandomAccessFile(file, flagsToString(flags)));
676     }
677 
678     DataFork(RandomAccessFile file)
679       throws IOException
680     {
681       this.file = file;
682     }
683 
684     public RandomAccessFile nativeFile()
685     {
686       return file;
687     }
688 
689     public int getForkType()
690     {
691       return FORK_DATA;
692     }
693 
694     public void readRange(long offset, long length, ByteWriter ww)
695       throws IOException
696     {
697       length = Math.min(getLength() - offset, length);
698       if (length < 0 || offset < 0)
699       {
700         throw new EOFException();
701       }
702       file.seek(offset);
703       ww.readFromFile(file, length);
704     }
705 
706     public long writeRange(long offset, long length, ByteReader rr)
707       throws IOException
708     {
709       file.seek(offset);
710       return rr.writeToFile(file, length);
711     }
712 
713     public long getLength()
714       throws IOException
715     {
716       return file.length();
717     }
718 
719     public void setLength(long len)
720       throws IOException
721     {
722       file.setLength(len);
723     }
724 
725     public void flush()
726       throws IOException
727     {
728       file.getFD().sync();
729     }
730 
731     public void close()
732     {
733       try
734       {
735         file.close();
736       }
737       catch (Exception ex)
738       {
739         ex.printStackTrace();
740       }
741     }
742   }
743 }
744