summaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyCreatorGenerator.java
blob: 040715fccf86b1086a5867553ff5c751929b97f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
@VaadinApache2LicenseForJavaFiles@
 */
package com.vaadin.terminal.gwt.widgetsetutils;

import java.io.PrintWriter;
import java.util.Date;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import com.vaadin.terminal.gwt.client.ServerConnector;
import com.vaadin.terminal.gwt.client.communication.InitializableServerRpc;
import com.vaadin.terminal.gwt.client.communication.RpcProxy.RpcProxyCreator;
import com.vaadin.terminal.gwt.client.communication.ServerRpc;

public class RpcProxyCreatorGenerator extends Generator {

    @Override
    public String generate(TreeLogger logger, GeneratorContext ctx,
            String requestedClassName) throws UnableToCompleteException {
        logger.log(TreeLogger.DEBUG, "Running RpcProxyCreatorGenerator");
        TypeOracle typeOracle = ctx.getTypeOracle();
        assert (typeOracle != null);

        JClassType requestedType = typeOracle.findType(requestedClassName);
        String packageName = requestedType.getPackage().getName();
        String className = requestedType.getSimpleSourceName() + "Impl";
        if (requestedType == null) {
            logger.log(TreeLogger.ERROR, "Unable to find metadata for type '"
                    + requestedClassName + "'", null);
            throw new UnableToCompleteException();
        }

        createType(logger, ctx, packageName, className);
        return packageName + "." + className;
    }

    private void createType(TreeLogger logger, GeneratorContext context,
            String packageName, String className) {
        ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(
                packageName, className);

        PrintWriter printWriter = context.tryCreate(logger,
                composer.getCreatedPackage(),
                composer.getCreatedClassShortName());
        if (printWriter == null) {
            // print writer is null if source code has already been generated
            return;
        }
        Date date = new Date();
        TypeOracle typeOracle = context.getTypeOracle();

        // init composer, set class properties, create source writer
        composer.addImport(GWT.class.getCanonicalName());
        composer.addImport(ServerRpc.class.getCanonicalName());
        composer.addImport(ServerConnector.class.getCanonicalName());
        composer.addImport(InitializableServerRpc.class.getCanonicalName());
        composer.addImport(IllegalArgumentException.class.getCanonicalName());
        composer.addImplementedInterface(RpcProxyCreator.class
                .getCanonicalName());

        SourceWriter sourceWriter = composer.createSourceWriter(context,
                printWriter);
        sourceWriter.indent();

        sourceWriter
                .println("public <T extends ServerRpc> T create(Class<T> rpcInterface, ServerConnector connector) {");
        sourceWriter.indent();

        sourceWriter
                .println("if (rpcInterface == null || connector == null) {");
        sourceWriter.indent();
        sourceWriter
                .println("throw new IllegalArgumentException(\"RpcInterface and/or connector cannot be null\");");
        sourceWriter.outdent();

        JClassType initializableInterface = typeOracle.findType(ServerRpc.class
                .getCanonicalName());

        for (JClassType rpcType : initializableInterface.getSubtypes()) {
            String rpcClassName = rpcType.getQualifiedSourceName();
            if (InitializableServerRpc.class.getCanonicalName().equals(
                    rpcClassName)) {
                // InitializableClientToServerRpc is a special marker interface
                // that should not get a generated class
                continue;
            }
            sourceWriter.println("} else if (rpcInterface == " + rpcClassName
                    + ".class) {");
            sourceWriter.indent();
            sourceWriter.println(rpcClassName + " rpc = GWT.create("
                    + rpcClassName + ".class);");
            sourceWriter.println("((" + InitializableServerRpc.class.getName()
                    + ") rpc).initRpc(connector);");
            sourceWriter.println("return (T) rpc;");
            sourceWriter.outdent();
        }

        sourceWriter.println("} else {");
        sourceWriter.indent();
        sourceWriter
                .println("throw new IllegalArgumentException(\"No RpcInterface of type \"+ rpcInterface.getName() + \" was found.\");");
        sourceWriter.outdent();
        // End of if
        sourceWriter.println("}");
        // End of method
        sourceWriter.println("}");

        // close generated class
        sourceWriter.outdent();
        sourceWriter.println("}");
        // commit generated class
        context.commit(logger, printWriter);
        logger.log(Type.INFO, composer.getCreatedClassName() + " created in "
                + (new Date().getTime() - date.getTime()) / 1000 + "seconds");

    }
}