Coverage Report - org.simject.remoting.server.SimServerServlet
 
Classes in this File Line Coverage Branch Coverage Complexity
SimServerServlet
0%
0/72
0%
0/16
0
 
 1  
 /*
 2  
  * Copyright 2008 Simon Martinelli, Rebenweg 32, 3236 Gampelen, Switzerland
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of 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,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.simject.remoting.server;
 17  
 
 18  
 import java.beans.XMLDecoder;
 19  
 import java.beans.XMLEncoder;
 20  
 import java.io.ByteArrayOutputStream;
 21  
 import java.io.IOException;
 22  
 import java.io.ObjectInputStream;
 23  
 import java.io.ObjectOutputStream;
 24  
 import java.lang.reflect.InvocationTargetException;
 25  
 import java.lang.reflect.Method;
 26  
 import java.util.StringTokenizer;
 27  
 import java.util.logging.Level;
 28  
 import java.util.logging.Logger;
 29  
 
 30  
 import javax.servlet.ServletException;
 31  
 import javax.servlet.http.HttpServlet;
 32  
 import javax.servlet.http.HttpServletRequest;
 33  
 import javax.servlet.http.HttpServletResponse;
 34  
 
 35  
 import org.simject.SimFactory;
 36  
 import org.simject.util.Protocol;
 37  
 import org.simject.util.SimConstants;
 38  
 
 39  
 /**
 40  
  * This servlet can be used as endpoint for remote access over HTTP to a
 41  
  * resource
 42  
  * 
 43  
  * @author Simon Martinelli
 44  
  */
 45  
 @SuppressWarnings("serial")
 46  0
 public class SimServerServlet extends HttpServlet {
 47  
 
 48  0
         private final static Logger logger = Logger
 49  
                         .getLogger(SimServerServlet.class.getName());
 50  
 
 51  
         /**
 52  
          * Context parameter that contains the configuration file location
 53  
          */
 54  
         private final static String SIMJECT_CONFIG = "simjectConfig";
 55  
 
 56  
         /**
 57  
          * Reference to the SimFactory
 58  
          */
 59  
         private SimFactory simFactory;
 60  
 
 61  
         @Override
 62  
         public void init() throws ServletException {
 63  0
                 if (this.simFactory == null) {
 64  
                         // Get the context parameter with the config file
 65  0
                         final String configFile = this.getServletContext()
 66  
                                         .getInitParameter(SIMJECT_CONFIG);
 67  
                         // create a SimFactory based on the config file
 68  0
                         this.simFactory = new SimFactory(configFile);
 69  
                 }
 70  0
         }
 71  
 
 72  
         @Override
 73  
         protected void doPost(final HttpServletRequest req,
 74  
                         final HttpServletResponse resp) throws ServletException,
 75  
                         IOException {
 76  0
                 this.invokeMethod(req, resp);
 77  0
         }
 78  
 
 79  
         /**
 80  
          * Invokes a method based on the parameters passed from the client
 81  
          * 
 82  
          * @param req
 83  
          * @param resp
 84  
          * @param obj
 85  
          * @param args
 86  
          * @throws IOException
 87  
          * @throws IllegalAccessException
 88  
          * @throws InvocationTargetException
 89  
          * @throws IOException
 90  
          * @throws ClassNotFoundException
 91  
          * @throws NoSuchMethodException
 92  
          * @throws SecurityException
 93  
          */
 94  
         private void invokeMethod(final HttpServletRequest req,
 95  
                         final HttpServletResponse resp) throws IOException {
 96  
 
 97  0
                 Object result = null;
 98  
                 try {
 99  
                         // get the classname
 100  0
                         final String className = this.getClassName(req);
 101  
                         // create a Class instance
 102  0
                         final Class<?> clazz = Class.forName(className);
 103  
                         // and get the resource from the SimFactory
 104  0
                         final Object obj = this.simFactory.getResource(clazz);
 105  
                         // get passed arguments and invoke the method
 106  0
                         final Object[] args = this.getArguments(req);
 107  
                         // get the method name from the HTTP header
 108  0
                         final String methodString = req
 109  
                                         .getHeader(SimConstants.PARAM_METHOD);
 110  
 
 111  
                         // get the parameter types from the HTTP header
 112  0
                         final String paramTypesString = req
 113  
                                         .getHeader(SimConstants.PARAM_TYPES);
 114  
 
 115  0
                         logger.info("Request for class <" + clazz.getName() + "> method <"
 116  
                                         + methodString + "> params <" + paramTypesString + ">");
 117  
 
 118  0
                         if (paramTypesString == null) {
 119  
                                 // method without parameters to invoke
 120  0
                                 final Method method = obj.getClass().getMethod(methodString);
 121  0
                                 result = method.invoke(obj);
 122  0
                         } else {
 123  
                                 // method with parameters should be called. Converts the string
 124  
                                 // from the header to Class array
 125  0
                                 final Class<?>[] parameterTypes = this
 126  
                                                 .getParameterTypes(paramTypesString);
 127  0
                                 final Method method = obj.getClass().getMethod(methodString,
 128  
                                                 parameterTypes);
 129  
 
 130  0
                                 result = method.invoke(obj, args);
 131  
                         }
 132  0
                 } catch (Exception e) {
 133  
                         // If an exception occurs during invocation put it in the result to
 134  
                         // have it serialized
 135  0
                         logger.log(Level.INFO, "Exception occured during invocation", e);
 136  0
                         result = e;
 137  0
                 }
 138  0
                 if (result != null) {
 139  0
                         if (req.getContentType().equals(Protocol.Xml.getContentType())) {
 140  0
                                 this.sendXmlResponse(resp, result);
 141  
                         } else {
 142  0
                                 this.sendBinaryResponse(resp, result);
 143  
                         }
 144  
                 }
 145  0
         }
 146  
 
 147  
         /**
 148  
          * Sends the result as binary stream
 149  
          * 
 150  
          * @param resp
 151  
          * @param result
 152  
          * @throws IOException
 153  
          */
 154  
         private void sendBinaryResponse(final HttpServletResponse resp,
 155  
                         final Object result) throws IOException {
 156  0
                 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
 157  0
                 final ObjectOutputStream oos = new ObjectOutputStream(baos);
 158  0
                 oos.writeObject(result);
 159  0
                 oos.close();
 160  
 
 161  0
                 resp.setContentType(Protocol.Binary.getContentType());
 162  0
                 resp.getOutputStream().write(baos.toByteArray());
 163  0
         }
 164  
 
 165  
         /**
 166  
          * Sends the result as XML stream
 167  
          * 
 168  
          * @param resp
 169  
          * @param result
 170  
          * @throws IOException
 171  
          */
 172  
         private void sendXmlResponse(final HttpServletResponse resp,
 173  
                         final Object result) throws IOException {
 174  0
                 resp.setContentType(Protocol.Xml.getContentType());
 175  0
                 final XMLEncoder encoder = new XMLEncoder(resp.getOutputStream());
 176  0
                 encoder.writeObject(result);
 177  0
         }
 178  
 
 179  
         /**
 180  
          * Returns an array of Class containing the types of the parameters
 181  
          * 
 182  
          * @param parameterString
 183  
          * @return
 184  
          * @throws ClassNotFoundException
 185  
          */
 186  
         private Class<?>[] getParameterTypes(final String parameterString)
 187  
                         throws ClassNotFoundException {
 188  0
                 Class<?>[] parameters = new Class[0];
 189  0
                 if (parameterString != null) {
 190  
                         // The parameter types are seperated by ","
 191  0
                         final StringTokenizer stokenizer = new StringTokenizer(
 192  
                                         parameterString, SimConstants.PARAM_TYPE_DELIM);
 193  0
                         parameters = new Class[stokenizer.countTokens()];
 194  0
                         int index = 0;
 195  0
                         while (stokenizer.hasMoreTokens()) {
 196  0
                                 final String className = stokenizer.nextToken();
 197  
 
 198  0
                                 final Class<?> clazz = Class.forName(className);
 199  0
                                 parameters[index] = clazz;
 200  0
                                 index++;
 201  0
                         }
 202  
                 }
 203  0
                 return parameters;
 204  
         }
 205  
 
 206  
         /**
 207  
          * Get Arguments
 208  
          * 
 209  
          * @param req
 210  
          * @return
 211  
          * @throws IOException
 212  
          * @throws ClassNotFoundException
 213  
          */
 214  
         private Object[] getArguments(final HttpServletRequest req)
 215  
                         throws IOException, ClassNotFoundException {
 216  
 
 217  0
                 Object args = null;
 218  0
                 if (req.getContentType().equals(Protocol.Xml.getContentType())) {
 219  0
                         final XMLDecoder decoder = new XMLDecoder(req.getInputStream());
 220  0
                         args = decoder.readObject();
 221  0
                 } else {
 222  0
                         final ObjectInputStream ois = new ObjectInputStream(req
 223  
                                         .getInputStream());
 224  0
                         args = ois.readObject();
 225  
                 }
 226  
 
 227  0
                 return (Object[]) args;
 228  
         }
 229  
 
 230  
         /**
 231  
          * Parses the class name out of the path info
 232  
          * 
 233  
          * @param req
 234  
          * @return
 235  
          */
 236  
         private String getClassName(final HttpServletRequest req) {
 237  0
                 final StringTokenizer stokenzier = new StringTokenizer(req
 238  
                                 .getPathInfo(), "/");
 239  0
                 String[] tokens = new String[stokenzier.countTokens()];
 240  0
                 int index = 0;
 241  0
                 while (stokenzier.hasMoreTokens()) {
 242  0
                         tokens[index] = stokenzier.nextToken();
 243  0
                         index++;
 244  
                 }
 245  0
                 return tokens[0];
 246  
         }
 247  
 
 248  
         @Override
 249  
         protected void doGet(final HttpServletRequest req,
 250  
                         final HttpServletResponse resp) throws ServletException,
 251  
                         IOException {
 252  0
                 this.doPost(req, resp);
 253  0
         }
 254  
 }