/*******************************************************************************
* Copyright 2012 Geoscience Australia
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package au.gov.ga.earthsci.core.retrieve;
import java.net.URL;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.annotation.PostConstruct;
import javax.inject.Singleton;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Creatable;
import org.eclipse.e4.core.di.annotations.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import au.gov.ga.earthsci.core.retrieve.retriever.DefaultRetriever;
/**
* Basic implementation of the {@link IRetrieverFactory} interface.
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
@Creatable
@Singleton
public class RetrieverFactory implements IRetrieverFactory
{
public static final String RETRIEVER_EXTENSION_POINT_ID = "au.gov.ga.earthsci.core.retrieve.retrievers"; //$NON-NLS-1$
public static final String RETRIEVER_EXTENSION_POINT_CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$
private Set<IRetriever> retrievers = new LinkedHashSet<IRetriever>();
private ReadWriteLock retrieversLock = new ReentrantReadWriteLock();
private IRetriever defaultRetriever = new DefaultRetriever();
private final static Logger logger = LoggerFactory.getLogger(RetrieverFactory.class);
/**
* Load registered {@link IRetriever}s from the provided extension registry.
* <p/>
* This method will inject dependencies on loaded classes using the provided
* eclipse context, as appropriate.
*
* @param registry
* The extension registry to search for {@link IRetriever}s
* @param context
* The context to use for dependency injection etc.
*/
@PostConstruct
public void loadRetrievers(@Optional IExtensionRegistry registry, IEclipseContext context)
{
if (registry == null)
{
logger.warn("Extension registry not found, no retrieval service retrievers are registered"); //$NON-NLS-1$
return;
}
logger.info("Registering retrieval service retrievers"); //$NON-NLS-1$
IConfigurationElement[] config = registry.getConfigurationElementsFor(RETRIEVER_EXTENSION_POINT_ID);
try
{
for (IConfigurationElement e : config)
{
final Object o = e.createExecutableExtension(RETRIEVER_EXTENSION_POINT_CLASS_ATTRIBUTE);
if (o instanceof IRetriever)
{
ContextInjectionFactory.inject(o, context);
context.set(e.getAttribute(RETRIEVER_EXTENSION_POINT_CLASS_ATTRIBUTE), o);
registerRetriever((IRetriever) o);
}
}
}
catch (CoreException e)
{
logger.error("Exception while loading retrievers", e); //$NON-NLS-1$
}
}
/**
* Register a retriever on this service instance.
*
* @param retriever
* The retriever to register
*/
@Override
public void registerRetriever(IRetriever retriever)
{
if (retriever == null)
{
return;
}
retrieversLock.writeLock().lock();
try
{
retrievers.add(retriever);
}
finally
{
retrieversLock.writeLock().unlock();
}
}
@Override
public IRetriever getRetriever(URL url)
{
if (url == null)
{
return null;
}
retrieversLock.readLock().lock();
try
{
for (IRetriever r : retrievers)
{
if (r.supports(url))
{
return r;
}
}
return getDefaultRetriever();
}
finally
{
retrieversLock.readLock().unlock();
}
}
public IRetriever getDefaultRetriever()
{
return defaultRetriever;
}
public void setDefaultRetriever(IRetriever defaultRetriever)
{
this.defaultRetriever = defaultRetriever;
}
}