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

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

properties webmaster
dataProtocol

File size: 15.0 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            if( methodDescription.isRequestMandatory() )
123                params[params.length - 1] = request;
124
125            if( methodDescription.isLoginMandatory() )
126            {
127                final User user = (User) request.getSession().getAttribute( "SES_USER" );
128                if( null == user )
129                    return new ModelAndView( defaultView, "errors", "login.error.unknown" );
130            }
131
132            if( methodDescription.isBackofficeMethod() )
133            {
134                final User user = (User) request.getSession().getAttribute( "SES_USER" );
135                if( null == user )
136                {
137                    return new ModelAndView( defaultView, "errors", "login.error.unknown" );
138                }
139                else if( null != user && !user.isAccessToBO() )
140                {
141                    return new ModelAndView( defaultView, "errors", "login.error.bo.notAccepted" );
142                }
143            }
144
145            final Object result;
146            try
147            {
148                // Invoke method (go to controller)
149                result = methodDescription.getMethod().invoke( this, params );
150            }
151            catch( Throwable e )
152            {
153                sendSerializedException( response, e.getCause() );
154                return null;
155            }
156
157            // Return result
158            if( !methodDescription.getView().isEmpty() )
159            {
160                response.setStatus( HttpServletResponse.SC_OK );
161                if( result instanceof Map )
162                    return new ModelAndView( methodDescription.getView(), (Map) result );
163                else
164                    return new ModelAndView( methodDescription.getView(), "result", result );
165            }
166            else if( methodDescription.isJsonResult() )
167            {
168                response.setStatus( HttpServletResponse.SC_OK );
169                final String jsonResult = convertToJson( result );
170                WebHelper.writeJsonToResponse( response, jsonResult );
171                return null;
172            }
173            else if( null != methodDescription.getDownloadFile() && !"".equals( methodDescription.getDownloadFile() ) )
174            {
175                final String fileName = methodDescription.getDownloadFile();
176                final String downloadPath = getProperty( "downloadPath" );
177
178                response.setContentType( "multipart/zip" );
179                response.setHeader( "Content-Disposition", "attachment; filename=\"" + fileName.trim() + "\";" );
180
181                final File file = new File( downloadPath + fileName );
182                if( !file.exists() )
183                    throw new WebException( WebException.WebCode.ERROR_TO_DOWNLOAD_FILE, file.getPath() );
184
185                response.setContentLength( (int) file.length() );
186                try
187                {
188                    final OutputStream outputStream = response.getOutputStream();
189                    final FileInputStream fileInputStream = new FileInputStream( file );
190
191                    final BufferedInputStream bufferedInputStream = new BufferedInputStream( fileInputStream );
192                    final InputStream inputStream = new BufferedInputStream( bufferedInputStream );
193
194                    int count;
195                    final byte[] buf = new byte[4096];
196                    while( ( count = inputStream.read( buf ) ) > -1 )
197                        outputStream.write( buf, 0, count );
198                    inputStream.close();
199                    outputStream.close();
200                }
201                catch( Exception ex )
202                {
203                    throw new WebException( WebException.WebCode.ERROR_TO_DOWNLOAD_FILE, ex );
204                }
205                return null;
206            }
207            else
208            {
209                response.setStatus( HttpServletResponse.SC_NO_CONTENT );
210                return null;
211            }
212        }
213        catch( Throwable e )
214        {
215            throw new WebException( e );
216        }
217    }
218
219    private void sendSerializedException( @NotNull final HttpServletResponse response, @NotNull final Throwable exception )
220            throws IOException
221    {
222        response.setStatus( WebHelper.STATUS_CODE_SERVICE_EXCEPTION );
223
224        if( exception.getCause().equals( WebException.getExceptionThrowable() ) )
225            WebHelper.writeJsonToResponse( response, exception.getLocalizedMessage() );
226        else
227            WebHelper.writeJsonToResponse( response, _jsonHelper.toJSONObject( exception ).toString() );
228    }
229
230    @NotNull
231    private String convertToJson( @Nullable final Object object )
232    {
233        if( null == object )
234            return JSONNull.getInstance().toString();
235        if( object instanceof JSON )
236            return object.toString();
237        if( object instanceof Collection )
238            return _jsonHelper.toJSON( (Collection) object ).toString();
239        if( object.getClass().isArray() )
240            return _jsonHelper.toJSON( object ).toString();
241        if( object instanceof Number || object instanceof Boolean || object instanceof String )
242            return JSONUtils.valueToString( object );
243        return _jsonHelper.toJSON( object ).toString();
244    }
245
246    @NotNull
247    private Object[] buildParams( @NotNull final MethodDescription methodDescription, @NotNull final HttpServletRequest request )
248            throws InvalidParameterException
249    {
250        final List<Object> params = new ArrayList<Object>();
251        for( final ParamDescription paramDescription : methodDescription.getParams() )
252        {
253            if( null == paramDescription )
254            {
255                params.add( null );
256                continue;
257            }
258            final boolean canBeNull = !paramDescription.isPrimitive() && !paramDescription.isMandatory();
259            final String paramValue = WebHelper.getRequestParameter( request, paramDescription.getName(), null, canBeNull );
260            final boolean useJSON = paramDescription.isUsingJSON();
261            params.add( convertParameter( paramDescription.getType(), paramValue, useJSON ) );
262        }
263        return params.toArray( new Object[params.size()] );
264    }
265
266    @Nullable
267    private Object convertParameter( @NotNull final Class paramType, @Nullable final String paramValue, final boolean useJSON )
268    {
269        if( null == paramValue )
270            return null;
271        if( useJSON )
272            return _jsonHelper.fromJSON( _jsonHelper.toJSON( paramValue ), paramType );
273        if( JSONObject.class.equals( paramType ) )
274            return _jsonHelper.toJSON( paramValue );
275        if( JSONArray.class.equals( paramType ) )
276            return _jsonHelper.toJSON( paramValue );
277        if( String.class.equals( paramType ) )
278            return paramValue;
279        if( Boolean.TYPE.equals( paramType ) || Boolean.class.equals( paramType ) )
280            return Boolean.valueOf( paramValue );
281        if( Integer.TYPE.equals( paramType ) || Integer.class.equals( paramType ) )
282            return Integer.valueOf( paramValue );
283        if( Long.TYPE.equals( paramType ) || Long.class.equals( paramType ) )
284            return Long.valueOf( paramValue );
285        if( Float.TYPE.equals( paramType ) || Float.class.equals( paramType ) )
286            return Float.valueOf( paramValue );
287        if( Double.TYPE.equals( paramType ) || Double.class.equals( paramType ) )
288            return Double.valueOf( paramValue );
289        if( Date.class.isAssignableFrom( paramType ) )
290            return new Date( Long.valueOf( paramValue ) );
291        if( paramType.isEnum() )
292            return Enum.valueOf( paramType, paramValue );
293        if( Map.class.isAssignableFrom( paramType ) )
294            return JSONObject.fromObject( paramValue );
295
296        throw new UnsupportedOperationException( "Unsupported: cast parameter to " + paramType.getName() );
297    }
298
299    private void initialize()
300            throws WebException
301    {
302        for( final Method method : getClass().getMethods() )
303        {
304            final ControllerMethod annotation = method.getAnnotation( ControllerMethod.class );
305            if( null != annotation )
306            {
307                final MethodDescription methodDescription = new MethodDescription( method, annotation );
308                fillMethodDescription( method, methodDescription );
309                _methods.put( method.getName(), methodDescription );
310            }
311        }
312
313        _initialized = true;
314    }
315
316    private void fillMethodDescription( @NotNull final Method method, @NotNull final MethodDescription methodDescription )
317            throws WebException
318    {
319        final Class<?>[] paramTypes = method.getParameterTypes();
320        final Annotation[][] paramAnnotations = method.getParameterAnnotations();
321
322        if( paramTypes.length != paramAnnotations.length )
323            throw new WebException( WebException.WebCode.ERROR_NUMBER_OF_PARAM_TYPES_NOT_EQUAL_TO_PARAM_ANNOTATIONS, paramTypes.length + " " + paramAnnotations.length );
324
325        for( int i = 0; i < paramTypes.length; ++i )
326        {
327            ParamName paramNameAnnotation = null;
328            Mandatory mandatoryAnnotation = null;
329            UseJSON useJSONAnnotation = null;
330            for( final Annotation paramAnnotation : paramAnnotations[i] )
331            {
332                if( paramAnnotation instanceof ParamName )
333                    paramNameAnnotation = (ParamName) paramAnnotation;
334                if( paramAnnotation instanceof Mandatory )
335                    mandatoryAnnotation = (Mandatory) paramAnnotation;
336                if( paramAnnotation instanceof UseJSON )
337                    useJSONAnnotation = (UseJSON) paramAnnotation;
338            }
339            if( null == paramNameAnnotation )
340                methodDescription.addNullParam();
341            else
342            {
343                final boolean mandatory = ( null != mandatoryAnnotation );
344                final boolean useJSON = ( null != useJSONAnnotation );
345                methodDescription.addParam( paramNameAnnotation.value(), paramTypes[i], mandatory, useJSON );
346            }
347        }
348    }
349
350    @Required
351    public void setMethodNameResolver( final MethodNameResolver methodNameResolver )
352    {
353        _methodNameResolver = methodNameResolver;
354    }
355
356    protected JSONHelper getJsonHelper()
357    {
358        return _jsonHelper;
359    }
360
361    @Required
362    public void setJsonHelper( final JSONHelper jsonHelper )
363    {
364        _jsonHelper = jsonHelper;
365    }
366
367    protected Map<String, MethodDescription> getMethods()
368    {
369        return _methods;
370    }
371
372    @Required
373    public void setTapasService( @NotNull final TapasService tapasService )
374    {
375        _tapasService = tapasService;
376    }
377
378    public TapasService getTapasService()
379    {
380        return _tapasService;
381    }
382
383    private static final Log LOGGER = LogFactory.getLog( ControllerEther.class );
384
385    private JSONHelper _jsonHelper;
386    private MethodNameResolver _methodNameResolver;
387    private Map<String, MethodDescription> _methods = new HashMap<String, MethodDescription>();
388    private boolean _initialized; /*=false*/
389
390    private TapasService _tapasService;
391}
Note: See TracBrowser for help on using the repository browser.