001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020
021 package org.granite.messaging.webapp;
022
023 import java.io.BufferedReader;
024 import java.io.IOException;
025 import java.io.PrintWriter;
026 import java.io.UnsupportedEncodingException;
027 import java.security.Principal;
028 import java.util.AbstractMap;
029 import java.util.Collection;
030 import java.util.Enumeration;
031 import java.util.HashMap;
032 import java.util.HashSet;
033 import java.util.Hashtable;
034 import java.util.Locale;
035 import java.util.Map;
036 import java.util.Set;
037
038 import javax.servlet.AsyncContext;
039 import javax.servlet.DispatcherType;
040 import javax.servlet.RequestDispatcher;
041 import javax.servlet.ServletContext;
042 import javax.servlet.ServletException;
043 import javax.servlet.ServletInputStream;
044 import javax.servlet.ServletOutputStream;
045 import javax.servlet.ServletRequest;
046 import javax.servlet.ServletResponse;
047 import javax.servlet.http.Cookie;
048 import javax.servlet.http.HttpServletRequest;
049 import javax.servlet.http.HttpServletResponse;
050 import javax.servlet.http.HttpSession;
051 import javax.servlet.http.Part;
052
053 import org.granite.clustering.TransientReference;
054 import org.granite.clustering.TransientReferenceHolder;
055 import org.granite.config.GraniteConfig;
056 import org.granite.config.GraniteConfigListener;
057 import org.granite.config.flex.ServicesConfig;
058 import org.granite.context.GraniteContext;
059
060 /**
061 * @author Franck WOLFF
062 */
063 public class ServletGraniteContext extends GraniteContext {
064
065 private final ServletContext servletContext;
066
067 protected InitialisationMap initialisationMap = null;
068 protected ApplicationMap applicationMap = null;
069 protected SessionMap sessionMap = null;
070 protected HttpServletRequest request = null;
071 protected HttpServletResponse response = null;
072 protected HttpSession session = null;
073
074
075 public static ServletGraniteContext createThreadInstance(
076 GraniteConfig graniteConfig,
077 ServicesConfig servicesConfig,
078 ServletContext context,
079 String sessionId,
080 String clientType) {
081
082 ServletGraniteContext graniteContext = new ServletGraniteContext(graniteConfig, servicesConfig, context, sessionId, clientType);
083 setCurrentInstance(graniteContext);
084 return graniteContext;
085 }
086
087 public static ServletGraniteContext createThreadInstance(
088 GraniteConfig graniteConfig,
089 ServicesConfig servicesConfig,
090 ServletContext context,
091 HttpSession session,
092 String clientType) {
093
094 ServletGraniteContext graniteContext = new ServletGraniteContext(graniteConfig, servicesConfig, context, session, clientType);
095 setCurrentInstance(graniteContext);
096 return graniteContext;
097 }
098
099
100 protected ServletGraniteContext(
101 GraniteConfig graniteConfig,
102 ServicesConfig servicesConfig,
103 ServletContext servletContext,
104 String sessionId,
105 String clientType) {
106
107 super(graniteConfig, servicesConfig, sessionId, clientType);
108 this.servletContext = servletContext;
109 }
110
111 protected ServletGraniteContext(
112 GraniteConfig graniteConfig,
113 ServicesConfig servicesConfig,
114 ServletContext servletContext,
115 HttpSession session,
116 String clientType) {
117
118 super(graniteConfig, servicesConfig, session.getId(), clientType);
119 this.servletContext = servletContext;
120 this.session = session;
121 }
122
123 public ServletContext getServletContext() {
124 return servletContext;
125 }
126
127 public HttpServletRequest getRequest() {
128 if (request == null)
129 request = new BasicRequest();
130 return request;
131 }
132
133 public HttpServletResponse getResponse() {
134 if (response == null)
135 response = new BasicResponse();
136 return response;
137 }
138
139 public HttpSession getSession(boolean create) {
140 return getSession();
141 }
142
143 public HttpSession getSession() {
144 if (session != null)
145 return session;
146
147 if (getSessionId() == null)
148 return null;
149
150 // Lookup session in session map when using embedded Jetty
151 @SuppressWarnings("unchecked")
152 Map<String, HttpSession> sessionMap = (Map<String, HttpSession>)servletContext.getAttribute(GraniteConfigListener.GRANITE_SESSION_MAP);
153 return sessionMap != null ? sessionMap.get(getSessionId()) : null;
154 }
155
156 @Override
157 public Object getSessionLock() {
158 return null;
159 }
160
161
162 @Override
163 public Map<String, String> getInitialisationMap() {
164 if (initialisationMap == null)
165 initialisationMap = new InitialisationMap(servletContext);
166 return initialisationMap;
167 }
168
169 @Override
170 public Map<String, Object> getApplicationMap() {
171 if (applicationMap == null)
172 applicationMap = new ApplicationMap(servletContext);
173 return applicationMap;
174 }
175
176 @Override
177 public Map<String, Object> getSessionMap() {
178 return null;
179 }
180 @Override
181 public Map<String, Object> getSessionMap(boolean create) {
182 if (sessionMap == null && getSession() != null)
183 sessionMap = new SessionMap(getSession());
184 return sessionMap;
185 }
186
187 @Override
188 public Map<String, Object> getRequestMap() {
189 return null;
190 }
191
192
193 private class BasicRequest implements HttpServletRequest {
194
195 private Map<String, Object> attributes = new HashMap<String, Object>();
196
197 public ServletContext getServletContext() {
198 return servletContext;
199 }
200
201 public Object getAttribute(String key) {
202 return attributes.get(key);
203 }
204
205 public void removeAttribute(String key) {
206 attributes.remove(key);
207 }
208
209 public void setAttribute(String key, Object value) {
210 attributes.put(key, value);
211 }
212
213 public Enumeration<String> getAttributeNames() {
214 return new Hashtable<String, Object>(attributes).keys();
215 }
216
217 public HttpSession getSession() {
218 return ServletGraniteContext.this.getSession();
219 }
220
221 public HttpSession getSession(boolean create) {
222 return ServletGraniteContext.this.getSession(create);
223 }
224
225 public String getRequestedSessionId() {
226 return null;
227 }
228
229 public boolean isRequestedSessionIdFromCookie() {
230 return false;
231 }
232
233 public boolean isRequestedSessionIdFromURL() {
234 return false;
235 }
236
237 public boolean isRequestedSessionIdFromUrl() {
238 return false;
239 }
240
241 public boolean isRequestedSessionIdValid() {
242 return false;
243 }
244
245 public Principal getUserPrincipal() {
246 return null;
247 }
248
249 public boolean isUserInRole(String arg0) {
250 return false;
251 }
252
253 public void login(String arg0, String arg1) throws ServletException {
254 }
255
256 public void logout() throws ServletException {
257 }
258
259 public String getCharacterEncoding() {
260 return null;
261 }
262
263 public int getContentLength() {
264 return 0;
265 }
266
267 public String getContentType() {
268 return null;
269 }
270
271 public DispatcherType getDispatcherType() {
272 return null;
273 }
274
275 public ServletInputStream getInputStream() throws IOException {
276 return null;
277 }
278
279 public String getLocalAddr() {
280 return null;
281 }
282
283 public String getLocalName() {
284 return null;
285 }
286
287 public int getLocalPort() {
288 return 0;
289 }
290
291 public Locale getLocale() {
292 return null;
293 }
294
295 public Enumeration<Locale> getLocales() {
296 return null;
297 }
298
299 public String getParameter(String arg0) {
300 return null;
301 }
302
303 public Map<String, String[]> getParameterMap() {
304 return null;
305 }
306
307 public Enumeration<String> getParameterNames() {
308 return null;
309 }
310
311 public String[] getParameterValues(String arg0) {
312 return null;
313 }
314
315 public String getProtocol() {
316 return null;
317 }
318
319 public BufferedReader getReader() throws IOException {
320 return null;
321 }
322
323 public String getRealPath(String arg0) {
324 return null;
325 }
326
327 public String getRemoteAddr() {
328 return null;
329 }
330
331 public String getRemoteHost() {
332 return null;
333 }
334
335 public int getRemotePort() {
336 return 0;
337 }
338
339 public RequestDispatcher getRequestDispatcher(String arg0) {
340 return null;
341 }
342
343 public String getScheme() {
344 return null;
345 }
346
347 public String getServerName() {
348 return null;
349 }
350
351 public int getServerPort() {
352 return 0;
353 }
354
355 public AsyncContext getAsyncContext() {
356 return null;
357 }
358
359 public boolean isAsyncStarted() {
360 return false;
361 }
362
363 public boolean isAsyncSupported() {
364 return false;
365 }
366
367 public boolean isSecure() {
368 return false;
369 }
370
371 public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException {
372 }
373
374 public AsyncContext startAsync() throws IllegalStateException {
375 return null;
376 }
377
378 public AsyncContext startAsync(ServletRequest arg0, ServletResponse arg1) throws IllegalStateException {
379 return null;
380 }
381
382 public boolean authenticate(HttpServletResponse arg0) throws IOException, ServletException {
383 return false;
384 }
385
386 public String getAuthType() {
387 return null;
388 }
389
390 public String getContextPath() {
391 return null;
392 }
393
394 public Cookie[] getCookies() {
395 return null;
396 }
397
398 public long getDateHeader(String arg0) {
399 return 0;
400 }
401
402 public String getHeader(String arg0) {
403 return null;
404 }
405
406 public Enumeration<String> getHeaderNames() {
407 return null;
408 }
409
410 public Enumeration<String> getHeaders(String arg0) {
411 return null;
412 }
413
414 public int getIntHeader(String arg0) {
415 return 0;
416 }
417
418 public String getMethod() {
419 return null;
420 }
421
422 public Part getPart(String arg0) throws IOException, ServletException {
423 return null;
424 }
425
426 public Collection<Part> getParts() throws IOException, ServletException {
427 return null;
428 }
429
430 public String getPathInfo() {
431 return null;
432 }
433
434 public String getPathTranslated() {
435 return null;
436 }
437
438 public String getQueryString() {
439 return null;
440 }
441
442 public String getRemoteUser() {
443 return null;
444 }
445
446 public String getRequestURI() {
447 return null;
448 }
449
450 public StringBuffer getRequestURL() {
451 return null;
452 }
453
454 public String getServletPath() {
455 return null;
456 }
457 }
458
459 private class BasicResponse implements HttpServletResponse {
460
461 public void flushBuffer() throws IOException {
462 }
463
464 public int getBufferSize() {
465 return 0;
466 }
467
468 public String getCharacterEncoding() {
469 return null;
470 }
471
472 public String getContentType() {
473 return null;
474 }
475
476 public Locale getLocale() {
477 return null;
478 }
479
480 public ServletOutputStream getOutputStream() throws IOException {
481 return null;
482 }
483
484 public PrintWriter getWriter() throws IOException {
485 return null;
486 }
487
488 public boolean isCommitted() {
489 return false;
490 }
491
492 public void reset() {
493 }
494
495 public void resetBuffer() {
496 }
497
498 public void setBufferSize(int arg0) {
499 }
500
501 public void setCharacterEncoding(String arg0) {
502 }
503
504 public void setContentLength(int arg0) {
505 }
506
507 public void setContentType(String arg0) {
508 }
509
510 public void setLocale(Locale arg0) {
511 }
512
513 public void addCookie(Cookie arg0) {
514 }
515
516 public void addDateHeader(String arg0, long arg1) {
517 }
518
519 public void addHeader(String arg0, String arg1) {
520 }
521
522 public void addIntHeader(String arg0, int arg1) {
523 }
524
525 public boolean containsHeader(String arg0) {
526 return false;
527 }
528
529 public String encodeRedirectURL(String arg0) {
530 return null;
531 }
532
533 public String encodeRedirectUrl(String arg0) {
534 return null;
535 }
536
537 public String encodeURL(String arg0) {
538 return null;
539 }
540
541 public String encodeUrl(String arg0) {
542 return null;
543 }
544
545 public String getHeader(String arg0) {
546 return null;
547 }
548
549 public Collection<String> getHeaderNames() {
550 return null;
551 }
552
553 public Collection<String> getHeaders(String arg0) {
554 return null;
555 }
556
557 public int getStatus() {
558 return 0;
559 }
560
561 public void sendError(int arg0) throws IOException {
562 }
563
564 public void sendError(int arg0, String arg1) throws IOException {
565 }
566
567 public void sendRedirect(String arg0) throws IOException {
568 }
569
570 public void setDateHeader(String arg0, long arg1) {
571 }
572
573 public void setHeader(String arg0, String arg1) {
574 }
575
576 public void setIntHeader(String arg0, int arg1) {
577 }
578
579 public void setStatus(int arg0) {
580 }
581
582 public void setStatus(int arg0, String arg1) {
583 }
584
585 }
586 }
587
588
589 abstract class BaseContextMap<T,U> extends AbstractMap<T,U> {
590
591 protected static final String KEY_STRING_ERROR = "Key should be a non null String: ";
592
593 @Override
594 public void clear() {
595 throw new UnsupportedOperationException();
596 }
597
598 @Override
599 public void putAll(Map<? extends T, ? extends U> t) {
600 throw new UnsupportedOperationException();
601 }
602
603 @Override
604 public U remove(Object key) {
605 throw new UnsupportedOperationException();
606 }
607
608 static class Entry<T,U> implements Map.Entry<T,U> {
609
610 private final T key;
611 private final U value;
612
613 Entry(T key, U value) {
614 this.key = key;
615 this.value = value;
616 }
617
618 public T getKey() {
619 return key;
620 }
621
622 public U getValue() {
623 return value;
624 }
625
626 public U setValue(U value) {
627 throw new UnsupportedOperationException();
628 }
629
630 @Override
631 public int hashCode() {
632 return ((key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()));
633 }
634
635 @Override
636 public boolean equals(Object obj) {
637 if (obj == this)
638 return true;
639
640 if (obj == null || !(obj instanceof Map.Entry<?, ?>))
641 return false;
642
643 Map.Entry<?, ?> input = (Map.Entry<?, ?>)obj;
644 Object inputKey = input.getKey();
645 Object inputValue = input.getValue();
646
647 if (inputKey == key || (inputKey != null && inputKey.equals(key))) {
648 if (inputValue == value || (inputValue != null && inputValue.equals(value)))
649 return true;
650 }
651 return false;
652 }
653 }
654 }
655
656 class InitialisationMap extends BaseContextMap<String, String> {
657
658 private ServletContext servletContext = null;
659
660 InitialisationMap(ServletContext servletContext) {
661 if (servletContext == null)
662 throw new NullPointerException("servletContext is null");
663 this.servletContext = servletContext;
664 }
665
666 @Override
667 public String get(Object key) {
668 if (!(key instanceof String))
669 return null;
670 return servletContext.getInitParameter(key.toString());
671 }
672
673 @Override
674 public String put(String key, String value) {
675 throw new UnsupportedOperationException();
676 }
677
678 @Override
679 public Set<Map.Entry<String, String>> entrySet() {
680 Set<Map.Entry<String, String>> entries = new HashSet<Map.Entry<String, String>>();
681 for (Enumeration<?> e = servletContext.getInitParameterNames(); e.hasMoreElements();) {
682 String key = (String)e.nextElement();
683 entries.add(new Entry<String, String>(key, servletContext.getInitParameter(key)));
684 }
685 return entries;
686 }
687
688 @Override
689 public boolean equals(Object obj) {
690 if (obj == null || !(obj instanceof InitialisationMap))
691 return false;
692 return super.equals(obj);
693 }
694 }
695
696 class ApplicationMap extends BaseContextMap<String, Object> {
697
698 private ServletContext servletContext = null;
699
700 ApplicationMap(ServletContext servletContext) {
701 if (servletContext == null)
702 throw new NullPointerException("servletContext is null");
703 this.servletContext = servletContext;
704 }
705
706 @Override
707 public Object get(Object key) {
708 if (!(key instanceof String))
709 return null;
710 return servletContext.getAttribute(key.toString());
711 }
712
713 @Override
714 public Object put(String key, Object value) {
715 if (key == null)
716 throw new IllegalArgumentException(KEY_STRING_ERROR + key);
717 Object result = servletContext.getAttribute(key);
718 servletContext.setAttribute(key, value);
719 return (result);
720 }
721
722 @Override
723 public Object remove(Object key) {
724 if (!(key instanceof String))
725 return null;
726 Object result = servletContext.getAttribute(key.toString());
727 servletContext.removeAttribute(key.toString());
728 return result;
729 }
730
731 @Override
732 public Set<Map.Entry<String, Object>> entrySet() {
733 Set<Map.Entry<String, Object>> entries = new HashSet<Map.Entry<String, Object>>();
734 for (Enumeration<?> e = servletContext.getAttributeNames(); e.hasMoreElements();) {
735 String key = (String)e.nextElement();
736 entries.add(new Entry<String, Object>(key, servletContext.getAttribute(key)));
737 }
738 return entries;
739 }
740
741 @Override
742 public boolean equals(Object obj) {
743 if (obj == null || !(obj instanceof ApplicationMap))
744 return false;
745 return super.equals(obj);
746 }
747 }
748
749 class SessionMap extends BaseContextMap<String, Object> {
750
751 private HttpServletRequest request = null;
752 private HttpSession session = null;
753
754 SessionMap(HttpSession session) {
755 if (session == null)
756 throw new NullPointerException("session is null");
757 this.session = session;
758 }
759
760 SessionMap(HttpServletRequest request) {
761 if (request == null)
762 throw new NullPointerException("request is null");
763 this.request = request;
764 }
765
766 @Override
767 public Object get(Object key) {
768 if (!(key instanceof String))
769 return null;
770 Object value = getSession().getAttribute(key.toString());
771 if (value instanceof TransientReferenceHolder)
772 return ((TransientReferenceHolder)value).get();
773 return value;
774 }
775
776 @Override
777 public Object put(String key, Object value) {
778 if (key == null)
779 throw new IllegalArgumentException(KEY_STRING_ERROR + key);
780 HttpSession session = getSession();
781 Object result = session.getAttribute(key);
782 if (result instanceof TransientReferenceHolder)
783 result = ((TransientReferenceHolder)result).get();
784 if (value != null && value.getClass().isAnnotationPresent(TransientReference.class))
785 value = new TransientReferenceHolder(value);
786 session.setAttribute(key, value);
787 return result;
788 }
789
790 @Override
791 public Object remove(Object key) {
792 if (!(key instanceof String))
793 return null;
794 HttpSession session = getSession();
795 Object result = session.getAttribute(key.toString());
796 if (result instanceof TransientReferenceHolder)
797 result = ((TransientReferenceHolder)result).get();
798 session.removeAttribute(key.toString());
799 return result;
800 }
801
802 @Override
803 public Set<Map.Entry<String, Object>> entrySet() {
804 Set<Map.Entry<String, Object>> entries = new HashSet<Map.Entry<String, Object>>();
805 HttpSession session = getSession();
806 for (Enumeration<?> e = session.getAttributeNames(); e.hasMoreElements(); ) {
807 String key = (String)e.nextElement();
808 Object value = session.getAttribute(key);
809 if (value instanceof TransientReferenceHolder)
810 value = ((TransientReferenceHolder)value).get();
811 entries.add(new Entry<String, Object>(key, value));
812 }
813 return entries;
814 }
815
816 @Override
817 public boolean equals(Object obj) {
818 if (obj == null || !(obj instanceof SessionMap))
819 return false;
820 return super.equals(obj);
821 }
822
823 private HttpSession getSession() {
824 if (request != null)
825 return request.getSession(true);
826 return session;
827 }
828 }
829