blob: e7a7071f25d0ee0763e104e779dff26d7167044b [file] [log] [blame]
bobv@google.comc21149e2010-11-05 11:25:19 +00001/*
2 * Copyright 2010 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16package com.google.gwt.autobean.server;
17
18import com.google.gwt.autobean.shared.AutoBean;
19import com.google.gwt.autobean.shared.AutoBeanFactory;
20import com.google.gwt.autobean.shared.AutoBeanFactory.Category;
21import com.google.gwt.autobean.shared.AutoBeanFactory.NoWrap;
22
23import java.lang.reflect.InvocationHandler;
24import java.lang.reflect.Proxy;
25
26/**
27 * Generates JVM-compatible implementations of AutoBeanFactory and AutoBean
28 * types.
29 * <p>
30 * NB: This implementation is excessively dynamic, however, the inability to
31 * create a TypeOracle fram a ClassLoader prevents re-using the existing model
32 * code. If the model code could be reused, it would be straightforward to
33 * simply generate implementations of the various interfaces.
34 * <p>
35 * This implementation is written assuming that the AutoBeanFactory and
36 * associated declarations will validate if compiled and used with the
37 * AutoBeanFactoyModel.
38 */
39public class AutoBeanFactoryMagic {
40 /**
41 * Create an instance of an AutoBeanFactory.
42 *
43 * @param <F> the factory type
44 * @param clazz the Class representing the factory interface
45 * @return an instance of the AutoBeanFactory
46 */
47 public static <F extends AutoBeanFactory> F create(Class<F> clazz) {
48 Configuration.Builder builder = new Configuration.Builder();
49 Category cat = clazz.getAnnotation(Category.class);
50 if (cat != null) {
51 builder.setCategories(cat.value());
52 }
53 NoWrap noWrap = clazz.getAnnotation(NoWrap.class);
54 if (noWrap != null) {
55 builder.setNoWrap(noWrap.value());
56 }
57
58 return makeProxy(clazz, new FactoryHandler(builder.build()));
59 }
60
61 /**
62 * Create an instance of an AutoBean directly.
63 *
64 * @param <T> the interface type implemented by the AutoBean
65 * @param clazz the interface type implemented by the AutoBean
66 * @return an instance of an AutoBean
67 */
68 public static <T> AutoBean<T> createBean(Class<T> clazz,
69 Configuration configuration) {
70 return new ProxyAutoBean<T>(clazz, configuration);
71 }
72
73 /**
74 * Utility method to crete a new {@link Proxy} instance.
75 *
76 * @param <T> the interface type to be implemented by the Proxy
77 * @param intf the Class representing the interface type
78 * @param handler the implementation of the interface
79 * @return a Proxy instance
80 */
81 static <T> T makeProxy(Class<T> intf, InvocationHandler handler) {
82 return intf.cast(Proxy.newProxyInstance(
83 Thread.currentThread().getContextClassLoader(), new Class<?>[]{intf},
84 handler));
85 }
86}