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 021package org.granite.messaging.webapp; 022 023import java.io.BufferedReader; 024import java.io.IOException; 025import java.io.PrintWriter; 026import java.io.UnsupportedEncodingException; 027import java.security.Principal; 028import java.util.AbstractMap; 029import java.util.Collection; 030import java.util.Enumeration; 031import java.util.HashMap; 032import java.util.HashSet; 033import java.util.Hashtable; 034import java.util.Locale; 035import java.util.Map; 036import java.util.Set; 037 038import javax.servlet.AsyncContext; 039import javax.servlet.DispatcherType; 040import javax.servlet.RequestDispatcher; 041import javax.servlet.ServletContext; 042import javax.servlet.ServletException; 043import javax.servlet.ServletInputStream; 044import javax.servlet.ServletOutputStream; 045import javax.servlet.ServletRequest; 046import javax.servlet.ServletResponse; 047import javax.servlet.http.Cookie; 048import javax.servlet.http.HttpServletRequest; 049import javax.servlet.http.HttpServletResponse; 050import javax.servlet.http.HttpSession; 051import javax.servlet.http.Part; 052 053import org.granite.clustering.TransientReference; 054import org.granite.clustering.TransientReferenceHolder; 055import org.granite.config.GraniteConfig; 056import org.granite.config.GraniteConfigListener; 057import org.granite.config.flex.ServicesConfig; 058import org.granite.context.GraniteContext; 059 060/** 061 * @author Franck WOLFF 062 */ 063public 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 589abstract 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 656class 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 696class 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 749class 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