<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<book>
  <bookinfo>
    <title>Red5 Flash Server</title>

    <subtitle>Reference Documentation</subtitle>

    <releaseinfo>1.0.0</releaseinfo>

    <authorgroup>
      <author>
        <firstname>Dan</firstname>

        <surname>Rossi</surname>
      </author>
    </authorgroup>
  </bookinfo>

  <toc></toc>

  <preface id="preface">
    <title>Preface</title>

    <para>Overall Preface here</para>
   </preface>

  <part id="red5-architecture">
    <title>Red5 Architecture</title>

    <partintro>
      <para>Part intro</para>
    </partintro>

    <chapter id="introduction">
    	<chapterinfo>
    		<date>10/24/05</date>
    		<authorgroup>
    			<author>
    				<firstname>Dominick </firstname>
    				<surname>Accattato</surname>
    				<email>(daccattato at gmail dot com)</email>
    			</author>
    		</authorgroup>
    	</chapterinfo>
    	
    	<title>Introduction</title>
    	
    			
      <sect1 id="what-is-red5">
      	<title>What is Red5?</title>

      	<para>An open source project dedicated towards the interaction between the Flash Player and a 
      		Free Connection Oriented Server using rtmp (real time messaging protocol).
      	</para>
      </sect1>
    	
    	<sect1 id="download-red5">
    		<title>Where can I download Red5?</title>
    		
    		<para><ulink url="http://osflash.org/red5#conference_links">Mirrors: http://osflash.org/red5#conference_links</ulink></para>
    	</sect1>
    	
    	<sect1 id="why-does-red5-exist">
    		<title>Why does Red5 exist?</title>
    		
    		<para>
    			Like most open source projects, the project exists because there was interest in the topic.  
    			Even before any code was written people had been dissecting the bytes that come down the pipe 
    			from the flash comm server and flash player interaction.
    		</para>
    	</sect1>
    	
    	<sect1 id="what-does-red5-mean">
    		<title>What does Red5 mean?</title>
    		
    		<para>
    			<ulink url="http://osflash.org/red5#why_red5">Please read: Why "RED5"?</ulink>
    		</para>
    	</sect1>
    	
    	<sect1 id="why-is-it-not-called-red5-media-server">
    		<title>Why is it not called Red5 Media Server?</title>
    		<para>
    			Red5 does much more than server up media.  We feel that Red5 is a technology.  
    		</para>
    	</sect1>
    	
    	<sect1 id="what-other-names-does-red5-go-by">
    		<title>What other names does Red5 go by?</title>
    		<para>
    			Red5 aka R5
    		</para>
    	</sect1>
    	
    	<sect1 id="what-does-the-red5-logo-look-like">
    		<title>What does the Red5 logo look like?</title>
    		<para>
    			<graphic fileref="images/FinalLogo.png" format="PNG" width="200" />
    		</para>
    	</sect1>
    	
    	<sect1 id="rtmp-legal">
    		<title>Is Red5 Legal ?</title>
    		<para>
    			RTMP (real time messaging protocol) has been introduced to the Flash Platform as a proprietary closed source protocol.  
    			Can we legally create source code that may unveil the true workings behind this protocol?
    		</para>
    		<para>
    			Yes, examining packets is not illegal. The Red5 team has stated its intent to remain completely legal in 
    			this situation, and thanks to some outstanding developers in the Flash world, 
    			we've never had to even consider any other alternative.
    		</para>
    	</sect1>
    	
    	<sect1 id="outcome-of-project">
    		<title>What is the outcome of this project ?</title>
    		<para>
    			What would be the best possible scenario that could come out of this project?
    		</para>
    		<para>
    			Macromedia would endorse us and provide the open source community with the RTMP protocol specifications.  
    			This would greatly help out the few who are coding “Free Servers” out there including 
    			the Red5 open source project.
    		</para>
    	</sect1>
    	
    	<sect1 id="what-license-does-red5-use">
    		<title>What license does Red5 use?</title>
    		<para>
    			Red5 uses the LGPL license.  <ulink url="http://www.opensource.org/licenses/lgpl-license.php">LGPL license</ulink>
    		</para>
    	</sect1>
    	
    	<sect1 id="what-is-the-estimated-time-of-delivery-for-red5">
    		<title>What is the estimated time of delivery for Red5 ?</title>
    		<para>
    			Please Review:  <ulink url="http://review.codegent.net/opensource/RED5_draft_roadmap.pdf">Project Roadmap</ulink>.
    		</para>
    	</sect1>
    	
    	<sect1 id="what-is-rtmp">
    		<title>RTMP</title>
    		<para>
    			<ulink url="http://en.wikipedia.org/wiki/Real_Time_Messaging_Protocol">Real Time Messaging Protocol</ulink> (RTMP) Is a proprietary protocol developed by 
    			Macromedia that is primarily used with Macromedia's Media Server product to stream audio 
    			and video over the web. 
    			
    			The default connection port is 1935.
    		</para>
    		<para>Red5 page dedicated to RTMP: <ulink url="http://osflash.org/rtmp_os">http://osflash.org/rtmp_os</ulink>.</para>
    	</sect1>
    	
    	<sect1 id="what-is-amf">
    		<title>AMF</title>
    		<para>
    			Action Message Format (AMF) is a binary message format designed for the ActionScript object model.
    		</para>
    	</sect1>
    	
    	<sect1 id="what-implementations-are-there">
    		<title>What implementations are there ?</title>
    		<para>
    			Java and Ruby.  Currently all focus has been on the Java implementation. 
    		</para>
    	</sect1>
    	
    	<sect1 id="how-mature-is-the-java-implementation">
    		<title>How mature is the Java implementation?</title>
    		<para>
    			There is a codebase checked into subversion.  The code currently uses two frameworks, 
    			<link linkend="why-choose-mina">Mina</link> and <link linkend="why-choose-spring">Spring</link> discussed below.  The protocol handler has been created and output of byte 
    			information is viewable.  Team members are currently testing the code and sending different rtmp 
    			calls from the flash player to figure out how to deal with the rest of the rmtp protocol.  
    		</para>
    	</sect1>
    	
    	<sect1 id="why-choose-mina">
    		<title>Why did the Red5 team choose Mina?</title>
    		<para>
    			It allowed us to focus on the protocol, and not implementing low level nio code. 
    			We also plan to implement other protocols / transports in the future so having a 
    			standard framework is good.
    		</para>
    		<para>
    			I looked at a number of frameworks for this. Mina, EmberIO, Mule, etc. 
    			Mina seemed to be the most focused and developed (essentially being v2 of Netty). 
    			EmberIO is quite similar and something we should look into in the future, esp the threading 
    			stategies but not as mature or documented as a framework. Mule seems to be message exchange / 
    			network framework on speed. It does everything which I think is too much for our stage of development.
    		</para>
    	</sect1>
    	
    	<sect1 id="why-choose-spring">
    		<title>Why did the Red5 team choose Spring?</title>
    		<para>
    			TODO
    		</para>
    	</sect1>
    	
    	<sect1 id="component-frameworks">
    		<title>Which component frameworks are we currently reviewing?</title>
    		<para>
    			Actionstep, ASwing.
    		</para>
    	</sect1>
    	
    	<sect1 id="advantages-component-frameworks">
    		<title>What are the advantages of this framework?</title>
    		<para>
    			TODO
    		</para>
    	</sect1>
    	
    	<sect1 id="eta-component-frameworks">
    		<title>What is the estimated time of delivery for these components (eta)?</title>
    		<para>
    			TODO
    		</para>
    	</sect1>
    	
    	<sect1 id="use-component-frameworks">
    		<title>Do I have to use this component framework?</title>
    		<para>
    			TODO
    		</para>
    	</sect1>
    	
    	<sect1 id="use-flash-component-frameworks">
    		<title>Can I use Macromedia Flash Communication Server components?</title>
    		<para>
    			TODO
    		</para>
    	</sect1>
    	
    	<sect1 id="choice-of-ide">
    		<title>What IDE (integrated development environment) are we using?</title>
    		<para>
    			I’m using eclipse.  I know a few others are too.  As well, you will need to install the subversion plugin 
    			so that you can check out the code base.  
    			Additionally, you should install one of the actionscript plugins if you plan to do any of the front end coding.
    		</para>
    		<para>
    			Recommend IDE / Software
    			
    			<itemizedlist>
    				<listitem>
    					<para><ulink url="http://www.eclipse.org/downloads">Eclipse IDE </ulink></para>
    				</listitem>
    				<listitem>
    					<para><ulink url="http://springide.org/project">Spring IDE Eclipse Plugin </ulink></para>
    				</listitem>
    				<listitem>
    					<para><ulink url="http://aseclipseplugin.sourceforge.net/wordpress">ASDT Eclipse Actionscript Plugin </ulink></para>
    				</listitem>
    			</itemizedlist>
    			
    		</para>
    	</sect1>
    	
    	<sect1 id="red5-irc">
    		<title>Is there a place that we can meet and talk about the project status?</title>
    		<para>
    			Yes, you can join a few of us developers on IRC (internet relay chat).  
    			Connect to the irc.freenet.org server and then join room #red5
    		</para>
    	</sect1>
    	
    	<sect1 id="red5-mailing-list">
    		<title>Is there a mailing list ?</title>
    		<para>
    			Yes, <ulink url="red5@osflash.org">red5@osflash.org</ulink>.  
    			You can find more information on the site <ulink url="http://osflash.org/doku.php?id=red5">http://osflash.org/doku.php?id=red5</ulink>
    		</para>
    	</sect1>
    	
    	<sect1 id="best-place-to-start">
    		<title>Where’s the best place to start?</title>
    		<para>
    			Where’s the best place to start?
    			Read about the protocol.  <ulink url="http://osflash.org/doku.php?id=red5#protocol">http://osflash.org/doku.php?id=red5#protocol</ulink>.    
    			Navigate the Red5 site, learn the basics behind the frameworks.  
    			Then check out the codebase and discuss through one of the many communication channels (irc, mailing list).  
    			If you are interested in becoming a Red5 team member please fill out the <ulink url="http://osflash.org/red5_signupform">Team Signup Form</ulink> and email it to the project managers.
    		</para>
    	</sect1>
    	
    	<sect1 id="what-are-the-milestones">
    		<title>What are the milestones ?</title>
    		<para>
    			TODO
    		</para>
    	</sect1>
    	
    	<sect1 id="team-members">
    		<title>Who are the team members?</title>
    		<para>
    			Project Management
    			<itemizedlist>
    				<listitem><para><ulink url="http://osflash.org/chris_allen">Chris Allen</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/john_grden">John Grden</ulink></para></listitem>
    			</itemizedlist>
    			
    			Server Side Development
    			<itemizedlist>
    				<listitem><para><ulink url="http://osflash.org/mick_merres">Mick Merres</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/luke_hubbard">Luke Hubbard</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/grant_davies">Grant Davies</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/fernando_augusto">Fernando Augusto</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/lucas_ferreira">Lucas Ferreira</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/chris_allen">Chris Allen</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/ashvin_savani">Ashvin Savani</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/yannick_connan">Yannick Connan</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/dominick_accattato">Dominick Accattato</ulink></para></listitem>
    			</itemizedlist>
    			
    			Release Manager
    			<itemizedlist>
    				<listitem><para><ulink url="http://osflash.org/grant_davies">Grant Davies</ulink></para></listitem>
    			</itemizedlist>
    			
    			Codecs/Media integration
    			<itemizedlist>
    				<listitem><para><ulink url="http://osflash.org/dominick_accattato">Dominick Accattato</ulink></para></listitem>
    			</itemizedlist>
    			
    			Client Side/API Testing
    			<itemizedlist>
    				<listitem><para><ulink url="http://osflash.org/john_grden">John Grden</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/marcos_augusto">Marcos Augusto</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/gabriel_laet">Gabriel Laet</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/marlos_carmo">Marlos Carmo</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/tim_beynart">Tim Beynart</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/lucas_ferreira">Lucas Ferreira</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/chris_allen">Chris Allen</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/ashvin_savani">Ashvin Savani</ulink></para></listitem>
    			</itemizedlist>
    			
    			Branding/Logo/Website
    			<itemizedlist>
    				<listitem><para><ulink url="http://osflash.org/tim_beynart">Tim Beynart</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/aldo_bucchi">Aldo Bucchi</ulink></para></listitem>
    			</itemizedlist>
    			
    			Documentation
    			<itemizedlist>
    				<listitem><para><ulink url="http://osflash.org/patrick_mineault">Patrick Mineault (AMF documentation)</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/john_grden">John Grden</ulink></para></listitem>
    				<listitem><para><ulink url="http://osflash.org/lee_mccoll-sylvester">Lee McColl-Sylvester</ulink></para></listitem>
    			</itemizedlist>
    		</para>
    	</sect1>
    </chapter>
  	
  	<chapter id="migration-guide">
  		<chapterinfo>
  			<date>2006-11-15 10:22:04 +1100 (Wed, 15 Nov 2006)</date>
  			<authorgroup>
  				<author>
  					<firstname>Joachim</firstname>
  					<surname>Bauch</surname>
  					<email>jojo@struktur.de</email>
  				</author>
  			</authorgroup>
  		
  		</chapterinfo>
  		
  		<title>Migration guide from FCS/FMS to Red5</title> 
		<para>
			This document describes API differences between the Macromedia Flash
			Communication Server / Flash Media Server 2 and Red5.  It aims at helping
			migrate existing applications to Red5.
			
			If you don't have an application in Red5 yet, please read the tutorial about
			`howto create new applications`__ first.
		</para>
  		
  		<sect1 id="application-callbacks">
  			<title>Application callbacks</title>
  			<para>
  				When implementing serverside applications, one of the most important
  				functionalities is to get notified about clients that connect or disconnect
  				and to be informed about the creation of new instances of the application.
  			</para>
  		</sect1>
  		
  		<sect1 id="interface-iscopehandler">
  			<title>Interface IScopeHandler</title>
  			<para>
  				Red5 specifies these actions in the interface IScopeHandler_.  See the API
  				documentation for further details.
  			</para>
  		</sect1>
  		
  		<sect1 id="class-applicationadapter">
  			<title>Class ApplicationAdapter</title>
  			<para>
  				As some methods may be called multiple times for one request (e.g. `connect`
  				will be called once for every scope in the tree the client connects to),
  				the class ApplicationAdapter_ defines additional methods.
  				
  				This class usually is used as base class for new applications.
  				
  				Here is a short overview of methods of the FCS / FMS `application` class and
  				their corresponding methods of ApplicationAdapter_ in Red5:
  			</para>
  			
  			<table id="compare-table">
  				<title></title>
  				<tgroup cols="2" align="left" colsep="1" rowsep="1">
  					<colspec colname="c1"/>
  					<colspec colname="c2"/>
  					<thead>
  						<row>
  							<entry>FCS / FMS</entry>
  							<entry>Red5</entry>
  						</row>
  					</thead>
  					<tbody>					
  						<row>
  							<entry>onAppStart</entry>
  							<entry>
  								appStart
  								roomStart
  							</entry>
  						</row>
  						<row>
  							<entry>onAppStop </entry>
  							<entry>
  								appStop
  								roomStop
  							</entry>
  						</row>
  						<row>
  							<entry>onConnect</entry>
  							<entry>
  								appConnect
  								roomConnect
  								appJoin
  								roomJoin
  							</entry>
  						</row>
  						<row>
  							<entry>onDisconnect</entry>
  							<entry>
  								appDisconnect
  								roomDisconnect
  								appLeave
  								roomLeave
  							</entry>
  						</row>
  					</tbody>
  				</tgroup>
  			</table>
  			<para>
  				The `app*` methods are called for the main application, the `room*` methods
  				are called for rooms (i.e. instances) of the application.
  				
  				You can also also use the ApplicationAdapter_ to check for streams, shared
  				objects, or subscribe them.  See the API documentation for further details.
  			</para>
  			
  		</sect1>
  		
  		<sect1 id="execution-order-of-connection-methods">
  			<title>Execution order of connection methods</title>
  			<para>
  				Assuming you connect to `rtmp://server/app/room1/room2`
  				
  				At first, the connection is established, so the user "connects" to all scopes
  				that are traversed up to `room2`:
  				
  				<orderedlist>
  					<listitem>
  						<para>`app`     (-> appConnect)</para>
  					</listitem>
  					<listitem>
  						<para>`room1`   (-> roomConnect)</para>
  					</listitem>
  					<listitem>
  						<para>`room2`   (-> roomConnect)</para>
  					</listitem>
  				</orderedlist>
  				
  			</para>
  			<para>
  				After the connection is established, the client object is retrieved and if
  				it's the first connection by this client to the scope, he "joins" the scopes:
  				
  				<orderedlist>
  					<listitem>
  						<para>`app`     (-> appJoin)</para>
  					</listitem>
  					<listitem>
  						<para>`room1`   (-> roomJoin)</para>
  					</listitem>
  					<listitem>
  						<para>`room2`   (-> roomJoin)</para>
  					</listitem>
  				</orderedlist>
  			</para>
  			<para>
  				If the same client establishes a second connection to the same scope, only
  				the `connect` methods will be called.  If you conect to partially the same
  				scopes, only a few `join` methods might be called, e.g.
  				`rtmp://server/app/room1/room3` will trigger
  				
  				
  				<orderedlist>
  					<listitem>
  						<para>`appConnect("app")`</para>
  					</listitem>
  					<listitem>
  						<para>`joinConnect("room1")`</para>
  					</listitem>
  					<listitem>
  						<para>`joinConnect("room3")`</para>
  					</listitem>
  					<listitem>
  						<para>`roomJoin("room3")`</para>
  					</listitem>
  				</orderedlist>
  			</para>
  			<para>
  				The `appStart` method currently is only called once during startup of Red5
  				as it currently can't unload/load applications like FCS/FMS does.
  				The `roomStart` methods are called when the first client connects to a room. 
  			</para>
  		</sect1>
  		
  		<sect1 id="accepting-rejecting-clients">
  			<title>Accepting / rejecting clients</title>
  			<para>
  				FCS / FMS provide the methods `acceptConnection` and `rejectConnection` to
  				accept and reject new clients.  To allow clients to connect, no special
  				action is required by Red5 applications, the `*Connect` methods just need
  				to return `true` in this case.
  				
  				If a client should not be allowed to connect, the method `rejectClient`
  				can be called which is implemented by the ApplicationAdapter_ class. Any
  				parameter passed to `rejectClient` is available as the `application`
  				property of the status object that is returned to the caller.
  			</para>
  		</sect1>
  		
  		<sect1 id="current-connection-and-clients">
  			<title>Current connection and client</title>
  			<para>
  				Red5 supports two different ways to access the current connection from an
  				invoked method.  The connection can  be used to get the active client and
  				the scope he is connected to.  The first possibility uses the "magic" Red5_
  				object:
  			</para>
  			<programlisting>
  				<literal>
  					import org.red5.server.api.IClient;
  					import org.red5.server.api.IConnection;
  					import org.red5.server.api.IScope;
  					import org.red5.server.api.Red5;
  					
  					public void whoami() {
  						IConnection conn = Red5.getConnectionLocal();
  						IClient client = conn.getClient();
  						IScope scope = conn.getScope();
  						// ...
  					}
  				</literal>
  			</programlisting>
  			<para>
  				The second possiblity requires the method to be defined with an argument of
  				type IConnection_ as implicit first parameter which is automatically added
  				by Red5 when a client calls the method:
  			</para>
  			<programlisting>
  				<literal>
  					import org.red5.server.api.IClient;
  					import org.red5.server.api.IConnection;
  					import org.red5.server.api.IScope;
  					
  					public void whoami(IConnection conn) {
  						IClient client = conn.getClient();
  						IScope scope = conn.getScope();
  						// ...
  					}
  				</literal>
  			</programlisting>
  		</sect1>
  		
  		<sect1 id="additonal-handlers">
  			<title>Additional handlers</title>
  			<para>
  				For many applications, existing classes containing application logic that
  				is not related to Red5 are required to be reused.  In order to make them
  				available for clients connecting through RTMP, these classes need to be
  				registered as handlers in Red5.
  			</para>
  			<para>
  				There are currently two ways to register these handlers:
  				
  				<orderedlist>
  					<listitem>
  						<para>By adding them to the configuration files.</para>
  					</listitem>
  					<listitem>
  						<para>By registering them manually from the application code.</para>
  					</listitem>
  				</orderedlist>
  			</para>
  			<para>
  				The handlers can be executed by clients with code similar to this:
  				
  				<programlisting>
  					<literal>
  						nc = new NetConnection();
  						nc.connect("rtmp://localhost/myapp");
  						nc.call("handler.method", nc, "Hello world!");
  					</literal>
  				</programlisting>
  				
  				If a handler is requested, Red5 always looks it up in the custom scope
  				handlers before checking the handlers that have been set up in the context
  				through the configuration file.
  			</para>
  		</sect1>
  		
  		<sect1 id="handlers-in-configuration-files">
  			<title>Handlers in configuration files</title>
  			<para>
  				This method is best suited for handlers that are common to all scopes the
  				application runs in and that don't need to change during the lifetime of
  				an application.
  			</para>
  			
  			<para>
  				To register the class `com.fancycode.red5.HandlerSample` as handler `sample`,
  				the following bean needs to be added to `WEB-INF/red5-web.xml`:
  				
  				<programlisting>
  					<literal>
  						<![CDATA[
  						
  						<bean id="sample.service" 
  							class="com.fancycode.red5.HandlerSample" 
  							singleton="true" />
  						]]>
  					</literal>
  				</programlisting>
  				
  				<note id="note-handlers-from-configuration">
  					<para>
  						Note that the id of the bean is constructed as the name of the handler
  						(here `sample`) and the keyword `service`.
  					</para>
  				</note>
  			</para>
  		</sect1>
  		
  		<sect1 id="handlers-from-application-code">
  			<title>Handlers from application code</title>
  			<para>
  				All applications that use handlers which are different for the various
  				scopes or want to change handlers, need a way to register them from the
  				serverside code.  These handlers always override the handlers configured in
  				`red5-web.xml`.  The methods required for registration are described in the
  				interface IServiceHandlerProvider_ which is implemented by
  				ApplicationAdapter_.
  			</para>
  			
  			<para>
  				The same class as above can be registered using this code:
  				
  				<programlisting>
  					<literal>
  						public boolean appStart(IScope app) {
	  						if (!super.appStart(scope))
	  						return false;
	  						
	  						Object handler = new com.fancycode.red5.HandlerSample();
	  						app.registerServiceHandler("sample", handler);
	  						return true;
  						}
  					</literal>
  				</programlisting>
  				
  				<note id="note-handlers-from-application">
  					<para>
  						Note that in this example, only the application scope has the `sample`
  						handler but not the subscopes!  If the handler should be available in the
  						rooms as well, it must be registered in `roomStart` for the room scopes.
  					</para>
  				</note>
  			</para>
  		</sect1>
  		
  		<sect1 id="calls-to-client-methods">
  			<title>Calls to client methods</title>  			
  			<para>
  				To call methods from your Red5 application on the client, you will first need
  				a reference to the current connection object:
  				
  				<programlisting>
  					<literal>
  						import org.red5.server.api.IConnection;
  						import org.red5.server.api.Red5;
  						import org.red5.server.api.service.IServiceCapableConnection;
  						...
  						IConnection conn = Red5.getConnectionLocal();
  					</literal>
  				</programlisting>
  				
  				If the connection implements the IServiceCapableConnection_ interface, it
  				supports calling methods on the other end:
  				
  				<programlisting>
  					<literal>
  						if (conn instanceof IServiceCapableConnection) {
  							IServiceCapableConnection sc = (IServiceCapableConnection) conn;
  							sc.invoke("the_method", new Object[]{"One", 1});
  						}
  					</literal>
  				</programlisting>
  				
  				If you need the result of the method call, you must provide a class that
  				implements the IPendingServiceCallback_ interface:
  				
  				<programlisting>
  					<literal>
  						import org.red5.server.api.service.IPendingService;
  						import org.red5.server.api.service.IPendingServiceCallback;
  						
  						class MyCallback implements IPendingServiceCallback {
  						
  							public void resultReceived(IPendingServiceCall call) { 
  								// Do something with "call.getResult()"
  							}
  						}
  					</literal>
  				</programlisting>
  				
  				The method call looks now like this:
  				
  				<programlisting>
  					<literal>
  						if (conn instanceof IServiceCapableConnection) {
  							IServiceCapableConnection sc = (IServiceCapableConnection) conn;
  							sc.invoke("the_method", new Object[]{"One", 1}, new MyCallback());
  						}
  					</literal>
  				</programlisting>
  				
  				Of course you can implement this interface in your application and pass a
  				reference to the application instance.
  			</para>
  		</sect1>
  		
  		<sect1 id="sharedobjects">
  			<title>SharedObjects</title>
  			<para>
  				The methods to access shared objects from an application are specified in the
  				interface ISharedObjectService_.
  				
  				When dealing with shared objects in serverside scripts, special care must be
  				taken about the scope they are created in.
  			</para>
  			
  			<para>
  				To create a new shared object when a room is created, you can override the
  				method `roomStart` in your application:
  				
  				<programlisting>
  					<literal>
  						import org.red5.server.adapter.ApplicationAdapter;
  						import org.red5.server.api.IScope;
  						import org.red5.server.api.so.ISharedObject;
  						
  						public class SampleApplication extends ApplicationAdapter {
  						
	  						public boolean roomStart(IScope room) {
		  						if (!super.roomStart(room))
		  						return false;
		  						
		  						createSharedObject(room, "sampleSO", true);
		  						ISharedObject so = getSharedObject(room, "sampleSO");
		  						
		  						// Now you could do something with the shared object...
		  						
		  						return true;		
	  						}
  						}
  					</literal>
  				</programlisting>
  				
  				Now everytime a first user connects to a room of a application, e.g. through
  				`rtmp://server/application/room1`, a shared object `sampleSO` is created by
  				the server.
  				
  				If a shared object should be created for connections to the main application,
  				e.g. `rtmp://server/application`, the same must be done in the method
  				`appStart`.
  				
  				For further informations about the possible methods a shared object provides
  				please refer to the api documentation of the interface ISharedObject_.
  			</para>
  		</sect1>
  		
  		<sect1 id="serverside-change-listeners">
  			<title>Serverside change listeners</title>
  			
  			<para>
  				To get notified about changes of the shared object similar to `onSync` in
  				FCS / FMS, a listener must implement the interface ISharedObjectListener_:
  				
  				<programlisting>
  					<literal>
  						<![CDATA[
  						import org.red5.server.api.so.ISharedObject;
  						import org.red5.server.api.so.ISharedObjectListener;
  						
  						public class SampleSharedObjectListener
  							implements ISharedObjectListener {
  						
  							public void onSharedObjectUpdate(ISharedObject so,
  								String key, Object value) {
  								// The attribute <key> of the shared object <so>
  								// was changed to <value>.
  							}
  								
  							public void onSharedObjectDelete(ISharedObject so, String key) {
  								// The attribute <key> of the shared object <so> was deleted.
  							}
  									
  							public void onSharedObjectSend(ISharedObject so,
  								String method, List params) {
  								// The handler <method> of the shared object <so> was called
  								// with the parameters <params>.
  							}
  											
  							// Other methods as described in the interface...
  						}
  						]]>
  											
  					</literal>
  				</programlisting>
  				
  				Additionally, the listener must get registered at the shared object:
  				
  				<programlisting>
  					<literal>
  						ISharedObject so = getSharedObject(scope, "sampleSO");
  						so.addSharedObjectListener(new SampleSharedObjectListener());
  					</literal>
  				</programlisting>
  			</para>
  		</sect1>
  		
  		<sect1 id="changing-from-application-code">
  			<title>Changing from application code</title>
  			
  			<para>
  				A shared object can be changed by the server as well:
  				
  				<programlisting>
  					<literal>
  						ISharedObject so = getSharedObject(scope, "sampleSO");
  						so.setAttribute("fullname", "Sample user");
  					</literal>
  				</programlisting>
  				
  				Here all subscribed clients as well as the registered handlers are notified
  				about the new / changed attribute.
  				
  				If multiple actions on a shared object should be combined in one update
  				event to the subscribed clients, the methods `beginUpdate` and `endUpdate`
  				must be used:
  				
  				<programlisting>
  					<literal>
  						ISharedObject so = getSharedObject(scope, "sampleSO");
  						so.beginUpdate();
  						so.setAttribute("One", "1");
  						so.setAttribute("Two", "2");
  						so.removeAttribute("Three");
  						so.endUpdate();
  					</literal>
  				</programlisting>
  				
  				The serverside listeners will receive their update notifications through
  				separate method calls as without the `beginUpdate` and `endUpdate`.
  			</para>
  		</sect1>
  		
  		<sect1 id="sharedobject-event-handlers">
  			<title>SharedObject event handlers</title>
  			
  			<para>
  				<![CDATA[
  					Calls to shared object handlers through `remote_so.send(<handler>, <args>)`
  					from a Flash client or the corresponding serverside call can be mapped to
  					methods in Red5.  Therefore a handler must get registered through a method
  					of the ISharedObjectHandlerProvider_ interface similar to the application
  					handlers:
  				]]>
  				
  				<programlisting>
  					<literal>
  						package com.fancycode.red5;
  						
  						class MySharedObjectHandler 
  						{
  							public void myMethod(String arg1) {
  								// Now do something
  							}
  						}
  						
  						...
  						ISharedObject so = getSharedObject(scope, "sampleSO");
  						so.registerServiceHandler(new MySharedObjectHandler());
  					</literal>
  				</programlisting>
  				
  				Handlers with a given name can be registered as well:
  				
  				<programlisting>
  					<literal>
  						ISharedObject so = getSharedObject(scope, "sampleSO");
  						so.registerServiceHandler("one.two", new MySharedObjectHandler());
  					</literal>
  				</programlisting>
  				
  				Here, the method could be called through `one.two.myMethod`.
  				
  				<![CDATA[
  				Another way to define event handlers for SharedObjects is to add them to the
  				`red5-web.xml` similar to the file-based application handlers.  The beans
  				must have a name of `<SharedObjectName>.<DottedServiceName>.soservice`, so
  					the above example could also be defined with:
  				]]>
  				
  				
  				<programlisting>
  					<literal>
  						<![CDATA[
  						<bean id="sampleSO.one.two.soservice" 
  							class="com.fancycode.red5.MySharedObjectHandler" 
  							singleton="true" />
  						]]>
  					</literal>
  				</programlisting>
  				
  					
  			</para>
  		</sect1>
  		
  		<sect1 id="persistence">
  			<title>Persistence</title>
  			
  			<para>
  				Persistence is used so properties of objects can be used even after the server
  				has been restarted.  In FCS / FMS usually local shared objects on the
  				serverside are used for this.
  				
  				Red5 allows arbitrary objects to be persistent, all they need to do is
  				implement the interface IPersistable_.  Basically these objects have a `type`,
  				a `path`, a `name` (all strings) and know how to serialize and deserialize
  				themselves.
  				
  				Here is a sample of serialization and deserialization:
  				
  				<programlisting>
  					<literal>
  						import java.io.IOException;
  						import org.red5.io.object.Input;
  						import org.red5.io.object.Output;
  						import org.red5.server.api.persistence.IPersistable;
  						
  						class MyPersistentObject implements IPersistable {
  						
	  						// Attribute that will be made persistent
	  						private String data = "My persistent value";
	  						
	  						void serialize(Output output) throws IOException {
	  							// Save the objects's data.
	  							output.writeString(data);
	  						}
	  						
	  						void deserialize(Input input) throws IOException {
	  							// Load the object's data.
	  							data = input.readString();
	  						}
	  						
	  						// Other methods as described in the interface...
  						}
  					</literal>
  				</programlisting>
  				
  				To save or load this object, the following code can be used:
  				
  				<programlisting>
  					<literal>
  						import org.red5.server.adapter.ApplicationAdapter;
  						import org.red5.server.api.IScope;
  						import org.red5.server.api.Red5;
  						import org.red5.server.api.persistence.IPersistenceStore;
  						
  						class MyApplication extends ApplicationAdapter {
  						
	  						private void saveObject(MyPersistentObject object) {
		  						// Get current scope.
		  						IScope scope = Red5.getConnectionLocal().getScope();
		  						// Save object in current scope.
		  						scope.getStore().save(object);
	  						}
	  						
	  						private void loadObject(MyPersistentObject object) {
		  						// Get current scope.
		  						IScope scope = Red5.getConnectionLocal().getScope();
		  						// Load object from current scope.
		  						scope.getStore().load(object);
	  						}
  						}
  					</literal>
  				</programlisting>
  				
  				If no custom objects are required for an application, but data must be stored
  				for future reuse, it can be added to the IScope_ through the interface
  				IAttributeStore_.  In scopes, all attributes that don't start with
  				`IPersistable.TRANSIENT_PREFIX` are persistent.
  				
  				The backend that is used to store objects is configurable.  By default
  				persistence in memory and in the filesystem is available.
  				
  				<![CDATA[
  				When using filesystem persistence for every object a file is created in
  				"webapps/<app>/persistence/<type>/<path>/<name>.red5", e.g. for a shared
  					object "theSO" in the connection to "rtmp://server/myApp/room1" a file at
  					"webapps/myApp/persistence/SharedObject/room1/theSO.red5" would be created.
  				]]>	
  			</para>
  		</sect1>
  		
  		<sect1 id="periodic-events">
  			<title>Periodic events</title>
  			
  			<para>
  				Applications that need to perform tasks regularly can use the `setInterval`
  				in FCS / FMS to schedule methods for periodic execution.
  				
  				Red5 provides a scheduling service (ISchedulingService_) that is implemented
  				by ApplicationAdapter_ like most other services.  The service can register
  				an object (which needs to implement the IScheduledJob_ interface) whose
  				`execute` method is called in a given interval.
  				
  				To register an object, code like this can be used:
  				
  				<programlisting>
  					<literal>
  						import org.red5.server.api.IScope;
  						import org.red5.server.api.IScheduledJob;
  						import org.red5.server.api.ISchedulingService;
  						import org.red5.server.adapter.ApplicationAdapter;
  						
  						class MyJob implements IScheduledJob {
  						
  							public void execute(ISchedulingService service) {
  								// Do something
  							}
  						}
  						
  						public class SampleApplication extends ApplicationAdapter {
  						
	  						public boolean roomStart(IScope room) {
		  						if (!super.roomStart(room))
		  						return false;
		  						
		  						// Schedule invokation of job every 10 seconds.
		  						String id = addScheduledJob(10000, new MyJob());
		  						room.setAttribute("MyJobId", id);
		  						return true;		
	  						}
  						}
  					</literal>
  				</programlisting>
  				
  				The id that is returned by `addScheduledJob` can be used later to stop
  				execution of the registered job:
  				
  				<programlisting>
  					<literal>
  						public void roomStop(IScope room) {
	  						String id = (String) room.getAttribute("MyJobId");
	  						removeScheduledJob(id);
	  						super.roomStop(room);
  						}
  					</literal>
  				</programlisting>
  			</para>
  		</sect1>
  		
  		<sect1 id="remoting">
  			<title>Remoting</title>
  			
  			<para>
  				Remoting can be used by non-rtmp clients to invoke methods in Red5.  Another
  				possibility is to call methods from Red5 to other servers that provide a
  				remoting service.
  			</para>
  		</sect1>
  		
  		<sect1 id="remoting-server">
  			<title>Remoting server</title>
  			
  			<para>
  				Services that should be available for clients need to be registered the same
  				way as additional application handlers are registered.  See above for details.
  			</para>
  			<para>
  				To enable remoting support for an application, the following section must be
  				added to the `WEB-INF/web.xml` file:
  				
  				<programlisting>
  					<literal>
  						<![CDATA[
  						<servlet>
  							<servlet-name>gateway</servlet-name>
  							<servlet-class>
  								org.red5.server.net.servlet.AMFGatewayServlet
  							</servlet-class>
  						</servlet>
  						
  						<servlet-mapping>
  							<servlet-name>gateway</servlet-name>
  							<url-pattern>/gateway/*</url-pattern>
  						</servlet-mapping>
  						]]>
  						
  					</literal>
  				</programlisting>
  				
  				<![CDATA[
  				The path specified in the `<url-pattern>` tag (here `gateway`) can be used
  					by the remoting client as connection url.  If this example would have been
  					specified for an application `myApp`, the URL would be:
  				]]>
  				
  				<programlisting>
  					<literal>
  						http://localhost:5080/myApp/gateway
  					</literal>
  				</programlisting>
  				
  				Methods invoked through this connection will be executed in the context of
  				the application scope.  If the methods should be executed in subscopes, the
  				path to the subscopes must be added to the URL like:
  				
  				<programlisting>
  					<literal>
  						http://localhost:5080/myApp/gateway/room1/room2
  					</literal>
  				</programlisting>
  			</para>
  		</sect1>
  		
  		<sect1 id="remoting-client">
  			<title>Remoting client</title>
  			
  			<para>
  				The class RemotingClient_ defines all methods that are required to call
  				methods through the remoting protocol.
  			</para>
  			<para>
  				The following code serves as example about how to use the remoting client:
  				
  				<programlisting>
  					<literal>
  						import org.red5.server.net.remoting.RemotingClient;
  						
  						String url = "http://server/path/to/service";
  						RemotingClient client = new RemotingClient(url);
  						Object[] args = new Object[]{"Hello world!"};
  						Object result = client.invokeMethod("service.remotingMethod", args);
  						// Now do something with the result
  						
  					</literal>
  				</programlisting>
  				
  				By default, a timeout of 30 seconds will be used per call, this can be
  				changed by passing a second parameter to the constructor defining the maximum
  				timeout in milliseconds.
  				
  				The remoting headers `AppendToGatewayUrl`, `ReplaceGatewayUrl` and
  				`RequestPersistentHeader` are handled automatically by the Red5 remoting
  				client.
  				
  				Some methods may take a rather long time on the called server to complete, so
  				it's better to perform the call asynchronously to avoid blocking a thread in
  				Red5.  Therefore an object that implements the interface IRemotingCallback_
  				must be passed as additional parameter:
  				
  				<programlisting>
  					<literal>
  						import org.red5.server.net.remoting.RemotingClient;
  						import org.red5.server.net.remoting.IRemotingCallback;
  						
  						public class CallbackHandler implements IRemotingCallback {
  						
	  						void errorReceived(RemotingClient client, String method,
	  							Object[] params, Throwable error) {
	  							// An error occurred while performing the remoting call.
	  						}
	  						
	  						void resultReceived(RemotingClient client, String method,
	  							Object[] params, Object result) {
	  							// The result was received from the server.
	  						}
  						}
  					</literal>
  				</programlisting>
  				
  				<programlisting>
  					<literal>
  						String url = "http://server/path/to/service";
  						RemotingClient client = new RemotingClient(url);
  						Object[] args = new Object[]{"Hello world!"};
  						IRemotingCallback callback = new CallbackHandler();
  						client.invokeMethod("service.remotingMethod", args, callback);
  					</literal>
  				</programlisting>
  			</para>
  		</sect1>
  		
  		<sect1 id="todo">
  			<title>Streams</title>
  			
  			<para>
  				TODO: How can streams be accessed from an application?
  			</para>
  		</sect1>
  		
  	</chapter>
  </part>
  
	<part id="configs">
		<title>Configuration files used by Red5</title>
		
		<partintro>
			<para>
				This document describes the configuration files used by Red5.
				
				Please note that this document is still *work in progress*, so some things
				may (and surely will) change until the final release of Red5!
			</para>
		</partintro>
		
	  	<chapter id="configuration-files-conf">
	  		<chapterinfo>
	  			<date>26 September 2006</date>
	  			<authorgroup>
	  				<author>
	  					<firstname>Joachim</firstname>
	  					<surname>Bauch</surname>
	  					<email>jojo@struktur.de</email>
	  				</author>
	  				<author>
	  					<firstname>Paul</firstname>
	  					<surname>Gregoire</surname>
	  					<email>mondain@gmail.com</email>
	  				</author>
	  			</authorgroup>
	  			
	  		</chapterinfo>
	  		
	  		<title>Directory "conf"</title> 
	  		<para>
	  			
	  		</para>
	  		
	  		<sect1 id="jetty-xml">
	  			<title>jetty.xml</title>
	  			<para>
	  				The settings of the HTTP server and servlet container are specified using
	  				this file.  It runs on all available interfaces on port 5080 by default.
	  				
	  				See the `Jetty homepage`__ for further information about the syntax of this
	  				file.
	  				
	  				<ulink url="http://jetty.mortbay.org/jetty6/">http://jetty.mortbay.org/jetty6/</ulink>
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="keystore">
	  			<title>keystore</title>
	  			<para>
	  				Contains a sample private key and certificate to be used for secure
	  				connections.
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="log4j-properties">
	  			<title>log4j.properties</title>
	  			<para>
	  				Controls the log levels and output handlers for the logging subsystem.
	  				
	  				Further information about log4j can be found on `the official homepage`.
	  				
	  				<ulink url="http://logging.apache.org/log4j/docs/">http://logging.apache.org/log4j/docs/</ulink>
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="realm-properties">
	  			<title>realm.properties (Jetty)</title>
	  			<para>
	  				This file defines users passwords and roles that can be used for protected
	  				areas.
	  				
	  				The format is:
	  				
	  				<programlisting>
	  					<literal>
	  						<![CDATA[
	  						<username>: <password>[,<rolename> ...]
	  						]]>
	  					</literal>
	  				</programlisting>
	  				
	  				Passwords may be clear text, obfuscated or checksummed.  The class 
	  				"org.mortbay.util.Password" should be used to generate obfuscated passwords
	  				or password checksums.
	  				
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="tomcat-properties">
	  			<title>tomcat-users.xml (Tomcat)</title>
	  			<para>
	  				This file defines users passwords and roles that can be used for protected
	  				areas.
	  				
	  				The format is:
	  				
	  				<programlisting>
	  					<literal>
	  						<![CDATA[
	  						<user name="<username>" password="<password>" roles="[,<rolename> ...]" />
	  						]]>
	  					</literal>
	  				</programlisting>
	  				
	  				Passwords may be clear text, obfuscated or checksummed. For information on different
	  				digest support or available realm implementations use the how-to:
	  				<ulink url="http://tomcat.apache.org/tomcat-5.5-doc/realm-howto.html">http://tomcat.apache.org/tomcat-5.5-doc/realm-howto.html</ulink>
	  				
	  				Further information about tomcat realms can be found on `the official homepage` 
	  				<ulink url="http://tomcat.apache.org/tomcat-5.5-doc/catalina/docs/api/org/apache/catalina/realm/package-summary.html">http://tomcat.apache.org/tomcat-5.5-doc/catalina/docs/api/org/apache/catalina/realm/package-summary.html</ulink>	  				
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="red5-globals">
	  			<title>red5.globals</title>
	  			<para>
	  				Specifies the path to the configuration file for the default global context
	  				to be used for Red5.
	  				
	  				By default this file is located in "/webapps/red5-default.xml".
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="red5-properties">
	  			<title>red5.properties</title>
	  			<para>
	  				File containing key / value pairs to configure the host and port of basic
	  				services like RTMP or remoting.
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="red5-xml">
	  			<title>red5.xml</title>
	  			<para>
	  				The main configuration file that wires together the context tree.  It takes
	  				care of loading "red5-common.xml" and "red5-core.xml" and sets up the rest of
	  				the server.  This is the first file to be loaded by Red5. 
	  				The J2EE container is selected in this configuration file by configuring one of the
	  				following bean elements.
	  				
	  				- Jetty
	  				
	  				<programlisting>
	  					<literal>
	  						<![CDATA[
	  						<bean id="jetty6.server" class="org.red5.server.JettyLoader" init-method="init" autowire="byType" />
	  						]]>
	  					</literal>
	  				</programlisting>
	  				
	  				- Tomcat
	  				
	  				<programlisting>
	  					<literal>
	  						<![CDATA[
	  						<bean id="tomcat.server" class="org.red5.server.TomcatLoader" init-method="init" destroy-method="shutdown" autowire="byType">
	  							... cut for brevity ...
	  						</bean>
	  						]]>
	  					</literal>
	  				</programlisting>
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="red5-common-xml">
	  			<title>red5-common.xml</title>
	  			<para>
	  				Classes that are shared between all child contexts are declared in this file.
	  				It contains information about the object serializers / deserializers, the
	  				codecs to be used for the network protocols as well as the available video
	  				codecs.
	  				
	  				The object (FLV) cache is configured / spring-wired in this file. Four implementations
	  				are currently available; The first one is our own creation (simple byte-buffers) and the others use
	  				WhirlyCache, or Ehcache. If no caching is desired then the NoCache implementation should be specified like so:
	  				
	  				<programlisting>
	  					<literal>
	  						<![CDATA[
	  						<bean id="object.cache" class="org.red5.server.cache.NoCacheImpl"/>
	  						]]>
	  					</literal>
	  				</programlisting>
	  				
	  				The other bean configurations are as follows (Only one may be used at a time):
	  				
	  				- Red5 homegrown simple example
	  				
	  				<programlisting>
	  					<literal>
	  						<![CDATA[
	  						 <bean id="object.cache" class="org.red5.server.cache.CacheImpl" init-method="init" autowire="byType"> 
        							 <property name="maxEntries"><value>5</value></property>
    							 </bean>
	  						]]>
	  					</literal>
	  				</programlisting>
	  				
	  				- EhCache http://ehcache.sourceforge.net/
	  				
	  				<programlisting>
	  					<literal>
	  						<![CDATA[
	  						<bean id="object.cache" class="org.red5.server.cache.EhCacheImpl" init-method="init">
	  							<property name="diskStore" value="java.io.tmpdir" />
	  							<property name="memoryStoreEvictionPolicy" value="LFU" />
	  							<property name="cacheManagerEventListener"><null/></property>		
	  							<property name="cacheConfigs">
	  								<list>
	  									<bean class="net.sf.ehcache.config.CacheConfiguration">
	  										<property name="name" value="flv.cache" />
	  										<property name="maxElementsInMemory" value="5" />
	  										<property name="eternal" value="false" />
	  										<property name="timeToIdleSeconds" value="0" />
	  										<property name="timeToLiveSeconds" value="0" />
	  										<property name="overflowToDisk" value="false" />
	  										<property name="diskPersistent" value="false" />
	  									</bean>			
	  								</list>
	  							</property>
	  						</bean> 
	  						]]>
	  					</literal>
	  				</programlisting>
	  				
	  				- Whirlycache https://whirlycache.dev.java.net/
	  				
	  				<programlisting>
	  					<literal>
	  						<![CDATA[
	  						<bean id="object.cache" class="org.red5.server.cache.WhirlyCacheImpl" init-method="init" autowire="byType">
	  							<property name="maxEntries" value="5" />
	  							<property name="cacheConfig">
	  								<bean class="com.whirlycott.cache.CacheConfiguration">
	  									<property name="name" value="flv.cache" />
	  									<property name="maxSize" value="5" />
	  									<!-- This policy removes cached items, biased towards least frequently used (LFU) Items -->
	  									<property name="policy"><value>com.whirlycott.cache.policy.LFUMaintenancePolicy</value></property>
	  									<!-- This policy removes cached items, biased towards least recently used (LRU) Items -->
	  									<!-- property name="policy"><value>com.whirlycott.cache.policy.LRUMaintenancePolicy</value></property -->
	  									<!-- This policy removes cache items in the order in which they were added -->
	  									<!-- property name="policy"><value>com.whirlycott.cache.policy.FIFOMaintenancePolicy</value></property -->
	  									<!-- A predicate for filtering Collections of Items based on their expiration time -->
	  									<!-- property name="policy"><value>com.whirlycott.cache.policy.ExpirationTimePredicate</value></property -->		
	  									<!-- property name="backend"><value>com.whirlycott.cache.impl.ConcurrentHashMapImpl</value></property -->
	  									<property name="backend"><value>com.whirlycott.cache.impl.FastHashMapImpl</value></property>
	  								</bean>
	  							</property>
	  						</bean> 
	  						]]>
	  					</literal>
	  				</programlisting>
	  				
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="red5-core-xml">
	  			<title>red5-core.xml</title>
	  			<para>
	  				All available network services are specified here. By default these are
	  				RTMP and RTMPT.  The actual settings for the RTMPT server can be found in
	  				"red5-rtmpt.xml" when using Jetty as the J2EE container.
	  				
	  				The RTMPT handler is selected by configuring one of the following bean elements.
	  				
	  				- Jetty
	  				
	  				<programlisting>
	  					<literal>
	  						<![CDATA[
	  						<bean id="rtmpt.server" class="org.red5.server.net.rtmpt.RTMPTLoader" init-method="init" autowire="byType" />
	  						]]>
	  					</literal>
	  				</programlisting>
	  				
	  				- Tomcat
	  				
	  				<programlisting>
	  					<literal>
	  						<![CDATA[
	  						<bean id="rtmpt.server" class="org.red5.server.net.rtmpt.TomcatRTMPTLoader" init-method="init" autowire="byType">
	  							... cut for brevity ...
	  						</bean>
	  						]]>
	  					</literal>
	  				</programlisting>
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="red5-rtmpt-xml">
	  			<title>red5-rtmpt.xml</title>
	  			<para>
	  				Sets up the mapping between the RTMPT URLs and the servlets to use as well
	  				as specify the host and port to run on.  By default the RTMPT server runs on
	  				all available interfaces on port 8088.
	  				
	  				See the `Jetty homepage`  for further information about the syntax of this
	  				file.
	  				
	  				http://jetty.mortbay.org/jetty6/
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="web-xml">
	  			<title>web.xml (Tomcat)</title>
	  			<para>
	  				Default web.xml file used by Tomcat.  The settings from this file are applied to a web
	  				application before it's own WEB_INF/web.xml file.
	  				
	  				Further info about the configuration of this file may be found here: 
	  				<ulink url="http://tomcat.apache.org/tomcat-5.5-doc/jasper-howto.html#Configuration">http://tomcat.apache.org/tomcat-5.5-doc/jasper-howto.html#Configuration</ulink>
	  			</para>
	  		</sect1>
	  		
	  		<sect1 id="web-default-xml">
	  			<title>web-default.xml (Jetty)</title>
	  			<para>
	  				Default web.xml file used by Jetty.  The settings from this file are applied to a web
	  				application before it's own WEB_INF/web.xml file.
	  			</para>
	  		</sect1>
	  	</chapter>
		
		<chapter id="configuration-files-webapp">
			<chapterinfo>
				<date>26 September 2006</date>
				<authorgroup>
					<author>
						<firstname>Joachim</firstname>
						<surname>Bauch</surname>
						<email>jojo@struktur.de</email>
					</author>
					<author>
						<firstname>Paul</firstname>
						<surname>Gregoire</surname>
						<email>mondain@gmail.com</email>
					</author>
				</authorgroup>
				
			</chapterinfo>
			
			<title>Webapp config directory</title> 
			<para>
				
			</para>
			
			<sect1 id="red5-web-xml">
				<title>red5-web.xml</title>
				<para>
					Red5 applications are configured within this file. The scripting implementations or Java
					applications are configured via Spring bean elements.
					
					- Java application
					
					<programlisting>
						<literal>
							<![CDATA[
							<bean id="web.handler" class="org.red5.server.webapp.oflaDemo.Application" singleton="true" />
							]]>
						</literal>
					</programlisting>
					
					- Javascript / Rhino application
					
					<programlisting>
						<literal>
							<![CDATA[
							<bean id="web.handler" class="org.red5.server.script.rhino.RhinoScriptFactory">
								<constructor-arg index="0" value="classpath:applications/main.js"/>
								<!-- Implemented interfaces -->
								<constructor-arg index="1">
									<list>
										<value>org.red5.server.api.IScopeHandler</value>
										<value>org.red5.server.adapter.IApplication</value>
									</list>
								</constructor-arg>
								<!-- Extended class -->
								<constructor-arg index="2">
									<value>org.red5.server.adapter.ApplicationAdapter</value>
								</constructor-arg>
							</bean>
							]]>
						</literal>
					</programlisting>
					
					- Ruby application 
					
					<programlisting>
						<literal>
							<![CDATA[
							<bean id="web.handler" class="org.red5.server.script.jruby.JRubyScriptFactory">
								<constructor-arg index="0" value="classpath:applications/main.rb"/>
								<constructor-arg index="1">
									<list>
										<value>org.red5.server.api.IScopeHandler</value>
										<value>org.red5.server.adapter.IApplication</value>
									</list>
								</constructor-arg>
							</bean>
							]]>
						</literal>
					</programlisting>
				</para>
			</sect1>
			
		</chapter>
	</part>
	<part id="red5-building">
		<title>Building Red5</title>
		
		<partintro>
			<para>Part intro</para>
		</partintro>
		
		<chapter id="building-ant">
			<chapterinfo>
				<date>10/24/05</date>
				<authorgroup>
					<author>
						<firstname>Dominick </firstname>
						<surname>Accattato</surname>
						<email>(daccattato at gmail dot com)</email>
					</author>
				</authorgroup>
			</chapterinfo>
			
			<title>Building with Ant</title>
			
			<para>
				TODO
			</para>
		</chapter>
		
		<chapter id="building-debian">
			<chapterinfo>
				<date>10/24/05</date>
				<authorgroup>
					<author>
						<firstname>Dominick </firstname>
						<surname>Accattato</surname>
						<email>(daccattato at gmail dot com)</email>
					</author>
				</authorgroup>
			</chapterinfo>
			
			<title>Building  a Red5 Debian package</title>
			
			<procedure>
				<step>
					<para>
						Install the debian packages "dpkg-dev", "debhelper", "dh-make",
						"devscripts" and "fakeroot".
					</para>
				</step>
				<step>
					<para>
						Checkout the debian build scripts to a folder "debian" inside the Red5
						root from http://svn1.cvsdude.com/osflash/red5/debian/trunk
					</para>
				</step>
				<step>
					<para>
						Update "debian/changelog" and add an entry for the new version you are
						building. Note that the syntax must match the previous entries!
					</para>
				</step>
				<step>
					<para>
						Update the filename in "debian/files" to match the version you are
						building.
					</para>
				</step>
				<step>
					<para>
						Make sure you run from a clean Red5 checkout of the tag to build!!!
					</para>
				</step>
				<step>
					<para>
						From the red5 root run "dpkg-buildpackage -uc -b -rfakeroot"
					</para>
				</step>
				<step>
					<para>
						If all goes well, you should have a debian package one folder below the
						Red5 root.
					</para>
				</step>
			</procedure>
		</chapter>
		
		<chapter id="release-red5">
			<chapterinfo>
				<date>10/24/05</date>
				<authorgroup>
					<author>
						<firstname>Dominick </firstname>
						<surname>Accattato</surname>
						<email>(daccattato at gmail dot com)</email>
					</author>
				</authorgroup>
			</chapterinfo>
			
			<title>Release</title>
			
			<para>
				This document describes the steps necessary to create a new release of Red5:
			</para>
			
			<procedure>
				<step>
					<para>
						Make sure everything has been committed to the trunk or correct branch.
					</para>
				</step>
				<step>
					<para>
						Update the file doc/changelog.txt with informations about the new release.
					</para>
				</step>
				<step>
					<para>
						Create tags of the modules that are linked into the main code tree:
					</para>
					<para>
						- documentation at http://svn1.cvsdude.com/osflash/red5/doc/tags
					</para>
					<para>
						Tags for versions should always be the version string with dots replaced
						by underscores, e.g. version "1.2.3" becomes tag "1_2_3".
					</para>
					<para>
						If you would tag the documentation folder for version "1.2.3", you would
						use the url http://svn1.cvsdude.com/osflash/red5/doc/tags/1_2_3
					</para>
				</step>
				<step>
					<para>
						Tag the server code according to the naming scheme from above at
						http://svn1.cvsdude.com/osflash/red5/java/server/tags
					</para>
				</step>
				<step>
					<para>
						Update the svn:externals in the newly created server code tag to point
						to the tagged modules from step 3.
					</para>
				</step>
				<step>
					<para>
						You're done.
					</para>
				</step>
			</procedure>
		</chapter>
	</part>
	
	<part id="red5-applications">
		<title>Applications</title>
		
		<partintro>
			<para>
				This document describes how new applications can be created in Red5.
				It applies to the new API introduced by Red5 0.4.
			</para>
		</partintro>
		
		<chapter id="red5-new-application">
			<chapterinfo>
				<date>3 May 2007</date>
				<authorgroup>
					<author>
						<firstname>Paul</firstname>
						<surname>Gregoire</surname>
						<email></email>
					</author>
				</authorgroup>
			</chapterinfo>
			
			<title>Create new applications in Red5</title>
			
			<para>
				This document describes how new applications can be created in Red5.
				It applies to the new API introduced by Red5 0.4.
			</para>
			
			<sect1 id="application-directory">
				<title>The application directory</title>
				<para>
					Red5 stores all application definitions as folders inside the "webapps"
					directory beneath the root of Red5.  So the first thing you will have to
					do in order to create a new application, is to create a new subfolder
					in "webapps".  By convention this folder should get the same name the
					application will be reached later.
				</para>
				<para>
					Inside your new application, you will need a folder "WEB-INF" containing
					configuration files about the classes to use.  You can use the templates
					provided by Red5 in the folder "doc/templates/myapp".
				</para>
				<para>
					During the start of Red5, all folders inside "webapps" are searched for
					a directory "WEB-INF" containing the configuration files.
				</para>
			</sect1>
			
			<sect1 id="application-configuration">
				<title>Configuration</title>
				<para>
					The main configuration file that is loaded is "web.xml".  It contains the
					following parameters:
				</para>
				
				<sect2 id="globalScope">
					<title>globalScope</title>
					<para>
						The name of the global scope, this should be left at the default:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
							<context-param>
								<param-name>globalScope</param-name>
								<param-value>default</param-value>
							</context-param>
							]]>
						</literal>
					</programlisting>
				</sect2>
				
				<sect2 id="contextConfigLocation">
					<title>contextConfigLocation</title>
					<para>
						Specifies the name(s) of handler configuration files for this application.
						The handler configuration files reference the classes that are used to notify
						the application about joining / leaving clients and that provide the methods
						a client can call.
					</para>
					
					<para>
						Additionally, the handler configuration files specify the scope hierarchy for
						these classes.
					</para>
					
					<para>
						The path name given here can contain wildcards to load multiple files:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
     <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/red5-*.xml</param-value>
    </context-param>
							]]>
						</literal>
					</programlisting>
				</sect2>
				
				<sect2 id="locatorFactorySelector">
					<title>locatorFactorySelector</title>
					<para>
						References the configuration file of the root application context which
						usually is "red5.xml":
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   <context-param>
        <param-name>locatorFactorySelector</param-name>
        <param-value>red5.xml</param-value>
    </context-param>
							]]>
						</literal>
					</programlisting>
				</sect2>
				
				<sect2 id="parentContextKey">
					<title>parentContextKey</title>
					<para>
						Name of the parent context, this usually is "default.context":
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   <context-param>
        <param-name>parentContextKey</param-name>
        <param-value>default.context</param-value>
    </context-param>
							]]>
						</literal>
					</programlisting>
				</sect2>
				
				<sect2 id="log4jConfigLocation">
					<title>log4jConfigLocation</title>
					<para>
						Path to the configuration file for the logging subsystem:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/log4j.properties</param-value>
    </context-param>
							]]>
						</literal>
					</programlisting>
				</sect2>
				
				<sect2 id="webAppRootKey">
					<title>webAppRootKey</title>
					<para>
						Unique name for this application, should be the public name:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>/myapp</param-value>
    </context-param>
							]]>
						</literal>
					</programlisting>
				</sect2>
				
			</sect1>
			
			<sect1 id="handler-configuration">
				<title>Handler configuration</title>
				<para>
					Every handler configuration file must contain at least three beans:
				</para>
				
				<sect2 id="context">
					<title>Context</title>
					<para>
						The context bean has the reserved name `web.context` and is used to map paths
						to scopes, lookup services and handlers.  The default class for this is
						`org.red5.server.Context`.
					</para>
					
					<para>
						By default this bean is specified as:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   <bean id="web.context" class="org.red5.server.Context" 
          autowire="byType" />
							]]>
						</literal>
					</programlisting>
					
					<para>
						Every application can only have one context.  However this context can be
						shared across multiple scopes.
					</para>
				</sect2>
				
				<sect2 id="scopes">
					<title>Scopes</title>
					<para>
						Every application needs at least one scope that links the handler to the
						context and the server.  The scopes can be used to build a tree where clients
						can connect to every node and share objects inside this scope (like shared
						objects or live streams).  You can see the scopes as rooms or instances.
					</para>
					
					<para>
						The default scope usually has the name `web.scope`, but the name can be chosen
						arbitrarily.
					</para>
					
					<para>
						The bean has the following properties:
					</para>
					
					<para>
						`server` - This references the global server `red5.server`.
					</para>
					<para>
						`parent` - References the parent for this scope and usually is `global.scope`.
					</para>
					<para>
						`context` - The server context for this scope, use the `web.context` from above.
					</para>
					<para>
						`handler` - The handler for this scope (see below).
					</para>
					<para>
						`contextPath` - The path to use when connecting to this scope.
					</para>
					<para>
						`virtualHosts` - A comma separated list of hostnames or ip addresses this scope runs at.
					</para>
					
					<para>
						A sample definition looks like this:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   <bean id="web.scope" class="org.red5.server.WebScope"
          init-method="register">
        <property name="server" ref="red5.server" />
        <property name="parent" ref="global.scope" />
        <property name="context" ref="web.context" />
        <property name="handler" ref="web.handler" />
        <property name="contextPath" value="/myapp" />
        <property name="virtualHosts" value="localhost, 127.0.0.1" />
    </bean>
							]]>
						</literal>
					</programlisting>
					
					<para>
						You can move the values for `contextPath` and `virtualHosts` to a separate
						properties file and use parameters.  In that case you need another bean:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
    <bean id="placeholderConfig"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="/WEB-INF/red5-web.properties" />
    </bean>
							]]>
						</literal>
					</programlisting>
					
					<para>
						Assuming a `red5-web.properties` containing the following data:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
    webapp.contextPath=/myapp
    webapp.virtualHosts=localhost, 127.0.0.1
							]]>
						</literal>
					</programlisting>
					
					<para>
						the properties of the scope can now be changed to:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
    <property name="contextPath" value="${webapp.contextPath}" />
    <property name="virtualHosts" value="${webapp.virtualHosts}" />
							]]>
						</literal>
					</programlisting>
					
					<para>
						The `contextPath` specified in the configuration can be seen as "root" path
						of the scope.  You can add additional elements after the configured path when
						connecting to dynamically create extra scopes.
					</para>
					
					<para>
						These extra scopes all use the same handler but have their own properties,
						shared objects and live streams.
					</para>
				</sect2>
				
				<sect2 id="handlers">
					<title>Handlers</title>
					<para>
						Every context needs a handler that implements the methods called when a client
						connects to the scope, leaves it and that contains additional methods that can
						be called by the client.  The interface these handlers need to implement is
						specified by `org.red5.server.api.IScopeHandler`, however you can implement
						other interfaces if you want to control access to shared objects or streams.
					</para>
					
					<para>
						A sample implementation that can be used as base class can be found at
						`org.red5.server.adapter.ApplicationAdapter`.  Please refer to the javadoc
						documentation for further details.
					</para>
					
					<para>
						The bean for a scope handler is configured by:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
  <bean id="web.handler" 
          class="the.path.to.my.Application" 
          singleton="true" />
							]]>
						</literal>
					</programlisting>
					
					<para>
						The `id` attribute is referenced by the scope definition above.
					</para>
					
					<para>
						If you don't need any special server-side logic, you can use the default
						application handler provided by Red5:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
  <bean id="web.handler" 
          class="org.red5.server.adapter.ApplicationAdapter" 
          singleton="true" />
							]]>
						</literal>
					</programlisting>
				</sect2>
				
				<sect2 id="sample-handler">
					<title>Sample handler</title>
					<para>
						A sample handler can be implemented in a few lines of code:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   package the.path.to.my;
    
    import org.red5.server.adapter.ApplicationAdapter;
    
    public class Application extends ApplicationAdapter {
        
        public Double add(Double a, Double b){
            return a + b;
        }
    
    }
							]]>
						</literal>
					</programlisting>
					
					<para>
						Assuming the sample configuration above, you can call this method using the
						following ActionScript snippet:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
    nc = new NetConnection();
    nc.connect("rtmp://localhost/myapp");
    nc.onResult = function(obj) {
        trace("The result is " + obj);
    }
    nc.call("add", nc, 1, 2);
							]]>
						</literal>
					</programlisting>
					
					<para>
						This should give you the output:
					</para>
					
					<blockquote>
						<para>The result is 3</para>
					</blockquote>
				</sect2>
				
			</sect1>
			
		</chapter>
		
		
		<chapter id="red5-new-application-war">
			<chapterinfo>
				<date>2007-05-03</date>
				<authorgroup>
					<author>
						<firstname>Paul</firstname>
						<surname>Gregoire</surname>
						<email>mondain@gmail.com</email>
					</author>
				</authorgroup>
			</chapterinfo>
			
			<title>Setup applications in Red5 WAR</title>
			
			<para>
				This document describes how applications can be configured in Red5 when using the WAR
				implementation. In this version of Red5 the J2EE container is not contained within Red5 
				and therefore is configured differently. This document assumes that the application WAR 
				has already been expanded.
			</para>
			
			<sect1 id="application-directory-war">
				<title>The application directory</title>
				<para>
					An application war is normally expanded into a directory based upon the name of the war file, eg. red5.war
					expands into tomcat/webapps/red5 on a Tomcat server. In a standard Red5 installation, all the applications 
					are stored within their own directory under the webapps directory; the difference here is that they are all
					located in the same directory.
				</para>
			</sect1>
			
			<sect1 id="application-configuration-war">
				<title>Configuration</title>
				<para>
					The WAR version stores all application definitions as Spring configuration files suffixed with the
					string "-context.xml"; If your application was called ofla then its configuration file would be
					named "ofla-context.xml". The context files are loaded automatically upon server startup.
				</para>
				<para>
					The main configuration file that is loaded is "web.xml".  It contains the following parameters:
				</para>
				
				<sect2 id="globalScope-war">
					<title>globalScope</title>
					<para>
						The name of the global scope, this should be left at the default:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   <context-param>
        <param-name>globalScope</param-name>
        <param-value>default</param-value>
    </context-param>
							]]>
						</literal>
					</programlisting>
				</sect2>
				
				<sect2 id="contextConfigLocation-war">
					<title>contextConfigLocation</title>
					<para>
						Specifies the name(s) of handler configuration files for this application.
						The handler configuration files reference the classes that are used to notify
						the application about joining / leaving clients and that provide the methods
						a client can call.
					</para>
					
					<para>
						Additionally, the handler configuration files specify the scope hierarchy for
						these classes.
					</para>
					
					<para>
						The path name given here can contain wildcards to load multiple files:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
        <context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/applicationContext.xml, /WEB-INF/red5-common.xml, /WEB-INF/red5-core.xml, /WEB-INF/*-context.xml</param-value>
	</context-param>
							]]>
						</literal>
					</programlisting>
				</sect2>
				
				<sect2 id="listener-war">
					<title>listener (start-up / shutdown)</title>
					<para>
						References the context listener servlet of the application, this technically takes the place of
						the Standalone.class in a standard Red5 server.
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
       <listener>
		<!-- Impersonates a org.springframework.web.context.ContextLoaderListener -->
		<listener-class>org.red5.server.MainServlet</listener-class>
	</listener>
							]]>
						</literal>
					</programlisting>
				</sect2>
				
				<sect2 id="parentContextKey-war">
					<title>parentContextKey</title>
					<para>
						Name of the parent context, this usually is "default.context":
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   <context-param>
        <param-name>parentContextKey</param-name>
        <param-value>default.context</param-value>
    </context-param>
							]]>
						</literal>
					</programlisting>
				</sect2>
				
				<sect2 id="log4jConfigLocation-war">
					<title>log4jConfigLocation</title>
					<para>
						Path to the configuration file for the logging subsystem:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/log4j.properties</param-value>
    </context-param>
							]]>
						</literal>
					</programlisting>
				</sect2>
			</sect1>
			
			<sect1 id="handler-configuration-war">
				<title>Handler configuration</title>
				<para>
					Every handler configuration file must contain at least three beans:
				</para>
				
				<sect2 id="context-war">
					<title>Context</title>
					<para>
						The context bean has the reserved name `web.context` and is used to map paths
						to scopes, lookup services and handlers.  The default class for this is
						`org.red5.server.Context`.
					</para>
					
					<para>
						By default this bean is specified as:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   <bean id="web.context" class="org.red5.server.Context" 
          autowire="byType" />
							]]>
						</literal>
					</programlisting>
					
					<para>
						<![CDATA[
						Every application can only have one context and they should follow this naming convention 
						'<application name>.context' so that they will not conflict with one another. 
						Application contexts can be shared across multiple scopes.
						]]>
					</para>
				</sect2>
				
				<sect2 id="scopes-war">
					<title>Scopes</title>
					<para>
						Every application needs at least one scope that links the handler to the
						context and the server.  The scopes can be used to build a tree where clients
						can connect to every node and share objects inside this scope (like shared
						objects or live streams).  You can see the scopes as rooms or instances.
					</para>
					
					<para>
						<![CDATA[
						The default scope usually has the name 'web.scope' and they should follow this naming 
						convention '<application name>.scope' so that they will not conflict with one another.
						]]>
					</para>
					
					<para>
						The bean has the following properties:
					</para>
					
					<para>
						`server` - This references the global server `red5.server`.
					</para>
					<para>
						`parent` - References the parent for this scope and usually is `global.scope`.
					</para>
					<para>
						`context` - The server context for this scope, use the `web.context` from above.
					</para>
					<para>
						`handler` - The handler for this scope (see below).
					</para>
					<para>
						`contextPath` - The path to use when connecting to this scope.
					</para>
					<para>
						`virtualHosts` - A comma separated list of hostnames or ip addresses this scope runs at.
					</para>
					
					<para>
						In this version we do not control
						the host names, this is accomplished by the server.
					</para>
					
					<para>
						A sample definition looks like this:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
    <bean id="ofla.scope" class="org.red5.server.WebScope" init-method="register">
        <property name="server" ref="red5.server" />
        <property name="parent" ref="global.scope" />
        <property name="context" ref="ofla.context" />
        <property name="handler" ref="ofla.handler" />
        <property name="contextPath" value="/oflaDemo" />
        <property name="virtualHosts" value="localhost, 127.0.0.1" />
    </bean>
							]]>
						</literal>
					</programlisting>
					
					<para>
						The 'contextPath' specified in the configuration can be seen as "root" path of the scope.  
						You can add additional elements after the configured path when connecting to dynamically 
						create extra scopes.
					</para>
					<para>
						These extra scopes all use the same handler but have their own properties, shared objects and
						live streams.
					</para>
				</sect2>
				
				<sect2 id="handlers-war">
					<title>Handlers</title>
					<para>
						Every context needs a handler that implements the methods called when a client
						connects to the scope, leaves it and that contains additional methods that can
						be called by the client.  The interface these handlers need to implement is
						specified by `org.red5.server.api.IScopeHandler`, however you can implement
						other interfaces if you want to control access to shared objects or streams.
					</para>
					
					<para>
						A sample implementation that can be used as base class can be found at
						`org.red5.server.adapter.ApplicationAdapter`.  Please refer to the javadoc
						documentation for further details.
					</para>
					
					<para>
						The bean for a scope handler is configured by:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
  <bean id="ofla.handler" class="the.path.to.my.Application" singleton="true" />
							]]>
						</literal>
					</programlisting>
					
					<para>
						The `id` attribute is referenced by the scope definition above.
					</para>
					
					<para>
						If you don't need any special server-side logic, you can use the default
						application handler provided by Red5:
					</para>
					
					<programlisting>
						<literal>
							<![CDATA[
   <bean id="web.handler" class="org.red5.server.adapter.ApplicationAdapter" singleton="true" />
							]]>
						</literal>
					</programlisting>
				</sect2>
			</sect1>
		</chapter>
		
	</part>
		
	
	<part id="red5-management">
		<title>Management</title>
		
		<partintro>
			<para>Part intro</para>
		</partintro>
		
		<chapter id="red5-jmx">
			<chapterinfo>
				<date>3 May 2007</date>
				<authorgroup>
					<author>
						<firstname>Paul</firstname>
						<surname>Gregoire</surname>
						<email></email>
					</author>
				</authorgroup>
			</chapterinfo>
			
			<title>Java Management Extensions (JMX) and Red5</title>
			
			<para>
				TODO
			</para>
			
			<sect1 id="jmx-classes">
				<title>JMX classes</title>
				<para>
					Red5's implementation consists of the following classes and various other MBeans:
					
					org.red5.server.jmx.JMXFactory - Provides access to the platform MBeanServer as well as registration, unregistration, and creation of new MBean instances. Creation and registration is performed using StandardMBean wrappers.
					
					org.red5.server.jmx.JMXAgent - Provides the HTML adapter and registration of MBeans.
					
					org.red5.server.jmx.JMXUtil - Helper methods for working with ObjectName or MBean instances.
				</para>
			</sect1>
			
			<sect1 id="spring-config">
				<title>Spring configuration</title>
				<para>
					The Spring configuration for the JMX implementation allows you to configure the "domain" 
					for MBean registration and listener port for the HTML adaptor. 
					The default entries are shown below.
					
					<programlisting>
						<literal>
							<![CDATA[
							<!-- JMX server -->
							<bean id="jmxFactory" class="org.red5.server.jmx.JMXFactory">
								<property name="domain" value="org.red5.server"/>
							</bean>
							<bean id="jmxAgent" class="org.red5.server.jmx.JMXAgent" init-method="init">
								<!-- The RMI adapter allows remote connections to the MBeanServer -->
								<property name="enableRmiAdapter" value="true" />
								<property name="rmiAdapterPort" value="9999"/>
								<!-- The HTML adapter allows connections to the MBeanServer via a web browser -->
								<property name="enableHtmlAdapter" value="false" />
								<property name="htmlAdapterPort" value="8082"/>
							</bean>
							]]>
						</literal>
					</programlisting>
					
					The HTML adapter is disabled by default, but it allows easy management of MBeans from a web browser.
					The RMI adapter may only be used if an RMI registry is running. To start a registry simply execute this at the command prompt:
					
					- windows
					rmiregistry 9999
					
					- unix
					rmiregistry 9999 &amp;
					
					The "9999" is the port and should match your RMI configuration.
				</para>
			</sect1>
			
			<sect1 id="jconsole">
				<title>jConsole</title>
				<para>
					JConsole is a utility that ships with the JRE (since 1.5), it allows you to manage local and remote JMX implementations. 
					To enable introspection you must add the following VM parameter to your startup:
					
					-Dcom.sun.management.jmxremote
					
					After the parameter is set and the application initialized you can start jConsole at the command line by typing:
					
					<command>
						jconsole
					</command>
					
					
					A Swing application will appear and you must select the implementation (agent) you wish to manage, 
					for local simply select "org.red5.server.Standalone".
					
				</para>
			</sect1>	
			
			<sect1 id="management-resources">
				<title>Links</title>
				<para>
					<ulink url="http://www.onjava.com/pub/a/onjava/2004/09/29/tigerjmx.html?page=1">http://www.onjava.com/pub/a/onjava/2004/09/29/tigerjmx.html?page=1</ulink>
					<ulink url="http://www.onjava.com/pub/a/onjava/2004/09/29/tigerjmx.html?page=1">http://java.sun.com/developer/JDCTechTips/2005/tt0315.html#2</ulink>
				</para>
			</sect1>		
		</chapter>
	</part>
	
	<part id="red5-scripting">
		<title>Scripting</title>
		
		<partintro>
			<para>
				TODO
			</para>
		</partintro>
		
		<chapter id="red5-scripting-choose">
			<chapterinfo>
				<date>2 Feb 2007</date>
				<authorgroup>
					<author>
						<firstname>Paul</firstname>
						<surname>Gregoire</surname>
						<email></email>
					</author>
				</authorgroup>
				
				<revhistory>
					<revision>
						<revnumber>2</revnumber>
						<date>2 Feb 2007</date>
					</revision>
				</revhistory>
				
			</chapterinfo>
			
			<title>Select a scripting implementation</title>
			
			<note>
				<para>Level: Beginner</para>
			</note>
			
			<para>
				Red5 includes interpreters for the following scripting languages:
			</para>
			
			<itemizedlist>
				<listitem>
					<para>Javascript - version 1.6 (Mozilla Rhino version 1.6.2)</para>
				</listitem>
				<listitem>
					<para>JRuby - version 0.9.2 (Ruby version 1.8.5)</para>
				</listitem>
				<listitem>
					<para>Jython - version 2.1 (Python version 2.1)</para>
				</listitem>
				<listitem>
					<para>Groovy - version 1.0</para>
				</listitem>
				<listitem>
					<para>Beanshell - version 2.0b4</para>
				</listitem>
			</itemizedlist>
			
			<para>
				Future versions may include:
			</para>
			
			<itemizedlist>
				<listitem>
					<para>JudoScript</para>
				</listitem>
				<listitem>
					<para>Scala</para>
				</listitem>
				<listitem>
					<para>PHP (This one is non-trivial, I may just provide a bridge)</para>
				</listitem>
				<listitem>
					<para>Actionscript (Not SSAS)</para>
				</listitem>
			</itemizedlist>
			
			<para>
				The scripting implementation classes are pre-specified in the 
				following locations depending upon your Java version:
			</para>
			
			<variablelist>
				<varlistentry>
					<term>Java5</term>
					<listitem>
						<para>jsr-223-1.0-pr.jar /META-INF/services/javax.script.ScriptEngineFactory</para>
					</listitem>
				</varlistentry>
				<varlistentry>
					<term>Java6</term>
					<listitem>
						<para>resources.jar /META-INF/services/javax.script.ScriptEngineFactory</para>
					</listitem>
				</varlistentry>
				<varlistentry>
					<term>Red5</term>
					<listitem>
						<para>red5.jar /META-INF/services/javax.script.ScriptEngineFactory</para>
					</listitem>
				</varlistentry>
			</variablelist>
			
			<para>
				It is most likely that the classes read from the jdk or jre will be prefered over any specified elsewhere.
			</para>
		</chapter>
		
		<chapter id="red5-scripting-configuring">
			<chapterinfo>
				<date>2 Feb 2007</date>
				<authorgroup>
					<author>
						<firstname>Paul</firstname>
						<surname>Gregoire</surname>
						<email></email>
					</author>
				</authorgroup>
				
				<revhistory>
					<revision>
						<revnumber>2</revnumber>
						<date>2 Feb 2007</date>
					</revision>
				</revhistory>
				
			</chapterinfo>
			
			<title>Configuring Spring</title>
			
			<note>
				<para>Level: Intermediate</para>
			</note>
			
			<para>
				Step one is to locate your web applications red5-web.xml file. Within the xml config file the web.scope bean 
				definition must supply a web.handler, this handler is your Red5 application (An application must extend the org.red5.server.adapter.ApplicationAdapter class).
				The application provides access to the Red5 server and any service instances that are created. 
				The service instances and the application itself may be scripted.
			</para>
			
			<para>
				Bean definitions in Spring config files may not have the same id, here are some web handler definition examples:
			</para>
			
			<variablelist>
				<varlistentry>
					<term>Java</term>
					<listitem>
						<para>
							<programlisting>
								<literal>
									<![CDATA[
			<bean id="web.handler" class="org.red5.server.webapp.oflaDemo.Application" />					
									]]>
								</literal>
							</programlisting>
						</para>
					</listitem>
				</varlistentry>
				
				<varlistentry>
					<term>Javascript</term>
					<listitem>
						<para>
							<programlisting>
								<literal>
									<![CDATA[
<bean id="web.handler" class="org.red5.server.script.rhino.RhinoScriptFactory">
	<constructor-arg index="0" value="classpath:applications/main.js"/>
	<constructor-arg index="1">
		<list>
			<value>org.red5.server.api.IScopeHandler</value>
     		<value>org.red5.server.adapter.IApplication</value>
		</list>
	</constructor-arg>
	<constructor-arg index="2">
		<value>org.red5.server.adapter.ApplicationAdapter</value>
	</constructor-arg>
</bean>
			
									]]>
								</literal>
							</programlisting>
						</para>
					</listitem>
				</varlistentry>
				
				<varlistentry>
					<term>Ruby</term>
					<listitem>
						<para>
							<programlisting>
								<literal>
									<![CDATA[
<bean id="web.handler" class="org.springframework.scripting.jruby.JRubyScriptFactory">
	<constructor-arg index="0" value="classpath:applications/main.rb"/>
	<constructor-arg index="1">
		<list>
			<value>org.red5.server.api.IScopeHandler</value>
			<value>org.red5.server.adapter.IApplication</value>
		</list>
	</constructor-arg>
</bean>	
									]]>
								</literal>
							</programlisting>
						</para>
					</listitem>
				</varlistentry>
				
				<varlistentry>
					<term>Groovy</term>
					<listitem>
						<para>
							<programlisting>
								<literal>
									<![CDATA[
<bean id="web.handler" class="org.red5.server.script.groovy.GroovyScriptFactory">
	<constructor-arg index="0" value="classpath:applications/main.groovy"/>
	<constructor-arg index="1">
		<list>
			<value>org.red5.server.api.IScopeHandler</value>
			<value>org.red5.server.adapter.IApplication</value>
		</list>
	</constructor-arg>
</bean>
									]]>
								</literal>
							</programlisting>
						</para>
					</listitem>
				</varlistentry>
				
				<varlistentry>
					<term>Python</term>
					<listitem>
						<para>
							<programlisting>
								<literal>
									<![CDATA[
<bean id="web.handler" class="org.red5.server.script.jython.JythonScriptFactory">
	<constructor-arg index="0" value="classpath:applications/main.py"/>
	<constructor-arg index="1">
		<list>
    		<value>org.red5.server.api.IScopeHandler</value>
    		<value>org.red5.server.adapter.IApplication</value>
		</list>
	</constructor-arg>
        <constructor-arg index="2">
		<list>
            <value>One</value>
            <value>2</value>
            <value>III</value>
        </list>
    </constructor-arg>
</bean>
									]]>
								</literal>
							</programlisting>
						</para>
					</listitem>
				</varlistentry>
			</variablelist>
			
			<para>
				In general the configuration using scripted classes is defined using the constructor arguments (see interpreter section) in the following order:
			</para>
			
			<variablelist>
				<varlistentry>
					<term>Argument 1</term>
					<listitem>
						<para>Location of the script source file</para>
					</listitem>
				</varlistentry>
				
				<varlistentry>
					<term>Argument 2</term>
					<listitem>
						<para>Java interfaces implemented by the script</para>
						<para>
							The interfaces for the code which extends an Application are basically boilerplate as seen in the examples above; You do not
							have to use those interfaces in all your script definitions.
						</para>
					</listitem>
				</varlistentry>
				
				<varlistentry>
					<term>Argument 3</term>
					<listitem>
						<para>Java classes extended by the script</para>
						<para>The extended class is not always necessary, it depends upon the scripting engine implementation.</para>
					</listitem>
				</varlistentry>
				
			</variablelist>
			
			<para>
				The example location starts with classpath:applications which in physical disk terms for the "oflaDemo" 
				application equates to webapps/oflaDemo/WEB-INF/applications 
			</para>
			
		</chapter>
		
		<chapter id="red5-scripting-creating">
			<chapterinfo>
				<date>2 Feb 2007</date>
				<authorgroup>
					<author>
						<firstname>Paul</firstname>
						<surname>Gregoire</surname>
						<email></email>
					</author>
				</authorgroup>
				
				<revhistory>
					<revision>
						<revnumber>2</revnumber>
						<date>2 Feb 2007</date>
					</revision>
				</revhistory>
				
			</chapterinfo>
			
			<title>Creating an application script</title>
			
			<note>
				<para>Level: Intermediate</para>
			</note>
			
			<sect1 id="red5-scripting-application-adapter">
				<title>Application adapter</title>
				<para>
					Scripting an application adapter is more difficult in some languages than it is in others, 
					because of this I present the Ruby example which works really well and is easy to write 
					and integrate. The application services are easily written in any of the supported languages, 
					but they require a Java interface at a minimum.
				</para>
				
				<sect2>
					<title>JRuby application adapter implementation</title>
					<para>
						<programlisting>
							<literal>
							<![CDATA[
							require 'java'
module RedFive
    include_package "org.red5.server.api"
    include_package "org.red5.server.api.stream"
    include_package "org.red5.server.api.stream.support"
    include_package "org.red5.server.adapter"
    include_package "org.red5.server.stream"
end

#
# application.rb - a translation into Ruby of the ofla demo application, a red5 example.
#
# @author Paul Gregoire
#
class Application < RedFive::ApplicationAdapter

    attr_reader :appScope, :serverStream
	attr_writer :appScope, :serverStream
	 
	def initialize
	   #call super to init the superclass, in this case a Java class
	   super
	   puts "Initializing ruby application"
	end

	def appStart(app)
        puts "Ruby appStart"
		@appScope = app
		return true
	end

	def appConnect(conn, params) 
		puts "Ruby appConnect"
		measureBandwidth(conn)
		puts "Ruby appConnect 2"
		if conn.instance_of?(RedFive::IStreamCapableConnection)
		    puts "Got stream capable connection"
			sbc = RedFive::SimpleBandwidthConfigure.new
			sbc.setMaxBurst(8388608)
			sbc.setBurst(8388608)
			sbc.setOverallBandwidth(8388608)
			conn.setBandwidthConfigure(sbc)
		end
		return super
	end

	def appDisconnect(conn) 
		puts "Ruby appDisconnect"
		if appScope == conn.getScope && @serverStream != nil 
			@serverStream.close
		end
		super
	end

	def toString
		return "Ruby toString"
	end

    def setScriptContext(scriptContext)
	   puts "Ruby application setScriptContext"
    end

    def method_missing(m, *args)
      super unless @value.respond_to?(m) 
      return @value.send(m, *args)
    end

end
	
							]]>
							</literal>
						</programlisting>
					</para>
				</sect2>
			</sect1>	
			
			<sect1 id="red5-scripting-application-services">
				<title>Application services</title>
				<para>
					Here is an example of a Java interface (Yes, the methods are supposed to be empty) 
					which is used in the examples to provide a template for applications which will gather a list 
					of files and return them as a "Map" (key-value pairs) to the caller.
				</para>
				
				<sect2>
					<title>Simple Java interface for implementation by scripts </title>
					<para>
						<programlisting>
							<literal>
							<![CDATA[
							package org.red5.server.webapp.oflaDemo;

import java.util.Map;

public interface IDemoService {

	/**
     * Getter for property 'listOfAvailableFLVs'.
     *
     * @return Value for property 'listOfAvailableFLVs'.
     */
    public Map getListOfAvailableFLVs();

    public Map getListOfAvailableFLVs(String string);

}
	
							]]>
							</literal>
						</programlisting>
					</para>
				</sect2>
				<sect2>
					<title>Spring bean definition for a script implementation of the interface</title>
					<programlisting>
						<literal>
							<![CDATA[
	<bean id="demoService.service" class="org.springframework.scripting.jruby.JRubyScriptFactory">
		<constructor-arg index="0" value="classpath:applications/demoservice.rb"/>
		<constructor-arg index="1">
			<list>
     			<value>org.red5.server.webapp.oflaDemo.IDemoService</value>
  			</list>
		</constructor-arg>
	</bean>

							]]>
						</literal>
					</programlisting>
						
				</sect2>
				<sect2>
					<title>JRuby script implementing the interface</title>
				<programlisting>
					<literal>
						<![CDATA[
						require 'java'
module RedFive
    include_package "org.springframework.core.io"
    include_package "org.red5.server.webapp.oflaDemo"
end
include_class "org.red5.server.api.Red5"
include_class "java.util.HashMap"

#
# demoservice.rb - a translation into Ruby of the ofla demo application, a red5 example.
#
# @author Paul Gregoire
#
class DemoService < RedFive::DemoServiceImpl

    attr_reader :filesMap
    attr_writer :filesMap

	def initialize
	   puts "Initializing ruby demoservice"
	   super
	   @filesMap = HashMap.new
	end

	def getListOfAvailableFLVs
		puts "Getting the FLV files"
		begin
            dirname = File.expand_path('webapps/oflaDemo/streams').to_s
			Dir.open(dirname).entries.grep(/\.flv$/) do |dir|
			    dir.each do |flvName|
      			    fileInfo = HashMap.new
      			    stats = File.stat(dirname+'/'+flvName)
      			    fileInfo["name"] = flvName
      			    fileInfo["lastModified"] = stats.mtime
      			    fileInfo["size"] = stats.size || 0
                    @filesMap[flvName] = fileInfo
                    print 'FLV Name:', flvName
                    print 'Last modified date:', stats.mtime
                    print 'Size:', stats.size || 0
                    print '-------'
                end
            end
		rescue Exception => ex
			puts "Error in getListOfAvailableFLVs #{errorType} \n"
			puts "Exception: #{ex} \n"
			puts caller.join("\n");
		end
		return filesMap
	end

	def formatDate(date)
		return date.strftime("%d/%m/%Y %I:%M:%S")
	end

    def method_missing(m, *args)
      super unless @value.respond_to?(m)
      return @value.send(m, *args)
    end

end
						]]>
					</literal>
				</programlisting>
				</sect2>
				<sect2>
					<title>Java application implementing the interface</title>
					<para>
						upon which the Ruby code was based (This code is NOT needed when using the script)
					</para>
					<programlisting>
						<literal>
						<![CDATA[
						package org.red5.server.webapp.oflaDemo;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.red5.server.api.IScope;
import org.red5.server.api.Red5;
import org.springframework.core.io.Resource;

public class DemoService {

	protected static Log log = LogFactory.getLog(DemoService.class.getName());

	/**
     * Getter for property 'listOfAvailableFLVs'.
     *
     * @return Value for property 'listOfAvailableFLVs'.
     */
    public Map getListOfAvailableFLVs() {
		IScope scope = Red5.getConnectionLocal().getScope();
		Map<String, Map> filesMap = new HashMap<String, Map>();
		Map<String, Object> fileInfo;
		try {
			log.debug("getting the FLV files");
			Resource[] flvs = scope.getResources("streams/*.flv");
			if (flvs != null) {
				for (Resource flv : flvs) {
					File file = flv.getFile();
					Date lastModifiedDate = new Date(file.lastModified());
					String lastModified = formatDate(lastModifiedDate);
					String flvName = flv.getFile().getName();
					String flvBytes = Long.toString(file.length());
					if (log.isDebugEnabled()) {
						log.debug("flvName: " + flvName);
						log.debug("lastModified date: " + lastModified);
						log.debug("flvBytes: " + flvBytes);
						log.debug("-------");
					}
					fileInfo = new HashMap<String, Object>();
					fileInfo.put("name", flvName);
					fileInfo.put("lastModified", lastModified);
					fileInfo.put("size", flvBytes);
					filesMap.put(flvName, fileInfo);
				}
			}

			Resource[] mp3s = scope.getResources("streams/*.mp3");
			if (mp3s != null) {
				for (Resource mp3 : mp3s) {
					File file = mp3.getFile();
					Date lastModifiedDate = new Date(file.lastModified());
					String lastModified = formatDate(lastModifiedDate);
					String flvName = mp3.getFile().getName();
					String flvBytes = Long.toString(file.length());
					if (log.isDebugEnabled()) {
						log.debug("flvName: " + flvName);
						log.debug("lastModified date: " + lastModified);
						log.debug("flvBytes: " + flvBytes);
						log.debug("-------");
					}
					fileInfo = new HashMap<String, Object>();
					fileInfo.put("name", flvName);
					fileInfo.put("lastModified", lastModified);
					fileInfo.put("size", flvBytes);
					filesMap.put(flvName, fileInfo);
				}
			}
		} catch (IOException e) {
			log.error(e);
		}
		return filesMap;
	}

	private String formatDate(Date date) {
		SimpleDateFormat formatter;
		String pattern = "dd/MM/yy H:mm:ss";
		Locale locale = new Locale("en", "US");
		formatter = new SimpleDateFormat(pattern, locale);
		return formatter.format(date);
	}

}
	
						]]>
						</literal>
					</programlisting>
				</sect2>
				
				<sect2>
					<title>Flex AS3 method calling the service</title>
					<programlisting>
						<literal>
						<![CDATA[
	[Bindable]
    public var videoList:ArrayCollection;

    public function catchVideos():void{
		// call server-side method
		// create a responder and set it to getMediaList
		var nc_responder:Responder = new Responder(getMediaList, null);
		// call the server side method to get list of FLV's
		nc.call("demoService.getListOfAvailableFLVs", nc_responder);
	}

    public function getMediaList(list:Object):void{
		// this is the result of the server side getListOfAvailableFLVs
		var mediaList:Array = new Array();
		for(var items:String in list){
			mediaList.push({label:items, size:list[items].size, dateModified:list[items].lastModified});
		}
		// videoList is bindable and the datagrid is set to use this for it's dataprovider
		// wrap it in an ArrayCollection first
		videoList = new ArrayCollection(mediaList);
	}

						]]>
						</literal>
					</programlisting>
				</sect2>
				
			</sect1>
			<sect1>
				<title>Creating your own interpreter</title>
				<note>
					<para>Level: Advanced</para>
				</note>
				<para>
					Lets just open this up by saying that I attempted to build an interpreter for PHP this last weekend 02/2007 and it was a real pain; 
					after four hours I had to give up. So what I learned from this is that you must first identify scripting languages 
					which operate as applications, not as http request processors. Heres a test: Can X language be compiled into 
					an executable or be run on the command-line? If yes then it should be trivial to integrate. 
				</para>
			</sect1>
			<sect1>
				<title>Links with scripting information</title>
				
				<variablelist>
					<varlistentry>
						<term>Spring scripting</term>
						<listitem>
							<para><ulink url="http://static.springframework.org/spring/docs/2.0.x/reference/dynamic-language.html">http://static.springframework.org/spring/docs/2.0.x/reference/dynamic-language.html</ulink></para>
							<para><ulink url="http://rhinoinspring.sourceforge.net/">http://rhinoinspring.sourceforge.net/</ulink></para>
						</listitem>
					</varlistentry>
					<varlistentry>
						<term>Java scripting</term>
						<listitem>
							<para><ulink url="http://java.sun.com/developer/technicalArticles/J2SE/Desktop/scripting/">http://java.sun.com/developer/technicalArticles/J2SE/Desktop/scripting/</ulink></para>
							<para><ulink url="http://blogs.sun.com/sundararajan/">http://blogs.sun.com/sundararajan/</ulink></para>
							<para><ulink url="https://scripting.dev.java.net/">https://scripting.dev.java.net/</ulink></para>
							<para><ulink url="https://scripting.dev.java.net/">https://scripting.dev.java.net/</ulink></para>
							<para><ulink url="http://today.java.net/pub/a/today/2006/04/11/scripting-for-java-platform.html">http://today.java.net/pub/a/today/2006/04/11/scripting-for-java-platform.html</ulink></para>
							<para><ulink url="http://www.javaworld.com/javaworld/jw-03-2005/jw-0314-scripting_p.html">http://www.javaworld.com/javaworld/jw-03-2005/jw-0314-scripting_p.html</ulink></para>
							<para><ulink url="http://www.oreillynet.com/onjava/blog/2004/01/java_scripting_half_the_size_h.html">http://www.oreillynet.com/onjava/blog/2004/01/java_scripting_half_the_size_h.html</ulink></para>
							<para><ulink url="http://www.robert-tolksdorf.de/vmlanguages.html">http://www.robert-tolksdorf.de/vmlanguages.html</ulink></para>
						</listitem>
					</varlistentry>
					
					<varlistentry>
						<term>Javascript</term>
						<listitem>
							<para><ulink url="http://www.mozilla.org/rhino/">http://www.mozilla.org/rhino/</ulink></para>
							<para><ulink url="http://www.mozilla.org/rhino/ScriptingJava.html">http://www.mozilla.org/rhino/ScriptingJava.html</ulink></para>
						</listitem>
					</varlistentry>
					
					<varlistentry>
						<term>Ruby</term>
						<listitem><para><ulink url="http://jruby.codehaus.org/">http://jruby.codehaus.org/</ulink></para></listitem>
					</varlistentry>
					
					<varlistentry>
						<term>Beanshell</term>
						<listitem><para><ulink url="http://www.beanshell.org/">http://www.beanshell.org/</ulink></para></listitem>
					</varlistentry>
					
					<varlistentry>
						<term>Python</term>
						<listitem>
							<para><ulink url="http://www.jython.org/Project/">http://www.jython.org/Project/</ulink></para>
							<para><ulink url="http://www.onjava.com/pub/a/onjava/2002/03/27/jython.html">http://www.onjava.com/pub/a/onjava/2002/03/27/jython.html</ulink></para>
							<para><ulink url="http://jepp.sourceforge.net/">http://jepp.sourceforge.net/</ulink></para>
							<para><ulink url="http://jpe.sourceforge.net/">http://jpe.sourceforge.net/</ulink></para>
							<para><ulink url="http://jpype.sourceforge.net/">http://jpype.sourceforge.net/</ulink></para>
						</listitem>
					</varlistentry>
					
					<varlistentry>
						<term>Groovy</term>
						<listitem><para><ulink url="http://groovy.codehaus.org/">http://groovy.codehaus.org/</ulink></para></listitem>
					</varlistentry>
					
					
				</variablelist>
				
			</sect1>
			
		</chapter>
	</part>
</book>