1 50 51 package org.openlaszlo.iv.flash.servlet; 52 53 import java.rmi.RemoteException ; 54 import java.io.*; 55 import java.net.*; 56 import java.util.*; 57 58 import javax.servlet.*; 59 import javax.servlet.http.*; 60 61 import org.openlaszlo.iv.flash.api.*; 62 import org.openlaszlo.iv.flash.util.*; 63 import org.openlaszlo.iv.flash.parser.*; 64 import org.openlaszlo.iv.flash.cache.*; 65 66 import org.openlaszlo.iv.flash.url.*; 67 import org.openlaszlo.iv.flash.api.image.*; 68 import org.openlaszlo.iv.flash.api.sound.*; 69 import org.openlaszlo.iv.flash.context.*; 70 71 import org.apache.log4j.*; 72 import org.apache.log4j.spi.*; 73 74 78 public class GeneratorServlet extends HttpServlet { 79 80 private String errorTemplateName = null; 81 private int currentThreadNum = 0; 82 private int maxThreads = 0; 83 private int gcAfterJobsCount = 0; 84 private int jobsCountSinceLastGC = 0; 85 private boolean wrapAssets = false; 86 private boolean createServletContext = false; 87 88 public void init( ServletConfig config ) throws ServletException { 89 super.init( config ); 90 91 String installDir = getInitParameter("org.openlaszlo.iv.flash.virtualInstallDir"); 93 if( installDir != null ) { 94 installDir = config.getServletContext().getRealPath(installDir); 95 } else { 96 installDir = getInitParameter("org.openlaszlo.iv.flash.installDir"); 97 if( installDir == null ) { 98 installDir = config.getServletContext().getRealPath("/"); 99 } 100 } 101 102 String propFileName = getInitParameter("org.openlaszlo.iv.flash.propertiesFile"); 103 104 Util.init(installDir, propFileName); 105 106 StatManager.init(); 108 109 createServletContext = PropertyManager.getBoolProperty( "org.openlaszlo.iv.flash.servletContext", false ); 111 maxThreads = PropertyManager.getIntProperty( "org.openlaszlo.iv.flash.maxThreads", 0 ); 112 gcAfterJobsCount = PropertyManager.getIntProperty( "org.openlaszlo.iv.flash.garbageCollectAfterJobCount", 0 ); 113 wrapAssets = PropertyManager.getBoolProperty( "org.openlaszlo.iv.flash.wrapAssets", false ); 114 115 String fileName = PropertyManager.getProperty("org.openlaszlo.iv.flash.errorTemplate","bin/error.swt"); 117 if( fileName != null ) { 118 File errFile = Util.getSysFile( fileName ); 119 if( errFile.exists() ) { 120 errorTemplateName = errFile.getAbsolutePath(); 121 } 122 } 123 124 Log.info(""); 125 Log.logRB(Resource.SERVERSTARTED); 126 Log.info(""); 127 } 128 129 132 private void showTextError( String msg, HttpServletResponse res ) 133 throws ServletException, IOException 134 { 135 res.setContentType("text/html"); 136 PrintWriter pw = res.getWriter(); 137 pw.print( "<html><body><font color=red>"+msg+"</font></body></html>" ); 138 pw.close(); 139 } 140 141 144 private void showError( Throwable t, String fileName, HttpServletResponse res ) 145 throws ServletException, IOException 146 { 147 String fullMessage = t.getLocalizedMessage(); 148 149 if( errorTemplateName == null ) { 150 showTextError( fullMessage, res ); 151 } else { 152 try { 153 if( fullMessage == null ) fullMessage = t.getClass().getName(); 154 StandardContext context = new StandardContext(); 155 context.setValue( "bulkErrMessage", fullMessage ); 156 context.setValue( "template_name", fileName ); 157 FlashOutput fob = process(errorTemplateName, context, null); 158 send( fob, res ); 159 } catch( Throwable tt ) { 160 Log.log( tt ); 161 showTextError( fullMessage, res ); 162 } 163 } 164 } 165 166 169 private Context createServletContext( HttpServletRequest req ) { 170 CommandExecutor executor = new OnlineCommandExecutor(); 171 CommandContext context = new CommandContext( executor ); 172 Enumeration e = req.getParameterNames(); 173 while( e.hasMoreElements() ) { 174 String name = (String ) e.nextElement(); 175 String value = Util.processEscapes( req.getParameter(name) ); 176 context.setValue(name, value); 177 } 178 return context; 179 } 180 181 protected long getLastModified( HttpServletRequest req ) { 182 return -1; 183 } 184 185 public void doGet( HttpServletRequest req, HttpServletResponse res ) 186 throws ServletException, IOException 187 { 188 doGen( req, res ); 189 } 190 191 public void doPost( HttpServletRequest req, HttpServletResponse res ) 192 throws ServletException, IOException 193 { 194 doGen( req, res ); 195 } 196 197 public void doGen( HttpServletRequest req, HttpServletResponse res ) 198 throws ServletException, IOException 199 { 200 if( maxThreads > 0 && currentThreadNum >= maxThreads ) { 201 res.sendError( res.SC_SERVICE_UNAVAILABLE ); 202 return; 203 } 204 205 try { 206 currentThreadNum++; 207 208 GeneratorServletContext context = null; 210 if( createServletContext ) { 211 context = GeneratorServletContext.createContext(); 212 context.setHttpServletRequest( req ); 213 context.setHttpServletResponse( res ); 214 context.setServletConfig( getServletConfig() ); 215 } 216 217 218 String fileName = getRequestedFileName( req ); 219 220 if( fileName.endsWith( "__admin__.swt" ) ) { 222 adminRequest( req, res ); 223 return; 224 } 225 226 processTemplate( fileName, req, res ); 227 228 } finally { 229 currentThreadNum--; 230 231 if( createServletContext ) GeneratorServletContext.destroyContext(); 233 234 jobsCountSinceLastGC++; 235 if( gcAfterJobsCount > 0 && jobsCountSinceLastGC >= gcAfterJobsCount ) { 236 System.runFinalization(); 237 System.gc(); 238 jobsCountSinceLastGC = 0; 239 } 240 } 241 } 242 243 246 public void processTemplate( String fileName, HttpServletRequest req, HttpServletResponse res ) 247 throws ServletException, IOException 248 { 249 long totalTime = System.currentTimeMillis(); 250 long processTime = totalTime; 251 252 FlashOutput fob = null; 253 254 263 264 Log.logRB(Resource.REQUESTFROM, new Object [] {req.getRemoteHost()}); 265 266 long lifespan = -1L; 268 String key = null; 269 boolean grc = Util.toBool( req.getParameter("grc"), false ); grc = grc || RequestCache.getSettings().isForce(); 271 if( grc ) { 272 lifespan = Util.toInt( req.getParameter("gre"), -1 )*1000L; 273 key = fileName+"?"+req.getQueryString(); 275 fob = RequestCache.getRequest( key ); 276 } 277 278 279 boolean needToCache = grc && fob == null; 280 281 if( fob == null ) { 283 try { 284 Context context = createServletContext( req ); 285 286 String encoding = req.getParameter("genc"); 287 288 if( wrapAssets && 289 (fileName.endsWith( ".jpg.swt" ) || 290 fileName.endsWith( ".png.swt" ) || 291 fileName.endsWith( ".gif.swt" )) ) 292 { 293 fob = wrapImage( fileName.substring(0, fileName.length()-4), context ); 294 } else if( wrapAssets && fileName.endsWith( ".mp3.swt" ) ) { 295 fob = wrapSound( fileName.substring(0, fileName.length()-4), context ); 296 } else { 297 fob = process( fileName, context, encoding ); 298 } 299 300 } catch( FileNotFoundException e ) { 301 Log.logRB(Resource.FILENOTFOUND, new Object [] {fileName}); 302 res.sendError( res.SC_NOT_FOUND ); 303 return; 304 } catch( OutOfMemoryError e ) { 305 FontCache.getInstance().clear(); 307 MediaCache.getInstance().clear(); 308 RequestCache.getInstance().clear(); 309 XMLCache.getInstance().clear(); 310 System.gc(); 311 Log.logRB(Resource.PROCESSERROR, new Object [] {fileName}, e); 312 showError(e, fileName, res); 313 return; 314 } catch( Throwable e ) { 315 Log.logRB(Resource.PROCESSERROR, new Object [] {fileName}, e); 316 showError(e, fileName, res); 317 return; 318 } 319 } 320 processTime = System.currentTimeMillis()-processTime; 321 322 if( needToCache ) { 324 RequestCache.addRequest( key, fob, lifespan ); 325 } 326 327 try { 329 send( fob, res ); 330 } catch( Throwable t ) { 331 Log.logRB(Resource.SENDERROR, new Object [] {fileName}, t); 332 return; 333 } 334 335 totalTime = System.currentTimeMillis()-totalTime; 337 Log.logRB( Resource.PROCESSREQUEST, new Object [] { fileName, new Integer (fob.getSize()), new Long (processTime), new Long (totalTime) } ); 338 339 StatManager.addRequest( fileName, fob.getSize(), processTime, totalTime ); 341 } 342 343 358 protected FlashOutput process( String fileName, Context context, String encoding ) 359 throws IVException, IOException 360 { 361 FlashFile file = FlashFile.parse(fileName, false, encoding); 362 363 file.processFile( context ); 364 365 return file.generate(); 366 } 367 368 384 protected FlashOutput wrapImage( String fileName, Context context ) 385 throws IVException, IOException 386 { 387 IVUrl url = IVUrl.newUrl(fileName); 388 389 Bitmap bitmap = (Bitmap) MediaCache.getMedia(url); 390 if( bitmap == null ) { 391 bitmap = Bitmap.newBitmap(url); 392 } 393 MediaCache.addMedia(url, bitmap, bitmap.getSize(), true); 394 395 int width = Util.toInt(context.getValue("width"), -1) * 20; 396 int height = Util.toInt(context.getValue("height"), -1) * 20; 397 boolean center = Util.toBool(context.getValue("center"), false); 398 boolean scale = width >= 0 && height >= 0; 399 400 Instance inst = bitmap.newInstance( width, height, scale, center ); 401 402 Script script = new Script(1); 403 script.setMain(); 404 405 script.newFrame().addInstance( inst, 1 ); 406 407 FlashFile file = FlashFile.newFlashFile(); 408 409 file.setFrameSize( inst.getBounds() ); 410 file.setMainScript( script ); 411 412 return file.generate(); 413 } 414 415 427 protected FlashOutput wrapSound( String fileName, Context context ) 428 throws IVException, IOException 429 { 430 Script script = new Script(1); 431 script.setMain(); 432 433 IVUrl url = IVUrl.newUrl(fileName); 434 435 MP3Sound sound = (MP3Sound) MediaCache.getMedia(url); 436 if( sound == null ) { 437 sound = MP3Sound.newMP3Sound( url ); 438 } 439 MediaCache.addMedia(url, sound, sound.getSize(), true); 440 441 int delay = Util.toInt(context.getValue("delay"), 0); 443 444 if( delay != 0 ) { 445 sound.setDelaySeek( delay ); 446 } 447 448 SoundInfo soundInfo = SoundInfo.newSoundInfo( 0 ); 449 StartSound startSound = StartSound.newStartSound( sound, soundInfo ); 450 451 script.newFrame().addFlashObject( startSound ); 452 453 FlashFile file = FlashFile.newFlashFile(); 454 455 file.setFrameSize( GeomHelper.newRectangle(0,0,0,0) ); 456 file.setMainScript( script ); 457 458 return file.generate(); 459 } 460 461 469 protected void send( FlashOutput fob, HttpServletResponse res ) 470 throws ServletException, IOException 471 { 472 res.setContentLength( fob.getSize() ); 473 res.setContentType( "application/x-shockwave-flash" ); 474 475 ServletOutputStream sos = res.getOutputStream(); 476 try { 477 sos.write( fob.getBuf(), 0, fob.getSize() ); 478 } finally { 479 sos.close(); 480 } 481 } 482 483 486 protected String getRequestedFileName( HttpServletRequest req ) { 487 return getServletContext().getRealPath( req.getServletPath() ); 488 } 490 491 private void debugInfo( HttpServletRequest req ) { 492 499 506 } 507 508 523 public void adminRequest( HttpServletRequest req, HttpServletResponse res ) 524 throws ServletException, IOException 525 { 526 String userName = req.getParameter( "username" ); 528 String password = req.getParameter( "password" ); 529 String myUserName = PropertyManager.getProperty( "org.openlaszlo.iv.flash.adminUserName" ); 530 String myPassword = PropertyManager.getProperty( "org.openlaszlo.iv.flash.adminPassword" ); 531 if( myUserName == null || myPassword == null || 532 userName == null || password == null || 533 userName.length() == 0 || password.length() == 0 || 534 !myUserName.equals(userName) || 535 !myPassword.equals(password) ) 536 { 537 res.sendError( res.SC_UNAUTHORIZED ); 538 return; 539 } 540 541 if( req.getParameter( "showHTMLStat" ) != null ) { 543 showHTMLStat( req, res ); 544 } else if( req.getParameter( "getCurrentStat" ) != null ) { 545 getCurrentStat( req, res ); 546 } else if( req.getParameter( "getServerXMLInfo" ) != null ) { 547 getServerXMLInfo( req, res ); 548 } else { 549 showTextError( "unknown admin request", res ); 550 } 551 } 552 553 556 public void getCurrentStat( HttpServletRequest req, HttpServletResponse res ) 557 throws ServletException, IOException 558 { 559 res.setContentType( "application/x-www-urlformencoded" ); 560 PrintWriter pw = res.getWriter(); 561 562 pw.print( "threadsNum=" + currentThreadNum ); 563 pw.print( "&serverInfo=" + URLEncoder.encode(getServletContext().getServerInfo()) ); 564 565 StatUnit sinceStartup = StatManager.getSinceStartup(); 566 long upTime = System.currentTimeMillis() - sinceStartup.getStartTime(); 567 String upTimeStr = (upTime/3600000)+"h+"+((upTime/60000)%60)+"m+"+((upTime/1000)%60)+"s"; 568 pw.print( "&upTime=" + upTimeStr ); 569 sinceStartup.printVars(pw); 570 pw.close(); 571 } 572 573 576 public void showHTMLStat( HttpServletRequest req, HttpServletResponse res ) 577 throws ServletException, IOException 578 { 579 res.setContentType("text/html"); 580 PrintWriter pw = res.getWriter(); 581 pw.print( "<html><body>" ); 582 pw.print( "Current number of threads running: "+currentThreadNum+"<br>" ); 583 pw.print( "<hr>Since startup: " ); 584 StatManager.getSinceStartup().print(pw); 585 Vector v = StatManager.getStatistic(); 586 for( int i=0; i<v.size(); i++ ) { 587 pw.print("<hr>"); 588 StatUnit su = (StatUnit) v.elementAt(i); 589 su.print(pw); 590 } 591 pw.print("<hr>"); 592 pw.print( "</body></html>" ); 593 pw.close(); 594 } 595 596 599 public void getServerXMLInfo( HttpServletRequest req, HttpServletResponse res ) 600 throws ServletException, IOException 601 { 602 res.setContentType( "text/xml" ); 603 PrintWriter pw = res.getWriter(); 604 605 pw.println( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" ); 606 pw.println( "<!-- generated by JGenerator servlet -->" ); 607 609 pw.println( "<jgenerator-server>" ); 610 611 StatUnit sinceStartup = StatManager.getSinceStartup(); 612 613 long upTime = System.currentTimeMillis() - sinceStartup.getStartTime(); 615 String upTimeStr = (upTime/3600000)+"h+"+((upTime/60000)%60)+"m+"+((upTime/1000)%60)+"s"; 616 pw.println( "<server-info>" ); 617 pw.println( "<threads-num>"+currentThreadNum+"</threads-num>" ); 618 pw.println( "<uptime>"+upTimeStr+"</uptime>" ); 619 pw.println( "<description>"+getServletContext().getServerInfo()+"</description>" ); 620 pw.println( "</server-info>" ); 621 622 pw.println( "<statistics>" ); 624 sinceStartup.printXML(pw,true); 625 Vector v = StatManager.getStatistic(); 626 for( int i=0; i<v.size(); i++ ) { 627 StatUnit su = (StatUnit) v.elementAt(i); 628 su.printXML(pw,false); 629 } 630 pw.println( "</statistics>" ); 631 632 pw.println( "<properties>" ); 634 635 640 pw.println( "</properties>" ); 641 642 pw.println( "</jgenerator-server>" ); 643 644 pw.close(); 645 } 646 647 652 public class OnlineCommandExecutor extends CommandExecutor { 653 654 } 655 656 } 657 658 | Popular Tags |