<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][16127] </title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=16127">16127</a></dd>
<dt>Author</dt> <dd>dvarnes</dd>
<dt>Date</dt> <dd>2010-01-03 08:54:19 -0600 (Sun, 03 Jan 2010)</dd>
</dl>

<h3>Log Message</h3>
<pre>Initial commit - java ESL inbound/outbound client implementation</pre>

<h3>Added Paths</h3>
<ul>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientproject">freeswitch/trunk/contrib/dvarnes/java/esl-client/.project</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/.settings/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientsettingsorgmavenideeclipseprefs">freeswitch/trunk/contrib/dvarnes/java/esl-client/.settings/org.maven.ide.eclipse.prefs</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientclasspath">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.classpath</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientproject">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.project</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.settings/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsettingsorgeclipsejdtcoreprefs">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.settings/org.eclipse.jdt.core.prefs</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsettingsorgmavenideeclipseprefs">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.settings/org.maven.ide.eclipse.prefs</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientTODOtxt">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/TODO.txt</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientpomxml">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/pom.xml</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientIEslEventListenerjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/IEslEventListener.java</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinboundClientjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/Client.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinboundInboundClientHandlerjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundClientHandler.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinboundInboundConnectionFailurejava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundConnectionFailure.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinboundInboundPipelineFactoryjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundPipelineFactory.java</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinternalAbstractEslClientHandlerjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/AbstractEslClientHandler.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinternalHeaderParserjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/HeaderParser.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinternalIEslProtocolListenerjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/IEslProtocolListener.java</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/debug/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinternaldebugChannelEventRunnablejava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/debug/ChannelEventRunnable.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinternaldebugExecutionHandlerjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/debug/ExecutionHandler.java</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientoutboundAbstractOutboundClientHandlerjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/AbstractOutboundClientHandler.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientoutboundAbstractOutboundPipelineFactoryjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/AbstractOutboundPipelineFactory.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientoutboundSocketClientjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/SocketClient.java</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/example/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientoutboundexampleSimpleHangupOutboundHandlerjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/example/SimpleHangupOutboundHandler.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientoutboundexampleSimpleHangupPipelineFactoryjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/example/SimpleHangupPipelineFactory.java</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransportCommandResponsejava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/CommandResponse.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransportSendMsgjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/SendMsg.java</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/event/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransporteventEslEventjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/event/EslEvent.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransporteventEslEventHeaderNamesjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/event/EslEventHeaderNames.java</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransportmessageEslHeadersjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslHeaders.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransportmessageEslMessagejava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslMessage.java</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransportmessageEslMessageDecoderjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslMessageDecoder.java</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/resources/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/inbound/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrctestjavaorgfreeswitcheslclientinboundClientTestjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/inbound/ClientTest.java</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/outbound/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrctestjavaorgfreeswitcheslclientoutboundSocketClientTestjava">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/outbound/SocketClientTest.java</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/resources/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrctestresourceslogbacktestxml">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/resources/logback-test.xml</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/</li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientexampleclasspath">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/.classpath</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientexampleproject">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/.project</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientexamplepomxml">freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/pom.xml</a></li>
<li><a href="#freeswitchtrunkcontribdvarnesjavaeslclientpomxml">freeswitch/trunk/contrib/dvarnes/java/esl-client/pom.xml</a></li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/src/</li>
<li>freeswitch/trunk/contrib/dvarnes/java/esl-client/src/site/</li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientproject"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/.project (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/.project                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/.project        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;projectDescription&gt;
+        &lt;name&gt;org.freeswitch.esl&lt;/name&gt;
+        &lt;comment&gt;&lt;/comment&gt;
+        &lt;projects&gt;
+        &lt;/projects&gt;
+        &lt;buildSpec&gt;
+                &lt;buildCommand&gt;
+                        &lt;name&gt;org.maven.ide.eclipse.maven2Builder&lt;/name&gt;
+                        &lt;arguments&gt;
+                        &lt;/arguments&gt;
+                &lt;/buildCommand&gt;
+        &lt;/buildSpec&gt;
+        &lt;natures&gt;
+                &lt;nature&gt;org.maven.ide.eclipse.maven2Nature&lt;/nature&gt;
+        &lt;/natures&gt;
+&lt;/projectDescription&gt;
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/.project
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientsettingsorgmavenideeclipseprefs"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/.settings/org.maven.ide.eclipse.prefs (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/.settings/org.maven.ide.eclipse.prefs                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/.settings/org.maven.ide.eclipse.prefs        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+#Sat Dec 12 17:33:34 EST 2009
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
</ins></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientclasspath"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.classpath (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.classpath                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.classpath        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;classpath&gt;
+        &lt;classpathentry kind=&quot;src&quot; output=&quot;target/classes&quot; path=&quot;src/main/java&quot;/&gt;
+        &lt;classpathentry excluding=&quot;**&quot; kind=&quot;src&quot; output=&quot;target/classes&quot; path=&quot;src/main/resources&quot;/&gt;
+        &lt;classpathentry kind=&quot;src&quot; output=&quot;target/test-classes&quot; path=&quot;src/test/java&quot;/&gt;
+        &lt;classpathentry excluding=&quot;**&quot; kind=&quot;src&quot; output=&quot;target/test-classes&quot; path=&quot;src/test/resources&quot;/&gt;
+        &lt;classpathentry kind=&quot;con&quot; path=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5&quot;/&gt;
+        &lt;classpathentry kind=&quot;con&quot; path=&quot;org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER&quot;/&gt;
+        &lt;classpathentry kind=&quot;output&quot; path=&quot;target/classes&quot;/&gt;
+&lt;/classpath&gt;
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.classpath
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientproject"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.project (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.project                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.project        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;projectDescription&gt;
+        &lt;name&gt;org.freeswitch.esl.client.netty&lt;/name&gt;
+        &lt;comment&gt;&lt;/comment&gt;
+        &lt;projects&gt;
+        &lt;/projects&gt;
+        &lt;buildSpec&gt;
+                &lt;buildCommand&gt;
+                        &lt;name&gt;org.eclipse.jdt.core.javabuilder&lt;/name&gt;
+                        &lt;arguments&gt;
+                        &lt;/arguments&gt;
+                &lt;/buildCommand&gt;
+                &lt;buildCommand&gt;
+                        &lt;name&gt;org.maven.ide.eclipse.maven2Builder&lt;/name&gt;
+                        &lt;arguments&gt;
+                        &lt;/arguments&gt;
+                &lt;/buildCommand&gt;
+        &lt;/buildSpec&gt;
+        &lt;natures&gt;
+                &lt;nature&gt;org.eclipse.jdt.core.javanature&lt;/nature&gt;
+                &lt;nature&gt;org.maven.ide.eclipse.maven2Nature&lt;/nature&gt;
+        &lt;/natures&gt;
+&lt;/projectDescription&gt;
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.project
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsettingsorgeclipsejdtcoreprefs"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.settings/org.eclipse.jdt.core.prefs (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.settings/org.eclipse.jdt.core.prefs                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.settings/org.eclipse.jdt.core.prefs        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+#Sun Jan 03 23:33:57 EST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
</ins></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsettingsorgmavenideeclipseprefs"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.settings/org.maven.ide.eclipse.prefs (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.settings/org.maven.ide.eclipse.prefs                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/.settings/org.maven.ide.eclipse.prefs        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+#Sat Dec 12 17:44:54 EST 2009
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
</ins></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientTODOtxt"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/TODO.txt (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/TODO.txt                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/TODO.txt        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+
+As at 2010.01.03
+
+Features still to be implemented
+ * More testing of the outbound socket client
+ * Send event command
+ * Send message command for inbound client
+ * Refactor the api of the inbound client into the abstract handler so it is also available in outbound handlers
+ * Per event(s) listener
+ * Provide XML event handling - not sure if this is useful since the raw event is not exposed, although it could be if needed.
+ * 'myevent' event subscription - not a priority here, easy if required.
+ * Provide timeout protection on the client.sendSyncApiCommand().  It will currently block for ever.
+ * Working examples in an example project (started).

+Quality items
+ * Ask FS dev team for any ESL event generation test strategies/suites.
+ * Are all message header names in the enum ?
+ * Improve Javadoc coverage
+ * Add cross references to the FS wiki in the Javadocs .. eg list of api commands and events.
+ * Add unit test coverage
+ * Investigate availability of FS JIRA for issue tracking
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/TODO.txt
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientpomxml"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/pom.xml (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/pom.xml                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/pom.xml        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,92 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;!--
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+--&gt;
+&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&gt;
+  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
+  &lt;parent&gt;
+    &lt;groupId&gt;org.freeswitch.esl.client&lt;/groupId&gt;
+    &lt;artifactId&gt;esl-client-parent&lt;/artifactId&gt;
+    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
+  &lt;/parent&gt;
+  &lt;artifactId&gt;org.freeswitch.esl.client&lt;/artifactId&gt;
+  &lt;name&gt;FreeSWITCH Event Socket Library - Java Client&lt;/name&gt;
+  &lt;packaging&gt;bundle&lt;/packaging&gt;
+  &lt;build&gt;
+  
+    &lt;plugins&gt;
+    
+      &lt;!--  this plugin will create the target jar as a correct OSGi bundle  --&gt;
+      &lt;plugin&gt;
+        &lt;groupId&gt;org.apache.felix&lt;/groupId&gt;
+        &lt;artifactId&gt;maven-bundle-plugin&lt;/artifactId&gt;
+        &lt;version&gt;2.0.1&lt;/version&gt;
+        &lt;extensions&gt;true&lt;/extensions&gt;
+        &lt;configuration&gt;
+          &lt;unpackBundle&gt;true&lt;/unpackBundle&gt;
+          &lt;instructions&gt;
+            &lt;Bundle-SymbolicName&gt;${project.artifactId}&lt;/Bundle-SymbolicName&gt;
+            &lt;Bundle-Version&gt;${project.version}&lt;/Bundle-Version&gt;
+            &lt;Bundle-DocURL&gt;http://www.freeswitch.org&lt;/Bundle-DocURL&gt;
+            &lt;Import-Package&gt;*&lt;/Import-Package&gt;
+            &lt;Export-Package&gt;
+              org.freeswitch.esl.client,
+              org.freeswitch.esl.client.transport.event,
+              org.freeswitch.esl.client.transport.message,
+            &lt;/Export-Package&gt;
+            &lt;!--  the debug package is a temporary hack  --&gt;
+            &lt;Private-Package&gt;
+              org.freeswitch.esl.client.internal,
+              org.freeswitch.esl.client.debug
+            &lt;/Private-Package&gt;
+          &lt;/instructions&gt;
+        &lt;/configuration&gt;
+      &lt;/plugin&gt;
+      
+    &lt;/plugins&gt;
+    
+  &lt;/build&gt;
+  &lt;dependencies&gt;
+
+    &lt;dependency&gt;
+      &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
+      &lt;artifactId&gt;slf4j-api&lt;/artifactId&gt;
+      &lt;version&gt;1.5.10&lt;/version&gt;
+    &lt;/dependency&gt;
+    
+    &lt;dependency&gt;
+      &lt;groupId&gt;org.jboss.netty&lt;/groupId&gt;
+      &lt;artifactId&gt;netty&lt;/artifactId&gt;
+      &lt;version&gt;3.1.5.GA&lt;/version&gt;
+    &lt;/dependency&gt;
+    
+    &lt;!--  test dependencies --&gt;
+    
+    &lt;dependency&gt;
+      &lt;groupId&gt;junit&lt;/groupId&gt;
+      &lt;artifactId&gt;junit&lt;/artifactId&gt;
+      &lt;version&gt;4.7&lt;/version&gt;
+      &lt;scope&gt;test&lt;/scope&gt;
+    &lt;/dependency&gt;
+    
+    &lt;dependency&gt;
+      &lt;groupId&gt;ch.qos.logback&lt;/groupId&gt;
+      &lt;artifactId&gt;logback-classic&lt;/artifactId&gt;
+      &lt;version&gt;0.9.18&lt;/version&gt;
+      &lt;scope&gt;test&lt;/scope&gt;
+    &lt;/dependency&gt;
+    
+  &lt;/dependencies&gt;
+&lt;/project&gt;
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/pom.xml
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientIEslEventListenerjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/IEslEventListener.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/IEslEventListener.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/IEslEventListener.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client;
+
+import org.freeswitch.esl.client.transport.event.EslEvent;
+
+/**
+ * Interface for observers wanting to be notified of incoming FreeSWITCH Event Socket events.
+ * &lt;/p&gt;
+ * Incoming events arrive asynchronously and are processed into two queues, one for server 
+ * initiated events, and one for the results of client requested background jobs.
+ * &lt;/p&gt;  
+ * Each queue is serviced by a different thread pool (to ensure lowest latency for event-driven events) 
+ * and each queue is guaranteed to be processed (and listeners notified) in the order in which the
+ * events are received off the wire.
+ * &lt;/p&gt;
+ * This design ensures that incoming event processing is not blocked by any long-running listener process.
+ * However multiple listeners will be notified sequentially, and so one slow listener can cause latency
+ * to other listeners.
+ *   
+ * @author  david varnes
+ * @version $Id$
+ */
+public interface IEslEventListener
+{
+    /**
+     * Signal of a server initiated event.
+     * 
+     * @param event as an {@link EslEvent} 
+     */
+    void eventReceived( EslEvent event );
+    
+    /**
+     * Signal of an event containing the result of a client requested background job.  The Job-UUID will
+     * be available as an event header of that name.
+     * 
+     * @param event as an {@link EslEvent}
+     */
+    void backgroundJobResultReceived( EslEvent event );
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/IEslEventListener.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinboundClientjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/Client.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/Client.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/Client.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,474 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.inbound;
+
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.freeswitch.esl.client.IEslEventListener;
+import org.freeswitch.esl.client.internal.IEslProtocolListener;
+import org.freeswitch.esl.client.transport.CommandResponse;
+import org.freeswitch.esl.client.transport.event.EslEvent;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+import org.jboss.netty.bootstrap.ClientBootstrap;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelFuture;
+import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Entry point to connect to a running FreeSWITCH Event Socket Library module, as a client.
+ * &lt;/p&gt;
+ * This class provides what the FreeSWITCH documentation refers to as an 'Inbound' connection
+ * to the Event Socket module. That is, with reference to the socket listening on the FreeSWITCH
+ * server, this client occurs as an inbound connection to the server.
+ * &lt;/p&gt;
+ * See http://wiki.freeswitch.org/wiki/Mod_event_socket
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public class Client
+{
+    private final Logger log = LoggerFactory.getLogger( this.getClass() );
+    
+    private final List&lt;IEslEventListener&gt; eventListeners = new CopyOnWriteArrayList&lt;IEslEventListener&gt;();
+    private final Executor eventListenerExecutor = Executors.newSingleThreadExecutor( 
+        new ThreadFactory()
+        {
+            AtomicInteger threadNumber = new AtomicInteger( 1 );
+            public Thread newThread( Runnable r )
+            {
+                return new Thread( r, &quot;EslEventNotifier-&quot; + threadNumber.getAndIncrement() );
+            }
+        });
+    private final Executor backgroundJobListenerExecutor = Executors.newSingleThreadExecutor( 
+        new ThreadFactory()
+        {
+            AtomicInteger threadNumber = new AtomicInteger( 1 );
+            public Thread newThread( Runnable r )
+            {
+                return new Thread( r, &quot;EslBackgroundJobNotifier-&quot; + threadNumber.getAndIncrement() );
+            }
+        });
+    
+    private AtomicBoolean authenticatorResponded = new AtomicBoolean( false );
+    private boolean authenticated;
+    private CommandResponse authenticationResponse;
+    private Channel channel;
+    
+    public boolean canSend()
+    {
+        return channel != null &amp;&amp; channel.isConnected() &amp;&amp; authenticated; 
+    }
+    
+    public void addEventListener( IEslEventListener listener )
+    {
+        if ( listener != null )
+        {
+            eventListeners.add( listener );
+        }
+    }
+
+    /**
+     * Attempt to establish an authenticated connection to the nominated FreeSWITCH ESL server socket.
+     * This call will block, waiting for an authentication handshake to occur, or timeout after the
+     * supplied number of seconds.  
+     *  
+     * @param host can be either ip address or hostname
+     * @param port tcp port that server socket is listening on (set in event_socket_conf.xml)
+     * @param password server event socket is expecting (set in event_socket_conf.xml) 
+     * @param timeoutSeconds number of seconds to wait for the server socket before aborting
+     */
+    public void connect( String host, int port, String password, int timeoutSeconds ) throws InboundConnectionFailure
+    {
+        // If already connected, disconnect first
+        if ( canSend() )
+        {
+            close();
+        }
+        
+        // Configure this client
+        ClientBootstrap bootstrap = new ClientBootstrap(
+            new NioClientSocketChannelFactory( 
+                Executors.newCachedThreadPool(), 
+                Executors.newCachedThreadPool() ) ); 
+        
+        // Add ESL handler and factory
+        InboundClientHandler handler = new InboundClientHandler( password, protocolListener );
+        bootstrap.setPipelineFactory( new InboundPipelineFactory( handler ) );
+        
+        // Attempt connection
+        ChannelFuture future = bootstrap.connect( new InetSocketAddress( host, port ) );
+        
+        // Wait till attempt succeeds, fails or timeouts
+        if ( ! future.awaitUninterruptibly( timeoutSeconds, TimeUnit.SECONDS ) )
+        {
+            throw new InboundConnectionFailure( &quot;Timeout connecting to &quot; + host + &quot;:&quot; + port );
+        }
+        // Did not timeout 
+        channel = future.getChannel();
+        // But may have failed anyway
+        if ( !future.isSuccess() )
+        {
+            log.warn( &quot;Failed to connect to [{}:{}]&quot;, host, port );
+            log.warn( &quot;  * reason: {}&quot;, future.getCause() );
+            
+            channel = null;
+            bootstrap.releaseExternalResources();
+            
+            throw new InboundConnectionFailure( &quot;Could not connect to &quot; + host + &quot;:&quot; + port, future.getCause() );
+        }
+        
+        //  Wait for the authentication handshake to call back
+        while ( ! authenticatorResponded.get() )
+        {
+            try
+            {
+                Thread.sleep( 250 );
+            } 
+            catch ( InterruptedException e )
+            {
+                // ignore
+            }
+        }
+        
+        if ( ! authenticated )
+        {
+            throw new InboundConnectionFailure( &quot;Authentication failed: &quot; + authenticationResponse.getReplyText() );
+        }
+    }
+    
+    /**
+     * Sends a FreeSWITCH API command to the server and blocks, waiting for an immediate response from the 
+     * server.
+     * &lt;p/&gt;
+     * The outcome of the command from the server is retured in an {@link EslMessage} object.
+     * 
+     * @param command API command to send
+     * @param arg command arguments
+     * @return an {@link EslMessage} containing command results
+     */
+    public EslMessage sendSyncApiCommand( String command, String arg )
+    {
+        checkConnected();
+        InboundClientHandler handler = (InboundClientHandler)channel.getPipeline().getLast();
+        StringBuilder sb = new StringBuilder();
+        if ( command != null &amp;&amp; !command.isEmpty() )
+        {
+            sb.append( &quot;api &quot; );
+            sb.append( command );
+        }
+        if ( arg != null &amp;&amp; !arg.isEmpty() )
+        {
+            sb.append( ' ' );
+            sb.append( arg );
+        }
+
+        return handler.sendSyncSingleLineCommand( channel, sb.toString() );
+    }
+    
+    /**
+     * Submit a FreeSWITCH API command to the server to be executed in background mode. A synchronous 
+     * response from the server provides a UUID to identify the job execution results. When the server
+     * has completed the job execution it fires a BACKGROUND_JOB Event with the execution results.&lt;p/&gt;
+     * Note that this Client must be subscribed in the normal way to BACKGOUND_JOB Events, in order to 
+     * receive this event.
+     *     
+     * @param command API command to send
+     * @param arg command arguments
+     * @return String Job-UUID that the server will tag result event with.
+     */
+    public String sendAsyncApiCommand( String command, String arg )
+    {
+        checkConnected();
+        InboundClientHandler handler = (InboundClientHandler)channel.getPipeline().getLast();
+        StringBuilder sb = new StringBuilder();
+        if ( command != null &amp;&amp; !command.isEmpty() )
+        {
+            sb.append( &quot;bgapi &quot; );
+            sb.append( command );
+        }
+        if ( arg != null &amp;&amp; !arg.isEmpty() )
+        {
+            sb.append( ' ' );
+            sb.append( arg );
+        }
+        
+        return handler.sendAsyncCommand( channel, sb.toString() );
+    }
+    
+    /**
+     * Set the current event subscription for this connection to the server.  Examples of the events 
+     * argument are:
+     * &lt;pre&gt;
+     *   ALL
+     *   CHANNEL_CREATE CHANNEL_DESTROY HEARTBEAT
+     *   CUSTOM conference::maintenance
+     *   CHANNEL_CREATE CHANNEL_DESTROY CUSTOM conference::maintenance sofia::register sofia::expire
+     * &lt;/pre&gt; 
+     * Subsequent calls to this method replaces any previous subscriptions that were set.
+     * &lt;/p&gt;
+     * Note: current implementation can only process 'plain' events.
+     * 
+     * @param format can be { plain | xml }
+     * @param events { all | space separated list of events } 
+     * @return a {@link CommandResponse} with the server's response.
+     */
+    public CommandResponse setEventSubscriptions( String format, String events )
+    {
+        // temporary hack
+        if ( ! format.equals( &quot;plain&quot; ) )
+        {
+            throw new IllegalStateException( &quot;Only 'plain' event format is supported at present&quot; );
+        }
+        
+        checkConnected();
+        InboundClientHandler handler = (InboundClientHandler)channel.getPipeline().getLast();
+        StringBuilder sb = new StringBuilder();
+        if ( format != null &amp;&amp; !format.isEmpty() )
+        {
+            sb.append( &quot;event &quot; );
+            sb.append( format );
+        }
+        if ( events != null &amp;&amp; !events.isEmpty() )
+        {
+            sb.append( ' ' );
+            sb.append( events );
+        }
+        EslMessage response = handler.sendSyncSingleLineCommand( channel, sb.toString() );
+
+        return new CommandResponse( sb.toString(), response );
+    }
+    
+    /**
+     * Cancel any existing event subscription.
+     * 
+     * @return a {@link CommandResponse} with the server's response.
+     */
+    public CommandResponse cancelEventSubscriptions()
+    {
+        checkConnected();
+        InboundClientHandler handler = (InboundClientHandler)channel.getPipeline().getLast();
+        EslMessage response = handler.sendSyncSingleLineCommand( channel, &quot;noevents&quot; );
+
+        return new CommandResponse( &quot;noevents&quot;, response );
+    }
+
+    /**
+     * Add an event filter to the current set of event filters on this connection. Any of the event headers
+     * can be used as a filter.
+     * &lt;/p&gt;
+     * Note that event filters follow 'filter-in' semantics. That is, when a filter is applied
+     * only the filtered values will be received. Multiple filters can be added to the current
+     * connection.
+     * &lt;/p&gt;
+     * Example filters:
+     * &lt;pre&gt;
+     *    eventHeader        valueToFilter
+     *    ----------------------------------
+     *    Event-Name         CHANNEL_EXECUTE
+     *    Channel-State      CS_NEW
+     * &lt;/pre&gt;
+     * 
+     * @param eventHeader to filter on
+     * @param valueToFilter the value to match
+     * @return a {@link CommandResponse} with the server's response.
+     */
+    public CommandResponse addEventFilter( String eventHeader, String valueToFilter )
+    {
+        checkConnected();
+        InboundClientHandler handler = (InboundClientHandler)channel.getPipeline().getLast();
+        StringBuilder sb = new StringBuilder();
+        if ( eventHeader != null &amp;&amp; !eventHeader.isEmpty() )
+        {
+            sb.append( &quot;filter &quot; );
+            sb.append( eventHeader );
+        }
+        if ( valueToFilter != null &amp;&amp; !valueToFilter.isEmpty() )
+        {
+            sb.append( ' ' );
+            sb.append( valueToFilter );
+        }
+        EslMessage response = handler.sendSyncSingleLineCommand( channel, sb.toString() );
+        
+        return new CommandResponse( sb.toString(), response );
+    }
+    
+    /**
+     * Delete an event filter from the current set of event filters on this connection.  See  
+     * {@link Client.addEventFilter}   
+     * 
+     * @param eventHeader   to remove
+     * @param valueToFilter to remove
+     * @return a {@link CommandResponse} with the server's response.
+     */
+    public CommandResponse deleteEventFilter( String eventHeader, String valueToFilter )
+    {
+        checkConnected();
+        InboundClientHandler handler = (InboundClientHandler)channel.getPipeline().getLast();
+        StringBuilder sb = new StringBuilder();
+        if ( eventHeader != null &amp;&amp; !eventHeader.isEmpty() )
+        {
+            sb.append( &quot;filter delete &quot; );
+            sb.append( eventHeader );
+        }
+        if ( valueToFilter != null &amp;&amp; !valueToFilter.isEmpty() )
+        {
+            sb.append( ' ' );
+            sb.append( valueToFilter );
+        }
+        EslMessage response = handler.sendSyncSingleLineCommand( channel, sb.toString() );
+
+        return new CommandResponse( sb.toString(), response );
+    }
+
+    /**
+     * Enable log output.
+     * 
+     * @param level using the same values as in console.conf
+     * @return a {@link CommandResponse} with the server's response.
+     */
+    public CommandResponse setLoggingLevel( String level )
+    {
+        checkConnected();
+        InboundClientHandler handler = (InboundClientHandler)channel.getPipeline().getLast();
+        StringBuilder sb = new StringBuilder();
+        if ( level != null &amp;&amp; !level.isEmpty() )
+        {
+            sb.append( &quot;log &quot; );
+            sb.append( level );
+        }
+        EslMessage response = handler.sendSyncSingleLineCommand( channel, sb.toString() );
+
+        return new CommandResponse( sb.toString(), response );
+    }
+
+    /**
+     * Disable any logging previously enabled with setLogLevel().
+     * 
+     * @return a {@link CommandResponse} with the server's response.
+     */
+    public CommandResponse cancelLogging()
+    {
+        checkConnected();
+        InboundClientHandler handler = (InboundClientHandler)channel.getPipeline().getLast();
+        EslMessage response = handler.sendSyncSingleLineCommand( channel, &quot;nolog&quot; );
+
+        return new CommandResponse( &quot;nolog&quot;, response );
+    }
+
+    /**
+     * Close the socket connection
+     * 
+     * @return a {@link CommandResponse} with the server's response.
+     */
+    public CommandResponse close()
+    {
+        checkConnected();
+        InboundClientHandler handler = (InboundClientHandler)channel.getPipeline().getLast();
+        EslMessage response = handler.sendSyncSingleLineCommand( channel, &quot;exit&quot; );
+
+        return new CommandResponse( &quot;exit&quot;, response );
+    }
+    
+    /*
+     *  Internal observer of the ESL protocol 
+     */
+    private final IEslProtocolListener protocolListener = new IEslProtocolListener()
+    {
+        public void authResponseReceived( CommandResponse response )
+        {
+            authenticatorResponded.set( true );
+            authenticated = response.isOk();
+            authenticationResponse = response;
+            log.debug( &quot;Auth response success={}, message=[{}]&quot;, authenticated, response.getReplyText() );
+        }
+        
+        public void eventReceived( final EslEvent event )
+        {
+            log.debug( &quot;Event received [{}]&quot;, event );
+            /*
+             *  Notify listeners in a different thread in order to:
+             *    - not to block the IO threads with potentially long-running listeners
+             *    - generally be defensive running other people's code
+             *  Use a different worker thread pool for async job results than for event driven
+             *  events to keep the latency as low as possible.
+             */
+            if ( event.getEventName().equals( &quot;BACKGROUND_JOB&quot; ) )
+            {
+                for ( final IEslEventListener listener : eventListeners )
+                {
+                    backgroundJobListenerExecutor.execute( new Runnable()
+                    {
+                        public void run()
+                        {
+                            try
+                            {
+                                listener.backgroundJobResultReceived( event );
+                            }
+                            catch ( Throwable t )
+                            {
+                                log.error( &quot;Error caught notifying listener of job result [&quot; + event + ']', t );
+                            }
+                        }
+                    } );
+                }
+            }
+            else
+            {
+                for ( final IEslEventListener listener : eventListeners )
+                {
+                    eventListenerExecutor.execute( new Runnable()
+                    {
+                        public void run()
+                        {
+                            try
+                            {
+                                listener.eventReceived( event );
+                            }
+                            catch ( Throwable t )
+                            {
+                                log.error( &quot;Error caught notifying listener of event [&quot; + event + ']', t );
+                            }
+                        }
+                    } );
+                }
+            }
+        }
+
+        public void disconnected()
+        {
+            log.info( &quot;Disconnected ..&quot; );
+        }
+    };
+    
+    private void checkConnected()
+    {
+        if ( ! canSend() )
+        {
+            throw new IllegalStateException( &quot;Not connected to FreeSWITCH Event Socket&quot; );
+        }
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/Client.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinboundInboundClientHandlerjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundClientHandler.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundClientHandler.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundClientHandler.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,89 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.inbound;
+
+import org.freeswitch.esl.client.internal.AbstractEslClientHandler;
+import org.freeswitch.esl.client.internal.IEslProtocolListener;
+import org.freeswitch.esl.client.transport.CommandResponse;
+import org.freeswitch.esl.client.transport.event.EslEvent;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+import org.freeswitch.esl.client.transport.message.EslHeaders.Value;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipelineCoverage;
+import org.jboss.netty.handler.execution.ExecutionHandler;
+
+/**
+ * End users of the inbound {@link Client} should not need to use this class. 
+ * &lt;/p&gt;
+ * Specialised {@link AbstractEslClientHandler} that implements the connection logic for an 
+ * 'Inbound' FreeSWITCH Event Socket connection.  The responsibilities for this class are:
+ * &lt;/p&gt;
+ * * To handle the auth request that the FreeSWITCH server will send immediately following a new 
+ * connection when mode is Inbound.
+ * &lt;/p&gt;
+ * * To signal the observing {@link IEslProtocolListener} (expected to be the Inbound client 
+ * implementation when ESL events are received.
+ * &lt;/p&gt;
+ * Note: implementation requirement is that an {@link ExecutionHandler} is placed in the processing 
+ * pipeline prior to this handler. This will ensure that each incoming message is processed in its
+ * own thread (although still guaranteed to be processed in the order of receipt).
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+@ChannelPipelineCoverage( &quot;one&quot; )
+public class InboundClientHandler extends AbstractEslClientHandler
+{
+    private final String password;
+    private final IEslProtocolListener listener;
+    
+    public InboundClientHandler( String password, IEslProtocolListener listener )
+    {
+        this.password = password;
+        this.listener = listener;
+    }
+    
+    protected void handleEslEvent( ChannelHandlerContext ctx, EslEvent event )
+    {
+        log.debug( &quot;Received event: [{}]&quot;, event );
+        listener.eventReceived( event );
+    }
+
+    protected void handleAuthRequest( ChannelHandlerContext ctx )
+    {
+        log.debug( &quot;Auth requested, sending [auth {}]&quot;, &quot;*****&quot; );
+        EslMessage response = sendSyncSingleLineCommand( ctx.getChannel(), &quot;auth &quot; + password );
+        log.debug( &quot;Auth response [{}]&quot;, response );
+        if ( response.getContentType().equals( Value.COMMAND_REPLY ) )
+        {
+            CommandResponse commandResponse = new CommandResponse( &quot;auth &quot; + password, response );
+            listener.authResponseReceived( commandResponse );
+        }
+        else
+        {
+            log.error( &quot;Bad auth response message [{}]&quot;, response );
+            throw new IllegalStateException( &quot;Incorrect auth response&quot; ); 
+        }
+    }
+
+    @Override
+    protected void handleDisconnectionNotice()
+    {
+        log.debug( &quot;Received disconnection notice&quot; );
+        listener.disconnected();
+    }
+    
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundClientHandler.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinboundInboundConnectionFailurejava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundConnectionFailure.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundConnectionFailure.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundConnectionFailure.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.inbound;
+
+/**
+ * Checked exception to handle connection failures.
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public class InboundConnectionFailure extends Exception
+{
+    private static final long serialVersionUID = 1L;
+
+    public InboundConnectionFailure( String message )
+    {
+        super( message );
+    }
+    
+    public InboundConnectionFailure( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundConnectionFailure.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinboundInboundPipelineFactoryjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundPipelineFactory.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundPipelineFactory.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundPipelineFactory.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,70 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.inbound;
+
+import org.freeswitch.esl.client.internal.debug.ExecutionHandler;
+import org.freeswitch.esl.client.transport.message.EslMessageDecoder;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.ChannelHandler;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
+import org.jboss.netty.handler.codec.string.StringDecoder;
+import org.jboss.netty.handler.codec.string.StringEncoder;
+import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;
+
+/**
+ * End users of the {@link Client} should not need to use this class. 
+ * &lt;/p&gt;
+ * Convenience factory to assemble a Netty processing pipeline for inbound clients.
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public class InboundPipelineFactory implements ChannelPipelineFactory
+{
+    private final ChannelHandler handler;
+    
+    private final ChannelBuffer[] delimiters = 
+        new ChannelBuffer[] { ChannelBuffers.wrappedBuffer( new byte[] { '\n' } ),
+                              ChannelBuffers.wrappedBuffer( new byte[] { '\n', '\n' } ) };
+    
+    public InboundPipelineFactory( ChannelHandler handler )
+    {
+        this.handler = handler;
+    }
+    
+    public ChannelPipeline getPipeline() throws Exception
+    {
+        ChannelPipeline pipeline = Channels.pipeline(); 
+        // Add the text line codec combination first
+        pipeline.addLast( &quot;framer&quot;, new DelimiterBasedFrameDecoder( 8192, delimiters ) );  
+        pipeline.addLast( &quot;stringDecoder&quot;, new StringDecoder() );
+        pipeline.addLast( &quot;encoder&quot;, new StringEncoder() );
+        pipeline.addLast( &quot;eslMessageDecoder&quot;, new EslMessageDecoder() );
+        // Add an executor to ensure separate thread for each upstream message from here
+        pipeline.addLast( &quot;executor&quot;, new ExecutionHandler( 
+            new OrderedMemoryAwareThreadPoolExecutor( 16, 1048576, 1048576 ) ) );
+
+        // now the inbound client logic
+        pipeline.addLast( &quot;clientHandler&quot;, handler );
+        
+        return pipeline;
+    }
+
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/inbound/InboundPipelineFactory.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinternalAbstractEslClientHandlerjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/AbstractEslClientHandler.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/AbstractEslClientHandler.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/AbstractEslClientHandler.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,258 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.internal;
+
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.freeswitch.esl.client.transport.event.EslEvent;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+import org.freeswitch.esl.client.transport.message.EslHeaders.Name;
+import org.freeswitch.esl.client.transport.message.EslHeaders.Value;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelUpstreamHandler;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
+import org.jboss.netty.handler.execution.ExecutionHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Specialised {@link ChannelUpstreamHandler} that implements the logic of an ESL connection that
+ * is common to both inbound and outbound clients. This 
+ * handler expects to receive decoded {@link EslMessage} or {@link EslEvent} objects. The key 
+ * responsibilities for this class are:
+ * &lt;/p&gt;
+ * * To synthesise a synchronous command/response api.  All IO operations using the underlying Netty 
+ * library are intrinsically asynchronous which provides for excellent response and scalability.  This 
+ * class provides for a blocking wait mechanism for responses to commands issued to the server.  A 
+ * key assumption here is that the FreeSWITCH server will process synchronous requests in the order they
+ * are received.
+ * &lt;/p&gt;
+ * * Concrete sub classes are expected to 'terminate' the Netty IO processing pipeline (ie be the 'last'
+ * handler). 
+ * &lt;/p&gt;
+ * Note: implementation requirement is that an {@link ExecutionHandler} is placed in the processing 
+ * pipeline prior to this handler. This will ensure that each incoming message is processed in its
+ * own thread (although still guaranteed to be processed in the order of receipt).
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public abstract class AbstractEslClientHandler extends SimpleChannelUpstreamHandler
+{
+    public static final String MESSAGE_TERMINATOR = &quot;\n\n&quot;;  
+    public static final String LINE_TERMINATOR = &quot;\n&quot;;  
+
+    protected final Logger log = LoggerFactory.getLogger( this.getClass() );
+
+    private final Lock syncLock = new ReentrantLock();
+    private final Queue&lt;SyncCallback&gt; syncCallbacks = new ConcurrentLinkedQueue&lt;SyncCallback&gt;();
+
+    @Override
+    public void messageReceived( ChannelHandlerContext ctx, MessageEvent e ) throws Exception
+    {
+        if ( e.getMessage() instanceof EslMessage )
+        {
+            EslMessage message = (EslMessage)e.getMessage();
+            String contentType = message.getContentType();
+            if ( contentType.equals( Value.TEXT_EVENT_PLAIN ) ||
+                    contentType.equals( Value.TEXT_EVENT_XML ) )
+            {
+                //  transform into an event
+                EslEvent eslEvent = new EslEvent( message );
+                handleEslEvent( ctx, eslEvent );
+            }
+            else
+            {
+                handleEslMessage( ctx, (EslMessage)e.getMessage() );
+            }
+        }
+        else
+        {
+            throw new IllegalStateException( &quot;Unexpected message type: &quot; + e.getMessage().getClass() );
+        }
+    }
+    
+    /**
+     * Synthesise a synchronous command/response by creating a callback object which is placed in 
+     * queue and blocks waiting for another IO thread to process an incoming {@link EslMessage} and
+     * attach it to the callback.
+     * 
+     * @param channel
+     * @param command single string to send
+     * @return the {@link EslMessage} attached to this command's callback
+     */
+    public EslMessage sendSyncSingleLineCommand( Channel channel, final String command )
+    {
+        SyncCallback callback = new SyncCallback();
+        syncLock.lock();
+        try 
+        {
+            syncCallbacks.add( callback );
+            channel.write( command + MESSAGE_TERMINATOR );
+        } 
+        finally 
+        {
+            syncLock.unlock();
+        }
+        
+        //  Block until the response is available 
+        return callback.get();
+    }
+
+    /**
+     * Synthesise a synchronous command/response by creating a callback object which is placed in 
+     * queue and blocks waiting for another IO thread to process an incoming {@link EslMessage} and
+     * attach it to the callback.
+     * 
+     * @param channel
+     * @param command List of command lines to send
+     * @return the {@link EslMessage} attached to this command's callback
+     */
+    public EslMessage sendSyncMultiLineCommand( Channel channel, final List&lt;String&gt; commandLines )
+    {
+        SyncCallback callback = new SyncCallback();
+        //  Build command with double line terminator at the end
+        StringBuilder sb = new StringBuilder();
+        for ( String line : commandLines )
+        {
+            sb.append( line );
+            sb.append( LINE_TERMINATOR );
+        }
+        sb.append( LINE_TERMINATOR );
+        
+        syncLock.lock();
+        try 
+        {
+            syncCallbacks.add( callback );
+            channel.write( sb.toString() );
+        } 
+        finally 
+        {
+            syncLock.unlock();
+        }
+        
+        //  Block until the response is available 
+        return callback.get();
+    }
+
+    /**
+     * Returns the Job UUID of that the response event will have.
+     * 
+     * @param channel
+     * @param command
+     * @return Job-UUID as a string
+     */
+    public String sendAsyncCommand( Channel channel, final String command )
+    {
+        /*
+         * Send synchronously to get the Job-UUID to return, the results of the actual 
+         * job request will be returned by the server as an async event.
+         */
+        EslMessage response = sendSyncSingleLineCommand( channel, command );
+        if ( response.hasHeader( Name.JOB_UUID ) )
+        {
+            return response.getHeaderValue( Name.JOB_UUID );
+        }
+        else
+        {
+            throw new IllegalStateException( &quot;Missing Job-UUID header in bgapi response&quot; );
+        }
+    }
+    
+    protected void handleEslMessage( ChannelHandlerContext ctx, EslMessage message )
+    {
+        log.info( &quot;Received message: [{}]&quot;, message );
+        String contentType = message.getContentType();
+        
+        if ( contentType.equals( Value.API_RESPONSE ) )
+        {
+            log.debug( &quot;Api response received [{}]&quot;, message );
+            syncCallbacks.poll().handle( message );
+        }
+        else if ( contentType.equals( Value.COMMAND_REPLY ) )
+        {
+            log.debug( &quot;Command reply received [{}]&quot;, message );
+            syncCallbacks.poll().handle( message );
+        }
+        else if ( contentType.equals( Value.AUTH_REQUEST ) )
+        {
+            log.debug( &quot;Auth request received [{}]&quot;, message );
+            handleAuthRequest( ctx );
+        }
+        else if ( contentType.equals( Value.TEXT_DISCONNECT_NOTICE ) )
+        {
+            log.debug( &quot;Disconnect notice received [{}]&quot;, message );
+            handleDisconnectionNotice();
+        }
+        else
+        {
+            log.warn( &quot;Unexpected message content type [{}]&quot;, contentType );
+        }
+    }
+
+    protected abstract void handleEslEvent( ChannelHandlerContext ctx, EslEvent event );
+
+    protected abstract void handleAuthRequest( ChannelHandlerContext ctx );
+
+    protected abstract void handleDisconnectionNotice();
+    
+    private static class SyncCallback
+    {
+        private static final Logger log = LoggerFactory.getLogger( SyncCallback.class );
+        private final CountDownLatch latch = new CountDownLatch( 1 );
+        private EslMessage response;
+
+        /**
+         * Block waiting for the countdown latch to be released, then return the 
+         * associated response object.
+         * @return
+         */
+        EslMessage get()
+        {
+            try
+            {
+                log.trace( &quot;awaiting latch ... &quot; );
+                latch.await();
+            }
+            catch ( InterruptedException e )
+            {
+                throw new RuntimeException( e );
+            }
+            
+            log.trace( &quot;returning response [{}]&quot;, response );
+            return response;
+        }
+
+        /**
+         * Attach this response to the callback and release the countdown latch.
+         * @param response
+         */
+        void handle( EslMessage response )
+        {
+            this.response = response;
+            log.trace( &quot;releasing latch for response [{}]&quot;, response );
+            latch.countDown();
+        }
+    }
+
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/AbstractEslClientHandler.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinternalHeaderParserjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/HeaderParser.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/HeaderParser.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/HeaderParser.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,98 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.internal;
+
+/**
+ * This parser provides a static helper method to split a standard Header field
+ * into the name and value parts.
+ * &lt;p/&gt;
+ * This code was copied from the splitHeader() method in the 
+ * &lt;code&gt;org.jboss.netty.handler.codec.http.HttpMessageDecoder&lt;/code&gt; class, which
+ * is licensed under the Apache License version 2. Original author: Trustin Lee.
+ *  
+ * @author         Trustin Lee
+ * @author   david varnes
+ */
+public class HeaderParser
+{
+    /**
+     * Split a header in the form 
+     * &lt;pre&gt;
+     *   Header-Name: Some_header-value
+     * &lt;/pre&gt;
+     * into a String array.
+     * 
+     * @param  sb the string header to parse
+     * @return a String[] array with header name at 0 and header value at 1
+     */
+    public static String[] splitHeader(String sb) {
+        final int length = sb.length();
+        int nameStart;
+        int nameEnd;
+        int colonEnd;
+        int valueStart;
+        int valueEnd;
+
+        nameStart = findNonWhitespace(sb, 0);
+        for (nameEnd = nameStart; nameEnd &lt; length; nameEnd ++) {
+            char ch = sb.charAt(nameEnd);
+            if (ch == ':' || Character.isWhitespace(ch)) {
+                break;
+            }
+        }
+
+        for (colonEnd = nameEnd; colonEnd &lt; length; colonEnd ++) {
+            if (sb.charAt(colonEnd) == ':') {
+                colonEnd ++;
+                break;
+            }
+        }
+
+        valueStart = findNonWhitespace(sb, colonEnd);
+        if (valueStart == length) {
+            return new String[] {
+                    sb.substring(nameStart, nameEnd),
+                    &quot;&quot;
+            };
+        }
+
+        valueEnd = findEndOfString(sb);
+        return new String[] {
+                sb.substring(nameStart, nameEnd),
+                sb.substring(valueStart, valueEnd)
+        };
+    }
+
+    private static int findNonWhitespace(String sb, int offset) {
+        int result;
+        for (result = offset; result &lt; sb.length(); result ++) {
+            if (!Character.isWhitespace(sb.charAt(result))) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    private static int findEndOfString(String sb) {
+        int result;
+        for (result = sb.length(); result &gt; 0; result --) {
+            if (!Character.isWhitespace(sb.charAt(result - 1))) {
+                break;
+            }
+        }
+        return result;
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/HeaderParser.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinternalIEslProtocolListenerjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/IEslProtocolListener.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/IEslProtocolListener.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/IEslProtocolListener.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.internal;
+
+import org.freeswitch.esl.client.inbound.Client;
+import org.freeswitch.esl.client.transport.CommandResponse;
+import org.freeswitch.esl.client.transport.event.EslEvent;
+
+/**
+ * End users of the {@link Client} should not need to use this class. 
+ * &lt;/p&gt;
+ * Allow client implementations to observe events arriving from the server.
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public interface IEslProtocolListener
+{
+    void authResponseReceived( CommandResponse response );
+    
+    void eventReceived( EslEvent event );
+    
+    void disconnected();
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/IEslProtocolListener.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinternaldebugChannelEventRunnablejava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/debug/ChannelEventRunnable.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/debug/ChannelEventRunnable.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/debug/ChannelEventRunnable.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,87 @@
</span><ins>+package org.freeswitch.esl.client.internal.debug;
+/*
+ * Copyright 2009 Red Hat, Inc.
+ *
+ * Red Hat licenses this file to you under the Apache License, version 2.0
+ * (the &quot;License&quot;); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import java.util.concurrent.Executor;
+
+import org.jboss.netty.channel.ChannelEvent;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.util.EstimatableObjectWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * a {@link Runnable} which sends the specified {@link ChannelEvent} upstream.
+ * Most users will not see this type at all because it is used by
+ * {@link Executor} implementors only
+ *
+ * @author The Netty Project (netty-dev@lists.jboss.org)
+ * @author Trustin Lee (tlee@redhat.com)
+ *
+ * @version $Rev: 1685 $, $Date: 2009-08-28 16:15:49 +0900 (금, 28 8 2009) $
+ *
+ */
+public class ChannelEventRunnable implements Runnable, EstimatableObjectWrapper {
+    
+    private final Logger log = LoggerFactory.getLogger( this.getClass() );
+    private final ChannelHandlerContext ctx;
+    private final ChannelEvent e;
+    volatile int estimatedSize;
+
+    /**
+     * Creates a {@link Runnable} which sends the specified {@link ChannelEvent}
+     * upstream via the specified {@link ChannelHandlerContext}.
+     */
+    public ChannelEventRunnable(ChannelHandlerContext ctx, ChannelEvent e) {
+        this.ctx = ctx;
+        this.e = e;
+    }
+
+    /**
+     * Returns the {@link ChannelHandlerContext} which will be used to
+     * send the {@link ChannelEvent} upstream.
+     */
+    public ChannelHandlerContext getContext() {
+        return ctx;
+    }
+
+    /**
+     * Returns the {@link ChannelEvent} which will be sent upstream.
+     */
+    public ChannelEvent getEvent() {
+        return e;
+    }
+
+    /**
+     * Sends the event upstream.
+     */
+    public void run() {
+//        log.info( &quot;Sending [{}] upstream in [{}]&quot;, e, ctx );
+        try
+        {
+            ctx.sendUpstream(e);
+        }
+        catch ( Throwable t )
+        {
+            log.error( &quot;Caught --&gt;&quot;, t );
+        }
+    }
+
+    public Object unwrap() {
+        return e;
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/debug/ChannelEventRunnable.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientinternaldebugExecutionHandlerjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/debug/ExecutionHandler.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/debug/ExecutionHandler.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/debug/ExecutionHandler.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,118 @@
</span><ins>+package org.freeswitch.esl.client.internal.debug;
+
+/*
+ * Copyright 2009 Red Hat, Inc.
+ *
+ * Red Hat licenses this file to you under the Apache License, version 2.0
+ * (the &quot;License&quot;); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.concurrent.Executor;
+
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelDownstreamHandler;
+import org.jboss.netty.channel.ChannelEvent;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineCoverage;
+import org.jboss.netty.channel.ChannelState;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.ChannelUpstreamHandler;
+import org.jboss.netty.util.ExternalResourceReleasable;
+import org.jboss.netty.util.internal.ExecutorUtil;
+
+/**
+ * Forwards an upstream {@link ChannelEvent} to an {@link Executor}.
+ * &lt;p&gt;
+ * You can implement various thread model by adding this handler to a
+ * {@link ChannelPipeline}.  The most common use case of this handler is to
+ * add a {@link ExecutionHandler} which was specified with
+ * {@link OrderedMemoryAwareThreadPoolExecutor}:
+ * &lt;pre&gt;
+ * ChannelPipeline pipeline = ...;
+ * pipeline.addLast(&quot;decoder&quot;, new MyProtocolDecoder());
+ * pipeline.addLast(&quot;encoder&quot;, new MyProtocolEncoder());
+ *
+ * // HERE
+ * &lt;strong&gt;pipeline.addLast(&quot;executor&quot;, new {@link ExecutionHandler}(new {@link OrderedMemoryAwareThreadPoolExecutor}(16, 1048576, 1048576)));&lt;/strong&gt;
+ *
+ * pipeline.addLast(&quot;handler&quot;, new MyBusinessLogicHandler());
+ * &lt;/pre&gt;
+ * to utilize more processors to handle {@link ChannelEvent}s.  You can also
+ * use other {@link Executor} implementation than the recommended
+ * {@link OrderedMemoryAwareThreadPoolExecutor}.
+ *
+ * @author The Netty Project (netty-dev@lists.jboss.org)
+ * @author Trustin Lee (tlee@redhat.com)
+ *
+ * @version $Rev: 1685 $, $Date: 2009-08-28 16:15:49 +0900 (금, 28 8 2009) $
+ *
+ * @apiviz.landmark
+ * @apiviz.has java.util.concurrent.ThreadPoolExecutor
+ */
+@ChannelPipelineCoverage(&quot;all&quot;)
+public class ExecutionHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler, ExternalResourceReleasable {
+
+    private final Executor executor;
+
+    /**
+     * Creates a new instance with the specified {@link Executor}.
+     * Specify an {@link OrderedMemoryAwareThreadPoolExecutor} if unsure.
+     */
+    public ExecutionHandler(Executor executor) {
+        if (executor == null) {
+            throw new NullPointerException(&quot;executor&quot;);
+        }
+        this.executor = executor;
+    }
+
+    /**
+     * Returns the {@link Executor} which was specified with the constructor.
+     */
+    public Executor getExecutor() {
+        return executor;
+    }
+
+    /**
+     * Shuts down the {@link Executor} which was specified with the constructor
+     * and wait for its termination.
+     */
+    public void releaseExternalResources() {
+        ExecutorUtil.terminate(getExecutor());
+    }
+
+    public void handleUpstream(
+            ChannelHandlerContext context, ChannelEvent e) throws Exception {
+        executor.execute(new ChannelEventRunnable(context, e));
+    }
+
+    public void handleDownstream(
+            ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
+        if (e instanceof ChannelStateEvent) {
+            ChannelStateEvent cse = (ChannelStateEvent) e;
+            if (cse.getState() == ChannelState.INTEREST_OPS &amp;&amp;
+                (((Integer) cse.getValue()).intValue() &amp; Channel.OP_READ) != 0) {
+
+                // setReadable(true) requested
+                boolean readSuspended = ctx.getAttachment() != null;
+                if (readSuspended) {
+                    // Drop the request silently if MemoryAwareThreadPool has
+                    // set the flag.
+                    e.getFuture().setSuccess();
+                    return;
+                }
+            }
+        }
+
+        ctx.sendDownstream(e);
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/internal/debug/ExecutionHandler.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientoutboundAbstractOutboundClientHandlerjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/AbstractOutboundClientHandler.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/AbstractOutboundClientHandler.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/AbstractOutboundClientHandler.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,72 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.outbound;
+
+import org.freeswitch.esl.client.internal.AbstractEslClientHandler;
+import org.freeswitch.esl.client.transport.event.EslEvent;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipelineCoverage;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.handler.execution.ExecutionHandler;
+
+/**
+ * Specialised {@link AbstractEslClientHandler} that implements the base connecction logic for an 
+ * 'Outbound' FreeSWITCH Event Socket connection.  The responsibilities for this class are:
+ * &lt;/p&gt;
+ * * To send a 'connect' command when the FreeSWITCH server first establishes a new connection with
+ * the socket client in Outbound mode.  This will result in an incoming {@link EslMessage} that is
+ * transformed into an {@link EslEvent} that sub classes can handle.
+ * &lt;/p&gt;
+ * Note: implementation requirement is that an {@link ExecutionHandler} is placed in the processing 
+ * pipeline prior to this handler. This will ensure that each incoming message is processed in its
+ * own thread (although still guaranteed to be processed in the order of receipt).
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+@ChannelPipelineCoverage( &quot;one&quot; )
+public abstract class AbstractOutboundClientHandler extends AbstractEslClientHandler
+{
+
+    @Override
+    public void channelConnected( ChannelHandlerContext ctx, ChannelStateEvent e ) throws Exception
+    {
+        // Have received a connection from FreeSWITCH server, send connect response
+        log.debug( &quot;Received new connection from server, sending connect message&quot; );
+        
+        EslMessage response = sendSyncSingleLineCommand( ctx.getChannel(), &quot;connect&quot; );
+        // A hack in the message decoder treats most of this incoming message as an event so parse now
+        EslEvent channelDataEvent = new EslEvent( response, true );
+        // Let implementing sub classes choose what to do next
+        handleConnectResponse( ctx, channelDataEvent );
+    }
+
+    protected abstract void handleConnectResponse( ChannelHandlerContext ctx, EslEvent event );
+
+    @Override
+    protected void handleAuthRequest( ChannelHandlerContext ctx )
+    {
+        // This should not happen in outbound mode
+        log.warn( &quot;Auth request received in outbound mode, ignoring&quot; ); 
+    }
+
+    @Override
+    protected void handleDisconnectionNotice()
+    {
+        log.debug( &quot;Received disconnection notice&quot; );
+    }    
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/AbstractOutboundClientHandler.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientoutboundAbstractOutboundPipelineFactoryjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/AbstractOutboundPipelineFactory.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/AbstractOutboundPipelineFactory.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/AbstractOutboundPipelineFactory.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,63 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.outbound;
+
+import org.freeswitch.esl.client.internal.debug.ExecutionHandler;
+import org.freeswitch.esl.client.transport.message.EslMessageDecoder;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
+import org.jboss.netty.handler.codec.string.StringDecoder;
+import org.jboss.netty.handler.codec.string.StringEncoder;
+import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;
+
+/**
+ * &lt;/p&gt;
+ * An abstract factory to assemble a Netty processing pipeline for outbound clients.
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public abstract class AbstractOutboundPipelineFactory implements ChannelPipelineFactory
+{
+    
+    private final ChannelBuffer[] delimiters = 
+        new ChannelBuffer[] { ChannelBuffers.wrappedBuffer( new byte[] { '\n' } ),
+                              ChannelBuffers.wrappedBuffer( new byte[] { '\n', '\n' } ) };
+    
+    public ChannelPipeline getPipeline() throws Exception
+    {
+        ChannelPipeline pipeline = Channels.pipeline(); 
+        // Add the text line codec combination first
+        pipeline.addLast( &quot;framer&quot;, new DelimiterBasedFrameDecoder( 8192, delimiters ) );  
+        pipeline.addLast( &quot;stringDecoder&quot;, new StringDecoder() );
+        pipeline.addLast( &quot;encoder&quot;, new StringEncoder() );
+        pipeline.addLast( &quot;eslMessageDecoder&quot;, new EslMessageDecoder( true ) );
+        // Add an executor to ensure separate thread for each upstream message from here
+        pipeline.addLast( &quot;executor&quot;, new ExecutionHandler( 
+            new OrderedMemoryAwareThreadPoolExecutor( 16, 1048576, 1048576 ) ) );
+
+        // now the outbound client logic
+        pipeline.addLast( &quot;clientHandler&quot;, makeHandler() );
+        
+        return pipeline;
+    }
+
+    protected abstract AbstractOutboundClientHandler makeHandler();
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/AbstractOutboundPipelineFactory.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientoutboundSocketClientjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/SocketClient.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/SocketClient.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/SocketClient.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,83 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.outbound;
+
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelFactory;
+import org.jboss.netty.channel.group.ChannelGroup;
+import org.jboss.netty.channel.group.ChannelGroupFuture;
+import org.jboss.netty.channel.group.DefaultChannelGroup;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Entry point to run a socket client that a running FreeSWITCH Event Socket Library module can
+ * make outbound connections to.
+ * &lt;/p&gt;
+ * This class provides for what the FreeSWITCH documentation refers to as 'Outbound' connections
+ * from the Event Socket module. That is, with reference to the module running on the FreeSWITCH
+ * server, this client accepts an outbound connection from the server module.
+ * &lt;/p&gt;
+ * See http://wiki.freeswitch.org/wiki/Mod_event_socket
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public class SocketClient
+{
+    private final Logger log = LoggerFactory.getLogger( this.getClass() );
+
+    private final ChannelGroup allChannels = new DefaultChannelGroup( &quot;esl-socket-client&quot; );
+    
+    private final int port;
+    private final ChannelFactory channelFactory;
+    private final AbstractOutboundPipelineFactory pipelineFactory;
+    
+    public SocketClient( int port, AbstractOutboundPipelineFactory pipelineFactory )
+    {
+        this.port = port;
+        this.pipelineFactory = pipelineFactory;
+        this.channelFactory =  new NioServerSocketChannelFactory( 
+            Executors.newCachedThreadPool(), 
+            Executors.newCachedThreadPool() ); 
+    }
+    
+    public void start()
+    {
+        ServerBootstrap bootstrap = new ServerBootstrap( channelFactory );
+        
+        bootstrap.setPipelineFactory( pipelineFactory );
+        bootstrap.setOption( &quot;child.tcpNoDelay&quot;, true );
+        bootstrap.setOption( &quot;child.keepAlive&quot;, true );
+        
+        Channel serverChannel = bootstrap.bind( new InetSocketAddress( port ) );
+        allChannels.add( serverChannel );
+        log.info( &quot;SocketClient waiting for connections on port [{}] ...&quot;, port );
+    }
+    
+    public void stop()
+    {
+        ChannelGroupFuture future = allChannels.close();
+        future.awaitUninterruptibly();
+        channelFactory.releaseExternalResources();
+        log.info( &quot;SocketClient stopped&quot; );
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/SocketClient.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientoutboundexampleSimpleHangupOutboundHandlerjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/example/SimpleHangupOutboundHandler.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/example/SimpleHangupOutboundHandler.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/example/SimpleHangupOutboundHandler.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,84 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.outbound.example;
+
+import org.freeswitch.esl.client.outbound.AbstractOutboundClientHandler;
+import org.freeswitch.esl.client.transport.SendMsg;
+import org.freeswitch.esl.client.transport.event.EslEvent;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+import org.freeswitch.esl.client.transport.message.EslHeaders.Name;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+
+/**
+ * Simple example of a handler for outbound connection from FreeSWITCH server.
+ * This class will log some of the FreeSWTICH call channel variables and 
+ * then hangup the call.  
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public class SimpleHangupOutboundHandler extends AbstractOutboundClientHandler
+{
+    
+    @Override
+    protected void handleConnectResponse( ChannelHandlerContext ctx, EslEvent event )
+    {
+        log.info( &quot;Received connect response [{}]&quot;, event );
+        if ( event.getEventName().equalsIgnoreCase( &quot;CHANNEL_DATA&quot; ) )
+        {
+            // this is the response to the initial connect 
+            log.info( &quot;=======================  incoming channel data  =============================&quot; );
+            log.info( &quot;Event-Date-Local: [{}]&quot;, event.getEventDateLocal() );
+            log.info( &quot;Unique-ID: [{}]&quot;, event.getEventHeaders().get( &quot;Unique-ID&quot; ) );
+            log.info( &quot;Channel-ANI: [{}]&quot;, event.getEventHeaders().get( &quot;Channel-ANI&quot; ) );
+            log.info( &quot;Answer-State: [{}]&quot;, event.getEventHeaders().get( &quot;Answer-State&quot; ) );
+            log.info( &quot;Caller-Destination-Number: [{}]&quot;, event.getEventHeaders().get( &quot;Caller-Destination-Number&quot; ) );
+            log.info( &quot;=======================  = = = = = = = = = = =  =============================&quot; );
+            
+            // now hangup the call
+            hangupCall( ctx.getChannel() );
+        }
+        else
+        {
+            throw new IllegalStateException( &quot;Unexpected event after connect: [&quot; + event.getEventName() + ']' );
+        }
+    }
+
+    @Override
+    protected void handleEslEvent( ChannelHandlerContext ctx, EslEvent event )
+    {
+        log.info( &quot;Received event [{}]&quot;, event );
+    }
+    
+    private void hangupCall( Channel channel )
+    {
+        SendMsg hangupMsg = new SendMsg();
+        hangupMsg.addCallCommand( &quot;execute&quot; );
+        hangupMsg.addExecuteAppName( &quot;hangup&quot; );
+        
+        EslMessage response = sendSyncMultiLineCommand( channel, hangupMsg.getMsgLines() );
+        
+        if ( response.getHeaderValue( Name.REPLY_TEXT ).startsWith( &quot;+OK&quot; ) )
+        {
+            log.info( &quot;Call hangup successful&quot; );
+        }
+        else
+        {
+            
+        }
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/example/SimpleHangupOutboundHandler.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclientoutboundexampleSimpleHangupPipelineFactoryjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/example/SimpleHangupPipelineFactory.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/example/SimpleHangupPipelineFactory.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/example/SimpleHangupPipelineFactory.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.outbound.example;
+
+import org.freeswitch.esl.client.outbound.AbstractOutboundClientHandler;
+import org.freeswitch.esl.client.outbound.AbstractOutboundPipelineFactory;
+
+/**
+ * Factory for the simple hangup handler
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public class SimpleHangupPipelineFactory extends AbstractOutboundPipelineFactory
+{
+
+    @Override
+    protected AbstractOutboundClientHandler makeHandler()
+    {
+        return new SimpleHangupOutboundHandler();
+    }
+
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/outbound/example/SimpleHangupPipelineFactory.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransportCommandResponsejava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/CommandResponse.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/CommandResponse.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/CommandResponse.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,73 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.transport;
+
+import org.freeswitch.esl.client.transport.message.EslMessage;
+import org.freeswitch.esl.client.transport.message.EslHeaders.Name;
+
+/**
+ * Result object to carry the results of a command sent to the FreeSWITCH Event Socket.
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public class CommandResponse
+{
+    private final String command;
+    private final String replyText;
+    private final EslMessage response;
+    private final boolean success;
+    
+    public CommandResponse( String command, EslMessage response )
+    {
+        this.command = command;
+        this.response = response;
+        this.replyText = response.getHeaderValue( Name.REPLY_TEXT );
+        this.success = replyText.startsWith( &quot;+OK&quot; );
+    }
+    
+    /**
+     * @return the original command sent to the server
+     */
+    public String getCommand()
+    {
+        return command;
+    }
+    
+    /**
+     * @return true if and only if the response Reply-Text line starts with &quot;+OK&quot;
+     */
+    public boolean isOk()
+    {
+        return success;
+    }
+    
+    /**
+     * @return the full response Reply-Text line.
+     */
+    public String getReplyText()
+    {
+        return replyText;
+    }
+    
+    /**
+     * @return {@link EslMessage} the full response from the server 
+     */
+    public EslMessage getResponse()
+    {
+        return response;
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/CommandResponse.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransportSendMsgjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/SendMsg.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/SendMsg.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/SendMsg.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,64 @@
</span><ins>+package org.freeswitch.esl.client.transport;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SendMsg
+{
+    private final List&lt;String&gt; msgLines = new ArrayList&lt;String&gt;();
+    
+    public SendMsg()
+    {
+        msgLines.add( &quot;sendmsg&quot; );
+    }
+    
+    public SendMsg( String uuid )
+    {
+        msgLines.add( &quot;sendmsg &quot; + uuid );
+    }
+    
+    public void addCallCommand( String command )
+    {
+        msgLines.add( &quot;call-command: &quot; + command );
+    }
+    
+    public void addExecuteAppName( String appName )
+    {
+        msgLines.add( &quot;execute-app-name: &quot; + appName );
+    }
+    
+    public void addExecuteAppArg( String arg )
+    {
+        msgLines.add( &quot;execute-app-arg: &quot; + arg );
+    }
+    
+    public void addLoops( int count )
+    {
+        msgLines.add( &quot;loops: &quot; + count );
+    }
+
+    public void addHangupCause( String cause )
+    {
+        msgLines.add( &quot;hangup-cause: &quot; + cause );
+    }
+
+    public void addNomediaUuid( String info )
+    {
+        msgLines.add( &quot;nomedia-uuid: &quot; + info );
+    }
+    
+    public void addEventLock()
+    {
+        msgLines.add( &quot;event-lock: true&quot; );
+    }
+    
+    public void addGenericLine( String name, String value )
+    {
+        msgLines.add( name + &quot;: &quot; + value );
+    }
+    
+    public List&lt;String&gt; getMsgLines()
+    {
+        return msgLines;
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/SendMsg.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransporteventEslEventjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/event/EslEvent.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/event/EslEvent.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/event/EslEvent.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,234 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.transport.event;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.freeswitch.esl.client.internal.HeaderParser;
+import org.freeswitch.esl.client.transport.message.EslHeaders;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+import org.freeswitch.esl.client.transport.message.EslHeaders.Name;
+import org.freeswitch.esl.client.transport.message.EslHeaders.Value;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * FreeSWITCH Event Socket events are decoded into this data object.
+ * &lt;/p&gt;
+ * An ESL event is modelled as a collection of text lines. An event always has several eventHeader
+ * lines, and optionally may have some eventBody lines.  In addition the messageHeaders of the 
+ * original containing {@link EslMessage} which carried the event are also available. 
+ * &lt;/p&gt;
+ * The eventHeader lines are parsed and cached in a map keyed by the eventHeader name string. An event
+ * is always expected to have an &quot;Event-Name&quot; eventHeader. Commonly used eventHeader names are coded
+ * in {@link EslEventHeaderNames}&lt;/br&gt;
+ * Any eventBody lines are cached in a list.&lt;/br&gt;
+ * The messageHeader lines from the original message are cached in a map keyed by {@link EslHeaders.Name}.
+ *  
+ * @author  david varnes
+ * @version $Id$
+ * @see EslEventHeaderNames
+ */
+public class EslEvent 
+{
+    private final Logger log = LoggerFactory.getLogger( this.getClass() );
+    
+    private final Map&lt;Name,String&gt; messageHeaders;
+    private final Map&lt;String,String&gt; eventHeaders;
+    private final List&lt;String&gt; eventBody;
+    private boolean decodeEventHeaders = true;
+    
+    public EslEvent( EslMessage rawMessage )
+    {
+        this( rawMessage, false );
+    }
+    
+    public EslEvent( EslMessage rawMessage, boolean parseCommandReply )
+    {
+        messageHeaders = rawMessage.getHeaders();
+        eventHeaders = new HashMap&lt;String,String&gt;( rawMessage.getBodyLines().size() );
+        eventBody = new ArrayList&lt;String&gt;();
+        // plain or xml body
+        if ( rawMessage.getContentType().equals( Value.TEXT_EVENT_PLAIN ) )
+        {
+            parsePlainBody( rawMessage.getBodyLines() );
+        }
+        else if ( rawMessage.getContentType().equals( Value.TEXT_EVENT_XML ) )
+        {
+            throw new IllegalStateException( &quot;XML events are not yet supported&quot; );
+        }
+        else if ( rawMessage.getContentType().equals( Value.COMMAND_REPLY ) &amp;&amp; parseCommandReply )
+        {
+            parsePlainBody( rawMessage.getBodyLines() );
+        }
+        else
+        {
+            throw new IllegalStateException( &quot;Unexpected EVENT content-type: &quot; + 
+                rawMessage.getContentType() );
+        }
+    }
+
+    /**
+     * The message headers of the original ESL message from which this event was decoded.
+     * The message headers are stored in a map keyed by {@link EslHeaders.Name}. The string mapped value 
+     * is the parsed content of the header line (ie, it does not include the header name).
+     *  
+     * @return map of header values
+     */
+    public Map&lt;Name,String&gt; getMessageHeaders()
+    {
+        return messageHeaders;
+    }
+
+    /**
+     * The event headers of this event. The headers are parsed and stored in a map keyed by the string 
+     * name of the header, and the string mapped value is the parsed content of the event header line 
+     * (ie, it does not include the header name).
+     *  
+     * @return map of event header values
+     */
+    public Map&lt;String, String&gt; getEventHeaders()
+    {
+        return eventHeaders;
+    }
+    
+    /**
+     * Any event body lines that were present in the event.
+     * 
+     * @return list of decoded event body lines, may be an empty list.
+     */
+    public List&lt;String&gt; getEventBodyLines()
+    {
+        return eventBody;
+    }
+    
+    /**
+     * Convenience method.
+     * 
+     * @return the string value of the event header &quot;Event-Name&quot;
+     */
+    public String getEventName()
+    {
+        return getEventHeaders().get( EslEventHeaderNames.EVENT_NAME ); 
+    }
+    
+    /**
+     * Convenience method.
+     * 
+     * @return long value of the event header &quot;Event-Date-Timestamp&quot;
+     */
+    public long getEventDateTimestamp()
+    {
+        return Long.valueOf( getEventHeaders().get( EslEventHeaderNames.EVENT_DATE_TIMESTAMP ) );
+    }
+
+    /**
+     * Convenience method.
+     * 
+     * @return long value of the event header &quot;Event-Date-Local&quot;
+     */
+    public String getEventDateLocal()
+    {
+        return getEventHeaders().get( EslEventHeaderNames.EVENT_DATE_LOCAL );
+    }
+
+    /**
+     * Convenience method.
+     * 
+     * @return long value of the event header &quot;Event-Date-GMT&quot;
+     */
+    public String getEventDateGmt()
+    {
+        return getEventHeaders().get( EslEventHeaderNames.EVENT_DATE_GMT );
+    }
+
+    /**
+     * Convenience method.
+     * 
+     * @return true if the eventBody list is not empty.
+     */
+    public boolean hasEventBody()
+    {
+        return ! eventBody.isEmpty();
+    }
+    
+    private void parsePlainBody( final List&lt;String&gt; rawBodyLines )
+    {
+        boolean isEventBody = false;
+        for ( String rawLine : rawBodyLines )
+        {
+            if ( ! isEventBody )
+            {
+                // split the line
+                String[] headerParts = HeaderParser.splitHeader( rawLine );
+                if ( decodeEventHeaders )
+                {
+                    try
+                    {
+                        String decodedValue = URLDecoder.decode( headerParts[1], &quot;UTF-8&quot; );
+                        log.trace( &quot;decoded from: [{}]&quot;, headerParts[1] );
+                        log.trace( &quot;decoded   to: [{}]&quot;, decodedValue );
+                        eventHeaders.put( headerParts[0], decodedValue );
+                    }
+                    catch ( UnsupportedEncodingException e )
+                    {
+                        log.warn( &quot;Could not URL decode [{}]&quot;, headerParts[1] );
+                        eventHeaders.put( headerParts[0], headerParts[1] );
+                    }
+                }
+                else
+                {
+                    eventHeaders.put( headerParts[0], headerParts[1] );
+                }
+                if ( headerParts[0].equals( EslEventHeaderNames.CONTENT_LENGTH ) )
+                {
+                    // the remaining lines will be considered body lines
+                    isEventBody = true;
+                }
+            }
+            else
+            {
+                // ignore blank line (always is one following the content-length
+                if ( rawLine.length() &gt; 0 )
+                {
+                    eventBody.add( rawLine );
+                }
+            }
+        }
+
+    }
+    
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder( &quot;EslEvent: name=[&quot; );
+        sb.append( getEventName() );
+        sb.append( &quot;] headers=&quot; );
+        sb.append( messageHeaders.size() );
+        sb.append( &quot;, eventHeaders=&quot; );
+        sb.append( eventHeaders.size() );
+        sb.append( &quot;, eventBody=&quot; );
+        sb.append( eventBody.size() );
+        sb.append( &quot; lines.&quot; );
+        
+        return sb.toString();
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/event/EslEvent.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransporteventEslEventHeaderNamesjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/event/EslEventHeaderNames.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/event/EslEventHeaderNames.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/event/EslEventHeaderNames.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,87 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.transport.event;
+
+/**
+ * Container class for some commonly used ESL event header names (note there are many more!).
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public class EslEventHeaderNames
+{
+    /**
+     * {@code &quot;Event-Name&quot;}
+     */
+    public static final String EVENT_NAME = &quot;Event-Name&quot;;
+    /**
+     * {@code &quot;Event-Date-Local&quot;}
+     */
+    public static final String EVENT_DATE_LOCAL = &quot;Event-Date-Local&quot;;
+    /**
+     * {@code &quot;Event-Date-GMT&quot;}
+     */
+    public static final String EVENT_DATE_GMT = &quot;Event-Date-GMT&quot;;
+    /**
+     * {@code &quot;Event-Date-Timestamp&quot;}
+     */
+    public static final String EVENT_DATE_TIMESTAMP = &quot;Event-Date-Timestamp&quot;;
+    /**
+     * {@code &quot;Event-Calling-File&quot;}
+     */
+    public static final String EVENT_CALLING_FILE = &quot;Event-Calling-File&quot;;
+    /**
+     * {@code &quot;Event-Calling-Function&quot;}
+     */
+    public static final String EVENT_CALLING_FUNCTION = &quot;Event-Calling-Function&quot;;
+    /**
+     * {@code &quot;Event-Calling-Line-Number&quot;}
+     */
+    public static final String EVENT_CALLING_LINE_NUMBER = &quot;Event-Calling-Line-Number&quot;;
+    /**
+     * {@code &quot;FreeSWITCH-Hostname&quot;}
+     */
+    public static final String FREESWITCH_HOSTNAME = &quot;FreeSWITCH-Hostname&quot;;
+    /**
+     * {@code &quot;FreeSWITCH-IPv4&quot;}
+     */
+    public static final String FREESWITCH_IPV4 = &quot;FreeSWITCH-IPv4&quot;;
+    /**
+     * {@code &quot;FreeSWITCH-IPv6&quot;}
+     */
+    public static final String FREESWITCH_IPV6 = &quot;FreeSWITCH-IPv6&quot;;
+    /**
+     * {@code &quot;Core-UUID&quot;}
+     */
+    public static final String CORE_UUID = &quot;Core-UUID&quot;;
+    /**
+     * {@code &quot;Content-Length&quot;}
+     */
+    public static final String CONTENT_LENGTH = &quot;Content-Length&quot;;
+    /**
+     * {@code &quot;Job-Command&quot;}
+     */
+    public static final String JOB_COMMAND = &quot;Job-Command&quot;;
+    /**
+     * {@code &quot;Job-UUID&quot;}
+     */
+    public static final String JOB_UUID = &quot;Job-UUID&quot;;
+
+    private EslEventHeaderNames()
+    {
+        /* private class */
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/event/EslEventHeaderNames.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransportmessageEslHeadersjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslHeaders.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslHeaders.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslHeaders.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,139 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.transport.message;
+
+/**
+ * Container class for enumeration of ESL message header names, and some commonly used 
+ * header string values.
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+public class EslHeaders
+{
+    /**
+     * Standard ESL header names.
+     * &lt;/p&gt;
+     * Note this enum will need to be kept in synch with any new headers introduced on the server side.
+     * 
+     * @author david varnes 
+     * @version $Id$
+     */
+    public enum Name
+    {
+        /*
+         *  Minor optimization - put most often used headers at the top for fastest resolution
+         *  in static fromLiteral().  
+         */
+        
+        /**
+         * {@code &quot;Content-Type&quot;}
+         */
+        CONTENT_TYPE( &quot;Content-Type&quot; ),
+        /**
+         * {@code &quot;Content-Length&quot;}
+         */
+        CONTENT_LENGTH( &quot;Content-Length&quot; ),
+        /**
+         * {@code &quot;Reply-Text&quot;}
+         */
+        REPLY_TEXT( &quot;Reply-Text&quot; ),
+        /**
+         * {@code &quot;Job-UUID&quot;}
+         */
+        JOB_UUID( &quot;Job-UUID&quot; ),
+        /**
+         * {@code &quot;Socket-Mode&quot;}
+         */
+        SOCKET_MODE( &quot;Socket-Mode&quot; ),
+        /**
+         * {@code &quot;Control&quot;}
+         */
+        Control( &quot;Control&quot; ),
+        ;
+        
+        private final String literal;
+        
+        private Name( String literal )
+        {
+            this.literal = literal;
+        }
+        
+        public String literal()
+        {
+            return literal;
+        }
+        
+        public static Name fromLiteral( String literal )
+        {
+            for ( Name name : values() )
+            {
+                if ( name.literal.equalsIgnoreCase( literal ) )
+                {
+                    return name;
+                }
+            }
+            
+            return null;
+        }
+    }
+    
+    /**
+     * Some common ESL header values. These are provided as a convenience for commonly used values.
+     * &lt;/p&gt;
+     * This values are not coded as an enum to allow for the very large range of possible values,
+     * since they are just Strings.
+     *
+     * @author david varnes
+     * @version $Id$
+     */
+    public static final class Value 
+    {
+        /**
+         * {@code &quot;+OK&quot;}
+         */
+        public static final String OK = &quot;+OK&quot;;
+        /**
+         * {@code &quot;auth/request&quot;}
+         */
+        public static final String AUTH_REQUEST = &quot;auth/request&quot;;
+        /**
+         * {@code &quot;api/response&quot;}
+         */
+        public static final String API_RESPONSE = &quot;api/response&quot;;
+        /**
+         * {@code &quot;command/reply&quot;}
+         */
+        public static final String COMMAND_REPLY = &quot;command/reply&quot;;
+        /**
+         * {@code &quot;text/event-plain&quot;}
+         */
+        public static final String TEXT_EVENT_PLAIN = &quot;text/event-plain&quot;;
+        /**
+         * {@code &quot;text/event-xml&quot;}
+         */
+        public static final String TEXT_EVENT_XML = &quot;text/event-xml&quot;;
+        /**
+         * {@code &quot;text/disconnect-notice&quot;}
+         */
+        public static final String TEXT_DISCONNECT_NOTICE = &quot;text/disconnect-notice&quot;;
+        /**
+         * {@code &quot;-ERR invalid&quot;}
+         */
+        public static final String ERR_INVALID = &quot;-ERR invalid&quot;;
+    }
+    
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslHeaders.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransportmessageEslMessagejava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslMessage.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslMessage.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslMessage.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,188 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.transport.message;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.freeswitch.esl.client.transport.message.EslHeaders.Name;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Basic FreeSWITCH Event Socket messages from the server are decoded into this data object.
+ * &lt;/p&gt;
+ * An ESL message is modelled as text lines.  A message always has one or more header lines, and 
+ * optionally may have some body lines.
+ * &lt;p/&gt;
+ * Header lines are parsed and cached in a map keyed by the {@link EslHeaders.Name} enum.  A message
+ * is always expected to have a &quot;Content-Type&quot; header&lt;/br&gt;
+ * Any Body lines are cached in a list.
+ * 
+ * @author  david varnes
+ * @version $Id$
+ * @see EslHeaders.Name
+ */
+public class EslMessage
+{
+    private final Logger log = LoggerFactory.getLogger( this.getClass() );
+    
+    private final Map&lt;Name,String&gt; headers = new HashMap&lt;Name,String&gt;();
+    private final List&lt;String&gt; body = new ArrayList&lt;String&gt;();
+    
+    private Integer contentLength = null;
+    private int receivedContentLength = 0;
+
+    /**
+     * All the received message headers in a map keyed by {@link EslHeaders.Name}. The string mapped value 
+     * is the parsed content of the header line (ie, it does not include the header name).
+     *  
+     * @return map of header values
+     */
+    public Map&lt;Name,String&gt; getHeaders()
+    {
+        return headers;
+    }
+
+    /**
+     * Convenience method
+     * 
+     * @param headerName as a {@link EslHeaders.Name}
+     * @return true if an only if there is a header entry with the supplied header name 
+     */
+    public boolean hasHeader( Name headerName )
+    {
+        return headers.containsKey( headerName );
+    }
+
+    /**
+     * Convenience method
+     * 
+     * @param headerName as a {@link EslHeaders.Name}
+     * @return same as getHeaders().get( headerName )
+     */
+    public String getHeaderValue( Name headerName )
+    {
+        return headers.get( headerName );
+    }
+    
+    /**
+     * Convenience method
+     * 
+     * @return true if and only if a header exists with name &quot;Content-Length&quot; 
+     */
+    public boolean hasContentLength()
+    {
+        return headers.containsKey( Name.CONTENT_LENGTH );
+    }
+    
+    /**
+     * Convenience method
+     * 
+     * @return integer value of header with name &quot;Content-Length&quot;
+     */
+    public Integer getContentLength()
+    {
+        if ( contentLength != null )
+        {
+            return contentLength;
+        }
+        if ( hasContentLength() )
+        {
+            contentLength = Integer.valueOf( headers.get( Name.CONTENT_LENGTH) );
+        }
+        return contentLength;
+    }
+    
+    /**
+     * Convenience method
+     * 
+     * @return header value of header with name &quot;Content-Type&quot;
+     */
+    public String getContentType()
+    {
+        return headers.get( Name.CONTENT_TYPE );
+    }
+
+    /**
+     * Any received message body lines
+     * 
+     * @return list with a string for each line received, may be an empty list
+     */
+    public List&lt;String&gt; getBodyLines()
+    {
+        return body;
+    }
+    
+    /**
+     * Used by the {@link EslMessageDecoder}.
+     * 
+     * @param name
+     * @param value
+     */
+    void addHeader( Name name, String value )
+    {
+        log.debug( &quot;adding header [{}] [{}]&quot;, name, value );
+        headers.put( name, value );
+    }
+    
+    /**
+     * Used by the {@link EslMessageDecoder}
+     * 
+     * @param line
+     */
+    void addBodyLine( String line )
+    {
+        if ( line == null )
+        {
+            return;
+        }
+        receivedContentLength += ( line.length() + 1 );
+        // ignore empty lines (signals the end of a body section)
+        if ( line.length() &gt; 0 )
+        {
+            body.add( line );
+        }
+    }
+
+    /**
+     * Used by the {@link EslMessageDecoder}
+     * 
+     * @return true if receivedContentLength &lt; contentLength
+     */
+    boolean waitingForContent()
+    {
+        log.debug( &quot;received [{}], expecting [{}]&quot;, receivedContentLength, getContentLength() );
+        return receivedContentLength &lt; getContentLength();
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder( &quot;EslMessage: contentType=[&quot; );
+        sb.append( getContentType() );
+        sb.append( &quot;] headers=&quot; );
+        sb.append( headers.size() );
+        sb.append( &quot;, body=&quot; );
+        sb.append( body.size() );
+        sb.append( &quot; lines.&quot; );
+        
+        return sb.toString();
+    }
+    
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslMessage.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrcmainjavaorgfreeswitcheslclienttransportmessageEslMessageDecoderjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslMessageDecoder.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslMessageDecoder.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslMessageDecoder.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,142 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.transport.message;
+
+import org.freeswitch.esl.client.internal.HeaderParser;
+import org.freeswitch.esl.client.transport.message.EslHeaders.Name;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipelineCoverage;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
+import org.jboss.netty.channel.UpstreamMessageEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Decoder used by the IO processing pipeline. Client consumers should never need to use
+ * this class.
+ * 
+ * @author  david varnes
+ * @version $Id$
+ */
+@ChannelPipelineCoverage( &quot;one&quot; )
+public class EslMessageDecoder extends SimpleChannelUpstreamHandler
+{
+    private final Logger log = LoggerFactory.getLogger( this.getClass() );
+    
+    private EslMessage currentMessage;
+    private boolean treatUnknownHeadersAsBody = false;
+    
+    public EslMessageDecoder()
+    {
+        
+    }
+    
+    public EslMessageDecoder( boolean treatUnknownHeadersAsBody )
+    {
+        this.treatUnknownHeadersAsBody = treatUnknownHeadersAsBody;
+    }
+    
+    private enum State
+    {
+        NEW_MESSAGE,
+        READ_HEADER_LINE,
+        READ_BODY_LINE,
+    }
+    
+    private State state = State.NEW_MESSAGE;
+    
+    @Override
+    public void messageReceived( ChannelHandlerContext ctx, MessageEvent e ) throws Exception
+    {
+        // Assume this is a decoded string
+        String messageLine = e.getMessage().toString();
+        
+        log.debug( &quot;Received string: [{}]&quot;, e.getMessage() );
+        log.trace( &quot;State [{}]&quot;, state );
+        
+        switch ( state )
+        {
+        case NEW_MESSAGE:
+            if ( messageLine.isEmpty() )
+            {
+                break;
+            }
+            currentMessage = new EslMessage();
+            state = State.READ_HEADER_LINE;
+            // fall-through  
+        case READ_HEADER_LINE:
+            if ( messageLine.isEmpty() )
+            {
+                if ( currentMessage.hasContentLength() )
+                {
+                    //  end of headers - body to come
+                    state = State.READ_BODY_LINE;
+                }
+                else
+                {
+                    // end of message
+                    state = State.NEW_MESSAGE;
+                    // send upstream
+                    UpstreamMessageEvent upstreamEvent = new UpstreamMessageEvent( e.getChannel(), 
+                        currentMessage, e.getRemoteAddress() );
+                    currentMessage = null;
+                    
+                    ctx.sendUpstream( upstreamEvent );
+                }
+            }
+            else
+            {
+                // split the line
+                String[] headerParts = HeaderParser.splitHeader( messageLine );
+                Name headerName = Name.fromLiteral( headerParts[0] );
+                if ( headerName == null )
+                {
+                    if ( treatUnknownHeadersAsBody )
+                    {
+                        // treat this as a body line - note that this will screw up genuine body 
+                        // content-length calculations
+                        currentMessage.addBodyLine( messageLine );
+                    }
+                    else
+                    {
+                        throw new IllegalStateException( &quot;Unhandled ESL header [&quot; + headerParts[0] + ']' );
+                    }
+                }
+                currentMessage.addHeader( headerName, headerParts[1] );
+            }
+            break;
+        case READ_BODY_LINE:
+            // monitor received content compared to expected content-length
+            currentMessage.addBodyLine( messageLine );
+            if ( ! currentMessage.waitingForContent() )
+            {
+                // end of message
+                state = State.NEW_MESSAGE;
+                // send upstream
+                UpstreamMessageEvent upstreamEvent = new UpstreamMessageEvent( e.getChannel(), 
+                    currentMessage, e.getRemoteAddress() );
+                currentMessage = null;
+                
+                ctx.sendUpstream( upstreamEvent );
+            }
+            break;
+        default:
+            break;
+        }
+        
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/main/java/org/freeswitch/esl/client/transport/message/EslMessageDecoder.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrctestjavaorgfreeswitcheslclientinboundClientTestjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/inbound/ClientTest.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/inbound/ClientTest.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/inbound/ClientTest.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,119 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.inbound;
+
+import org.freeswitch.esl.client.IEslEventListener;
+import org.freeswitch.esl.client.inbound.Client;
+import org.freeswitch.esl.client.inbound.InboundConnectionFailure;
+import org.freeswitch.esl.client.transport.event.EslEvent;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ClientTest
+{
+    private final Logger log = LoggerFactory.getLogger( this.getClass() );
+
+    private String host = &quot;localhost&quot;;
+    private int port = 8021;
+    private String password = &quot;ClueCon&quot;; 
+        
+    @Test
+    public void do_connect() throws InterruptedException
+    {
+        Client client = new Client();
+     
+        client.addEventListener( new IEslEventListener()
+        {
+            public void eventReceived( EslEvent event )
+            {
+                log.info( &quot;Event received [{}]&quot;, event );
+            }
+            public void backgroundJobResultReceived( EslEvent event )
+            {
+                log.info( &quot;Background job result received [{}]&quot;, event );
+            }
+            
+        } );
+        
+        log.info( &quot;Client connecting ..&quot; );
+        try
+        {
+            client.connect( host, port, password, 2 );
+        }
+        catch ( InboundConnectionFailure e )
+        {
+            log.error( &quot;Connect failed&quot;, e );
+            return;
+        }
+        log.info( &quot;Client connected ..&quot; );
+        
+//      client.setEventSubscriptions( &quot;plain&quot;, &quot;heartbeat CHANNEL_CREATE CHANNEL_DESTROY BACKGROUND_JOB&quot; );
+        client.setEventSubscriptions( &quot;plain&quot;, &quot;all&quot; );
+        client.addEventFilter( &quot;Event-Name&quot;, &quot;heartbeat&quot; );
+        client.cancelEventSubscriptions();
+        client.setEventSubscriptions( &quot;plain&quot;, &quot;all&quot; );
+        client.addEventFilter( &quot;Event-Name&quot;, &quot;heartbeat&quot; );
+        client.addEventFilter( &quot;Event-Name&quot;, &quot;channel_create&quot; );
+        client.addEventFilter( &quot;Event-Name&quot;, &quot;background_job&quot; );
+//        client.sendSyncCommand( &quot;echo&quot;, &quot;Foo foo bar&quot; );
+//        client.sendSyncCommand( &quot;originate&quot;, &quot;sofia/internal/101@192.168.100.201! sofia/internal/102@192.168.100.201!&quot; );
+        
+//        client.sendSyncApiCommand( &quot;sofia status&quot;, &quot;&quot; );
+        String jobId = client.sendAsyncApiCommand( &quot;status&quot;, &quot;&quot; );
+        log.info( &quot;Job id [{}] for [status]&quot;, jobId );
+        client.sendSyncApiCommand( &quot;version&quot;, &quot;&quot; );
+//        client.sendAsyncApiCommand( &quot;status&quot;, &quot;&quot; );
+//        client.sendSyncApiCommand( &quot;sofia status&quot;, &quot;&quot; );
+//        client.sendAsyncApiCommand( &quot;status&quot;, &quot;&quot; );
+        EslMessage response = client.sendSyncApiCommand( &quot;sofia status&quot;, &quot;&quot; );
+        log.info( &quot;sofia status = [{}]&quot;, response.getBodyLines().get( 3 ) );
+        
+        Thread.sleep( 25000 );
+        client.close();
+    }
+
+    @Test
+    public void do_multi_connects() throws InterruptedException
+    {
+        Client client = new Client();
+        
+        log.info( &quot;Client connecting ..&quot; );
+        try
+        {
+            client.connect( host, port, password, 2 );
+        }
+        catch ( InboundConnectionFailure e )
+        {
+            log.error( &quot;Connect failed&quot;, e );
+            return;
+        }
+        log.info( &quot;Client connected ..&quot; );
+        
+        log.info( &quot;Client connecting ..&quot; );
+        try
+        {
+            client.connect( &quot;127.0.0.1&quot;, 8021, password, 2 );
+        }
+        catch ( InboundConnectionFailure e )
+        {
+            log.error( &quot;Connect failed&quot;, e );
+            return;
+        }
+        log.info( &quot;Client connected ..&quot; );
+    }
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/inbound/ClientTest.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrctestjavaorgfreeswitcheslclientoutboundSocketClientTestjava"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/outbound/SocketClientTest.java (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/outbound/SocketClientTest.java                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/outbound/SocketClientTest.java        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+/*
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.freeswitch.esl.client.outbound;
+
+import org.freeswitch.esl.client.outbound.example.SimpleHangupPipelineFactory;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class SocketClientTest
+{
+    private final Logger log = LoggerFactory.getLogger( this.getClass() );
+
+    @Test
+    public void run_client() throws InterruptedException
+    {
+        log.info( &quot;Test starting ...&quot; );
+
+        
+        SocketClient client = new SocketClient( 8084, new SimpleHangupPipelineFactory() );
+        
+        client.start();
+        
+        Thread.sleep( 45000 );
+
+        client.stop();
+
+        
+        log.info( &quot;Test ended&quot; );
+    }
+    
+}
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/java/org/freeswitch/esl/client/outbound/SocketClientTest.java
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientsrctestresourceslogbacktestxml"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/resources/logback-test.xml (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/resources/logback-test.xml                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/resources/logback-test.xml        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;!--
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+--&gt;
+&lt;configuration&gt;
+
+  &lt;appender name=&quot;STDOUT&quot;
+   class=&quot;ch.qos.logback.core.ConsoleAppender&quot;&gt;
+   &lt;layout class=&quot;ch.qos.logback.classic.PatternLayout&quot;&gt;
+     &lt;Pattern&gt;
+        %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+      &lt;/Pattern&gt;
+    &lt;/layout&gt;
+  &lt;/appender&gt;
+
+  &lt;logger name=&quot;org.freeswitch.esl.client.outbound.example&quot;&gt;
+    &lt;level value=&quot;debug&quot; /&gt;
+  &lt;/logger&gt;
+  &lt;logger name=&quot;org.freeswitch.esl.client.inbound&quot;&gt;
+    &lt;level value=&quot;debug&quot; /&gt;
+  &lt;/logger&gt;
+  &lt;logger name=&quot;org.freeswitch.esl.client.transport.message&quot;&gt;
+    &lt;level value=&quot;info&quot; /&gt;
+  &lt;/logger&gt;
+  &lt;logger name=&quot;org.freeswitch.esl.client&quot;&gt;
+    &lt;level value=&quot;info&quot; /&gt;
+  &lt;/logger&gt;
+
+  &lt;root&gt;
+    &lt;level value=&quot;warn&quot; /&gt;
+    &lt;appender-ref ref=&quot;STDOUT&quot; /&gt;
+  &lt;/root&gt;
+
+&lt;/configuration&gt;
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client/src/test/resources/logback-test.xml
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientexampleclasspath"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/.classpath (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/.classpath                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/.classpath        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;classpath&gt;
+        &lt;classpathentry kind=&quot;src&quot; output=&quot;target/classes&quot; path=&quot;src/main/java&quot;/&gt;
+        &lt;classpathentry excluding=&quot;**&quot; kind=&quot;src&quot; output=&quot;target/classes&quot; path=&quot;src/main/resources&quot;/&gt;
+        &lt;classpathentry kind=&quot;src&quot; output=&quot;target/test-classes&quot; path=&quot;src/test/java&quot;/&gt;
+        &lt;classpathentry excluding=&quot;**&quot; kind=&quot;src&quot; output=&quot;target/test-classes&quot; path=&quot;src/test/resources&quot;/&gt;
+        &lt;classpathentry kind=&quot;con&quot; path=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5&quot;/&gt;
+        &lt;classpathentry kind=&quot;con&quot; path=&quot;org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER&quot;/&gt;
+        &lt;classpathentry kind=&quot;output&quot; path=&quot;target/classes&quot;/&gt;
+&lt;/classpath&gt;
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/.classpath
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientexampleproject"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/.project (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/.project                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/.project        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;projectDescription&gt;
+        &lt;name&gt;org.freeswitch.esl.client.example&lt;/name&gt;
+        &lt;comment&gt;&lt;/comment&gt;
+        &lt;projects&gt;
+        &lt;/projects&gt;
+        &lt;buildSpec&gt;
+                &lt;buildCommand&gt;
+                        &lt;name&gt;org.eclipse.jdt.core.javabuilder&lt;/name&gt;
+                        &lt;arguments&gt;
+                        &lt;/arguments&gt;
+                &lt;/buildCommand&gt;
+                &lt;buildCommand&gt;
+                        &lt;name&gt;org.maven.ide.eclipse.maven2Builder&lt;/name&gt;
+                        &lt;arguments&gt;
+                        &lt;/arguments&gt;
+                &lt;/buildCommand&gt;
+        &lt;/buildSpec&gt;
+        &lt;natures&gt;
+                &lt;nature&gt;org.eclipse.jdt.core.javanature&lt;/nature&gt;
+                &lt;nature&gt;org.maven.ide.eclipse.maven2Nature&lt;/nature&gt;
+        &lt;/natures&gt;
+&lt;/projectDescription&gt;
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/.project
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientorgfreeswitcheslclientexamplepomxml"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/pom.xml (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/pom.xml                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/pom.xml        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,33 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;!--
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+--&gt;
+&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&gt;
+  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
+  &lt;parent&gt;
+    &lt;groupId&gt;org.freeswitch.esl.client&lt;/groupId&gt;
+    &lt;artifactId&gt;esl-client-parent&lt;/artifactId&gt;
+    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
+  &lt;/parent&gt;
+  &lt;artifactId&gt;org.freeswitch.esl.client.example&lt;/artifactId&gt;
+  &lt;name&gt;FreeSWITCH Event Socket Library - Java Client example usage&lt;/name&gt;
+  &lt;dependencies&gt;
+    &lt;dependency&gt;
+      &lt;groupId&gt;org.freeswitch.esl.client&lt;/groupId&gt;
+      &lt;artifactId&gt;org.freeswitch.esl.client&lt;/artifactId&gt;
+      &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
+    &lt;/dependency&gt;
+  &lt;/dependencies&gt;
+&lt;/project&gt;
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/org.freeswitch.esl.client.example/pom.xml
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre></div>
<a id="freeswitchtrunkcontribdvarnesjavaeslclientpomxml"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/dvarnes/java/esl-client/pom.xml (0 => 16127)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/dvarnes/java/esl-client/pom.xml                                (rev 0)
+++ freeswitch/trunk/contrib/dvarnes/java/esl-client/pom.xml        2010-01-03 14:54:19 UTC (rev 16127)
</span><span class="lines">@@ -0,0 +1,96 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;!--
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the &quot;License&quot;); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an &quot;AS IS&quot; BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+--&gt;
+&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&gt;
+  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
+  &lt;groupId&gt;org.freeswitch.esl.client&lt;/groupId&gt;
+  &lt;artifactId&gt;esl-client-parent&lt;/artifactId&gt;
+  &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
+  &lt;packaging&gt;pom&lt;/packaging&gt;
+  &lt;name&gt;FreeSWITCH Event Socket Library - Java Client project&lt;/name&gt;
+  &lt;url&gt;http://www.freeswitch.org&lt;/url&gt;
+  &lt;description&gt;
+    The FreeSWITCH Event Socket Library provides a TCP based control and/or
+    monitoring interface to a running switch.  This project provides a Java
+    client to the ESL.
+  &lt;/description&gt;
+  &lt;organization&gt;
+    &lt;name&gt;FreeSWITCH.org&lt;/name&gt;
+    &lt;url&gt;http://www.freeswitch.org&lt;/url&gt;
+  &lt;/organization&gt;
+  &lt;licenses&gt;
+    &lt;license&gt;
+      &lt;name&gt;Apache License, Version 2.0&lt;/name&gt;
+      &lt;url&gt;http://www.apache.org/licenses/LICENSE-2.0&lt;/url&gt;
+    &lt;/license&gt;
+  &lt;/licenses&gt;
+  &lt;inceptionYear&gt;2009&lt;/inceptionYear&gt;
+  &lt;scm&gt;
+    &lt;connection&gt;scm:svn:http://svn.freeswitch.org/svn/freeswitch/trunk/contrib/dvarnes/java/esl-client&lt;/connection&gt;
+    &lt;developerConnection&gt;scm:svn:http://svn.freeswitch.org/svn/freeswitch/trunk/contrib/dvarnes/java/esl-client&lt;/developerConnection&gt;
+  &lt;/scm&gt;
+  &lt;developers&gt;
+    &lt;developer&gt;
+      &lt;id&gt;dvarnes&lt;/id&gt;
+      &lt;name&gt;david varnes&lt;/name&gt;
+      &lt;email&gt;david at varnes dot net&lt;/email&gt;
+      &lt;timezone&gt;GMT+10&lt;/timezone&gt;
+    &lt;/developer&gt;
+  &lt;/developers&gt;
+  &lt;modules&gt;
+          &lt;module&gt;org.freeswitch.esl.client&lt;/module&gt;
+          &lt;module&gt;org.freeswitch.esl.client.example&lt;/module&gt;
+  &lt;/modules&gt;
+  &lt;build&gt;
+    &lt;pluginManagement&gt;
+      &lt;plugins&gt;
+        &lt;plugin&gt;
+          &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
+          &lt;configuration&gt;
+            &lt;source&gt;1.5&lt;/source&gt;
+            &lt;target&gt;1.5&lt;/target&gt;
+          &lt;/configuration&gt;
+        &lt;/plugin&gt;
+      &lt;/plugins&gt;
+    &lt;/pluginManagement&gt;
+    &lt;plugins&gt;
+      &lt;!--  every child project inherits these plugins --&gt;
+      &lt;plugin&gt;
+        &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
+        &lt;configuration&gt;
+          &lt;source&gt;1.5&lt;/source&gt;
+          &lt;target&gt;1.5&lt;/target&gt;
+        &lt;/configuration&gt;
+      &lt;/plugin&gt;
+      &lt;plugin&gt;
+        &lt;artifactId&gt;maven-source-plugin&lt;/artifactId&gt;
+        &lt;version&gt;2.1&lt;/version&gt;
+        &lt;executions&gt;
+          &lt;execution&gt;
+            &lt;id&gt;attach-source&lt;/id&gt;
+            &lt;phase&gt;package&lt;/phase&gt;
+            &lt;goals&gt;
+              &lt;goal&gt;jar&lt;/goal&gt;
+            &lt;/goals&gt;
+            &lt;configuration&gt;
+              &lt;attach&gt;true&lt;/attach&gt;
+            &lt;/configuration&gt;
+          &lt;/execution&gt;
+        &lt;/executions&gt;
+      &lt;/plugin&gt;
+    &lt;/plugins&gt;
+  &lt;/build&gt;  
+&lt;/project&gt;
</ins><span class="cx">Property changes on: freeswitch/trunk/contrib/dvarnes/java/esl-client/pom.xml
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:keywords
</span><span class="cx">   + Id
</span><span class="cx">Name: svn:eol-style
</span><span class="cx">   + native
</span></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>

</body>
</html>