PageRenderTime 34ms CodeModel.GetById 15ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 1ms

/gwtrpccommlayer/src/main/java/com/googlecode/gwtrpccommlayer/server/AbstractGwtRpcCommLayerServlet.java

https://code.google.com/p/gwtrpccommlayer/
Java | 297 lines | 145 code | 42 blank | 110 comment | 13 complexity | 9383e547dd4ee57b7d6af6d5b070c73b MD5 | raw file
  1/*
  2 * Copyright 2010 Jeff McHugh (Segue Development LLC)
  3 * 
  4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  5 * in compliance with the License. You may obtain a copy of the License at
  6 * 
  7 * http://www.apache.org/licenses/LICENSE-2.0
  8 * 
  9 * Unless required by applicable law or agreed to in writing, software distributed under the License
 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 11 * or implied. See the License for the specific language governing permissions and limitations under
 12 * the License.
 13 */
 14package com.googlecode.gwtrpccommlayer.server;
 15
 16
 17import com.google.gwt.user.server.rpc.RemoteServiceServlet;
 18import com.googlecode.gwtrpccommlayer.shared.GwtRpcCommLayerPojoConstants;
 19import com.googlecode.gwtrpccommlayer.shared.GwtRpcCommLayerPojoRequest;
 20import com.googlecode.gwtrpccommlayer.shared.GwtRpcCommLayerPojoResponse;
 21
 22import javax.servlet.ServletConfig;
 23import javax.servlet.ServletException;
 24import javax.servlet.ServletRequest;
 25import javax.servlet.ServletResponse;
 26import javax.servlet.http.HttpServletRequest;
 27import javax.servlet.http.HttpServletResponse;
 28import java.io.*;
 29import java.lang.reflect.InvocationTargetException;
 30import java.lang.reflect.Method;
 31import java.util.LinkedList;
 32
 33/**
 34 * This class can either sit above your servlet (i.e. your servlet extends this) or it can wrap
 35 * your servlet (i.e. it will receive the calls and delegate it to the respective methods
 36 * @author jeff mchugh
 37 *
 38 */
 39public abstract class AbstractGwtRpcCommLayerServlet extends RemoteServiceServlet
 40{
 41
 42	private static final long	serialVersionUID	= -8829760243946113688L;
 43
 44	Object servletInstance = null;
 45
 46    public AbstractGwtRpcCommLayerServlet() { }
 47    //@Inject
 48    //Can be extended and injected Guice
 49
 50	public AbstractGwtRpcCommLayerServlet(Object servletImplementation)
 51	{
 52        this.servletInstance = servletImplementation;
 53
 54        //this.servletImplementation = servletImplementation;
 55	}
 56
 57	/**
 58	 * Initializes the servlet
 59	 */
 60	public void init(ServletConfig config) throws ServletException
 61	{
 62		super.init(config);
 63
 64
 65		/*
 66		 * The default is to assume this instance is the selected servlet
 67		 */
 68		servletInstance = this;
 69
 70
 71		/*
 72		 * Check to see another servlet should be the target
 73		 */
 74        //todo: this is currently configured using an init param in web.xml.  We need to change this to use something guice-friendly!
 75        //maybe use @Inject(optional=true) @Named("CommLayerImplClass") String strImplmentationClass;
 76
 77		String servletImplClassName = config.getInitParameter(GwtRpcCommLayerPojoConstants.GWT_RPC_COMM_LAYER_SERVLET_IMPL_CLASS);
 78        //Use guice injected name instead of init parameter
 79        //if ( servletImplementation != null)
 80		if ( servletImplClassName != null && !servletImplClassName.trim().equals(""))
 81		{
 82			try
 83			{
 84				Class clzz = Class.forName(servletImplClassName);
 85				servletInstance = clzz.newInstance();
 86			}
 87			catch(Throwable t)
 88			{
 89				throw new ServletException(t);
 90			}
 91		}
 92	}
 93
 94
 95	/**
 96	 * any servlet that extends can opt to deny these request
 97	 * either explicitly or using web.xml
 98	 * @return
 99	 */
100	protected boolean allowGwtRpcPojoRequest()
101	{
102		return true;
103	}
104
105	protected void initalizePerRequestPerResponseIfNeeded()
106	{
107		if ( super.perThreadRequest == null )
108		{
109			super.perThreadRequest = new ThreadLocal<HttpServletRequest>();
110		}
111		if ( super.perThreadResponse == null )
112		{
113			super.perThreadResponse = new ThreadLocal<HttpServletResponse>();
114		}
115	}
116
117
118	/**
119	 * Override the main service call and implement the special handling here
120	 */
121	public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException
122	{
123        //need some function intercept <ServletRequest,Boolean>
124
125		HttpServletRequest request 		= (HttpServletRequest) req;
126		HttpServletResponse response 	= (HttpServletResponse) resp;
127
128		/*
129		 * If the GwtRpcCommLayerClient has made this request, this header should be provided
130		 */
131		String gwtClientUserAgent 		= request.getHeader(GwtRpcCommLayerPojoConstants.GWT_RPC_COMM_LAYER_CLIENT_KEY);
132
133
134		/*
135		 * Only execute this block if:
136		 *  - allowGwtRpcPojoRequest() is true
137		 *  - is POST
138		 *  - gwtClientUserAgent = 'GwtRpcCommLayerPojoRequest'
139		 */
140		if ( allowGwtRpcPojoRequest()
141                && request.getMethod().equals("POST")
142                && gwtClientUserAgent != null
143                && gwtClientUserAgent.equalsIgnoreCase(GwtRpcCommLayerPojoConstants.GWT_RPC_COMM_LAYER_POJO_CLIENT))
144		{
145			try
146			{
147
148				/*
149				 * This might not be initialized.
150				 * So do it if needed
151				 */
152				initalizePerRequestPerResponseIfNeeded();
153
154				super.perThreadRequest.set(request);
155			    super.perThreadResponse.set(response);
156
157				doServicePojoRequest(request,response);
158			}
159			finally
160			{
161			    super.perThreadRequest.set(null);
162			    super.perThreadResponse.set(null);
163			}
164
165		}
166		else
167		{
168			/*
169			 * Call up the chain and allow one of the implementations handle the request accordingly.
170			 * For an
171			 */
172			super.service(req, resp);
173		}
174	}
175
176	/**
177	 * Reads the request's InputStream and cast it to the correct Object type(s)
178	 * @param req
179	 * @param resp
180	 * @throws javax.servlet.ServletException
181	 * @throws java.io.IOException
182	 */
183	protected abstract void doServicePojoRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
184
185    protected Object getImplementation() {
186       return this.servletInstance;
187    }
188
189	/**
190	 * Execute the actual method within the GwtRpc servlet
191	 * @param pojoRequest
192	 * @param req
193	 * @param resp
194	 * @throws Throwable
195	 */
196	public void executePojoRequest(GwtRpcCommLayerPojoRequest pojoRequest,HttpServletRequest req, HttpServletResponse resp) throws Throwable
197	{
198		try
199		{
200			/*
201			 * extract the appropriate method
202			 */
203			Method method = getMethod(pojoRequest);
204
205			/*
206			 * invoke the method
207			 */
208			Object returnedInstance = invokeMethod(pojoRequest, method);
209
210			/*
211			 * wrap response within a response object
212			 */
213			GwtRpcCommLayerPojoResponse pojoResp = new GwtRpcCommLayerPojoResponse();
214			pojoResp.setResponseInstance( (Serializable) returnedInstance);
215
216			/*
217			 * send back the result as a stream set of bytes
218			 */
219			serializeResponse(req,resp,pojoRequest,pojoResp);
220		}
221		catch(NoSuchMethodException e)
222		{
223			log("Method does not found.", e);
224			resp.sendError(500, e.toString() );
225		}
226		catch(InvocationTargetException e)
227		{
228			log("Error executing method.", e.getCause());
229			resp.sendError(500, e.toString() );
230		}
231		catch(IllegalAccessException e)
232		{
233			log("Error accessing method.", e);
234			resp.sendError(500, e.toString() );
235		}
236	}
237
238	/**
239	 * Write the appropriate response
240	 * @param req
241	 * @param resp
242	 * @param pojoRequest
243	 * @param pojoResp
244	 * @throws java.io.IOException
245	 */
246	protected void serializeResponse(HttpServletRequest req, HttpServletResponse resp, GwtRpcCommLayerPojoRequest pojoRequest, GwtRpcCommLayerPojoResponse pojoResp) throws IOException
247	{
248		ByteArrayOutputStream bos = new ByteArrayOutputStream();
249		ObjectOutputStream objOut = new ObjectOutputStream(bos);
250		objOut.writeObject(pojoResp);
251		objOut.flush();
252		objOut.close();
253
254		resp.setContentType("binary/octet-stream");
255		resp.setContentLength(bos.toByteArray().length);
256		OutputStream out = resp.getOutputStream();
257		out.write(bos.toByteArray());
258		out.flush();
259	}
260
261	/**
262	 *
263	 * @param stressTestRequest
264	 * @return
265	 * @throws NoSuchMethodException
266	 */
267	protected Method getMethod(GwtRpcCommLayerPojoRequest stressTestRequest) throws NoSuchMethodException, ClassNotFoundException {
268		int count = 0;
269		Class<?> paramClasses[] = new Class[stressTestRequest.getMethodParameters().size()];
270
271        LinkedList<Class<?>> lstParameterClasses = new LinkedList<Class<?>>();
272        for (String methodName: stressTestRequest.getParameterClassNames()) {
273            lstParameterClasses.add(Class.forName(methodName));
274        }
275
276        Class[] arrParameterClasses = lstParameterClasses.toArray(new Class[0]);
277        return getClass().getMethod(stressTestRequest.getMethodName(), arrParameterClasses);
278    }
279
280	/**
281	 *
282	 * @param stressTestRequest
283	 * @param method
284	 * @return
285	 * @throws java.lang.reflect.InvocationTargetException
286	 * @throws IllegalAccessException
287	 */
288	protected Object invokeMethod(GwtRpcCommLayerPojoRequest stressTestRequest, Method method) throws InvocationTargetException, IllegalAccessException
289	{
290        //todo: call toArray with correct size Object Array
291		Object paramsAsObjects[] = stressTestRequest.getMethodParameters().toArray( new Object[0]);
292		Object instance = method.invoke(servletInstance, paramsAsObjects);
293		return instance;
294	}
295	
296	
297}