org.apache.wink.common.internal.registry.ContextAccessor Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.wink.common.internal.registry;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Providers;
import org.apache.wink.common.RuntimeContext;
import org.apache.wink.common.internal.runtime.RuntimeContextTLS;
public class ContextAccessor {
public T getContext(Class contextClass, RuntimeContext runtimeContext) {
// try to get a context from a ContextResolver
T context = getContextFromResolver(contextClass, runtimeContext);
if (context != null) {
return context;
}
// get a context from one of the message context accessors
return getContextFromAccessor(contextClass, runtimeContext);
}
/**
* Obtain a context from one of the contexts available through the
* RuntimeContext. This can be done in two ways: if runtimeContext is
* provided, the context is obtained directly. If runtimeContext is null,
* then a proxy is created which obtains the RuntimeContext using the TLS.
*
* @param - interface of the context
* @param contextClass - interface of the context
* @param runtimeContext - RuntimeContext
* @return instance of T if context was found or null otherwise.
*/
@SuppressWarnings("unchecked")
public T getContextFromAccessor(final Class contextClass, RuntimeContext runtimeContext) {
// return context directly
if (runtimeContext != null) {
try {
T instance = runtimeContext.getAttribute(contextClass);
if (instance != null) {
return instance;
}
/*
* if the instance isn't directly available from the
* runtimecontext at this time, inject a proxy instead. This
* allows context attributes to be added after a class is
* instantiated
*/
} catch (Exception e) {
if (e instanceof InvocationTargetException) {
Throwable ite = ((InvocationTargetException)e).getTargetException();
if (ite instanceof RuntimeException) {
throw (RuntimeException)ite;
}
throw new WebApplicationException(ite);
}
throw new WebApplicationException(e);
}
}
// return a proxy that looks for a context on TLS during the method
// invocation
T proxy =
(T)Proxy.newProxyInstance(Injectable.class.getClassLoader(),
new Class[] {contextClass},
new InvocationHandler() {
public Object invoke(Object proxy,
Method method,
Object[] args) throws Throwable {
// use runtimeContext from TLS
RuntimeContext runtimeContext =
RuntimeContextTLS.getRuntimeContext();
if (runtimeContext == null) {
if("toString".equals(method.getName()) && (args == null || args.length == 0)) {
return "Proxy for " + contextClass.getName();
}
throw new IllegalStateException();
}
// get the real context from the
// RuntimeContext
// We need to call getContext() instead of getContextFromAccessor() as some context will be created from the context resolvers
Object context = getContext(contextClass, runtimeContext);
// invoke the method on the real
// context
return method.invoke(context, args);
}
});
return proxy;
}
/**
* Get a context from on of the registered context providers
*
* @param type
* @param runtimeContext
* @return
*/
public T getContextFromResolver(Class contextClass, RuntimeContext runtimeContext) {
if (runtimeContext == null) {
return null;
}
Providers providers = runtimeContext.getProviders();
if (providers != null) {
HttpHeaders httpHeaders = runtimeContext.getHttpHeaders();
MediaType mediaType = null;
if (httpHeaders != null) {
// this is hotfix for WINK-166
mediaType = httpHeaders.getMediaType();
}
if (mediaType == null) {
mediaType = MediaType.WILDCARD_TYPE;
}
ContextResolver contextResolver =
providers.getContextResolver(contextClass, mediaType);
if (contextResolver != null) {
T context = contextResolver.getContext(contextClass);
if (context != null) {
return context;
}
}
}
return null;
}
}