Source for gnu.inet.ftp.FTPURLConnection

   1: /*
   2:  * FTPURLConnection.java
   3:  * Copyright (C) 2003 The Free Software Foundation
   4:  * 
   5:  * This file is part of GNU inetlib, a library.
   6:  * 
   7:  * GNU inetlib is free software; you can redistribute it and/or modify
   8:  * it under the terms of the GNU General Public License as published by
   9:  * the Free Software Foundation; either version 2 of the License, or
  10:  * (at your option) any later version.
  11:  * 
  12:  * GNU inetlib is distributed in the hope that it will be useful,
  13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15:  * GNU General Public License for more details.
  16:  * 
  17:  * You should have received a copy of the GNU General Public License
  18:  * along with this library; if not, write to the Free Software
  19:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20:  * 
  21:  * Linking this library statically or dynamically with other modules is
  22:  * making a combined work based on this library.  Thus, the terms and
  23:  * conditions of the GNU General Public License cover the whole
  24:  * combination.
  25:  *
  26:  * As a special exception, the copyright holders of this library give you
  27:  * permission to link this library with independent modules to produce an
  28:  * executable, regardless of the license terms of these independent
  29:  * modules, and to copy and distribute the resulting executable under
  30:  * terms of your choice, provided that you also meet, for each linked
  31:  * independent module, the terms and conditions of the license of that
  32:  * module.  An independent module is a module which is not derived from
  33:  * or based on this library.  If you modify this library, you may extend
  34:  * this exception to your version of the library, but you are not
  35:  * obliged to do so.  If you do not wish to do so, delete this
  36:  * exception statement from your version.
  37:  */
  38: 
  39: package gnu.inet.ftp;
  40: 
  41: import java.io.FileNotFoundException;
  42: import java.io.FilterInputStream;
  43: import java.io.FilterOutputStream;
  44: import java.io.InputStream;
  45: import java.io.IOException;
  46: import java.io.OutputStream;
  47: import java.net.InetAddress;
  48: import java.net.URL;
  49: import java.net.URLConnection;
  50: import java.security.AccessController;
  51: import java.security.PrivilegedAction;
  52: import java.util.HashMap;
  53: import java.util.Map;
  54: 
  55: import gnu.inet.util.GetLocalHostAction;
  56: import gnu.inet.util.GetSystemPropertyAction;
  57: 
  58: /**
  59:  * An FTP URL connection.
  60:  *
  61:  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
  62:  */
  63: public class FTPURLConnection
  64:   extends URLConnection
  65: {
  66: 
  67:   /**
  68:    * The connection managing the protocol exchange.
  69:    */
  70:   protected FTPConnection connection;
  71: 
  72:   protected boolean passive;
  73:   protected int representationType;
  74:   protected int fileStructure;
  75:   protected int transferMode;
  76: 
  77:   /**
  78:    * Constructs an FTP connection to the specified URL.
  79:    * @param url the URL
  80:    */
  81:   public FTPURLConnection(URL url)
  82:   {
  83:     super(url);
  84:     passive = true;
  85:     representationType = FTPConnection.TYPE_BINARY;
  86:     fileStructure = -1;
  87:     transferMode = -1;
  88:   }
  89: 
  90:   /**
  91:    * Establishes the connection.
  92:    */
  93:   public void connect()
  94:     throws IOException
  95:   {
  96:     if (connected)
  97:       {
  98:         return;
  99:       }
 100:     String host = url.getHost();
 101:     int port = url.getPort();
 102:     String username = url.getUserInfo();
 103:     String password = null;
 104:     if (username != null)
 105:       {
 106:         int ci = username.indexOf(':');
 107:         if (ci != -1)
 108:           {
 109:             password = username.substring(ci + 1);
 110:             username = username.substring(0, ci);
 111:           }
 112:       }
 113:     else
 114:       {
 115:         username = "anonymous";
 116:         PrivilegedAction a = new GetSystemPropertyAction("user.name");
 117:         String systemUsername =(String) AccessController.doPrivileged(a);
 118:         a = new GetLocalHostAction();
 119:         InetAddress localhost =(InetAddress) AccessController.doPrivileged(a);
 120:         password = systemUsername + "@" +
 121:           ((localhost == null) ? "localhost" : localhost.getHostName());
 122:       }
 123:     connection = new FTPConnection(host, port);
 124:     if (!connection.authenticate(username, password))
 125:       {
 126:         throw new SecurityException("Authentication failed");
 127:       }
 128:     connection.setPassive(passive);
 129:     if (representationType != -1)
 130:       {
 131:         connection.setRepresentationType(representationType);
 132:       }
 133:     if (fileStructure != -1)
 134:       {
 135:         connection.setFileStructure(fileStructure);
 136:       }
 137:     if (transferMode != -1)
 138:       {
 139:         connection.setTransferMode(transferMode);
 140:       }
 141:   }
 142:   
 143:   /**
 144:    * This connection supports doInput.
 145:    */
 146:   public void setDoInput(boolean doinput)
 147:   {
 148:     doInput = doinput;
 149:   }
 150: 
 151:   /**
 152:    * This connection supports doOutput.
 153:    */
 154:   public void setDoOutput(boolean dooutput)
 155:   {
 156:     doOutput = dooutput;
 157:   }
 158:   
 159:   /**
 160:    * Returns an input stream that reads from this open connection.
 161:    */
 162:   public InputStream getInputStream()
 163:     throws IOException
 164:   {
 165:     if (!connected)
 166:       {
 167:         connect();
 168:       }
 169:     String path = url.getPath();
 170:     String filename = null;
 171:     int lsi = path.lastIndexOf('/');
 172:     if (lsi != -1)
 173:       {
 174:         filename = path.substring(lsi + 1);
 175:         path = path.substring(0, lsi);
 176:         if (!connection.changeWorkingDirectory(path))
 177:           {
 178:             throw new FileNotFoundException(path);
 179:           }
 180:       }
 181:     if (filename != null && filename.length() > 0)
 182:       {
 183:         return this.new ClosingInputStream(connection.retrieve(filename));
 184:       }
 185:     else
 186:       {
 187:         return this.new ClosingInputStream(connection.list(null));
 188:       }
 189:   }
 190:   
 191:   /**
 192:    * Returns an output stream that writes to this connection.
 193:    */
 194:   public OutputStream getOutputStream()
 195:     throws IOException
 196:   {
 197:     if (!connected)
 198:       {
 199:         connect();
 200:       }
 201:     String dir = url.getPath();
 202:     String filename = url.getFile();
 203:     if (!connection.changeWorkingDirectory(dir))
 204:       {
 205:         throw new FileNotFoundException(dir);
 206:       }
 207:     if (filename != null)
 208:       {
 209:         return this.new ClosingOutputStream(connection.store(filename));
 210:       }
 211:     else
 212:       {
 213:         throw new FileNotFoundException(filename);
 214:       }
 215:   }
 216: 
 217:   public String getRequestProperty(String key)
 218:   {
 219:     if ("passive".equals(key))
 220:       {
 221:         return Boolean.toString(passive);
 222:       }
 223:     else if ("representationType".equals(key))
 224:       {
 225:         switch (representationType)
 226:           {
 227:           case FTPConnection.TYPE_ASCII:
 228:             return "ASCII";
 229:           case FTPConnection.TYPE_EBCDIC:
 230:             return "EBCDIC";
 231:           case FTPConnection.TYPE_BINARY:
 232:             return "BINARY";
 233:           }
 234:       }
 235:     else if ("fileStructure".equals(key))
 236:       {
 237:         switch (fileStructure)
 238:           {
 239:           case FTPConnection.STRUCTURE_FILE:
 240:             return "FILE";
 241:           case FTPConnection.STRUCTURE_RECORD:
 242:             return "RECORD";
 243:           case FTPConnection.STRUCTURE_PAGE:
 244:             return "PAGE";
 245:           }
 246:       }
 247:     else if ("transferMode".equals(key))
 248:       {
 249:         switch (transferMode)
 250:           {
 251:           case FTPConnection.MODE_STREAM:
 252:             return "STREAM";
 253:           case FTPConnection.MODE_BLOCK:
 254:             return "BLOCK";
 255:           case FTPConnection.MODE_COMPRESSED:
 256:             return "COMPRESSED";
 257:           }
 258:       }
 259:     return null;
 260:   }
 261: 
 262:   public Map getRequestProperties()
 263:   {
 264:     Map map = new HashMap();
 265:     addRequestPropertyValue(map, "passive");
 266:     addRequestPropertyValue(map, "representationType");
 267:     addRequestPropertyValue(map, "fileStructure");
 268:     addRequestPropertyValue(map, "transferMode");
 269:     return map;
 270:   }
 271: 
 272:   private void addRequestPropertyValue(Map map, String key)
 273:   {
 274:     String value = getRequestProperty(key);
 275:     map.put(key, value);
 276:   }
 277:   
 278:   public void setRequestProperty(String key, String value)
 279:   {
 280:     if (connected)
 281:       {
 282:         throw new IllegalStateException();
 283:       }
 284:     if ("passive".equals(key))
 285:       {
 286:         passive = Boolean.valueOf(value).booleanValue();
 287:       }
 288:     else if ("representationType".equals(key))
 289:       {
 290:         if ("A".equalsIgnoreCase(value) ||
 291:             "ASCII".equalsIgnoreCase(value))
 292:           {
 293:             representationType = FTPConnection.TYPE_ASCII;
 294:           }
 295:         else if ("E".equalsIgnoreCase(value) ||
 296:                  "EBCDIC".equalsIgnoreCase(value))
 297:           {
 298:             representationType = FTPConnection.TYPE_EBCDIC;
 299:           }
 300:         else if ("I".equalsIgnoreCase(value) ||
 301:                  "BINARY".equalsIgnoreCase(value))
 302:           {
 303:             representationType = FTPConnection.TYPE_BINARY;
 304:           }
 305:         else
 306:           {
 307:             throw new IllegalArgumentException(value);
 308:           }
 309:       }
 310:     else if ("fileStructure".equals(key))
 311:       {
 312:         if ("F".equalsIgnoreCase(value) ||
 313:             "FILE".equalsIgnoreCase(value))
 314:           {
 315:             fileStructure = FTPConnection.STRUCTURE_FILE;
 316:           }
 317:         else if ("R".equalsIgnoreCase(value) ||
 318:                  "RECORD".equalsIgnoreCase(value))
 319:           {
 320:             fileStructure = FTPConnection.STRUCTURE_RECORD;
 321:           }
 322:         else if ("P".equalsIgnoreCase(value) ||
 323:                  "PAGE".equalsIgnoreCase(value))
 324:           {
 325:             fileStructure = FTPConnection.STRUCTURE_PAGE;
 326:           }
 327:         else
 328:           {
 329:             throw new IllegalArgumentException(value);
 330:           }
 331:       }
 332:     else if ("transferMode".equals(key))
 333:       {
 334:         if ("S".equalsIgnoreCase(value) ||
 335:             "STREAM".equalsIgnoreCase(value))
 336:           {
 337:             transferMode = FTPConnection.MODE_STREAM;
 338:           }
 339:         else if ("B".equalsIgnoreCase(value) ||
 340:                  "BLOCK".equalsIgnoreCase(value))
 341:           {
 342:             transferMode = FTPConnection.MODE_BLOCK;
 343:           }
 344:         else if ("C".equalsIgnoreCase(value) ||
 345:                  "COMPRESSED".equalsIgnoreCase(value))
 346:           {
 347:             transferMode = FTPConnection.MODE_COMPRESSED;
 348:           }
 349:         else
 350:           {
 351:             throw new IllegalArgumentException(value);
 352:           }
 353:       }
 354:   }
 355: 
 356:   public void addRequestProperty(String key, String value)
 357:   {
 358:     setRequestProperty(key, value);
 359:   }
 360: 
 361:   class ClosingInputStream
 362:     extends FilterInputStream
 363:   {
 364: 
 365:     ClosingInputStream(InputStream in)
 366:     {
 367:       super(in);
 368:     }
 369: 
 370:     public void close()
 371:       throws IOException
 372:     {
 373:       super.close();
 374:       connection.logout();
 375:     }
 376:     
 377:   }
 378: 
 379:   class ClosingOutputStream
 380:     extends FilterOutputStream
 381:   {
 382: 
 383:     ClosingOutputStream(OutputStream out)
 384:     {
 385:       super(out);
 386:     }
 387: 
 388:     public void close()
 389:       throws IOException
 390:     {
 391:       super.close();
 392:       connection.logout();
 393:     }
 394:     
 395:   }
 396: 
 397: }