blob: 06e9802bc50a44c8f3ce7849ac85c0adf95a2d69 [file] [log] [blame]
/****************************************************************************
* Copyright (c) 2008 Composent, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Composent, Inc. - initial API and implementation
*****************************************************************************/
package org.eclipse.ecf.provider.filetransfer.browse;
import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.URLConnection;
import org.eclipse.ecf.core.security.Callback;
import org.eclipse.ecf.core.security.CallbackHandler;
import org.eclipse.ecf.core.security.IConnectContext;
import org.eclipse.ecf.core.security.NameCallback;
import org.eclipse.ecf.core.security.ObjectCallback;
import org.eclipse.ecf.core.security.UnsupportedCallbackException;
import org.eclipse.ecf.core.util.Proxy;
import org.eclipse.ecf.filetransfer.BrowseFileTransferException;
import org.eclipse.ecf.filetransfer.IRemoteFile;
import org.eclipse.ecf.filetransfer.IRemoteFileSystemListener;
import org.eclipse.ecf.filetransfer.identity.IFileID;
import org.eclipse.ecf.internal.provider.filetransfer.Activator;
import org.eclipse.ecf.internal.provider.filetransfer.IURLConnectionModifier;
import org.eclipse.ecf.internal.provider.filetransfer.Messages;
import org.eclipse.ecf.provider.filetransfer.util.JREProxyHelper;
import org.eclipse.osgi.util.NLS;
/**
*
*/
public class URLFileSystemBrowser extends AbstractFileSystemBrowser {
private static final String USERNAME_PREFIX = Messages.UrlConnectionRetrieveFileTransfer_USERNAME_PROMPT;
private static final String JRE_CONNECT_TIMEOUT_PROPERTY = "sun.net.client.defaultConnectTimeout"; //$NON-NLS-1$
private static final String DEFAULT_CONNECT_TIMEOUT = "30000"; //$NON-NLS-1$
private static final String JRE_READ_TIMEOUT_PROPERTY = "sun.net.client.defaultReadTimeout"; //$NON-NLS-1$
private static final String DEFAULT_READ_TIMEOUT = "30000"; //$NON-NLS-1$
private JREProxyHelper proxyHelper = null;
protected String username = null;
protected String password = null;
/**
* @param directoryOrFileID
* @param listener
*/
public URLFileSystemBrowser(IFileID directoryOrFileID, IRemoteFileSystemListener listener, URL directoryOrFileURL, IConnectContext connectContext, Proxy proxy) {
super(directoryOrFileID, listener, directoryOrFileURL, connectContext, proxy);
proxyHelper = new JREProxyHelper();
}
private void setupTimeouts() {
String existingTimeout = System.getProperty(JRE_CONNECT_TIMEOUT_PROPERTY);
if (existingTimeout == null) {
System.setProperty(JRE_CONNECT_TIMEOUT_PROPERTY, DEFAULT_CONNECT_TIMEOUT);
}
existingTimeout = System.getProperty(JRE_READ_TIMEOUT_PROPERTY);
if (existingTimeout == null) {
System.setProperty(JRE_READ_TIMEOUT_PROPERTY, DEFAULT_READ_TIMEOUT);
}
}
/* (non-Javadoc)
* @see org.eclipse.ecf.provider.filetransfer.browse.AbstractFileSystemBrowser#runRequest()
*/
protected void runRequest() throws Exception {
int code = -1;
try {
setupProxies();
setupAuthentication();
setupTimeouts();
URLConnection urlConnection = directoryOrFile.openConnection();
// set cache to off if using jar protocol
// this is for addressing bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=235933
if (directoryOrFile.getProtocol().equalsIgnoreCase("jar")) { //$NON-NLS-1$
urlConnection.setUseCaches(false);
}
// Add http 1.1 'Connection: close' header in order to potentially avoid
// server issue described here https://bugs.eclipse.org/bugs/show_bug.cgi?id=234916#c13
// See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=247197
// also see http 1.1 rfc section 14-10 in http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
urlConnection.setRequestProperty("Connection", "close"); //$NON-NLS-1$ //$NON-NLS-2$
IURLConnectionModifier connectionModifier = Activator.getDefault().getURLConnectionModifier();
if (connectionModifier != null) {
connectionModifier.setSocketFactoryForConnection(urlConnection);
}
InputStream ins = urlConnection.getInputStream();
code = getResponseCode(urlConnection);
ins.close();
if (isHTTP()) {
if (code == HttpURLConnection.HTTP_OK) {
// do nothing
} else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
throw new BrowseFileTransferException(NLS.bind("File not found: {0}", directoryOrFile.toString()), code); //$NON-NLS-1$
} else if (code == HttpURLConnection.HTTP_UNAUTHORIZED) {
throw new BrowseFileTransferException("Unauthorized", code); //$NON-NLS-1$
} else if (code == HttpURLConnection.HTTP_FORBIDDEN) {
throw new BrowseFileTransferException("Forbidden", code); //$NON-NLS-1$
} else if (code == HttpURLConnection.HTTP_PROXY_AUTH) {
throw new BrowseFileTransferException("Proxy auth required", code); //$NON-NLS-1$
} else {
throw new BrowseFileTransferException(NLS.bind("General connection error with response code={0}", new Integer(code)), code); //$NON-NLS-1$
}
}
remoteFiles = new IRemoteFile[1];
remoteFiles[0] = new URLRemoteFile(urlConnection.getLastModified(), urlConnection.getContentLength(), fileID);
} catch (Exception e) {
Exception except = (e instanceof BrowseFileTransferException) ? e : new BrowseFileTransferException(NLS.bind("Could not connect to {0}", directoryOrFile), e, code); //$NON-NLS-1$
throw except;
}
}
private boolean isHTTP() {
final String protocol = directoryOrFile.getProtocol();
if (protocol.equalsIgnoreCase("http") || protocol.equalsIgnoreCase("https")) //$NON-NLS-1$ //$NON-NLS-2$
return true;
return false;
}
private int getResponseCode(URLConnection urlConnection) {
int responseCode = -1;
String response = urlConnection.getHeaderField(0);
if (response == null) {
responseCode = -1;
return responseCode;
}
if (!response.startsWith("HTTP/")) //$NON-NLS-1$
return -1;
response = response.trim();
final int mark = response.indexOf(" ") + 1; //$NON-NLS-1$
if (mark == 0)
return -1;
int last = mark + 3;
if (last > response.length())
last = response.length();
responseCode = Integer.parseInt(response.substring(mark, last));
return responseCode;
}
protected void setupAuthentication() throws IOException, UnsupportedCallbackException {
if (connectContext == null)
return;
final CallbackHandler callbackHandler = connectContext.getCallbackHandler();
if (callbackHandler == null)
return;
final NameCallback usernameCallback = new NameCallback(USERNAME_PREFIX);
final ObjectCallback passwordCallback = new ObjectCallback();
// Call callback with username and password callbacks
callbackHandler.handle(new Callback[] {usernameCallback, passwordCallback});
username = usernameCallback.getName();
Object o = passwordCallback.getObject();
if (!(o instanceof String))
throw new UnsupportedCallbackException(passwordCallback, Messages.UrlConnectionRetrieveFileTransfer_UnsupportedCallbackException);
password = (String) passwordCallback.getObject();
// Now set authenticator to our authenticator with user and password
Authenticator.setDefault(new UrlConnectionAuthenticator());
}
class UrlConnectionAuthenticator extends Authenticator {
/* (non-Javadoc)
* @see java.net.Authenticator#getPasswordAuthentication()
*/
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
}
protected void setupProxy(final Proxy proxy2) {
proxyHelper.setupProxy(proxy2);
}
}