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

Last change on this file since 440 was 440, checked in by rboipsl, 12 years ago

ajout anotations
usermandatory

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