source: ether_ndacc/trunk/web/src/com/ether/ControllerEther.java @ 204

Last change on this file since 204 was 204, checked in by vmipsl, 13 years ago

[Internationalisation]

File size: 9.2 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, EtherException
44    {
45                try {
46                        if (!_initialized)
47                                initialize();
48
49
50                        request.setCharacterEncoding(UTF8Charset.getEncoding());
51
52                        final String methodName = _methodNameResolver.getHandlerMethodName(request);
53
54                        final MethodDescription methodDescription = _methods.get(methodName);
55                        if (null == methodDescription) {
56                                WebHelper.displayError( response, methodName );
57                                return null;
58                        }
59
60                        return invokeMethod(methodDescription, request, response);
61                } catch (UnsupportedEncodingException e) {
62                        throw new WebException(WebException.WebCode.ERROR_UNSUPPORTED_UTF8_ENCODING, e);
63                } catch (NoSuchRequestHandlingMethodException e) {
64                        throw new WebException(WebException.WebCode.ERROR_NO_REQUEST_HANDLING_METHOD, e);
65                }
66        }
67
68        @Nullable
69        private ModelAndView invokeMethod( @NotNull final MethodDescription methodDescription, @NotNull final HttpServletRequest request, @NotNull final HttpServletResponse response)
70                throws WebException
71        {
72                try {
73                        // Parse parameters
74                        final Object[] params = buildParams(methodDescription, request);
75
76                        // Invoke method (go to controller)
77                        final Object result = methodDescription.getMethod().invoke(this, params);
78
79                        if (!methodDescription.getView().isEmpty()) {
80                                response.setStatus(HttpServletResponse.SC_OK);
81                                if (result instanceof Map)
82                                        return new ModelAndView(methodDescription.getView(), (Map) result);
83                                else
84                                        return new ModelAndView(methodDescription.getView(), "result", result);
85
86                        } else if (methodDescription.isJsonResult()) {
87                                response.setStatus(HttpServletResponse.SC_OK);
88                                final String jsonResult = convertToJson(result);
89                                WebHelper.writeJsonToResponse(response, jsonResult);
90                                return null;
91                        } else {
92                                response.setStatus(HttpServletResponse.SC_NO_CONTENT);
93                                return null;
94                        }
95                } catch (Throwable e) {
96                        throw new WebException(e);
97                }
98        }
99
100        @NotNull
101        private String convertToJson( @Nullable final Object object )
102    {
103        if( null == object)
104            return JSONNull.getInstance().toString();
105        if( object instanceof JSON )
106            return object.toString();
107        if( object instanceof Collection )
108            return _jsonHelper.toJSON( (Collection) object ).toString();
109        if( object.getClass().isArray() )
110            return _jsonHelper.toJSON( object ).toString();
111        if( object instanceof Number || object instanceof Boolean || object instanceof String )
112            return JSONUtils.valueToString( object );
113        return _jsonHelper.toJSON( object ).toString();
114    }
115
116        @NotNull
117        private Object[] buildParams(@NotNull final MethodDescription methodDescription, @NotNull final HttpServletRequest request)
118                throws InvalidParameterException
119        {
120                final List<Object> params = new ArrayList<Object>();
121                for (final ParamDescription paramDescription : methodDescription.getParams()) {
122                        if (null == paramDescription) {
123                                params.add(null);
124                                continue;
125                        }
126                        final boolean canBeNull = !paramDescription.isPrimitive() && !paramDescription.isMandatory();
127                        final String paramValue = WebHelper.getRequestParameter(request, paramDescription.getName(), null, canBeNull);
128                        final boolean useJSON = paramDescription.isUsingJSON();
129                        params.add(convertParameter(paramDescription.getType(), paramValue, useJSON));
130                }
131                return params.toArray(new Object[params.size()]);
132        }
133
134        @Nullable
135        private Object convertParameter( @NotNull final Class paramType, @Nullable final String paramValue, final boolean useJSON )
136    {
137        if( null == paramValue )
138            return null;
139        if( useJSON )
140            return _jsonHelper.fromJSON( _jsonHelper.toJSON( paramValue ), paramType );
141        if( JSONObject.class.equals( paramType ) )
142            return _jsonHelper.toJSON( paramValue );
143        if( JSONArray.class.equals( paramType ) )
144            return _jsonHelper.toJSON( paramValue );
145        if( String.class .equals( paramType ) )
146            return paramValue;
147        if( Boolean.TYPE.equals( paramType ) || Boolean.class.equals( paramType ) )
148            return Boolean.valueOf( paramValue );
149        if( Integer.TYPE.equals( paramType ) || Integer.class.equals( paramType ) )
150            return Integer.valueOf( paramValue );
151        if( Long.TYPE.equals( paramType ) || Long.class.equals( paramType ) )
152            return Long.valueOf( paramValue );
153        if( Float.TYPE.equals( paramType ) || Float.class.equals( paramType ) )
154            return Float.valueOf( paramValue );
155        if( Double.TYPE.equals( paramType ) || Double.class.equals( paramType ) )
156            return Double.valueOf( paramValue );
157        if( Date.class.isAssignableFrom( paramType ) )
158            return new Date( Long.valueOf( paramValue ) );
159        if( paramType.isEnum() )
160            return Enum.valueOf( paramType, paramValue );
161        if( Map.class.isAssignableFrom( paramType ) )
162            return JSONObject.fromObject( paramValue );
163
164        throw new UnsupportedOperationException( "Unsupported: cast parameter to " + paramType.getName() );
165    }
166
167    private void initialize()
168        throws WebException
169    {
170        for( final Method method : getClass().getMethods() )
171        {
172            final ControllerMethod annotation = method.getAnnotation( ControllerMethod.class );
173            if( null != annotation )
174            {
175                final MethodDescription methodDescription = new MethodDescription( method, annotation );
176                fillMethodDescription( method, methodDescription );
177                _methods.put( method.getName(), methodDescription );
178            }
179        }
180
181        _initialized = true;
182    }
183
184    private void fillMethodDescription( @NotNull final Method method, @NotNull final MethodDescription methodDescription )
185        throws WebException
186    {
187        final Class<?>[] paramTypes = method.getParameterTypes();
188        final Annotation[][] paramAnnotations = method.getParameterAnnotations();
189
190        if(paramTypes.length != paramAnnotations.length)
191                throw new WebException(WebException.WebCode.ERROR_NUMBER_OF_PARAM_TYPES_NOT_EQUAL_TO_PARAM_ANNOTATIONS, paramTypes.length+" "+paramAnnotations.length);
192
193        for( int i = 0; i < paramTypes.length; ++i )
194        {
195            ParamName paramNameAnnotation = null;
196            Mandatory mandatoryAnnotation = null;
197            UseJSON useJSONAnnotation = null;
198            for( final Annotation paramAnnotation : paramAnnotations[i] )
199            {
200                if( paramAnnotation instanceof ParamName )
201                    paramNameAnnotation = (ParamName) paramAnnotation;
202                if( paramAnnotation instanceof Mandatory )
203                    mandatoryAnnotation = (Mandatory) paramAnnotation;
204                if( paramAnnotation instanceof UseJSON )
205                    useJSONAnnotation = (UseJSON) paramAnnotation;
206            }
207            if( null == paramNameAnnotation )
208                methodDescription.addNullParam();
209            else
210            {
211                final boolean mandatory = ( null != mandatoryAnnotation );
212                final boolean useJSON = ( null != useJSONAnnotation );
213                methodDescription.addParam( paramNameAnnotation.value(), paramTypes[i], mandatory, useJSON );
214            }
215        }
216    }
217
218    @Required
219    public void setMethodNameResolver( final MethodNameResolver methodNameResolver )
220    {
221        _methodNameResolver = methodNameResolver;
222    }
223
224    protected JSONHelper getJsonHelper()
225    {
226        return _jsonHelper;
227    }
228
229    @Required
230    public void setJsonHelper( final JSONHelper jsonHelper )
231    {
232        _jsonHelper = jsonHelper;
233    }
234
235    protected Map<String, MethodDescription> getMethods()
236    {
237        return _methods;
238    }
239
240    private static final Log LOGGER = LogFactory.getLog( ControllerEther.class );
241
242    private JSONHelper _jsonHelper;
243    private MethodNameResolver _methodNameResolver;
244    private Map<String, MethodDescription> _methods = new HashMap<String, MethodDescription>();
245    private boolean _initialized; /*=false*/
246}
Note: See TracBrowser for help on using the repository browser.