Java tutorial
/* * Copyright (c) 2013 Google Inc. * Copyright (c) 2016 WisePersist.org * * 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 org.wisepersist.gwtmockito.ng.fakes; import com.google.gwt.core.client.GWT; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; import com.google.gwt.resources.client.ResourceCallback; import com.google.gwt.resources.client.ResourcePrototype; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.google.gwt.safehtml.shared.SafeUri; import com.google.gwt.safehtml.shared.UriUtils; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; /** * Provides fake implementations of {@link ClientBundle}s. Any methods in the * bundle returning {@link CssResource}s will GWT.create the {@link CssResource} * (which by default will cause it to be generated by * {@link FakeMessagesProvider}. Other types of resources will be generated to * return unique values from their getText() or getSafeUri() methods. * * @author ekuefler@google.com (Erik Kuefler) */ public class FakeClientBundleProvider implements FakeProvider<ClientBundle> { /** * Returns a new instance of the given type that implements methods as * described in the class description. * * @param type Interface to be implemented by the returned type. */ @Override public final ClientBundle getFake(final Class<?> type) { return (ClientBundle) createNewProxyInstance(type, new InvocationHandler() { @Override public Object invoke(final Object proxy, final Method method, final Object[] args) //NOPMD throws Exception { final Class<?> returnType = method.getReturnType(); final Object result; if (CssResource.class.isAssignableFrom(returnType)) { result = GWT.create(returnType); } else { result = createFakeResource(returnType, method.getName()); } return result; } }); } /** * Creates a new proxy instance with type and invocation handler specified. * * @param type The type specified. * @param handler The invocation handler specified. * @param <T> The generic type specified. * @return The proxy instance created. */ @SuppressWarnings("unchecked") // safe since the proxy implements type private <T> T createNewProxyInstance(final Class<T> type, final InvocationHandler handler) { return (T) Proxy.newProxyInstance(FakeClientBundleProvider.class.getClassLoader(), new Class<?>[] { type }, handler); //NOPMD } /** * Creates a fake resource class that returns its own name where possible. * * @param type The type specified. * @param name The name specified. * @param <T> The generic type specified. * @return Fake resource created. */ @SuppressWarnings("unchecked") // safe since the proxy implements type private <T> T createFakeResource(final Class<T> type, final String name) { return createNewProxyInstance(type, new InvocationHandler() { @Override public Object invoke(final Object proxy, final Method method, final Object[] args) //NOPMD throws Exception { return doInvoke(method, args, name); } }); } /** * Fake invoking on a specified method with arguments. * * @param method The method specified. * @param args The arguments specified. * @param name The name specified. * @return The result object. */ private Object doInvoke(final Method method, final Object[] args, final String name) { final Object result; final Class<?> returnType = method.getReturnType(); if (returnType == String.class) { result = name; } else if (returnType == SafeHtml.class) { result = SafeHtmlUtils.fromTrustedString(name); } else if (returnType == SafeUri.class) { result = UriUtils.fromTrustedString(name); } else if (returnType == boolean.class) { result = false; } else if (returnType == int.class) { result = 0; } else if (method.getParameterTypes()[0] == ResourceCallback.class) { result = createFakeForResourceCallback(args[0], name); } else { throw new IllegalArgumentException("Unexpected return type for method " + method.getName()); } return result; } /** * Creates fake resource for {@link ResourceCallback}. * * @param arg The object arg specified. * @param name The name specified. * @return Null object as nothing need to be returned. */ @SuppressWarnings("unchecked") // safe since the proxy implements type private Object createFakeForResourceCallback(final Object arg, final String name) { // Read the underlying resource type out of the generic parameter // in the method's argument final Class<?> resourceType = (Class<?>) ((ParameterizedType) arg.getClass().getGenericInterfaces()[0]) .getActualTypeArguments()[0]; ((ResourceCallback<ResourcePrototype>) arg) .onSuccess((ResourcePrototype) createFakeResource(resourceType, name)); return null; } }