| /* |
| * 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.web.bindery.requestfactory.shared.BaseProxy; |
| import com.google.web.bindery.requestfactory.shared.Locator; |
| import com.google.web.bindery.requestfactory.shared.ProxyFor; |
| import com.google.web.bindery.requestfactory.shared.ProxyForName; |
| import com.google.web.bindery.requestfactory.shared.Request; |
| import com.google.web.bindery.requestfactory.shared.RequestContext; |
| import com.google.web.bindery.requestfactory.shared.Service; |
| import com.google.web.bindery.requestfactory.shared.ServiceLocator; |
| import com.google.web.bindery.requestfactory.shared.ServiceName; |
| |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Modifier; |
| |
| /** |
| * Adds support to the ServiceLayer chain for using {@link Locator} and |
| * {@link ServiceLocator} helper objects. |
| */ |
| final class LocatorServiceLayer extends ServiceLayerDecorator { |
| |
| @Override |
| public <T> T createDomainObject(Class<T> clazz) { |
| Locator<T, ?> l = getLocator(clazz); |
| if (l == null) { |
| return super.createDomainObject(clazz); |
| } |
| return l.create(clazz); |
| } |
| |
| @Override |
| public <T extends Locator<?, ?>> T createLocator(Class<T> clazz) { |
| return newInstance(clazz, Locator.class); |
| } |
| |
| @Override |
| public Object createServiceInstance(Class<? extends RequestContext> requestContext) { |
| Class<? extends ServiceLocator> locatorType = getTop().resolveServiceLocator(requestContext); |
| ServiceLocator locator = getTop().createServiceLocator(locatorType); |
| Class<?> serviceClass = getTop().resolveServiceClass(requestContext); |
| return locator.getInstance(serviceClass); |
| } |
| |
| @Override |
| public <T extends ServiceLocator> T createServiceLocator(Class<T> serviceLocatorType) { |
| return newInstance(serviceLocatorType, ServiceLocator.class); |
| } |
| |
| @Override |
| public Object getId(Object domainObject) { |
| return doGetId(domainObject); |
| } |
| |
| @Override |
| public Class<?> getIdType(Class<?> domainType) { |
| Locator<?, ?> l = getLocator(domainType); |
| if (l == null) { |
| return super.getIdType(domainType); |
| } |
| return l.getIdType(); |
| } |
| |
| @Override |
| public Object getVersion(Object domainObject) { |
| return doGetVersion(domainObject); |
| } |
| |
| @Override |
| public boolean isLive(Object domainObject) { |
| return doIsLive(domainObject); |
| } |
| |
| @Override |
| public <T> T loadDomainObject(Class<T> clazz, Object domainId) { |
| return doLoadDomainObject(clazz, domainId); |
| } |
| |
| /** |
| * Returns true if the context method returns a {@link Request} and the domain |
| * method is non-static. |
| */ |
| @Override |
| public boolean requiresServiceLocator(Method contextMethod, Method domainMethod) { |
| return Request.class.isAssignableFrom(contextMethod.getReturnType()) |
| && !Modifier.isStatic(domainMethod.getModifiers()); |
| } |
| |
| @Override |
| public Class<? extends Locator<?, ?>> resolveLocator(Class<?> domainType) { |
| // Find the matching BaseProxy |
| Class<?> proxyType = getTop().resolveClientType(domainType, BaseProxy.class, false); |
| if (proxyType == null) { |
| return null; |
| } |
| |
| // Check it for annotations |
| Class<? extends Locator<?, ?>> locatorType; |
| ProxyFor l = proxyType.getAnnotation(ProxyFor.class); |
| ProxyForName ln = proxyType.getAnnotation(ProxyForName.class); |
| if (l != null && !Locator.class.equals(l.locator())) { |
| @SuppressWarnings("unchecked") |
| Class<? extends Locator<?, ?>> found = (Class<? extends Locator<?, ?>>) l.locator(); |
| locatorType = found; |
| } else if (ln != null && ln.locator().length() > 0) { |
| try { |
| @SuppressWarnings("unchecked") |
| Class<? extends Locator<?, ?>> found = |
| (Class<? extends Locator<?, ?>>) Class.forName(ln.locator(), false, |
| getTop().getDomainClassLoader()).asSubclass(Locator.class); |
| locatorType = found; |
| } catch (ClassNotFoundException e) { |
| return die(e, "Could not find the locator type specified in the @%s annotation %s", |
| ProxyForName.class.getCanonicalName(), ln.value()); |
| } |
| } else { |
| // No locator annotation |
| locatorType = null; |
| } |
| return locatorType; |
| } |
| |
| @Override |
| public Class<? extends ServiceLocator> resolveServiceLocator( |
| Class<? extends RequestContext> requestContext) { |
| Class<? extends ServiceLocator> locatorType; |
| |
| Service l = requestContext.getAnnotation(Service.class); |
| ServiceName ln = requestContext.getAnnotation(ServiceName.class); |
| if (l != null && !ServiceLocator.class.equals(l.locator())) { |
| locatorType = l.locator(); |
| } else if (ln != null && ln.locator().length() > 0) { |
| try { |
| locatorType = |
| Class.forName(ln.locator(), false, getTop().getDomainClassLoader()).asSubclass( |
| ServiceLocator.class); |
| } catch (ClassNotFoundException e) { |
| return die(e, "Could not find the locator type specified in the @%s annotation %s", |
| ServiceName.class.getCanonicalName(), ln.value()); |
| } |
| } else { |
| locatorType = null; |
| } |
| return locatorType; |
| } |
| |
| private <T> Object doGetId(T domainObject) { |
| @SuppressWarnings("unchecked") |
| Class<T> clazz = (Class<T>) domainObject.getClass(); |
| Locator<T, ?> l = getLocator(clazz); |
| if (l == null) { |
| return super.getId(domainObject); |
| } |
| return l.getId(domainObject); |
| } |
| |
| private <T> Object doGetVersion(T domainObject) { |
| @SuppressWarnings("unchecked") |
| Class<T> clazz = (Class<T>) domainObject.getClass(); |
| Locator<T, ?> l = getLocator(clazz); |
| if (l == null) { |
| return super.getVersion(domainObject); |
| } |
| return l.getVersion(domainObject); |
| } |
| |
| private <T> boolean doIsLive(T domainObject) { |
| @SuppressWarnings("unchecked") |
| Class<T> clazz = (Class<T>) domainObject.getClass(); |
| Locator<T, ?> l = getLocator(clazz); |
| if (l == null) { |
| return super.isLive(domainObject); |
| } |
| return l.isLive(domainObject); |
| } |
| |
| private <T, I> T doLoadDomainObject(Class<T> clazz, Object domainId) { |
| @SuppressWarnings("unchecked") |
| Locator<T, I> l = (Locator<T, I>) getLocator(clazz); |
| if (l == null) { |
| return super.loadDomainObject(clazz, domainId); |
| } |
| I id = l.getIdType().cast(domainId); |
| return l.find(clazz, id); |
| } |
| |
| @SuppressWarnings("unchecked") |
| private <T, I> Locator<T, I> getLocator(Class<T> domainType) { |
| Class<? extends Locator<?, ?>> locatorType = getTop().resolveLocator(domainType); |
| if (locatorType == null) { |
| return null; |
| } |
| return (Locator<T, I>) getTop().createLocator(locatorType); |
| } |
| |
| private <T> T newInstance(Class<T> clazz, Class<? super T> base) { |
| Throwable ex; |
| try { |
| return clazz.newInstance(); |
| } catch (InstantiationException e) { |
| ex = e; |
| } catch (IllegalAccessException e) { |
| ex = e; |
| } |
| return this.<T> die(ex, "Could not instantiate %s %s. Is it default-instantiable?", base |
| .getSimpleName(), clazz.getCanonicalName()); |
| } |
| } |