You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by ch...@apache.org on 2008/05/10 03:16:22 UTC

svn commit: r655002 - in /incubator/shindig/trunk/php: config.php src/common/CacheFile.php src/gadgets/JsFeatureLoader.php src/gadgets/JsLibrary.php src/gadgets/http/GadgetRenderingServlet.php

Author: chabotc
Date: Fri May  9 18:16:22 2008
New Revision: 655002

URL: http://svn.apache.org/viewvc?rev=655002&view=rev
Log:
Optimized the features parsing and gadget output a bit, adding lazy loading and readfile operations where posible, plus removed un-used compress command.

Modified:
    incubator/shindig/trunk/php/config.php
    incubator/shindig/trunk/php/src/common/CacheFile.php
    incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php
    incubator/shindig/trunk/php/src/gadgets/JsLibrary.php
    incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php

Modified: incubator/shindig/trunk/php/config.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/config.php?rev=655002&r1=655001&r2=655002&view=diff
==============================================================================
--- incubator/shindig/trunk/php/config.php (original)
+++ incubator/shindig/trunk/php/config.php Fri May  9 18:16:22 2008
@@ -45,16 +45,6 @@
 
 	'focedJsLibs' => '',
 	
-	// The PHP gadget server can compress feature javascript libraries on the fly,
-	// set this command to the javascript compressor you want to to use, we advice
-	// using yuicompressor (http://developer.yahoo.com/yui/compressor/) but many others
-	// will work too. When building your command, use %1 as the input file, and %2 
-	// as the output file. Leave empty if you don't want this functionality.
-	//
-	// Config example for using the yuicompressor:
-	//'compress_command' => "java -jar " . realpath(dirname(__FILE__)) . "/yuicompressor-2.3.5.jar -o %2\$s %1\$s",
-	'compress_command' => '',
-	
 	// Configurable classes to use, this way we provide extensibility for what 
 	// backends the gadget server uses for its logic functionality. 
 	'blacklist_class' => 'BasicGadgetBlacklist',

Modified: incubator/shindig/trunk/php/src/common/CacheFile.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/CacheFile.php?rev=655002&r1=655001&r2=655002&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/CacheFile.php (original)
+++ incubator/shindig/trunk/php/src/common/CacheFile.php Fri May  9 18:16:22 2008
@@ -64,7 +64,7 @@
 		// we serialize the whole request object, since we don't only want the
 		// responseContent but also the postBody used, headers, size, etc
 		$data = serialize($value);
-		if (! file_put_contents($cacheFile, $data)) {
+		if (! @file_put_contents($cacheFile, $data)) {
 			throw new CacheException("Could not store data in cache file");
 		}
 	}

Modified: incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php?rev=655002&r1=655001&r2=655002&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php Fri May  9 18:16:22 2008
@@ -132,7 +132,7 @@
 					$content = $feature->basePath . '/' . $content;
 				}
 			}
-			$library = JsLibrary::create($type, $content, $this->debug);
+			$library = JsLibrary::create($type, $content);
 			if ($library != null) {
 				if ($isContainer) {
 					$feature->containerJs[] = $library;

Modified: incubator/shindig/trunk/php/src/gadgets/JsLibrary.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/JsLibrary.php?rev=655002&r1=655001&r2=655002&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/JsLibrary.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/JsLibrary.php Fri May  9 18:16:22 2008
@@ -23,7 +23,7 @@
 	private $type;
 	private $content;
 	private $featureName; // used to track what feature this belongs to
-
+	private $loaded = false;
 	
 	public function __construct($type, $content, $featureName = '')
 	{
@@ -36,9 +36,25 @@
 	{
 		return $this->type;
 	}
+	
+	public function readfile()
+	{
+		// hack to bypass having the script in memory and dump it directly to stdout
+		if (!$this->loaded && $this->type == 'FILE') {
+			readfile($this->content);
+			echo "\n";
+		} else {
+			// a call to getContent was already made so we have it in memory, just echo it then
+			echo $this->content;
+		}
+	}
 
 	public function getContent()
 	{
+		if (!$this->loaded && $this->type == 'FILE') {
+			$this->content = JsLibrary::loadData($this->content, $this->type);
+			$this->loaded = true;
+		}
 		return $this->content;
 	}
 
@@ -50,13 +66,13 @@
 	public function toString()
 	{
 		if ($this->type == 'URL') {
-			return "<script src=\"" . $this->content . "\"></script>";
+			return "<script src=\"" . $this->getContent() . "\"></script>";
 		} else {
-			return "<script><!--\n" . $this->content . "\n--></script>";
+			return "<script><!--\n" . $this->getContent() . "\n--></script>";
 		}
 	}
 
-	static function create($type, $content, $debug)
+	static function create($type, $content)
 	{
 		$feature = '';
 		if ($type == 'FILE') {
@@ -66,21 +82,20 @@
 				$feature = substr($feature, 0, strlen($feature) - 1);
 			}
 			$feature = substr($feature, strrpos($feature, '/') + 1);
-			$content = JsLibrary::loadData($content, $type, $debug);
 		}
 		return new JsLibrary($type, $content, $feature);
 	}
 
-	static private function loadData($name, $type, $debug)
+	static private function loadData($name, $type)
 	{
 		// we don't really do 'resources', so limiting this to files only
 		if ($type == 'FILE') {
-			return JsLibrary::loadFile($name, $debug);
+			return JsLibrary::loadFile($name);
 		}
 		return null;
 	}
 
-	static private function loadFile($fileName, $debug)
+	static private function loadFile($fileName)
 	{
 		if (empty($fileName)) {
 			return '';
@@ -94,25 +109,8 @@
 		if (! is_readable($fileName)) {
 			throw new Exception("JsLibrary file not readable: $fileName");
 		}
-		$compressCommand = Config::get('compress_command');
-		if ($debug || empty($compressCommand)) {
-			if (! ($content = @file_get_contents($fileName))) {
-				throw new Exception("JsLibrary error reading file: $fileName");
-			}
-		} else {
-			// attempt to compress the feature javascript file
-			$input_file = escapeshellarg($fileName);
-			$output_file = tempnam(Config::get('cache_root'), 'js-comp');
-			$cmd = sprintf($compressCommand, $input_file, $output_file);
-			$null = $status = 0;
-			exec($cmd, $null, $status);
-			if ($status === 0) {
-				// successfully compressed.
-				$content = file_get_contents($output_file);
-			} else {
-				// if the compress_command isn't functioning, just return the plain uncompressed content
-				$content = @file_get_contents($fileName);
-			}
+		if (! ($content = @file_get_contents($fileName))) {
+			throw new Exception("JsLibrary error reading file: $fileName");
 		}
 		return $content;
 	}

Modified: incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php?rev=655002&r1=655001&r2=655002&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php Fri May  9 18:16:22 2008
@@ -128,19 +128,31 @@
 	 */
 	private function outputHtmlGadget($gadget, $context, $view)
 	{
-		$this->setContentType("text/html; charset=UTF-8");
-		$output = '';
-		if (!$view->getQuirks()) {
-			$output .= "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">";
-		}
-		$output .= "<html>\n<head>\n";
-		// TODO: This is so wrong. (todo copied from java shindig, but i would agree with it :))
-		$output .= "<style type=\"text/css\">body,td,div,span,p{font-family:arial,sans-serif;} a {color:#0000cc;}a:visited {color:#551a8b;}a:active {color:#ff0000;}body{margin: 0px;padding: 0px;background-color:white;}</style>\n";
-		$output .= "</head>\n<body>\n";
 		$externJs = "";
-		$inlineJs = "";
 		$externFmt = "<script src=\"%s\"></script>";
 		$forcedLibs = $context->getForcedJsLibs();
+		$this->setContentType("text/html; charset=UTF-8");
+		if ($context->getIgnoreCache()) {
+			// no cache was requested, set non-caching-headers
+			$this->setNoCache(true);
+		} elseif (isset($_GET['v'])) {
+			// version was given, cache for a long long time (a year)
+			$this->setCacheTime(365 * 24 * 60 * 60);
+		} else {
+			// no version was given, cache for 5 minutes
+			$this->setCacheTime(5 * 60);
+		}
+		// Was a privacy policy header configured? if so set it
+		if (Config::get('P3P') != '') {
+			header("P3P: ".Config::get('P3P'));
+		}
+		if (!$view->getQuirks()) {
+			echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n";
+		}
+		echo "<html>\n<head>".
+		     "<style type=\"text/css\">body,td,div,span,p{font-family:arial,sans-serif;} a {color:#0000cc;}a:visited {color:#551a8b;}a:active {color:#ff0000;}body{margin: 0px;padding: 0px;background-color:white;}</style>".
+		     "</head><body>".
+		     "<script><!--\n";
 		foreach ( $gadget->getJsLibraries() as $library ) {
 			$type = $library->getType();
 			if ($type == 'URL') {
@@ -148,30 +160,29 @@
 				// servlet. We should probably inline external JS as well.
 				$externJs .= sprintf($externFmt, $library->getContent()) . "\n";
 			} else if ($type == 'INLINE') {
-				$inlineJs .= $library->getContent() . "\n";
+				$library->readfile();
 			} else {
 				// FILE or RESOURCE
 				if ($forcedLibs == null) {
-					$inlineJs .= $library->getContent() . "\n";
+					$library->readfile();
 				}
 				// otherwise it was already included by config.forceJsLibs.
 			}
 		}
+		echo "\n-->\n</script>\n";
 		// Forced libs first.
 		if (! empty($forcedLibs)) {
 			$libs = explode(':', $forcedLibs);
-			$output .= sprintf($externFmt, Config::get('default_js_prefix').$this->getJsUrl($libs, $gadget)) . "\n";
-		}
-		if (strlen($inlineJs) > 0) {
-			$output .= "<script><!--\n" . $inlineJs . "\n-->\n</script>\n";
+			echo sprintf($externFmt, Config::get('default_js_prefix').$this->getJsUrl($libs, $gadget)) . "\n";
 		}
 		if (strlen($externJs) > 0) {
-			$output .= $externJs;
+			echo $externJs;
 		}
-		$output .= "<script><!--\n";
-		$output .= $this->appendJsConfig($context, $gadget);
-		$output .= $this->appendMessages($gadget);
-		$output .= "-->\n</script>\n";
+		echo "<script><!--\n".
+		     $this->appendJsConfig($context, $gadget).
+		     $this->appendMessages($gadget).
+		     "-->\n</script>\n";
+		
 		$gadgetExceptions = array();
 		$content = $gadget->getSubstitutions()->substitute($view->getContent());
 		if (empty($content)) {
@@ -181,24 +192,9 @@
 		if (count($gadgetExceptions)) {
 			throw new GadgetException(print_r($gadgetExceptions, true));
 		}
-		$output .= $content . "\n";
-		$output .= "<script>gadgets.util.runOnLoadHandlers();</script>\n";
-		$output .= "</body>\n</html>";
-		if ($context->getIgnoreCache()) {
-			// no cache was requested, set non-caching-headers
-			$this->setNoCache(true);
-		} elseif (isset($_GET['v'])) {
-			// version was given, cache for a long long time (a year)
-			$this->setCacheTime(365 * 24 * 60 * 60);
-		} else {
-			// no version was given, cache for 5 minutes
-			$this->setCacheTime(5 * 60);
-		}
-		// Was a privacy policy header configured? if so set it
-		if (Config::get('P3P') != '') {
-			header("P3P: ".Config::get('P3P'));
-		}
-		echo $output;
+		echo $content . "\n".
+		     "<script>gadgets.util.runOnLoadHandlers();</script>\n".
+		     "</body>\n</html>";
 	}
 	
 	/**



Re: svn commit: r655002 - in /incubator/shindig/trunk/php: config.php src/common/CacheFile.php src/gadgets/JsFeatureLoader.php src/gadgets/JsLibrary.php src/gadgets/http/GadgetRenderingServlet.php

Posted by Chris Chabot <ch...@xs4all.nl>.
Ps anyone following the trunk make sure to do a rm -rf /tmp/shindig to  
clear your cache after this change. The internal formats of the  
(cached) js library classes changed a bit, and you'd get weird errors  
if you didn't (along the lines of "waring: readfile() file name to  
long")

	-- Chris

On May 10, 2008, at 3:16 AM, chabotc@apache.org wrote:

> Author: chabotc
> Date: Fri May  9 18:16:22 2008
> New Revision: 655002
>
> URL: http://svn.apache.org/viewvc?rev=655002&view=rev
> Log:
> Optimized the features parsing and gadget output a bit, adding lazy  
> loading and readfile operations where posible, plus removed un-used  
> compress command.
>
> Modified:
>    incubator/shindig/trunk/php/config.php
>    incubator/shindig/trunk/php/src/common/CacheFile.php
>    incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php
>    incubator/shindig/trunk/php/src/gadgets/JsLibrary.php
>    incubator/shindig/trunk/php/src/gadgets/http/ 
> GadgetRenderingServlet.php
>
> Modified: incubator/shindig/trunk/php/config.php
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/config.php?rev=655002&r1=655001&r2=655002&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- incubator/shindig/trunk/php/config.php (original)
> +++ incubator/shindig/trunk/php/config.php Fri May  9 18:16:22 2008
> @@ -45,16 +45,6 @@
>
> 	'focedJsLibs' => '',
> 	
> -	// The PHP gadget server can compress feature javascript libraries  
> on the fly,
> -	// set this command to the javascript compressor you want to to  
> use, we advice
> -	// using yuicompressor (http://developer.yahoo.com/yui/ 
> compressor/) but many others
> -	// will work too. When building your command, use %1 as the input  
> file, and %2
> -	// as the output file. Leave empty if you don't want this  
> functionality.
> -	//
> -	// Config example for using the yuicompressor:
> -	//'compress_command' => "java -jar " .  
> realpath(dirname(__FILE__)) . "/yuicompressor-2.3.5.jar -o %2\$s %1\ 
> $s",
> -	'compress_command' => '',
> -	
> 	// Configurable classes to use, this way we provide extensibility  
> for what
> 	// backends the gadget server uses for its logic functionality.
> 	'blacklist_class' => 'BasicGadgetBlacklist',
>
> Modified: incubator/shindig/trunk/php/src/common/CacheFile.php
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/CacheFile.php?rev=655002&r1=655001&r2=655002&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- incubator/shindig/trunk/php/src/common/CacheFile.php (original)
> +++ incubator/shindig/trunk/php/src/common/CacheFile.php Fri May  9  
> 18:16:22 2008
> @@ -64,7 +64,7 @@
> 		// we serialize the whole request object, since we don't only want  
> the
> 		// responseContent but also the postBody used, headers, size, etc
> 		$data = serialize($value);
> -		if (! file_put_contents($cacheFile, $data)) {
> +		if (! @file_put_contents($cacheFile, $data)) {
> 			throw new CacheException("Could not store data in cache file");
> 		}
> 	}
>
> Modified: incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php?rev=655002&r1=655001&r2=655002&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php  
> (original)
> +++ incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php Fri  
> May  9 18:16:22 2008
> @@ -132,7 +132,7 @@
> 					$content = $feature->basePath . '/' . $content;
> 				}
> 			}
> -			$library = JsLibrary::create($type, $content, $this->debug);
> +			$library = JsLibrary::create($type, $content);
> 			if ($library != null) {
> 				if ($isContainer) {
> 					$feature->containerJs[] = $library;
>
> Modified: incubator/shindig/trunk/php/src/gadgets/JsLibrary.php
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/JsLibrary.php?rev=655002&r1=655001&r2=655002&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- incubator/shindig/trunk/php/src/gadgets/JsLibrary.php (original)
> +++ incubator/shindig/trunk/php/src/gadgets/JsLibrary.php Fri May  9  
> 18:16:22 2008
> @@ -23,7 +23,7 @@
> 	private $type;
> 	private $content;
> 	private $featureName; // used to track what feature this belongs to
> -
> +	private $loaded = false;
> 	
> 	public function __construct($type, $content, $featureName = '')
> 	{
> @@ -36,9 +36,25 @@
> 	{
> 		return $this->type;
> 	}
> +	
> +	public function readfile()
> +	{
> +		// hack to bypass having the script in memory and dump it  
> directly to stdout
> +		if (!$this->loaded && $this->type == 'FILE') {
> +			readfile($this->content);
> +			echo "\n";
> +		} else {
> +			// a call to getContent was already made so we have it in  
> memory, just echo it then
> +			echo $this->content;
> +		}
> +	}
>
> 	public function getContent()
> 	{
> +		if (!$this->loaded && $this->type == 'FILE') {
> +			$this->content = JsLibrary::loadData($this->content, $this->type);
> +			$this->loaded = true;
> +		}
> 		return $this->content;
> 	}
>
> @@ -50,13 +66,13 @@
> 	public function toString()
> 	{
> 		if ($this->type == 'URL') {
> -			return "<script src=\"" . $this->content . "\"></script>";
> +			return "<script src=\"" . $this->getContent() . "\"></script>";
> 		} else {
> -			return "<script><!--\n" . $this->content . "\n--></script>";
> +			return "<script><!--\n" . $this->getContent() . "\n--></script>";
> 		}
> 	}
>
> -	static function create($type, $content, $debug)
> +	static function create($type, $content)
> 	{
> 		$feature = '';
> 		if ($type == 'FILE') {
> @@ -66,21 +82,20 @@
> 				$feature = substr($feature, 0, strlen($feature) - 1);
> 			}
> 			$feature = substr($feature, strrpos($feature, '/') + 1);
> -			$content = JsLibrary::loadData($content, $type, $debug);
> 		}
> 		return new JsLibrary($type, $content, $feature);
> 	}
>
> -	static private function loadData($name, $type, $debug)
> +	static private function loadData($name, $type)
> 	{
> 		// we don't really do 'resources', so limiting this to files only
> 		if ($type == 'FILE') {
> -			return JsLibrary::loadFile($name, $debug);
> +			return JsLibrary::loadFile($name);
> 		}
> 		return null;
> 	}
>
> -	static private function loadFile($fileName, $debug)
> +	static private function loadFile($fileName)
> 	{
> 		if (empty($fileName)) {
> 			return '';
> @@ -94,25 +109,8 @@
> 		if (! is_readable($fileName)) {
> 			throw new Exception("JsLibrary file not readable: $fileName");
> 		}
> -		$compressCommand = Config::get('compress_command');
> -		if ($debug || empty($compressCommand)) {
> -			if (! ($content = @file_get_contents($fileName))) {
> -				throw new Exception("JsLibrary error reading file: $fileName");
> -			}
> -		} else {
> -			// attempt to compress the feature javascript file
> -			$input_file = escapeshellarg($fileName);
> -			$output_file = tempnam(Config::get('cache_root'), 'js-comp');
> -			$cmd = sprintf($compressCommand, $input_file, $output_file);
> -			$null = $status = 0;
> -			exec($cmd, $null, $status);
> -			if ($status === 0) {
> -				// successfully compressed.
> -				$content = file_get_contents($output_file);
> -			} else {
> -				// if the compress_command isn't functioning, just return the  
> plain uncompressed content
> -				$content = @file_get_contents($fileName);
> -			}
> +		if (! ($content = @file_get_contents($fileName))) {
> +			throw new Exception("JsLibrary error reading file: $fileName");
> 		}
> 		return $content;
> 	}
>
> Modified: incubator/shindig/trunk/php/src/gadgets/http/ 
> GadgetRenderingServlet.php
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php?rev=655002&r1=655001&r2=655002&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- incubator/shindig/trunk/php/src/gadgets/http/ 
> GadgetRenderingServlet.php (original)
> +++ incubator/shindig/trunk/php/src/gadgets/http/ 
> GadgetRenderingServlet.php Fri May  9 18:16:22 2008
> @@ -128,19 +128,31 @@
> 	 */
> 	private function outputHtmlGadget($gadget, $context, $view)
> 	{
> -		$this->setContentType("text/html; charset=UTF-8");
> -		$output = '';
> -		if (!$view->getQuirks()) {
> -			$output .= "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"  
> \"http://www.w3.org/TR/html4/strict.dtd\">";
> -		}
> -		$output .= "<html>\n<head>\n";
> -		// TODO: This is so wrong. (todo copied from java shindig, but i  
> would agree with it :))
> -		$output .= "<style type=\"text/css\">body,td,div,span,p{font- 
> family:arial,sans-serif;} a {color:#0000cc;}a:visited  
> {color:#551a8b;}a:active {color:#ff0000;}body{margin: 0px;padding:  
> 0px;background-color:white;}</style>\n";
> -		$output .= "</head>\n<body>\n";
> 		$externJs = "";
> -		$inlineJs = "";
> 		$externFmt = "<script src=\"%s\"></script>";
> 		$forcedLibs = $context->getForcedJsLibs();
> +		$this->setContentType("text/html; charset=UTF-8");
> +		if ($context->getIgnoreCache()) {
> +			// no cache was requested, set non-caching-headers
> +			$this->setNoCache(true);
> +		} elseif (isset($_GET['v'])) {
> +			// version was given, cache for a long long time (a year)
> +			$this->setCacheTime(365 * 24 * 60 * 60);
> +		} else {
> +			// no version was given, cache for 5 minutes
> +			$this->setCacheTime(5 * 60);
> +		}
> +		// Was a privacy policy header configured? if so set it
> +		if (Config::get('P3P') != '') {
> +			header("P3P: ".Config::get('P3P'));
> +		}
> +		if (!$view->getQuirks()) {
> +			echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd 
> \">\n";
> +		}
> +		echo "<html>\n<head>".
> +		     "<style type=\"text/css\">body,td,div,span,p{font- 
> family:arial,sans-serif;} a {color:#0000cc;}a:visited  
> {color:#551a8b;}a:active {color:#ff0000;}body{margin: 0px;padding:  
> 0px;background-color:white;}</style>".
> +		     "</head><body>".
> +		     "<script><!--\n";
> 		foreach ( $gadget->getJsLibraries() as $library ) {
> 			$type = $library->getType();
> 			if ($type == 'URL') {
> @@ -148,30 +160,29 @@
> 				// servlet. We should probably inline external JS as well.
> 				$externJs .= sprintf($externFmt, $library->getContent()) . "\n";
> 			} else if ($type == 'INLINE') {
> -				$inlineJs .= $library->getContent() . "\n";
> +				$library->readfile();
> 			} else {
> 				// FILE or RESOURCE
> 				if ($forcedLibs == null) {
> -					$inlineJs .= $library->getContent() . "\n";
> +					$library->readfile();
> 				}
> 				// otherwise it was already included by config.forceJsLibs.
> 			}
> 		}
> +		echo "\n-->\n</script>\n";
> 		// Forced libs first.
> 		if (! empty($forcedLibs)) {
> 			$libs = explode(':', $forcedLibs);
> -			$output .= sprintf($externFmt, Config::get('default_js_prefix'). 
> $this->getJsUrl($libs, $gadget)) . "\n";
> -		}
> -		if (strlen($inlineJs) > 0) {
> -			$output .= "<script><!--\n" . $inlineJs . "\n-->\n</script>\n";
> +			echo sprintf($externFmt, Config::get('default_js_prefix').$this- 
> >getJsUrl($libs, $gadget)) . "\n";
> 		}
> 		if (strlen($externJs) > 0) {
> -			$output .= $externJs;
> +			echo $externJs;
> 		}
> -		$output .= "<script><!--\n";
> -		$output .= $this->appendJsConfig($context, $gadget);
> -		$output .= $this->appendMessages($gadget);
> -		$output .= "-->\n</script>\n";
> +		echo "<script><!--\n".
> +		     $this->appendJsConfig($context, $gadget).
> +		     $this->appendMessages($gadget).
> +		     "-->\n</script>\n";
> +		
> 		$gadgetExceptions = array();
> 		$content = $gadget->getSubstitutions()->substitute($view- 
> >getContent());
> 		if (empty($content)) {
> @@ -181,24 +192,9 @@
> 		if (count($gadgetExceptions)) {
> 			throw new GadgetException(print_r($gadgetExceptions, true));
> 		}
> -		$output .= $content . "\n";
> -		$output .= "<script>gadgets.util.runOnLoadHandlers();</script>\n";
> -		$output .= "</body>\n</html>";
> -		if ($context->getIgnoreCache()) {
> -			// no cache was requested, set non-caching-headers
> -			$this->setNoCache(true);
> -		} elseif (isset($_GET['v'])) {
> -			// version was given, cache for a long long time (a year)
> -			$this->setCacheTime(365 * 24 * 60 * 60);
> -		} else {
> -			// no version was given, cache for 5 minutes
> -			$this->setCacheTime(5 * 60);
> -		}
> -		// Was a privacy policy header configured? if so set it
> -		if (Config::get('P3P') != '') {
> -			header("P3P: ".Config::get('P3P'));
> -		}
> -		echo $output;
> +		echo $content . "\n".
> +		     "<script>gadgets.util.runOnLoadHandlers();</script>\n".
> +		     "</body>\n</html>";
> 	}
> 	
> 	/**
>