source: geisa/web/src/com/ether/ControllerEther.java @ 390

Last change on this file since 390 was 390, checked in by npipsl, 12 years ago

Création du projet GEISA

File size: 9.5 KB
Line 
1package com.ether;
2
3import java.io.UnsupportedEncodingException;
4import java.lang.annotation.Annotation;
5import java.lang.reflect.Method;
6import java.security.InvalidParameterException;
7import java.util.ArrayList;
8import java.util.Collection;
9import java.util.Date;
10import java.util.HashMap;
11import java.util.List;
12import java.util.Map;
13
14import javax.servlet.http.HttpServletRequest;
15import javax.servlet.http.HttpServletResponse;
16
17import net.sf.json.JSON;
18import net.sf.json.JSONArray;
19import net.sf.json.JSONNull;
20import net.sf.json.JSONObject;
21import net.sf.json.util.JSONUtils;
22
23import org.apache.commons.logging.Log;
24import org.apache.commons.logging.LogFactory;
25import org.jetbrains.annotations.NotNull;
26import org.jetbrains.annotations.Nullable;
27import org.springframework.beans.factory.annotation.Required;
28import org.springframework.web.servlet.ModelAndView;
29import org.springframework.web.servlet.mvc.AbstractController;
30import org.springframework.web.servlet.mvc.multiaction.MethodNameResolver;
31import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
32
33import com.ether.annotation.ControllerMethod;
34import com.ether.annotation.Mandatory;
35import com.ether.annotation.ParamName;
36import com.ether.annotation.UseJSON;
37
38public class ControllerEther extends AbstractController
39{
40        @Override
41        @Nullable
42        protected ModelAndView handleRequestInternal(@NotNull final HttpServletRequest request, @NotNull final HttpServletResponse response)
43                throws WebException
44        {
45                try {
46                        if (!_initialized)
47                                initialize();
48
49                        request.setCharacterEncoding(UTF8Charset.getEncoding());
50                       
51                        // Get method to call
52                        final String methodName = _methodNameResolver.getHandlerMethodName(request);
53
54                        final MethodDescription methodDescription = _methods.get(methodName);
55                        if (null == methodDescription) {
56                                WebHelper.displayAjaxError(response, methodName);
57                                if (LOGGER.isWarnEnabled())
58                                        LOGGER.warn(String.format("Controller=%1$s Method=%2$s METHOD NOT FOUND", getClass().getSimpleName(), methodName));
59                                return null;
60                        }
61
62                        return invokeMethod(methodDescription, request, response);
63
64                } catch (UnsupportedEncodingException e) {
65                        throw new WebException(WebException.WebCode.ERROR_UNSUPPORTED_UTF8_ENCODING, e);
66                } catch (NoSuchRequestHandlingMethodException e) {
67                        throw new WebException(WebException.WebCode.ERROR_NO_REQUEST_HANDLING_METHOD, e);
68                }
69        }
70
71        @Nullable
72        private ModelAndView invokeMethod( @NotNull final MethodDescription methodDescription, @NotNull final HttpServletRequest request, @NotNull final HttpServletResponse response)
73                throws WebException
74        {
75                try {
76                        // Parse parameters
77                        final Object[] params = buildParams(methodDescription, request);
78
79                        // Invoke method (go to controller)
80                        final Object result = methodDescription.getMethod().invoke(this, params);
81                       
82                        // Return result
83                        if (!methodDescription.getView().isEmpty()) {
84                                response.setStatus(HttpServletResponse.SC_OK);
85                                if (result instanceof Map)
86                                        return new ModelAndView(methodDescription.getView(), (Map) result);
87                                else
88                                        return new ModelAndView(methodDescription.getView(), "result", result);
89                               
90                        } else if (methodDescription.isJsonResult()) {
91                                response.setStatus(HttpServletResponse.SC_OK);
92                                final String jsonResult = convertToJson(result);
93                                WebHelper.writeJsonToResponse(response, jsonResult);                           
94                                return null;
95                        } else {
96                                response.setStatus(HttpServletResponse.SC_NO_CONTENT);
97                                return null;
98                        }
99                       
100                } catch (Throwable e) {
101                        throw new WebException(e);
102                }
103        }       
104       
105        @NotNull
106        private String convertToJson( @Nullable final Object object )
107    {
108        if( null == object)
109            return JSONNull.getInstance().toString();
110        if( object instanceof JSON )
111            return object.toString();
112        if( object instanceof Collection )
113            return _jsonHelper.toJSON( (Collection) object ).toString();
114        if( object.getClass().isArray() )
115            return _jsonHelper.toJSON( object ).toString();
116        if( object instanceof Number || object instanceof Boolean || object instanceof String )
117            return JSONUtils.valueToString( object );
118        return _jsonHelper.toJSON( object ).toString();
119    }
120
121        @NotNull
122        private Object[] buildParams(@NotNull final MethodDescription methodDescription, @NotNull final HttpServletRequest request) 
123                throws InvalidParameterException
124        {
125                final List<Object> params = new ArrayList<Object>();
126                for (final ParamDescription paramDescription : methodDescription.getParams()) {
127                        if (null == paramDescription) {
128                                params.add(null);
129                                continue;
130                        }
131                        final boolean canBeNull = !paramDescription.isPrimitive() && !paramDescription.isMandatory();
132                        final String paramValue = WebHelper.getRequestParameter(request, paramDescription.getName(), null, canBeNull);
133                        final boolean useJSON = paramDescription.isUsingJSON();
134                        params.add(convertParameter(paramDescription.getType(), paramValue, useJSON));
135                }
136                return params.toArray(new Object[params.size()]);
137        }
138       
139        @Nullable
140        private Object convertParameter( @NotNull final Class paramType, @Nullable final String paramValue, final boolean useJSON )
141    {
142        if( null == paramValue )
143            return null;
144        if( useJSON )
145            return _jsonHelper.fromJSON( _jsonHelper.toJSON( paramValue ), paramType );
146        if( JSONObject.class.equals( paramType ) )
147            return _jsonHelper.toJSON( paramValue );
148        if( JSONArray.class.equals( paramType ) )
149            return _jsonHelper.toJSON( paramValue );
150        if( String.class .equals( paramType ) )
151            return paramValue;
152        if( Boolean.TYPE.equals( paramType ) || Boolean.class.equals( paramType ) )
153            return Boolean.valueOf( paramValue );
154        if( Integer.TYPE.equals( paramType ) || Integer.class.equals( paramType ) )
155            return Integer.valueOf( paramValue );
156        if( Long.TYPE.equals( paramType ) || Long.class.equals( paramType ) )
157            return Long.valueOf( paramValue );
158        if( Float.TYPE.equals( paramType ) || Float.class.equals( paramType ) )
159            return Float.valueOf( paramValue );
160        if( Double.TYPE.equals( paramType ) || Double.class.equals( paramType ) )
161            return Double.valueOf( paramValue );
162        if( Date.class.isAssignableFrom( paramType ) )
163            return new Date( Long.valueOf( paramValue ) );
164        if( paramType.isEnum() )
165            return Enum.valueOf( paramType, paramValue );
166        if( Map.class.isAssignableFrom( paramType ) )
167            return JSONObject.fromObject( paramValue );
168
169        throw new UnsupportedOperationException( "Unsupported: cast parameter to " + paramType.getName() );
170    }
171
172    private void initialize() 
173        throws WebException
174    {
175        for( final Method method : getClass().getMethods() )
176        {
177            final ControllerMethod annotation = method.getAnnotation( ControllerMethod.class );
178            if( null != annotation )
179            {
180                final MethodDescription methodDescription = new MethodDescription( method, annotation );
181                fillMethodDescription( method, methodDescription );
182                _methods.put( method.getName(), methodDescription );
183            }
184        }
185
186        _initialized = true;
187    }
188
189    private void fillMethodDescription( @NotNull final Method method, @NotNull final MethodDescription methodDescription ) 
190        throws WebException
191    {
192        final Class<?>[] paramTypes = method.getParameterTypes();
193        final Annotation[][] paramAnnotations = method.getParameterAnnotations();
194
195        if(paramTypes.length != paramAnnotations.length)
196                throw new WebException(WebException.WebCode.ERROR_NUMBER_OF_PARAM_TYPES_NOT_EQUAL_TO_PARAM_ANNOTATIONS, paramTypes.length+" "+paramAnnotations.length);
197         
198        for( int i = 0; i < paramTypes.length; ++i )
199        {
200            ParamName paramNameAnnotation = null;
201            Mandatory mandatoryAnnotation = null;
202            UseJSON useJSONAnnotation = null;
203            for( final Annotation paramAnnotation : paramAnnotations[i] )
204            {
205                if( paramAnnotation instanceof ParamName )
206                    paramNameAnnotation = (ParamName) paramAnnotation;
207                if( paramAnnotation instanceof Mandatory )
208                    mandatoryAnnotation = (Mandatory) paramAnnotation;
209                if( paramAnnotation instanceof UseJSON )
210                    useJSONAnnotation = (UseJSON) paramAnnotation;
211            }
212            if( null == paramNameAnnotation )
213                methodDescription.addNullParam();
214            else
215            {
216                final boolean mandatory = ( null != mandatoryAnnotation );
217                final boolean useJSON = ( null != useJSONAnnotation );
218                methodDescription.addParam( paramNameAnnotation.value(), paramTypes[i], mandatory, useJSON );
219            }
220        }
221    }   
222
223   
224    @Required
225    public void setMethodNameResolver( final MethodNameResolver methodNameResolver )
226    {
227        _methodNameResolver = methodNameResolver;
228    }
229
230    protected JSONHelper getJsonHelper()
231    {
232        return _jsonHelper;
233    }
234
235    @Required
236    public void setJsonHelper( final JSONHelper jsonHelper )
237    {
238        _jsonHelper = jsonHelper;
239    }
240
241    protected Map<String, MethodDescription> getMethods()
242    {
243        return _methods;
244    }
245
246    private static final Log LOGGER = LogFactory.getLog( ControllerEther.class );
247   
248    private JSONHelper _jsonHelper;
249    private MethodNameResolver _methodNameResolver;
250    private Map<String, MethodDescription> _methods = new HashMap<String, MethodDescription>();
251    private boolean _initialized; /*=false*/
252}
Note: See TracBrowser for help on using the repository browser.