1 19 20 package org.objectweb.jac.aspects.gui.web; 21 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.io.OutputStream ; 25 import java.io.OutputStreamWriter ; 26 import java.io.Writer ; 27 import java.util.Arrays ; 28 import java.util.Collection ; 29 import java.util.HashSet ; 30 import java.util.Hashtable ; 31 import java.util.Iterator ; 32 import java.util.Map ; 33 import javax.servlet.http.HttpServletResponse ; 34 import org.apache.log4j.Logger; 35 import org.mortbay.http.HttpContext; 36 import org.mortbay.http.HttpServer; 37 import org.mortbay.http.handler.ResourceHandler; 38 import org.mortbay.jetty.servlet.ServletHandler; 39 import org.mortbay.util.InetAddrPort; 40 import org.mortbay.util.MultiException; 41 import org.objectweb.jac.aspects.gui.*; 42 import org.objectweb.jac.aspects.session.SessionAC; 43 import org.objectweb.jac.core.Collaboration; 44 import org.objectweb.jac.core.rtti.AbstractMethodItem; 45 import org.objectweb.jac.lib.Attachment; 46 import org.objectweb.jac.util.ExtArrays; 47 import org.objectweb.jac.util.ExtBoolean; 48 import org.objectweb.jac.util.Strings; 49 50 62 public class WebDisplay implements CustomizedDisplay { 63 static Logger logger = Logger.getLogger("display"); 64 static Logger loggerWeb = Logger.getLogger("web"); 65 static Logger loggerViews = Logger.getLogger("web.views"); 66 static Logger loggerRequest = Logger.getLogger("web.request"); 67 static Logger loggerHtml = Logger.getLogger("web.html"); 68 static Logger loggerEditor = Logger.getLogger("gui.editor"); 69 70 71 ViewFactory factory; 72 Hashtable frames = new Hashtable (); 74 75 76 Session session; 77 78 83 public WebDisplay(ViewFactory factory, String sessionId) { 84 this.factory = factory; 85 session = new Session(sessionId); 86 Collaboration.get().addAttribute( 87 SessionAC.SESSION_ID, sessionId ); 88 } 89 90 public static final String RESPONSE = "gui.web.response"; 91 public static final String REQUEST = "gui.web.request"; 92 public static final String ON_ENTER_ACTION = "GuiAC.web.ON_ENTER_ACTION"; 93 94 98 public static void setResponse(HttpServletResponse response) { 99 Collaboration.get().addAttribute(RESPONSE,response); 100 } 101 105 public static HttpServletResponse getResponse() { 106 return (HttpServletResponse )Collaboration.get().getAttribute(RESPONSE); 107 } 108 109 113 public static void setRequest(JacRequest request) { 114 loggerRequest.debug("Setting request for "+Strings.hex(Collaboration.get())+ 115 ": "+request); 116 Collaboration.get().addAttribute(REQUEST,request); 117 } 118 119 123 public static JacRequest getRequest() { 124 return (JacRequest)Collaboration.get().getAttribute(REQUEST); 125 } 126 127 protected static void grabResponse() { 128 setResponse(null); 129 } 132 133 142 public static void readValues(DisplayContext editors, JacRequest request, 143 boolean commit) 144 { 145 loggerEditor.debug("reading values from context "+editors); 146 Iterator i = editors.getEditors().iterator(); 147 while (i.hasNext()) { 148 View editor = (View)i.next(); 149 try { 150 Object parameter = request.getParameter(editor.getLabel()); 151 loggerEditor.debug("reading value for "+editor.getLabel()); 152 if (editor instanceof JacRequestReader) { 153 ((JacRequestReader)editor).readValue(request); 154 } else { 155 if (((FieldEditor)editor).isEnabled()) { 156 HTMLEditor htmlEditor = (HTMLEditor)editor; 157 if (htmlEditor.readValue(parameter) && commit) { 158 try { 159 htmlEditor.commit(); 160 } catch (Exception e) { 161 throw new CommitException( 162 e, 163 ((FieldEditor)editor).getSubstance(), 164 ((FieldEditor)editor).getField()); 165 } 166 } 167 } 168 } 169 } catch (CommitException e) { 170 throw e; 171 } catch(Exception e) { 172 loggerEditor.error("Failed to readValue for "+editor+"/"+editor.getLabel(),e); 173 } 174 } 175 } 176 177 public static void readValuesAndRefresh( 178 DisplayContext editors, JacRequest request, 179 boolean commit) 180 { 181 try { 182 readValues(editors,request,commit); 183 editors.getDisplay().refresh(); 184 } catch(CommitException e) { 185 editors.getDisplay().showError( 186 "Commit error", 187 "Failed to set value of "+e.getField()+ 188 " on "+GuiAC.toString(e.getObject())+ 189 ": "+e.getNested().getMessage()); 190 } 191 } 192 193 public void fullRefresh() { 194 Iterator it = frames.entrySet().iterator(); 195 while(it.hasNext()) { 196 Map.Entry entry = (Map.Entry )it.next(); 197 View frame = (View)entry.getValue(); 198 CustomizedGUI customized = ((CustomizedView)frame).getCustomizedGUI(); 199 frame.close(true); 200 View newframe = factory.createView( 201 customized.getTitle(),"Customized", 202 new Object [] {customized,null}, 203 new DisplayContext(this,null)); 204 logger.debug("frame created "+newframe); 205 frames.put(entry.getKey(),newframe); 206 session.newRequest(new Request(newframe)); 207 } 208 } 209 210 public void showCustomized(String id, Object object) { 211 showCustomized(id,object,null); 212 } 213 214 public void showCustomized(String id, Object object, Map panels) { 215 logger.debug("showCustomized("+id+","+object+")"); 216 try { 217 CustomizedGUI customized = (CustomizedGUI)object; 218 if (frames.get(id)!=null) { 219 if (panels!=null) { 220 CustomizedView frame = (CustomizedView)frames.get(id); 221 GenericFactory.initCustomized(frame.getFactory(), 222 frame.getContext(), 223 frame.getPanelView(), 224 customized, panels); 225 } 226 refresh(); 227 } else { 228 HTMLViewer frame = (HTMLViewer)factory.createView( 229 customized.getTitle(),"Customized", 230 new Object [] {customized,panels}, 231 new DisplayContext(this,null)); 232 logger.debug("frame created"); 233 frames.put(id,frame); 234 session.newRequest(new Request((View)frame)); 235 refresh(); 236 } 237 } catch(Exception e) { 238 e.printStackTrace(); 239 showError("showCustomized error",e.toString()); 240 } 241 } 242 243 public void show(Object object) { 244 logger.debug("show("+object+")"); 245 show(object,false); 246 } 247 248 public void show(Object object, 249 String viewType, Object [] viewParams) { 250 logger.debug("show("+object+","+viewType+","+ 251 (viewParams!=null?Arrays.asList(viewParams):null)+")"); 252 show(object,viewType,viewParams,false); 253 } 254 255 protected void show(Object object, boolean newWindow) { 256 show(object, 257 "Object",new String [] {GuiAC.DEFAULT_VIEW}, 258 newWindow); 259 } 260 261 protected void show(Object object, 262 String viewType, Object [] viewParams, 263 boolean newWindow) { 264 if (object==null) { 265 refresh(); 266 271 } else if (object instanceof InputStream ) { 272 try { 273 byte[] buffer = new byte[4096]; 274 InputStream input = (InputStream )object; 275 int length; 276 OutputStream output = getResponse().getOutputStream(); 277 while ((length=input.read(buffer))!=-1) { 278 output.write(buffer,0,length); 279 } 280 } catch (IOException e) { 281 logger.error("Failed to output stream",e); 282 } finally { 283 getRequest().setResponse(); 284 } 285 } else if (object instanceof Attachment) { 286 try { 287 DisplayContext context = new DisplayContext(this,null); 288 HttpServletResponse response = getResponse(); 289 response.setContentType(((Attachment)object).getMimeType()); 290 response.getOutputStream().write(((Attachment)object).getData()); 291 } catch (IOException e) { 292 logger.error("Failed to output stream",e); 293 } finally { 294 getRequest().setResponse(); 295 } 296 } else { 297 DisplayContext context = new DisplayContext(this,null); 298 View objectView = 299 factory.createView("object", 300 viewType,ExtArrays.add(object,viewParams), 301 context); 302 String title; 303 if (object!=null) { 304 Class substance_type = object.getClass(); 305 String tn = substance_type.getName(); 306 307 title = tn.substring( tn.lastIndexOf('.') + 1) + " " + 308 GuiAC.toString(object); 309 } else { 310 title= "<null>"; 311 } 312 313 View page = factory.createView( 314 title,"Window", 315 new Object [] {objectView,ExtBoolean.valueOf(newWindow)}, 316 context); 317 context.setWindow(page); 318 session.newRequest(new Request(page)); 319 refresh(); 320 } 321 } 322 323 public void openView(Object object) { 324 logger.debug("openView("+object+")"); 325 show(object,true); 326 } 327 328 public boolean showModal(Object object, String title, String header, 329 Object parent, 330 boolean okButton, boolean cancelButton, 331 boolean closeButton) 332 { 333 logger.debug("showModal("+object+","+title+")"); 334 DisplayContext context = new DisplayContext(this,null); 335 logger.debug("new context "+context); 336 View objectView = factory.createObjectView("object",object,context); 337 338 return showModal(objectView,context, 339 title,header,parent, 340 okButton,cancelButton,closeButton); 341 } 342 343 public boolean showModal(Object object, 344 String viewType, Object [] viewParams, 345 String title, String header, 346 Object parent, 347 boolean okButton, boolean cancelButton, 348 boolean closeButton) 349 { 350 logger.debug("showModal("+object+","+title+","+viewType+")"); 351 DisplayContext context = new DisplayContext(this,null); 352 View objectView = factory.createView("object",viewType, 353 ExtArrays.add(object,viewParams),context); 354 355 return showModal(objectView,context, 356 title,header,parent, 357 okButton,cancelButton,closeButton); 358 } 359 360 public boolean showModal(View objectView, DisplayContext context, 361 String title, String header, 362 Object parent, 363 boolean okButton, boolean cancelButton, 364 boolean closeButton) 365 { 366 logger.debug("objectView = "+objectView+", context="+Strings.hex(context)); 367 if (objectView instanceof org.objectweb.jac.aspects.gui.EditorContainer) 368 ((org.objectweb.jac.aspects.gui.EditorContainer)objectView).setShowButtons(false); 369 370 DialogView page = 371 (DialogView)factory.createView( 372 title,"Dialog", 373 new Object [] {objectView,parent,title,header}, 374 context); 375 context.setWindow(page); 376 session.newRequest(new Request(page)); 377 refresh(); 378 379 try { 380 boolean result = page.waitForClose(); 381 WebDisplay.setResponse(((Dialog)page).getResponse()); 382 WebDisplay.setRequest(((Dialog)page).getRequest()); 383 return result; 384 } catch (TimeoutException timeout) { 385 addTimedoutDialog(page); 386 throw timeout; 387 } 388 } 389 390 public boolean showInput(Object substance, AbstractMethodItem method, 391 Object [] parameters) 392 { 393 logger.debug("showInput("+substance+","+method+","+ 394 Arrays.asList(parameters)+")"); 395 DisplayContext dc = (DisplayContext)Collaboration.get() 396 .getAttribute(GuiAC.DISPLAY_CONTEXT); 397 dc = new DisplayContext(this,null); 399 DialogView page = GenericFactory.createInputDialog(substance, 401 method,parameters,dc); 402 dc.setWindow(page); 403 session.newRequest(new Request(page)); 404 refresh(); 405 try { 406 if (page.waitForClose()) { 407 EditorContainer inputView = (EditorContainer)page.getContentView(); 408 Iterator it = inputView.getEditors().iterator(); 409 int i=0; 410 JacRequest request = getRequest(); 411 while (it.hasNext()) { 412 if (method.getParameterTypes()[i] != DisplayContext.class) { 413 FieldEditor editor = (FieldEditor)it.next(); 414 method.setParameter(parameters,i,editor.getValue()); 415 } 416 i++; 417 } 418 setResponse(((Dialog)page).getResponse()); 419 setRequest(((Dialog)page).getRequest()); 420 return true; 421 } else { 422 setResponse(((Dialog)page).getResponse()); 423 setRequest(((Dialog)page).getRequest()); 424 return false; 425 } 426 } catch (TimeoutException timeout) { 427 addTimedoutDialog(page); 428 throw timeout; 429 } 430 } 431 432 public boolean showMessage(String message, String title, 433 boolean okButton, 434 boolean cancelButton, 435 boolean closeButton ) { 436 logger.debug("showMessage("+message+","+title+")"); 437 return showModal(null,title,message,null,okButton,cancelButton,closeButton); 438 } 439 440 protected View buildMessage(String title, String message) { 441 DisplayContext context=(DisplayContext)Collaboration.get() 442 .getAttribute(GuiAC.DISPLAY_CONTEXT); 443 if(context==null) { 444 context=new DisplayContext(this,null); 445 } 446 View label = factory.createView("message","text", 447 new Object [] {message,null,null},context); 448 View page = factory.createView("Object view","Window", 449 new Object [] {label,Boolean.FALSE},context); 450 return page; 451 } 452 453 public void showMessage(String title, String message) { 454 logger.debug("showMessage("+title+","+message+")"); 455 try { 456 View page = buildMessage(title,message); 457 session.newRequest(new Request(page)); 458 } finally { 459 refresh(); 460 } 461 } 462 463 public Object showRefreshMessage(String title, String message) { 464 View page = null; 465 try { 466 DisplayContext context=(DisplayContext)Collaboration.get() 467 .getAttribute(GuiAC.DISPLAY_CONTEXT); 468 if (context==null) { 469 context=new DisplayContext(this,null); 470 } 471 View label = factory.createView("message","text", 472 new Object [] {message,null,null},context); 473 page = factory.createView("Object view","RefreshWindow", 474 new Object [] {label},context); 475 session.newRequest(new Request(page)); 476 } finally { 477 refresh(); 478 } 479 return page; 480 } 481 482 public void showError(String title, String message) { 483 showMessage(title,message); 484 } 485 486 public void showStatus(String message) { 487 } 488 489 public void applicationStarted() { 490 } 491 492 493 public CustomizedView getCustomizedView(String customizedID) { 494 return (CustomizedView)frames.get(customizedID); 495 } 496 public Collection getCustomizedViews() { 497 return frames.values(); 498 } 499 public ViewFactory getFactory() { 500 return factory; 501 } 502 503 String displayID; 504 505 public String getDisplayID() { 506 return displayID; 507 } 508 509 public void setDisplayID(String displayID) { 510 this.displayID = displayID; 511 } 512 513 public void close() { 514 Iterator i = frames.values().iterator(); 516 while(i.hasNext()) { 517 View view = (View)i.next(); 518 view.close(true); 519 } 520 } 521 522 524 public Object [] buildParameterValues(AbstractMethodItem method, String [] params) { 525 Object [] result = new Object [params.length]; 526 Class [] pts = method.getParameterTypes(); 527 for(int i=0; i<params.length; i++) 528 { 529 } 532 return result; 533 } 534 535 public void refresh() { 536 if (getResponse()==null) { 537 logger.debug("refresh ignored since response==null"); 538 return; 539 } 540 logger.debug("refresh"); 541 Object view = session.getCurrentRequest().getView(); 542 if (view == null) { 543 showError("Display error","Nothing to refresh yet"); 544 logger.debug("Nothing to refresh yet"); 545 } else { 546 try { 547 loggerHtml.debug("genHTML on "+view+"("+Strings.hex(getResponse())+")"); 548 ((HTMLViewer)view).genHTML(getResponse().getWriter()); 549 } catch(Exception e) { 550 logger.error("refresh failed",e); 551 } finally { 552 getRequest().setResponse(); 553 } 554 } 555 } 556 557 static HttpServer httpServer; 558 public static HttpServer getHttpServer() { 559 if (httpServer==null) { 560 httpServer = new HttpServer(); 561 } 562 return httpServer; 563 } 564 565 566 static HashSet startedGuis = new HashSet (); 567 568 static HashSet openedPorts = new HashSet (); 569 570 578 public static void startWebServer(String application, String [] guiIDs, int defaultPort) 579 throws IOException , MultiException 580 { 581 loggerWeb.debug("startWebServer on port "+defaultPort); 582 httpServer = getHttpServer(); 583 HttpContext context = httpServer.getContext("/jac"); 584 585 ServletHandler servletHandler = new ServletHandler(); 586 for (int i=0; i<guiIDs.length;i++) { 587 if (startedGuis.contains(guiIDs[i])) { 588 loggerWeb.debug("skipping already registered GUI "+guiIDs[i]); 589 } else { 590 loggerWeb.debug("register GUI "+guiIDs[i]); 591 592 String split[] = Strings.split(guiIDs[i],":"); 593 String gui = split[0]; 594 int port = split.length>=2 ? Integer.parseInt(split[1]) : defaultPort; 595 596 if (!openedPorts.contains(new Integer (port))) { 597 httpServer.addListener(new InetAddrPort(port)); 598 openedPorts.add(new Integer (port)); 599 } 600 601 context.setClassLoader(WebDisplay.class.getClassLoader()); 604 605 servletHandler.addServlet("Jac","/"+gui, 606 "org.objectweb.jac.aspects.gui.web.JacLocalServlet"); 607 } 608 } 609 context.addHandler(servletHandler); 610 611 context = httpServer.getContext("/jac/resources"); 612 context.setBaseResource(new ClasspathResource()); 613 context.setClassLoader(WebDisplay.class.getClassLoader()); 614 context.addHandler(new ResourceHandler()); 615 616 startWebServer(); 617 } 618 619 622 public static synchronized void startWebServer() throws MultiException { 623 if (httpServer.isStarted()) { 624 try { 625 httpServer.stop(); 626 } catch (Exception e) { 627 e.printStackTrace(); 628 } 629 } 630 httpServer.start(); 631 } 632 633 Hashtable ids = new Hashtable (); 635 Hashtable views = new Hashtable (); 637 638 645 public String registerView(View view) { 646 String id = (String )ids.get(view); 647 if (id==null) { 648 id = Integer.toString(view.hashCode()); 649 ids.put(view,id); 650 views.put(id,view); 651 loggerViews.debug(toString()+".registerView("+view+") -> "+id); 652 } 653 return id; 654 } 655 656 661 public void unregisterView(View view) { 662 Object id = ids.get(view); 663 loggerViews.debug(toString()+".unregisterView("+view+") "+id); 664 ids.remove(view); 665 if (id!=null) { 666 views.remove(id); 667 } 668 } 669 670 676 public View getView(String id) { 677 loggerViews.debug(toString()+".getView("+id+")"); 678 return (View)views.get(id); 679 } 680 681 687 public String getViewID(View view) { 688 return (String )ids.get(view); 689 } 690 691 HashSet timedoutDialogs = new HashSet (); 693 public void addTimedoutDialog(DialogView dialog) { 694 timedoutDialogs.add(getViewID(dialog)); 695 } 696 699 public boolean isTimedout(String viewID) { 700 return timedoutDialogs.contains(viewID); 701 } 702 703 String servletName; 704 708 public void setServletName(String name) { 709 servletName = name; 710 } 711 714 public String getServletName() { 715 return servletName; 716 } 717 718 public void closeWindow(View window, boolean validate) { 719 loggerWeb.debug("closeWindow "+window); 720 Iterator i = session.getRequests().iterator(); 721 Request request = null; 722 while (i.hasNext()) { 723 request = (Request)i.next(); 724 if (request.getView().equals(window)) { 725 ((View)request.getView()).close(validate); 729 session.getRequests().remove(request); 730 break; 731 } 732 } 733 } 734 735 public Session getSession() { 736 return session; 737 } 738 739 public boolean fillParameters(AbstractMethodItem method, Object [] parameters) { 740 Class [] paramTypes = method.getParameterTypes(); 741 for (int i=0; i<paramTypes.length; i++) { 742 if (Writer .class.isAssignableFrom(paramTypes[i]) 743 && parameters[i]==null) 744 { 745 String type = (String )method.getAttribute(GuiAC.MIME_TYPE); 746 if (type!=null) { 747 logger.info("Setting mime-type: "+type); 748 getResponse().setContentType(type+"; "+GuiAC.getEncoding()); 749 } 750 try { 751 parameters[i] = 752 new OutputStreamWriter ( 753 getResponse().getOutputStream(), 754 GuiAC.getEncoding()); 755 grabResponse(); } catch(Exception e) { 757 logger.error("Failed to set Writer parameter "+i+ 758 " for "+method.getLongName(),e); 759 } 760 return paramTypes.length<=1; 761 } else if (OutputStream .class.isAssignableFrom(paramTypes[i]) 762 && parameters[i]==null) { 763 String type = (String )method.getAttribute(GuiAC.MIME_TYPE); 764 if (type!=null) { 765 logger.info("Setting mime-type: "+type); 766 getResponse().setContentType(type+"; "+GuiAC.getEncoding()); 767 } 768 try { 769 parameters[i] = getResponse().getOutputStream(); 770 grabResponse(); } catch(Exception e) { 772 logger.error("Failed to set OutputStream parameter "+i+ 773 " for "+method.getLongName(),e); 774 } 775 return paramTypes.length<=1; 776 } 777 } 778 779 return false; 780 } 781 782 785 public void onInvocationReturn(Object substance, AbstractMethodItem method) { 786 Class [] paramTypes = method.getParameterTypes(); 787 for (int i=0; i<paramTypes.length; i++) { 788 if (Writer .class.isAssignableFrom(paramTypes[i]) || 791 OutputStream .class.isAssignableFrom(paramTypes[i])) 792 { 793 getRequest().setResponse(); 794 } 795 } 796 } 797 798 } 799 | Popular Tags |