001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.user.client.rpc.impl;
017:
018: import com.google.gwt.http.client.Request;
019: import com.google.gwt.http.client.RequestBuilder;
020: import com.google.gwt.http.client.RequestException;
021: import com.google.gwt.user.client.rpc.AsyncCallback;
022: import com.google.gwt.user.client.rpc.InvocationException;
023: import com.google.gwt.user.client.rpc.SerializationException;
024: import com.google.gwt.user.client.rpc.SerializationStreamFactory;
025: import com.google.gwt.user.client.rpc.ServiceDefTarget;
026: import com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.ResponseReader;
027:
028: /**
029: * Superclass for client-side
030: * {@link com.google.gwt.user.client.rpc.RemoteService RemoteService} proxies.
031: *
032: * For internal use only.
033: */
034: public abstract class RemoteServiceProxy implements
035: SerializationStreamFactory, ServiceDefTarget {
036: /**
037: * Return <code>true</code> if the encoded response contains a value
038: * returned by the method invocation.
039: *
040: * @param encodedResponse
041: * @return <code>true</code> if the encoded response contains a value
042: * returned by the method invocation
043: */
044: static boolean isReturnValue(String encodedResponse) {
045: return encodedResponse.startsWith("//OK");
046: }
047:
048: /**
049: * Return <code>true</code> if the encoded response contains a checked
050: * exception that was thrown by the method invocation.
051: *
052: * @param encodedResponse
053: * @return <code>true</code> if the encoded response contains a checked
054: * exception that was thrown by the method invocation
055: */
056: static boolean isThrownException(String encodedResponse) {
057: return encodedResponse.startsWith("//EX");
058: }
059:
060: /**
061: * Returns a string that encodes the result of a method invocation.
062: * Effectively, this just removes any headers from the encoded response.
063: *
064: * @param encodedResponse
065: * @return string that encodes the result of a method invocation
066: */
067: private static String getEncodedInstance(String encodedResponse) {
068: if (isReturnValue(encodedResponse)
069: || isThrownException(encodedResponse)) {
070: return encodedResponse.substring(4);
071: }
072:
073: return encodedResponse;
074: }
075:
076: /**
077: * The module base URL as specified during construction.
078: */
079: private final String moduleBaseURL;
080:
081: /**
082: * URL of the
083: * {@link com.google.gwt.user.client.rpc.RemoteService RemoteService}.
084: */
085: private String remoteServiceURL;
086:
087: /**
088: * The name of the serialization policy file specified during construction.
089: */
090: private final String serializationPolicyName;
091:
092: /**
093: * The {@link Serializer} instance used to serialize and deserialize
094: * instances.
095: */
096: private final Serializer serializer;
097:
098: protected RemoteServiceProxy(String moduleBaseURL,
099: String remoteServiceURL, String serializationPolicyName,
100: Serializer serializer) {
101: this .moduleBaseURL = moduleBaseURL;
102: this .remoteServiceURL = remoteServiceURL;
103: this .serializer = serializer;
104: this .serializationPolicyName = serializationPolicyName;
105: }
106:
107: /**
108: * Returns a
109: * {@link com.google.gwt.user.client.rpc.SerializationStreamReader SerializationStreamReader}
110: * that is ready for reading.
111: *
112: * @param encoded string that encodes the response of an RPC request
113: * @return {@link com.google.gwt.user.client.rpc.SerializationStreamReader SerializationStreamReader}
114: * that is ready for reading
115: * @throws SerializationException
116: */
117: public ClientSerializationStreamReader createStreamReader(
118: String encoded) throws SerializationException {
119: ClientSerializationStreamReader clientSerializationStreamReader = new ClientSerializationStreamReader(
120: serializer);
121: clientSerializationStreamReader
122: .prepareToRead(getEncodedInstance(encoded));
123: return clientSerializationStreamReader;
124: }
125:
126: /**
127: * Returns a
128: * {@link com.google.gwt.user.client.rpc.SerializationStreamWriter SerializationStreamWriter}
129: * that has had {@link ClientSerializationStreamWriter#prepareToWrite()}
130: * called on it and it has already had had the name of the remote service
131: * interface written as well.
132: *
133: * @return {@link com.google.gwt.user.client.rpc.SerializationStreamWriter SerializationStreamWriter}
134: * that has had
135: * {@link ClientSerializationStreamWriter#prepareToWrite()} called on
136: * it and it has already had had the name of the remote service
137: * interface written as well
138: */
139: public ClientSerializationStreamWriter createStreamWriter() {
140: ClientSerializationStreamWriter clientSerializationStreamWriter = new ClientSerializationStreamWriter(
141: serializer, moduleBaseURL, serializationPolicyName);
142: clientSerializationStreamWriter.prepareToWrite();
143: return clientSerializationStreamWriter;
144: }
145:
146: /**
147: * @see ServiceDefTarget#getServiceEntryPoint()
148: */
149: public String getServiceEntryPoint() {
150: return remoteServiceURL;
151: }
152:
153: /**
154: * @see ServiceDefTarget#setServiceEntryPoint(String)
155: */
156: public void setServiceEntryPoint(String url) {
157: this .remoteServiceURL = url;
158: }
159:
160: /**
161: * Performs a remote service method invocation.
162: *
163: * @param <T> return type for the AsyncCallback
164: * @param responseReader instance used to read the return value of the
165: * invocation
166: * @param requestData payload that encodes the addressing and arguments of the
167: * RPC call
168: * @param callback callback handler
169: *
170: * @return a {@link Request} object that can be used to track the request
171: */
172: protected <T> Request doInvoke(ResponseReader responseReader,
173: String requestData, AsyncCallback<T> callback) {
174:
175: if (getServiceEntryPoint() == null) {
176: throw new NoServiceEntryPointSpecifiedException();
177: }
178:
179: RequestCallbackAdapter<T> responseHandler = new RequestCallbackAdapter<T>(
180: this , callback, responseReader);
181: RequestBuilder rb = new RequestBuilder(RequestBuilder.POST,
182: getServiceEntryPoint());
183: try {
184: return rb.sendRequest(requestData, responseHandler);
185: } catch (RequestException ex) {
186: InvocationException iex = new InvocationException(
187: "Unable to initiate the asynchronous service invocation -- check the network connection",
188: ex);
189: callback.onFailure(iex);
190: }
191:
192: return null;
193: }
194: }
|