source: tapas/web/src/com/ether/ControllerEther.java @ 449

Last change on this file since 449 was 449, checked in by vmipsl, 12 years ago

downloadFile to response

File size: 14.1 KB
Line 
1package com.ether;
2
3import com.ether.annotation.ControllerMethod;
4import com.ether.annotation.Mandatory;
5import com.ether.annotation.ParamName;
6import com.ether.annotation.UseJSON;
7import com.ether.user.User;
8import net.sf.json.JSON;
9import net.sf.json.JSONArray;
10import net.sf.json.JSONNull;
11import net.sf.json.JSONObject;
12import net.sf.json.util.JSONUtils;
13import org.apache.commons.logging.Log;
14import org.apache.commons.logging.LogFactory;
15import org.jetbrains.annotations.NotNull;
16import org.jetbrains.annotations.Nullable;
17import org.springframework.beans.factory.annotation.Required;
18import org.springframework.web.servlet.ModelAndView;
19import org.springframework.web.servlet.mvc.AbstractController;
20import org.springframework.web.servlet.mvc.multiaction.MethodNameResolver;
21import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
22
23import javax.servlet.http.HttpServletRequest;
24import javax.servlet.http.HttpServletResponse;
25import java.io.IOException;
26import java.io.UnsupportedEncodingException;
27import java.lang.annotation.Annotation;
28import java.lang.reflect.Method;
29import java.security.InvalidParameterException;
30import java.util.ArrayList;
31import java.util.Collection;
32import java.util.Date;
33import java.util.HashMap;
34import java.util.List;
35import java.util.Map;
36
37public class ControllerEther
38        extends AbstractController
39{
40    /**
41     * This method is used to change Locale with the framework Spring
42     *
43     * @throws WebException
44     */
45    @ControllerMethod()
46    public void setLocale()
47            throws WebException
48    {
49    }
50
51    /**
52     * This method returns a property writed in the properties file
53     *
54     * @return
55     * @throws WebException
56     */
57    public String getProperty( @NotNull final String property )
58            throws WebException
59    {
60        try
61        {
62            final String webInfPath = getServletContext().getRealPath( "WEB-INF" );
63            return WebHelper.getProperty( webInfPath + "/classes/", WebHelper.PROPERTIES_FILE, property );
64        }
65        catch( IOException e )
66        {
67            throw new WebException( WebException.WebCode.ERROR_TO_READ_FILE_PROPERTIES, e );
68        }
69    }
70
71    @Override
72    @Nullable
73    protected ModelAndView handleRequestInternal( @NotNull final HttpServletRequest request, @NotNull final HttpServletResponse response )
74            throws WebException
75    {
76        try
77        {
78            if( !_initialized )
79                initialize();
80
81            request.setCharacterEncoding( UTF8Charset.getEncoding() );
82
83            // Get method to call
84            final String methodName = _methodNameResolver.getHandlerMethodName( request );
85
86            final MethodDescription methodDescription = _methods.get( methodName );
87            if( null == methodDescription )
88            {
89                WebHelper.displayAjaxError( response, methodName );
90                if( LOGGER.isWarnEnabled() )
91                    LOGGER.warn( String.format( "Controller=%1$s Method=%2$s METHOD NOT FOUND", getClass().getSimpleName(), methodName ) );
92                return null;
93            }
94
95            return invokeMethod( methodDescription, request, response );
96        }
97        catch( UnsupportedEncodingException e )
98        {
99            throw new WebException( WebException.WebCode.ERROR_UNSUPPORTED_UTF8_ENCODING, e );
100        }
101        catch( NoSuchRequestHandlingMethodException e )
102        {
103            throw new WebException( WebException.WebCode.ERROR_NO_REQUEST_HANDLING_METHOD, e );
104        }
105    }
106
107    @Nullable
108    private ModelAndView invokeMethod( @NotNull final MethodDescription methodDescription, @NotNull final HttpServletRequest request, @NotNull final HttpServletResponse response )
109            throws WebException
110    {
111        try
112        {
113            // Parse parameters
114            final Object[] params = buildParams( methodDescription, request );
115            final String defaultView = ( null != methodDescription.getDefaultView() && !"".equals( methodDescription.getDefaultView() ) ) ? methodDescription.getDefaultView() : methodDescription.getView();
116
117
118            if( methodDescription.isRequestMandatory() )
119                params[params.length - 1] = request; //params = parametre de la methode du Controller
120
121
122            if( methodDescription.isLoginMandatory() )
123            {
124                final User user = (User) request.getSession().getAttribute( "SES_USER" );
125                if( null == user )
126                    return new ModelAndView( defaultView, "errors", "login.error.unknown" );
127            }
128
129            if( methodDescription.isUserMandatory() )
130            {
131                final User user = (User) request.getSession().getAttribute( "SES_USER" );
132                if( null == user )
133                    return new ModelAndView( defaultView, "errors", "login.error.unknown" );
134                else
135                    params[params.length - 1] = user;
136            }
137
138            if( methodDescription.isBackofficeMethod() )
139            {
140                final User user = (User) request.getSession().getAttribute( "SES_USER" );
141                if( null == user )
142                {
143                    return new ModelAndView( defaultView, "errors", "login.error.unknown" );
144                }
145                else if( null != user && !user.isAccessToBO() )
146                {
147                    return new ModelAndView( defaultView, "errors", "login.error.bo.notAccepted" );
148                }
149            }
150
151            final Object result;
152            try
153            {
154                // Invoke method (go to controller)
155                result = methodDescription.getMethod().invoke( this, params );
156            }
157            catch( Throwable e )
158            {
159                sendSerializedException( response, e.getCause() );
160                return null;
161            }
162
163            // Return result
164            if( !methodDescription.getView().isEmpty() )
165            {
166                response.setStatus( HttpServletResponse.SC_OK );
167                if( result instanceof Map )
168                    return new ModelAndView( methodDescription.getView(), (Map) result );
169                else
170                    return new ModelAndView( methodDescription.getView(), "result", result );
171            }
172            else if( methodDescription.isJsonResult() )
173            {
174                response.setStatus( HttpServletResponse.SC_OK );
175                final String jsonResult = convertToJson( result );
176                WebHelper.writeJsonToResponse( response, jsonResult );
177                return null;
178            }
179            else if( null != methodDescription.getDownloadFile() && !"".equals( methodDescription.getDownloadFile() ) )
180            {
181                final String fileName = methodDescription.getDownloadFile();
182                final String downloadPath = getProperty( "downloadPath" );
183                WebHelper.downloadFileToResponse( fileName, downloadPath, response );
184                return null;
185            }
186            else
187            {
188                response.setStatus( HttpServletResponse.SC_NO_CONTENT );
189                return null;
190            }
191        }
192        catch( Throwable e )
193        {
194            throw new WebException( e );
195        }
196    }
197
198    private void sendSerializedException( @NotNull final HttpServletResponse response, @NotNull final Throwable exception )
199            throws IOException
200    {
201        response.setStatus( WebHelper.STATUS_CODE_SERVICE_EXCEPTION );
202
203        if( exception.getCause().equals( WebException.getExceptionThrowable() ) )
204            WebHelper.writeJsonToResponse( response, exception.getLocalizedMessage() );
205        else
206            WebHelper.writeJsonToResponse( response, _jsonHelper.toJSONObject( exception ).toString() );
207    }
208
209    @NotNull
210    private String convertToJson( @Nullable final Object object )
211    {
212        if( null == object )
213            return JSONNull.getInstance().toString();
214        if( object instanceof JSON )
215            return object.toString();
216        if( object instanceof Collection )
217            return _jsonHelper.toJSON( (Collection) object ).toString();
218        if( object.getClass().isArray() )
219            return _jsonHelper.toJSON( object ).toString();
220        if( object instanceof Number || object instanceof Boolean || object instanceof String )
221            return JSONUtils.valueToString( object );
222        return _jsonHelper.toJSON( object ).toString();
223    }
224
225    @NotNull
226    private Object[] buildParams( @NotNull final MethodDescription methodDescription, @NotNull final HttpServletRequest request )
227            throws InvalidParameterException
228    {
229        final List<Object> params = new ArrayList<Object>();
230        for( final ParamDescription paramDescription : methodDescription.getParams() )
231        {
232            if( null == paramDescription )
233            {
234                params.add( null );
235                continue;
236            }
237            final boolean canBeNull = !paramDescription.isPrimitive() && !paramDescription.isMandatory();
238            final String paramValue = WebHelper.getRequestParameter( request, paramDescription.getName(), null, canBeNull );
239            final boolean useJSON = paramDescription.isUsingJSON();
240            params.add( convertParameter( paramDescription.getType(), paramValue, useJSON ) );
241        }
242        return params.toArray( new Object[params.size()] );
243    }
244
245    @Nullable
246    private Object convertParameter( @NotNull final Class paramType, @Nullable final String paramValue, final boolean useJSON )
247    {
248        if( null == paramValue )
249            return null;
250        if( useJSON )
251            return _jsonHelper.fromJSON( _jsonHelper.toJSON( paramValue ), paramType );
252        if( JSONObject.class.equals( paramType ) )
253            return _jsonHelper.toJSON( paramValue );
254        if( JSONArray.class.equals( paramType ) )
255            return _jsonHelper.toJSON( paramValue );
256        if( String.class.equals( paramType ) )
257            return paramValue;
258        if( Boolean.TYPE.equals( paramType ) || Boolean.class.equals( paramType ) )
259            return Boolean.valueOf( paramValue );
260        if( Integer.TYPE.equals( paramType ) || Integer.class.equals( paramType ) )
261            return Integer.valueOf( paramValue );
262        if( Long.TYPE.equals( paramType ) || Long.class.equals( paramType ) )
263            return Long.valueOf( paramValue );
264        if( Float.TYPE.equals( paramType ) || Float.class.equals( paramType ) )
265            return Float.valueOf( paramValue );
266        if( Double.TYPE.equals( paramType ) || Double.class.equals( paramType ) )
267            return Double.valueOf( paramValue );
268        if( Date.class.isAssignableFrom( paramType ) )
269            return new Date( Long.valueOf( paramValue ) );
270        if( paramType.isEnum() )
271            return Enum.valueOf( paramType, paramValue );
272        if( Map.class.isAssignableFrom( paramType ) )
273            return JSONObject.fromObject( paramValue );
274
275        throw new UnsupportedOperationException( "Unsupported: cast parameter to " + paramType.getName() );
276    }
277
278    private void initialize()
279            throws WebException
280    {
281        for( final Method method : getClass().getMethods() )
282        {
283            final ControllerMethod annotation = method.getAnnotation( ControllerMethod.class );
284            if( null != annotation )
285            {
286                final MethodDescription methodDescription = new MethodDescription( method, annotation );
287                fillMethodDescription( method, methodDescription );
288                _methods.put( method.getName(), methodDescription );
289            }
290        }
291
292        _initialized = true;
293    }
294
295    private void fillMethodDescription( @NotNull final Method method, @NotNull final MethodDescription methodDescription )
296            throws WebException
297    {
298        final Class<?>[] paramTypes = method.getParameterTypes();
299        final Annotation[][] paramAnnotations = method.getParameterAnnotations();
300
301        if( paramTypes.length != paramAnnotations.length )
302            throw new WebException( WebException.WebCode.ERROR_NUMBER_OF_PARAM_TYPES_NOT_EQUAL_TO_PARAM_ANNOTATIONS, paramTypes.length + " " + paramAnnotations.length );
303
304        for( int i = 0; i < paramTypes.length; ++i )
305        {
306            ParamName paramNameAnnotation = null;
307            Mandatory mandatoryAnnotation = null;
308            UseJSON useJSONAnnotation = null;
309            for( final Annotation paramAnnotation : paramAnnotations[i] )
310            {
311                if( paramAnnotation instanceof ParamName )
312                    paramNameAnnotation = (ParamName) paramAnnotation;
313                if( paramAnnotation instanceof Mandatory )
314                    mandatoryAnnotation = (Mandatory) paramAnnotation;
315                if( paramAnnotation instanceof UseJSON )
316                    useJSONAnnotation = (UseJSON) paramAnnotation;
317            }
318            if( null == paramNameAnnotation )
319                methodDescription.addNullParam();
320            else
321            {
322                final boolean mandatory = ( null != mandatoryAnnotation );
323                final boolean useJSON = ( null != useJSONAnnotation );
324                methodDescription.addParam( paramNameAnnotation.value(), paramTypes[i], mandatory, useJSON );
325            }
326        }
327    }
328
329    @Required
330    public void setMethodNameResolver( final MethodNameResolver methodNameResolver )
331    {
332        _methodNameResolver = methodNameResolver;
333    }
334
335    protected JSONHelper getJsonHelper()
336    {
337        return _jsonHelper;
338    }
339
340    @Required
341    public void setJsonHelper( final JSONHelper jsonHelper )
342    {
343        _jsonHelper = jsonHelper;
344    }
345
346    protected Map<String, MethodDescription> getMethods()
347    {
348        return _methods;
349    }
350
351    @Required
352    public void setTapasService( @NotNull final TapasService tapasService )
353    {
354        _tapasService = tapasService;
355    }
356
357    public TapasService getTapasService()
358    {
359        return _tapasService;
360    }
361
362    private static final Log LOGGER = LogFactory.getLog( ControllerEther.class );
363
364    private JSONHelper _jsonHelper;
365    private MethodNameResolver _methodNameResolver;
366    private Map<String, MethodDescription> _methods = new HashMap<String, MethodDescription>();
367    private boolean _initialized; /*=false*/
368
369    private TapasService _tapasService;
370}
Note: See TracBrowser for help on using the repository browser.