001/*
002 * Version 0.70 01/04/2002
003 *
004 * Visit my url for update: http://www.geocities.com/beapetrovicova/
005 * 
006 * jFtp was developed by Bea Petrovicova <beapetrovicova@yahoo.com>.
007 * The design and implementation of jFtp are available for royalty-free 
008 * adoption and use. This software is provided 'as is' without any 
009 * guarantees. Copyright is retained by Bea Petrovicova. Redistribution 
010 * of any part of jFtp or any derivative works must include this notice.
011 * 
012 */
013
014package cz.dhl.io;
015
016import cz.dhl.ftp.Ftp;
017import cz.dhl.ui.CoConsole;
018import cz.dhl.ui.CoProgress;
019import java.io.BufferedInputStream;
020import java.io.BufferedOutputStream;
021import java.io.BufferedReader;
022import java.io.BufferedWriter;
023import java.io.IOException;
024import java.io.InputStream;
025import java.io.InputStreamReader;
026import java.io.OutputStream;
027import java.io.OutputStreamWriter;
028import java.io.Reader;
029import java.io.Writer;
030
031/**
032 * Copies files.
033 * 
034 * @Version 0.70 01/04/2002
035 * @author Bea Petrovicova <beapetrovicova@yahoo.com>  
036 * @see CoFile
037 */
038public abstract class CoLoad
039{  CoConsole console; 
040
041   CoLoad() {}
042
043   /** Delete Files Recursively. 
044    * @param src Files to be deleted */
045   static public boolean delete(CoFile files[])
046   {  return CoLoad.delete(files,new CoProgressNull()); }
047   
048   /** Delete Files Recursively.
049    * @param files Files to be deleted
050    * @param progress Progress indicator
051    * @return True on success.
052    * @see CoProgress
053    */
054   static public boolean delete(CoFile files[], CoProgress progress)
055   {  boolean done = true; if(files!=null)
056      for(int i=0;i<files.length;i++)
057         /* Aggressive delete, includes 
058            links and special files. */
059         if(!files[i].isDirectory())
060         {  if(progress.isAborted()) { done = false; break; }
061            progress.setFile(files[i]);
062            if(!files[i].delete()) 
063            {  done = false; break; }
064         } else if(files[i].isDirectory())
065            try
066            {  if(progress.isAborted()) { done = false; break; }
067               progress.setFile(files[i]);
068               if(!CoLoad.delete(files[i].listCoFiles(),progress)) 
069               {  done = false; break; }
070               else if(!files[i].delete()) 
071               {  done = false; break; }
072            } catch(SecurityException e) 
073            { done = false; break; }
074      return done;
075   }
076
077   /** Copy Files Recursively.
078    * @param to Destination directory
079    * @param files Source files
080    * @return True on success.
081    */
082   static public boolean copy(CoFile to, CoFile files[])
083   {  return CoLoad.copy(to,files,new CoProgressNull()); }
084   
085   /** Copy Files Recursively.
086    * @param to Destination directory
087    * @param files Source files
088    * @param progress Progress indicator
089    * @return True on success.
090    */
091   static public boolean copy(CoFile to, CoFile files[], CoProgress progress)
092   {  boolean done = true; if(files!=null)
093      for(int i=0;i<files.length;i++)
094         /* Selective copy, excluding 
095            links and special files. */
096         if(files[i].isFile())
097         {  if(progress.isAborted()) { done = false; break; }
098            CoFile tofile = to.newFileChild(files[i].getName());
099            progress.setFile(tofile,files[i]); 
100            if(!CoLoad.copy(tofile,files[i],progress))
101               { done = false; break; }
102         } else if(files[i].isDirectory())
103            try
104            {  if(progress.isAborted()) { done = false; break; }
105               CoFile todir = to.newFileChild(files[i].getName());
106               progress.setFile(todir,files[i]);
107               /* Aggressive mkdir, attempt 
108                  to copy contents on error. */
109               todir.mkdir();
110               if(!CoLoad.copy(to.newFileChild(files[i].getName()),
111                                    files[i].listCoFiles(),progress))
112                  { done = false; break; }
113            } catch(SecurityException e) 
114            { done = false; break; } 
115      return done;
116   }
117
118   /** Copy File.
119    * @param dst Destination file
120    * @param src Source file
121    * @return True on success. */
122   static public boolean copy(CoFile dst, CoFile file)
123   {  return copy(dst,file,new CoProgressNull()); }   
124
125   /** Copy File.
126    * @param dst Destination file
127    * @param src Source file
128    * @param progress Progress indicator
129    * @return True on success. */
130   static public boolean copy(CoFile dst, CoFile file,CoProgress progress)
131   {  CoConsole console = null;
132      if(dst.getConsole()!=null)
133         console = dst.getConsole();
134      else if(file.getConsole()!=null)
135         console = file.getConsole();
136      else if(console==null)
137         console = new CoConsole() 
138         {  public void print(String message) {} };
139      return copy(dst,file,progress,console);
140   }
141
142   /** Copy File.
143    * @param dst Destination file
144    * @param src Source file
145    * @param progress Progress indicator
146    * @param console Console output
147    * @return True on success. */
148   static public boolean copy(CoFile dst, CoFile file, CoProgress progress, CoConsole console)
149   {  boolean done=false; CoLoad load = null; 
150      try 
151      {  load = CoLoad.open(dst,file,console);
152         int increment = 0;
153         while(increment != -1)
154         {  if(progress.isAborted()) { done = false; break; }
155            try
156            {  increment = load.transfer(); }
157            catch(IOException e) { progress.setDelay(60000); increment=0; }
158            if(increment!=-1)
159               progress.setProgress(increment); }
160         done=true; }
161      catch(IOException e) { /* ??.printerr(e); */ }
162      finally
163      {  try { if(load!=null) load.close(); } catch(IOException e) { /* ??.printerr(e); */ } }
164      return done;
165   }
166      
167   static CoLoad open(CoFile dst, CoFile src, CoConsole console) throws IOException
168   {  if(dst.getDataType()=='A' || src.getDataType()=='A')
169         return new CoTextLoad(dst,src,console);
170      else return new CoDataLoad(dst,src,console); }
171   
172   abstract int transfer() throws IOException;
173   abstract void close() throws IOException;
174}
175
176final class CoDataLoad extends CoLoad
177{  private byte cbuf[] = new byte[4096];   
178   private InputStream ibuf = null;
179   private OutputStream obuf = null;
180   
181   CoDataLoad(CoFile dst, CoFile src, CoConsole console) throws IOException
182   {  this.console=console;
183      try
184      {  ibuf = new BufferedInputStream(src.getInputStream());
185         obuf = new BufferedOutputStream(dst.getOutputStream()); }
186      catch(IOException e)
187      {  if(ibuf==null)
188            console.print("< Can't obtain INPUT STREAM for '" +src.getName() +"'! >"); 
189         else if(obuf==null)
190            console.print("< Can't obtain OUTPUT STREAM for '" +dst.getName() +"'! >"); 
191         close(); throw e;
192      } 
193   }
194
195   public int transfer() throws IOException 
196   {  int len;
197      if((len=ibuf.read(cbuf,0,4096)) > 0)
198         obuf.write(cbuf,0,len);
199      return len;
200   } 
201   
202   public void close() throws IOException
203   {  IOException ex = null;
204      while(ibuf!=null || obuf!=null)
205      {  try 
206         {  InputStream i; OutputStream o;
207            if(ibuf!=null) { i=ibuf; ibuf=null; i.close(); }
208            if(obuf!=null) { o=obuf; obuf=null; o.close(); }
209         } catch(IOException e) { ex = e; }
210      }
211      if(ex!=null) throw ex;
212   }
213
214}
215
216final class CoTextLoad extends CoLoad
217{  private BufferedReader ibuf  = null;
218   private BufferedWriter obuf  = null;
219   
220   CoTextLoad(CoFile dst, CoFile src, CoConsole console) throws IOException
221   {  this.console=console;
222      try
223      {  ibuf = new BufferedReader(new InputStreamReader(src.getInputStream()));
224         obuf = new BufferedWriter(new OutputStreamWriter(dst.getOutputStream())); }
225      catch(IOException e)
226      {  if(ibuf==null)
227            console.print("< Can't obtain INPUT STREAM for '" +src.getName() +"'! >"); 
228         else if(obuf==null)
229            console.print("< Can't obtain OUTPUT STREAM for '" +dst.getName() +"'! >"); 
230         close(); throw e;
231      }
232   }
233
234   public int transfer() throws IOException 
235   {  String line = null;
236      if((line=ibuf.readLine()) != null)
237      {  obuf.write(line); 
238         obuf.newLine(); 
239         return line.length();
240      } else return -1;
241   } 
242   
243   public void close() throws IOException
244   {  IOException x = null;
245      while(ibuf!=null || obuf!=null)
246      {  try 
247         {  Reader r; Writer w;
248            if(ibuf!=null) { r=ibuf; ibuf=null; r.close(); }
249            if(obuf!=null) { w=obuf; obuf=null; w.close(); }
250         } catch(IOException e) { x = e; }
251      }
252      if(x!=null) throw x;
253   }
254}
255
256class CoProgressNull implements CoProgress
257{  CoProgressNull() {}
258   public void setProgress(int done) {}
259   public void setFile(CoFile file) {}
260   public void setFile(CoFile to,CoFile file) {}
261   public void setDelay(long increment) {}
262   public boolean isAborted() {return false; } }