001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2005-2009 Pentaho and others
008// All Rights Reserved.
009*/
010package mondrian.tui;
011
012import java.io.*;
013import java.security.Principal;
014import java.text.ParseException;
015import java.text.SimpleDateFormat;
016import java.util.*;
017import javax.servlet.*;
018import javax.servlet.http.*;
019
020/**
021 * Partial implementation of the {@link HttpServletRequest} where just
022 * enough is present to allow for communication between Mondrian's
023 * XMLA code and other code in the same JVM.
024 *
025 * <p>Currently it is used in both the CmdRunner and in XMLA JUnit tests.
026 * If you need to add to this implementation, please do so.
027 *
028 * @author Richard M. Emberson
029 */
030public class MockHttpServletRequest implements HttpServletRequest {
031    public static String AUTHORIZATION = "Authorization";
032    public static final String DATE_FORMAT_HEADER =
033        "EEE, d MMM yyyy HH:mm:ss Z";
034
035    public static class MockRequestDispatcher implements RequestDispatcher {
036        private ServletRequest forwardedRequest;
037        private ServletResponse forwardedResponse;
038        private ServletRequest includedRequest;
039        private ServletResponse includedResponse;
040        private String path;
041
042        MockRequestDispatcher() {
043        }
044
045        public void setPath(String path) {
046            this.path = path;
047        }
048
049        public String getPath() {
050            return this.path;
051        }
052
053        public void forward(ServletRequest request, ServletResponse response)
054            throws ServletException, IOException
055        {
056            this.forwardedRequest = request;
057            this.forwardedResponse = response;
058        }
059
060        public void include(ServletRequest request, ServletResponse response)
061            throws ServletException, IOException
062        {
063            this.includedRequest = request;
064            this.includedResponse = response;
065        }
066
067        public ServletRequest getForwardedRequest() {
068            return this.forwardedRequest;
069        }
070
071        public ServletResponse getForwardedResponse() {
072            return this.forwardedResponse;
073        }
074        public ServletRequest getIncludedRequest() {
075            return this.includedRequest;
076        }
077
078        public ServletResponse getIncludedResponse() {
079            return this.includedResponse;
080        }
081    }
082    static class MockServletInputStream extends ServletInputStream {
083        private ByteArrayInputStream stream;
084
085        public MockServletInputStream(byte[] data) {
086            stream = new ByteArrayInputStream(data);
087        }
088
089        public int read() throws IOException {
090            return stream.read();
091        }
092    }
093
094
095    private HttpSession session;
096    //private ByteArrayInputStream bin;
097    private Map<String, String[]> parameters;
098    private Map<String, RequestDispatcher> requestDispatchers;
099    private List<Locale> locales;
100    private String serverName;
101    private String charEncoding;
102    private String method;
103    private String pathInfo;
104    private String pathTranslated;
105    private String contextPath;
106    private String queryString;
107    private String remoteUser;
108    private String requestedSessionId;
109    private String servletPath;
110    private String scheme;
111    private String localName;
112    private String localAddr;
113    private String authType;
114    private String protocol;
115    private String schema;
116    private Principal principal;
117    private List<Cookie> cookies;
118    private boolean requestedSessionIdIsFromCookie;
119    private int remotePort;
120    private int localPort;
121    private int serverPort;
122    private String remoteAddr;
123    private String remoteHost;
124    private Map<String, Object> attributes;
125    private final LinkedHashMap<String, List<String>> headers;
126    private boolean sessionCreated;
127    private String requestedURI;
128    private StringBuffer requestUrl;
129    private String bodyContent;
130    private Map<String, Boolean> roles;
131
132    public MockHttpServletRequest() {
133        this(new byte[0]);
134    }
135    public MockHttpServletRequest(byte[] bytes) {
136        this(new String(bytes));
137    }
138    public MockHttpServletRequest(String bodyContent) {
139        this.bodyContent = bodyContent;
140        this.attributes = Collections.emptyMap();
141        //this.bin = new ByteArrayInputStream(bytes);
142        this.headers = new LinkedHashMap<String, List<String>>();
143        this.requestDispatchers = new HashMap<String, RequestDispatcher>();
144        this.parameters = new HashMap<String, String[]>();
145        this.cookies = new ArrayList<Cookie>();
146        this.locales = new ArrayList<Locale>();
147        this.roles = new HashMap<String, Boolean>();
148        this.requestedSessionIdIsFromCookie = true;
149        this.method = "GET";
150        this.protocol = "HTTP/1.1";
151        this.serverName = "localhost";
152        this.serverPort = 8080;
153        this.scheme = "http";
154        this.remoteHost = "localhost";
155        this.remoteAddr = "127.0.0.1";
156        this.localAddr = "127.0.0.1";
157        this.localName = "localhost";
158        this.localPort = 8080;
159        this.remotePort = 5000;
160
161        this.sessionCreated = false;
162    }
163
164
165    /**
166     *  Returns the value of the named attribute as an Object, or null if no
167     *  attribute of the given name exists.
168     *
169     */
170    public Object getAttribute(String name) {
171        return this.attributes.get(name);
172    }
173
174    /**
175     * to this request.
176     *
177     */
178    public Enumeration getAttributeNames() {
179        return Collections.enumeration(attributes.keySet());
180    }
181
182    /**
183     * Returns the name of the character encoding used in the body of this
184     * request.
185     *
186     */
187    public String getCharacterEncoding() {
188        return charEncoding;
189    }
190
191    /**
192     *
193     *
194     */
195    public void setCharacterEncoding(String charEncoding)
196        throws UnsupportedEncodingException
197    {
198        this.charEncoding = charEncoding;
199    }
200
201    /**
202     *  Returns the length, in bytes, of the request body and made available by
203     *  the input stream, or -1 if the length is not known.
204     *
205     */
206    public int getContentLength() {
207        return getIntHeader("Content-Length");
208    }
209
210    /**
211     * Returns the MIME type of the body of the request, or null if the type is
212     * not known.
213     *
214     */
215    public String getContentType() {
216        return getHeader("Content-Type");
217    }
218
219    /**
220     * Retrieves the body of the request as binary data using a
221     * ServletInputStream.
222     *
223     * @throws IOException
224     */
225    public ServletInputStream getInputStream() throws IOException {
226        return new MockServletInputStream(bodyContent.getBytes());
227    }
228
229    /**
230     * Returns the value of a request parameter as a String, or null if the
231     * parameter does not exist.
232     *
233     */
234    public String getParameter(String name) {
235        String[] values = getParameterValues(name);
236        return (null != values && 0 < values.length)
237            ? values[0] : null;
238    }
239
240    /**
241     * Returns an Enumeration of String objects containing the names of the
242     * parameters contained in this request.
243     *
244     */
245    public Enumeration getParameterNames() {
246        return Collections.enumeration(parameters.keySet());
247    }
248
249    /**
250     * Returns an array of String objects containing all of the values the given
251     * request parameter has, or null if the parameter does not exist.
252     *
253     */
254    public String[] getParameterValues(String name) {
255        return parameters.get(name);
256    }
257
258
259    /**
260     * Returns the name and version of the protocol the request uses in the form
261     * protocol/majorVersion.minorVersion, for example, HTTP/1.1.
262     *
263     */
264    public String getProtocol() {
265        return protocol;
266    }
267
268    /**
269     * Returns the name of the scheme used to make this request, for example,
270     * http, https, or ftp.
271     *
272     */
273    public String getScheme() {
274        return schema;
275    }
276
277    /**
278     * Returns the host name of the server that received the request.
279     *
280     */
281    public String getServerName() {
282        return serverName;
283    }
284
285    /**
286     * Returns the port number on which this request was received.
287     *
288     */
289    public int getServerPort() {
290        return serverPort;
291    }
292
293    /**
294     * Retrieves the body of the request as character data using a
295     * BufferedReader.
296     *
297     * @throws IOException
298     */
299    public BufferedReader getReader() throws IOException {
300        return (bodyContent == null)
301            ? null
302            : new BufferedReader(new StringReader(bodyContent));
303    }
304
305    /**
306     * Returns the Internet Protocol (IP) address of the client that sent the
307     * request.
308     *
309     */
310    public String getRemoteAddr() {
311        return remoteAddr;
312    }
313
314    /**
315     * Returns the fully qualified name of the client that sent the request, or
316     * the IP address of the client if the name cannot be determined.
317     *
318     */
319    public String getRemoteHost() {
320        return remoteHost;
321    }
322
323    /**
324     *  Stores an attribute in this request.
325     *
326     */
327    public void setAttribute(String name, Object obj) {
328        if (attributes == Collections.EMPTY_MAP) {
329            attributes = new HashMap<String, Object>();
330        }
331        this.attributes.put(name, obj);
332    }
333
334    /**
335     *  Removes an attribute from this request.
336     *
337     */
338    public void removeAttribute(String name) {
339        this.attributes.remove(name);
340    }
341
342    /**
343     * Returns the preferred Locale that the client will accept content in,
344     * based on the Accept-Language header.
345     *
346     */
347    public Locale getLocale() {
348        return (locales.size() < 1)
349            ? Locale.getDefault()
350            : locales.get(0);
351    }
352
353    /**
354     * Returns an Enumeration of Locale objects indicating, in decreasing order
355     * starting with the preferred locale, the locales that are acceptable to
356     * the client based on the Accept-Language header.
357     *
358     */
359    public Enumeration getLocales() {
360        return Collections.enumeration(locales);
361    }
362
363    /**
364     *  Returns a boolean indicating whether this request was made using a
365     *  secure channel, such as HTTPS.
366     *
367     */
368    public boolean isSecure() {
369        String scheme = getScheme();
370        return (scheme == null)
371            ? false
372            : scheme.equals("https");
373    }
374
375    /**
376     * Returns a RequestDispatcher object that acts as a wrapper for the
377     * resource located at the given path.
378     *
379     */
380    public RequestDispatcher getRequestDispatcher(String path) {
381        RequestDispatcher dispatcher =
382            requestDispatchers.get(path);
383        if (dispatcher == null) {
384            dispatcher = new MockRequestDispatcher();
385            setRequestDispatcher(path, dispatcher);
386        }
387        return dispatcher;
388    }
389
390    /**
391     * Deprecated. As of Version 2.1 of the Java Servlet API, use
392     * ServletContext.getRealPath(java.lang.String) instead.
393     * @deprecated Method getRealPath is deprecated
394     *
395     */
396    public String getRealPath(String path) {
397        HttpSession session = getSession();
398        return (session == null)
399            ? null
400            : session.getServletContext().getRealPath(path);
401    }
402
403    /**
404     *
405     *
406     */
407    public int getRemotePort() {
408        return remotePort;
409    }
410
411    /**
412     *
413     *
414     */
415    public String getLocalName() {
416        return localName;
417    }
418
419    /**
420     *
421     *
422     */
423    public String getLocalAddr() {
424        return localAddr;
425    }
426
427    /**
428     *
429     *
430     */
431    public int getLocalPort() {
432        return localPort;
433    }
434
435    /**
436     * Returns the name of the authentication scheme used to protect the
437     * servlet, for example, "BASIC" or "SSL," or null if the servlet was not
438     * protected.
439     *
440     */
441    public String getAuthType() {
442        return authType;
443    }
444
445    /**
446     * Returns an array containing all of the Cookie objects the client sent
447     * with this request.
448     *
449     */
450    public Cookie[] getCookies() {
451        return cookies.toArray(new Cookie[cookies.size()]);
452    }
453
454    /**
455     * Returns the value of the specified request header as a long value that
456     * represents a Date object.
457     *
458     */
459    public long getDateHeader(String name) {
460        String header = getHeader(name);
461        if (header == null) {
462            return -1;
463        }
464        try {
465            Date dateValue =
466                new SimpleDateFormat(
467                    DATE_FORMAT_HEADER, Locale.US).parse(header);
468            return dateValue.getTime();
469        } catch (ParseException exc) {
470            throw new IllegalArgumentException(exc.getMessage());
471        }
472    }
473
474    /**
475     * Returns the value of the specified request header as a String.
476     *
477     */
478    public String getHeader(String name) {
479        List<String> headerList = headers.get(name);
480
481        return ((headerList == null) || (headerList.size() == 0))
482            ? null
483            : headerList.get(0);
484    }
485
486    /**
487     *  Returns all the values of the specified request header as an Enumeration
488     *  of String objects.
489     *
490     */
491    public Enumeration getHeaders(String name) {
492        List<String> headerList = headers.get(name);
493        return (headerList == null)
494            ? null
495            : Collections.enumeration(headerList);
496    }
497
498    /**
499     * Returns an enumeration of all the header names this request contains.
500     *
501     */
502    public Enumeration getHeaderNames() {
503        return Collections.enumeration(headers.keySet());
504    }
505
506    /**
507     * Returns the value of the specified request header as an int.
508     *
509     */
510    public int getIntHeader(String name) {
511        String header = getHeader(name);
512        return (header == null)
513            ? -1
514            : Integer.parseInt(header);
515    }
516
517    /**
518     * Returns the name of the HTTP method with which this request was made, for
519     * example, GET, POST, or PUT.
520     *
521     */
522    public String getMethod() {
523        return this.method;
524    }
525
526    /**
527     * Returns any extra path information associated with the URL the client
528     * sent when it made this request.
529     *
530     */
531    public String getPathInfo() {
532        return pathInfo;
533    }
534
535    /**
536     * Returns any extra path information after the servlet name but before the
537     * query string, and translates it to a real path.
538     *
539     */
540    public String getPathTranslated() {
541        return pathTranslated;
542    }
543
544    /**
545     * Returns the portion of the request URI that indicates the context of the
546     * request.
547     *
548     */
549    public String getContextPath() {
550        return contextPath;
551    }
552
553    /**
554     * Returns the query string that is contained in the request URL after the
555     * path.
556     *
557     */
558    public String getQueryString() {
559        return queryString;
560    }
561
562    /**
563     * Returns the login of the user making this request, if the user has been
564     * authenticated, or null if the user has not been authenticated.
565     *
566     */
567    public String getRemoteUser() {
568        return remoteUser;
569    }
570
571    /**
572     *  Returns a boolean indicating whether the authenticated user is included
573     *  in the specified logical "role".
574     *
575     */
576    public boolean isUserInRole(String role) {
577        return roles.get(role);
578    }
579
580    /**
581     *  Returns a java.security.Principal object containing the name of the
582     *  current authenticated user.
583     *
584     */
585    public Principal getUserPrincipal() {
586        return principal;
587    }
588
589    /**
590     * Returns the session ID specified by the client.
591     *
592     */
593    public String getRequestedSessionId() {
594        HttpSession session = getSession();
595        return (session == null)
596            ? null
597            : session.getId();
598    }
599
600    /**
601     * Returns the part of this request's URL from the protocol name up to the
602     * query string in the first line of the HTTP request.
603     *
604     */
605    public String getRequestURI() {
606        return requestedURI;
607    }
608
609    /**
610     *
611     *
612     */
613    public StringBuffer getRequestURL() {
614        return requestUrl;
615    }
616
617    /**
618     * Returns the part of this request's URL that calls the servlet.
619     *
620     */
621    public String getServletPath() {
622        return servletPath;
623    }
624
625    /**
626     * Returns the current HttpSession associated with this request or, if if
627     * there is no current session and create is true, returns a new session.
628     *
629     */
630    public HttpSession getSession(boolean create) {
631        if (! create && ! sessionCreated) {
632            return null;
633        }
634        return getSession();
635    }
636
637    /**
638     *  Returns the current session associated with this request, or if the
639     *  request does not have a session, creates one.
640     *
641     */
642    public HttpSession getSession() {
643        sessionCreated = true;
644        return session;
645    }
646
647    /**
648     * Checks whether the requested session ID is still valid.
649     *
650     */
651    public boolean isRequestedSessionIdValid() {
652        HttpSession session = getSession();
653        return (session != null);
654    }
655
656    /**
657     * Checks whether the requested session ID came in as a cookie.
658     *
659     */
660    public boolean isRequestedSessionIdFromCookie() {
661        return requestedSessionIdIsFromCookie;
662    }
663
664    /**
665     *  Checks whether the requested session ID came in as part of the request
666     *  URL.
667     *
668     */
669    public boolean isRequestedSessionIdFromURL() {
670        return !requestedSessionIdIsFromCookie;
671    }
672
673    public boolean isRequestedSessionIdFromUrl() {
674        // deprecated as of version 2.1 of Servlet API.
675        return isRequestedSessionIdFromURL();
676    }
677
678    /////////////////////////////////////////////////////////////////////////
679    //
680    // implementation access
681    //
682    /////////////////////////////////////////////////////////////////////////
683/*
684    public void setBytes(byte[] bytes) {
685        this.bin = new ByteArrayInputStream(bytes);
686    }
687*/
688    /**
689     *
690     *
691     */
692    public Map getParameterMap() {
693        return Collections.unmodifiableMap(parameters);
694    }
695
696    public void setServerName(String serverName) {
697        this.serverName = serverName;
698    }
699    public void setRemoteHost(String remoteHost) {
700        this.remoteHost = remoteHost;
701    }
702    public void setRemoteAddr(String remoteAddr) {
703        this.remoteAddr = remoteAddr;
704    }
705    public void setMethod(String method) {
706        this.method = method;
707    }
708    public void setPathInfo(String pathInfo) {
709        this.pathInfo = pathInfo;
710    }
711    public void setPathTranslated(String pathTranslated) {
712        this.pathTranslated = pathTranslated;
713    }
714    public void setContextPath(String contextPath) {
715        this.contextPath = contextPath;
716    }
717    public void setQueryString(String queryString) {
718        this.queryString = queryString;
719    }
720    public void setRemoteUser(String remoteUser) {
721        this.remoteUser = remoteUser;
722    }
723    public void setRequestedSessionId(String requestedSessionId) {
724        this.requestedSessionId = requestedSessionId;
725    }
726    public void setRequestURI(String requestedURI) {
727        this.requestedURI = requestedURI;
728    }
729    public void setServletPath(String servletPath) {
730        this.servletPath = servletPath;
731    }
732    public void setLocalName(String localName) {
733        this.localName = localName;
734    }
735    public void setLocalAddr(String localAddr) {
736        this.localAddr = localAddr;
737    }
738    public void setAuthType(String authType) {
739        this.authType = authType;
740    }
741    public void setProtocol(String protocol) {
742        this.protocol = protocol;
743    }
744    public void setScheme(String schema) {
745        this.schema = schema;
746    }
747
748    public void setRemotePort(int remotePort) {
749        this.remotePort = remotePort;
750    }
751    public void setLocalPort(int localPort) {
752        this.localPort = localPort;
753    }
754    public void setServerPort(int serverPort) {
755        this.serverPort = serverPort;
756    }
757
758    public void setContentType(String contentType) {
759        setHeader("Content-Type", contentType);
760    }
761    public void setHeader(String name, String value) {
762        List<String> valueList = headers.get(name);
763        if (valueList == null) {
764            valueList = new ArrayList<String>();
765            headers.put(name, valueList);
766        }
767        valueList.add(value);
768    }
769    /////////////////////////////////////////////////////////////////////////
770    //
771    // helpers
772    //
773    /////////////////////////////////////////////////////////////////////////
774
775    public void clearParameters() {
776        parameters.clear();
777    }
778
779    public void setupAddParameter(String key, String[] values) {
780        parameters.put(key, values);
781    }
782    public void setupAddParameter(String key, String value) {
783        setupAddParameter(key, new String[] { value });
784    }
785
786    public void clearAttributes() {
787        attributes.clear();
788    }
789
790    public void setSession(HttpSession session) {
791        this.session = session;
792    }
793
794    public Map<String, RequestDispatcher> getRequestDispatcherMap() {
795        return Collections.unmodifiableMap(requestDispatchers);
796    }
797
798    public void setRequestDispatcher(
799        String path,
800        RequestDispatcher dispatcher)
801    {
802        if (dispatcher instanceof MockRequestDispatcher) {
803            ((MockRequestDispatcher)dispatcher).setPath(path);
804        }
805        requestDispatchers.put(path, dispatcher);
806    }
807
808    public void addLocale(Locale locale) {
809        locales.add(locale);
810    }
811
812    public void addLocales(List<Locale> localeList) {
813        locales.addAll(localeList);
814    }
815
816    public void addHeader(String key, String value) {
817        List<String> valueList = headers.get(key);
818        if (valueList == null) {
819            valueList = new ArrayList<String>();
820            headers.put(key, valueList);
821        }
822        valueList.add(value);
823    }
824    public void clearHeader(String key) {
825        headers.remove(key);
826    }
827
828    public void setRequestURL(String requestUrl) {
829        this.requestUrl = new StringBuffer(requestUrl);
830    }
831
832    public void setUserPrincipal(Principal principal) {
833        this.principal = principal;
834    }
835
836    public void addCookie(Cookie cookie) {
837        cookies.add(cookie);
838    }
839
840    public void setRequestedSessionIdFromCookie(
841        boolean requestedSessionIdIsFromCookie)
842    {
843        this.requestedSessionIdIsFromCookie = requestedSessionIdIsFromCookie;
844    }
845
846    public void setUserInRole(String role, boolean isInRole) {
847        roles.put(role, isInRole);
848    }
849
850    public void setBodyContent(byte[] data) {
851        setBodyContent(new String(data));
852    }
853
854    public void setBodyContent(String bodyContent) {
855        this.bodyContent = bodyContent;
856    }
857
858
859}
860
861// End MockHttpServletRequest.java