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.shared.annotations.Delayed;
import com.vaadin.shared.communication.ClientRpc;
import com.vaadin.shared.communication.ServerRpc;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.Connect.LoadStyle;
import com.vaadin.terminal.gwt.client.ServerConnector;
import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader;
+import com.vaadin.terminal.gwt.client.metadata.InvokationHandler;
+import com.vaadin.terminal.gwt.client.metadata.ProxyHandler;
+import com.vaadin.terminal.gwt.client.metadata.TypeData;
import com.vaadin.terminal.gwt.client.metadata.TypeDataBundle;
import com.vaadin.terminal.gwt.client.metadata.TypeDataStore;
import com.vaadin.terminal.gwt.widgetsetutils.metadata.ClientRpcVisitor;
import com.vaadin.terminal.gwt.widgetsetutils.metadata.ConnectorBundle;
import com.vaadin.terminal.gwt.widgetsetutils.metadata.ConnectorInitVisitor;
+import com.vaadin.terminal.gwt.widgetsetutils.metadata.ServerRpcVisitor;
import com.vaadin.terminal.gwt.widgetsetutils.metadata.StateInitVisitor;
import com.vaadin.terminal.gwt.widgetsetutils.metadata.TypeVisitor;
import com.vaadin.terminal.gwt.widgetsetutils.metadata.WidgetInitVisitor;
writeReturnTypes(w, bundle);
writeInvokers(w, bundle);
writeParamTypes(w, bundle);
+ writeProxys(w, bundle);
+ wirteDelayedInfo(w, bundle);
+ }
+
+ private void wirteDelayedInfo(SourceWriter w, ConnectorBundle bundle) {
+ Map<JClassType, Set<JMethod>> needsDelayedInfo = bundle
+ .getNeedsDelayedInfo();
+ Set<Entry<JClassType, Set<JMethod>>> entrySet = needsDelayedInfo
+ .entrySet();
+ for (Entry<JClassType, Set<JMethod>> entry : entrySet) {
+ JClassType type = entry.getKey();
+ Set<JMethod> methods = entry.getValue();
+ for (JMethod method : methods) {
+ Delayed annotation = method.getAnnotation(Delayed.class);
+ if (annotation != null) {
+ w.print("store.setDelayed(");
+ printClassLiteral(w, type);
+ w.print(", \"");
+ w.print(escape(method.getName()));
+ w.println("\");");
+
+ if (annotation.lastonly()) {
+ w.print("store.setLastonly(");
+ printClassLiteral(w, type);
+ w.print(", \"");
+ w.print(escape(method.getName()));
+ w.println("\");");
+ }
+ }
+ }
+ }
+ }
+
+ private void writeProxys(SourceWriter w, ConnectorBundle bundle) {
+ Set<JClassType> needsProxySupport = bundle.getNeedsProxySupport();
+ for (JClassType type : needsProxySupport) {
+ w.print("store.setProxyHandler(");
+ printClassLiteral(w, type);
+ w.print(", new ");
+ w.print(ProxyHandler.class.getCanonicalName());
+ w.println("() {");
+ w.indent();
+
+ w.println("public Object createProxy(final "
+ + InvokationHandler.class.getName() + " handler) {");
+ w.indent();
+
+ w.print("return new ");
+ w.print(type.getQualifiedSourceName());
+ w.println("() {");
+ w.indent();
+
+ JMethod[] methods = type.getOverridableMethods();
+ for (JMethod method : methods) {
+ if (method.isAbstract()) {
+ w.print("public ");
+ w.print(method.getReturnType().getQualifiedSourceName());
+ w.print(" ");
+ w.print(method.getName());
+ w.print("(");
+
+ JType[] types = method.getParameterTypes();
+ for (int i = 0; i < types.length; i++) {
+ if (i != 0) {
+ w.print(", ");
+ }
+ w.print(types[i].getQualifiedSourceName());
+ w.print(" p");
+ w.print(Integer.toString(i));
+ }
+
+ w.println(") {");
+ w.indent();
+
+ if (!method.getReturnType().getQualifiedSourceName()
+ .equals("void")) {
+ w.print("return ");
+ }
+
+ w.print("handler.invoke(this, ");
+ w.print(TypeData.class.getCanonicalName());
+ w.print(".getType(");
+ printClassLiteral(w, type);
+ w.print(").getMethod(\"");
+ w.print(escape(method.getName()));
+ w.print("\"), new Object [] {");
+ for (int i = 0; i < types.length; i++) {
+ w.print("p" + i + ", ");
+ }
+ w.println("});");
+
+ w.outdent();
+ w.println("}");
+ }
+ }
+
+ w.outdent();
+ w.println("};");
+
+ w.outdent();
+ w.println("}");
+
+ w.outdent();
+ w.println("});");
+
+ }
}
private void writeParamTypes(SourceWriter w, ConnectorBundle bundle) {
Set<JMethod> methods = entry.getValue();
for (JMethod method : methods) {
- w.println("store.setParamTypes(");
+ w.print("store.setParamTypes(");
printClassLiteral(w, type);
w.print(", \"");
w.print(escape(method.getName()));
- w.println("\", new Type[] {");
+ w.print("\", new Type[] {");
for (JType parameter : method.getParameterTypes()) {
ConnectorBundleLoaderFactory.writeTypeCreator(w, parameter);
for (JClassType type : constructors) {
w.print("store.setConstructor(");
printClassLiteral(w, type);
- w.print(", new Invoker() {");
+ w.println(", new Invoker() {");
w.indent();
w.println("public Object invoke(Object target, Object[] params) {");
throws NotFoundException {
List<TypeVisitor> visitors = Arrays.<TypeVisitor> asList(
new ConnectorInitVisitor(), new StateInitVisitor(),
- new WidgetInitVisitor(), new ClientRpcVisitor());
+ new WidgetInitVisitor(), new ClientRpcVisitor(),
+ new ServerRpcVisitor());
for (TypeVisitor typeVisitor : visitors) {
typeVisitor.init(oracle);
}
+++ /dev/null
-/*
- * Copyright 2011 Vaadin Ltd.
- *
- * 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.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.shared.communication.ServerRpc;
-import com.vaadin.terminal.gwt.client.ServerConnector;
-import com.vaadin.terminal.gwt.client.communication.InitializableServerRpc;
-import com.vaadin.terminal.gwt.client.communication.RpcProxy.RpcProxyCreator;
-
-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);
- if (requestedType == null) {
- logger.log(TreeLogger.ERROR, "Unable to find metadata for type '"
- + requestedClassName + "'", null);
- throw new UnableToCompleteException();
- }
- String packageName = requestedType.getPackage().getName();
- String className = requestedType.getSimpleSourceName() + "Impl";
-
- 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");
-
- }
-}
+++ /dev/null
-/*
- * Copyright 2011 Vaadin Ltd.
- *
- * 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.vaadin.terminal.gwt.widgetsetutils;
-
-import java.io.PrintWriter;
-
-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.JMethod;
-import com.google.gwt.core.ext.typeinfo.JParameter;
-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.shared.annotations.Delayed;
-import com.vaadin.shared.communication.MethodInvocation;
-import com.vaadin.shared.communication.ServerRpc;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.ServerConnector;
-import com.vaadin.terminal.gwt.client.communication.InitializableServerRpc;
-
-/**
- * GWT generator that creates client side proxy classes for making RPC calls
- * from the client to the server.
- *
- * GWT.create() calls for interfaces extending {@link ServerRpc} are affected,
- * and a proxy implementation is created. Note that the init(...) method of the
- * proxy must be called before the proxy is used.
- *
- * @since 7.0
- */
-public class RpcProxyGenerator extends Generator {
- @Override
- public String generate(TreeLogger logger, GeneratorContext ctx,
- String requestedClassName) throws UnableToCompleteException {
- logger.log(TreeLogger.DEBUG, "Running RpcProxyGenerator", null);
-
- TypeOracle typeOracle = ctx.getTypeOracle();
- assert (typeOracle != null);
-
- JClassType requestedType = typeOracle.findType(requestedClassName);
- if (requestedType == null) {
- logger.log(TreeLogger.ERROR, "Unable to find metadata for type '"
- + requestedClassName + "'", null);
- throw new UnableToCompleteException();
- }
-
- String generatedClassName = "ServerRpc_"
- + requestedType.getName().replaceAll("[$.]", "_");
-
- JClassType initializableInterface = typeOracle
- .findType(InitializableServerRpc.class.getCanonicalName());
-
- ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(
- requestedType.getPackage().getName(), generatedClassName);
- composer.addImplementedInterface(requestedType.getQualifiedSourceName());
- composer.addImplementedInterface(initializableInterface
- .getQualifiedSourceName());
- composer.addImport(MethodInvocation.class.getCanonicalName());
-
- PrintWriter printWriter = ctx.tryCreate(logger,
- composer.getCreatedPackage(),
- composer.getCreatedClassShortName());
- if (printWriter != null) {
- logger.log(Type.INFO, "Generating client proxy for RPC interface '"
- + requestedType.getQualifiedSourceName() + "'");
- SourceWriter writer = composer.createSourceWriter(ctx, printWriter);
-
- // constructor
- writer.println("public " + generatedClassName + "() {}");
-
- // initialization etc.
- writeCommonFieldsAndMethods(logger, writer, typeOracle);
-
- // actual proxy methods forwarding calls to the server
- writeRemoteProxyMethods(logger, writer, typeOracle, requestedType,
- requestedType.isClassOrInterface().getInheritableMethods());
-
- // End of class
- writer.outdent();
- writer.println("}");
-
- ctx.commit(logger, printWriter);
- }
-
- return composer.getCreatedClassName();
- }
-
- private void writeCommonFieldsAndMethods(TreeLogger logger,
- SourceWriter writer, TypeOracle typeOracle) {
- JClassType applicationConnectionClass = typeOracle
- .findType(ApplicationConnection.class.getCanonicalName());
-
- // fields
- writer.println("private " + ServerConnector.class.getName()
- + " connector;");
-
- // init method from the RPC interface
- writer.println("public void initRpc(" + ServerConnector.class.getName()
- + " connector) {");
- writer.indent();
- writer.println("this.connector = connector;");
- writer.outdent();
- writer.println("}");
- }
-
- private static void writeRemoteProxyMethods(TreeLogger logger,
- SourceWriter writer, TypeOracle typeOracle,
- JClassType requestedType, JMethod[] methods) {
- for (JMethod m : methods) {
- writer.print(m.getReadableDeclaration(false, false, false, false,
- true));
- writer.println(" {");
- writer.indent();
-
- Delayed delayedAnnotation = m.getAnnotation(Delayed.class);
- boolean delayed = delayedAnnotation != null;
- boolean lastonly = delayed && delayedAnnotation.lastonly();
-
- writer.print("this.connector.getConnection().addMethodInvocationToQueue(new MethodInvocation(this.connector.getConnectorId(), \""
- + requestedType.getQualifiedBinaryName() + "\", \"");
- writer.print(m.getName());
- writer.print("\", new Object[] {");
- // new Object[] { ... } for parameters - autoboxing etc. by the
- // compiler
- JParameter[] parameters = m.getParameters();
- boolean first = true;
- for (JParameter p : parameters) {
- if (!first) {
- writer.print(", ");
- }
- first = false;
-
- writer.print(p.getName());
- }
- writer.println("}), " + delayed + ", " + lastonly + ");");
-
- writer.outdent();
- writer.println("}");
- }
- }
-}
private final Map<JClassType, Set<JMethod>> needsReturnType = new HashMap<JClassType, Set<JMethod>>();
private final Collection<TypeVisitor> visitors;
+
+ private final Set<JClassType> needsProxySupport = new HashSet<JClassType>();
private final Map<JClassType, Set<JMethod>> needsInvoker = new HashMap<JClassType, Set<JMethod>>();
private final Map<JClassType, Set<JMethod>> needsParamTypes = new HashMap<JClassType, Set<JMethod>>();
+ private final Map<JClassType, Set<JMethod>> needsDelayedInfo = new HashMap<JClassType, Set<JMethod>>();
private ConnectorBundle(String name, ConnectorBundle previousBundle,
Collection<TypeVisitor> visitors) {
public Map<JClassType, Set<JMethod>> getNeedsParamTypes() {
return Collections.unmodifiableMap(needsParamTypes);
}
+
+ public void setNeedsProxySupport(JClassType type) {
+ if (!isNeedsProxySupport(type)) {
+ ensureVisited(type);
+ needsProxySupport.add(type);
+ }
+ }
+
+ private boolean isNeedsProxySupport(JClassType type) {
+ if (needsProxySupport.contains(type)) {
+ return true;
+ } else {
+ return previousBundle != null
+ && previousBundle.isNeedsProxySupport(type);
+ }
+ }
+
+ public Set<JClassType> getNeedsProxySupport() {
+ return Collections.unmodifiableSet(needsProxySupport);
+ }
+
+ public void setNeedsDelayedInfo(JClassType type, JMethod method) {
+ if (!isNeedsDelayedInfo(type, method)) {
+ ensureVisited(type);
+ addMapping(needsDelayedInfo, type, method);
+ }
+ }
+
+ private boolean isNeedsDelayedInfo(JClassType type, JMethod method) {
+ if (hasMapping(needsDelayedInfo, type, method)) {
+ return true;
+ } else {
+ return previousBundle != null
+ && previousBundle.isNeedsDelayedInfo(type, method);
+ }
+ }
+
+ public Map<JClassType, Set<JMethod>> getNeedsDelayedInfo() {
+ return Collections.unmodifiableMap(needsDelayedInfo);
+ }
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * 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.vaadin.terminal.gwt.widgetsetutils.metadata;
+
+import java.util.Set;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JMethod;
+
+public class ServerRpcVisitor extends TypeVisitor {
+ @Override
+ public void visitServerRpc(TreeLogger logger, JClassType type,
+ ConnectorBundle bundle) {
+ bundle.setNeedsProxySupport(type);
+
+ Set<? extends JClassType> superTypes = type
+ .getFlattenedSupertypeHierarchy();
+ for (JClassType subType : superTypes) {
+ if (subType.isInterface() != null) {
+ JMethod[] methods = subType.getMethods();
+ for (JMethod method : methods) {
+ bundle.setNeedsDelayedInfo(type, method);
+ }
+ }
+ }
+ }
+}
class="com.vaadin.terminal.gwt.client.ui.dd.VAcceptCriterionFactory" />
</generate-with>
- <!-- Generate client side proxies for client to server RPC interfaces -->
- <generate-with
- class="com.vaadin.terminal.gwt.widgetsetutils.RpcProxyGenerator">
- <when-type-assignable
- class="com.vaadin.shared.communication.ServerRpc" />
- </generate-with>
-
- <!-- Generate client side proxies for client to server RPC interfaces -->
- <generate-with
- class="com.vaadin.terminal.gwt.widgetsetutils.RpcProxyCreatorGenerator">
- <when-type-assignable
- class="com.vaadin.terminal.gwt.client.communication.RpcProxy.RpcProxyCreator" />
- </generate-with>
-
<generate-with class="com.vaadin.terminal.gwt.widgetsetutils.ConnectorBundleLoaderFactory">
<when-type-assignable class="com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader" />
</generate-with>
}
public ApplicationConnection() {
+ // Assuming Root data is eagerly loaded
+ ConnectorBundleLoader.get().loadBundle(
+ ConnectorBundleLoader.EAGER_BUNDLE_NAME, null);
rootConnector = GWT.create(RootConnector.class);
rpcManager = GWT.create(RpcManager.class);
layoutManager = GWT.create(LayoutManager.class);
initializeClientHooks();
- // Assuming Root data is eagerly loaded
- ConnectorBundleLoader.get().loadBundle(
- ConnectorBundleLoader.EAGER_BUNDLE_NAME, null);
-
rootConnector.init(cnf.getRootPanelId(), this);
showLoadingIndicator();
}
+++ /dev/null
-/*
- * Copyright 2011 Vaadin Ltd.
- *
- * 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.vaadin.terminal.gwt.client.communication;
-
-import com.vaadin.shared.communication.ServerRpc;
-import com.vaadin.terminal.gwt.client.ServerConnector;
-
-/**
- * Initialization support for client to server RPC interfaces.
- *
- * This is in a separate interface used by the GWT generator class. The init
- * method is not in {@link ServerRpc} because then also server side proxies
- * would have to implement the initialization method.
- *
- * @since 7.0
- */
-public interface InitializableServerRpc extends ServerRpc {
- /**
- * Associates the RPC proxy with a connector. Called by generated code.
- * Should never be called manually.
- *
- * @param connector
- * The connector the ServerRPC instance is assigned to.
- */
- public void initRpc(ServerConnector connector);
-}
\ No newline at end of file
public Type[] getParameterTypes(MethodInvocation invocation) {
Method method = getMethod(invocation);
- Type[] parameterTypes = method.getParameterTypes();
- if (parameterTypes == null) {
+ try {
+ Type[] parameterTypes = method.getParameterTypes();
+ return parameterTypes;
+ } catch (NoDataException e) {
throw new IllegalStateException("There is no information about "
+ method.getSignature()
- + ". Did you remember to compile the right widgetset?");
-
+ + ". Did you remember to compile the right widgetset?", e);
}
- return parameterTypes;
}
public void parseAndApplyInvocation(JSONArray rpcCall,
*/
package com.vaadin.terminal.gwt.client.communication;
-import com.google.gwt.core.client.GWT;
+import com.vaadin.shared.communication.MethodInvocation;
import com.vaadin.shared.communication.ServerRpc;
import com.vaadin.terminal.gwt.client.ServerConnector;
+import com.vaadin.terminal.gwt.client.metadata.InvokationHandler;
+import com.vaadin.terminal.gwt.client.metadata.Method;
+import com.vaadin.terminal.gwt.client.metadata.NoDataException;
+import com.vaadin.terminal.gwt.client.metadata.TypeData;
/**
* Class for creating proxy instances for Client to Server RPC.
*/
public class RpcProxy {
- private static RpcProxyCreator impl = GWT.create(RpcProxyCreator.class);
-
- /**
- * Create a proxy class for the given Rpc interface and assign it to the
- * given connector.
- *
- * @param rpcInterface
- * The rpc interface to construct a proxy for
- * @param connector
- * The connector this proxy is connected to
- * @return A proxy class used for calling Rpc methods.
- */
public static <T extends ServerRpc> T create(Class<T> rpcInterface,
ServerConnector connector) {
- return impl.create(rpcInterface, connector);
+ try {
+ return (T) TypeData.getType(rpcInterface).createProxy(
+ new RpcInvokationHandler(rpcInterface, connector));
+ } catch (NoDataException e) {
+ throw new IllegalStateException("There is no information about "
+ + rpcInterface
+ + ". Did you forget to compile the widgetset?");
+ }
}
- public interface RpcProxyCreator {
- <T extends ServerRpc> T create(Class<T> rpcInterface,
- ServerConnector connector);
+ private static final class RpcInvokationHandler implements
+ InvokationHandler {
+ private final Class<?> rpcInterface;
+ private final ServerConnector connector;
+
+ private RpcInvokationHandler(Class<?> rpcInterface,
+ ServerConnector connector) {
+ this.rpcInterface = rpcInterface;
+ this.connector = connector;
+ }
+
+ @Override
+ public Object invoke(Object target, Method method, Object[] params) {
+ MethodInvocation invocation = new MethodInvocation(
+ connector.getConnectorId(), rpcInterface.getName(),
+ method.getName(), params);
+ connector.getConnection().addMethodInvocationToQueue(invocation,
+ method.isDelayed(), method.isLastonly());
+ // No RPC iface should have a return value
+ return null;
+ }
}
}
--- /dev/null
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * 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.vaadin.terminal.gwt.client.metadata;
+
+public interface InvokationHandler {
+ public Object invoke(Object target, Method method, Object[] params);
+}
return getSignature().hashCode();
}
- public Type[] getParameterTypes() {
+ public Type[] getParameterTypes() throws NoDataException {
return TypeDataStore.getParamTypes(this);
}
+ public boolean isDelayed() {
+ return TypeDataStore.isDelayed(this);
+ }
+
+ public boolean isLastonly() {
+ return TypeDataStore.isLastonly(this);
+ }
+
}
--- /dev/null
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * 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.vaadin.terminal.gwt.client.metadata;
+
+public interface ProxyHandler {
+
+ Object createProxy(InvokationHandler invokationHandler);
+
+}
return getSignature().hashCode();
}
+ public Object createProxy(InvokationHandler invokationHandler)
+ throws NoDataException {
+ return TypeDataStore.get().getProxyHandler(this)
+ .createProxy(invokationHandler);
+ }
+
}
package com.vaadin.terminal.gwt.client.metadata;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
public class TypeDataStore {
private static final String CONSTRUCTOR_NAME = "!new";
private final Map<String, Class<?>> identifiers = new HashMap<String, Class<?>>();
+ private final Map<Type, ProxyHandler> proxyHandlers = new HashMap<Type, ProxyHandler>();
+
+ private final Set<Method> delayedMethods = new HashSet<Method>();
+ private final Set<Method> lastonlyMethods = new HashSet<Method>();
+
private final Map<Method, Type> returnTypes = new HashMap<Method, Type>();
private final Map<Method, Invoker> invokers = new HashMap<Method, Invoker>();
private final Map<Method, Type[]> paramTypes = new HashMap<Method, Type[]>();
invokers.put(new Method(getType(type), methodName), invoker);
}
- public static Type[] getParamTypes(Method method) {
- return get().paramTypes.get(method);
+ public static Type[] getParamTypes(Method method) throws NoDataException {
+ Type[] types = get().paramTypes.get(method);
+ if (types == null) {
+ throw new NoDataException("There are no parameter type data for "
+ + method.getSignature());
+ }
+ return types;
}
public void setParamTypes(Class<?> type, String methodName,
public static boolean hasIdentifier(String identifier) {
return get().identifiers.containsKey(identifier);
}
+
+ public static ProxyHandler getProxyHandler(Type type)
+ throws NoDataException {
+ ProxyHandler proxyHandler = get().proxyHandlers.get(type);
+ if (proxyHandler == null) {
+ throw new NoDataException("No proxy handler for "
+ + type.getSignature());
+ }
+ return proxyHandler;
+ }
+
+ public void setProxyHandler(Class<?> type, ProxyHandler proxyHandler) {
+ proxyHandlers.put(getType(type), proxyHandler);
+ }
+
+ public static boolean isDelayed(Method method) {
+ return get().delayedMethods.contains(method);
+ }
+
+ public void setDelayed(Class<?> type, String methodName) {
+ delayedMethods.add(getType(type).getMethod(methodName));
+ }
+
+ public static boolean isLastonly(Method method) {
+ return get().lastonlyMethods.contains(method);
+ }
+
+ public void setLastonly(Class<?> clazz, String methodName) {
+ lastonlyMethods.add(getType(clazz).getMethod(methodName));
+ }
}