<!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>+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+        <name>org.freeswitch.esl</name>
+        <comment></comment>
+        <projects>
+        </projects>
+        <buildSpec>
+                <buildCommand>
+                        <name>org.maven.ide.eclipse.maven2Builder</name>
+                        <arguments>
+                        </arguments>
+                </buildCommand>
+        </buildSpec>
+        <natures>
+                <nature>org.maven.ide.eclipse.maven2Nature</nature>
+        </natures>
+</projectDescription>
</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>+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+        <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+        <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+        <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+        <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+        <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+        <classpathentry kind="output" path="target/classes"/>
+</classpath>
</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>+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+        <name>org.freeswitch.esl.client.netty</name>
+        <comment></comment>
+        <projects>
+        </projects>
+        <buildSpec>
+                <buildCommand>
+                        <name>org.eclipse.jdt.core.javabuilder</name>
+                        <arguments>
+                        </arguments>
+                </buildCommand>
+                <buildCommand>
+                        <name>org.maven.ide.eclipse.maven2Builder</name>
+                        <arguments>
+                        </arguments>
+                </buildCommand>
+        </buildSpec>
+        <natures>
+                <nature>org.eclipse.jdt.core.javanature</nature>
+                <nature>org.maven.ide.eclipse.maven2Nature</nature>
+        </natures>
+</projectDescription>
</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>+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the "License");
+ * 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 "AS IS" 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.freeswitch.esl.client</groupId>
+ <artifactId>esl-client-parent</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>org.freeswitch.esl.client</artifactId>
+ <name>FreeSWITCH Event Socket Library - Java Client</name>
+ <packaging>bundle</packaging>
+ <build>
+
+ <plugins>
+
+ <!-- this plugin will create the target jar as a correct OSGi bundle -->
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.0.1</version>
+ <extensions>true</extensions>
+ <configuration>
+ <unpackBundle>true</unpackBundle>
+ <instructions>
+ <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+ <Bundle-Version>${project.version}</Bundle-Version>
+ <Bundle-DocURL>http://www.freeswitch.org</Bundle-DocURL>
+ <Import-Package>*</Import-Package>
+ <Export-Package>
+ org.freeswitch.esl.client,
+ org.freeswitch.esl.client.transport.event,
+ org.freeswitch.esl.client.transport.message,
+ </Export-Package>
+ <!-- the debug package is a temporary hack -->
+ <Private-Package>
+ org.freeswitch.esl.client.internal,
+ org.freeswitch.esl.client.debug
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </build>
+ <dependencies>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.5.10</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.netty</groupId>
+ <artifactId>netty</artifactId>
+ <version>3.1.5.GA</version>
+ </dependency>
+
+ <!-- test dependencies -->
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.7</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>0.9.18</version>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+</project>
</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 "License");
+ * 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 "AS IS" 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.
+ * </p>
+ * 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.
+ * </p>
+ * 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.
+ * </p>
+ * 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 "License");
+ * 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 "AS IS" 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.
+ * </p>
+ * 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.
+ * </p>
+ * 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<IEslEventListener> eventListeners = new CopyOnWriteArrayList<IEslEventListener>();
+ private final Executor eventListenerExecutor = Executors.newSingleThreadExecutor(
+ new ThreadFactory()
+ {
+ AtomicInteger threadNumber = new AtomicInteger( 1 );
+ public Thread newThread( Runnable r )
+ {
+ return new Thread( r, "EslEventNotifier-" + threadNumber.getAndIncrement() );
+ }
+ });
+ private final Executor backgroundJobListenerExecutor = Executors.newSingleThreadExecutor(
+ new ThreadFactory()
+ {
+ AtomicInteger threadNumber = new AtomicInteger( 1 );
+ public Thread newThread( Runnable r )
+ {
+ return new Thread( r, "EslBackgroundJobNotifier-" + threadNumber.getAndIncrement() );
+ }
+ });
+
+ private AtomicBoolean authenticatorResponded = new AtomicBoolean( false );
+ private boolean authenticated;
+ private CommandResponse authenticationResponse;
+ private Channel channel;
+
+ public boolean canSend()
+ {
+ return channel != null && channel.isConnected() && 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( "Timeout connecting to " + host + ":" + port );
+ }
+ // Did not timeout
+ channel = future.getChannel();
+ // But may have failed anyway
+ if ( !future.isSuccess() )
+ {
+ log.warn( "Failed to connect to [{}:{}]", host, port );
+ log.warn( " * reason: {}", future.getCause() );
+
+ channel = null;
+ bootstrap.releaseExternalResources();
+
+ throw new InboundConnectionFailure( "Could not connect to " + host + ":" + 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( "Authentication failed: " + authenticationResponse.getReplyText() );
+ }
+ }
+
+ /**
+ * Sends a FreeSWITCH API command to the server and blocks, waiting for an immediate response from the
+ * server.
+ * <p/>
+ * 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 && !command.isEmpty() )
+ {
+ sb.append( "api " );
+ sb.append( command );
+ }
+ if ( arg != null && !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.<p/>
+ * 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 && !command.isEmpty() )
+ {
+ sb.append( "bgapi " );
+ sb.append( command );
+ }
+ if ( arg != null && !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:
+ * <pre>
+ * ALL
+ * CHANNEL_CREATE CHANNEL_DESTROY HEARTBEAT
+ * CUSTOM conference::maintenance
+ * CHANNEL_CREATE CHANNEL_DESTROY CUSTOM conference::maintenance sofia::register sofia::expire
+ * </pre>
+ * Subsequent calls to this method replaces any previous subscriptions that were set.
+ * </p>
+ * 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( "plain" ) )
+ {
+ throw new IllegalStateException( "Only 'plain' event format is supported at present" );
+ }
+
+ checkConnected();
+ InboundClientHandler handler = (InboundClientHandler)channel.getPipeline().getLast();
+ StringBuilder sb = new StringBuilder();
+ if ( format != null && !format.isEmpty() )
+ {
+ sb.append( "event " );
+ sb.append( format );
+ }
+ if ( events != null && !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, "noevents" );
+
+ return new CommandResponse( "noevents", 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.
+ * </p>
+ * 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.
+ * </p>
+ * Example filters:
+ * <pre>
+ * eventHeader valueToFilter
+ * ----------------------------------
+ * Event-Name CHANNEL_EXECUTE
+ * Channel-State CS_NEW
+ * </pre>
+ *
+ * @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 && !eventHeader.isEmpty() )
+ {
+ sb.append( "filter " );
+ sb.append( eventHeader );
+ }
+ if ( valueToFilter != null && !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 && !eventHeader.isEmpty() )
+ {
+ sb.append( "filter delete " );
+ sb.append( eventHeader );
+ }
+ if ( valueToFilter != null && !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 && !level.isEmpty() )
+ {
+ sb.append( "log " );
+ 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, "nolog" );
+
+ return new CommandResponse( "nolog", 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, "exit" );
+
+ return new CommandResponse( "exit", 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( "Auth response success={}, message=[{}]", authenticated, response.getReplyText() );
+ }
+
+ public void eventReceived( final EslEvent event )
+ {
+ log.debug( "Event received [{}]", 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( "BACKGROUND_JOB" ) )
+ {
+ for ( final IEslEventListener listener : eventListeners )
+ {
+ backgroundJobListenerExecutor.execute( new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ listener.backgroundJobResultReceived( event );
+ }
+ catch ( Throwable t )
+ {
+ log.error( "Error caught notifying listener of job result [" + event + ']', t );
+ }
+ }
+ } );
+ }
+ }
+ else
+ {
+ for ( final IEslEventListener listener : eventListeners )
+ {
+ eventListenerExecutor.execute( new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ listener.eventReceived( event );
+ }
+ catch ( Throwable t )
+ {
+ log.error( "Error caught notifying listener of event [" + event + ']', t );
+ }
+ }
+ } );
+ }
+ }
+ }
+
+ public void disconnected()
+ {
+ log.info( "Disconnected .." );
+ }
+ };
+
+ private void checkConnected()
+ {
+ if ( ! canSend() )
+ {
+ throw new IllegalStateException( "Not connected to FreeSWITCH Event Socket" );
+ }
+ }
+}
</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 "License");
+ * 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 "AS IS" 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.
+ * </p>
+ * Specialised {@link AbstractEslClientHandler} that implements the connection logic for an
+ * 'Inbound' FreeSWITCH Event Socket connection. The responsibilities for this class are:
+ * </p>
+ * * To handle the auth request that the FreeSWITCH server will send immediately following a new
+ * connection when mode is Inbound.
+ * </p>
+ * * To signal the observing {@link IEslProtocolListener} (expected to be the Inbound client
+ * implementation when ESL events are received.
+ * </p>
+ * 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( "one" )
+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( "Received event: [{}]", event );
+ listener.eventReceived( event );
+ }
+
+ protected void handleAuthRequest( ChannelHandlerContext ctx )
+ {
+ log.debug( "Auth requested, sending [auth {}]", "*****" );
+ EslMessage response = sendSyncSingleLineCommand( ctx.getChannel(), "auth " + password );
+ log.debug( "Auth response [{}]", response );
+ if ( response.getContentType().equals( Value.COMMAND_REPLY ) )
+ {
+ CommandResponse commandResponse = new CommandResponse( "auth " + password, response );
+ listener.authResponseReceived( commandResponse );
+ }
+ else
+ {
+ log.error( "Bad auth response message [{}]", response );
+ throw new IllegalStateException( "Incorrect auth response" );
+ }
+ }
+
+ @Override
+ protected void handleDisconnectionNotice()
+ {
+ log.debug( "Received disconnection notice" );
+ 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 "License");
+ * 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 "AS IS" 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 "License");
+ * 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 "AS IS" 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.
+ * </p>
+ * 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( "framer", new DelimiterBasedFrameDecoder( 8192, delimiters ) );
+ pipeline.addLast( "stringDecoder", new StringDecoder() );
+ pipeline.addLast( "encoder", new StringEncoder() );
+ pipeline.addLast( "eslMessageDecoder", new EslMessageDecoder() );
+ // Add an executor to ensure separate thread for each upstream message from here
+ pipeline.addLast( "executor", new ExecutionHandler(
+ new OrderedMemoryAwareThreadPoolExecutor( 16, 1048576, 1048576 ) ) );
+
+ // now the inbound client logic
+ pipeline.addLast( "clientHandler", 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 "License");
+ * 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 "AS IS" 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:
+ * </p>
+ * * 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.
+ * </p>
+ * * Concrete sub classes are expected to 'terminate' the Netty IO processing pipeline (ie be the 'last'
+ * handler).
+ * </p>
+ * 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 = "\n\n";
+ public static final String LINE_TERMINATOR = "\n";
+
+ protected final Logger log = LoggerFactory.getLogger( this.getClass() );
+
+ private final Lock syncLock = new ReentrantLock();
+ private final Queue<SyncCallback> syncCallbacks = new ConcurrentLinkedQueue<SyncCallback>();
+
+ @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( "Unexpected message type: " + 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<String> 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( "Missing Job-UUID header in bgapi response" );
+ }
+ }
+
+ protected void handleEslMessage( ChannelHandlerContext ctx, EslMessage message )
+ {
+ log.info( "Received message: [{}]", message );
+ String contentType = message.getContentType();
+
+ if ( contentType.equals( Value.API_RESPONSE ) )
+ {
+ log.debug( "Api response received [{}]", message );
+ syncCallbacks.poll().handle( message );
+ }
+ else if ( contentType.equals( Value.COMMAND_REPLY ) )
+ {
+ log.debug( "Command reply received [{}]", message );
+ syncCallbacks.poll().handle( message );
+ }
+ else if ( contentType.equals( Value.AUTH_REQUEST ) )
+ {
+ log.debug( "Auth request received [{}]", message );
+ handleAuthRequest( ctx );
+ }
+ else if ( contentType.equals( Value.TEXT_DISCONNECT_NOTICE ) )
+ {
+ log.debug( "Disconnect notice received [{}]", message );
+ handleDisconnectionNotice();
+ }
+ else
+ {
+ log.warn( "Unexpected message content type [{}]", 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( "awaiting latch ... " );
+ latch.await();
+ }
+ catch ( InterruptedException e )
+ {
+ throw new RuntimeException( e );
+ }
+
+ log.trace( "returning response [{}]", 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( "releasing latch for response [{}]", 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 "License");
+ * 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 "AS IS" 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.
+ * <p/>
+ * This code was copied from the splitHeader() method in the
+ * <code>org.jboss.netty.handler.codec.http.HttpMessageDecoder</code> 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
+ * <pre>
+ * Header-Name: Some_header-value
+ * </pre>
+ * 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 < length; nameEnd ++) {
+ char ch = sb.charAt(nameEnd);
+ if (ch == ':' || Character.isWhitespace(ch)) {
+ break;
+ }
+ }
+
+ for (colonEnd = nameEnd; colonEnd < length; colonEnd ++) {
+ if (sb.charAt(colonEnd) == ':') {
+ colonEnd ++;
+ break;
+ }
+ }
+
+ valueStart = findNonWhitespace(sb, colonEnd);
+ if (valueStart == length) {
+ return new String[] {
+ sb.substring(nameStart, nameEnd),
+ ""
+ };
+ }
+
+ 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 < 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 > 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 "License");
+ * 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 "AS IS" 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.
+ * </p>
+ * 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 "License"); 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 "AS IS" 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( "Sending [{}] upstream in [{}]", e, ctx );
+ try
+ {
+ ctx.sendUpstream(e);
+ }
+ catch ( Throwable t )
+ {
+ log.error( "Caught -->", 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 "License"); 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 "AS IS" 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}.
+ * <p>
+ * 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}:
+ * <pre>
+ * ChannelPipeline pipeline = ...;
+ * pipeline.addLast("decoder", new MyProtocolDecoder());
+ * pipeline.addLast("encoder", new MyProtocolEncoder());
+ *
+ * // HERE
+ * <strong>pipeline.addLast("executor", new {@link ExecutionHandler}(new {@link OrderedMemoryAwareThreadPoolExecutor}(16, 1048576, 1048576)));</strong>
+ *
+ * pipeline.addLast("handler", new MyBusinessLogicHandler());
+ * </pre>
+ * 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("all")
+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("executor");
+ }
+ 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 &&
+ (((Integer) cse.getValue()).intValue() & 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 "License");
+ * 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 "AS IS" 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:
+ * </p>
+ * * 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.
+ * </p>
+ * 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( "one" )
+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( "Received new connection from server, sending connect message" );
+
+ EslMessage response = sendSyncSingleLineCommand( ctx.getChannel(), "connect" );
+ // 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( "Auth request received in outbound mode, ignoring" );
+ }
+
+ @Override
+ protected void handleDisconnectionNotice()
+ {
+ log.debug( "Received disconnection notice" );
+ }
+}
</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 "License");
+ * 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 "AS IS" 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;
+
+/**
+ * </p>
+ * 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( "framer", new DelimiterBasedFrameDecoder( 8192, delimiters ) );
+ pipeline.addLast( "stringDecoder", new StringDecoder() );
+ pipeline.addLast( "encoder", new StringEncoder() );
+ pipeline.addLast( "eslMessageDecoder", new EslMessageDecoder( true ) );
+ // Add an executor to ensure separate thread for each upstream message from here
+ pipeline.addLast( "executor", new ExecutionHandler(
+ new OrderedMemoryAwareThreadPoolExecutor( 16, 1048576, 1048576 ) ) );
+
+ // now the outbound client logic
+ pipeline.addLast( "clientHandler", 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 "License");
+ * 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 "AS IS" 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.
+ * </p>
+ * 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.
+ * </p>
+ * 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( "esl-socket-client" );
+
+ 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( "child.tcpNoDelay", true );
+ bootstrap.setOption( "child.keepAlive", true );
+
+ Channel serverChannel = bootstrap.bind( new InetSocketAddress( port ) );
+ allChannels.add( serverChannel );
+ log.info( "SocketClient waiting for connections on port [{}] ...", port );
+ }
+
+ public void stop()
+ {
+ ChannelGroupFuture future = allChannels.close();
+ future.awaitUninterruptibly();
+ channelFactory.releaseExternalResources();
+ log.info( "SocketClient stopped" );
+ }
+}
</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 "License");
+ * 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 "AS IS" 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( "Received connect response [{}]", event );
+ if ( event.getEventName().equalsIgnoreCase( "CHANNEL_DATA" ) )
+ {
+ // this is the response to the initial connect
+ log.info( "======================= incoming channel data =============================" );
+ log.info( "Event-Date-Local: [{}]", event.getEventDateLocal() );
+ log.info( "Unique-ID: [{}]", event.getEventHeaders().get( "Unique-ID" ) );
+ log.info( "Channel-ANI: [{}]", event.getEventHeaders().get( "Channel-ANI" ) );
+ log.info( "Answer-State: [{}]", event.getEventHeaders().get( "Answer-State" ) );
+ log.info( "Caller-Destination-Number: [{}]", event.getEventHeaders().get( "Caller-Destination-Number" ) );
+ log.info( "======================= = = = = = = = = = = = =============================" );
+
+ // now hangup the call
+ hangupCall( ctx.getChannel() );
+ }
+ else
+ {
+ throw new IllegalStateException( "Unexpected event after connect: [" + event.getEventName() + ']' );
+ }
+ }
+
+ @Override
+ protected void handleEslEvent( ChannelHandlerContext ctx, EslEvent event )
+ {
+ log.info( "Received event [{}]", event );
+ }
+
+ private void hangupCall( Channel channel )
+ {
+ SendMsg hangupMsg = new SendMsg();
+ hangupMsg.addCallCommand( "execute" );
+ hangupMsg.addExecuteAppName( "hangup" );
+
+ EslMessage response = sendSyncMultiLineCommand( channel, hangupMsg.getMsgLines() );
+
+ if ( response.getHeaderValue( Name.REPLY_TEXT ).startsWith( "+OK" ) )
+ {
+ log.info( "Call hangup successful" );
+ }
+ 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 "License");
+ * 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 "AS IS" 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 "License");
+ * 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 "AS IS" 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( "+OK" );
+ }
+
+ /**
+ * @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 "+OK"
+ */
+ 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<String> msgLines = new ArrayList<String>();
+
+ public SendMsg()
+ {
+ msgLines.add( "sendmsg" );
+ }
+
+ public SendMsg( String uuid )
+ {
+ msgLines.add( "sendmsg " + uuid );
+ }
+
+ public void addCallCommand( String command )
+ {
+ msgLines.add( "call-command: " + command );
+ }
+
+ public void addExecuteAppName( String appName )
+ {
+ msgLines.add( "execute-app-name: " + appName );
+ }
+
+ public void addExecuteAppArg( String arg )
+ {
+ msgLines.add( "execute-app-arg: " + arg );
+ }
+
+ public void addLoops( int count )
+ {
+ msgLines.add( "loops: " + count );
+ }
+
+ public void addHangupCause( String cause )
+ {
+ msgLines.add( "hangup-cause: " + cause );
+ }
+
+ public void addNomediaUuid( String info )
+ {
+ msgLines.add( "nomedia-uuid: " + info );
+ }
+
+ public void addEventLock()
+ {
+ msgLines.add( "event-lock: true" );
+ }
+
+ public void addGenericLine( String name, String value )
+ {
+ msgLines.add( name + ": " + value );
+ }
+
+ public List<String> 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 "License");
+ * 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 "AS IS" 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.
+ * </p>
+ * 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.
+ * </p>
+ * The eventHeader lines are parsed and cached in a map keyed by the eventHeader name string. An event
+ * is always expected to have an "Event-Name" eventHeader. Commonly used eventHeader names are coded
+ * in {@link EslEventHeaderNames}</br>
+ * Any eventBody lines are cached in a list.</br>
+ * 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<Name,String> messageHeaders;
+ private final Map<String,String> eventHeaders;
+ private final List<String> eventBody;
+ private boolean decodeEventHeaders = true;
+
+ public EslEvent( EslMessage rawMessage )
+ {
+ this( rawMessage, false );
+ }
+
+ public EslEvent( EslMessage rawMessage, boolean parseCommandReply )
+ {
+ messageHeaders = rawMessage.getHeaders();
+ eventHeaders = new HashMap<String,String>( rawMessage.getBodyLines().size() );
+ eventBody = new ArrayList<String>();
+ // 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( "XML events are not yet supported" );
+ }
+ else if ( rawMessage.getContentType().equals( Value.COMMAND_REPLY ) && parseCommandReply )
+ {
+ parsePlainBody( rawMessage.getBodyLines() );
+ }
+ else
+ {
+ throw new IllegalStateException( "Unexpected EVENT content-type: " +
+ 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<Name,String> 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<String, String> 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<String> getEventBodyLines()
+ {
+ return eventBody;
+ }
+
+ /**
+ * Convenience method.
+ *
+ * @return the string value of the event header "Event-Name"
+ */
+ public String getEventName()
+ {
+ return getEventHeaders().get( EslEventHeaderNames.EVENT_NAME );
+ }
+
+ /**
+ * Convenience method.
+ *
+ * @return long value of the event header "Event-Date-Timestamp"
+ */
+ public long getEventDateTimestamp()
+ {
+ return Long.valueOf( getEventHeaders().get( EslEventHeaderNames.EVENT_DATE_TIMESTAMP ) );
+ }
+
+ /**
+ * Convenience method.
+ *
+ * @return long value of the event header "Event-Date-Local"
+ */
+ public String getEventDateLocal()
+ {
+ return getEventHeaders().get( EslEventHeaderNames.EVENT_DATE_LOCAL );
+ }
+
+ /**
+ * Convenience method.
+ *
+ * @return long value of the event header "Event-Date-GMT"
+ */
+ 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<String> 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], "UTF-8" );
+ log.trace( "decoded from: [{}]", headerParts[1] );
+ log.trace( "decoded to: [{}]", decodedValue );
+ eventHeaders.put( headerParts[0], decodedValue );
+ }
+ catch ( UnsupportedEncodingException e )
+ {
+ log.warn( "Could not URL decode [{}]", 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() > 0 )
+ {
+ eventBody.add( rawLine );
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder( "EslEvent: name=[" );
+ sb.append( getEventName() );
+ sb.append( "] headers=" );
+ sb.append( messageHeaders.size() );
+ sb.append( ", eventHeaders=" );
+ sb.append( eventHeaders.size() );
+ sb.append( ", eventBody=" );
+ sb.append( eventBody.size() );
+ sb.append( " lines." );
+
+ 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 "License");
+ * 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 "AS IS" 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 "Event-Name"}
+ */
+ public static final String EVENT_NAME = "Event-Name";
+ /**
+ * {@code "Event-Date-Local"}
+ */
+ public static final String EVENT_DATE_LOCAL = "Event-Date-Local";
+ /**
+ * {@code "Event-Date-GMT"}
+ */
+ public static final String EVENT_DATE_GMT = "Event-Date-GMT";
+ /**
+ * {@code "Event-Date-Timestamp"}
+ */
+ public static final String EVENT_DATE_TIMESTAMP = "Event-Date-Timestamp";
+ /**
+ * {@code "Event-Calling-File"}
+ */
+ public static final String EVENT_CALLING_FILE = "Event-Calling-File";
+ /**
+ * {@code "Event-Calling-Function"}
+ */
+ public static final String EVENT_CALLING_FUNCTION = "Event-Calling-Function";
+ /**
+ * {@code "Event-Calling-Line-Number"}
+ */
+ public static final String EVENT_CALLING_LINE_NUMBER = "Event-Calling-Line-Number";
+ /**
+ * {@code "FreeSWITCH-Hostname"}
+ */
+ public static final String FREESWITCH_HOSTNAME = "FreeSWITCH-Hostname";
+ /**
+ * {@code "FreeSWITCH-IPv4"}
+ */
+ public static final String FREESWITCH_IPV4 = "FreeSWITCH-IPv4";
+ /**
+ * {@code "FreeSWITCH-IPv6"}
+ */
+ public static final String FREESWITCH_IPV6 = "FreeSWITCH-IPv6";
+ /**
+ * {@code "Core-UUID"}
+ */
+ public static final String CORE_UUID = "Core-UUID";
+ /**
+ * {@code "Content-Length"}
+ */
+ public static final String CONTENT_LENGTH = "Content-Length";
+ /**
+ * {@code "Job-Command"}
+ */
+ public static final String JOB_COMMAND = "Job-Command";
+ /**
+ * {@code "Job-UUID"}
+ */
+ public static final String JOB_UUID = "Job-UUID";
+
+ 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 "License");
+ * 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 "AS IS" 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.
+ * </p>
+ * 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 "Content-Type"}
+ */
+ CONTENT_TYPE( "Content-Type" ),
+ /**
+ * {@code "Content-Length"}
+ */
+ CONTENT_LENGTH( "Content-Length" ),
+ /**
+ * {@code "Reply-Text"}
+ */
+ REPLY_TEXT( "Reply-Text" ),
+ /**
+ * {@code "Job-UUID"}
+ */
+ JOB_UUID( "Job-UUID" ),
+ /**
+ * {@code "Socket-Mode"}
+ */
+ SOCKET_MODE( "Socket-Mode" ),
+ /**
+ * {@code "Control"}
+ */
+ Control( "Control" ),
+ ;
+
+ 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.
+ * </p>
+ * 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 "+OK"}
+ */
+ public static final String OK = "+OK";
+ /**
+ * {@code "auth/request"}
+ */
+ public static final String AUTH_REQUEST = "auth/request";
+ /**
+ * {@code "api/response"}
+ */
+ public static final String API_RESPONSE = "api/response";
+ /**
+ * {@code "command/reply"}
+ */
+ public static final String COMMAND_REPLY = "command/reply";
+ /**
+ * {@code "text/event-plain"}
+ */
+ public static final String TEXT_EVENT_PLAIN = "text/event-plain";
+ /**
+ * {@code "text/event-xml"}
+ */
+ public static final String TEXT_EVENT_XML = "text/event-xml";
+ /**
+ * {@code "text/disconnect-notice"}
+ */
+ public static final String TEXT_DISCONNECT_NOTICE = "text/disconnect-notice";
+ /**
+ * {@code "-ERR invalid"}
+ */
+ public static final String ERR_INVALID = "-ERR invalid";
+ }
+
+}
</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 "License");
+ * 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 "AS IS" 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.
+ * </p>
+ * An ESL message is modelled as text lines. A message always has one or more header lines, and
+ * optionally may have some body lines.
+ * <p/>
+ * Header lines are parsed and cached in a map keyed by the {@link EslHeaders.Name} enum. A message
+ * is always expected to have a "Content-Type" header</br>
+ * 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<Name,String> headers = new HashMap<Name,String>();
+ private final List<String> body = new ArrayList<String>();
+
+ 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<Name,String> 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 "Content-Length"
+ */
+ public boolean hasContentLength()
+ {
+ return headers.containsKey( Name.CONTENT_LENGTH );
+ }
+
+ /**
+ * Convenience method
+ *
+ * @return integer value of header with name "Content-Length"
+ */
+ 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 "Content-Type"
+ */
+ 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<String> getBodyLines()
+ {
+ return body;
+ }
+
+ /**
+ * Used by the {@link EslMessageDecoder}.
+ *
+ * @param name
+ * @param value
+ */
+ void addHeader( Name name, String value )
+ {
+ log.debug( "adding header [{}] [{}]", 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() > 0 )
+ {
+ body.add( line );
+ }
+ }
+
+ /**
+ * Used by the {@link EslMessageDecoder}
+ *
+ * @return true if receivedContentLength < contentLength
+ */
+ boolean waitingForContent()
+ {
+ log.debug( "received [{}], expecting [{}]", receivedContentLength, getContentLength() );
+ return receivedContentLength < getContentLength();
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder( "EslMessage: contentType=[" );
+ sb.append( getContentType() );
+ sb.append( "] headers=" );
+ sb.append( headers.size() );
+ sb.append( ", body=" );
+ sb.append( body.size() );
+ sb.append( " lines." );
+
+ 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 "License");
+ * 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 "AS IS" 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( "one" )
+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( "Received string: [{}]", e.getMessage() );
+ log.trace( "State [{}]", 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( "Unhandled ESL header [" + 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 "License");
+ * 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 "AS IS" 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 = "localhost";
+ private int port = 8021;
+ private String password = "ClueCon";
+
+ @Test
+ public void do_connect() throws InterruptedException
+ {
+ Client client = new Client();
+
+ client.addEventListener( new IEslEventListener()
+ {
+ public void eventReceived( EslEvent event )
+ {
+ log.info( "Event received [{}]", event );
+ }
+ public void backgroundJobResultReceived( EslEvent event )
+ {
+ log.info( "Background job result received [{}]", event );
+ }
+
+ } );
+
+ log.info( "Client connecting .." );
+ try
+ {
+ client.connect( host, port, password, 2 );
+ }
+ catch ( InboundConnectionFailure e )
+ {
+ log.error( "Connect failed", e );
+ return;
+ }
+ log.info( "Client connected .." );
+
+// client.setEventSubscriptions( "plain", "heartbeat CHANNEL_CREATE CHANNEL_DESTROY BACKGROUND_JOB" );
+ client.setEventSubscriptions( "plain", "all" );
+ client.addEventFilter( "Event-Name", "heartbeat" );
+ client.cancelEventSubscriptions();
+ client.setEventSubscriptions( "plain", "all" );
+ client.addEventFilter( "Event-Name", "heartbeat" );
+ client.addEventFilter( "Event-Name", "channel_create" );
+ client.addEventFilter( "Event-Name", "background_job" );
+// client.sendSyncCommand( "echo", "Foo foo bar" );
+// client.sendSyncCommand( "originate", "sofia/internal/101@192.168.100.201! sofia/internal/102@192.168.100.201!" );
+
+// client.sendSyncApiCommand( "sofia status", "" );
+ String jobId = client.sendAsyncApiCommand( "status", "" );
+ log.info( "Job id [{}] for [status]", jobId );
+ client.sendSyncApiCommand( "version", "" );
+// client.sendAsyncApiCommand( "status", "" );
+// client.sendSyncApiCommand( "sofia status", "" );
+// client.sendAsyncApiCommand( "status", "" );
+ EslMessage response = client.sendSyncApiCommand( "sofia status", "" );
+ log.info( "sofia status = [{}]", response.getBodyLines().get( 3 ) );
+
+ Thread.sleep( 25000 );
+ client.close();
+ }
+
+ @Test
+ public void do_multi_connects() throws InterruptedException
+ {
+ Client client = new Client();
+
+ log.info( "Client connecting .." );
+ try
+ {
+ client.connect( host, port, password, 2 );
+ }
+ catch ( InboundConnectionFailure e )
+ {
+ log.error( "Connect failed", e );
+ return;
+ }
+ log.info( "Client connected .." );
+
+ log.info( "Client connecting .." );
+ try
+ {
+ client.connect( "127.0.0.1", 8021, password, 2 );
+ }
+ catch ( InboundConnectionFailure e )
+ {
+ log.error( "Connect failed", e );
+ return;
+ }
+ log.info( "Client connected .." );
+ }
+}
</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 "License");
+ * 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 "AS IS" 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( "Test starting ..." );
+
+
+ SocketClient client = new SocketClient( 8084, new SimpleHangupPipelineFactory() );
+
+ client.start();
+
+ Thread.sleep( 45000 );
+
+ client.stop();
+
+
+ log.info( "Test ended" );
+ }
+
+}
</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>+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the "License");
+ * 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 "AS IS" 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.
+-->
+<configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+ </Pattern>
+ </layout>
+ </appender>
+
+ <logger name="org.freeswitch.esl.client.outbound.example">
+ <level value="debug" />
+ </logger>
+ <logger name="org.freeswitch.esl.client.inbound">
+ <level value="debug" />
+ </logger>
+ <logger name="org.freeswitch.esl.client.transport.message">
+ <level value="info" />
+ </logger>
+ <logger name="org.freeswitch.esl.client">
+ <level value="info" />
+ </logger>
+
+ <root>
+ <level value="warn" />
+ <appender-ref ref="STDOUT" />
+ </root>
+
+</configuration>
</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>+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+        <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+        <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+        <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+        <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+        <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+        <classpathentry kind="output" path="target/classes"/>
+</classpath>
</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>+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+        <name>org.freeswitch.esl.client.example</name>
+        <comment></comment>
+        <projects>
+        </projects>
+        <buildSpec>
+                <buildCommand>
+                        <name>org.eclipse.jdt.core.javabuilder</name>
+                        <arguments>
+                        </arguments>
+                </buildCommand>
+                <buildCommand>
+                        <name>org.maven.ide.eclipse.maven2Builder</name>
+                        <arguments>
+                        </arguments>
+                </buildCommand>
+        </buildSpec>
+        <natures>
+                <nature>org.eclipse.jdt.core.javanature</nature>
+                <nature>org.maven.ide.eclipse.maven2Nature</nature>
+        </natures>
+</projectDescription>
</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>+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the "License");
+ * 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 "AS IS" 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.freeswitch.esl.client</groupId>
+ <artifactId>esl-client-parent</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>org.freeswitch.esl.client.example</artifactId>
+ <name>FreeSWITCH Event Socket Library - Java Client example usage</name>
+ <dependencies>
+ <dependency>
+ <groupId>org.freeswitch.esl.client</groupId>
+ <artifactId>org.freeswitch.esl.client</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project>
</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>+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright 2010 david varnes.
+ *
+ * Licensed under the Apache License, version 2.0 (the "License");
+ * 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 "AS IS" 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.freeswitch.esl.client</groupId>
+ <artifactId>esl-client-parent</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>FreeSWITCH Event Socket Library - Java Client project</name>
+ <url>http://www.freeswitch.org</url>
+ <description>
+ 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.
+ </description>
+ <organization>
+ <name>FreeSWITCH.org</name>
+ <url>http://www.freeswitch.org</url>
+ </organization>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <inceptionYear>2009</inceptionYear>
+ <scm>
+ <connection>scm:svn:http://svn.freeswitch.org/svn/freeswitch/trunk/contrib/dvarnes/java/esl-client</connection>
+ <developerConnection>scm:svn:http://svn.freeswitch.org/svn/freeswitch/trunk/contrib/dvarnes/java/esl-client</developerConnection>
+ </scm>
+ <developers>
+ <developer>
+ <id>dvarnes</id>
+ <name>david varnes</name>
+ <email>david at varnes dot net</email>
+ <timezone>GMT+10</timezone>
+ </developer>
+ </developers>
+ <modules>
+         <module>org.freeswitch.esl.client</module>
+         <module>org.freeswitch.esl.client.example</module>
+ </modules>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <!-- every child project inherits these plugins -->
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.1</version>
+ <executions>
+ <execution>
+ <id>attach-source</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <attach>true</attach>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
</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>