Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.google.web.bindery.requestfactory.server.ServiceLayerCache Maven / Gradle / Ivy
/*
* Copyright 2010 Google Inc.
*
* 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 com.google.web.bindery.requestfactory.server;
import com.google.gwt.rpc.server.Pair;
import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.Locator;
import com.google.web.bindery.requestfactory.shared.ServiceLocator;
import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* A cache for idempotent methods in {@link ServiceLayer}. The caching is
* separate from {@link ReflectiveServiceLayer} so that the cache can be applied
* to any decorators injected by the user.
*/
class ServiceLayerCache extends ServiceLayerDecorator {
/**
* ConcurrentHashMaps don't allow null keys or values, but sometimes we want
* to cache a null value.
*/
private static final Object NULL_MARKER = new Object();
private static SoftReference>> methodCache;
private static final Method createLocator;
private static final Method createServiceInstance;
private static final Method getDomainClassLoader;
private static final Method getGetter;
private static final Method getIdType;
private static final Method getRequestReturnType;
private static final Method getSetter;
private static final Method requiresServiceLocator;
private static final Method resolveClass;
private static final Method resolveClientType;
private static final Method resolveDomainClass;
private static final Method resolveDomainMethod;
private static final Method resolveLocator;
private static final Method resolveRequestContextMethod;
private static final Method resolveServiceLocator;
private static final Method resolveTypeToken;
static {
createLocator = getMethod("createLocator", Class.class);
createServiceInstance = getMethod("createServiceInstance", Method.class, Method.class);
getDomainClassLoader = getMethod("getDomainClassLoader");
getGetter = getMethod("getGetter", Class.class, String.class);
getIdType = getMethod("getIdType", Class.class);
getRequestReturnType = getMethod("getRequestReturnType", Method.class);
getSetter = getMethod("getSetter", Class.class, String.class);
requiresServiceLocator = getMethod("requiresServiceLocator", Method.class, Method.class);
resolveClass = getMethod("resolveClass", String.class);
resolveClientType = getMethod("resolveClientType", Class.class, Class.class, boolean.class);
resolveDomainClass = getMethod("resolveDomainClass", Class.class);
resolveDomainMethod = getMethod("resolveDomainMethod", Method.class);
resolveLocator = getMethod("resolveLocator", Class.class);
resolveRequestContextMethod =
getMethod("resolveRequestContextMethod", String.class, String.class);
resolveServiceLocator = getMethod("resolveServiceLocator", Method.class, Method.class);
resolveTypeToken = getMethod("resolveTypeToken", Class.class);
}
private static Map> getCache() {
Map> toReturn = methodCache == null ? null : methodCache.get();
if (toReturn == null) {
toReturn = new ConcurrentHashMap>();
methodCache = new SoftReference>>(toReturn);
}
return toReturn;
}
private static Method getMethod(String name, Class>... argTypes) {
try {
return ServiceLayer.class.getMethod(name, argTypes);
} catch (SecurityException e) {
throw new RuntimeException("Could not set up ServiceLayerCache Methods", e);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Could not set up ServiceLayerCache Methods", e);
}
}
private final Map> methodMap = getCache();
@Override
public > T createLocator(Class clazz) {
return getOrCache(createLocator, clazz, clazz, clazz);
}
@Override
public Object createServiceInstance(Method contextMethod, Method domainMethod) {
return getOrCache(createServiceInstance, new Pair(contextMethod, domainMethod),
Object.class, contextMethod, domainMethod);
}
@Override
public ClassLoader getDomainClassLoader() {
return getOrCache(getDomainClassLoader, NULL_MARKER, ClassLoader.class);
}
@Override
public Method getGetter(Class> domainType, String property) {
return getOrCache(getGetter, new Pair, String>(domainType, property), Method.class,
domainType, property);
}
@Override
public Class> getIdType(Class> domainType) {
return getOrCache(getIdType, domainType, Class.class, domainType);
}
@Override
public Type getRequestReturnType(Method contextMethod) {
return getOrCache(getRequestReturnType, contextMethod, Type.class, contextMethod);
}
@Override
public Method getSetter(Class> domainType, String property) {
return getOrCache(getSetter, new Pair, String>(domainType, property), Method.class,
domainType, property);
}
@Override
public boolean requiresServiceLocator(Method contextMethod, Method domainMethod) {
return getOrCache(requiresServiceLocator,
new Pair(contextMethod, domainMethod), Boolean.class, contextMethod,
domainMethod);
}
@Override
public Class extends BaseProxy> resolveClass(String typeToken) {
Class> found = getOrCache(resolveClass, typeToken, Class.class, typeToken);
return found.asSubclass(BaseProxy.class);
}
@Override
public Class extends T> resolveClientType(Class> domainClass, Class clientType,
boolean required) {
Class> clazz =
getOrCache(resolveClientType, new Pair, Class>>(domainClass, clientType),
Class.class, domainClass, clientType, required);
return clazz == null ? null : clazz.asSubclass(clientType);
}
@Override
public Class> resolveDomainClass(Class> clazz) {
return getOrCache(resolveDomainClass, clazz, Class.class, clazz);
}
@Override
public Method resolveDomainMethod(Method requestContextMethod) {
return getOrCache(resolveDomainMethod, requestContextMethod, Method.class, requestContextMethod);
}
@Override
@SuppressWarnings("unchecked")
public Class extends Locator, ?>> resolveLocator(Class> domainType) {
return getOrCache(resolveLocator, domainType, Class.class, domainType);
}
@Override
public Method resolveRequestContextMethod(String requestContextClass, String methodName) {
return getOrCache(resolveRequestContextMethod, new Pair(requestContextClass,
methodName), Method.class, requestContextClass, methodName);
}
@Override
public Class extends ServiceLocator> resolveServiceLocator(Method contextMethod,
Method domainMethod) {
Class> clazz =
getOrCache(resolveServiceLocator, new Pair(contextMethod, domainMethod),
Class.class, contextMethod, domainMethod);
return clazz == null ? null : clazz.asSubclass(ServiceLocator.class);
}
@Override
public String resolveTypeToken(Class extends BaseProxy> domainClass) {
return getOrCache(resolveTypeToken, domainClass, String.class, domainClass);
}
private T getOrCache(Method method, K key, Class valueType, Object... args) {
Map map = methodMap.get(method);
if (map == null) {
map = new ConcurrentHashMap();
methodMap.put(method, map);
}
Object raw = map.get(key);
if (raw == NULL_MARKER) {
return null;
}
T toReturn = valueType.cast(raw);
if (toReturn == null) {
Throwable ex = null;
try {
toReturn = valueType.cast(method.invoke(getNext(), args));
map.put(key, toReturn == null ? NULL_MARKER : toReturn);
} catch (InvocationTargetException e) {
// The next layer threw an exception
Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
// Re-throw RuntimeExceptions, which likely originate from die()
throw ((RuntimeException) cause);
}
die(cause, "Unexpected checked exception");
} catch (IllegalArgumentException e) {
ex = e;
} catch (IllegalAccessException e) {
ex = e;
}
if (ex != null) {
die(ex, "Bad method invocation");
}
}
return toReturn;
}
}