/**
* Copyright 2005-2014 Restlet
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: Apache 2.0 or or EPL 1.0 (the "Licenses"). You can
* select the license that you prefer but you may not use this file except in
* compliance with one of these Licenses.
*
* You can obtain a copy of the Apache 2.0 license at
* http://www.opensource.org/licenses/apache-2.0
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://restlet.com/products/restlet-framework
*
* Restlet is a registered trademark of Restlet S.A.S.
*/
package org.restlet.ext.jaxrs.internal.wrappers.provider;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Providers;
import org.restlet.engine.util.SystemUtils;
import org.restlet.ext.jaxrs.InstantiateException;
import org.restlet.ext.jaxrs.ObjectFactory;
import org.restlet.ext.jaxrs.internal.core.ThreadLocalizedContext;
import org.restlet.ext.jaxrs.internal.exceptions.ConvertCookieParamException;
import org.restlet.ext.jaxrs.internal.exceptions.ConvertHeaderParamException;
import org.restlet.ext.jaxrs.internal.exceptions.ConvertMatrixParamException;
import org.restlet.ext.jaxrs.internal.exceptions.ConvertPathParamException;
import org.restlet.ext.jaxrs.internal.exceptions.ConvertQueryParamException;
import org.restlet.ext.jaxrs.internal.exceptions.ConvertRepresentationException;
import org.restlet.ext.jaxrs.internal.exceptions.IllegalBeanSetterTypeException;
import org.restlet.ext.jaxrs.internal.exceptions.IllegalConstrParamTypeException;
import org.restlet.ext.jaxrs.internal.exceptions.IllegalFieldTypeException;
import org.restlet.ext.jaxrs.internal.exceptions.IllegalPathParamTypeException;
import org.restlet.ext.jaxrs.internal.exceptions.IllegalTypeException;
import org.restlet.ext.jaxrs.internal.exceptions.ImplementationException;
import org.restlet.ext.jaxrs.internal.exceptions.InjectException;
import org.restlet.ext.jaxrs.internal.exceptions.MissingAnnotationException;
import org.restlet.ext.jaxrs.internal.exceptions.MissingConstructorException;
import org.restlet.ext.jaxrs.internal.exceptions.NoMessageBodyReaderException;
import org.restlet.ext.jaxrs.internal.exceptions.ProviderNotInitializableException;
import org.restlet.ext.jaxrs.internal.util.Util;
import org.restlet.ext.jaxrs.internal.wrappers.WrapperUtil;
import org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList;
/**
* @author Stephan Koops
*/
class PerRequestProviderWrapper extends AbstractProviderWrapper {
private final JaxRsProviders allProviders;
private final ExtensionBackwardMapping extensionBackwardMapping;
private final Class<?> jaxRsProviderClass;
private final Logger logger;
private final ObjectFactory objectFactory;
private final ThreadLocalizedContext tlContext;
/**
* Creates a new wrapper for a Provider and initializes the provider. If the
* given class is not a provider, an {@link IllegalArgumentException} is
* thrown.
*
* @param jaxRsProviderClass
* the JAX-RS provider class.
* @param objectFactory
* The object factory is responsible for the provider
* instantiation, if given.
* @param tlContext
* @param allProviders
* @param extensionBackwardMapping
* @param logger
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws MissingConstructorException
* @throws InstantiateException
* @throws MissingAnnotationException
* @throws WebApplicationException
* @throws IllegalConstrParamTypeException
* @throws IllegalPathParamTypeException
*/
public PerRequestProviderWrapper(final Class<?> jaxRsProviderClass,
final ObjectFactory objectFactory,
final ThreadLocalizedContext tlContext,
final JaxRsProviders allProviders,
final ExtensionBackwardMapping extensionBackwardMapping,
final Logger logger) throws IllegalArgumentException,
InvocationTargetException, MissingConstructorException,
InstantiateException, MissingAnnotationException,
WebApplicationException, IllegalConstrParamTypeException,
IllegalPathParamTypeException {
super(jaxRsProviderClass);
this.jaxRsProviderClass = jaxRsProviderClass;
this.objectFactory = objectFactory;
this.tlContext = tlContext;
this.allProviders = allProviders;
this.extensionBackwardMapping = extensionBackwardMapping;
this.logger = logger;
createInstance(); // test, if it works.
// If not, the provider class is not useable.
}
/**
* @param providerConstructor
* the constructor to use.
* @param jaxRsProviderClass
* class for exception message.
* @param tlContext
* The tread local wrapped call context
* @param allProviders
* all entity providers. <<<<<<< .mine =======
* @param allResolvers
* all available {@link ContextResolver}s. >>>>>>> .r3440
* @param extensionBackwardMapping
* the extension backward mapping
* @param logger
* the logger to use
* @throws IllegalArgumentException
* @throws InvocationTargetException
* if the constructor throws an Throwable
* @throws InstantiateException
* @throws MissingAnnotationException
* @throws WebApplicationException
* @throws IllegalConstrParamTypeException
* if one of the fields or bean setters annotated with @
* {@link Context} has a type that must not be annotated with
* @{@link Context}.
* @throws IllegalPathParamTypeException
* @throws MissingConstructorException
*/
private Object createInstance() throws IllegalArgumentException,
InvocationTargetException, InstantiateException,
MissingAnnotationException, WebApplicationException,
IllegalConstrParamTypeException, IllegalPathParamTypeException,
MissingConstructorException {
Util.checkClassConcrete(jaxRsProviderClass, "provider");
if (objectFactory != null) {
Object jaxRsProvider;
jaxRsProvider = objectFactory.getInstance(jaxRsProviderClass);
if (jaxRsProvider != null) {
return jaxRsProvider;
}
}
final Constructor<?> providerConstructor = WrapperUtil
.findJaxRsConstructor(jaxRsProviderClass, "provider");
ParameterList parameters;
try {
parameters = new ParameterList(providerConstructor, tlContext,
false, allProviders, extensionBackwardMapping, false,
logger, true);
} catch (IllegalTypeException ite) {
throw new IllegalConstrParamTypeException(ite);
}
try {
final Object[] args = parameters.get();
return WrapperUtil.createInstance(providerConstructor, args);
} catch (NoMessageBodyReaderException e) {
// should be not possible here
throw new IllegalArgumentException(
"Could not instantiate the Provider, class "
+ jaxRsProviderClass.getName(), e);
} catch (ConvertRepresentationException e) {
// should be not possible here
throw new IllegalArgumentException(
"Could not instantiate the Provider, class "
+ jaxRsProviderClass.getName(), e);
} catch (ConvertHeaderParamException e) {
// should be not possible here
throw new IllegalArgumentException(
"Could not instantiate the Provider, class "
+ jaxRsProviderClass.getName(), e);
} catch (ConvertPathParamException e) {
// should be not possible here
throw new IllegalArgumentException(
"Could not instantiate the Provider, class "
+ jaxRsProviderClass.getName(), e);
} catch (ConvertMatrixParamException e) {
// should be not possible here
throw new IllegalArgumentException(
"Could not instantiate the Provider, class "
+ jaxRsProviderClass.getName(), e);
} catch (ConvertQueryParamException e) {
// should be not possible here
throw new IllegalArgumentException(
"Could not instantiate the Provider, class "
+ jaxRsProviderClass.getName(), e);
} catch (ConvertCookieParamException e) {
// should be not possible here
throw new IllegalArgumentException(
"Could not instantiate the Provider, class "
+ jaxRsProviderClass.getName(), e);
}
}
@Override
public final boolean equals(Object otherProvider) {
if (this == otherProvider) {
return true;
}
if (!(otherProvider instanceof PerRequestProviderWrapper)) {
return false;
}
return this.jaxRsProviderClass
.equals(((PerRequestProviderWrapper) otherProvider).jaxRsProviderClass);
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.provider.ProviderWrapper#getClassName()
*/
@Override
public String getClassName() {
return this.jaxRsProviderClass.getName();
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.provider.ProviderWrapper#getExcMapperType()
*/
public Class<?> getExcMapperType() {
return Util.getGenericClass(this.jaxRsProviderClass,
ExceptionMapper.class);
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.provider.ProviderWrapper#getInitializedCtxResolver()
*/
public ContextResolver getInitializedCtxResolver()
throws ProviderNotInitializableException {
return new SingletonProvider(instantiateAndInitialize(), logger);
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.provider.ProviderWrapper#getInitializedExcMapper()
*/
@SuppressWarnings("unchecked")
public ExceptionMapper<? extends Throwable> getInitializedExcMapper()
throws ProviderNotInitializableException {
return (ExceptionMapper<? extends Throwable>) instantiateAndInitialize();
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.provider.ProviderWrapper#getInitializedReader()
*/
public org.restlet.ext.jaxrs.internal.wrappers.provider.MessageBodyReader getInitializedReader()
throws ProviderNotInitializableException {
return new SingletonProvider(instantiateAndInitialize(), logger);
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.provider.ProviderWrapper#getInitializedWriter()
*/
public org.restlet.ext.jaxrs.internal.wrappers.provider.MessageBodyWriter getInitializedWriter()
throws ProviderNotInitializableException {
return new SingletonProvider(instantiateAndInitialize(), logger);
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.provider.ProviderWrapper#hashCode()
*/
@Override
public int hashCode() {
return SystemUtils.hashCode(this.jaxRsProviderClass);
}
/**
* This method does nothing in this class.
*
* @see ProviderWrapper#initAtAppStartUp(ThreadLocalizedContext, Providers,
* ExtensionBackwardMapping)
*/
public void initAtAppStartUp(ThreadLocalizedContext tlContext,
Providers allProviders,
ExtensionBackwardMapping extensionBackwardMapping)
throws InjectException, InvocationTargetException,
IllegalTypeException {
// nothing to do here
}
/**
* Instantiates the provider class, initializes the instance and returns it
* unwrapped.
*
* @throws ProviderNotInitializableException
* @throws WebApplicationException
*/
private Object instantiateAndInitialize()
throws ProviderNotInitializableException {
Object jaxRsProvider;
try {
jaxRsProvider = createInstance();
} catch (IllegalConstrParamTypeException e) {
throw new ImplementationException(
"The provider could not be instantiated, but this could not be here",
e);
} catch (IllegalPathParamTypeException e) {
throw new ImplementationException(
"The provider could not be instantiated, but this could not be here",
e);
} catch (IllegalArgumentException e) {
throw new ImplementationException(
"The provider could not be instantiated, but this could not be here",
e);
} catch (WebApplicationException e) {
throw new ImplementationException(
"The provider could not be instantiated, but this could not be here",
e);
} catch (MissingAnnotationException e) {
throw new ImplementationException(
"The provider could not be instantiated, but this could not be here",
e);
} catch (MissingConstructorException e) {
throw new ImplementationException(
"The provider could not be instantiated, but this could not be here",
e);
} catch (InvocationTargetException e) {
throw new ImplementationException(
"The provider could not be instantiated, but this could not be here",
e);
} catch (InstantiateException e) {
throw new ImplementationException(
"The provider could not be instantiated, but this could not be here",
e);
}
try {
initProvider(jaxRsProvider, tlContext, allProviders,
extensionBackwardMapping);
} catch (IllegalFieldTypeException e) {
logger.log(Level.WARNING, "The provider " + this.getClassName()
+ " could not be initialized and so it could not be used",
e);
throw new ProviderNotInitializableException();
} catch (IllegalBeanSetterTypeException e) {
logger.log(Level.WARNING, "The provider " + this.getClassName()
+ " could not be initialized and so it could not be used",
e);
throw new ProviderNotInitializableException();
} catch (InjectException e) {
logger.log(Level.WARNING, "The provider " + this.getClassName()
+ " could not be initialized and so it could not be used",
e);
throw new ProviderNotInitializableException();
} catch (InvocationTargetException e) {
logger.log(Level.WARNING, "The provider " + this.getClassName()
+ " could not be initialized and so it could not be used",
e);
throw new ProviderNotInitializableException();
}
return jaxRsProvider;
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.provider.ProviderWrapper#isContextResolver()
*/
@Override
public boolean isContextResolver() {
return Util.doesImplement(jaxRsProviderClass,
javax.ws.rs.ext.ContextResolver.class);
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.provider.ProviderWrapper#isExceptionMapper()
*/
@Override
public boolean isExceptionMapper() {
return Util.doesImplement(jaxRsProviderClass,
javax.ws.rs.ext.ExceptionMapper.class);
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.provider.ProviderWrapper#isReader()
*/
@Override
public boolean isReader() {
return Util.doesImplement(jaxRsProviderClass,
javax.ws.rs.ext.MessageBodyReader.class);
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.provider.ProviderWrapper#isWriter()
*/
@Override
public boolean isWriter() {
return Util.doesImplement(jaxRsProviderClass,
javax.ws.rs.ext.MessageBodyWriter.class);
}
}