1 17 package org.apache.excalibur.source.impl; 18 19 import java.io.ByteArrayOutputStream ; 20 import java.io.FileNotFoundException ; 21 import java.io.IOException ; 22 import java.io.OutputStream ; 23 import java.net.URL ; 24 import java.util.Map ; 25 26 import org.apache.excalibur.source.ModifiableSource; 27 import org.apache.excalibur.source.SourceException; 28 import org.apache.excalibur.source.SourceNotFoundException; 29 import org.apache.excalibur.source.SourceParameters; 30 import org.apache.excalibur.source.SourceResolver; 31 import org.apache.excalibur.source.SourceUtil; 32 33 import sun.net.ftp.FtpClient; 34 35 40 public class FTPSource extends URLSource implements ModifiableSource 41 { 42 private boolean m_isAscii; 43 44 public FTPSource() 45 { 46 super(); 47 } 48 49 53 public void init(final URL url, final Map parameters) throws IOException 54 { 55 final String systemId = url.toExternalForm(); 56 setSystemId(systemId); 57 setScheme(SourceUtil.getScheme(systemId)); 58 59 m_url = url; 60 m_isAscii = false; 61 62 if (parameters != null) 63 { 64 m_parameters = (SourceParameters) parameters.get(SourceResolver.URI_PARAMETERS); 65 final String method = (String ) parameters.get(SourceResolver.METHOD); 66 67 if ("ASCII".equalsIgnoreCase(method)) 68 { 69 m_isAscii = true; 70 } 71 } 72 } 73 74 80 public boolean canCancel( final OutputStream stream ) 81 { 82 if (stream instanceof FTPSourceOutputStream) 83 { 84 FTPSourceOutputStream fsos = (FTPSourceOutputStream) stream; 85 if ( fsos.getSource() == this ) 86 { 87 return fsos.canCancel(); 88 } 89 } 90 91 throw new IllegalArgumentException ( "The stream is not associated to this source" ); 92 } 93 94 100 public void cancel( final OutputStream stream ) throws IOException 101 { 102 if (stream instanceof FTPSourceOutputStream) 103 { 104 FTPSourceOutputStream fsos = (FTPSourceOutputStream) stream; 105 if ( fsos.getSource() == this ) 106 { 107 try 108 { 109 fsos.cancel(); 110 } 111 catch ( Exception e ) 112 { 113 throw new SourceException( "Exception during cancel.", e ); 114 } 115 return; 116 } 117 } 118 119 throw new IllegalArgumentException ( "The stream is not associated to this source" ); 120 } 121 122 125 public void delete() throws SourceException 126 { 127 EnhancedFtpClient ftpClient = null; 128 try 129 { 130 ftpClient = getFtpClient(); 131 final String relativePath = m_url.getPath().substring( 1 ); 132 ftpClient.delete( relativePath ); 133 } 134 catch ( IOException e ) 135 { 136 if ( e instanceof FileNotFoundException ) 137 { 138 throw new SourceNotFoundException( e.getMessage() ); 139 } 140 else 141 { 142 final String message = 143 "Failure during delete"; 144 throw new SourceException( message, e ); 145 } 146 } 147 finally 148 { 149 if ( ftpClient != null ) 150 { 151 try 152 { 153 ftpClient.closeServer(); 154 } 155 catch ( IOException e ) {} 156 } 157 } 158 } 159 160 164 protected void getInfos() 165 { 166 m_exists = false; 168 try 169 { 170 if (null == m_connection) 171 { 172 m_connection = m_url.openConnection(); 173 String userInfo = m_url.getUserInfo(); 174 } 175 setLastModified(m_connection.getLastModified()); 176 setContentLength(m_connection.getContentLength()); 177 m_mimeType = null; 181 m_exists = true; 182 } 183 catch (IOException ignore) 184 { 185 setContentLength(-1); 186 setLastModified(0); 187 } 188 } 189 190 193 public OutputStream getOutputStream() throws IOException 194 { 195 return new FTPSourceOutputStream( this ); 196 } 197 198 201 private final EnhancedFtpClient getFtpClient() 202 throws IOException 203 { 204 final EnhancedFtpClient ftpClient = 205 new EnhancedFtpClient( m_url.getHost() ); 206 ftpClient.login( getUser(), getPassword() ); 207 return ftpClient; 208 } 209 210 214 private final String getUser() 215 { 216 final String userInfo = m_url.getUserInfo(); 217 if ( userInfo != null ) 218 { 219 int index = userInfo.indexOf( ':' ); 220 if ( index != -1 ) 221 { 222 return userInfo.substring( 0, index ); 223 } 224 } 225 return null; 226 } 227 228 232 private final String getPassword() 233 { 234 final String userInfo = m_url.getUserInfo(); 235 if ( userInfo != null ) 236 { 237 int index = userInfo.indexOf( ':' ); 238 if ( index != -1 && userInfo.length() > index + 1 ) 239 { 240 return userInfo.substring( index + 1 ); 241 } 242 } 243 return null; 244 } 245 246 250 private static class EnhancedFtpClient extends FtpClient 251 { 252 253 private EnhancedFtpClient( String host ) throws IOException 254 { 255 super( host ); 256 } 257 258 void delete( final String path ) throws IOException 259 { 260 issueCommand( "DELE " + path ); 261 } 262 263 266 void mkdir( final String directoryName ) throws IOException 267 { 268 issueCommand( "MKD " + directoryName ); 269 } 270 271 283 void mkdirs( final String directoryPath ) throws IOException 284 { 285 try 286 { 287 cd( directoryPath ); 288 } 289 catch ( FileNotFoundException e ) 290 { 291 String directoryName = null; 293 final int index = directoryPath.lastIndexOf( '/' ); 294 if ( index != -1 ) 295 { 296 final String parentDirectoryPath = 297 directoryPath.substring( 0, index ); 298 directoryName = directoryPath.substring( index + 1 ); 299 mkdirs( parentDirectoryPath ); 300 } 301 else 302 { 303 directoryName = directoryPath; 304 } 305 mkdir( directoryName ); 306 cd( directoryName ); 307 } 308 } 309 310 } 311 312 316 private static class FTPSourceOutputStream extends ByteArrayOutputStream 317 { 318 private final FTPSource m_source; 319 private boolean m_isClosed = false; 320 321 FTPSourceOutputStream( final FTPSource source ) 322 { 323 super( 8192 ); 324 m_source = source; 325 } 326 327 public void close() throws IOException 328 { 329 if ( !m_isClosed ) 330 { 331 EnhancedFtpClient ftpClient = null; 332 OutputStream out = null; 333 try 334 { 335 ftpClient = m_source.getFtpClient(); 336 if (m_source.m_isAscii) { 337 ftpClient.ascii(); 338 } else { 339 ftpClient.binary(); 340 } 341 String parentPath = null; 342 String fileName = null; 343 final String relativePath = m_source.m_url.getPath().substring( 1 ); 344 final int index = relativePath.lastIndexOf( '/' ); 345 if ( index != -1 ) 346 { 347 parentPath = relativePath.substring( 0, index ); 348 fileName = relativePath.substring( index + 1 ); 349 ftpClient.mkdirs( parentPath ); 350 } 351 else 352 { 353 fileName = relativePath; 354 } 355 out = ftpClient.put( fileName ); 356 final byte[] bytes = toByteArray(); 357 out.write( bytes ); 358 } 359 finally 360 { 361 if ( out != null ) 362 { 363 try 364 { 365 out.close(); 366 } 367 catch ( IOException e ) {} 368 } 369 if ( ftpClient != null ) 370 { 371 try 372 { 373 ftpClient.closeServer(); 374 } 375 catch ( IOException e ) {} 376 } 377 m_isClosed = true; 378 } 379 } 380 } 381 382 boolean canCancel() 383 { 384 return !m_isClosed; 385 } 386 387 void cancel() throws Exception 388 { 389 if ( m_isClosed ) 390 { 391 final String message = 392 "Cannot cancel: outputstrem is already closed"; 393 throw new IllegalStateException ( message ); 394 } 395 m_isClosed = true; 396 } 397 398 FTPSource getSource() 399 { 400 return m_source; 401 } 402 403 } 404 405 } 406 | Popular Tags |