/* * 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.RequestContext; import com.google.web.bindery.requestfactory.shared.RequestFactory; import com.google.web.bindery.requestfactory.shared.ServiceLocator; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.validation.ConstraintViolation; /** * Users that intend to alter how RequestFactory interacts with the domain * environment can extend this type and provide it to * {@link ServiceLayer#create(ServiceLayerDecorator...)}. The methods defined in * this type will automatically delegate to the next decorator or the root * service object after being processed by{@code create()}. */ public class ServiceLayerDecorator extends ServiceLayer { private static final Logger log = Logger.getLogger(ServiceLayer.class.getName()); /** * A pointer to the next deepest layer. */ ServiceLayer next; @Override public <T> T createDomainObject(Class<T> clazz) { return getNext().createDomainObject(clazz); } @Override public <T extends Locator<?, ?>> T createLocator(Class<T> clazz) { return getNext().createLocator(clazz); } @Override public Object createServiceInstance(Class<? extends RequestContext> requestContext) { return getNext().createServiceInstance(requestContext); } @Override public <T extends ServiceLocator> T createServiceLocator(Class<T> clazz) { return getNext().createServiceLocator(clazz); } @Override public ClassLoader getDomainClassLoader() { return getNext().getDomainClassLoader(); } @Override public Method getGetter(Class<?> domainType, String property) { return getNext().getGetter(domainType, property); } @Override public Object getId(Object domainObject) { return getNext().getId(domainObject); } @Override public Class<?> getIdType(Class<?> domainType) { return getNext().getIdType(domainType); } @Override public Object getProperty(Object domainObject, String property) { return getNext().getProperty(domainObject, property); } @Override public Type getRequestReturnType(Method contextMethod) { return getNext().getRequestReturnType(contextMethod); } @Override public Method getSetter(Class<?> domainType, String property) { return getNext().getSetter(domainType, property); } @Override public Object getVersion(Object domainObject) { return getNext().getVersion(domainObject); } @Override public Object invoke(Method domainMethod, Object... args) { return getNext().invoke(domainMethod, args); } @Override public boolean isLive(Object domainObject) { return getNext().isLive(domainObject); } @Override public <T> T loadDomainObject(Class<T> clazz, Object domainId) { return getNext().loadDomainObject(clazz, domainId); } @Override public List<Object> loadDomainObjects(List<Class<?>> classes, List<Object> domainIds) { return getNext().loadDomainObjects(classes, domainIds); } @Override public boolean requiresServiceLocator(Method contextMethod, Method domainMethod) { return getNext().requiresServiceLocator(contextMethod, domainMethod); } @Override public Class<? extends BaseProxy> resolveClass(String typeToken) { return getNext().resolveClass(typeToken); } @Override public <T> Class<? extends T> resolveClientType(Class<?> domainClass, Class<T> clientType, boolean required) { return getNext().resolveClientType(domainClass, clientType, required); } @Override public Class<?> resolveDomainClass(Class<?> clazz) { return getNext().resolveDomainClass(clazz); } @Override public Method resolveDomainMethod(String operation) { return getNext().resolveDomainMethod(operation); } @Override public Class<? extends Locator<?, ?>> resolveLocator(Class<?> domainType) { return getNext().resolveLocator(domainType); } @Override public Class<? extends RequestContext> resolveRequestContext(String operation) { return getNext().resolveRequestContext(operation); } @Override public Method resolveRequestContextMethod(String operation) { return getNext().resolveRequestContextMethod(operation); } @Override public Class<? extends RequestFactory> resolveRequestFactory(String binaryName) { return getNext().resolveRequestFactory(binaryName); } @Override public Class<?> resolveServiceClass(Class<? extends RequestContext> requestContextClass) { return getNext().resolveServiceClass(requestContextClass); } @Override public Class<? extends ServiceLocator> resolveServiceLocator( Class<? extends RequestContext> requestContext) { return getNext().resolveServiceLocator(requestContext); } @Override public String resolveTypeToken(Class<? extends BaseProxy> proxyType) { return getNext().resolveTypeToken(proxyType); } @Override public void setProperty(Object domainObject, String property, Class<?> expectedType, Object value) { getNext().setProperty(domainObject, property, expectedType, value); } @Override public <T> Set<ConstraintViolation<T>> validate(T domainObject) { return getNext().validate(domainObject); } /** * Throw a fatal error up into the top-level processing code. This method * should be used to provide diagnostic information that will help the * end-developer track down problems when that data would expose * implementation details of the server to the client. * * @param e a throwable with more data, may be {@code null} * @param message a printf-style format string * @param args arguments for the message * @throws UnexpectedException this method never returns normally * @see #report(String, Object...) */ protected final <T> T die(Throwable e, String message, Object... args) throws UnexpectedException { String msg = String.format(message, args); log.log(Level.SEVERE, msg, e); throw new UnexpectedException(msg, e); } /** * Returns the top-most service layer. General-purpose ServiceLayer decorators * should use the instance provided by {@code getTop()} when calling public * methods on the ServiceLayer API to allow higher-level decorators to * override behaviors built into lower-level decorators. * * @return the ServiceLayer returned by * {@link #create(ServiceLayerDecorator...)} */ protected final ServiceLayer getTop() { return top; } /** * Report an exception thrown by code that is under the control of the * end-developer. * * @param userGeneratedException an {@link InvocationTargetException} thrown * by an invocation of user-provided code * @throws ReportableException this method never returns normally */ protected final <T> T report(InvocationTargetException userGeneratedException) throws ReportableException { throw new ReportableException(userGeneratedException.getCause()); } /** * Return a message to the client. This method should not include any data * that was not sent to the server by the client to avoid leaking data. * * @param msg a printf-style format string * @param args arguments for the message * @throws ReportableException this method never returns normally * @see #die(Throwable, String, Object...) */ protected final <T> T report(String msg, Object... args) throws ReportableException { throw new ReportableException(String.format(msg, args)); } /** * Retrieves the next service layer. Used only by the server-package code and * accessed by used code via {@code super.doSomething()}. */ final ServiceLayer getNext() { if (next == null) { // Unexpected, all methods should be implemented by some layer throw new UnsupportedOperationException(); } return next; } }