/* ********************************************************************** **
** Copyright notice **
** **
** (c) 2005-2006 RSSOwl Development Team **
** http://www.rssowl.org/ **
** **
** 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.rssowl.org/legal/epl-v10.html **
** **
** A copy is found in the file epl-v10.html and important notices to the **
** license from the team is found in the textfile LICENSE.txt distributed **
** in this package. **
** **
** This copyright notice MUST APPEAR in all copies of the file! **
** **
** Contributors: **
** RSSOwl Development Team - initial API and implementation **
** **
** ********************************************************************** */
package org.rssowl.core.connection;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.Platform;
import org.osgi.service.url.URLConstants;
import org.osgi.service.url.URLStreamHandlerService;
import org.rssowl.core.connection.auth.CredentialsException;
import org.rssowl.core.connection.auth.ICredentials;
import org.rssowl.core.connection.auth.ICredentialsProvider;
import org.rssowl.core.connection.auth.IProxyCredentials;
import org.rssowl.core.connection.internal.Activator;
import org.rssowl.core.connection.internal.DefaultCredentialsProvider;
import org.rssowl.core.model.NewsModel;
import org.rssowl.core.model.events.FeedAdapter;
import org.rssowl.core.model.events.FeedEvent;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
/**
* The ConnectionManager is the main class of the connection plugin. It is
* responsible to retrieve the contents of a Feed by supplying an InputStream.
*
* @author bpasero
*/
public class ConnectionManager {
/* ID of the contributed ProtocolHandlers */
private static final String PROTHANDLER_EXTENSION_POINT = "org.rssowl.core.connection.ProtocolHandler"; //$NON-NLS-1$
/* ID of the contributed CredentialsProviders */
private static final String CREDPROVIDER_EXTENSION_POINT = "org.rssowl.core.connection.CredentialsProvider"; //$NON-NLS-1$
private static ConnectionManager fInstance;
private Map<String, IProtocolHandler> fProtocolHandler;
private ICredentialsProvider fCredentialsProvider;
private FeedAdapter fFeedListener;
private ConnectionManager() {
fProtocolHandler = new HashMap<String, IProtocolHandler>();
}
/**
* Get the singleton instance of ConnectionManager, responsible to retrieve
* the contents of a Feed by supplying an InputStream
*
* @return The Singleton Instance.
*/
public static ConnectionManager getDefault() {
if (fInstance == null)
fInstance = new ConnectionManager();
return fInstance;
}
/**
* Load Contributions and register Stream Handlers.
*/
public void startup() {
/* Load Contributions */
loadProtocolHandlers();
fCredentialsProvider = loadCredentialsProvider();
/* Register URL Stream Handlers to OSGI */
registerURLStreamHandlers();
/* Register Listeners */
registerListeners();
}
private void registerListeners() {
fFeedListener = new FeedAdapter() {
@Override
public void feedDeleted(Set<FeedEvent> events) {
for (FeedEvent feedEvent : events) {
URL feedUrl = feedEvent.getEntity().getLink();
try {
if (fCredentialsProvider.getAuthCredentials(feedUrl) != null)
fCredentialsProvider.deleteAuthCredentials(feedUrl);
} catch (CredentialsException e) {
Activator.getDefault().getLog().log(e.getStatus());
}
}
}
};
NewsModel.getDefault().addFeedListener(fFeedListener);
}
/**
* Unregister from Listeners
*/
public void shutdown() {
unregisterListeners();
}
private void unregisterListeners() {
NewsModel.getDefault().removeFeedListener(fFeedListener);
}
/**
* Load the Contents of the given URL by connecting to it. Delegate this call
* to tbe suitable ProtocolHandler.
*
* @param url The URL to Load.
* @return The Content of the URL as InputStream.
* @throws ConnectionException In case of an error while loading the Feed or
* in case no suitable ProtocolHandler is present.
* @see AuthenticationRequiredException
* @see NotModifiedException
*/
public InputStream load(URL url) throws ConnectionException {
return load(url, null);
}
/**
* Load the Contents of the given URL by connecting to it. Delegate this call
* to tbe suitable ProtocolHandler. The given <code>HashMap</code> may be
* used to define connection related properties as defined in
* <code>IConnectionPropertyConstants</code> for example.
*
* @param url The URL to Load.
* @param properties Connection related properties as defined in
* <code>IConnectionPropertyConstants</code> for example.
* @return The Content of the URL as InputStream.
* @throws ConnectionException In case of an error while loading the Feed or
* in case no suitable ProtocolHandler is present.
* @see AuthenticationRequiredException
* @see NotModifiedException
*/
public InputStream load(URL url, Map<Object, Object> properties) throws ConnectionException {
String protocol = url.getProtocol();
IProtocolHandler handler = fProtocolHandler.get(protocol);
/* Handler present */
if (handler != null)
return handler.load(url, properties);
/* No Handler present */
throw new UnknownProtocolException(Activator.getDefault().createErrorStatus("Could not find a matching ProtocolHandler for: " + protocol, null)); //$NON-NLS-1$
}
/**
* Returns the Credentials-Provider capable of returning Credentials for
* protected URLs and Proxy-Server.
*
* @return The Credentials-Provider.
*/
public ICredentialsProvider getCredentialsProvider() {
return fCredentialsProvider;
}
/**
* Return the Authentication Credentials for the given Feed or NULL if none.
*
* @param url The URL to check present Authentication Credentials.
* @return the Authentication Credentials for the given Feed or NULL if none.
* @throws CredentialsException In case of an error while retrieving
* Credentials for the Feed.
*/
public ICredentials getAuthCredentials(URL url) throws CredentialsException {
if (fCredentialsProvider != null) {
ICredentials credentials = fCredentialsProvider.getAuthCredentials(url);
if (credentials != null)
return credentials;
}
return null;
}
/**
* Return the Proxy Credentials for the given Feed or NULL if none.
*
* @param url The URL to check present Proxy Credentials.
* @return the Proxy Credentials for the given Feed or NULL if none.
* @throws CredentialsException In case of an error while retrieving Proxy
* Credentials.
*/
public IProxyCredentials getProxyCredentials(URL url) throws CredentialsException {
if (fCredentialsProvider != null) {
IProxyCredentials credentials = fCredentialsProvider.getProxyCredentials(url);
if (credentials != null)
return credentials;
}
return null;
}
private void loadProtocolHandlers() {
IExtensionRegistry reg = Platform.getExtensionRegistry();
IConfigurationElement elements[] = reg.getConfigurationElementsFor(PROTHANDLER_EXTENSION_POINT);
for (IConfigurationElement element : elements) {
try {
String protocol = element.getAttribute("protocol"); //$NON-NLS-1$
/* Let 3d-Party contributions override our contributions */
if (fProtocolHandler.containsKey(protocol) && element.getNamespaceIdentifier().indexOf("org.rssowl") >= 0) //$NON-NLS-1$
continue;
fProtocolHandler.put(protocol, (IProtocolHandler) element.createExecutableExtension("class"));//$NON-NLS-1$
} catch (InvalidRegistryObjectException e) {
Activator.getDefault().logError(e.getMessage(), e);
} catch (CoreException e) {
Activator.getDefault().getLog().log(e.getStatus());
}
}
}
private ICredentialsProvider loadCredentialsProvider() {
IExtensionRegistry reg = Platform.getExtensionRegistry();
IConfigurationElement elements[] = reg.getConfigurationElementsFor(CREDPROVIDER_EXTENSION_POINT);
for (IConfigurationElement element : elements) {
try {
return ((ICredentialsProvider) element.createExecutableExtension("class"));//$NON-NLS-1$
} catch (CoreException e) {
Activator.getDefault().getLog().log(e.getStatus());
}
}
/* Return Default */
return new DefaultCredentialsProvider();
}
private void registerURLStreamHandlers() {
/* Foreach Contributed Protocol */
for (String protocol : fProtocolHandler.keySet()) {
IProtocolHandler protocolHandler = fProtocolHandler.get(protocol);
/* A URLStreamHandler is provided */
try {
if (protocolHandler.getURLStreamHandler() != null) {
Hashtable<String, String[]> properties = new Hashtable<String, String[]>(1);
properties.put(URLConstants.URL_HANDLER_PROTOCOL, new String[] { protocol });
Activator.getDefault().getContext().registerService(URLStreamHandlerService.class.getName(), protocolHandler.getURLStreamHandler(), properties);
}
} catch (ConnectionException e) {
Activator.getDefault().getLog().log(e.getStatus());
}
}
}
}