git-svn-id: http://bigbluebutton.googlecode.com/svn/trunk@2289 af16638f-c34d-0410-8cfa-b39d5352b314
This commit is contained in:
parent
67840af82a
commit
eec62a2421
12
asteriskjava/.classpath
Normal file
12
asteriskjava/.classpath
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="var" path="M2_REPO/log4j/log4j/1.2.13/log4j-1.2.13.jar" sourcepath="M2_REPO/log4j/log4j/1.2.13/log4j-1.2.13-sources.jar"/>
|
||||
<classpathentry kind="var" path="M2_REPO/junit/junit/4.0/junit-4.0.jar" sourcepath="M2_REPO/junit/junit/4.0/junit-4.0-sources.jar"/>
|
||||
<classpathentry kind="var" path="M2_REPO/org/easymock/easymock/2.2/easymock-2.2.jar" sourcepath="M2_REPO/org/easymock/easymock/2.2/easymock-2.2-sources.jar"/>
|
||||
<classpathentry exported="true" kind="con" path="GROOVY_SUPPORT"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
31
asteriskjava/.project
Normal file
31
asteriskjava/.project
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>asterisk-java-1.0.0-m2</name>
|
||||
<comment>Java interface for Asterisk PBX.</comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.codehaus.groovy.eclipse.groovyBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
|
||||
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
|
||||
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
|
||||
<nature>org.codehaus.groovy.eclipse.groovyNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -0,0 +1,4 @@
|
||||
#Sat Aug 15 16:30:35 EDT 2009
|
||||
eclipse.preferences.version=1
|
||||
groovy.compiler.output.path=bin-groovy
|
||||
support.groovy=true
|
3
asteriskjava/.settings/org.eclipse.jdt.core.prefs
Normal file
3
asteriskjava/.settings/org.eclipse.jdt.core.prefs
Normal file
@ -0,0 +1,3 @@
|
||||
#Sat Aug 15 16:30:35 EDT 2009
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch,*.groovy
|
39
asteriskjava/ANNOUNCEMENT
Normal file
39
asteriskjava/ANNOUNCEMENT
Normal file
@ -0,0 +1,39 @@
|
||||
ANNOUNCEMENT: Asterisk-Java 0.3.1 released
|
||||
|
||||
Asterisk-Java 0.3.1, the free Java library for Asterisk PBX integration,
|
||||
has been released.
|
||||
|
||||
The Asterisk-Java package consists of a set of Java classes that allow
|
||||
you to easily build Java applications that interact with an Asterisk
|
||||
PBX Server. Asterisk-Java supports both interfaces that Asterisk
|
||||
provides for this scenario: The FastAGI protocol and the Manager API.
|
||||
|
||||
Asterisk-Java 0.3.1 is a maintenance release that solves the
|
||||
following issues:
|
||||
* [AJ-81] - executeCliCommand() always executes "show voicemail users"
|
||||
* [AJ-86] - getChannelByName doesn't return the latest channel
|
||||
* [AJ-80] - getMeetMeRooms() should only return active rooms
|
||||
* [AJ-68] - Support for Bridge Action
|
||||
* [AJ-74] - Support Strategy property in QueueParamsEvent
|
||||
|
||||
Asterisk-Java takes advantage of the features of Java 5.0 and therefore
|
||||
requires a Java Virtual Machine of at least version 1.5.0.
|
||||
|
||||
Asterisk-Java is used in several commercial environments and by
|
||||
the following Open Source projects:
|
||||
* Asterisk-JTAPI
|
||||
JTAPI implementation for Asterisk.
|
||||
http://asterisk-jtapi.sf.net/
|
||||
* Asterisk-IM
|
||||
A plugin for the Openfire XMPP (jabber) server. It provides
|
||||
integrated presence between your IM client and phone, notification
|
||||
of incoming calls by IM and originate calls from supported IM
|
||||
clients.
|
||||
http://www.igniterealtime.org/projects/openfire/
|
||||
* Asterisk Desktop Manager (ADM)
|
||||
A desktop application that will allow for automatic on-call volume
|
||||
reduction, one click dial from clipboard, integrated phonebook
|
||||
and more.
|
||||
http://adm.hamnett.org/
|
||||
|
||||
Asterisk-Java is available under Apache 2.0 license at http://asterisk-java.org
|
145
asteriskjava/CHANGES
Normal file
145
asteriskjava/CHANGES
Normal file
@ -0,0 +1,145 @@
|
||||
Asterisk-Java 1.0.0
|
||||
Warning:
|
||||
Values for event properties of type String that match one of the null
|
||||
literals used by Asterisk are automatically set to null in A-J 1.0.0.
|
||||
The null literals are:
|
||||
"<unknown>", "unknown", "none", "<none>", "-none-", "(none)",
|
||||
"<not set>", "(not set)", "<no name>", "n/a", "<null>" and
|
||||
"(null)".
|
||||
|
||||
|
||||
Asterisk-Java 0.3.1
|
||||
* [AJ-81] - executeCliCommand() always executes "show voicemail users"
|
||||
* [AJ-86] - getChannelByName doesn't return the latest channel
|
||||
* [AJ-79] - Support for the CallWeaver protocol identifier
|
||||
* [AJ-80] - getMeetMeRooms() should only return active rooms
|
||||
* [AJ-68] - Support for Bridge Action
|
||||
* [AJ-74] - Support Strategy property in QueueParamsEvent
|
||||
* [AJ-78] - Documentation needs thorough examples of the Live API
|
||||
|
||||
Asterisk-Java 0.3
|
||||
* [AJ-30] - Fixed version detection when restarting Asterisk
|
||||
* [AJ-59] - Fixed incorrect class and method names when using JavaLoggingLog
|
||||
* [AJ-60] - Fixed DefaultManagerConnection.sendEventGeneratingAction()
|
||||
for Asterisk 1.4.1
|
||||
* [AJ-50] - Finished support for Asterisk 1.4
|
||||
* [AJ-54] - Fixed AsteriskQueue observer and Park events
|
||||
* [AJ-55] - Added "videoSupport" and "realtimeDevice" to PeerEntryEvent
|
||||
* [AJ-56] - Added "callerIdNum" to AbstractChannelEvent
|
||||
* [AJ-57] - Added "memberName" to AbstractQueueMemberEvent
|
||||
* [AJ-58] - Added support for OpenPBX
|
||||
* [AJ-43] - Added support for GetConfig and UpdateConfig actions
|
||||
* [AJ-62] - Added executeCliCommand() method to AsteriskServer
|
||||
* [AJ-2] - Updated design doc and tutorial according to AGI changes
|
||||
|
||||
Asterisk-Java 0.3-m2
|
||||
* Added getManagerConnection() to AsteriskServer (AJ-41)
|
||||
* Added timestamp property to ManagerEvent (AJ-35)
|
||||
* Added QueueSummaryAction, QueueSummaryEvent and
|
||||
QueueSummaryCompleteEvent (AJ-42)
|
||||
* Added ZapRestartAction (AJ-45)
|
||||
* Added PauseMontiorAction and UnpauseMonitorAction and
|
||||
pauseMontior() and unpauseMonitor() methods to
|
||||
AsteriskChannel (AJ-44)
|
||||
* Added AbstractManagerEventListener
|
||||
|
||||
Asterisk-Java 0.3-m1
|
||||
* Changed package name from net.sf.asterisk to org.asteriskjava
|
||||
and renamed AGI classes to Agi to conform to Java coding
|
||||
standards
|
||||
* Renamed ManagerEventHandler and ManagerResponseHandler to
|
||||
ManagerEventListener and SendActionCallback.
|
||||
* Introduced generics and leveraged other Java5 features like
|
||||
java.util.concurrent.
|
||||
* Added SSL support for the Manager API.
|
||||
* ManagerReader threads are now daemon threads so as soon as
|
||||
all other threads are terminated the JVM will quit
|
||||
* Changed log level for message about ManagerReader termination
|
||||
from INFO to DEBUG
|
||||
* ManagerConnectionFactory has been simplified. Usage example:
|
||||
new ManagerConnectionFactory("host", "user", "pass")
|
||||
.createManagerConnection();
|
||||
* Fixed timing bug in ResourceBundleMappingStrategy (AJ-25)
|
||||
* Fixed interrupt in DefaultManagerConnection (AJ-27)
|
||||
* Fixed accountCode always being null in AgiRequest
|
||||
* Fixed synchronization bug when generating internal action ids for
|
||||
the Manager API
|
||||
* Fixed synchronous sendAction for responses that are received really
|
||||
fast, i.e. before the thread is put asleep.
|
||||
* Fixed ConnectEvent being only fired after a successful
|
||||
login (AJ-32)
|
||||
* Fixed no setter for the dnd field when sending
|
||||
ZapShowChannelsAction (AJ-33)
|
||||
* Added support for login with eventMask (AJ-28)
|
||||
* Added support for using non-shared instances AgiScript, i.e. a
|
||||
new instance is used for each request if you set the
|
||||
shareInstances property on your MappingStrategy to false.
|
||||
Default is still to use shared instances (AJ-29)
|
||||
* Live objects now fire PropertyChangeEvents
|
||||
* Added extraContext, extraExten, extraPriority properties to
|
||||
RedirectAction to support BRIstuffed versions of Asterisk (AJ-34)
|
||||
* Added recordFile and controlStreamFile methods to AgiChannel and
|
||||
BaseAgiScript
|
||||
* Added channel variable AJ_AGISTATUS that is set by the AgiServer
|
||||
to "SUCCESS" if the AgiScript completed successfully, "FAILED"
|
||||
if it threw an exception or "NOT_FOUND" if the mapping strategy
|
||||
did not return a script for the requested URL.
|
||||
* Added MeetMeMuteEvent and muted property for MeetMeUser.
|
||||
* Added MeetMeMuteAction and MeetMeUnmuteAction.
|
||||
* Added ParkAction.
|
||||
* Added PlayDtmfAction and playDtmf() method for AsteriskChannel.
|
||||
* Added several new event properties for Asterisk 1.4:
|
||||
- MeetMeEvent: channel and uniqueId
|
||||
- MeetMeLeaveEvent: callerIdNum, callerIdName and duration
|
||||
- MeetMeTalkingEvent: status
|
||||
- StatusEvent: callerIdNum and callerIdName
|
||||
- OriginateEvent: callerIdNum and callerIdName
|
||||
- JoinEvent and LeaveEvent: uniqueId
|
||||
- AgentConnectEvent: brigedChannel
|
||||
|
||||
Asterisk-Java 0.2
|
||||
* Added SayDateTimeCommand (AJ-23)
|
||||
* Added GetFullVariableCommand (AJ-23)
|
||||
* Added ReceiveTextCommand (AJ-23)
|
||||
* Changed SetPriorityCommand to support labels (AJ-23)
|
||||
* Added callingPres, callingAni2, callingTns and callingTon
|
||||
properties to AGIRequest (AJ-22)
|
||||
* Fixed CallerId information in AGIRequest for
|
||||
Asterisk 1.2 (AJ-21)
|
||||
|
||||
Asterisk-Java 0.2-rc2
|
||||
* Fixed mapping of Variable property in OriginateAction for
|
||||
Asterisk 1.2 (AJ-15)
|
||||
* Added FaxReceived event from spandsp (AJ-20)
|
||||
* Added SimpleMappingStrategy and AGIServerThread to ease
|
||||
integration of AGIServer when using Spring Framework
|
||||
* Timeout for socket connection can now be specified for
|
||||
the ManagerConnection (AJ-16)
|
||||
* Added getPort() method to lookup port of an AGIServer (AJ-14)
|
||||
* Readded getContext(), getExtension(), getPriority() as
|
||||
convenience methods to Channel (AJ-12)
|
||||
* Decreased log level for unknown events to INFO (AJ-13)
|
||||
|
||||
Asterisk-Java 0.2-rc1
|
||||
* Added Support for the new Actions, Events and Commands
|
||||
of Asterisk 1.2
|
||||
* Fixed getting the uniqueId from a successful originate
|
||||
in the DefaultAsteriskManager
|
||||
* Added isConnected() method to ManagerConnection
|
||||
* Changed ManagerAction to be an interface rather that an
|
||||
abstract base class. If you extended ManagerAction, please
|
||||
use AbstractManagerAction instead.
|
||||
* Added support for event generating Actions, i.e. Actions
|
||||
that send their result as a series of Event rather than
|
||||
the usual ManagerResults. See the sendEventGeneratingAction()
|
||||
methods in ManagerConnection for more information.
|
||||
* Deprecated AbstractAGIScript in favor of BaseAGIScript. This
|
||||
allows you write cleaner AGI scripts as you don't have to
|
||||
pass the channel variable to all methods.
|
||||
* Added convenience constructors for manager actions
|
||||
|
||||
Asterisk-Java 0.1
|
||||
* Added accessors for raw attributes in ManagerResponse
|
||||
* Fixed bug in action id creation
|
||||
* Changed logging to use either log4j or java.util.logging
|
||||
* Fixed ExecCommand
|
202
asteriskjava/LICENSE.txt
Normal file
202
asteriskjava/LICENSE.txt
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
36
asteriskjava/README.txt
Normal file
36
asteriskjava/README.txt
Normal file
@ -0,0 +1,36 @@
|
||||
README for Asterisk-Java
|
||||
========================
|
||||
|
||||
== INTRODUCTION ==
|
||||
|
||||
The Asterisk-Java package consists of a set of Java classes that allow you to
|
||||
easily build Java applications that interact with an Asterisk PBX Server.
|
||||
Asterisk-Java supports both interfaces that Asterisk provides for this
|
||||
scenario: The FastAGI protocol and the Manager API.
|
||||
|
||||
The FastAGI implementation supports all commands currently available from
|
||||
Asterisk.
|
||||
|
||||
The Manager API implementation supports receiving events from the Asterisk
|
||||
server (e.g. call progess, registered peers, channel state) and sending
|
||||
actions to Asterisk (e.g. originate call, agent login/logoff, start/stop
|
||||
voice recording).
|
||||
|
||||
A complete list of the available events and actions is available in the
|
||||
javadocs.
|
||||
|
||||
See docs/tutorial.html for examples.
|
||||
|
||||
== LEGAL ==
|
||||
|
||||
Asterisk-Java is subject to the terms detailed in the license agreement
|
||||
accompanying it.
|
||||
|
||||
== GETTING ASTERISK-JAVA ==
|
||||
|
||||
Asterisk-Java is available from http://asterisk-java.org
|
||||
|
||||
== SYSTEM REQUIREMENTS ==
|
||||
|
||||
Asterisk-Java needs a Java Virtual Machine of at least version 1.6
|
||||
(Java SE 6.0).
|
32
asteriskjava/atlassian-ide-plugin.xml
Normal file
32
asteriskjava/atlassian-ide-plugin.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<atlassian-ide-plugin>
|
||||
<project-configuration>
|
||||
<servers>
|
||||
<jira>
|
||||
<server-id>e88a6130-6bd2-45dd-aa5d-57b845f76d0f</server-id>
|
||||
<name>jira.reucon.org</name>
|
||||
<url>http://jira.reucon.org</url>
|
||||
</jira>
|
||||
<crucible>
|
||||
<server-id>89c4100c-3c20-4d7d-8611-0dbe1bee742e</server-id>
|
||||
<name>reucon</name>
|
||||
<url>https://secure.reucon.net/fisheye</url>
|
||||
<isFisheyeInstance>true</isFisheyeInstance>
|
||||
</crucible>
|
||||
<bamboo>
|
||||
<server-id>68a20e42-e943-4a1d-b807-45cad35b4f73</server-id>
|
||||
<name>reucon</name>
|
||||
<url>https://secure.reucon.net/build</url>
|
||||
<use-favourites>false</use-favourites>
|
||||
<bamboo2>true</bamboo2>
|
||||
<plans>
|
||||
<plan key="AJ-DEF" />
|
||||
<plan key="AJ-NIGHTLY" />
|
||||
</plans>
|
||||
</bamboo>
|
||||
</servers>
|
||||
<default-crucible-server>89c4100c-3c20-4d7d-8611-0dbe1bee742e</default-crucible-server>
|
||||
<default-fisheye-server>89c4100c-3c20-4d7d-8611-0dbe1bee742e</default-fisheye-server>
|
||||
<default-fisheye-repo>repos</default-fisheye-repo>
|
||||
<fisheye-project-path>asterisk-java/trunk</fisheye-project-path>
|
||||
</project-configuration>
|
||||
</atlassian-ide-plugin>
|
204
asteriskjava/checkstyle.xml
Normal file
204
asteriskjava/checkstyle.xml
Normal file
@ -0,0 +1,204 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.1//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_1.dtd">
|
||||
|
||||
<!--
|
||||
|
||||
Checkstyle configuration that checks the sun coding conventions from:
|
||||
|
||||
- the Java Language Specification at
|
||||
http://java.sun.com/docs/books/jls/second_edition/html/index.html
|
||||
|
||||
- the Sun Code Conventions at http://java.sun.com/docs/codeconv/
|
||||
|
||||
- the Javadoc guidelines at
|
||||
http://java.sun.com/j2se/javadoc/writingdoccomments/index.html
|
||||
|
||||
- the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html
|
||||
|
||||
- some best practices
|
||||
|
||||
Checkstyle is very configurable. Be sure to read the documentation at
|
||||
http://checkstyle.sf.net (or in your downloaded distribution).
|
||||
|
||||
Most Checks are configurable, be sure to consult the documentation.
|
||||
|
||||
To completely disable a check, just comment it out or delete it from the file.
|
||||
|
||||
Finally, it is worth reading the documentation.
|
||||
|
||||
-->
|
||||
|
||||
<module name="Checker">
|
||||
|
||||
<!-- Checks that a package.html file exists for each package. -->
|
||||
<!-- See http://checkstyle.sf.net/config_javadoc.html#PackageHtml -->
|
||||
<module name="PackageHtml"/>
|
||||
|
||||
<!-- Checks whether files end with a new line. -->
|
||||
<!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
|
||||
<module name="NewlineAtEndOfFile"/>
|
||||
|
||||
<!-- Checks that property files contain the same keys. -->
|
||||
<!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
|
||||
<module name="Translation"/>
|
||||
|
||||
<module name="TreeWalker">
|
||||
|
||||
<property name="cacheFile" value="${checkstyle.cache.file}"/>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- Checks that are different from the sun coding conventions ones -->
|
||||
<!-- ************************************************************** -->
|
||||
<property name="tabWidth" value="4"/>
|
||||
<module name="LeftCurly">
|
||||
<property name="option" value="nl"/>
|
||||
</module>
|
||||
<module name="RightCurly">
|
||||
<property name="option" value="alone"/>
|
||||
</module>
|
||||
<module name="LineLength">
|
||||
<property name="max" value="120"/>
|
||||
<property name="ignorePattern" value="@version"/>
|
||||
</module>
|
||||
<module name="MemberName">
|
||||
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
|
||||
</module>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- Default Sun coding conventions checks -->
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<!-- Checks for Javadoc comments. -->
|
||||
<!-- See http://checkstyle.sf.net/config_javadoc.html -->
|
||||
<module name="JavadocMethod"/>
|
||||
<module name="JavadocType"/>
|
||||
<module name="JavadocVariable"/>
|
||||
|
||||
|
||||
<!-- Checks for Naming Conventions. -->
|
||||
<!-- See http://checkstyle.sf.net/config_naming.html -->
|
||||
<module name="ConstantName"/>
|
||||
<module name="LocalFinalVariableName"/>
|
||||
<module name="LocalVariableName"/>
|
||||
<module name="MethodName"/>
|
||||
<module name="PackageName"/>
|
||||
<module name="ParameterName"/>
|
||||
<module name="StaticVariableName"/>
|
||||
<module name="TypeName"/>
|
||||
|
||||
|
||||
<!-- Checks for Headers -->
|
||||
<!-- See http://checkstyle.sf.net/config_header.html -->
|
||||
<module name="Header">
|
||||
<!-- The follow property value demonstrates the ability -->
|
||||
<!-- to have access to ANT properties. In this case it uses -->
|
||||
<!-- the ${basedir} property to allow Checkstyle to be run -->
|
||||
<!-- from any directory within a project. -->
|
||||
<property name="headerFile" value="${checkstyle.header.file}"/>
|
||||
<property name="ignoreLines" value="1,6"/>
|
||||
</module>
|
||||
|
||||
<!-- Following interprets the header file as regular expressions. -->
|
||||
<!-- <module name="RegexpHeader"/> -->
|
||||
|
||||
|
||||
<!-- Checks for imports -->
|
||||
<!-- See http://checkstyle.sf.net/config_import.html -->
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="IllegalImport"/> <!-- defaults to sun.* packages -->
|
||||
<module name="RedundantImport"/>
|
||||
<module name="UnusedImports"/>
|
||||
|
||||
|
||||
<!-- Checks for Size Violations. -->
|
||||
<!-- See http://checkstyle.sf.net/config_sizes.html -->
|
||||
<module name="FileLength"/>
|
||||
<module name="MethodLength"/>
|
||||
<module name="ParameterNumber"/>
|
||||
|
||||
|
||||
<!-- Checks for whitespace -->
|
||||
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
|
||||
<module name="EmptyForIteratorPad"/>
|
||||
<module name="NoWhitespaceAfter"/>
|
||||
<module name="NoWhitespaceBefore"/>
|
||||
<module name="OperatorWrap"/>
|
||||
<module name="ParenPad"/>
|
||||
<module name="TabCharacter"/>
|
||||
<module name="WhitespaceAfter"/>
|
||||
<module name="WhitespaceAround"/>
|
||||
|
||||
|
||||
<!-- Modifier Checks -->
|
||||
<!-- See http://checkstyle.sf.net/config_modifiers.html -->
|
||||
<module name="ModifierOrder"/>
|
||||
<module name="RedundantModifier"/>
|
||||
|
||||
|
||||
<!-- Checks for blocks. You know, those {}'s -->
|
||||
<!-- See http://checkstyle.sf.net/config_blocks.html -->
|
||||
<module name="AvoidNestedBlocks"/>
|
||||
<module name="EmptyBlock"/>
|
||||
|
||||
<module name="NeedBraces"/>
|
||||
|
||||
|
||||
<!-- Checks for common coding problems -->
|
||||
<!-- See http://checkstyle.sf.net/config_coding.html -->
|
||||
<module name="AvoidInlineConditionals"/>
|
||||
<module name="DoubleCheckedLocking"/> <!-- MY FAVOURITE -->
|
||||
<module name="EmptyStatement"/>
|
||||
<module name="EqualsHashCode"/>
|
||||
<!-- module name="HiddenField"/ -->
|
||||
<module name="IllegalInstantiation"/>
|
||||
<module name="InnerAssignment"/>
|
||||
<module name="MagicNumber"/>
|
||||
<module name="MissingSwitchDefault"/>
|
||||
<module name="RedundantThrows"/>
|
||||
<module name="SimplifyBooleanExpression"/>
|
||||
<module name="SimplifyBooleanReturn"/>
|
||||
|
||||
<!-- Checks for class design -->
|
||||
<!-- See http://checkstyle.sf.net/config_design.html -->
|
||||
<module name="DesignForExtension"/>
|
||||
<module name="FinalClass"/>
|
||||
<module name="HideUtilityClassConstructor"/>
|
||||
<module name="InterfaceIsType"/>
|
||||
<module name="VisibilityModifier"/>
|
||||
|
||||
|
||||
<!-- Miscellaneous other checks. -->
|
||||
<!-- See http://checkstyle.sf.net/config_misc.html -->
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="FinalParameters"/>
|
||||
<module name="GenericIllegalRegexp">
|
||||
<property name="format" value="\s+$"/>
|
||||
<property name="ignoreComments" value="true"/>
|
||||
<property name="message" value="Line has trailing spaces."/>
|
||||
</module>
|
||||
<module name="TodoComment"/>
|
||||
<module name="UpperEll"/>
|
||||
|
||||
</module>
|
||||
|
||||
</module>
|
251
asteriskjava/codestyle.xml
Normal file
251
asteriskjava/codestyle.xml
Normal file
@ -0,0 +1,251 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="10">
|
||||
<profile name="reucon" version="10">
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="52"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="48"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="64"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="64"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="125"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
</profile>
|
||||
</profiles>
|
18
asteriskjava/dist/agi/demo.groovy
vendored
Normal file
18
asteriskjava/dist/agi/demo.groovy
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
// countdown
|
||||
(10..0).each { digit -> channel.sayNumber(digit.toString()) }
|
||||
|
||||
channel.streamFile('beep');
|
||||
|
||||
// read a few dtmf digits
|
||||
while ((digit = channel.waitForDigit(10000)) != 0)
|
||||
{
|
||||
if (digit == '#' || digit == '*')
|
||||
{
|
||||
break;
|
||||
}
|
||||
channel.sayDigits(digit.toString());
|
||||
}
|
||||
|
||||
// beep to say good bye ;)
|
||||
channel.streamFile('beep');
|
||||
|
22
asteriskjava/dist/agi/demo.js
vendored
Normal file
22
asteriskjava/dist/agi/demo.js
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// countdown
|
||||
for (var i = 10; i >= 0; i--)
|
||||
{
|
||||
channel.sayNumber(i);
|
||||
}
|
||||
|
||||
channel.streamFile('beep');
|
||||
|
||||
// read a few dtmf digits
|
||||
var digit;
|
||||
while ((digit = channel.waitForDigit(10000)) != 0)
|
||||
{
|
||||
if (digit == '#' || digit == '*')
|
||||
{
|
||||
break;
|
||||
}
|
||||
channel.sayDigits(digit);
|
||||
}
|
||||
|
||||
// beep to say good bye ;)
|
||||
channel.streamFile('beep');
|
||||
|
24
asteriskjava/dist/agi/demo.php
vendored
Normal file
24
asteriskjava/dist/agi/demo.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
// countdown
|
||||
for ($i = 10; $i >= 0; $i--)
|
||||
{
|
||||
$channel->sayNumber($i);
|
||||
}
|
||||
|
||||
$channel->streamFile('beep');
|
||||
|
||||
// read a few dtmf digits
|
||||
while (($digit = $channel->waitForDigit(10000)) != 0)
|
||||
{
|
||||
if ($digit == '#' || $digit == '*')
|
||||
{
|
||||
break;
|
||||
}
|
||||
$channel->sayDigits($digit);
|
||||
}
|
||||
|
||||
// beep to say good bye ;)
|
||||
$channel->streamFile('beep');
|
||||
|
||||
?>
|
BIN
asteriskjava/dist/lib/groovy-all-1.6.2.jar
vendored
Normal file
BIN
asteriskjava/dist/lib/groovy-all-1.6.2.jar
vendored
Normal file
Binary file not shown.
BIN
asteriskjava/dist/lib/javamail-141.jar
vendored
Normal file
BIN
asteriskjava/dist/lib/javamail-141.jar
vendored
Normal file
Binary file not shown.
BIN
asteriskjava/dist/lib/jruby-complete-1.2.0.jar
vendored
Normal file
BIN
asteriskjava/dist/lib/jruby-complete-1.2.0.jar
vendored
Normal file
Binary file not shown.
BIN
asteriskjava/dist/lib/mysql-connector-java-5.1.7-bin.jar
vendored
Normal file
BIN
asteriskjava/dist/lib/mysql-connector-java-5.1.7-bin.jar
vendored
Normal file
Binary file not shown.
BIN
asteriskjava/dist/lib/quercus-3.2.1.jar
vendored
Normal file
BIN
asteriskjava/dist/lib/quercus-3.2.1.jar
vendored
Normal file
Binary file not shown.
BIN
asteriskjava/dist/lib/resin-util-3.2.1.jar
vendored
Normal file
BIN
asteriskjava/dist/lib/resin-util-3.2.1.jar
vendored
Normal file
Binary file not shown.
BIN
asteriskjava/dist/lib/servlet-api-2.5.jar
vendored
Normal file
BIN
asteriskjava/dist/lib/servlet-api-2.5.jar
vendored
Normal file
Binary file not shown.
164
asteriskjava/lib/clover/clover.license
Normal file
164
asteriskjava/lib/clover/clover.license
Normal file
@ -0,0 +1,164 @@
|
||||
Product: Clover
|
||||
License: Open Source License, 0.x, 1.x
|
||||
Issued: Thu Oct 21 2004 21:27:21 CDT
|
||||
Expiry: Never
|
||||
Key: 7e1c2ed27ee858f42adedd953
|
||||
Name: Stefan Reuter
|
||||
Org: asterisk-java
|
||||
Certificate: AAABsm+Ow8B7/zEbxOMqqKwwrdpP+a1COmJGHco7sCNLjHkHnajPF+dQW
|
||||
Ct12PMy0uml0s9xuus5wKngJ9OFk5XFeh01dzQF66bhXH1bvegLfvja3Kle6BYtDv4LZgE
|
||||
gk3E0aJN4IbgTn+TgUckSevXDR4KzK77NWJfrVzkxV3/Jer0jWuM7QJbvwkyoXjNEVc/ye
|
||||
OTlpI6MQPLOI4Og5zfT4dHD72UJcFEgGvSx6kEeWPn+RGX8xt3GVb8MJ1ywMWYUIcFWe2m
|
||||
JfmT8OoDi6VDKGj/p0gCEpn+6zEmWuUoleg59zSy9cEHoJVDLjoVAqhUmFnDYl2Tk9LLP3
|
||||
3Gn0yLWqYQk2fzWw7d6BiJrcX/2seoMHkW4+l9l5JKzy0XyFHUIsTFzbjbeTmZpk24hkje
|
||||
f9PFP3hFn89RVjsozstxYnbhGeHhQZNk/uG0ftnAR0bXdFv0ZYFU0t/597/Kxw9gpyss1w
|
||||
r/rdMDm0c+7KgckZjxPrfvvFgAFuutYe//Ol8Be8lguE7Fkews81gIyc4d0NvU+gu7qUZo
|
||||
WOOjTVMuDM7TJWIHlKT54UGPELrE8E/I7XICOJa8WipV+qmMXPXk/q2oiu1udzSy7Tmvyi
|
||||
hZ85yCnuH9DBnpBZRbS88AtM6Lje56JhNykODYtRipYlvD8vlukR+/c4sBWNkJlYG7FU/o
|
||||
SP8Hrnh8VSFASymIfLGF/6v+wzRsoiAyO3MlQPDajIsCnmFIFanUVG453AmktJwxbKU0=
|
||||
License Agreement: CLOVER VERSION 1 (ONE) SOFTWARE LICENSE AGREEMENT
|
||||
|
||||
1. Licenses and Software
|
||||
|
||||
Cortex eBusiness Pty Ltd, an Australian Proprietary Limited Company
|
||||
("CENQUA") hereby grants to the purchaser (the "LICENSEE") a limited,
|
||||
revocable, worldwide, non-exclusive, non-transferable,
|
||||
non-sublicensable license to use the Clover version 1 (one) software
|
||||
(the "Software"), including any minor upgrades thereof during the Term
|
||||
(hereinafter defined) up to, but not including the next major version
|
||||
of the Software. The licensee shall not, or knowingly allow others to,
|
||||
reverse engineer, decompile, disassemble, modify, adapt, create
|
||||
derivative works from or otherwise attempt to derive source code from
|
||||
the Software provided. And, in accordance with the terms and
|
||||
conditions of this Software License Agreement (the "Agreement"), the
|
||||
Software shall be used solely by the licensed users in accordance with
|
||||
the following edition specific conditions:
|
||||
|
||||
a) Server Edition
|
||||
|
||||
A Server Edition license entitles the Licensee to execute one instance
|
||||
of Clover Server Edition on one (1) machine for the purposes of
|
||||
instrumenting source code and generating reports. There are no
|
||||
limitations on the use of the instrumented source code or generated
|
||||
reports produced by Server Edition.
|
||||
|
||||
b) Workstation Edition
|
||||
|
||||
A Workstation Edition license entitles the licensee to use Clover
|
||||
Workstation Edition on one (1) machine by one (1) individual end
|
||||
user. Workstation Edition does not permit the generation of reports
|
||||
for distribution.
|
||||
|
||||
c) Team Edition
|
||||
|
||||
A Team Edition license entitles the licensee to use Clover Team
|
||||
edition on any number of machines solely by the licensed number of
|
||||
users. Reports generated by Clover Team Edition are strictly for use
|
||||
only by the licensed number of individual end users.
|
||||
|
||||
2. License Fee
|
||||
|
||||
In exchange for the License(s), the Licensee shall pay to Cenqua a
|
||||
one-time, up front, non-refundable license fee. At the sole discretion
|
||||
of Cenqua this fee will be waived for non-commercial
|
||||
projects. Notwithstanding the Licensee's payment of the License Fee,
|
||||
Cenqua reserves the right to terminate the License if Cenqua discovers
|
||||
that the Licensee and/or the Licensee's use of the Software is in
|
||||
breach of this Agreement.
|
||||
|
||||
3. Proprietary Rights
|
||||
|
||||
Cenqua will retain all right, title and interest in and to the
|
||||
Software, all copies thereof, and Cenqua website(s), software, and
|
||||
other intellectual property, including, but not limited to, ownership
|
||||
of all copyrights, look and feel, trademark rights, design rights,
|
||||
trade secret rights and any and all other intellectual property and
|
||||
other proprietary rights therein. The Licensee will not directly or
|
||||
indirectly obtain or attempt to obtain at any time, any right, title
|
||||
or interest by registration or otherwise in or to the trademarks,
|
||||
service marks, copyrights, trade names, symbols, logos or designations
|
||||
or other intellectual property rights owned or used by Cenqua. All
|
||||
technical manuals or other information provided by Cenqua to the
|
||||
Licensee shall be the sole property of Cenqua.
|
||||
|
||||
4. Term and Termination
|
||||
|
||||
Subject to the other provisions hereof, this Agreement shall commence
|
||||
upon the Licensee's opting into this Agreement and continue until the
|
||||
Licensee discontinues use of the Software or the Agreement terminates
|
||||
automatically upon the Licensee's breach of any term or condition of
|
||||
this Agreement (the "Term"). Upon any such termination, the Licensee
|
||||
will delete the Software immediately.
|
||||
|
||||
5. Copying & Transfer
|
||||
|
||||
The Licensee may copy the Software for back-up purposes only. The
|
||||
Licensee may not assign or otherwise transfer the Software to any
|
||||
third party.
|
||||
|
||||
6. Specific Disclaimer of Warranty and Limitation of Liability
|
||||
|
||||
THE SOFTWARE IS PROVIDED WITHOUT WARRANTY OF ANY KIND. CENQUA
|
||||
DISCLAIMS ALL WARRANTIES, EXPRESSED OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE. CENQUA WILL NOT BE LIABLE FOR ANY DAMAGES
|
||||
ASSOCIATED WITH THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ORDINARY,
|
||||
INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING
|
||||
BUT NOT LIMITED TO DAMAGES RELATING TO LOST DATA OR LOST PROFITS, EVEN
|
||||
IF CENQUA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. Warranties and Representations
|
||||
|
||||
Licensee Indemnification. CENQUA agrees to indemnify, defend and hold
|
||||
the Licensee harmless from and against any and all liabilities,
|
||||
damages, losses, claims, costs, and expenses (including reasonable
|
||||
legal fees) arising out of or resulting from the Software or the use
|
||||
thereof infringing upon, misappropriating or violating any patents,
|
||||
copyrights, trademarks, or trade secret rights or other proprietary
|
||||
rights of persons, firms or entities who are not parties to this
|
||||
Agreement.
|
||||
|
||||
CENQUA Indemnification. The Licensee warrants and represents that the
|
||||
Licensee's actions with regard to the Software will be in compliance
|
||||
with all applicable laws; and the Licensee agrees to indemnify,
|
||||
defend, and hold CENQUA harmless from and against any and all
|
||||
liabilities, damages, losses, claims, costs, and expenses (including
|
||||
reasonable legal fees) arising out of or resulting from the
|
||||
Licensee's failure to observe the use restrictions set forth herein.
|
||||
|
||||
8. Publicity
|
||||
|
||||
The Licensee grants permission for CENQUA to use Licensee's name
|
||||
solely in customer lists. CENQUA shall not, without prior consent in
|
||||
writing, use the Licensee's name, or that of its affiliates, in any
|
||||
form with the specific exception of customer lists. CENQUA agrees to
|
||||
remove Licensee's name from any and all materials within 7 days if
|
||||
notified by the Licensee in writing.
|
||||
|
||||
9. Governing Law
|
||||
|
||||
This Agreement shall be governed by the laws of New South Wales,
|
||||
Australia.
|
||||
|
||||
10. Independent Contractors
|
||||
|
||||
The parties are independent contractors with respect to each other,
|
||||
and nothing in this Agreement shall be construed as creating an
|
||||
employer-employee relationship, a partnership, agency relationship or
|
||||
a joint venture between the parties.
|
||||
|
||||
11. Assignment
|
||||
|
||||
This Agreement is not assignable or transferable by the Licensee.
|
||||
CENQUA in its sole discretion may transfer a license to a third party
|
||||
at the written request of the Licensee.
|
||||
|
||||
12. Entire Agreement
|
||||
|
||||
This Agreement constitutes the entire agreement between the parties
|
||||
concerning the Licensee's use of the Software. This Agreement
|
||||
supersedes any prior verbal understanding between the parties and any
|
||||
Licensee purchase order or other ordering document, regardless of
|
||||
whether such document is received by CENQUA before or after execution
|
||||
of this Agreement. This Agreement may be amended only in writing by
|
||||
CENQUA.
|
293
asteriskjava/pom.xml
Normal file
293
asteriskjava/pom.xml
Normal file
@ -0,0 +1,293 @@
|
||||
<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.asteriskjava</groupId>
|
||||
<artifactId>asterisk-java</artifactId>
|
||||
<name>Asterisk-Java</name>
|
||||
<version>1.0.0-m2</version>
|
||||
<description>The free Java library for Asterisk PBX integration.</description>
|
||||
<url>http://asterisk-java.org/</url>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
</license>
|
||||
</licenses>
|
||||
<organization>
|
||||
<name>Stefan Reuter</name>
|
||||
<url>http://asterisk-java.org/</url>
|
||||
</organization>
|
||||
<inceptionYear>2004</inceptionYear>
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Stefan Reuter</name>
|
||||
<id>srt</id>
|
||||
<email>srt at users.sourceforge.net</email>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Pierre-Yves Roger</name>
|
||||
<id>partoutatis</id>
|
||||
<email>partoutatis at users.sourceforge.net</email>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>John Hood</name>
|
||||
<id>squinky86</id>
|
||||
<email>john at asteriasgi.com</email>
|
||||
<organization>Asteria Solutions Group, Inc.</organization>
|
||||
<timezone>-6</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Martin B. Smith</name>
|
||||
<id>martins</id>
|
||||
<email>martins at bebr.ufl.edu</email>
|
||||
<organization>Bureau of Economic and Business Research, University of Florida</organization>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.reucon.net/repos/asterisk-java/tags/asterisk-java-1.0.0-m2</connection>
|
||||
<developerConnection>scm:svn:https://secure.reucon.net/svn/repos/asterisk-java/tags/asterisk-java-1.0.0-m2</developerConnection>
|
||||
</scm>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>reucon</id>
|
||||
<url>https://secure.reucon.net/nexus/content/repositories/opensource</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>reucon</id>
|
||||
<url>https://secure.reucon.net/nexus/content/repositories/opensource-snapshots</url>
|
||||
</snapshotRepository>
|
||||
<site>
|
||||
<id>reucon</id>
|
||||
<url>dav:https://secure.reucon.net/maven/projects/public/${artifactId}/${version}</url>
|
||||
</site>
|
||||
</distributionManagement>
|
||||
<issueManagement>
|
||||
<system>JIRA</system>
|
||||
<url>http://jira.reucon.org/browse/AJ</url>
|
||||
</issueManagement>
|
||||
<mailingLists>
|
||||
<mailingList>
|
||||
<name>Asterisk-Java User List</name>
|
||||
<subscribe>http://lists.sourceforge.net/mailman/listinfo/asterisk-java-users</subscribe>
|
||||
<unsubscribe>http://lists.sourceforge.net/mailman/listinfo/asterisk-java-users</unsubscribe>
|
||||
<archive>http://sourceforge.net/mailarchive/forum.php?forum=asterisk-java-users</archive>
|
||||
</mailingList>
|
||||
<mailingList>
|
||||
<name>Asterisk-Java Developer List</name>
|
||||
<subscribe>http://lists.sourceforge.net/mailman/listinfo/asterisk-java-devel</subscribe>
|
||||
<unsubscribe>http://lists.sourceforge.net/mailman/listinfo/asterisk-java-devel</unsubscribe>
|
||||
<archive>http://sourceforge.net/mailarchive/forum.php?forum=asterisk-java-devel</archive>
|
||||
</mailingList>
|
||||
</mailingLists>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.0-beta-9</version>
|
||||
<configuration>
|
||||
<remoteTagging>true</remoteTagging>
|
||||
<preparationGoals>clean install</preparationGoals>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<tagBase>https://secure.reucon.net/svn/repos/${artifactId}/tags</tagBase>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>org.asteriskjava.Cli</mainClass>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<Class-Path>.</Class-Path>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.2-beta-2</version>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/bin.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>attached</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<version>2.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<extensions>
|
||||
<extension>
|
||||
<groupId>org.apache.maven.wagon</groupId>
|
||||
<artifactId>wagon-webdav</artifactId>
|
||||
<version>1.0-beta-2</version>
|
||||
</extension>
|
||||
</extensions>
|
||||
<finalName>${artifactId}</finalName>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymock</artifactId>
|
||||
<version>2.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.14</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<groups>
|
||||
<group>
|
||||
<title>Core Packages</title>
|
||||
<packages>
|
||||
org.asteriskjava:org.asteriskjava.fastagi:org.asteriskjava.fastagi.command:org.asteriskjava.fastagi.reply:org.asteriskjava.manager:org.asteriskjava.manager.action:org.asteriskjava.manager.response:org.asteriskjava.manager.event:org.asteriskjava.live:org.asteriskjava.util
|
||||
</packages>
|
||||
</group>
|
||||
<group>
|
||||
<title>Internal Packages</title>
|
||||
<packages>
|
||||
org.asteriskjava.fastagi.internal:org.asteriskjava.manager.internal:org.asteriskjava.live.internal:org.asteriskjava.util.internal
|
||||
</packages>
|
||||
</group>
|
||||
</groups>
|
||||
<header>${project.name}</header>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<formats>
|
||||
<format>html</format>
|
||||
<format>xml</format>
|
||||
</formats>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>jxr-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>surefire-report-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>changelog-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<configuration>
|
||||
<targetJdk>1.5</targetJdk>
|
||||
<minimumTokens>100</minimumTokens>
|
||||
<linkXRef>true</linkXRef>
|
||||
<rulesets>
|
||||
<ruleset>/rulesets/basic.xml</ruleset>
|
||||
</rulesets>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>1.2</version>
|
||||
</plugin>
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>jdepend-maven-plugin</artifactId>
|
||||
<version>2.0-beta-1-SNAPSHOT</version>
|
||||
</plugin>
|
||||
-->
|
||||
</plugins>
|
||||
</reporting>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>release</name>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<!-- Add to the command line:
|
||||
-Dkeystore=Stefan_Reuter_Code_Signing.jks
|
||||
-Dstorepass=secret
|
||||
-->
|
||||
<alias>Stefan_Reuter_Code_Signing</alias>
|
||||
<verify>true</verify>
|
||||
<!--
|
||||
<keystore>Stefan_Reuter_Code_Signing.jks</keystore>
|
||||
<storepass>secret</storepass>
|
||||
-->
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
6
asteriskjava/src/integrationtest/log4j.properties
Normal file
6
asteriskjava/src/integrationtest/log4j.properties
Normal file
@ -0,0 +1,6 @@
|
||||
log4j.rootCategory=INFO, Console
|
||||
log4j.category.org.asteriskjava.live=DEBUG
|
||||
|
||||
log4j.appender.Console=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.Console.layout.ConversionPattern=%d %c %p [%t] - %m\n
|
@ -0,0 +1,31 @@
|
||||
package org.asteriskjava.fastagi;
|
||||
|
||||
import org.asteriskjava.manager.DefaultManagerConnection;
|
||||
import org.asteriskjava.manager.ManagerConnection;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class GetDataScript extends BaseAgiScript
|
||||
{
|
||||
public void service(AgiRequest request, AgiChannel channel) throws AgiException
|
||||
{
|
||||
channel.streamFile("tt-monkeys");
|
||||
channel.sayDateTime(new Date().getTime());
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
ManagerConnection connection;
|
||||
AsyncAgiServer agiServer;
|
||||
|
||||
connection = new DefaultManagerConnection("localhost", "manager", "obelisk");
|
||||
agiServer = new AsyncAgiServer(new GetDataScript());
|
||||
connection.addEventListener(agiServer);
|
||||
connection.login();
|
||||
|
||||
while (true)
|
||||
{
|
||||
Thread.sleep(1000L);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package org.asteriskjava.fastagi;
|
||||
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.asteriskjava.live.DefaultAsteriskServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class HangupTest extends BaseAgiScript
|
||||
{
|
||||
private Logger logger = Logger.getLogger(HangupTest.class);
|
||||
|
||||
public void service(AgiRequest request, AgiChannel channel) throws AgiException
|
||||
{
|
||||
System.out.println(Arrays.toString(request.getArguments()));
|
||||
answer();
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < 5000; i++)
|
||||
{
|
||||
System.out.println("Saying " + i);
|
||||
sayDigits(String.valueOf(i));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.info("Exception caught: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException
|
||||
{
|
||||
AgiServerThread agiServerThread = new AgiServerThread();
|
||||
agiServerThread.setAgiServer(new DefaultAgiServer());
|
||||
agiServerThread.setDaemon(false);
|
||||
agiServerThread.startup();
|
||||
|
||||
DefaultAsteriskServer server = new DefaultAsteriskServer("localhost", 1234, "manager", "obelisk");
|
||||
server.initialize();
|
||||
server.originateToApplication("SIP/phone-02", "AGI",
|
||||
"agi://" + InetAddress.getLocalHost().getHostAddress() + "/" + HangupTest.class.getName()
|
||||
+ ", arg1,,arg3", 30000);
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
package org.asteriskjava.fastagi;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SpeechDemo extends BaseAgiScript
|
||||
{
|
||||
// the digits grammar is shipped as part of the Lumenvox engine
|
||||
private final String grammarPath = "/etc/lumenvox/Lang/BuiltinGrammars/ABNFDigits.gram";
|
||||
|
||||
public void service(AgiRequest request, AgiChannel channel) throws AgiException
|
||||
{
|
||||
try
|
||||
{
|
||||
// answer the call
|
||||
answer();
|
||||
|
||||
// and say hello
|
||||
streamFile("speech-demo/welcome");
|
||||
|
||||
// initialize the speech engine
|
||||
speechCreate();
|
||||
}
|
||||
catch (AgiHangupException e)
|
||||
{
|
||||
System.out.println("User hung up.");
|
||||
}
|
||||
catch (AgiSpeechException e)
|
||||
{
|
||||
System.out.println("Unable to initialize speech engine: no speech engine installed or licence trouble.");
|
||||
streamFile("speech-demo/engine-error");
|
||||
hangup();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
recognizeDigits();
|
||||
}
|
||||
}
|
||||
catch (AgiHangupException e)
|
||||
{
|
||||
System.out.println("User hung up.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
// make sure to destroy the speech object otherwise licenses might leak.
|
||||
speechDestroy();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// swallow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void recognizeDigits() throws AgiException
|
||||
{
|
||||
final String grammarLabel = "digits";
|
||||
|
||||
// load the grammar we are going the use
|
||||
speechLoadGrammar(grammarLabel, grammarPath);
|
||||
|
||||
// active it
|
||||
speechActivateGrammar(grammarLabel);
|
||||
|
||||
// and use if for recognition
|
||||
SpeechRecognitionResult result = speechRecognize("speech-demo/prompt", 10);
|
||||
System.out.println(result);
|
||||
|
||||
// deactivate the grammar
|
||||
speechDeactivateGrammar(grammarLabel);
|
||||
|
||||
// check whether speech was recognized or a DTMF digit was pressed
|
||||
if (result.isSpeech())
|
||||
{
|
||||
// if speech was recognized look at the confidence score
|
||||
if (result.getScore() > 990)
|
||||
{
|
||||
streamFile("speech-demo/absolutely-sure");
|
||||
}
|
||||
else if (result.getScore() > 800)
|
||||
{
|
||||
streamFile("speech-demo/pretty-sure");
|
||||
}
|
||||
else
|
||||
{
|
||||
streamFile("speech-demo/not-sure");
|
||||
}
|
||||
|
||||
// say what we have recognized
|
||||
sayDigits(result.getText());
|
||||
}
|
||||
else if (result.isDtmf())
|
||||
{
|
||||
// if the user pressed a DTMF digit
|
||||
streamFile("speech-demo/dtmf");
|
||||
|
||||
// read it back to him
|
||||
if (result.getDigit() == '*')
|
||||
{
|
||||
streamFile("digits/star");
|
||||
}
|
||||
else if (result.getDigit() == '#')
|
||||
{
|
||||
streamFile("digits/pound");
|
||||
}
|
||||
else
|
||||
{
|
||||
sayDigits(Character.toString(result.getDigit()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we received no input play an error message
|
||||
streamFile("speech-demo/no-input");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException
|
||||
{
|
||||
AgiServerThread agiServerThread = new AgiServerThread();
|
||||
agiServerThread.setAgiServer(new DefaultAgiServer());
|
||||
agiServerThread.setDaemon(false);
|
||||
agiServerThread.startup();
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.live;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class AsteriskServerTestCase extends TestCase
|
||||
{
|
||||
protected AsteriskServer server;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
server = new DefaultAsteriskServer("pbx0", "manager", "obelisk");
|
||||
//server = new DefaultAsteriskServer("localhost", "manager", "obelisk");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
server.getManagerConnection().logoff();
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package org.asteriskjava.live;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class MeetMeTest extends AsteriskServerTestCase
|
||||
{
|
||||
public void testMeetMeRoom() throws Exception
|
||||
{
|
||||
server.originateToExtension("Local/1201@basa", "conference", "1000", 1, 5000L);
|
||||
|
||||
server.getMeetMeRoom("1000");
|
||||
printRooms();
|
||||
System.out.println("waiting...");
|
||||
Thread.sleep(20000);
|
||||
printRooms();
|
||||
}
|
||||
|
||||
private void printRooms() throws Exception
|
||||
{
|
||||
Collection<MeetMeRoom> rooms;
|
||||
rooms = server.getMeetMeRooms();
|
||||
for (MeetMeRoom room : rooms)
|
||||
{
|
||||
System.out.println(room);
|
||||
for (MeetMeUser user : room.getUsers())
|
||||
{
|
||||
System.out.println(" " + user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Oct 28, 2004
|
||||
*/
|
||||
package org.asteriskjava.live;
|
||||
|
||||
import org.asteriskjava.config.ConfigFile;
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: MiscTest.java 991 2008-03-08 10:10:34Z srt $
|
||||
*/
|
||||
public class MiscTest extends AsteriskServerTestCase
|
||||
{
|
||||
public void testGlobalVariables() throws Exception
|
||||
{
|
||||
server.setGlobalVariable("AJ_TEST_VAR", "foobar");
|
||||
assertEquals("foobar", server.getGlobalVariable("AJ_TEST_VAR"));
|
||||
}
|
||||
|
||||
public void testFunctions() throws Exception
|
||||
{
|
||||
System.err.println(server.getGlobalVariable("DB(/Agents,1301)"));
|
||||
}
|
||||
|
||||
public void testGetVoicemailboxes() throws Exception
|
||||
{
|
||||
System.err.println("mailboxes: " + server.getVoicemailboxes());
|
||||
}
|
||||
|
||||
public void testGetConfig() throws Exception
|
||||
{
|
||||
ConfigFile config;
|
||||
|
||||
config = server.getConfig("voicemail.conf");
|
||||
assertEquals("voicemail.conf", config.getFilename());
|
||||
|
||||
System.err.println(config.getCategories());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Oct 28, 2004
|
||||
*/
|
||||
package org.asteriskjava.live;
|
||||
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: OriginateCauseAsyncTest.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class OriginateCauseAsyncTest extends AsteriskServerTestCase
|
||||
{
|
||||
private MyStatus status;
|
||||
private MyOriginateCallback cb;
|
||||
private Long timeout = 10000L;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
status = new MyStatus();
|
||||
cb = new MyOriginateCallback();
|
||||
}
|
||||
|
||||
public void testOriginateFailure() throws Exception
|
||||
{
|
||||
synchronized (status)
|
||||
{
|
||||
server.originateToExtensionAsync("Local/none@aj-test", "aj-test", "answer", 1, timeout, cb);
|
||||
status.wait();
|
||||
assertNotNull(status.failureException);
|
||||
}
|
||||
}
|
||||
|
||||
public void testOriginateSuccess() throws Exception
|
||||
{
|
||||
synchronized (status)
|
||||
{
|
||||
server.originateToExtensionAsync("Local/answer@aj-test", "aj-test", "answer", 1, timeout, cb);
|
||||
status.wait();
|
||||
status.print();
|
||||
assertNotNull(status.dialingChannel);
|
||||
assertNotNull(status.successChannel);
|
||||
}
|
||||
}
|
||||
|
||||
public void testOriginateBusy() throws Exception
|
||||
{
|
||||
synchronized (status)
|
||||
{
|
||||
server.originateToExtensionAsync("Local/busy@aj-test", "aj-test", "answer", 1, timeout, cb);
|
||||
status.wait();
|
||||
status.print();
|
||||
assertNotNull(status.busyChannel);
|
||||
}
|
||||
}
|
||||
|
||||
public void testOriginateCongestion() throws Exception
|
||||
{
|
||||
synchronized (status)
|
||||
{
|
||||
server.originateToExtensionAsync("Local/congestion@aj-test", "aj-test", "answer", 1, timeout, cb);
|
||||
status.wait();
|
||||
status.print();
|
||||
// congestion is treated like busy
|
||||
assertNotNull(status.busyChannel);
|
||||
}
|
||||
}
|
||||
|
||||
public void testOriginateNoAnswer() throws Exception
|
||||
{
|
||||
synchronized (status)
|
||||
{
|
||||
server.originateToExtensionAsync("Local/noanswer@aj-test", "aj-test", "answer", 1, timeout, cb);
|
||||
status.wait();
|
||||
status.print();
|
||||
assertNotNull(status.noAnswerChannel);
|
||||
}
|
||||
}
|
||||
|
||||
void showInfo(AsteriskChannel channel)
|
||||
{
|
||||
String name;
|
||||
String otherName;
|
||||
AsteriskChannel otherChannel;
|
||||
|
||||
System.err.println("linkedChannelHistory: " + channel.getLinkedChannelHistory());
|
||||
System.err.println("dialedChannelHistory: " + channel.getDialedChannelHistory());
|
||||
|
||||
name = channel.getName();
|
||||
if (name.startsWith("Local/"))
|
||||
{
|
||||
otherName = name.substring(0, name.length() - 1) + "2";
|
||||
System.err.println("other name: " + otherName);
|
||||
try
|
||||
{
|
||||
otherChannel = server.getChannelByName(otherName);
|
||||
}
|
||||
catch (ManagerCommunicationException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
System.err.println("other channel: " + otherChannel);
|
||||
System.err.println("other dialedChannel: " + otherChannel.getDialedChannel());
|
||||
System.err.println("other linkedChannelHistory: " + otherChannel.getLinkedChannelHistory());
|
||||
System.err.println("other dialedChannelHistory: " + otherChannel.getDialedChannelHistory());
|
||||
}
|
||||
}
|
||||
|
||||
class MyOriginateCallback implements OriginateCallback
|
||||
{
|
||||
boolean sealed = false;
|
||||
|
||||
public void onDialing(AsteriskChannel channel)
|
||||
{
|
||||
status.dialingChannel = channel;
|
||||
}
|
||||
|
||||
public void onFailure(LiveException cause)
|
||||
{
|
||||
status.failureException = cause;
|
||||
doNotify();
|
||||
}
|
||||
|
||||
public void onBusy(AsteriskChannel channel)
|
||||
{
|
||||
status.busyChannel = channel;
|
||||
doNotify();
|
||||
}
|
||||
|
||||
public void onNoAnswer(AsteriskChannel channel)
|
||||
{
|
||||
status.noAnswerChannel = channel;
|
||||
doNotify();
|
||||
}
|
||||
|
||||
public void onSuccess(AsteriskChannel channel)
|
||||
{
|
||||
status.successChannel = channel;
|
||||
doNotify();
|
||||
}
|
||||
|
||||
void doNotify()
|
||||
{
|
||||
if (sealed)
|
||||
{
|
||||
System.err.println("!!! Modifying sealed status !!!");
|
||||
}
|
||||
|
||||
sealed = true;
|
||||
synchronized (status)
|
||||
{
|
||||
status.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MyStatus
|
||||
{
|
||||
AsteriskChannel dialingChannel;
|
||||
AsteriskChannel busyChannel;
|
||||
AsteriskChannel noAnswerChannel;
|
||||
AsteriskChannel successChannel;
|
||||
LiveException failureException;
|
||||
|
||||
void print()
|
||||
{
|
||||
System.out.println("dialing = " + dialingChannel);
|
||||
System.out.println("busy = " + busyChannel);
|
||||
System.out.println("noAnswer = " + noAnswerChannel);
|
||||
System.out.println("success = " + successChannel);
|
||||
System.out.println("failure = " + failureException);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Oct 28, 2004
|
||||
*/
|
||||
package org.asteriskjava.live;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: OriginateCauseTest.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class OriginateCauseTest extends AsteriskServerTestCase
|
||||
{
|
||||
private AsteriskChannel channel;
|
||||
private Long timeout = 10000L;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
this.channel = null;
|
||||
}
|
||||
|
||||
public void xtestOriginateInvalidSourceChannel() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
server.originateToExtension("Local/none@aj-test", "aj-test", "answer", 1, timeout);
|
||||
fail("Originating from an invalid source channel must throw a NoSuchChannelException");
|
||||
}
|
||||
catch (NoSuchChannelException e)
|
||||
{
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
public void testOriginate() throws Exception
|
||||
{
|
||||
AsteriskChannel channel;
|
||||
|
||||
channel = server.originateToExtension("Local/answer@aj-test", "aj-test-delayed", "answer", 1, timeout);
|
||||
System.err.println(channel);
|
||||
|
||||
Thread.sleep(20000L);
|
||||
System.err.println(channel);
|
||||
}
|
||||
|
||||
public void xtestOriginateAsync() throws Exception
|
||||
{
|
||||
final String source;
|
||||
|
||||
//source = "SIP/1310";
|
||||
source = "Local/1337@from-local";
|
||||
// source = "Local/1310@from-local/n";
|
||||
server.originateToExtensionAsync(source, "conference", "1399", 1, timeout, new CallerId("AJ Test Call",
|
||||
"08003301000"), null, new OriginateCallback()
|
||||
{
|
||||
public void onDialing(final AsteriskChannel c)
|
||||
{
|
||||
channel = c;
|
||||
System.err.println("Dialing: " + channel);
|
||||
channel.addPropertyChangeListener(new PropertyChangeListener()
|
||||
{
|
||||
public void propertyChange(PropertyChangeEvent evt)
|
||||
{
|
||||
System.err.println("PropertyChange (" + ((AsteriskChannel) evt.getSource()).getName() + ") " + evt.getPropertyName() + ": " + evt.getOldValue() + " => " + evt.getNewValue());
|
||||
}
|
||||
});
|
||||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
scheduler.schedule(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
System.out.println("Tata");
|
||||
try
|
||||
{
|
||||
c.hangup();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void onSuccess(AsteriskChannel c)
|
||||
{
|
||||
channel = c;
|
||||
System.err.println("Success: " + c);
|
||||
showInfo(c);
|
||||
try
|
||||
{
|
||||
/*
|
||||
c.setVariable(AsteriskChannel.VARIABLE_MONITOR_EXEC, "/usr/local/bin/2wav2mp3");
|
||||
c.setVariable(AsteriskChannel.VARIABLE_MONITOR_EXEC_ARGS, "a b");
|
||||
c.startMonitoring("mtest", "wav", true);
|
||||
Thread.sleep(10000L);
|
||||
c.stopMonitoring();
|
||||
c.setAbsoluteTimeout(20);
|
||||
*/
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void onNoAnswer(AsteriskChannel c)
|
||||
{
|
||||
channel = c;
|
||||
System.err.println("No Answer: " + c);
|
||||
showInfo(c);
|
||||
}
|
||||
|
||||
public void onBusy(AsteriskChannel c)
|
||||
{
|
||||
channel = c;
|
||||
System.err.println("Busy: " + c);
|
||||
showInfo(c);
|
||||
}
|
||||
|
||||
public void onFailure(LiveException cause)
|
||||
{
|
||||
System.err.println("Failed: " + cause.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
Thread.sleep(20000L);
|
||||
System.err.println("final state: " + channel);
|
||||
if (channel != null)
|
||||
{
|
||||
System.err.println("final state linked channels: " + channel.getLinkedChannelHistory());
|
||||
}
|
||||
}
|
||||
|
||||
void showInfo(AsteriskChannel channel)
|
||||
{
|
||||
String name;
|
||||
String otherName;
|
||||
AsteriskChannel otherChannel;
|
||||
|
||||
System.err.println("linkedChannelHistory: " + channel.getLinkedChannelHistory());
|
||||
System.err.println("dialedChannelHistory: " + channel.getDialedChannelHistory());
|
||||
|
||||
name = channel.getName();
|
||||
if (name.startsWith("Local/"))
|
||||
{
|
||||
otherName = name.substring(0, name.length() - 1) + "2";
|
||||
System.err.println("other name: " + otherName);
|
||||
try
|
||||
{
|
||||
otherChannel = server.getChannelByName(otherName);
|
||||
}
|
||||
catch (ManagerCommunicationException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
System.err.println("other channel: " + otherChannel);
|
||||
System.err.println("other dialedChannel: " + otherChannel.getDialedChannel());
|
||||
System.err.println("other linkedChannelHistory: " + otherChannel.getLinkedChannelHistory());
|
||||
System.err.println("other dialedChannelHistory: " + otherChannel.getDialedChannelHistory());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Oct 28, 2004
|
||||
*/
|
||||
package org.asteriskjava.live;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: OriginateTest.java 1315 2009-06-02 22:36:54Z srt $
|
||||
*/
|
||||
public class OriginateTest extends AsteriskServerTestCase
|
||||
{
|
||||
private AsteriskChannel channel;
|
||||
private Long timeout = 20000L;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
this.channel = null;
|
||||
}
|
||||
|
||||
public void xtestOriginate() throws Exception
|
||||
{
|
||||
AsteriskChannel channel;
|
||||
channel = server.originateToExtension("SIP/1310", "from-local", "1330", 1, timeout);
|
||||
System.err.println(channel);
|
||||
System.err.println(channel.getVariable("AJ_TRACE_ID"));
|
||||
|
||||
Thread.sleep(20000L);
|
||||
System.err.println(channel);
|
||||
System.err.println(channel.getVariable("AJ_TRACE_ID"));
|
||||
}
|
||||
|
||||
public void testOriginateAsync() throws Exception
|
||||
{
|
||||
final String source;
|
||||
|
||||
//source = "SIP/1310";
|
||||
source = "Local/1218@from-local";
|
||||
// source = "Local/1310@from-local/n";
|
||||
server.originateToExtensionAsync(source, "from-local", "1299", 1, timeout, new CallerId("AJ Test Call",
|
||||
"08003301000"), null, new OriginateCallback()
|
||||
{
|
||||
public void onDialing(final AsteriskChannel c)
|
||||
{
|
||||
channel = c;
|
||||
System.err.println("Dialing: " + channel);
|
||||
channel.addPropertyChangeListener(new PropertyChangeListener()
|
||||
{
|
||||
public void propertyChange(PropertyChangeEvent evt)
|
||||
{
|
||||
System.err.println("PropertyChange (" + ((AsteriskChannel) evt.getSource()).getName() + ") " + evt.getPropertyName() + ": " + evt.getOldValue() + " => " + evt.getNewValue());
|
||||
}
|
||||
});
|
||||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
scheduler.schedule(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
System.out.println("Tata");
|
||||
try
|
||||
{
|
||||
System.out.println("Hanging up channel from onDial " + c);
|
||||
c.hangup();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void onSuccess(AsteriskChannel c)
|
||||
{
|
||||
channel = c;
|
||||
System.err.println("Success: " + c);
|
||||
showInfo(c);
|
||||
try
|
||||
{
|
||||
/*
|
||||
c.setVariable(AsteriskChannel.VARIABLE_MONITOR_EXEC, "/usr/local/bin/2wav2mp3");
|
||||
c.setVariable(AsteriskChannel.VARIABLE_MONITOR_EXEC_ARGS, "a b");
|
||||
c.startMonitoring("mtest", "wav", true);
|
||||
Thread.sleep(10000L);
|
||||
c.stopMonitoring();
|
||||
c.setAbsoluteTimeout(20);
|
||||
*/
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void onNoAnswer(AsteriskChannel c)
|
||||
{
|
||||
channel = c;
|
||||
System.err.println("No Answer: " + c);
|
||||
showInfo(c);
|
||||
}
|
||||
|
||||
public void onBusy(AsteriskChannel c)
|
||||
{
|
||||
channel = c;
|
||||
System.err.println("Busy: " + c);
|
||||
showInfo(c);
|
||||
}
|
||||
|
||||
public void onFailure(LiveException cause)
|
||||
{
|
||||
System.err.println("Failed: " + cause.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
Thread.sleep(20000L);
|
||||
System.err.println("final state: " + channel);
|
||||
if (channel != null)
|
||||
{
|
||||
System.err.println("final state linked channels: " + channel.getLinkedChannelHistory());
|
||||
}
|
||||
}
|
||||
|
||||
void showInfo(AsteriskChannel channel)
|
||||
{
|
||||
String name;
|
||||
String otherName;
|
||||
AsteriskChannel otherChannel;
|
||||
|
||||
System.err.println("linkedChannelHistory: " + channel.getLinkedChannelHistory());
|
||||
System.err.println("dialedChannelHistory: " + channel.getDialedChannelHistory());
|
||||
|
||||
name = channel.getName();
|
||||
if (name.startsWith("Local/"))
|
||||
{
|
||||
otherName = name.substring(0, name.length() - 1) + "2";
|
||||
System.err.println("other name: " + otherName);
|
||||
try
|
||||
{
|
||||
otherChannel = server.getChannelByName(otherName);
|
||||
}
|
||||
catch (ManagerCommunicationException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
System.err.println("other channel: " + otherChannel);
|
||||
System.err.println("other dialedChannel: " + otherChannel.getDialedChannel());
|
||||
System.err.println("other linkedChannelHistory: " + otherChannel.getLinkedChannelHistory());
|
||||
System.err.println("other dialedChannelHistory: " + otherChannel.getDialedChannelHistory());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Oct 28, 2004
|
||||
*/
|
||||
package org.asteriskjava.live;
|
||||
|
||||
import org.asteriskjava.manager.action.OriginateAction;
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: SofthangupTest.java 1087 2008-08-08 19:22:24Z srt $
|
||||
*/
|
||||
public class SofthangupTest extends AsteriskServerTestCase
|
||||
{
|
||||
public void testSofthangup() throws Exception
|
||||
{
|
||||
OriginateAction originate;
|
||||
|
||||
originate = new OriginateAction();
|
||||
originate.setChannel("Local/1310");
|
||||
originate.setContext("default");
|
||||
originate.setExten("1340");
|
||||
originate.setPriority(1);
|
||||
|
||||
//ManagerResponse response = managerConnection.sendAction(originate);
|
||||
//System.out.println("Response: " + response);
|
||||
|
||||
Thread.sleep(10000);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Oct 28, 2004
|
||||
*/
|
||||
package org.asteriskjava.live;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: TestDefaultAsteriskServer.java 1087 2008-08-08 19:22:24Z srt $
|
||||
*/
|
||||
public class TestDefaultAsteriskServer extends AsteriskServerTestCase
|
||||
{
|
||||
public void testGetChannels() throws Exception
|
||||
{
|
||||
System.out.println("waiting for channels...");
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(10000);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
}
|
||||
|
||||
Collection<AsteriskChannel> channels = server.getChannels();
|
||||
|
||||
System.out.println("got channels. waiting to hangup...");
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
}
|
||||
|
||||
for (AsteriskChannel channel : channels)
|
||||
{
|
||||
if (!channel.getName().startsWith("SIP/1310"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
System.out.println(channel);
|
||||
try
|
||||
{
|
||||
channel.redirectBothLegs("default", "1399", 1);
|
||||
//channel.hangup();
|
||||
}
|
||||
catch (NoSuchChannelException e)
|
||||
{
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void XtestGetQueues() throws Exception
|
||||
{
|
||||
System.out.println("waiting for queues...");
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(10000);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// swallow
|
||||
}
|
||||
|
||||
Collection<AsteriskQueue> queues = server.getQueues();
|
||||
for (AsteriskQueue queue : queues)
|
||||
{
|
||||
System.out.println(queue);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetVersion() throws Exception
|
||||
{
|
||||
System.out.println(Arrays.toString(server.getVersion("cdr_manager.c")));
|
||||
System.out.println(server.getVersion());
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Oct 28, 2004
|
||||
*/
|
||||
package org.asteriskjava.live;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: TestExtensionHistory.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class TestExtensionHistory extends AsteriskServerTestCase
|
||||
{
|
||||
public void testGetHistory() throws Exception
|
||||
{
|
||||
Collection<AsteriskChannel> channels;
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(5000);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
}
|
||||
|
||||
channels = server.getChannels();
|
||||
System.out.println("# of active channels: " + channels.size());
|
||||
for (AsteriskChannel channel : channels)
|
||||
{
|
||||
System.out.println(channel);
|
||||
System.out.println(" first extension: " + channel.getFirstExtension());
|
||||
System.out.println(" current extension: " + channel.getCurrentExtension());
|
||||
|
||||
for (ExtensionHistoryEntry extensionHistoryEntry : channel.getExtensionHistory())
|
||||
{
|
||||
System.out.println(" " + extensionHistoryEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Oct 28, 2004
|
||||
*/
|
||||
package org.asteriskjava.live;
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: TestLiveReconnect.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class TestLiveReconnect extends AsteriskServerTestCase
|
||||
{
|
||||
public void testLiveReconnect() throws Exception
|
||||
{
|
||||
System.out.println("Please stop and restart the Asterisk server...");
|
||||
while (true)
|
||||
{
|
||||
Thread.sleep(300000);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package org.asteriskjava.manager;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public abstract class AbstractManagerTestCase extends TestCase
|
||||
{
|
||||
protected DefaultManagerConnection getDefaultManagerConnection()
|
||||
{
|
||||
DefaultManagerConnection dmc;
|
||||
|
||||
dmc = new DefaultManagerConnection();
|
||||
dmc.setUsername("manager");
|
||||
dmc.setPassword("obelisk");
|
||||
dmc.setHostname("10.12.0.1");
|
||||
dmc.setPort(5038);
|
||||
|
||||
return dmc;
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Sep 24, 2004
|
||||
*/
|
||||
package org.asteriskjava.manager;
|
||||
|
||||
import org.asteriskjava.manager.action.CommandAction;
|
||||
import org.asteriskjava.manager.action.StatusAction;
|
||||
import org.asteriskjava.manager.action.VoicemailUsersListAction;
|
||||
import org.asteriskjava.manager.action.AgiAction;
|
||||
import org.asteriskjava.manager.event.ManagerEvent;
|
||||
import org.asteriskjava.manager.event.AsyncAgiEvent;
|
||||
import org.asteriskjava.manager.response.CommandResponse;
|
||||
import org.asteriskjava.manager.response.ManagerResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: TestAsyncAgi.java 956 2008-02-02 14:08:11Z srt $
|
||||
*/
|
||||
public class TestAsyncAgi extends AbstractManagerTestCase
|
||||
{
|
||||
public void testDialplanShow() throws Exception
|
||||
{
|
||||
DefaultManagerConnection managerConnection;
|
||||
|
||||
managerConnection = getDefaultManagerConnection();
|
||||
managerConnection.login();
|
||||
|
||||
CommandAction commandAction = new CommandAction("sip show peers");
|
||||
ManagerResponse response = managerConnection.sendAction(commandAction);
|
||||
if (response instanceof CommandResponse)
|
||||
{
|
||||
for (String item : ((CommandResponse) response).getResult())
|
||||
{
|
||||
System.out.println(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testAgiAction() throws Exception
|
||||
{
|
||||
DefaultManagerConnection dmc;
|
||||
|
||||
dmc = getDefaultManagerConnection();
|
||||
dmc.addEventListener(new ManagerEventListener()
|
||||
{
|
||||
public void onManagerEvent(ManagerEvent event)
|
||||
{
|
||||
System.out.println("Got event: " + event);
|
||||
if (event instanceof AsyncAgiEvent)
|
||||
{
|
||||
System.out.println("Decoded env: " + ((AsyncAgiEvent) event).decodeEnv());
|
||||
}
|
||||
}
|
||||
});
|
||||
dmc.login();
|
||||
System.out.println("Dial 1296");
|
||||
Thread.sleep(5000);
|
||||
ManagerResponse response = dmc.sendAction(new AgiAction(
|
||||
"IAX2/iax0-cgn_reucon_net-2",
|
||||
"EXEC Playback tt-monkeysintro",
|
||||
"myCommandId"));
|
||||
System.out.println(response);
|
||||
|
||||
// wait to receive events
|
||||
Thread.sleep(20000);
|
||||
dmc.logoff();
|
||||
Thread.sleep(3000);
|
||||
}
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Sep 24, 2004
|
||||
*/
|
||||
package org.asteriskjava.manager;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.asteriskjava.manager.action.StatusAction;
|
||||
import org.asteriskjava.manager.event.ManagerEvent;
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: TestConcurrentUseOfDefaultManagerConnection.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class TestConcurrentUseOfDefaultManagerConnection extends TestCase
|
||||
{
|
||||
private static final int NUM_THREADS = 400;
|
||||
private static final int NUM_LOOPS = 200;
|
||||
private DefaultManagerConnection dmc;
|
||||
private AtomicInteger succeeded;
|
||||
private AtomicInteger failed;
|
||||
private AtomicInteger total;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
dmc = new DefaultManagerConnection();
|
||||
dmc.setUsername("manager");
|
||||
dmc.setPassword("obelisk");
|
||||
dmc.setHostname("pbx0");
|
||||
|
||||
succeeded = new AtomicInteger(0);
|
||||
failed = new AtomicInteger(0);
|
||||
total = new AtomicInteger(0);
|
||||
|
||||
dmc.login();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
dmc.logoff();
|
||||
}
|
||||
|
||||
public void testConcurrency() throws Exception
|
||||
{
|
||||
Thread[] threads = new Thread[NUM_THREADS];
|
||||
long start;
|
||||
long end;
|
||||
|
||||
dmc.addEventListener(new ManagerEventListener()
|
||||
{
|
||||
public void onManagerEvent(ManagerEvent event)
|
||||
{
|
||||
//System.out.println("Got event: " + event);
|
||||
}
|
||||
});
|
||||
dmc.setDefaultEventTimeout(20000);
|
||||
dmc.setDefaultResponseTimeout(20000);
|
||||
|
||||
for (int i = 0; i < NUM_THREADS; i++)
|
||||
{
|
||||
threads[i] = new Thread(new Sender());
|
||||
threads[i].setName("Sender-" + i);
|
||||
}
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
for (int i = 0; i < NUM_THREADS; i++)
|
||||
{
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_THREADS; i++)
|
||||
{
|
||||
threads[i].join();
|
||||
}
|
||||
end = System.currentTimeMillis();
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
System.out.println("succeeded: " + succeeded);
|
||||
System.out.println("failed: " + failed);
|
||||
System.out.println("total: " + total);
|
||||
System.out.println("duration: " + (end - start));
|
||||
|
||||
assertEquals("failed actions", 0, failed.get());
|
||||
}
|
||||
|
||||
private class Sender implements Runnable
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
for (int i = 0; i < NUM_LOOPS; i++)
|
||||
{
|
||||
int id = total.getAndIncrement();
|
||||
String actionId = "A_" + id;
|
||||
try
|
||||
{
|
||||
/*
|
||||
PingAction a = new PingAction();
|
||||
a.setActionId(actionId);
|
||||
dmc.sendAction(a);
|
||||
succeeded.getAndIncrement();
|
||||
*/
|
||||
|
||||
ResponseEvents responseEvents;
|
||||
StatusAction a = new StatusAction();
|
||||
a.setActionId(actionId);
|
||||
responseEvents = dmc.sendEventGeneratingAction(a);
|
||||
if (responseEvents.getEvents().size() == 2)
|
||||
{
|
||||
succeeded.getAndIncrement();
|
||||
}
|
||||
else
|
||||
{
|
||||
failed.getAndIncrement();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
failed.getAndIncrement();
|
||||
System.err.println("Error for " + actionId);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Sep 24, 2004
|
||||
*/
|
||||
package org.asteriskjava.manager;
|
||||
|
||||
import org.asteriskjava.manager.action.CommandAction;
|
||||
import org.asteriskjava.manager.action.StatusAction;
|
||||
import org.asteriskjava.manager.action.SipShowPeerAction;
|
||||
import org.asteriskjava.manager.event.ManagerEvent;
|
||||
import org.asteriskjava.manager.response.CommandResponse;
|
||||
import org.asteriskjava.manager.response.SipShowPeerResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: TestDefaultManagerConnection.java 1242 2009-03-09 15:49:12Z srt $
|
||||
*/
|
||||
public class TestDefaultManagerConnection extends TestCase
|
||||
{
|
||||
private DefaultManagerConnection getDefaultManagerConnection()
|
||||
{
|
||||
DefaultManagerConnection dmc;
|
||||
|
||||
dmc = new DefaultManagerConnection();
|
||||
dmc.setUsername("manager");
|
||||
dmc.setPassword("obelisk");
|
||||
dmc.setHostname("pbx0.reucon.net");
|
||||
dmc.setPort(5038);
|
||||
//dmc.setSsl(true);
|
||||
|
||||
return dmc;
|
||||
}
|
||||
|
||||
public void XtestLogin() throws Exception
|
||||
{
|
||||
DefaultManagerConnection dmc;
|
||||
|
||||
dmc = getDefaultManagerConnection();
|
||||
dmc.login();
|
||||
dmc.addEventListener(new ManagerEventListener()
|
||||
{
|
||||
public void onManagerEvent(ManagerEvent event)
|
||||
{
|
||||
System.out.println("Got event: " + event);
|
||||
}
|
||||
});
|
||||
dmc.sendAction(new StatusAction());
|
||||
|
||||
// wait for 3 seconds to receive events
|
||||
Thread.sleep(3000);
|
||||
dmc.logoff();
|
||||
}
|
||||
|
||||
public void testMultipleLogins() throws Exception
|
||||
{
|
||||
DefaultManagerConnection dmc;
|
||||
CommandResponse response;
|
||||
|
||||
dmc = getDefaultManagerConnection();
|
||||
dmc.setDefaultResponseTimeout(5000);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
dmc.login();
|
||||
response = (CommandResponse) dmc.sendAction(new CommandAction("show version"));
|
||||
assertTrue("version does not start with \"Asterisk\"", response.getResult().get(0).startsWith("Asterisk"));
|
||||
dmc.logoff();
|
||||
}
|
||||
}
|
||||
|
||||
public void testLoginAuthenticationFailure() throws Exception
|
||||
{
|
||||
DefaultManagerConnection dmc;
|
||||
|
||||
dmc = getDefaultManagerConnection();
|
||||
dmc.setPassword("");
|
||||
|
||||
try
|
||||
{
|
||||
dmc.login();
|
||||
dmc.logoff();
|
||||
fail("No AuthenticationFailedException received.");
|
||||
}
|
||||
catch (AuthenticationFailedException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void testCommandAction() throws Exception
|
||||
{
|
||||
DefaultManagerConnection dmc;
|
||||
CommandResponse response;
|
||||
|
||||
dmc = getDefaultManagerConnection();
|
||||
dmc.login();
|
||||
|
||||
response = (CommandResponse) dmc.sendAction(new CommandAction("show voicemail users"));
|
||||
System.out.println("Got response: " + response.getResult());
|
||||
|
||||
dmc.logoff();
|
||||
}
|
||||
|
||||
public void testSipShowPeerAction() throws Exception
|
||||
{
|
||||
DefaultManagerConnection dmc;
|
||||
SipShowPeerResponse response;
|
||||
|
||||
dmc = getDefaultManagerConnection();
|
||||
dmc.login();
|
||||
|
||||
response = (SipShowPeerResponse) dmc.sendAction(new SipShowPeerAction("phone-02"));
|
||||
System.out.println("Got response: " + response);
|
||||
|
||||
dmc.logoff();
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Sep 24, 2004
|
||||
*/
|
||||
package org.asteriskjava.manager;
|
||||
|
||||
import org.asteriskjava.manager.action.CommandAction;
|
||||
import org.asteriskjava.manager.action.StatusAction;
|
||||
import org.asteriskjava.manager.action.VoicemailUsersListAction;
|
||||
import org.asteriskjava.manager.event.ManagerEvent;
|
||||
import org.asteriskjava.manager.response.CommandResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: TestVoicemailUsersListAction.java 947 2008-01-30 03:04:07Z srt $
|
||||
*/
|
||||
public class TestVoicemailUsersListAction extends AbstractManagerTestCase
|
||||
{
|
||||
public void testVoicemailUsersListAction() throws Exception
|
||||
{
|
||||
DefaultManagerConnection dmc;
|
||||
|
||||
dmc = getDefaultManagerConnection();
|
||||
dmc.login();
|
||||
ResponseEvents events = dmc.sendEventGeneratingAction(new VoicemailUsersListAction());
|
||||
|
||||
System.out.println(events.getResponse());
|
||||
for (ManagerEvent event : events.getEvents())
|
||||
{
|
||||
System.out.println(event);
|
||||
}
|
||||
|
||||
// wait for 3 seconds to receive events
|
||||
Thread.sleep(3000);
|
||||
dmc.logoff();
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* (c) 2004 Stefan Reuter
|
||||
*
|
||||
* Created on Sep 24, 2004
|
||||
*/
|
||||
package org.asteriskjava.manager;
|
||||
|
||||
import org.asteriskjava.manager.action.CommandAction;
|
||||
import org.asteriskjava.manager.action.StatusAction;
|
||||
import org.asteriskjava.manager.event.ManagerEvent;
|
||||
import org.asteriskjava.manager.response.CommandResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author srt
|
||||
* @version $Id: TestVoid.java 981 2008-02-14 03:44:49Z srt $
|
||||
*/
|
||||
public class TestVoid extends TestCase
|
||||
{
|
||||
private DefaultManagerConnection getDefaultManagerConnection()
|
||||
{
|
||||
DefaultManagerConnection dmc;
|
||||
|
||||
dmc = new DefaultManagerConnection();
|
||||
dmc.setUsername("manager");
|
||||
dmc.setPassword("obelisk");
|
||||
dmc.setHostname("pbx0.cologne.reucon.net");
|
||||
dmc.setPort(5038);
|
||||
|
||||
return dmc;
|
||||
}
|
||||
|
||||
public void testPrintEvents() throws Exception
|
||||
{
|
||||
DefaultManagerConnection dmc;
|
||||
|
||||
dmc = getDefaultManagerConnection();
|
||||
dmc.login();
|
||||
dmc.addEventListener(new ManagerEventListener()
|
||||
{
|
||||
public void onManagerEvent(ManagerEvent event)
|
||||
{
|
||||
System.out.println("Got event: " + event);
|
||||
}
|
||||
});
|
||||
// dmc.sendAction(new StatusAction());
|
||||
|
||||
Thread.sleep(30000);
|
||||
dmc.logoff();
|
||||
}
|
||||
}
|
28
asteriskjava/src/main/assembly/bin.xml
Normal file
28
asteriskjava/src/main/assembly/bin.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<assembly 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/xsd/assembly-1.1.0-SNAPSHOT.xsd">
|
||||
<id>bin</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<baseDirectory>${artifactId}-${version}</baseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<includes>
|
||||
<include>README*</include>
|
||||
<include>LICENSE*</include>
|
||||
<include>NOTICE*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>dist</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>target</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
128
asteriskjava/src/main/java/org/asteriskjava/AsteriskVersion.java
Normal file
128
asteriskjava/src/main/java/org/asteriskjava/AsteriskVersion.java
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represents the version of an Asterisk server.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AsteriskVersion.java 1087 2008-08-08 19:22:24Z srt $
|
||||
* @since 0.2
|
||||
*/
|
||||
public class AsteriskVersion implements Comparable<AsteriskVersion>, Serializable
|
||||
{
|
||||
private final int version;
|
||||
private final String versionString;
|
||||
|
||||
/**
|
||||
* Represents the Asterisk 1.0 series.
|
||||
*/
|
||||
public static final AsteriskVersion ASTERISK_1_0 = new AsteriskVersion(100, "Asterisk 1.0");
|
||||
|
||||
/**
|
||||
* Represents the Asterisk 1.2 series.
|
||||
*/
|
||||
public static final AsteriskVersion ASTERISK_1_2 = new AsteriskVersion(120, "Asterisk 1.2");
|
||||
|
||||
/**
|
||||
* Represents the Asterisk 1.4 series.
|
||||
*
|
||||
* @since 0.3
|
||||
*/
|
||||
public static final AsteriskVersion ASTERISK_1_4 = new AsteriskVersion(140, "Asterisk 1.4");
|
||||
|
||||
/**
|
||||
* Represents the Asterisk 1.6 series.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static final AsteriskVersion ASTERISK_1_6 = new AsteriskVersion(160, "Asterisk 1.6");
|
||||
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private AsteriskVersion(int version, String versionString)
|
||||
{
|
||||
this.version = version;
|
||||
this.versionString = versionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this version is equal to or higher than
|
||||
* the given version.
|
||||
*
|
||||
* @param o the version to compare to
|
||||
* @return <code>true</code> if this version is equal to or higher than
|
||||
* the given version, <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isAtLeast(AsteriskVersion o)
|
||||
{
|
||||
return version >= o.version;
|
||||
}
|
||||
|
||||
public int compareTo(AsteriskVersion o)
|
||||
{
|
||||
int otherVersion;
|
||||
|
||||
otherVersion = o.version;
|
||||
if (version < otherVersion)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (version > otherVersion)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AsteriskVersion that = (AsteriskVersion) o;
|
||||
|
||||
return version == that.version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return versionString;
|
||||
}
|
||||
}
|
135
asteriskjava/src/main/java/org/asteriskjava/Cli.java
Normal file
135
asteriskjava/src/main/java/org/asteriskjava/Cli.java
Normal file
@ -0,0 +1,135 @@
|
||||
package org.asteriskjava;
|
||||
|
||||
import org.asteriskjava.fastagi.DefaultAgiServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Simple command line interface for Asterisk-Java. This class is run when Asterisk-Java is started
|
||||
* with {@code java -jar asterisk-java.jar}. It is configured as Main-Class in the manifest.<p>
|
||||
* The command line interface supports the following options:
|
||||
* <dl>
|
||||
* <dt>{@code -a}, {@code -agi [port]}<dt>
|
||||
* <dd>Starts a FastAGI server</dd>
|
||||
*
|
||||
* <dt>{@code -h}, {@code -help}<dt>
|
||||
* <dd>Displays the available options</dd>
|
||||
*
|
||||
* <dt>{@code -v}, {@code -version}</dt>
|
||||
* <dd>Displays the version of Asterisk-Java</dd>
|
||||
* </dl>
|
||||
* If no option is given a FastAGI server is started on the default port.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class Cli
|
||||
{
|
||||
private void parseOptions(String[] args) throws Exception
|
||||
{
|
||||
if (args.length == 0)
|
||||
{
|
||||
startAgiServer();
|
||||
return;
|
||||
}
|
||||
|
||||
final String arg = args[0];
|
||||
if ("-h".equals(arg) || "-help".equals(arg))
|
||||
{
|
||||
showHelp();
|
||||
}
|
||||
else if ("-v".equals(arg) || "-version".equals(arg))
|
||||
{
|
||||
showVersion();
|
||||
}
|
||||
else if ("-a".equals(arg) || "-agi".equals(arg))
|
||||
{
|
||||
if (args.length >= 2)
|
||||
{
|
||||
Integer port = null;
|
||||
try
|
||||
{
|
||||
port = new Integer(args[1]);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
System.err.println("Invalid port '" + args[1] + "'. Port must be a number.");
|
||||
exit(1);
|
||||
}
|
||||
startAgiServer(port);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showHelp();
|
||||
}
|
||||
}
|
||||
|
||||
private void showHelp()
|
||||
{
|
||||
showVersion();
|
||||
System.err.println();
|
||||
System.err.println("-a, -agi [port]\n\tStarts a FastAGI server");
|
||||
System.err.println("-h, -help\n\tDisplays the available options\n");
|
||||
System.err.println("-v, -version\n\tDisplays the version of Asterisk-Java\n");
|
||||
}
|
||||
|
||||
private void showVersion()
|
||||
{
|
||||
System.out.println("Asterisk-Java " + getVersion());
|
||||
}
|
||||
|
||||
private String getVersion()
|
||||
{
|
||||
String version = "<unknown>";
|
||||
final InputStream is;
|
||||
final Properties properties;
|
||||
|
||||
is = getClass().getResourceAsStream("/META-INF/maven/org.asteriskjava/asterisk-java/pom.properties");
|
||||
if (is == null)
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
properties = new Properties();
|
||||
try
|
||||
{
|
||||
properties.load(is); // contains version, groupId and artifactId
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
version = properties.getProperty("version", version);
|
||||
return version;
|
||||
}
|
||||
|
||||
private void startAgiServer() throws IOException
|
||||
{
|
||||
startAgiServer(null);
|
||||
}
|
||||
|
||||
private void startAgiServer(Integer port) throws IOException
|
||||
{
|
||||
final DefaultAgiServer server;
|
||||
|
||||
server = new DefaultAgiServer();
|
||||
if (port != null)
|
||||
{
|
||||
server.setPort(port);
|
||||
}
|
||||
server.startup();
|
||||
}
|
||||
|
||||
private void exit(int code)
|
||||
{
|
||||
System.exit(code);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
new Cli().parseOptions(args);
|
||||
}
|
||||
}
|
140
asteriskjava/src/main/java/org/asteriskjava/config/Category.java
Normal file
140
asteriskjava/src/main/java/org/asteriskjava/config/Category.java
Normal file
@ -0,0 +1,140 @@
|
||||
package org.asteriskjava.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Category extends ConfigElement
|
||||
{
|
||||
private String name;
|
||||
private boolean template;
|
||||
private final List<Category> baseCategories = new ArrayList<Category>();
|
||||
private final List<ConfigElement> elements = new ArrayList<ConfigElement>();
|
||||
|
||||
/**
|
||||
* The last object in the list will get assigned any trailing comments when EOF is hit.
|
||||
*/
|
||||
//private String trailingComment;
|
||||
|
||||
public Category(String name)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Name must not be null");
|
||||
}
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Category(String filename, int lineno, String name)
|
||||
{
|
||||
super(filename, lineno);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this category.
|
||||
*
|
||||
* @return the name of this category.
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this category is a template.
|
||||
*
|
||||
* @return <code>true</code> if this category is a template, <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isTemplate()
|
||||
{
|
||||
return template;
|
||||
}
|
||||
|
||||
void markAsTemplate()
|
||||
{
|
||||
template = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of categories this category inherits from.
|
||||
*
|
||||
* @return a list of categories this category inherits from, never <code>null</code>.
|
||||
*/
|
||||
public List<Category> getBaseCategories()
|
||||
{
|
||||
return baseCategories;
|
||||
}
|
||||
|
||||
void addBaseCategory(Category baseCategory)
|
||||
{
|
||||
baseCategories.add(baseCategory);
|
||||
}
|
||||
|
||||
public List<ConfigElement> getElements()
|
||||
{
|
||||
return elements;
|
||||
}
|
||||
|
||||
public void addElement(ConfigElement element)
|
||||
{
|
||||
if (element instanceof Category)
|
||||
{
|
||||
throw new IllegalArgumentException("Nested categories are not allowed");
|
||||
}
|
||||
|
||||
elements.add(element);
|
||||
}
|
||||
|
||||
public String format()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
format(sb);
|
||||
for (ConfigElement e : elements)
|
||||
{
|
||||
sb.append("\n");
|
||||
e.format(sb);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StringBuilder rawFormat(StringBuilder sb)
|
||||
{
|
||||
sb.append("[").append(name).append("]");
|
||||
if (isTemplate() || !getBaseCategories().isEmpty())
|
||||
{
|
||||
sb.append("(");
|
||||
if (isTemplate())
|
||||
{
|
||||
sb.append("!");
|
||||
if (!getBaseCategories().isEmpty())
|
||||
{
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
Iterator<Category> inheritsFromIterator = getBaseCategories().iterator();
|
||||
while (inheritsFromIterator.hasNext())
|
||||
{
|
||||
sb.append(inheritsFromIterator.next().getName());
|
||||
if (inheritsFromIterator.hasNext())
|
||||
{
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package org.asteriskjava.config;
|
||||
|
||||
public abstract class ConfigDirective extends ConfigElement
|
||||
{
|
||||
protected ConfigDirective()
|
||||
{
|
||||
}
|
||||
|
||||
protected ConfigDirective(String filename, int lineno)
|
||||
{
|
||||
super(filename, lineno);
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package org.asteriskjava.config;
|
||||
|
||||
public abstract class ConfigElement
|
||||
{
|
||||
/**
|
||||
* Name of the file the category was read from.
|
||||
*/
|
||||
private String filename;
|
||||
|
||||
/**
|
||||
* Line number.
|
||||
*/
|
||||
private int lineno;
|
||||
private String preComment;
|
||||
private String samelineComment;
|
||||
|
||||
protected ConfigElement()
|
||||
{
|
||||
}
|
||||
|
||||
protected ConfigElement(String filename, int lineno)
|
||||
{
|
||||
this.filename = filename;
|
||||
this.lineno = lineno;
|
||||
}
|
||||
|
||||
public String getFileName()
|
||||
{
|
||||
return filename;
|
||||
}
|
||||
|
||||
public void setFileName(String filename)
|
||||
{
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public int getLineNumber()
|
||||
{
|
||||
return lineno;
|
||||
}
|
||||
|
||||
void setLineNumber(int lineno)
|
||||
{
|
||||
this.lineno = lineno;
|
||||
}
|
||||
|
||||
public String getPreComment()
|
||||
{
|
||||
return preComment;
|
||||
}
|
||||
|
||||
public void setPreComment(String preComment)
|
||||
{
|
||||
this.preComment = preComment;
|
||||
}
|
||||
|
||||
public String getComment()
|
||||
{
|
||||
return samelineComment;
|
||||
}
|
||||
|
||||
public void setComment(String samelineComment)
|
||||
{
|
||||
this.samelineComment = samelineComment;
|
||||
}
|
||||
|
||||
protected StringBuilder format(StringBuilder sb)
|
||||
{
|
||||
if (preComment != null && preComment.length() != 0)
|
||||
{
|
||||
sb.append(preComment);
|
||||
}
|
||||
|
||||
rawFormat(sb);
|
||||
|
||||
if (samelineComment != null && samelineComment.length() != 0)
|
||||
{
|
||||
sb.append(" ; ").append(samelineComment);
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
protected abstract StringBuilder rawFormat(StringBuilder sb);
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.config;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An Asterisk configuration file.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: ConfigFile.java 992 2008-03-08 23:31:13Z srt $
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface ConfigFile
|
||||
{
|
||||
/**
|
||||
* Returns the filename.
|
||||
*
|
||||
* @return the filename, for example "voicemail.conf".
|
||||
*/
|
||||
String getFilename();
|
||||
|
||||
/**
|
||||
* Returns the lines per category.
|
||||
*
|
||||
* @return the lines per category.
|
||||
*/
|
||||
Map<String, List<String>> getCategories();
|
||||
|
||||
String getValue(String category, String key);
|
||||
|
||||
List<String> getValues(String category, String key);
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.config;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* An Asterisk configuration file read from the filesystem.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: ConfigFileImpl.java 1044 2008-05-05 23:45:09Z msmith $
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ConfigFileImpl implements ConfigFile
|
||||
{
|
||||
private final String filename;
|
||||
protected final Map<String, Category> categories;
|
||||
|
||||
public ConfigFileImpl(String filename, Map<String, Category> categories)
|
||||
{
|
||||
this.filename = filename;
|
||||
this.categories = categories;
|
||||
}
|
||||
|
||||
public String getFilename()
|
||||
{
|
||||
return filename;
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getCategories()
|
||||
{
|
||||
final Map<String, List<String>> c;
|
||||
|
||||
c = new TreeMap<String, List<String>>();
|
||||
|
||||
synchronized (categories)
|
||||
{
|
||||
for (Category category : categories.values())
|
||||
{
|
||||
List<String> lines;
|
||||
|
||||
lines = new ArrayList<String>();
|
||||
for (ConfigElement element : category.getElements())
|
||||
{
|
||||
if (element instanceof ConfigVariable)
|
||||
{
|
||||
ConfigVariable cv = (ConfigVariable) element;
|
||||
lines.add(cv.getName() + "=" + cv.getValue());
|
||||
}
|
||||
}
|
||||
c.put(category.getName(), lines);
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public String getValue(String categoryName, String key)
|
||||
{
|
||||
final Category category;
|
||||
|
||||
category = getCategory(categoryName);
|
||||
if (category == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (ConfigElement element : category.getElements())
|
||||
{
|
||||
if (element instanceof ConfigVariable)
|
||||
{
|
||||
ConfigVariable cv = (ConfigVariable) element;
|
||||
|
||||
if (cv.getName().equals(key))
|
||||
{
|
||||
return cv.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getValues(String categoryName, String key)
|
||||
{
|
||||
final Category category;
|
||||
final List<String> result;
|
||||
|
||||
category = getCategory(categoryName);
|
||||
result = new ArrayList<String>();
|
||||
if (category == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
for (ConfigElement element : category.getElements())
|
||||
{
|
||||
if (element instanceof ConfigVariable)
|
||||
{
|
||||
ConfigVariable cv = (ConfigVariable) element;
|
||||
|
||||
if (cv.getName().equals(key))
|
||||
{
|
||||
result.add(cv.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Category getCategory(String name)
|
||||
{
|
||||
synchronized (categories)
|
||||
{
|
||||
return categories.get(name);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,492 @@
|
||||
package org.asteriskjava.config;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.CharBuffer;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Reads and parses Asterisk configuration files.
|
||||
* <p/>
|
||||
* See Asterisk's <code>main/config.c</code>.
|
||||
* <p/>
|
||||
* Client code is not supposed to use this class.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: ConfigFileReader.java 1140 2008-08-18 18:49:36Z srt $
|
||||
*/
|
||||
public class ConfigFileReader
|
||||
{
|
||||
private static final int MAX_LINE_LENGTH = 8192;
|
||||
private static char COMMENT_META = ';';
|
||||
private static char COMMENT_TAG = '-';
|
||||
private static final Set<Class> WARNING_CLASSES;
|
||||
|
||||
static
|
||||
{
|
||||
WARNING_CLASSES = new HashSet<Class>();
|
||||
WARNING_CLASSES.add(MissingEqualSignException.class);
|
||||
WARNING_CLASSES.add(UnknownDirectiveException.class);
|
||||
WARNING_CLASSES.add(MissingDirectiveParameterException.class);
|
||||
}
|
||||
|
||||
private StringBuilder commentBlock;
|
||||
protected final Map<String, Category> categories;
|
||||
private final List<ConfigParseException> warnings;
|
||||
|
||||
protected Category currentCategory;
|
||||
private int currentCommentLevel = 0;
|
||||
|
||||
public ConfigFileReader()
|
||||
{
|
||||
this.commentBlock = new StringBuilder();
|
||||
this.categories = new LinkedHashMap<String, Category>();
|
||||
this.warnings = new ArrayList<ConfigParseException>();
|
||||
}
|
||||
|
||||
public ConfigFile readFile(String configfile) throws IOException, ConfigParseException
|
||||
{
|
||||
final ConfigFile result;
|
||||
final BufferedReader reader;
|
||||
|
||||
reader = new BufferedReader(new FileReader(configfile));
|
||||
try
|
||||
{
|
||||
readFile(configfile, reader);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
reader.close();
|
||||
}
|
||||
catch (Exception e) // NOPMD
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
result = new ConfigFileImpl(configfile, new TreeMap<String, Category>(categories));
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
commentBlock = new StringBuilder();
|
||||
categories.clear();
|
||||
warnings.clear();
|
||||
currentCategory = null;
|
||||
currentCommentLevel = 0;
|
||||
}
|
||||
|
||||
Collection<Category> getCategories()
|
||||
{
|
||||
return categories.values();
|
||||
}
|
||||
|
||||
public Collection<ConfigParseException> getWarnings()
|
||||
{
|
||||
return new ArrayList<ConfigParseException>(warnings);
|
||||
}
|
||||
|
||||
void readFile(String configfile, BufferedReader reader) throws IOException, ConfigParseException
|
||||
{
|
||||
String line;
|
||||
int lineno = 0;
|
||||
CharBuffer buffer = CharBuffer.allocate(MAX_LINE_LENGTH);
|
||||
|
||||
reset();
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
lineno++;
|
||||
buffer.clear();
|
||||
buffer.put(line);
|
||||
buffer.put("\n");
|
||||
buffer.flip();
|
||||
|
||||
processLine(configfile, lineno, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigElement processLine(String configfile, int lineno, CharBuffer buffer) throws ConfigParseException
|
||||
{
|
||||
char c;
|
||||
final StringBuilder processLineBuilder;
|
||||
final StringBuilder lineCommentBuilder;
|
||||
|
||||
processLineBuilder = new StringBuilder(MAX_LINE_LENGTH);
|
||||
lineCommentBuilder = new StringBuilder(MAX_LINE_LENGTH);
|
||||
buffer.mark();
|
||||
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
final int position;
|
||||
|
||||
position = buffer.position();
|
||||
c = buffer.get();
|
||||
//System.out.println(position + ": " + c);
|
||||
|
||||
if (c == COMMENT_META)
|
||||
{
|
||||
if (position >= 1 && buffer.get(position - 1) == '\\')
|
||||
{
|
||||
/* Escaped semicolons aren't comments. */
|
||||
} // NOPMD
|
||||
else if (buffer.remaining() >= 3
|
||||
&& buffer.get(position + 1) == COMMENT_TAG
|
||||
&& buffer.get(position + 2) == COMMENT_TAG
|
||||
&& buffer.get(position + 3) != COMMENT_TAG)
|
||||
{
|
||||
/* Meta-Comment start detected ";--" */
|
||||
|
||||
currentCommentLevel++;
|
||||
//System.out.println("Comment start, new level: " + currentCommentLevel);
|
||||
|
||||
if (!inComment())
|
||||
{
|
||||
commentBlock.append(";--");
|
||||
buffer.position(position + 3);
|
||||
buffer.mark();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (inComment()
|
||||
&& position >= 2
|
||||
&& buffer.get(position - 1) == COMMENT_TAG
|
||||
&& buffer.get(position - 2) == COMMENT_TAG)
|
||||
{
|
||||
/* Meta-Comment end detected */
|
||||
|
||||
currentCommentLevel--;
|
||||
|
||||
if (!inComment())
|
||||
{
|
||||
buffer.reset();
|
||||
|
||||
//int commentLength = (position + 1) - buffer.position();
|
||||
|
||||
//buffer.reset();
|
||||
//for (int i = 0; i < commentLength; i++)
|
||||
//{
|
||||
// commentBlock.append(buffer.get());
|
||||
//}
|
||||
|
||||
commentBlock.append(c);
|
||||
//System.out.println("Comment end at " + position + ": '" + commentBlock.toString() + "'");
|
||||
|
||||
buffer.position(position + 1);
|
||||
buffer.compact();
|
||||
buffer.flip();
|
||||
|
||||
//System.out.println("Buffer compacted");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!inComment())
|
||||
{
|
||||
/* If ; is found, and we are not nested in a comment, we immediately stop all comment processing */
|
||||
//System.out.println("Found ; while not in comment");
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
lineCommentBuilder.append(buffer.get());
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Found ';' while in comment */
|
||||
} // NOPMD
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (inComment())
|
||||
{
|
||||
commentBlock.append(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
//System.out.println("Added '" + c + "' to processLine");
|
||||
processLineBuilder.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
String processLineString;
|
||||
String lineCommentString;
|
||||
ConfigElement configElement;
|
||||
|
||||
processLineString = processLineBuilder.toString().trim();
|
||||
lineCommentString = lineCommentBuilder.toString().trim();
|
||||
|
||||
//System.out.println("process line: '" + processLineString + "'");
|
||||
if (processLineString.length() == 0)
|
||||
{
|
||||
if (lineCommentString.length() != 0)
|
||||
{
|
||||
commentBlock.append(";");
|
||||
commentBlock.append(lineCommentString);
|
||||
}
|
||||
if (!inComment())
|
||||
{
|
||||
commentBlock.append("\n");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
configElement = processTextLine(configfile, lineno, processLineString);
|
||||
}
|
||||
catch (ConfigParseException e)
|
||||
{
|
||||
// some parsing exceptions are treated as warnings by Asterisk, we mirror this behavior.
|
||||
if (WARNING_CLASSES.contains(e.getClass()))
|
||||
{
|
||||
warnings.add(e);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (lineCommentString.length() != 0)
|
||||
{
|
||||
configElement.setComment(lineCommentString);
|
||||
}
|
||||
|
||||
if (commentBlock.length() != 0)
|
||||
{
|
||||
configElement.setPreComment(commentBlock.toString());
|
||||
commentBlock.delete(0, commentBlock.length());
|
||||
}
|
||||
|
||||
return configElement;
|
||||
}
|
||||
|
||||
boolean inComment()
|
||||
{
|
||||
return currentCommentLevel != 0;
|
||||
}
|
||||
|
||||
protected ConfigElement processTextLine(String configfile, int lineno, String line) throws ConfigParseException
|
||||
{
|
||||
ConfigElement configElement;
|
||||
|
||||
if (line.charAt(0) == '[') // A category header
|
||||
{
|
||||
configElement = parseCategoryHeader(configfile, lineno, line);
|
||||
}
|
||||
else if (line.charAt(0) == '#') // a directive - #include or #exec
|
||||
{
|
||||
configElement = parseDirective(configfile, lineno, line);
|
||||
}
|
||||
else // just a line
|
||||
{
|
||||
if (currentCategory == null)
|
||||
{
|
||||
throw new ConfigParseException(configfile, lineno,
|
||||
"parse error: No category context for line %d of %s", lineno, configfile);
|
||||
}
|
||||
|
||||
configElement = parseVariable(configfile, lineno, line);
|
||||
currentCategory.addElement(configElement);
|
||||
}
|
||||
|
||||
return configElement;
|
||||
}
|
||||
|
||||
protected Category parseCategoryHeader(String configfile, int lineno, String line) throws ConfigParseException
|
||||
{
|
||||
final Category category;
|
||||
final String name;
|
||||
final int nameEndPos;
|
||||
|
||||
/* format is one of the following:
|
||||
* [foo] define a new category named 'foo'
|
||||
* [foo](!) define a new template category named 'foo'
|
||||
* [foo](+) append to category 'foo', error if foo does not exist.
|
||||
* [foo](a) define a new category and inherit from template a.
|
||||
* You can put a comma-separated list of templates and '!' and '+'
|
||||
* between parentheses, with obvious meaning.
|
||||
*/
|
||||
|
||||
nameEndPos = line.indexOf(']');
|
||||
if (nameEndPos == -1)
|
||||
{
|
||||
throw new ConfigParseException(configfile, lineno,
|
||||
"parse error: no closing ']', line %d of %s", lineno, configfile);
|
||||
}
|
||||
name = line.substring(1, nameEndPos);
|
||||
category = new Category(configfile, lineno, name);
|
||||
|
||||
/* Handle options or categories to inherit from if available */
|
||||
if (line.length() > nameEndPos + 1 && line.charAt(nameEndPos + 1) == '(')
|
||||
{
|
||||
final String[] options;
|
||||
final String optionsString;
|
||||
final int optionsEndPos;
|
||||
|
||||
optionsString = line.substring(nameEndPos + 1);
|
||||
optionsEndPos = optionsString.indexOf(')');
|
||||
if (optionsEndPos == -1)
|
||||
{
|
||||
throw new ConfigParseException(configfile, lineno,
|
||||
"parse error: no closing ')', line %d of %s", lineno, configfile);
|
||||
}
|
||||
|
||||
options = optionsString.substring(1, optionsEndPos).split(",");
|
||||
for (String cur : options)
|
||||
{
|
||||
if ("!".equals(cur)) // category template
|
||||
{
|
||||
category.markAsTemplate();
|
||||
}
|
||||
else if ("+".equals(cur)) // category addition
|
||||
{
|
||||
final Category categoryToAddTo;
|
||||
|
||||
categoryToAddTo = categories.get(name);
|
||||
if (categoryToAddTo == null)
|
||||
{
|
||||
throw new ConfigParseException(configfile, lineno,
|
||||
"Category addition requested, but category '%s' does not exist, line %d of %s",
|
||||
name, lineno, configfile);
|
||||
}
|
||||
|
||||
//todo implement category addition
|
||||
//category = categoryToAddTo;
|
||||
}
|
||||
else
|
||||
{
|
||||
final Category baseCategory;
|
||||
|
||||
baseCategory = categories.get(cur);
|
||||
if (baseCategory == null)
|
||||
{
|
||||
throw new ConfigParseException(configfile, lineno,
|
||||
"Inheritance requested, but category '%s' does not exist, line %d of %s",
|
||||
cur, lineno, configfile);
|
||||
}
|
||||
inheritCategory(category, baseCategory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
appendCategory(category);
|
||||
return category;
|
||||
}
|
||||
|
||||
ConfigDirective parseDirective(String configfile, int lineno, String line) throws ConfigParseException
|
||||
{
|
||||
ConfigDirective directive;
|
||||
final StringBuilder nameBuilder;
|
||||
final StringBuilder paramBuilder;
|
||||
String name = null;
|
||||
String param;
|
||||
|
||||
nameBuilder = new StringBuilder();
|
||||
paramBuilder = new StringBuilder();
|
||||
for (int i = 1; i < line.length(); i++)
|
||||
{
|
||||
final char c;
|
||||
|
||||
c = line.charAt(i);
|
||||
if (name == null)
|
||||
{
|
||||
nameBuilder.append(c);
|
||||
if (Character.isWhitespace(c) || i + 1 == line.length())
|
||||
{
|
||||
name = nameBuilder.toString().trim();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
paramBuilder.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
param = paramBuilder.toString().trim();
|
||||
|
||||
if (param.length() != 0 &&
|
||||
(param.charAt(0) == '"' || param.charAt(0) == '<' || param.charAt(0) == '>'))
|
||||
{
|
||||
param = param.substring(1);
|
||||
}
|
||||
|
||||
int endPos = param.length() - 1;
|
||||
if (param.length() != 0 &&
|
||||
(param.charAt(endPos) == '"' || param.charAt(endPos) == '<' || param.charAt(endPos) == '>'))
|
||||
{
|
||||
param = param.substring(0, endPos);
|
||||
}
|
||||
|
||||
if ("exec".equalsIgnoreCase(name))
|
||||
{
|
||||
directive = new ExecDirective(configfile, lineno, param);
|
||||
}
|
||||
else if ("include".equalsIgnoreCase(name))
|
||||
{
|
||||
directive = new IncludeDirective(configfile, lineno, param);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UnknownDirectiveException(configfile, lineno,
|
||||
"Unknown directive '%s' at line %d of %s", name, lineno, configfile);
|
||||
}
|
||||
|
||||
if (param.length() == 0)
|
||||
{
|
||||
throw new MissingDirectiveParameterException(configfile, lineno,
|
||||
"Directive '#%s' needs an argument (%s) at line %d of %s",
|
||||
name.toLowerCase(Locale.US),
|
||||
"include".equalsIgnoreCase(name) ? "filename" : "/path/to/executable",
|
||||
lineno,
|
||||
configfile);
|
||||
}
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
protected ConfigVariable parseVariable(String configfile, int lineno, String line) throws ConfigParseException
|
||||
{
|
||||
int pos;
|
||||
String name;
|
||||
String value;
|
||||
|
||||
pos = line.indexOf('=');
|
||||
if (pos == -1)
|
||||
{
|
||||
throw new MissingEqualSignException(configfile, lineno,
|
||||
"No '=' (equal sign) in line %d of %s", lineno, configfile);
|
||||
}
|
||||
|
||||
name = line.substring(0, pos).trim();
|
||||
|
||||
// Ignore > in =>
|
||||
if (line.length() > pos + 1 && line.charAt(pos + 1) == '>')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
|
||||
value = (line.length() > pos + 1) ? line.substring(pos + 1).trim() : "";
|
||||
return new ConfigVariable(configfile, lineno, name, value);
|
||||
}
|
||||
|
||||
void inheritCategory(Category category, Category baseCategory)
|
||||
{
|
||||
category.addBaseCategory(baseCategory);
|
||||
}
|
||||
|
||||
void appendCategory(Category category)
|
||||
{
|
||||
categories.put(category.getName(), category);
|
||||
currentCategory = category;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package org.asteriskjava.config;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ConfigParseException extends Exception
|
||||
{
|
||||
private static final long serialVersionUID = 4346366210261425734L;
|
||||
private String filename;
|
||||
private int lineno;
|
||||
|
||||
public ConfigParseException(String filename, int lineno, String message)
|
||||
{
|
||||
super(message);
|
||||
this.filename = filename;
|
||||
this.lineno = lineno;
|
||||
}
|
||||
|
||||
public ConfigParseException(String filename, int lineno, String format, Object... params)
|
||||
{
|
||||
super(String.format(format, params));
|
||||
this.filename = filename;
|
||||
this.lineno = lineno;
|
||||
}
|
||||
|
||||
public String getFileName()
|
||||
{
|
||||
return filename;
|
||||
}
|
||||
|
||||
public int getLineNumber()
|
||||
{
|
||||
return lineno;
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package org.asteriskjava.config;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ConfigVariable extends ConfigElement
|
||||
{
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
public ConfigVariable(String name, String value)
|
||||
{
|
||||
setName(name);
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
public ConfigVariable(String filename, int lineno, String name, String value)
|
||||
{
|
||||
super(filename, lineno);
|
||||
setName(name);
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Variable name must not be null");
|
||||
}
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StringBuilder rawFormat(StringBuilder sb)
|
||||
{
|
||||
sb.append(name).append(" = ");
|
||||
if (value != null)
|
||||
{
|
||||
sb.append(value);
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name+"="+value;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package org.asteriskjava.config;
|
||||
|
||||
public class ExecDirective extends ConfigDirective
|
||||
{
|
||||
/**
|
||||
* file name of the executable.
|
||||
*/
|
||||
private final String execFile;
|
||||
|
||||
public ExecDirective(String execFile)
|
||||
{
|
||||
super();
|
||||
this.execFile = execFile;
|
||||
}
|
||||
|
||||
public ExecDirective(String filename, int lineno, String execFile)
|
||||
{
|
||||
super(filename, lineno);
|
||||
this.execFile = execFile;
|
||||
}
|
||||
|
||||
public String getExecFile()
|
||||
{
|
||||
return execFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StringBuilder rawFormat(StringBuilder sb)
|
||||
{
|
||||
sb.append("#exec \"").append(execFile).append("\"");
|
||||
return sb;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package org.asteriskjava.config;
|
||||
|
||||
public class IncludeDirective extends ConfigDirective
|
||||
{
|
||||
/**
|
||||
* file name included.
|
||||
*/
|
||||
private final String includeFile;
|
||||
|
||||
public IncludeDirective(String includeFile)
|
||||
{
|
||||
super();
|
||||
this.includeFile = includeFile;
|
||||
}
|
||||
|
||||
public IncludeDirective(String filename, int lineno, String includeFile)
|
||||
{
|
||||
super(filename, lineno);
|
||||
this.includeFile = includeFile;
|
||||
}
|
||||
|
||||
public String getIncludeFile()
|
||||
{
|
||||
return includeFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StringBuilder rawFormat(StringBuilder sb)
|
||||
{
|
||||
sb.append("#include \"").append(includeFile).append("\"");
|
||||
return sb;
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package org.asteriskjava.config;
|
||||
|
||||
/**
|
||||
* A required parameter to a directive is missing.<p>
|
||||
* The #include and #exec directives require a parameter (include file or command to execute).
|
||||
*/
|
||||
public class MissingDirectiveParameterException extends ConfigParseException
|
||||
{
|
||||
private static final long serialVersionUID = -3802754628756681515L;
|
||||
public MissingDirectiveParameterException(String filename, int lineno, String format, Object... params)
|
||||
{
|
||||
super(filename, lineno, format, params);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package org.asteriskjava.config;
|
||||
|
||||
/**
|
||||
* The equal sign on a variable assignment line is missing.<p>
|
||||
* A variable line must include an equal sign.
|
||||
*/
|
||||
public class MissingEqualSignException extends ConfigParseException
|
||||
{
|
||||
private static final long serialVersionUID = 2694490330074765342L;
|
||||
public MissingEqualSignException(String filename, int lineno, String format, Object... params)
|
||||
{
|
||||
super(filename, lineno, format, params);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package org.asteriskjava.config;
|
||||
|
||||
/**
|
||||
* An unknown directive has been encountered.<p>
|
||||
* Asterisk only supports #include and #exec directives.
|
||||
*/
|
||||
public class UnknownDirectiveException extends ConfigParseException
|
||||
{
|
||||
private static final long serialVersionUID = 4356355066633810196L;
|
||||
public UnknownDirectiveException(String filename, int lineno, String format, Object... params)
|
||||
{
|
||||
super(filename, lineno, format, params);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package org.asteriskjava.config.dialplan;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.asteriskjava.config.ConfigElement;
|
||||
|
||||
/**
|
||||
* Represents the dial plan extension as a specific kind of configuration
|
||||
* directive This class makes no interpretation of syntax checking of names,
|
||||
* priorities, or application (for now).
|
||||
*
|
||||
* @author martins
|
||||
*/
|
||||
public class ConfigExtension extends ConfigElement
|
||||
{
|
||||
String name, priority;
|
||||
|
||||
/**
|
||||
* Holds the application in the first element, and arguments in all subsequent elements. Similar to command line arguments array.
|
||||
*/
|
||||
String [] application;
|
||||
|
||||
public ConfigExtension(String filename, int lineno, String name, String priority, String [] application)
|
||||
{
|
||||
super(filename,lineno);
|
||||
this.name = name;
|
||||
this.priority = priority;
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StringBuilder rawFormat(StringBuilder sb)
|
||||
{
|
||||
return sb.append(toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "exten => " + name + "," + priority + "," + Arrays.asList(application);
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getPriority()
|
||||
{
|
||||
return priority;
|
||||
}
|
||||
|
||||
public String[] getApplication()
|
||||
{
|
||||
return application;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package org.asteriskjava.config.dialplan;
|
||||
|
||||
import org.asteriskjava.config.ConfigElement;
|
||||
|
||||
public class ConfigInclude extends ConfigElement
|
||||
{
|
||||
String category;
|
||||
|
||||
public ConfigInclude(String filename, int lineno, String category)
|
||||
{
|
||||
super(filename, lineno);
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StringBuilder rawFormat(StringBuilder sb)
|
||||
{
|
||||
return sb.append(toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "include => " + category;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return category;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package org.asteriskjava.config.dialplan;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.asteriskjava.config.Category;
|
||||
import org.asteriskjava.config.ConfigFileImpl;
|
||||
|
||||
public class ExtensionsConfigFile extends ConfigFileImpl
|
||||
{
|
||||
public ExtensionsConfigFile(String filename, Map<String, Category> categories)
|
||||
{
|
||||
super(filename, categories);
|
||||
}
|
||||
|
||||
public Collection<Category> getContexts()
|
||||
{
|
||||
return categories.values();
|
||||
}
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
package org.asteriskjava.config.dialplan;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.asteriskjava.config.ConfigElement;
|
||||
import org.asteriskjava.config.ConfigFileReader;
|
||||
import org.asteriskjava.config.ConfigParseException;
|
||||
import org.asteriskjava.config.ConfigVariable;
|
||||
|
||||
/*
|
||||
* Interprets extensions.conf as a special kind of config file, the dialplan.
|
||||
* - Line numbers correspond with pbx_config.c, tags/1.4.19 revision 96024
|
||||
*/
|
||||
public class ExtensionsConfigFileReader extends ConfigFileReader
|
||||
{
|
||||
/*
|
||||
* This method corresponds to an iteration of the loop at line 2212 Notes:
|
||||
* 1. [general] and [globals] are allowed to be a context here if they contain only configvariables
|
||||
* 2. switch and ignorepat are treated like regular ConfigVariable.
|
||||
*/
|
||||
@Override
|
||||
protected ConfigElement processTextLine(String configfile, int lineno, String line) throws ConfigParseException
|
||||
{
|
||||
ConfigElement configElement;
|
||||
|
||||
if(
|
||||
(line.trim().startsWith("exten") || line.trim().startsWith("include")) &&
|
||||
currentCategory != null &&
|
||||
(currentCategory.getName().equals("general") || currentCategory.getName().equals("globals"))
|
||||
)
|
||||
throw new ConfigParseException(configfile, lineno, "cannot have 'exten' or 'include' in global or general sections");
|
||||
|
||||
|
||||
/*
|
||||
* Goal here is to break out anything unique that we might want to
|
||||
* look at and parse separately. For now, only exten and include fit
|
||||
* that criteria. Eventually, I could see parsing sections for things
|
||||
* from macros, contexts to differentiate them from categories, switch
|
||||
* for realtime, and more.
|
||||
*/
|
||||
if (line.trim().startsWith("exten"))
|
||||
{
|
||||
configElement = parseExtension(configfile, lineno, line);
|
||||
currentCategory.addElement(configElement);
|
||||
return configElement;
|
||||
}
|
||||
else if(line.trim().startsWith("include"))
|
||||
{
|
||||
// use parseVariable since we have access to it
|
||||
ConfigVariable configvar = parseVariable(configfile, lineno, line);
|
||||
configElement = new ConfigInclude(configfile, lineno, configvar.getValue());
|
||||
currentCategory.addElement(configElement);
|
||||
return configElement;
|
||||
}
|
||||
|
||||
// leave everything else the same
|
||||
configElement = super.processTextLine(configfile, lineno, line);
|
||||
|
||||
return configElement;
|
||||
}
|
||||
|
||||
/* Roughly corresponds to pbx_config.c:2222 */
|
||||
protected ConfigExtension parseExtension(String configfile, int lineno, String line) throws ConfigParseException
|
||||
{
|
||||
ConfigVariable initialVariable = parseVariable(configfile, lineno, line);
|
||||
|
||||
if(!initialVariable.getName().equals("exten"))
|
||||
throw new ConfigParseException(configfile, lineno, "missing 'exten' near " + line);
|
||||
line = initialVariable.getValue().trim();
|
||||
|
||||
int nameIndex = line.indexOf(",", 0);
|
||||
if(nameIndex == -1)
|
||||
throw new ConfigParseException(configfile, lineno, "missing extension name near " + line);
|
||||
String name = line.substring(0, nameIndex);
|
||||
line = line.substring(name.length()+1, line.length()).trim();
|
||||
|
||||
int priorityDelimiter = line.indexOf(",", 0);
|
||||
if(priorityDelimiter == -1)
|
||||
throw new ConfigParseException(configfile, lineno, "missing extension priority near " + line);
|
||||
String priority = line.substring(0, priorityDelimiter);
|
||||
line = line.substring(priority.length()+1, line.length()).trim();
|
||||
|
||||
String [] application = harvestApplicationWithArguments(line);
|
||||
|
||||
return new ConfigExtension(configfile,lineno,name,priority,application);
|
||||
}
|
||||
|
||||
/* Roughly corresponds to pbx_config.c:2276 */
|
||||
private static String [] harvestApplicationWithArguments(String arg)
|
||||
{
|
||||
List<String> args = new ArrayList<String>();
|
||||
|
||||
if(args != null && arg.trim().length() >= 0)
|
||||
{
|
||||
String appl = "", data = "";
|
||||
|
||||
/* Find the first occurrence of either '(' or ',' */
|
||||
int firstc = arg.indexOf(',');
|
||||
int firstp = arg.indexOf('(');
|
||||
|
||||
if (firstc != -1 && (firstp == -1 || firstc < firstp)) {
|
||||
/* comma found, no parenthesis */
|
||||
/* or both found, but comma found first */
|
||||
String [] split = arg.split(",");
|
||||
appl = split[0];
|
||||
for(int i = 1; i < split.length; i++)
|
||||
data += split[i] + (i+1<split.length?",":"");
|
||||
} else if (firstc == -1 && firstp == -1) {
|
||||
/* Neither found */
|
||||
data = "";
|
||||
} else {
|
||||
/* Final remaining case is parenthesis found first */
|
||||
String [] split = arg.split("\\(");
|
||||
appl = split[0];
|
||||
for(int i = 1; i < split.length; i++)
|
||||
data += split[i] + (i+1<split.length?"(":"");
|
||||
int end = data.lastIndexOf(')');
|
||||
if (end == -1) {
|
||||
//ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data);
|
||||
} else if(end == data.length()-1) {
|
||||
data = data.substring(0, end);
|
||||
}
|
||||
data = processQuotesAndSlashes(data, ',', '|');
|
||||
}
|
||||
|
||||
if(!appl.trim().equals(""))
|
||||
{
|
||||
args.add(appl.trim());
|
||||
if(!data.trim().equals(""))
|
||||
{
|
||||
String [] dataSplit = data.split("\\|");
|
||||
for (String aDataSplit : dataSplit)
|
||||
{
|
||||
args.add(aDataSplit.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return args.toArray(new String[args.size()]);
|
||||
}
|
||||
|
||||
public ExtensionsConfigFile readExtensionsFile(String configfile) throws IOException, ConfigParseException
|
||||
{
|
||||
super.readFile(configfile);
|
||||
/* at some point, we may want to resolve back references */
|
||||
/* that include or goto from one context to another */
|
||||
return new ExtensionsConfigFile(configfile, categories);
|
||||
}
|
||||
|
||||
/* ast_process_quotes_and_slashes rewritten to be java friendly */
|
||||
private static String processQuotesAndSlashes(String start, char find, char replace_with)
|
||||
{
|
||||
String dataPut = "";
|
||||
int inEscape = 0;
|
||||
int inQuotes = 0;
|
||||
|
||||
char [] startChars = start.toCharArray();
|
||||
for (char startChar : startChars)
|
||||
{
|
||||
if (inEscape != 0)
|
||||
{
|
||||
dataPut += startChar; /* Always goes verbatim */
|
||||
inEscape = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (startChar == '\\')
|
||||
{
|
||||
inEscape = 1; /* Do not copy \ into the data */
|
||||
}
|
||||
else if (startChar == '\'')
|
||||
{
|
||||
inQuotes = 1 - inQuotes; /* Do not copy ' into the data */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Replace , with |, unless in quotes */
|
||||
dataPut += inQuotes != 0 ? startChar : ((startChar == find) ? replace_with : startChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataPut;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
/*
|
||||
* Copyright 2004-2006 Martin Smith
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
-->
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>Provides classes to manage the dialplan of an Asterisk server.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,27 @@
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
-->
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>Provides classes to manage the configuration of an Asterisk server.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,167 @@
|
||||
package org.asteriskjava.fastagi;
|
||||
|
||||
import org.asteriskjava.util.DaemonThreadFactory;
|
||||
import org.asteriskjava.util.Log;
|
||||
import org.asteriskjava.util.LogFactory;
|
||||
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
|
||||
/**
|
||||
* Abstract base class for FastAGI and AsyncAGI servers.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public abstract class AbstractAgiServer
|
||||
{
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* The default thread pool size.
|
||||
*/
|
||||
private static final int DEFAULT_POOL_SIZE = 10;
|
||||
|
||||
/**
|
||||
* The default thread pool size.
|
||||
*/
|
||||
private static final int DEFAULT_MAXIMUM_POOL_SIZE = 100;
|
||||
|
||||
/**
|
||||
* The minimum number of worker threads in the thread pool.
|
||||
*/
|
||||
private int poolSize = DEFAULT_POOL_SIZE;
|
||||
|
||||
/**
|
||||
* The maximum number of worker threads in the thread pool. This equals the maximum number of
|
||||
* concurrent requests this AgiServer can serve.
|
||||
*/
|
||||
private int maximumPoolSize = DEFAULT_MAXIMUM_POOL_SIZE;
|
||||
|
||||
/**
|
||||
* The thread pool that contains the worker threads to process incoming requests.
|
||||
*/
|
||||
private ThreadPoolExecutor pool;
|
||||
|
||||
/**
|
||||
* The strategy to use for mapping AgiRequests to AgiScripts that serve them.
|
||||
*/
|
||||
private MappingStrategy mappingStrategy;
|
||||
|
||||
private volatile boolean die = false;
|
||||
|
||||
/**
|
||||
* Sets the number of worker threads in the thread pool.
|
||||
* <p/>
|
||||
* This is the number of threads that are available even if they are idle.
|
||||
* <p/>
|
||||
* The default pool size is 10.
|
||||
*
|
||||
* @param poolSize the size of the worker thread pool.
|
||||
*/
|
||||
public void setPoolSize(int poolSize)
|
||||
{
|
||||
this.poolSize = poolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of worker threads in the thread pool.
|
||||
* <p/>
|
||||
* This equals the maximum number of concurrent requests this AgiServer can serve.
|
||||
* <p/>
|
||||
* The default maximum pool size is 100.
|
||||
*
|
||||
* @param maximumPoolSize the maximum size of the worker thread pool.
|
||||
*/
|
||||
public void setMaximumPoolSize(int maximumPoolSize)
|
||||
{
|
||||
this.maximumPoolSize = maximumPoolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategy to use for mapping AgiRequests to AgiScripts that serve them.
|
||||
*
|
||||
* @param mappingStrategy the mapping strategy to use.
|
||||
*/
|
||||
public void setMappingStrategy(MappingStrategy mappingStrategy)
|
||||
{
|
||||
this.mappingStrategy = mappingStrategy;
|
||||
}
|
||||
|
||||
protected MappingStrategy getMappingStrategy()
|
||||
{
|
||||
return mappingStrategy;
|
||||
}
|
||||
|
||||
protected boolean isDie()
|
||||
{
|
||||
return die;
|
||||
}
|
||||
|
||||
protected synchronized void shutdown()
|
||||
{
|
||||
this.die = true;
|
||||
if (pool != null)
|
||||
{
|
||||
pool.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable
|
||||
{
|
||||
super.finalize();
|
||||
|
||||
this.die = true;
|
||||
if (pool != null)
|
||||
{
|
||||
pool.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
protected void execute(Runnable command)
|
||||
{
|
||||
if (isDie())
|
||||
{
|
||||
logger.warn("AgiServer is shutting down: Refused to execute AgiScript");
|
||||
return;
|
||||
}
|
||||
getPool().execute(command);
|
||||
}
|
||||
|
||||
private synchronized ThreadPoolExecutor getPool()
|
||||
{
|
||||
if (pool == null)
|
||||
{
|
||||
pool = createPool();
|
||||
logger.info("Thread pool started.");
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ThreadPoolExecutor to serve the AGI requests. The nature of this pool
|
||||
* defines how many concurrent requests can be handled. The default implementation
|
||||
* returns a dynamic thread pool defined by the poolSize and maximumPoolSize properties.<p>
|
||||
* You can override this method to change this behavior. For example you can use a cached
|
||||
* pool with
|
||||
* <pre>
|
||||
* return Executors.newCachedThreadPool(new DaemonThreadFactory());
|
||||
* </pre>
|
||||
*
|
||||
* @return the ThreadPoolExecutor to use for serving AGI requests.
|
||||
* @see #setPoolSize(int)
|
||||
* @see #setMaximumPoolSize(int)
|
||||
*/
|
||||
protected ThreadPoolExecutor createPool()
|
||||
{
|
||||
return new ThreadPoolExecutor(
|
||||
poolSize,
|
||||
(maximumPoolSize < poolSize) ? poolSize : maximumPoolSize,
|
||||
50000L, TimeUnit.MILLISECONDS,
|
||||
new SynchronousQueue<Runnable>(),
|
||||
new DaemonThreadFactory()
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.io.File;
|
||||
|
||||
import org.asteriskjava.util.Log;
|
||||
import org.asteriskjava.util.LogFactory;
|
||||
|
||||
/**
|
||||
* Abstract base class for common mapping strategies.
|
||||
* <p/>
|
||||
* If you implement your own mapping strategy you can derive from this class.
|
||||
*
|
||||
* @author srt
|
||||
* @since 0.3
|
||||
*/
|
||||
public abstract class AbstractMappingStrategy implements MappingStrategy
|
||||
{
|
||||
/**
|
||||
* Reference to Asterisk-Java's logging subsystem.
|
||||
*/
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
private static final String[] DEFAULT_SCRIPT_PATH = new String[]{"agi"};
|
||||
|
||||
private ClassLoader defaultClassLoader = null;
|
||||
|
||||
/**
|
||||
* Returns the ClassLoader to use for loading AgiScript classes and load
|
||||
* other resources like the mapping properties file.<p>
|
||||
* By default this method returns a class loader that searches for classes in the
|
||||
* "agi" subdirectory (if it exists) and uses the context class loader of the
|
||||
* current thread as the parent class loader.<p>
|
||||
* You can override this method if you prefer using a different class loader.
|
||||
*
|
||||
* @return the ClassLoader to use for loading AgiScript classes and load
|
||||
* other resources like the mapping properties file.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected synchronized ClassLoader getClassLoader()
|
||||
{
|
||||
if (defaultClassLoader == null)
|
||||
{
|
||||
final ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
final List<URL> dirUrls = new ArrayList<URL>();
|
||||
|
||||
for (String scriptPathEntry : DEFAULT_SCRIPT_PATH)
|
||||
{
|
||||
final File scriptDir = new File(scriptPathEntry);
|
||||
if (! scriptDir.isDirectory())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
dirUrls.add(scriptDir.toURI().toURL());
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
// should not happen
|
||||
}
|
||||
}
|
||||
|
||||
if (dirUrls.size() == 0)
|
||||
{
|
||||
return parentClassLoader;
|
||||
}
|
||||
|
||||
defaultClassLoader = new URLClassLoader(dirUrls.toArray(new URL[dirUrls.size()]), parentClassLoader);
|
||||
}
|
||||
|
||||
return defaultClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of an AGI script.
|
||||
*
|
||||
* @param className Class name of the AGI script. The class must implement
|
||||
* {@link AgiScript}.
|
||||
* @return the created instance of the AGI script class. If the instance
|
||||
* can't be created an error is logged and <code>null</code> is
|
||||
* returned.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected AgiScript createAgiScriptInstance(String className)
|
||||
{
|
||||
Class tmpClass;
|
||||
Class<AgiScript> agiScriptClass;
|
||||
Constructor<AgiScript> constructor;
|
||||
AgiScript agiScript;
|
||||
|
||||
agiScript = null;
|
||||
|
||||
try
|
||||
{
|
||||
tmpClass = getClassLoader().loadClass(className);
|
||||
}
|
||||
catch (ClassNotFoundException e1)
|
||||
{
|
||||
logger.debug("Unable to create AgiScript instance of type " + className
|
||||
+ ": Class not found, make sure the class exists and is available on the CLASSPATH");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!AgiScript.class.isAssignableFrom(tmpClass))
|
||||
{
|
||||
logger.warn("Unable to create AgiScript instance of type " + className
|
||||
+ ": Class does not implement the AgiScript interface");
|
||||
return null;
|
||||
}
|
||||
|
||||
agiScriptClass = (Class<AgiScript>) tmpClass;
|
||||
try
|
||||
{
|
||||
constructor = agiScriptClass.getConstructor();
|
||||
agiScript = constructor.newInstance();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.warn("Unable to create AgiScript instance of type " + className, e);
|
||||
}
|
||||
|
||||
return agiScript;
|
||||
}
|
||||
}
|
@ -0,0 +1,799 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import org.asteriskjava.fastagi.command.AgiCommand;
|
||||
import org.asteriskjava.fastagi.reply.AgiReply;
|
||||
|
||||
|
||||
/**
|
||||
* Provides the functionality to send AgiCommands to Asterisk while handling an
|
||||
* AgiRequest.
|
||||
* <p/>
|
||||
* This interface is supposed to be used by AgiScripts for interaction with the
|
||||
* Asterisk server.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AgiChannel.java 1274 2009-03-21 11:08:19Z srt $
|
||||
*/
|
||||
public interface AgiChannel
|
||||
{
|
||||
/**
|
||||
* Returns the name of the channel.
|
||||
*
|
||||
* @return the name of the channel.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns the unqiue id of the channel.
|
||||
*
|
||||
* @return the unqiue id of the channel.
|
||||
*/
|
||||
String getUniqueId();
|
||||
|
||||
/**
|
||||
* Returns the reply received in response to the last command sent to Asterisk.
|
||||
*
|
||||
* @return the reply received in response to the last command sent to Asterisk
|
||||
* or <code>null</code> if none has yet been received.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
AgiReply getLastReply();
|
||||
|
||||
/**
|
||||
* Sends a command to asterisk and returns the corresponding reply. The reply is also
|
||||
* available through {@link #getLastReply()}.
|
||||
*
|
||||
* @param command the command to send.
|
||||
* @return the reply of the asterisk server containing the return value.
|
||||
* @throws AgiException if the command can't be sent to Asterisk (for
|
||||
* example because the channel has been hung up)
|
||||
*/
|
||||
AgiReply sendCommand(AgiCommand command) throws AgiException;
|
||||
|
||||
/**
|
||||
* Answers the channel.
|
||||
*
|
||||
* @since 0.2
|
||||
*/
|
||||
void answer() throws AgiException;
|
||||
|
||||
/**
|
||||
* Hangs the channel up.
|
||||
*
|
||||
* @since 0.2
|
||||
*/
|
||||
void hangup() throws AgiException;
|
||||
|
||||
/**
|
||||
* Cause the channel to automatically hangup at the given number of seconds
|
||||
* in the future.
|
||||
*
|
||||
* @param time the number of seconds before this channel is automatically
|
||||
* hung up.<p>
|
||||
* 0 disables the autohangup feature.
|
||||
* @since 0.2
|
||||
*/
|
||||
void setAutoHangup(int time) throws AgiException;
|
||||
|
||||
/**
|
||||
* Sets the caller id on the current channel.
|
||||
*
|
||||
* @param callerId the raw caller id to set, for example "John Doe<1234>".
|
||||
* @since 0.2
|
||||
*/
|
||||
void setCallerId(String callerId) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays music on hold from the default music on hold class.
|
||||
*
|
||||
* @since 0.2
|
||||
*/
|
||||
void playMusicOnHold() throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays music on hold from the given music on hold class.
|
||||
*
|
||||
* @param musicOnHoldClass the music on hold class to play music from as
|
||||
* configures in Asterisk's <code><musiconhold.conf/code>.
|
||||
* @since 0.2
|
||||
*/
|
||||
void playMusicOnHold(String musicOnHoldClass) throws AgiException;
|
||||
|
||||
/**
|
||||
* Stops playing music on hold.
|
||||
*
|
||||
* @since 0.2
|
||||
*/
|
||||
void stopMusicOnHold() throws AgiException;
|
||||
|
||||
/**
|
||||
* Returns the status of the channel.<p>
|
||||
* Return values:
|
||||
* <ul>
|
||||
* <li>0 Channel is down and available
|
||||
* <li>1 Channel is down, but reserved
|
||||
* <li>2 Channel is off hook
|
||||
* <li>3 Digits (or equivalent) have been dialed
|
||||
* <li>4 Line is ringing
|
||||
* <li>5 Remote end is ringing
|
||||
* <li>6 Line is up
|
||||
* <li>7 Line is busy
|
||||
* </ul>
|
||||
*
|
||||
* @return the status of the channel.
|
||||
* @since 0.2
|
||||
*/
|
||||
int getChannelStatus() throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file and waits for the user to enter DTMF digits until he
|
||||
* presses '#'. The user may interrupt the streaming by starting to enter
|
||||
* digits.
|
||||
*
|
||||
* @param file the name of the file to play
|
||||
* @return a String containing the DTMF the user entered
|
||||
* @since 0.2
|
||||
*/
|
||||
String getData(String file) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file and waits for the user to enter DTMF digits until he
|
||||
* presses '#' or the timeout occurs. The user may interrupt the streaming
|
||||
* by starting to enter digits.
|
||||
*
|
||||
* @param file the name of the file to play
|
||||
* @param timeout the timeout in milliseconds to wait for user input.<p>
|
||||
* 0 means standard timeout value, -1 means "ludicrous time"
|
||||
* (essentially never times out).
|
||||
* @return a String containing the DTMF the user entered
|
||||
* @since 0.2
|
||||
*/
|
||||
String getData(String file, long timeout) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file and waits for the user to enter DTMF digits until he
|
||||
* presses '#' or the timeout occurs or the maximum number of digits has
|
||||
* been entered. The user may interrupt the streaming by starting to enter
|
||||
* digits.
|
||||
*
|
||||
* @param file the name of the file to play
|
||||
* @param timeout the timeout in milliseconds to wait for user input.<p>
|
||||
* 0 means standard timeout value, -1 means "ludicrous time"
|
||||
* (essentially never times out).
|
||||
* @param maxDigits the maximum number of digits the user is allowed to
|
||||
* enter
|
||||
* @return a String containing the DTMF the user entered
|
||||
* @since 0.2
|
||||
*/
|
||||
String getData(String file, long timeout, int maxDigits)
|
||||
throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file, and waits for the user to press one of the given
|
||||
* digits. If none of the esacpe digits is pressed while streaming the file
|
||||
* it waits for the default timeout of 5 seconds still waiting for the user
|
||||
* to press a digit.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
* @param escapeDigits contains the digits that the user is expected to
|
||||
* press.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char getOption(String file, String escapeDigits) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file, and waits for the user to press one of the given
|
||||
* digits. If none of the esacpe digits is pressed while streaming the file
|
||||
* it waits for the specified timeout still waiting for the user to press a
|
||||
* digit.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
* @param escapeDigits contains the digits that the user is expected to
|
||||
* press.
|
||||
* @param timeout the timeout in milliseconds to wait if none of the defined
|
||||
* esacpe digits was presses while streaming.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char getOption(String file, String escapeDigits, long timeout)
|
||||
throws AgiException;
|
||||
|
||||
/**
|
||||
* Executes the given command.
|
||||
*
|
||||
* @param application the name of the application to execute, for example
|
||||
* "Dial".
|
||||
* @return the return code of the application of -2 if the application was
|
||||
* not found.
|
||||
* @since 0.2
|
||||
*/
|
||||
int exec(String application) throws AgiException;
|
||||
|
||||
/**
|
||||
* Executes the given command.
|
||||
*
|
||||
* @param application the name of the application to execute, for example
|
||||
* "Dial".
|
||||
* @param options the parameters to pass to the application, for example
|
||||
* "SIP/123".
|
||||
* @return the return code of the application of -2 if the application was
|
||||
* not found.
|
||||
* @since 0.2
|
||||
*/
|
||||
int exec(String application, String options) throws AgiException;
|
||||
|
||||
/**
|
||||
* Sets the context for continuation upon exiting the application.
|
||||
*
|
||||
* @param context the context for continuation upon exiting the application.
|
||||
* @since 0.2
|
||||
*/
|
||||
void setContext(String context) throws AgiException;
|
||||
|
||||
/**
|
||||
* Sets the extension for continuation upon exiting the application.
|
||||
*
|
||||
* @param extension the extension for continuation upon exiting the
|
||||
* application.
|
||||
* @since 0.2
|
||||
*/
|
||||
void setExtension(String extension) throws AgiException;
|
||||
|
||||
/**
|
||||
* Sets the priority or label for continuation upon exiting the application.
|
||||
*
|
||||
* @param priority the priority or label for continuation upon exiting the
|
||||
* application.
|
||||
* @since 0.2
|
||||
*/
|
||||
void setPriority(String priority) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file.
|
||||
*
|
||||
* @param file name of the file to play.
|
||||
* @since 0.2
|
||||
*/
|
||||
void streamFile(String file) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file and allows the user to escape by pressing one of the
|
||||
* given digit.
|
||||
*
|
||||
* @param file name of the file to play.
|
||||
* @param escapeDigits a String containing the DTMF digits that allow the
|
||||
* user to escape.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char streamFile(String file, String escapeDigits) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file starting at the specified offset and allows the
|
||||
* user to escape by pressing one of the given digit.
|
||||
*
|
||||
* @param file name of the file to play.
|
||||
* @param escapeDigits a String containing the DTMF digits that allow the
|
||||
* user to escape.
|
||||
* @param offset the offset samples to skip before streaming.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
char streamFile(String file, String escapeDigits, int offset) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given digit string.
|
||||
*
|
||||
* @param digits the digit string to say.
|
||||
* @since 0.2
|
||||
*/
|
||||
void sayDigits(String digits) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given number, returning early if any of the given DTMF number
|
||||
* are received on the channel.
|
||||
*
|
||||
* @param digits the digit string to say.
|
||||
* @param escapeDigits a String containing the DTMF digits that allow the
|
||||
* user to escape.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char sayDigits(String digits, String escapeDigits) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given number.
|
||||
*
|
||||
* @param number the number to say.
|
||||
* @since 0.2
|
||||
*/
|
||||
void sayNumber(String number) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given number, returning early if any of the given DTMF number
|
||||
* are received on the channel.
|
||||
*
|
||||
* @param number the number to say.
|
||||
* @param escapeDigits a String containing the DTMF digits that allow the
|
||||
* user to escape.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char sayNumber(String number, String escapeDigits) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given character string with phonetics.
|
||||
*
|
||||
* @param text the text to say.
|
||||
* @since 0.2
|
||||
*/
|
||||
void sayPhonetic(String text) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given character string with phonetics, returning early if any of
|
||||
* the given DTMF number are received on the channel.
|
||||
*
|
||||
* @param text the text to say.
|
||||
* @param escapeDigits a String containing the DTMF digits that allow the
|
||||
* user to escape.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char sayPhonetic(String text, String escapeDigits) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given character string.
|
||||
*
|
||||
* @param text the text to say.
|
||||
* @since 0.2
|
||||
*/
|
||||
void sayAlpha(String text) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given character string, returning early if any of the given DTMF
|
||||
* number are received on the channel.
|
||||
*
|
||||
* @param text the text to say.
|
||||
* @param escapeDigits a String containing the DTMF digits that allow the
|
||||
* user to escape.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char sayAlpha(String text, String escapeDigits) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given time.
|
||||
*
|
||||
* @param time the time to say in seconds since 00:00:00 on January 1, 1970.
|
||||
* @since 0.2
|
||||
*/
|
||||
void sayTime(long time) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given time, returning early if any of the given DTMF number are
|
||||
* received on the channel.
|
||||
*
|
||||
* @param time the time to say in seconds since 00:00:00 on January 1, 1970.
|
||||
* @param escapeDigits a String containing the DTMF digits that allow the
|
||||
* user to escape.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char sayTime(long time, String escapeDigits) throws AgiException;
|
||||
|
||||
/**
|
||||
* Returns the value of the current channel or global variable.<p>
|
||||
* Supports functions and builtin variables. To retrieve
|
||||
* the caller id you can use <code>getVariable("CALLERID(name)");<code><p>
|
||||
* Does not support expression parsing, use {@link #getFullVariable(String)} in those cases.
|
||||
*
|
||||
* @param name the name of the variable (or function call) to retrieve.
|
||||
* @return the value of the given variable or <code>null</code> if not
|
||||
* set.
|
||||
* @since 0.2
|
||||
*/
|
||||
String getVariable(String name) throws AgiException;
|
||||
|
||||
/**
|
||||
* Sets the value of the current channel or global variable to a new value.<p>
|
||||
* Supports functions and builtin variables. To set the caller id
|
||||
* you can use <code>setVariable("CALLERID(name)", "John Doe");</code>
|
||||
*
|
||||
* @param name the name of the variable (or function call) to set.
|
||||
* @param value the new value to set.
|
||||
* @since 0.2
|
||||
*/
|
||||
void setVariable(String name, String value) throws AgiException;
|
||||
|
||||
/**
|
||||
* Waits up to 'timeout' milliseconds to receive a DTMF digit.
|
||||
*
|
||||
* @param timeout timeout the milliseconds to wait for the channel to
|
||||
* receive a DTMF digit, -1 will wait forever.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char waitForDigit(int timeout) throws AgiException;
|
||||
|
||||
/**
|
||||
* Evaluates a channel expression for the current channel. To extract
|
||||
* the caller id use <code>getFullVariable("${CALLERID(name)}");</code>.<p>
|
||||
* Available since Asterisk 1.2.
|
||||
*
|
||||
* @param expr the expression to evaluate.
|
||||
* @return the value of the given expression or <code>null</code> if not
|
||||
* set.
|
||||
* @see #getVariable(String)
|
||||
* @since 0.2
|
||||
*/
|
||||
String getFullVariable(String expr) throws AgiException;
|
||||
|
||||
/**
|
||||
* Evaluates a channel expression for the given channel.To extract
|
||||
* the caller id of channel use <code>getFullVariable("${CALLERID(name)}", "SIP/john-0085d860");</code>.<p>
|
||||
* Available since Asterisk 1.2.
|
||||
*
|
||||
* @param expr the the expression to evaluate.
|
||||
* @param channel the name of the channel.
|
||||
* @return the value of the given expression or <code>null</code> if not
|
||||
* set.
|
||||
* @since 0.2
|
||||
*/
|
||||
String getFullVariable(String expr, String channel) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given time.<p>
|
||||
* Available since Asterisk 1.2.
|
||||
*
|
||||
* @param time the time to say in seconds elapsed since 00:00:00 on January
|
||||
* 1, 1970, Coordinated Universal Time (UTC)
|
||||
* @since 0.2
|
||||
*/
|
||||
void sayDateTime(long time) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given time and allows interruption by one of the given escape
|
||||
* digits.<p>
|
||||
* Available since Asterisk 1.2.
|
||||
*
|
||||
* @param time the time to say in seconds elapsed since 00:00:00 on January
|
||||
* 1, 1970, Coordinated Universal Time (UTC)
|
||||
* @param escapeDigits the digits that allow the user to interrupt this
|
||||
* command or <code>null</code> for none.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char sayDateTime(long time, String escapeDigits) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given time in the given format and allows interruption by one of
|
||||
* the given escape digits.<p>
|
||||
* Available since Asterisk 1.2.
|
||||
*
|
||||
* @param time the time to say in seconds elapsed since 00:00:00 on January
|
||||
* 1, 1970, Coordinated Universal Time (UTC)
|
||||
* @param escapeDigits the digits that allow the user to interrupt this
|
||||
* command or <code>null</code> for none.
|
||||
* @param format the format the time should be said in
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char sayDateTime(long time, String escapeDigits, String format) throws AgiException;
|
||||
|
||||
/**
|
||||
* Says the given time in the given format and timezone and allows
|
||||
* interruption by one of the given escape digits.<p>
|
||||
* Available since Asterisk 1.2.
|
||||
*
|
||||
* @param time the time to say in seconds elapsed since 00:00:00 on January
|
||||
* 1, 1970, Coordinated Universal Time (UTC)
|
||||
* @param escapeDigits the digits that allow the user to interrupt this
|
||||
* command or <code>null</code> for none.
|
||||
* @param format the format the time should be said in
|
||||
* @param timezone the timezone to use when saying the time, for example
|
||||
* "UTC" or "Europe/Berlin".
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.2
|
||||
*/
|
||||
char sayDateTime(long time, String escapeDigits, String format,
|
||||
String timezone) throws AgiException;
|
||||
|
||||
/**
|
||||
* Retrieves an entry in the Asterisk database for a given family and key.
|
||||
*
|
||||
* @param family the family of the entry to retrieve.
|
||||
* @param key the key of the entry to retrieve.
|
||||
* @return the value of the given family and key or <code>null</code> if there
|
||||
* is no such value.
|
||||
* @since 0.3
|
||||
*/
|
||||
String databaseGet(String family, String key) throws AgiException;
|
||||
|
||||
/**
|
||||
* Adds or updates an entry in the Asterisk database for a given family, key,
|
||||
* and value.
|
||||
*
|
||||
* @param family the family of the entry to add or update.
|
||||
* @param key the key of the entry to add or update.
|
||||
* @param value the new value of the entry.
|
||||
* @since 0.3
|
||||
*/
|
||||
void databasePut(String family, String key, String value) throws AgiException;
|
||||
|
||||
/**
|
||||
* Deletes an entry in the Asterisk database for a given family and key.
|
||||
*
|
||||
* @param family the family of the entry to delete.
|
||||
* @param key the key of the entry to delete.
|
||||
* @since 0.3
|
||||
*/
|
||||
void databaseDel(String family, String key) throws AgiException;
|
||||
|
||||
/**
|
||||
* Deletes a whole family of entries in the Asterisk database.
|
||||
*
|
||||
* @param family the family to delete.
|
||||
* @since 0.3
|
||||
*/
|
||||
void databaseDelTree(String family) throws AgiException;
|
||||
|
||||
/**
|
||||
* Deletes all entries of a given family in the Asterisk database that have a key
|
||||
* that starts with a given prefix.
|
||||
*
|
||||
* @param family the family of the entries to delete.
|
||||
* @param keytree the prefix of the keys of the entries to delete.
|
||||
* @since 0.3
|
||||
*/
|
||||
void databaseDelTree(String family, String keytree) throws AgiException;
|
||||
|
||||
/**
|
||||
* Sends a message to the Asterisk console via the verbose message system.
|
||||
*
|
||||
* @param message the message to send.
|
||||
* @param level the verbosity level to use. Must be in [1..4].
|
||||
* @since 0.3
|
||||
*/
|
||||
void verbose(String message, int level) throws AgiException;
|
||||
|
||||
/**
|
||||
* Record to a file until a given dtmf digit in the sequence is received.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
* @param format the format of the file to be recorded, for example "wav".
|
||||
* @param escapeDigits contains the digits that allow the user to end
|
||||
* recording.
|
||||
* @param timeout the maximum record time in milliseconds, or -1 for no
|
||||
* timeout.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.3
|
||||
*/
|
||||
char recordFile(String file, String format, String escapeDigits,
|
||||
int timeout) throws AgiException;
|
||||
|
||||
/**
|
||||
* Record to a file until a given dtmf digit in the sequence is received.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
* @param format the format of the file to be recorded, for example "wav".
|
||||
* @param escapeDigits contains the digits that allow the user to end
|
||||
* recording.
|
||||
* @param timeout the maximum record time in milliseconds, or -1 for no
|
||||
* timeout.
|
||||
* @param offset the offset samples to skip.
|
||||
* @param beep <code>true</code> if a beep should be played before
|
||||
* recording.
|
||||
* @param maxSilence The amount of silence (in seconds) to allow before
|
||||
* returning despite the lack of dtmf digits or reaching timeout.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.3
|
||||
*/
|
||||
char recordFile(String file, String format, String escapeDigits,
|
||||
int timeout, int offset, boolean beep, int maxSilence) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file allowing the user to control the streaming by
|
||||
* using "#" for forward and "*" for rewind.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
* @since 0.3
|
||||
*/
|
||||
void controlStreamFile(String file) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file allowing the user to control the streaming by
|
||||
* using "#" for forward and "*" for rewind. Pressing one of the escape
|
||||
* digits stops streaming.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
* @param escapeDigits contains the digits that allow the user to interrupt
|
||||
* this command.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.3
|
||||
*/
|
||||
char controlStreamFile(String file, String escapeDigits) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file allowing the user to control the streaming by
|
||||
* using "#" for forward and "*" for rewind. Pressing one of the escape
|
||||
* digits stops streaming. The file is played starting at the indicated
|
||||
* offset.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
* @param escapeDigits contains the digits that allow the user to interrupt
|
||||
* this command. May be <code>null</code> if you don't want the
|
||||
* user to interrupt.
|
||||
* @param offset the offset samples to skip before streaming.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.3
|
||||
*/
|
||||
char controlStreamFile(String file, String escapeDigits, int offset) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given file allowing the user to control the streaming by
|
||||
* using forwardDigit for forward, rewindDigit for rewind and pauseDigit for pause.
|
||||
* Pressing one of the escape digits stops streaming.
|
||||
* The file is played starting at the indicated
|
||||
* offset, use 0 to start at the beginning.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
* @param escapeDigits contains the digits that allow the user to interrupt
|
||||
* this command. May be <code>null</code> if you don't want the
|
||||
* user to interrupt.
|
||||
* @param offset the offset samples to skip before streaming, use 0 to start at the beginning.
|
||||
* @param forwardDigit the digit for fast forward.
|
||||
* @param rewindDigit the digit for rewind.
|
||||
* @param pauseDigit the digit for pause and unpause.
|
||||
* @return the DTMF digit pressed or 0x0 if none was pressed.
|
||||
* @since 0.3
|
||||
*/
|
||||
char controlStreamFile(String file, String escapeDigits,
|
||||
int offset, String forwardDigit, String rewindDigit,
|
||||
String pauseDigit) throws AgiException;
|
||||
|
||||
/**
|
||||
* Creates a speech object that uses the default speech engine. The speech object is
|
||||
* used by the other speech methods and must be created before they are called.
|
||||
*
|
||||
* @throws AgiSpeechException if the speech object cannot be created.
|
||||
* @see #speechDestroy()
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void speechCreate() throws AgiException;
|
||||
|
||||
/**
|
||||
* Creates a speech object that uses the given speech engine. The speech object is
|
||||
* used by the other speech methods and must be created before they are called.
|
||||
*
|
||||
* @param engine the name of the speech engine. For example "lumenvox".
|
||||
* @throws AgiSpeechException if the speech object cannot be created.
|
||||
* @see #speechDestroy()
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void speechCreate(String engine) throws AgiException;
|
||||
|
||||
/**
|
||||
* Sets the speech engine setting indicated by name to the given value.
|
||||
*
|
||||
* @param name the name of the setting to set.
|
||||
* @param value the value to set.
|
||||
* @throws AgiSpeechException if the setting cannot be set.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void speechSet(String name, String value) throws AgiException;
|
||||
|
||||
/**
|
||||
* Destroys the current speech object.
|
||||
*
|
||||
* @throws AgiSpeechException if the speech engine cannot be destroyed.
|
||||
* @see #speechCreate(String)
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void speechDestroy() throws AgiException;
|
||||
|
||||
/**
|
||||
* Loads the specified grammar. The grammer is then available for calls to {@link #speechActivateGrammar(String)}
|
||||
* under the given name. Eplicitly loading a grammer is only required if the grammer has not been defined in the
|
||||
* speech engine configuration, e.g. the <code>[grammars]</code> section of <code>lumenvox.conf</code>.
|
||||
*
|
||||
* @param label the name of the grammar, used for subsequent calls to {@link #speechActivateGrammar(String)},
|
||||
* {@link #speechDeactivateGrammar(String)} and {@link #speechUnloadGrammar(String)}.
|
||||
* @param path the path to the grammar to load.
|
||||
* @throws AgiSpeechException if the grammar cannot be loaded.
|
||||
* @see #speechUnloadGrammar(String)
|
||||
* @see #speechActivateGrammar(String)
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void speechLoadGrammar(String label, String path) throws AgiException;
|
||||
|
||||
/**
|
||||
* Unloads the specified grammar.
|
||||
*
|
||||
* @param label the name of the grammar to unload.
|
||||
* @throws AgiSpeechException if the grammar cannot be unloaded.
|
||||
* @see #speechLoadGrammar(String, String)
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void speechUnloadGrammar(String label) throws AgiException;
|
||||
|
||||
/**
|
||||
* Activates the specified grammar.
|
||||
*
|
||||
* @param label the name of the grammar to activate.
|
||||
* @throws AgiSpeechException if the grammar cannot be activated.
|
||||
* @see #speechDeactivateGrammar(String)
|
||||
* @see #speechLoadGrammar(String, String)
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void speechActivateGrammar(String label) throws AgiException;
|
||||
|
||||
/**
|
||||
* Deactivates the specified grammar.
|
||||
*
|
||||
* @param label the name to the grammar to deactivate.
|
||||
* @throws AgiSpeechException if the grammar cannot be deactivated.
|
||||
* @see #speechActivateGrammar(String)
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void speechDeactivateGrammar(String label) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given prompt while listening for speech and DTMF.
|
||||
*
|
||||
* @param prompt the name of the file to stream, must not include extension.
|
||||
* @param timeout the timeout in milliseconds to wait for user input.<p>
|
||||
* 0 means standard timeout value, -1 means "ludicrous time"
|
||||
* (essentially never times out).
|
||||
* @return the recognition result
|
||||
* @since 1.0.0
|
||||
*/
|
||||
SpeechRecognitionResult speechRecognize(String prompt, int timeout) throws AgiException;
|
||||
|
||||
/**
|
||||
* Plays the given prompt while listening for speech and DTMF.
|
||||
*
|
||||
* @param prompt the name of the file to stream, must not include extension.
|
||||
* @param timeout the timeout in milliseconds to wait for user input.<p>
|
||||
* 0 means standard timeout value, -1 means "ludicrous time"
|
||||
* (essentially never times out).
|
||||
* @param offset the offset samples to skip before streaming, use 0 to start at the beginning.
|
||||
* @return the recognition result
|
||||
* @since 1.0.0
|
||||
*/
|
||||
SpeechRecognitionResult speechRecognize(String prompt, int timeout, int offset) throws AgiException, AgiSpeechException;
|
||||
|
||||
/**
|
||||
* Defines the point in the dialplan where the call will continue when the AGI script
|
||||
* returns.<p>
|
||||
* This is a shortcut for calling {@link #setContext(String)}, {@link #setExtension(String)}
|
||||
* and {@link #setPriority(String)} in series.
|
||||
*
|
||||
* @param context the context for continuation upon exiting the application.
|
||||
* @param extension the extension for continuation upon exiting the
|
||||
* application.
|
||||
* @param priority the priority or label for continuation upon exiting the
|
||||
* application.
|
||||
* @see #setContext(String)
|
||||
* @see #setExtension(String)
|
||||
* @see #setPriority(String)
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void continueAt(String context, String extension, String priority) throws AgiException;
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
/**
|
||||
* Base class for all AGI specific exceptions.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AgiException.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class AgiException extends Exception
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 1215836054948768757L;
|
||||
|
||||
/**
|
||||
* Creates a new AgiException with the given message.
|
||||
*
|
||||
* @param message a message describing the AgiException.
|
||||
*/
|
||||
public AgiException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AgiException with the given message and cause.
|
||||
*
|
||||
* @param message a message describing the AgiException.
|
||||
* @param cause the throwable that caused this exception.
|
||||
*/
|
||||
public AgiException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
/**
|
||||
* The AgiHangupException is thrown if the channel is hung up while
|
||||
* processing the {@link org.asteriskjava.fastagi.AgiRequest}.<p>
|
||||
* Up to Asterisk 1.4 hanging up the channel also closes the TCP connection,
|
||||
* since Asterisk 1.6 the connection is kept alive but commands that
|
||||
* require an active channel return status code
|
||||
* {@link org.asteriskjava.fastagi.reply.AgiReply#SC_DEAD_CHANNEL}. Both events
|
||||
* are translated to an AgiHangupException.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AgiHangupException.java 1261 2009-03-14 03:17:17Z srt $
|
||||
*/
|
||||
public class AgiHangupException extends AgiException
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 3256444698691252274L;
|
||||
|
||||
/**
|
||||
* Creates a new AgiHangupException.
|
||||
*/
|
||||
public AgiHangupException()
|
||||
{
|
||||
super("Channel was hung up.");
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
/**
|
||||
* The AgiNetworkException usally wraps an IOException denoting a network
|
||||
* problem while talking to the Asterisk server.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AgiNetworkException.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class AgiNetworkException extends AgiException
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 3256445789629723703L;
|
||||
|
||||
/**
|
||||
* Creates a new AgiNetworkException with the given message and cause.
|
||||
*
|
||||
* @param message a message describing the AgiException.
|
||||
* @param cause the throwable that caused this exception.
|
||||
*/
|
||||
public AgiNetworkException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,478 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import org.asteriskjava.fastagi.command.AgiCommand;
|
||||
import org.asteriskjava.fastagi.internal.AgiConnectionHandler;
|
||||
import org.asteriskjava.fastagi.reply.AgiReply;
|
||||
|
||||
/**
|
||||
* AgiOperations provides some convinience methods that wrap the various
|
||||
* {@link AgiCommand AgiCommands}.
|
||||
*
|
||||
* @since 0.3
|
||||
* @author srt
|
||||
* @version $Id: AgiOperations.java 1271 2009-03-21 03:41:24Z srt $
|
||||
*/
|
||||
public class AgiOperations implements AgiChannel
|
||||
{
|
||||
private final AgiChannel channel;
|
||||
|
||||
/**
|
||||
* Creates a new instance that operates on the channel attached to the
|
||||
* current thread.
|
||||
*/
|
||||
public AgiOperations()
|
||||
{
|
||||
this.channel = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance that operates on the given channel.
|
||||
*
|
||||
* @param channel the channel to operate on.
|
||||
*/
|
||||
public AgiOperations(AgiChannel channel)
|
||||
{
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the channel to operate on.
|
||||
*
|
||||
* @return the channel to operate on.
|
||||
* @throws IllegalStateException if no {@link AgiChannel} is bound to the
|
||||
* current channel and no channel has been passed to the
|
||||
* constructor.
|
||||
*/
|
||||
protected AgiChannel getChannel()
|
||||
{
|
||||
AgiChannel threadBoundChannel;
|
||||
|
||||
if (channel != null)
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
|
||||
threadBoundChannel = AgiConnectionHandler.getChannel();
|
||||
if (threadBoundChannel == null)
|
||||
{
|
||||
throw new IllegalStateException("Trying to send command from an invalid thread");
|
||||
}
|
||||
|
||||
return threadBoundChannel;
|
||||
}
|
||||
|
||||
/* The following methods simply delegate to #getChannel() */
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return getChannel().getName();
|
||||
}
|
||||
|
||||
public String getUniqueId()
|
||||
{
|
||||
return getChannel().getUniqueId();
|
||||
}
|
||||
|
||||
public AgiReply getLastReply()
|
||||
{
|
||||
return getChannel().getLastReply();
|
||||
}
|
||||
|
||||
public AgiReply sendCommand(AgiCommand command)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().sendCommand(command);
|
||||
}
|
||||
|
||||
public void answer()
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().answer();
|
||||
}
|
||||
|
||||
public void hangup()
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().hangup();
|
||||
}
|
||||
|
||||
public void setAutoHangup(int time)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().setAutoHangup(time);
|
||||
}
|
||||
|
||||
public void setCallerId(String callerId)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().setCallerId(callerId);
|
||||
}
|
||||
|
||||
public void playMusicOnHold()
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().playMusicOnHold();
|
||||
}
|
||||
|
||||
public void playMusicOnHold(String musicOnHoldClass)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().playMusicOnHold(musicOnHoldClass);
|
||||
}
|
||||
|
||||
public void stopMusicOnHold()
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().stopMusicOnHold();
|
||||
}
|
||||
|
||||
public int getChannelStatus()
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().getChannelStatus();
|
||||
}
|
||||
|
||||
public String getData(String file)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().getData(file);
|
||||
}
|
||||
|
||||
public String getData(String file, long timeout)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().getData(file, timeout);
|
||||
}
|
||||
|
||||
public String getData(String file, long timeout, int maxDigits)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().getData(file, timeout, maxDigits);
|
||||
}
|
||||
|
||||
public char getOption(String file, String escapeDigits)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().getOption(file, escapeDigits);
|
||||
}
|
||||
|
||||
public char getOption(String file, String escapeDigits, long timeout)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().getOption(file, escapeDigits, timeout);
|
||||
}
|
||||
|
||||
public int exec(String application)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().exec(application);
|
||||
}
|
||||
|
||||
public int exec(String application, String options)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().exec(application, options);
|
||||
}
|
||||
|
||||
public void setContext(String context)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().setContext(context);
|
||||
}
|
||||
|
||||
public void setExtension(String extension)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().setExtension(extension);
|
||||
}
|
||||
|
||||
public void setPriority(String priority)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().setPriority(priority);
|
||||
}
|
||||
|
||||
public void streamFile(String file)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().streamFile(file);
|
||||
}
|
||||
|
||||
public char streamFile(String file, String escapeDigits)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().streamFile(file, escapeDigits);
|
||||
}
|
||||
|
||||
public char streamFile(String file, String escapeDigits, int offset)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().streamFile(file, escapeDigits, offset);
|
||||
}
|
||||
|
||||
public void sayDigits(String digits)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().sayDigits(digits);
|
||||
}
|
||||
|
||||
public char sayDigits(String digits, String escapeDigits)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().sayDigits(digits, escapeDigits);
|
||||
}
|
||||
|
||||
public void sayNumber(String number)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().sayNumber(number);
|
||||
}
|
||||
|
||||
public char sayNumber(String number, String escapeDigits)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().sayNumber(number, escapeDigits);
|
||||
}
|
||||
|
||||
public void sayPhonetic(String text)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().sayPhonetic(text);
|
||||
}
|
||||
|
||||
public char sayPhonetic(String text, String escapeDigits)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().sayPhonetic(text, escapeDigits);
|
||||
}
|
||||
|
||||
public void sayAlpha(String text)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().sayAlpha(text);
|
||||
}
|
||||
|
||||
public char sayAlpha(String text, String escapeDigits)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().sayAlpha(text, escapeDigits);
|
||||
}
|
||||
|
||||
public void sayTime(long time)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().sayTime(time);
|
||||
}
|
||||
|
||||
public char sayTime(long time, String escapeDigits)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().sayTime(time, escapeDigits);
|
||||
}
|
||||
|
||||
public String getVariable(String name)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().getVariable(name);
|
||||
}
|
||||
|
||||
public void setVariable(String name, String value)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().setVariable(name, value);
|
||||
}
|
||||
|
||||
public char waitForDigit(int timeout)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().waitForDigit(timeout);
|
||||
}
|
||||
|
||||
public String getFullVariable(String name)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().getFullVariable(name);
|
||||
}
|
||||
|
||||
public String getFullVariable(String name, String channel)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().getFullVariable(name, channel);
|
||||
}
|
||||
|
||||
public void sayDateTime(long time)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().sayDateTime(time);
|
||||
}
|
||||
|
||||
public char sayDateTime(long time, String escapeDigits)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().sayDateTime(time, escapeDigits);
|
||||
}
|
||||
|
||||
public char sayDateTime(long time, String escapeDigits, String format)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().sayDateTime(time, escapeDigits, format);
|
||||
}
|
||||
|
||||
public char sayDateTime(long time, String escapeDigits, String format, String timezone)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().sayDateTime(time, escapeDigits, format, timezone);
|
||||
}
|
||||
|
||||
public String databaseGet(String family, String key)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().databaseGet(family, key);
|
||||
}
|
||||
|
||||
public void databasePut(String family, String key, String value)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().databasePut(family, key, value);
|
||||
}
|
||||
|
||||
public void databaseDel(String family, String key)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().databaseDel(family, key);
|
||||
}
|
||||
|
||||
public void databaseDelTree(String family)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().databaseDelTree(family);
|
||||
}
|
||||
|
||||
public void databaseDelTree(String family, String keytree)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().databaseDelTree(family, keytree);
|
||||
}
|
||||
|
||||
public void verbose(String message, int level)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().verbose(message, level);
|
||||
}
|
||||
|
||||
public char recordFile(String file, String format, String escapeDigits, int timeout)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().recordFile(file, format, escapeDigits, timeout);
|
||||
}
|
||||
|
||||
public char recordFile(String file, String format, String escapeDigits, int timeout, int offset, boolean beep, int maxSilence)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().recordFile(file, format, escapeDigits, timeout, offset, beep, maxSilence);
|
||||
}
|
||||
|
||||
public void controlStreamFile(String file)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().controlStreamFile(file);
|
||||
}
|
||||
|
||||
public char controlStreamFile(String file, String escapeDigits)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().controlStreamFile(file, escapeDigits);
|
||||
}
|
||||
|
||||
public char controlStreamFile(String file, String escapeDigits, int offset)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().controlStreamFile(file, escapeDigits, offset);
|
||||
}
|
||||
|
||||
public char controlStreamFile(String file, String escapeDigits, int offset, String forwardDigit, String rewindDigit, String pauseDigit)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().controlStreamFile(file, escapeDigits, offset, forwardDigit, rewindDigit, pauseDigit);
|
||||
}
|
||||
|
||||
public void speechCreate() throws AgiException
|
||||
{
|
||||
getChannel().speechCreate();
|
||||
}
|
||||
|
||||
public void speechCreate(String engine)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().speechCreate(engine);
|
||||
}
|
||||
|
||||
public void speechSet(String name, String value)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().speechSet(name, value);
|
||||
}
|
||||
|
||||
public void speechDestroy()
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().speechDestroy();
|
||||
}
|
||||
|
||||
public void speechLoadGrammar(String name, String path)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().speechLoadGrammar(name, path);
|
||||
}
|
||||
|
||||
public void speechUnloadGrammar(String name)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().speechUnloadGrammar(name);
|
||||
}
|
||||
|
||||
public void speechActivateGrammar(String name)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().speechActivateGrammar(name);
|
||||
}
|
||||
|
||||
public void speechDeactivateGrammar(String name)
|
||||
throws AgiException
|
||||
{
|
||||
getChannel().speechDeactivateGrammar(name);
|
||||
}
|
||||
|
||||
public SpeechRecognitionResult speechRecognize(String prompt, int timeout)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().speechRecognize(prompt, timeout);
|
||||
}
|
||||
|
||||
public SpeechRecognitionResult speechRecognize(String prompt, int timeout, int offset)
|
||||
throws AgiException
|
||||
{
|
||||
return getChannel().speechRecognize(prompt, timeout, offset);
|
||||
}
|
||||
|
||||
public void continueAt(String context, String extension, String priority) throws AgiException
|
||||
{
|
||||
getChannel().continueAt(context, extension, priority);
|
||||
}
|
||||
}
|
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Provides client request information to an {@link org.asteriskjava.fastagi.AgiScript}.<p>
|
||||
* This includes information about the channel the script is invoked on and
|
||||
* parameters passed from the dialplan.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AgiRequest.java 1286 2009-04-04 09:40:40Z srt $
|
||||
*/
|
||||
public interface AgiRequest
|
||||
{
|
||||
/**
|
||||
* Returns a Map containing the raw request name/value pairs.
|
||||
*
|
||||
* @return Map contain raw request name/value pairs.
|
||||
*/
|
||||
Map getRequest();
|
||||
|
||||
/**
|
||||
* Returns the name of the script to execute including its full path.<p>
|
||||
* This corresponds to the request url with protocol, host, port and
|
||||
* parameters stripped off.<p>
|
||||
* As Async AGI does not yet pass a script parameter this property will
|
||||
* be <code>null</code> for requests received through Async AGI.
|
||||
*
|
||||
* @return the name of the script to execute.
|
||||
*/
|
||||
String getScript();
|
||||
|
||||
/**
|
||||
* Returns the full URL of the requestURL in the form
|
||||
* agi://host[:port][/script][?param1=value1¶m2=value2].
|
||||
*
|
||||
* @return the full URL of the requestURL in the form
|
||||
* agi://host[:port][/script][?param1=value1¶m2=value2].
|
||||
*/
|
||||
String getRequestURL();
|
||||
|
||||
/**
|
||||
* Returns the name of the channel.
|
||||
*
|
||||
* @return the name of the channel.
|
||||
*/
|
||||
String getChannel();
|
||||
|
||||
/**
|
||||
* Returns the unqiue id of the channel.
|
||||
*
|
||||
* @return the unqiue id of the channel.
|
||||
*/
|
||||
String getUniqueId();
|
||||
|
||||
/**
|
||||
* Returns the type of the channel, for example "SIP".
|
||||
*
|
||||
* @return the type of the channel, for example "SIP".
|
||||
*/
|
||||
String getType();
|
||||
|
||||
/**
|
||||
* Returns the language set for the current channel, for example "en".
|
||||
*
|
||||
* @return the language set for the current channel, for example "en".
|
||||
*/
|
||||
String getLanguage();
|
||||
|
||||
/**
|
||||
* Returns the Caller*ID number, for example "1234".<p>
|
||||
* Note: even with Asterisk 1.0 is contains only the numerical part
|
||||
* of the Caller ID.
|
||||
*
|
||||
* @return the Caller*ID number, for example "1234", if no Caller*ID is set or it
|
||||
* is "unknown" <code>null</code> is returned.
|
||||
* @deprecated as of 0.3, use {@link #getCallerIdNumber()} instead.
|
||||
*/
|
||||
String getCallerId();
|
||||
|
||||
/**
|
||||
* Returns the Caller*ID number, for example "1234".<p>
|
||||
* Note: even with Asterisk 1.0 is contains only the numerical part
|
||||
* of the Caller ID.
|
||||
*
|
||||
* @return the Caller*ID number, for example "1234", if no Caller*ID is set or it
|
||||
* is "unknown" <code>null</code> is returned.
|
||||
*/
|
||||
String getCallerIdNumber();
|
||||
|
||||
/**
|
||||
* Returns the the Caller*ID Name, for example "John Doe".
|
||||
*
|
||||
* @return the the Caller*ID Name, for example "John Doe", if no Caller*ID
|
||||
* Name is set or it is "unknown" <code>null</code> is returned.
|
||||
*/
|
||||
String getCallerIdName();
|
||||
|
||||
/**
|
||||
* Returns the number, that has been dialed by the user.
|
||||
*
|
||||
* @return the dialed number, if no DNID is available or it is "unknown"
|
||||
* <code>null</code> is returned.
|
||||
*/
|
||||
String getDnid();
|
||||
|
||||
/**
|
||||
* If this call has been forwared, the number of the person doing the
|
||||
* redirect is returned (Redirected dialed number identification service).<p>
|
||||
* This is usally only only available on PRI.
|
||||
*
|
||||
* @return the number of the person doing the redirect, , if no RDNIS is
|
||||
* available or it is "unknown" <code>null</code> is returned.
|
||||
*/
|
||||
String getRdnis();
|
||||
|
||||
/**
|
||||
* Returns the context in the dial plan from which the AGI script was
|
||||
* called.
|
||||
*
|
||||
* @return the context in the dial plan from which the AGI script was
|
||||
* called.
|
||||
*/
|
||||
String getContext();
|
||||
|
||||
/**
|
||||
* Returns the extension in the dial plan from which the AGI script was
|
||||
* called.
|
||||
*
|
||||
* @return the extension in the dial plan from which the AGI script was
|
||||
* called.
|
||||
*/
|
||||
String getExtension();
|
||||
|
||||
/**
|
||||
* Returns the priority of the dial plan entry the AGI script was
|
||||
* called from.
|
||||
*
|
||||
* @return the priority of the dial plan entry the AGI script was
|
||||
* called from.
|
||||
*/
|
||||
Integer getPriority();
|
||||
|
||||
/**
|
||||
* Returns wheather this agi is passed audio (EAGI - Enhanced AGI).<p>
|
||||
* Enhanced AGI is currently not supported on FastAGI.
|
||||
*
|
||||
* @return Boolean.TRUE if this agi is passed audio, Boolean.FALSE
|
||||
* otherwise.
|
||||
*/
|
||||
Boolean getEnhanced();
|
||||
|
||||
/**
|
||||
* Returns the account code set for the call.
|
||||
*
|
||||
* @return the account code set for the call.
|
||||
*/
|
||||
String getAccountCode();
|
||||
|
||||
/**
|
||||
* Returns the Callerid presentation/screening.<p>
|
||||
* Available since Asterisk 1.2.
|
||||
*
|
||||
* @return the Callerid presentation/screening.
|
||||
* @since 0.2
|
||||
*/
|
||||
Integer getCallingPres();
|
||||
|
||||
/**
|
||||
* Returns the Callerid ANI 2 (Info digits).<p>
|
||||
* Available since Asterisk 1.2.
|
||||
*
|
||||
* @return the Callerid ANI 2 (Info digits).
|
||||
* @since 0.2
|
||||
*/
|
||||
Integer getCallingAni2();
|
||||
|
||||
/**
|
||||
* Returns the Callerid Type of Number.<p>
|
||||
* Available since Asterisk 1.2.
|
||||
*
|
||||
* @return the Callerid Type of Number.
|
||||
* @since 0.2
|
||||
*/
|
||||
Integer getCallingTon();
|
||||
|
||||
/**
|
||||
* Returns the Callerid Transit Network Select.<p>
|
||||
* Available since Asterisk 1.2.
|
||||
*
|
||||
* @return the Callerid Transit Network Select.
|
||||
* @since 0.2
|
||||
*/
|
||||
Integer getCallingTns();
|
||||
|
||||
/**
|
||||
* Returns the value of a request parameter as a String, or
|
||||
* <code>null</code> if the parameter does not exist. You should only use
|
||||
* this method when you are sure the parameter has only one value.<p>
|
||||
* If the parameter might have more than one value, use
|
||||
* {@link #getParameterValues(String)}.<p>
|
||||
* If you use this method with a multivalued parameter, the value returned
|
||||
* is equal to the first value in the array returned by
|
||||
* <code>getParameterValues</code>.
|
||||
*
|
||||
* @param name a String containing the name of the parameter whose value is
|
||||
* requested.
|
||||
* @return a String representing the single value of the parameter.
|
||||
* @see #getParameterValues(String)
|
||||
*/
|
||||
String getParameter(String name);
|
||||
|
||||
/**
|
||||
* Returns an array of String objects containing all of the values the given
|
||||
* request parameter has, or
|
||||
* an empty array if the parameter does not exist.<p>
|
||||
* If the parameter has a single value, the array has a length of 1.
|
||||
*
|
||||
* @param name a String containing the name of the parameter whose value is requested.
|
||||
* @return an array of String objects containing the parameter's values.
|
||||
*/
|
||||
String[] getParameterValues(String name);
|
||||
|
||||
/**
|
||||
* Returns a Map of the parameters of this request.
|
||||
*
|
||||
* @return a java.util.Map containing parameter names as keys and parameter
|
||||
* values as map values. The keys in the parameter map are of type
|
||||
* String. The values in the parameter map are of type String array.
|
||||
*/
|
||||
Map<String, String[]> getParameterMap();
|
||||
|
||||
/**
|
||||
* Returns the array of arguments passed from the AGI dialplan command.<p>
|
||||
* Example: {@code AGI(agi://localhost/HelloWorld,value1,,value2)} results in
|
||||
* {@code getArguments()[0] = "value1"}, {@code getArguments()[1] = null}
|
||||
* and {@code getArguments()[2] = "value2"}.<p>
|
||||
* Available since Asterisk 1.6
|
||||
*
|
||||
* @return the array of arguments passed from the AGI command, never <code>null</code>.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
String[] getArguments();
|
||||
|
||||
/**
|
||||
* Returns the local address this channel, that is the IP address of the AGI
|
||||
* server.
|
||||
*
|
||||
* @return the local address this channel.
|
||||
* @since 0.2
|
||||
*/
|
||||
InetAddress getLocalAddress();
|
||||
|
||||
/**
|
||||
* Returns the local port of this channel, that is the port the AGI server
|
||||
* is listening on.
|
||||
*
|
||||
* @return the local port of this socket channel.
|
||||
* @since 0.2
|
||||
*/
|
||||
int getLocalPort();
|
||||
|
||||
/**
|
||||
* Returns the remote address of this channel, that is the IP address of the
|
||||
* Asterisk server.
|
||||
*
|
||||
* @return the remote address of this channel.
|
||||
* @since 0.2
|
||||
*/
|
||||
InetAddress getRemoteAddress();
|
||||
|
||||
/**
|
||||
* Returns the remote port of this channel, that is the client port the
|
||||
* Asterisk server is using for the AGI connection.
|
||||
*
|
||||
* @return the remote port of this channel.
|
||||
* @since 0.2
|
||||
*/
|
||||
int getRemotePort();
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
/**
|
||||
* AgiScripts are used by the AsteriskServer to handle AgiRequests received from
|
||||
* the Asterisk server.<p>
|
||||
* To implement functionality using this framework you have to implement this
|
||||
* interface.<p>
|
||||
* Note: The implementation of AgiScript must be threadsafe as only one instance
|
||||
* is used by AsteriskServer to handle all requests to a resource.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AgiScript.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public interface AgiScript
|
||||
{
|
||||
/**
|
||||
* The service method is called by the AsteriskServer whenever this
|
||||
* AgiScript should handle an incoming AgiRequest.
|
||||
*
|
||||
* @param request the initial data received from Asterisk when requesting
|
||||
* this script.
|
||||
* @param channel a handle to communicate with Asterisk such as sending
|
||||
* commands to the channel sending the request.
|
||||
*
|
||||
* @throws AgiException any exception thrown by your script will be logged.
|
||||
*/
|
||||
void service(final AgiRequest request, final AgiChannel channel) throws AgiException;
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Listens for incoming AGI connections, reads the inital data and builds an
|
||||
* {@link AgiRequest} that is then handed over to the appropriate
|
||||
* {@link org.asteriskjava.fastagi.AgiScript} for processing.
|
||||
*
|
||||
* @see org.asteriskjava.fastagi.AgiServerThread
|
||||
* @author srt
|
||||
* @version $Id: AgiServer.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public interface AgiServer
|
||||
{
|
||||
/**
|
||||
* Starts this AgiServer.<p>
|
||||
* After calling startup() this AgiServer is ready to receive requests from
|
||||
* Asterisk servers and process them.<p>
|
||||
* Note that this method will not return until the AgiServer has been shut down.
|
||||
* If you want to run the AgiServer in the background use wrap it with an
|
||||
* {@link AgiServerThread}.
|
||||
*
|
||||
* @throws IOException if the server socket cannot be bound.
|
||||
* @throws IllegalStateException if this AgiServer is already running.
|
||||
*/
|
||||
void startup() throws IOException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Stops this AgiServer.<p>
|
||||
* The server socket is closed, new connections are refused and resources
|
||||
* are freed. Any running {@link AgiScript}s are finish before shutdown
|
||||
* completes.
|
||||
*
|
||||
* @throws IllegalStateException if this AgiServer is already shut down or
|
||||
* has not yet been started.
|
||||
*/
|
||||
void shutdown() throws IllegalStateException;
|
||||
}
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.asteriskjava.util.Log;
|
||||
import org.asteriskjava.util.LogFactory;
|
||||
|
||||
/**
|
||||
* Runs an AgiServer in a separate Thread.
|
||||
* <p>
|
||||
* You can use this class to run an AgiServer in the background of your
|
||||
* application or run it in your servlet container or application server.
|
||||
* <p>
|
||||
* By default the thread used by this class is marked as daemon thread, that
|
||||
* means it will be destroyed when the last user thread has finished.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AgiServerThread.java 938 2007-12-31 03:23:38Z srt $
|
||||
* @since 0.2
|
||||
*/
|
||||
public class AgiServerThread
|
||||
{
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private static AtomicLong idCounter = new AtomicLong();
|
||||
private AgiServer agiServer;
|
||||
private Thread thread;
|
||||
private boolean daemon = true;
|
||||
|
||||
/**
|
||||
* Creates a new AgiServerThread.
|
||||
* <p>
|
||||
* Before you can run this thread you must set an {@link AgiServer} using
|
||||
* {@link #setAgiServer(AgiServer)}.
|
||||
* <p>
|
||||
* This constructor is mainly intended for use with setter based dependency
|
||||
* injection.
|
||||
*/
|
||||
public AgiServerThread()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AgiServerThread that runs the given {@link AgiServer}.
|
||||
*
|
||||
* @param agiServer the AgiServer to run.
|
||||
*/
|
||||
public AgiServerThread(AgiServer agiServer)
|
||||
{
|
||||
super();
|
||||
this.agiServer = agiServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the AgiServer to run.
|
||||
* <p>
|
||||
* This property must be set before starting the AgiServerThread by calling
|
||||
* startup.
|
||||
*
|
||||
* @param agiServer the AgiServer to run.
|
||||
*/
|
||||
public void setAgiServer(AgiServer agiServer)
|
||||
{
|
||||
this.agiServer = agiServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the thread as either a daemon thread or a user thread.
|
||||
* <p>
|
||||
* Default is <code>true</code>.
|
||||
*
|
||||
* @param daemon if <code>false</code>, marks the thread as a user
|
||||
* thread.
|
||||
* @see Thread#setDaemon(boolean)
|
||||
* @since 0.3
|
||||
*/
|
||||
public void setDaemon(boolean daemon)
|
||||
{
|
||||
this.daemon = daemon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the AgiServer in its own thread.
|
||||
* <p>
|
||||
* Note: The AgiServerThread is designed to handle one AgiServer instance at
|
||||
* a time so calling this method twice without stopping the AgiServer in
|
||||
* between will result in a RuntimeException.
|
||||
*
|
||||
* @throws IllegalStateException if the mandatory property agiServer has not
|
||||
* been set or the AgiServer had already been started.
|
||||
* @throws RuntimeException if the AgiServer can't be started due to IO
|
||||
* problems, for example because the socket has already been
|
||||
* bound by another process.
|
||||
*/
|
||||
public synchronized void startup() throws IllegalStateException, RuntimeException
|
||||
{
|
||||
if (agiServer == null)
|
||||
{
|
||||
throw new IllegalStateException("Mandatory property agiServer is not set.");
|
||||
}
|
||||
|
||||
if (thread != null)
|
||||
{
|
||||
throw new IllegalStateException("AgiServer is already started");
|
||||
}
|
||||
|
||||
thread = createThread();
|
||||
thread.start();
|
||||
}
|
||||
|
||||
protected Thread createThread()
|
||||
{
|
||||
Thread t;
|
||||
|
||||
t = new Thread(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
agiServer.startup();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
throw new RuntimeException("Exception running AgiServer.", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
t.setName("Asterisk-Java AgiServer-" + idCounter.getAndIncrement());
|
||||
t.setDaemon(daemon);
|
||||
t.setUncaughtExceptionHandler(new AgiThreadUncaughtExceptionHanlder());
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the {@link AgiServer}.
|
||||
* <p>
|
||||
* The AgiServer must have been started by calling {@link #startup()} before
|
||||
* you can stop it.
|
||||
*
|
||||
* @see AgiServer#shutdown()
|
||||
* @throws IllegalStateException if the mandatory property agiServer has not
|
||||
* been set or the AgiServer had already been shut down.
|
||||
*/
|
||||
public synchronized void shutdown() throws IllegalStateException
|
||||
{
|
||||
if (agiServer == null)
|
||||
{
|
||||
throw new IllegalStateException("Mandatory property agiServer is not set.");
|
||||
}
|
||||
|
||||
agiServer.shutdown();
|
||||
|
||||
if (thread != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
thread.join();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
logger.warn("Interrupted while waiting for AgiServer to shutdown.");
|
||||
}
|
||||
thread = null; // NOPMD by srt on 7/5/06 11:23 PM
|
||||
}
|
||||
}
|
||||
|
||||
class AgiThreadUncaughtExceptionHanlder implements UncaughtExceptionHandler
|
||||
{
|
||||
public void uncaughtException(Thread t, Throwable e)
|
||||
{
|
||||
logger.error("Uncaught exception in AgiServerThread", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
/**
|
||||
* The AgiSpeechException is thrown if a speech command can not be executed
|
||||
* successfully. The Asterisk Speech API is not very verbose about the reasons for
|
||||
* a failure so this exception is thrown for all failures of the speech
|
||||
* recognition engine.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AgiSpeechException.java 1271 2009-03-21 03:41:24Z srt $
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class AgiSpeechException extends AgiException
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
/**
|
||||
* Creates a new AgiSpeechException with the given message.
|
||||
*
|
||||
* @param message the message
|
||||
*/
|
||||
public AgiSpeechException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
package org.asteriskjava.fastagi;
|
||||
|
||||
import org.asteriskjava.manager.ManagerEventListener;
|
||||
import org.asteriskjava.manager.ManagerConnection;
|
||||
import org.asteriskjava.manager.event.ManagerEvent;
|
||||
import org.asteriskjava.manager.event.AsyncAgiEvent;
|
||||
import org.asteriskjava.manager.event.RenameEvent;
|
||||
import org.asteriskjava.util.Log;
|
||||
import org.asteriskjava.util.LogFactory;
|
||||
import org.asteriskjava.fastagi.internal.AsyncAgiConnectionHandler;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* AGI server for AGI over the Manager API (AsyncAGI).<p>
|
||||
* AsyncAGI is available since Asterisk 1.6.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class AsyncAgiServer extends AbstractAgiServer implements ManagerEventListener
|
||||
{
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final Map<Integer, AsyncAgiConnectionHandler> connectionHandlers;
|
||||
|
||||
/**
|
||||
* Creates a new AsyncAgiServer.<p>
|
||||
* Note that you must set a {@link org.asteriskjava.fastagi.MappingStrategy} before using it.
|
||||
* @see #setMappingStrategy(MappingStrategy)
|
||||
*/
|
||||
public AsyncAgiServer()
|
||||
{
|
||||
this.connectionHandlers = new HashMap<Integer, AsyncAgiConnectionHandler>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AsyncAgiServer with the given MappingStrategy.<p>
|
||||
* Please note that Async AGI does not currently support passing a script name, so your
|
||||
* MappingStrategy must be aware that the {@link org.asteriskjava.fastagi.AgiRequest#getScript() script}
|
||||
* property of the AgiRequests will likely be <code>null</code>.
|
||||
*
|
||||
* @param mappingStrategy the MappingStrategy to use to determine which AGI script to run
|
||||
* for a certain request.
|
||||
*/
|
||||
public AsyncAgiServer(MappingStrategy mappingStrategy)
|
||||
{
|
||||
this();
|
||||
setMappingStrategy(mappingStrategy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AsyncAgiServer that will execute the given AGI script for every
|
||||
* request.<p>
|
||||
* Internally this constructor uses a {@link org.asteriskjava.fastagi.StaticMappingStrategy}.
|
||||
*
|
||||
* @param agiScript the AGI script to execute.
|
||||
*/
|
||||
public AsyncAgiServer(AgiScript agiScript)
|
||||
{
|
||||
this();
|
||||
setMappingStrategy(new StaticMappingStrategy(agiScript));
|
||||
}
|
||||
|
||||
public void onManagerEvent(ManagerEvent event)
|
||||
{
|
||||
if (event instanceof AsyncAgiEvent)
|
||||
{
|
||||
handleAsyncAgiEvent((AsyncAgiEvent) event);
|
||||
}
|
||||
else if (event instanceof RenameEvent)
|
||||
{
|
||||
handleRenameEvent((RenameEvent) event);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAsyncAgiEvent(AsyncAgiEvent asyncAgiEvent)
|
||||
{
|
||||
final ManagerConnection connection;
|
||||
final String channelName;
|
||||
final AsyncAgiConnectionHandler connectionHandler;
|
||||
|
||||
connection = (ManagerConnection) asyncAgiEvent.getSource();
|
||||
channelName = asyncAgiEvent.getChannel();
|
||||
|
||||
if (asyncAgiEvent.isStart())
|
||||
{
|
||||
connectionHandler = new AsyncAgiConnectionHandler(getMappingStrategy(), asyncAgiEvent);
|
||||
setConnectionHandler(connection, channelName, connectionHandler);
|
||||
execute(connectionHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
connectionHandler = getConnectionHandler(connection, channelName);
|
||||
if (connectionHandler == null)
|
||||
{
|
||||
logger.info("No AsyncAgiConnectionHandler registered for channel " + channelName + ": Ignoring AsyncAgiEvent");
|
||||
return;
|
||||
}
|
||||
|
||||
if (asyncAgiEvent.isExec())
|
||||
{
|
||||
connectionHandler.onAsyncAgiExecEvent(asyncAgiEvent);
|
||||
}
|
||||
else if (asyncAgiEvent.isEnd())
|
||||
{
|
||||
connectionHandler.onAsyncAgiEndEvent(asyncAgiEvent);
|
||||
removeConnectionHandler(connection, channelName);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("Ignored unknown AsyncAgiEvent of sub type '" + asyncAgiEvent.getSubEvent() + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRenameEvent(RenameEvent renameEvent)
|
||||
{
|
||||
final ManagerConnection connection = (ManagerConnection) renameEvent.getSource();
|
||||
final AsyncAgiConnectionHandler connectionHandler = getConnectionHandler(connection, renameEvent.getChannel());
|
||||
|
||||
if (connectionHandler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
removeConnectionHandler(connection, renameEvent.getChannel());
|
||||
setConnectionHandler(connection, renameEvent.getNewname(), connectionHandler);
|
||||
|
||||
connectionHandler.updateChannelName(renameEvent.getNewname());
|
||||
}
|
||||
|
||||
private AsyncAgiConnectionHandler getConnectionHandler(ManagerConnection connection, String channelName)
|
||||
{
|
||||
synchronized (connectionHandlers)
|
||||
{
|
||||
return connectionHandlers.get(calculateHashKey(connection, channelName));
|
||||
}
|
||||
}
|
||||
|
||||
private void setConnectionHandler(ManagerConnection connection, String channelName, AsyncAgiConnectionHandler connectionHandler)
|
||||
{
|
||||
synchronized (connectionHandlers)
|
||||
{
|
||||
connectionHandlers.put(calculateHashKey(connection, channelName), connectionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeConnectionHandler(ManagerConnection connection, String channelName)
|
||||
{
|
||||
synchronized (connectionHandlers)
|
||||
{
|
||||
connectionHandlers.remove(calculateHashKey(connection, channelName));
|
||||
}
|
||||
}
|
||||
|
||||
private Integer calculateHashKey(ManagerConnection connection, String channelName)
|
||||
{
|
||||
return connection.hashCode() * 31 + channelName.hashCode();
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
/**
|
||||
* The BaseAgiScript provides some convinience methods to make it easier to
|
||||
* write custom {@link org.asteriskjava.fastagi.AgiScript}s.
|
||||
* <p>
|
||||
* Just extend it by your own script classes.
|
||||
*
|
||||
* @since 0.2
|
||||
* @author srt
|
||||
* @version $Id: BaseAgiScript.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public abstract class BaseAgiScript extends AgiOperations implements AgiScript
|
||||
{
|
||||
public BaseAgiScript()
|
||||
{
|
||||
super();
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A MappingStrategy that determines the AGIScript based on the fully
|
||||
* qualified class name given in the AGI URL.<p>
|
||||
* To use this ClassNameMappingStrategy the calls to your
|
||||
* {@link org.asteriskjava.fastagi.AgiScript} in
|
||||
* your dialplan should look like this:
|
||||
* <pre>
|
||||
* exten => 123,1,AGI(agi://your.server.com/com.example.agi.MyScript)
|
||||
* </pre>
|
||||
* Where com.example.agi.MyScript is the fully qualified name of your
|
||||
* AgiScript.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: ClassNameMappingStrategy.java 1140 2008-08-18 18:49:36Z srt $
|
||||
*/
|
||||
public class ClassNameMappingStrategy extends AbstractMappingStrategy
|
||||
{
|
||||
private Map<String, AgiScript> instances;
|
||||
private boolean shareInstances;
|
||||
|
||||
/**
|
||||
* Creates a new ClassNameMappingStrategy using shared instances.
|
||||
*/
|
||||
public ClassNameMappingStrategy()
|
||||
{
|
||||
this(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ClassNameMappingStrategy indicating whether to use shared
|
||||
* instances or not.
|
||||
*
|
||||
* @param shareInstances <code>true</code> to use shared instances,
|
||||
* <code>false</code> to create a new instance for
|
||||
* each request.
|
||||
* @since 0.3
|
||||
*/
|
||||
public ClassNameMappingStrategy(boolean shareInstances)
|
||||
{
|
||||
super();
|
||||
this.instances = new HashMap<String, AgiScript>();
|
||||
this.shareInstances = shareInstances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to use shared instances or not. If set to <code>true</code>
|
||||
* all AGIRequests are served by the same instance of an
|
||||
* AGIScript, if set to <code>false</code> a new instance is created for
|
||||
* each request.<p>
|
||||
* Default is <code>true</code>.
|
||||
*
|
||||
* @param shareInstances <code>true</code> to use shared instances,
|
||||
* <code>false</code> to create a new instance for
|
||||
* each request.
|
||||
* @since 0.3
|
||||
*/
|
||||
public synchronized void setShareInstances(boolean shareInstances)
|
||||
{
|
||||
this.shareInstances = shareInstances;
|
||||
}
|
||||
|
||||
public synchronized AgiScript determineScript(AgiRequest request)
|
||||
{
|
||||
AgiScript script;
|
||||
|
||||
if (shareInstances)
|
||||
{
|
||||
script = instances.get(request.getScript());
|
||||
if (script != null)
|
||||
{
|
||||
return script;
|
||||
}
|
||||
}
|
||||
|
||||
script = createAgiScriptInstance(request.getScript());
|
||||
if (script == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (shareInstances)
|
||||
{
|
||||
instances.put(request.getScript(), script);
|
||||
}
|
||||
|
||||
return script;
|
||||
}
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A mapping strategy that tries a sequence of other mapping strategies to find
|
||||
* an AgiScript matching the request. The first strategy that returns a result wins,
|
||||
* so the order of the mapping strategies passed to the CompositeMappingStrategy
|
||||
* matters.<p>
|
||||
* Example:
|
||||
* <pre>
|
||||
* new CompositeMappingStrategy(
|
||||
* new ResourceBundleMappingStrategy(),
|
||||
* new ClassNameMappingStrategy());
|
||||
* </pre>
|
||||
* This creates a new mapping strategy that first tries to look up the script
|
||||
* in <code>fastagi-mapping.properties</code> and - if the properties file is
|
||||
* not present on the classpath or contains no mapping for the request - uses
|
||||
* a {@link ClassNameMappingStrategy} to get the script.
|
||||
*
|
||||
* @see ResourceBundleMappingStrategy
|
||||
* @see ClassNameMappingStrategy
|
||||
* @author srt
|
||||
* @since 0.3
|
||||
* @version $Id: CompositeMappingStrategy.java 1015 2008-04-04 21:56:36Z srt $
|
||||
*/
|
||||
public class CompositeMappingStrategy implements MappingStrategy
|
||||
{
|
||||
private List<MappingStrategy> strategies;
|
||||
|
||||
/**
|
||||
* Creates a new empty CompositeMappingStrategy.
|
||||
*/
|
||||
public CompositeMappingStrategy()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CompositeMappingStrategy.
|
||||
*
|
||||
* @param strategies the strategies to use.
|
||||
*/
|
||||
public CompositeMappingStrategy(MappingStrategy... strategies)
|
||||
{
|
||||
super();
|
||||
this.strategies = new ArrayList<MappingStrategy>(Arrays.asList(strategies));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CompositeMappingStrategy.
|
||||
*
|
||||
* @param strategies the strategies to use.
|
||||
*/
|
||||
public CompositeMappingStrategy(List<MappingStrategy> strategies)
|
||||
{
|
||||
super();
|
||||
this.strategies = new ArrayList<MappingStrategy>(strategies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a strategy (at the end of the list).
|
||||
*
|
||||
* @param strategy the strategy to add.
|
||||
*/
|
||||
public void addStrategy(MappingStrategy strategy)
|
||||
{
|
||||
if (strategies == null)
|
||||
{
|
||||
strategies = new ArrayList<MappingStrategy>();
|
||||
}
|
||||
strategies.add(strategy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategies to use.
|
||||
*
|
||||
* @param strategies the strategies to use.
|
||||
*/
|
||||
public void setStrategies(List<MappingStrategy> strategies)
|
||||
{
|
||||
this.strategies = new ArrayList<MappingStrategy>(strategies);
|
||||
}
|
||||
|
||||
public AgiScript determineScript(AgiRequest request)
|
||||
{
|
||||
AgiScript script = null;
|
||||
|
||||
if (strategies == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (MappingStrategy strategy : strategies)
|
||||
{
|
||||
script = strategy.determineScript(request);
|
||||
if (script != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return script;
|
||||
}
|
||||
}
|
@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import org.asteriskjava.fastagi.internal.AgiConnectionHandler;
|
||||
import org.asteriskjava.fastagi.internal.FastAgiConnectionHandler;
|
||||
import org.asteriskjava.util.*;
|
||||
import org.asteriskjava.util.internal.ServerSocketFacadeImpl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link org.asteriskjava.fastagi.AgiServer} interface for FastAGI.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: DefaultAgiServer.java 1304 2009-05-12 22:51:12Z srt $
|
||||
*/
|
||||
public class DefaultAgiServer extends AbstractAgiServer implements AgiServer
|
||||
{
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* The default name of the resource bundle that contains the config.
|
||||
*/
|
||||
private static final String DEFAULT_CONFIG_RESOURCE_BUNDLE_NAME = "fastagi";
|
||||
|
||||
/**
|
||||
* The default bind port.
|
||||
*/
|
||||
private static final int DEFAULT_BIND_PORT = 4573;
|
||||
|
||||
private ServerSocketFacade serverSocket;
|
||||
private String configResourceBundleName = DEFAULT_CONFIG_RESOURCE_BUNDLE_NAME;
|
||||
private int port = DEFAULT_BIND_PORT;
|
||||
|
||||
/**
|
||||
* Creates a new DefaultAgiServer.
|
||||
*/
|
||||
public DefaultAgiServer()
|
||||
{
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DefaultAgiServer and loads its configuration from an alternative resource bundle.
|
||||
*
|
||||
* @param configResourceBundleName the name of the conifiguration resource bundle (default is "fastagi").
|
||||
*/
|
||||
public DefaultAgiServer(String configResourceBundleName)
|
||||
{
|
||||
this(configResourceBundleName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DefaultAgiServer that uses the given {@link MappingStrategy}.
|
||||
*
|
||||
* @param mappingStrategy the MappingStrategy to use to determine the AgiScript to run.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public DefaultAgiServer(MappingStrategy mappingStrategy)
|
||||
{
|
||||
this(null, mappingStrategy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DefaultAgiServer that runs the given {@link AgiScript} for all requests.
|
||||
*
|
||||
* @param agiScript the AgiScript to run.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public DefaultAgiServer(AgiScript agiScript)
|
||||
{
|
||||
this(null, new StaticMappingStrategy(agiScript));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DefaultAgiServer and loads its configuration from an alternative resource bundle and
|
||||
* uses the given {@link MappingStrategy}.
|
||||
*
|
||||
* @param configResourceBundleName the name of the conifiguration resource bundle (default is "fastagi").
|
||||
* @param mappingStrategy the MappingStrategy to use to determine the AgiScript to run.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public DefaultAgiServer(String configResourceBundleName, MappingStrategy mappingStrategy)
|
||||
{
|
||||
super();
|
||||
if (mappingStrategy == null)
|
||||
{
|
||||
final CompositeMappingStrategy compositeMappingStrategy = new CompositeMappingStrategy();
|
||||
|
||||
compositeMappingStrategy.addStrategy(new ResourceBundleMappingStrategy());
|
||||
compositeMappingStrategy.addStrategy(new ClassNameMappingStrategy());
|
||||
if (ReflectionUtil.isClassAvailable("javax.script.ScriptEngineManager"))
|
||||
{
|
||||
MappingStrategy scriptEngineMappingStrategy =
|
||||
(MappingStrategy) ReflectionUtil.newInstance("org.asteriskjava.fastagi.ScriptEngineMappingStrategy");
|
||||
if (scriptEngineMappingStrategy != null)
|
||||
{
|
||||
compositeMappingStrategy.addStrategy(scriptEngineMappingStrategy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("ScriptEngine support disabled: It is only availble when running at least Java 6");
|
||||
}
|
||||
|
||||
setMappingStrategy(compositeMappingStrategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
setMappingStrategy(mappingStrategy);
|
||||
}
|
||||
|
||||
if (configResourceBundleName != null)
|
||||
{
|
||||
this.configResourceBundleName = configResourceBundleName;
|
||||
}
|
||||
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the TCP port to listen on for new connections.
|
||||
* <p/>
|
||||
* The default port is 4573.
|
||||
*
|
||||
* @param bindPort the port to bind to.
|
||||
* @deprecated use {@see #setPort(int)} instead
|
||||
*/
|
||||
public void setBindPort(int bindPort)
|
||||
{
|
||||
this.port = bindPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the TCP port to listen on for new connections.
|
||||
* <p/>
|
||||
* The default port is 4573.
|
||||
*
|
||||
* @param port the port to bind to.
|
||||
* @since 0.2
|
||||
*/
|
||||
public void setPort(int port)
|
||||
{
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TCP port this server is configured to bind to.
|
||||
*
|
||||
* @return the TCP port this server is configured to bind to.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public int getPort()
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
private void loadConfig()
|
||||
{
|
||||
final ResourceBundle resourceBundle;
|
||||
|
||||
try
|
||||
{
|
||||
resourceBundle = ResourceBundle.getBundle(configResourceBundleName);
|
||||
}
|
||||
catch (MissingResourceException e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
String portString;
|
||||
|
||||
try
|
||||
{
|
||||
portString = resourceBundle.getString("port");
|
||||
}
|
||||
catch (MissingResourceException e)
|
||||
{
|
||||
// for backward compatibility only
|
||||
portString = resourceBundle.getString("bindPort");
|
||||
}
|
||||
port = Integer.parseInt(portString);
|
||||
}
|
||||
catch (Exception e) // NOPMD
|
||||
{
|
||||
// swallow
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
setPoolSize(Integer.parseInt(resourceBundle.getString("poolSize")));
|
||||
}
|
||||
catch (Exception e) // NOPMD
|
||||
{
|
||||
// swallow
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
setMaximumPoolSize(Integer.parseInt(resourceBundle.getString("maximumPoolSize")));
|
||||
}
|
||||
catch (Exception e) // NOPMD
|
||||
{
|
||||
// swallow
|
||||
}
|
||||
}
|
||||
|
||||
protected ServerSocketFacade createServerSocket() throws IOException
|
||||
{
|
||||
return new ServerSocketFacadeImpl(port, 0, null);
|
||||
}
|
||||
|
||||
public void startup() throws IOException, IllegalStateException
|
||||
{
|
||||
SocketConnectionFacade socket;
|
||||
AgiConnectionHandler connectionHandler;
|
||||
|
||||
try
|
||||
{
|
||||
serverSocket = createServerSocket();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("Unable start AgiServer: cannot to bind to *:" + port + ".", e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
logger.info("Listening on *:" + port + ".");
|
||||
|
||||
// loop will be terminated by accept() throwing an IOException when the
|
||||
// ServerSocket is closed.
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket = serverSocket.accept();
|
||||
logger.info("Received connection from " + socket.getRemoteAddress());
|
||||
connectionHandler = new FastAgiConnectionHandler(getMappingStrategy(), socket);
|
||||
execute(connectionHandler);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// swallow only if shutdown
|
||||
if (isDie())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.error("IOException while waiting for connections.", e);
|
||||
// log error but continue
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.info("AgiServer shut down.");
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
startup();
|
||||
}
|
||||
catch (IOException e) // NOPMD
|
||||
{
|
||||
// nothing we can do about that and exceptions have already been logged
|
||||
// by startup().
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() throws IllegalStateException
|
||||
{
|
||||
// setting the death flag causes the accept() loop to exit when a
|
||||
// SocketException occurs.
|
||||
super.shutdown();
|
||||
|
||||
if (serverSocket != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// closes the server socket and throws a SocketException on
|
||||
// Threads waiting in accept()
|
||||
serverSocket.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.warn("IOException while closing server socket.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable
|
||||
{
|
||||
super.finalize();
|
||||
|
||||
if (serverSocket != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
serverSocket.close();
|
||||
}
|
||||
catch (IOException e) // NOPMD
|
||||
{
|
||||
// swallow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
final AgiServer server;
|
||||
|
||||
server = new DefaultAgiServer();
|
||||
server.startup();
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
/**
|
||||
* An InvalidCommandSyntaxException is thrown when the reader receives a reply
|
||||
* with status code 520.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: InvalidCommandSyntaxException.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class InvalidCommandSyntaxException extends AgiException
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 3257002168165807929L;
|
||||
|
||||
private final String synopsis;
|
||||
private final String usage;
|
||||
|
||||
/**
|
||||
* Creates a new InvalidCommandSyntaxException with the given synopsis and
|
||||
* usage.
|
||||
*
|
||||
* @param synopsis the synopsis of the command.
|
||||
* @param usage the usage of the command.
|
||||
*/
|
||||
public InvalidCommandSyntaxException(String synopsis, String usage)
|
||||
{
|
||||
super("Invalid command syntax: " + synopsis);
|
||||
this.synopsis = synopsis;
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the synopsis of the command that was called with invalid syntax.
|
||||
*
|
||||
* @return the synopsis of the command that was called with invalid syntax.
|
||||
*/
|
||||
public String getSynopsis()
|
||||
{
|
||||
return synopsis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a description of the command that was called with invalid syntax.
|
||||
*
|
||||
* @return a description of the command that was called with invalid syntax.
|
||||
*/
|
||||
public String getUsage()
|
||||
{
|
||||
return usage;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
/**
|
||||
* An InvalidOrUnknownCommandException is thrown when the reader receives a reply
|
||||
* with status code 510.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: InvalidOrUnknownCommandException.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class InvalidOrUnknownCommandException extends AgiException
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 3257002168165807929L;
|
||||
|
||||
/**
|
||||
* Creates a new InvalidOrUnknownCommandException.
|
||||
*
|
||||
* @param command the invalid or unknown command.
|
||||
*/
|
||||
public InvalidOrUnknownCommandException(String command)
|
||||
{
|
||||
super("Invalid or unknown command: " + command);
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
/**
|
||||
* A MappingStrategy determines which {@link org.asteriskjava.fastagi.AgiScript}
|
||||
* is called to service a given {@link org.asteriskjava.fastagi.AgiRequest}.<p>
|
||||
* A MappingStrategy can use any of the properties
|
||||
* of an AgiRequest to do this. However most MappingStrategies will just use
|
||||
* the script property, that is the name of the invoked AGI script as passed
|
||||
* from Asterisk's dialplan.<p>
|
||||
* Asterisk-Java ships with several mapping strategies that are available out
|
||||
* of the box. If you have some special requirements that are not satisfied by
|
||||
* any of the available strategies feel free to implement this interface and
|
||||
* use your own strategy.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: MappingStrategy.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public interface MappingStrategy
|
||||
{
|
||||
/**
|
||||
* Returns the AgiScript instance that is responsible to handle
|
||||
* the given request.
|
||||
*
|
||||
* @param request the request to lookup.
|
||||
* @return the AgiScript instance to handle this request
|
||||
* or <code>null</code> if none could be determined by this strategy.
|
||||
*/
|
||||
AgiScript determineScript(AgiRequest request);
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
/**
|
||||
* Interface for an AgiScript that provides a name for logging and management.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface NamedAgiScript extends AgiScript
|
||||
{
|
||||
/**
|
||||
* Returns the name of the script.
|
||||
*
|
||||
* @return the name of the script
|
||||
*/
|
||||
String getName();
|
||||
}
|
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A MappingStrategy that is configured via a resource bundle.<p>
|
||||
* The resource bundle contains the script part of the url as key and the fully
|
||||
* qualified class name of the corresponding AgiScript as value.<p>
|
||||
* Example:
|
||||
*
|
||||
* <pre>
|
||||
* leastcostdial.agi = com.example.fastagi.LeastCostDialAgiScript
|
||||
* hello.agi = com.example.fastagi.HelloAgiScript
|
||||
* </pre>
|
||||
*
|
||||
* LeastCostDialAgiScript and HelloAgiScript must both implement the AgiScript
|
||||
* interface and have a default constructor with no parameters.<p>
|
||||
* The resource bundle (properties) file is called
|
||||
* <code>fastagi-mapping.properties</code> by default and must be available on
|
||||
* the classpath.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: ResourceBundleMappingStrategy.java 1140 2008-08-18 18:49:36Z srt $
|
||||
*/
|
||||
public class ResourceBundleMappingStrategy extends AbstractMappingStrategy
|
||||
{
|
||||
private static final String DEFAULT_RESOURCE_BUNDLE_NAME = "fastagi-mapping";
|
||||
private String resourceBundleName;
|
||||
private Map<String, String> mappings;
|
||||
private Map<String, AgiScript> instances;
|
||||
private boolean shareInstances;
|
||||
|
||||
/**
|
||||
* Creates a new ResourceBundleMappingStrategy using shared instances..
|
||||
*/
|
||||
public ResourceBundleMappingStrategy()
|
||||
{
|
||||
this(DEFAULT_RESOURCE_BUNDLE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ResourceBundleMappingStrategy with the given basename
|
||||
* of the resource bundle to use.
|
||||
*
|
||||
* @param resourceBundleName basename of the resource bundle to use
|
||||
*/
|
||||
public ResourceBundleMappingStrategy(String resourceBundleName)
|
||||
{
|
||||
this(resourceBundleName, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ResourceBundleMappingStrategy indicating whether to use shared
|
||||
* instances or not.
|
||||
*
|
||||
* @param shareInstances <code>true</code> to use shared instances,
|
||||
* <code>false</code> to create a new instance for
|
||||
* each request.
|
||||
* @since 0.3
|
||||
*/
|
||||
public ResourceBundleMappingStrategy(boolean shareInstances)
|
||||
{
|
||||
this(DEFAULT_RESOURCE_BUNDLE_NAME, shareInstances);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ResourceBundleMappingStrategy with the given basename
|
||||
* of the resource bundle to use and indicating whether to use shared
|
||||
* instances or not.
|
||||
*
|
||||
* @param resourceBundleName basename of the resource bundle to use
|
||||
* @param shareInstances <code>true</code> to use shared instances,
|
||||
* <code>false</code> to create a new instance for
|
||||
* each request.
|
||||
* @since 0.3
|
||||
*/
|
||||
public ResourceBundleMappingStrategy(String resourceBundleName, boolean shareInstances)
|
||||
{
|
||||
super();
|
||||
this.resourceBundleName = resourceBundleName;
|
||||
this.shareInstances = shareInstances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the basename of the resource bundle to use.<p>
|
||||
* Default is "fastagi-mapping".
|
||||
*
|
||||
* @param resourceBundleName basename of the resource bundle to use
|
||||
*/
|
||||
public void setResourceBundleName(String resourceBundleName)
|
||||
{
|
||||
this.resourceBundleName = resourceBundleName;
|
||||
synchronized (this)
|
||||
{
|
||||
this.mappings = null;
|
||||
this.instances = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to use shared instances or not. If set to <code>true</code>
|
||||
* all AgiRequests are served by the same instance of an
|
||||
* AgiScript, if set to <code>false</code> a new instance is created for
|
||||
* each request.<p>
|
||||
* Default is <code>true</code>.
|
||||
*
|
||||
* @param shareInstances <code>true</code> to use shared instances,
|
||||
* <code>false</code> to create a new instance for
|
||||
* each request.
|
||||
* @since 0.3
|
||||
*/
|
||||
public synchronized void setShareInstances(boolean shareInstances)
|
||||
{
|
||||
this.shareInstances = shareInstances;
|
||||
}
|
||||
|
||||
private synchronized void loadResourceBundle()
|
||||
{
|
||||
ResourceBundle resourceBundle;
|
||||
Enumeration keys;
|
||||
|
||||
mappings = new HashMap<String, String>();
|
||||
if (shareInstances)
|
||||
{
|
||||
instances = new HashMap<String, AgiScript>();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
resourceBundle = ResourceBundle.getBundle(resourceBundleName, Locale.getDefault(), getClassLoader());
|
||||
}
|
||||
catch (MissingResourceException e)
|
||||
{
|
||||
logger.info("Resource bundle '" + resourceBundleName + "' not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
keys = resourceBundle.getKeys();
|
||||
|
||||
while (keys.hasMoreElements())
|
||||
{
|
||||
String scriptName;
|
||||
String className;
|
||||
AgiScript agiScript;
|
||||
|
||||
scriptName = (String) keys.nextElement();
|
||||
className = resourceBundle.getString(scriptName);
|
||||
|
||||
mappings.put(scriptName, className);
|
||||
|
||||
if (shareInstances)
|
||||
{
|
||||
agiScript = createAgiScriptInstance(className);
|
||||
if (agiScript == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
instances.put(scriptName, agiScript);
|
||||
}
|
||||
|
||||
logger.info("Added mapping for '" + scriptName + "' to class " + className);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized AgiScript determineScript(AgiRequest request)
|
||||
{
|
||||
if (mappings == null || (shareInstances && instances == null))
|
||||
{
|
||||
loadResourceBundle();
|
||||
}
|
||||
|
||||
if (shareInstances)
|
||||
{
|
||||
return instances.get(request.getScript());
|
||||
}
|
||||
else
|
||||
{
|
||||
return createAgiScriptInstance(mappings.get(request.getScript()));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,385 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import org.asteriskjava.util.LogFactory;
|
||||
import org.asteriskjava.util.Log;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptException;
|
||||
import java.io.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.net.URLClassLoader;
|
||||
import java.net.URL;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
/**
|
||||
* A MappingStrategy that uses {@see javax.script.ScriptEngine} to run AgiScripts. This MappingStrategy
|
||||
* can be used to run JavaScript, Groovy, JRuby, etc. scripts.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ScriptEngineMappingStrategy implements MappingStrategy
|
||||
{
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* The binding under which the AGI request is made available to scripts.
|
||||
*/
|
||||
public static final String REQUEST = "request";
|
||||
|
||||
/**
|
||||
* The binding under which the AGI channel is made available to scripts.
|
||||
*/
|
||||
public static final String CHANNEL = "channel";
|
||||
|
||||
private static final String[] DEFAULT_SCRIPT_PATH = new String[]{"agi"};
|
||||
private static final String[] DEFAULT_LIB_PATH = new String[]{"lib"};
|
||||
|
||||
protected String[] scriptPath;
|
||||
protected String[] libPath;
|
||||
protected ScriptEngineManager scriptEngineManager = null;
|
||||
|
||||
/**
|
||||
* Creates a new ScriptEngineMappingStrategy that searches for scripts in the current directory.
|
||||
*/
|
||||
public ScriptEngineMappingStrategy()
|
||||
{
|
||||
this(DEFAULT_SCRIPT_PATH, DEFAULT_LIB_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ScriptEngineMappingStrategy that searches for scripts on the given path.
|
||||
*
|
||||
* @param scriptPath array of directory names to search for script files.
|
||||
* @param libPath array of directory names to search for additional libraries (jar files).
|
||||
*/
|
||||
public ScriptEngineMappingStrategy(String[] scriptPath, String[] libPath)
|
||||
{
|
||||
this.scriptPath = scriptPath;
|
||||
this.libPath = libPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path to search for script files.<p>
|
||||
* Default is "agi".
|
||||
*
|
||||
* @param scriptPath array of directory names to search for script files.
|
||||
*/
|
||||
public void setScriptPath(String[] scriptPath)
|
||||
{
|
||||
this.scriptPath = scriptPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path to search for additional libraries (jar files).<p>
|
||||
* Default is "lib".
|
||||
*
|
||||
* @param libPath array of directory names to search for additional libraries (jar files).
|
||||
*/
|
||||
public void setLibPath(String[] libPath)
|
||||
{
|
||||
this.libPath = libPath;
|
||||
}
|
||||
|
||||
public AgiScript determineScript(AgiRequest request)
|
||||
{
|
||||
// check is a file corresponding to the AGI request is found on the scriptPath
|
||||
final File file = searchFile(request.getScript(), scriptPath);
|
||||
if (file == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// check if there is a ScriptEngine that can handle the file
|
||||
final ScriptEngine scriptEngine = getScriptEngine(file);
|
||||
if (scriptEngine == null)
|
||||
{
|
||||
logger.debug("No ScriptEngine found that can handle '" + file.getPath() + "'");
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ScriptEngineAgiScript(file, scriptEngine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a ScriptEngine that can handle the given file.
|
||||
*
|
||||
* @param file the file to search a ScriptEngine for.
|
||||
* @return the ScriptEngine or <code>null</code> if none is found.
|
||||
*/
|
||||
protected ScriptEngine getScriptEngine(File file)
|
||||
{
|
||||
final String extension = getExtension(file.getName());
|
||||
if (extension == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return getScriptEngineManager().getEngineByExtension(extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ScriptEngineManager to use for loading the ScriptEngine. The ScriptEngineManager is only
|
||||
* created once and reused for subsequent requests. Override this method to provide your own implementation.
|
||||
*
|
||||
* @return the ScriptEngineManager to use for loading the ScriptEngine.
|
||||
* @see javax.script.ScriptEngineManager#ScriptEngineManager()
|
||||
*/
|
||||
protected synchronized ScriptEngineManager getScriptEngineManager()
|
||||
{
|
||||
if (scriptEngineManager == null)
|
||||
{
|
||||
this.scriptEngineManager = new ScriptEngineManager(getClassLoader());
|
||||
}
|
||||
return scriptEngineManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ClassLoader to use for the ScriptEngineManager. Adds all jar files in the "lib" subdirectory of
|
||||
* the current directory to the class path. Override this method to provide your own ClassLoader.
|
||||
*
|
||||
* @return the ClassLoader to use for the ScriptEngineManager.
|
||||
* @see #getScriptEngineManager()
|
||||
*/
|
||||
protected ClassLoader getClassLoader()
|
||||
{
|
||||
final ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
final List<URL> jarFileUrls = new ArrayList<URL>();
|
||||
|
||||
if (libPath == null || libPath.length == 0)
|
||||
{
|
||||
return parentClassLoader;
|
||||
}
|
||||
|
||||
for (String libPathEntry : libPath)
|
||||
{
|
||||
final File libDir = new File(libPathEntry);
|
||||
if (!libDir.isDirectory())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final File[] jarFiles = libDir.listFiles(new FilenameFilter()
|
||||
{
|
||||
public boolean accept(File dir, String name)
|
||||
{
|
||||
return name.endsWith(".jar");
|
||||
}
|
||||
});
|
||||
|
||||
for (File jarFile : jarFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
jarFileUrls.add(jarFile.toURI().toURL());
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
// should not happen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jarFileUrls.size() == 0)
|
||||
{
|
||||
return parentClassLoader;
|
||||
}
|
||||
|
||||
return new URLClassLoader(jarFileUrls.toArray(new URL[jarFileUrls.size()]), parentClassLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for the file with the given name on the path.
|
||||
*
|
||||
* @param scriptName the name of the file to search for.
|
||||
* @param path an array of directories to search for the file in order of preference.
|
||||
* @return the canonical file if found on the path or <code>null</code> if not found.
|
||||
*/
|
||||
protected File searchFile(String scriptName, String[] path)
|
||||
{
|
||||
if (scriptName == null || path == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (String pathElement : path)
|
||||
{
|
||||
final File pathElementDir = new File(pathElement);
|
||||
// skip if pathElement is not a directory
|
||||
if (!pathElementDir.isDirectory())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final File file = new File(pathElementDir, scriptName.replaceAll("/", Matcher.quoteReplacement(File.separator)));
|
||||
if (!file.exists())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// prevent attacks with scripts using ".." in their name.
|
||||
if (!isInside(file, pathElementDir))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.warn("Unable to check whether '" + file.getPath() + "' is below '" + pathElementDir.getPath() + "'");
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return file.getCanonicalFile();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("Unable to get canonical file for '" + file.getPath() + "'", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a file is contained within a given directory (or a sub directory) or not.
|
||||
*
|
||||
* @param file the file to check.
|
||||
* @param dir the directory to check.
|
||||
* @return <code>true</code> if file is below directory, <code>false</code> otherwise.
|
||||
* @throws IOException if the canonical path of file or dir cannot be determined.
|
||||
*/
|
||||
protected final boolean isInside(File file, File dir) throws IOException
|
||||
{
|
||||
return file.getCanonicalPath().startsWith(dir.getCanonicalPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extension (the part after the last ".") of the given script.
|
||||
*
|
||||
* @param scriptName the name of the script to return the extension of.
|
||||
* @return the extension of the script or <code>null</code> if there is no extension.
|
||||
*/
|
||||
protected static String getExtension(String scriptName)
|
||||
{
|
||||
if (scriptName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int filePosition = scriptName.lastIndexOf("/");
|
||||
String fileName;
|
||||
|
||||
if (scriptName.lastIndexOf("\\") > filePosition)
|
||||
{
|
||||
filePosition = scriptName.lastIndexOf("\\");
|
||||
}
|
||||
|
||||
if (filePosition >= 0)
|
||||
{
|
||||
fileName = scriptName.substring(filePosition + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fileName = scriptName;
|
||||
}
|
||||
|
||||
final int extensionPosition = fileName.lastIndexOf(".");
|
||||
if (extensionPosition >= 0)
|
||||
{
|
||||
return fileName.substring(extensionPosition + 1);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static Reader getReader(File file) throws FileNotFoundException
|
||||
{
|
||||
final InputStream is = new FileInputStream(file);
|
||||
return new InputStreamReader(is);
|
||||
}
|
||||
|
||||
protected class ScriptEngineAgiScript implements NamedAgiScript
|
||||
{
|
||||
final File file;
|
||||
final ScriptEngine scriptEngine;
|
||||
|
||||
/**
|
||||
* Creates a new ScriptEngineAgiScript.
|
||||
*
|
||||
* @param file the file that contains the script to execute.
|
||||
* @param scriptEngine the ScriptEngine to use for executing the script.
|
||||
*/
|
||||
public ScriptEngineAgiScript(File file, ScriptEngine scriptEngine)
|
||||
{
|
||||
this.file = file;
|
||||
this.scriptEngine = scriptEngine;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return file == null ? null : file.getName();
|
||||
}
|
||||
|
||||
public void service(AgiRequest request, AgiChannel channel) throws AgiException
|
||||
{
|
||||
final Bindings bindings = scriptEngine.createBindings();
|
||||
|
||||
bindings.put(ScriptEngine.FILENAME, file.getPath());
|
||||
bindings.put(REQUEST, request);
|
||||
bindings.put(CHANNEL, channel);
|
||||
|
||||
// support for custom bindings
|
||||
populateBindings(file, request, channel, bindings);
|
||||
|
||||
try
|
||||
{
|
||||
scriptEngine.eval(getReader(file), bindings);
|
||||
}
|
||||
catch (ScriptException e)
|
||||
{
|
||||
throw new AgiException("Execution of script '" + file.getPath() + "' with ScriptEngine failed", e);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new AgiException("Script '" + file.getPath() + "' not found", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method if you want to add additional bindings before the script is run. By default the
|
||||
* AGI request, AGI channel and the filename are available to scripts under the bindings "request", "channel"
|
||||
* and "javax.script.filename".
|
||||
*
|
||||
* @param file the script file.
|
||||
* @param request the AGI request.
|
||||
* @param channel the AGI channel.
|
||||
* @param bindings the bindings to populate.
|
||||
*/
|
||||
protected void populateBindings(File file, AgiRequest request, AgiChannel channel, Bindings bindings)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A MappingStrategy that is configured via a fixed set of properties.<p>
|
||||
* This mapping strategy is most useful when used with the Spring framework.<p>
|
||||
* Example (using Spring):
|
||||
*
|
||||
* <pre>
|
||||
* <beans>
|
||||
* <bean id="mapping"
|
||||
* class="org.asteriskjava.fastagi.SimpleMappingStrategy">
|
||||
* <property name="mappings">
|
||||
* <map>
|
||||
* <entry>
|
||||
* <key><value>hello.agi</value></key>
|
||||
* <ref local="hello"/>
|
||||
* </entry>
|
||||
* <entry>
|
||||
* <key><value>leastcostdial.agi</value></key>
|
||||
* <ref local="leastCostDial"/>
|
||||
* </entry>
|
||||
* </map>
|
||||
* </property>
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="hello"
|
||||
* class="com.example.fastagi.HelloAgiScript"/>
|
||||
*
|
||||
* <bean id="leastCostDial"
|
||||
* class="com.example.fastagi.LeastCostDialAgiScript">
|
||||
* <property name="rates"><value>rates.txt</value></property>
|
||||
* </bean>
|
||||
* <beans>
|
||||
* </pre>
|
||||
*
|
||||
* LeastCostDialAgiScript and HelloAgiScript must both implement the AgiScript.<p>
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: SimpleMappingStrategy.java 938 2007-12-31 03:23:38Z srt $
|
||||
* @since 0.2
|
||||
*/
|
||||
public class SimpleMappingStrategy implements MappingStrategy
|
||||
{
|
||||
private Map<String, AgiScript> mappings;
|
||||
|
||||
/**
|
||||
* Set the "path to AgiScript" mapping.<p>
|
||||
* Use the path (for example <code>hello.agi</code>) as key and your
|
||||
* AgiScript (for example <code>new HelloAgiScript()</code>) as value of
|
||||
* this map.
|
||||
*
|
||||
* @param mappings the path to AgiScript mapping.
|
||||
*/
|
||||
public void setMappings(Map<String, AgiScript> mappings)
|
||||
{
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
public AgiScript determineScript(AgiRequest request)
|
||||
{
|
||||
if (mappings == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return mappings.get(request.getScript());
|
||||
}
|
||||
}
|
@ -0,0 +1,238 @@
|
||||
package org.asteriskjava.fastagi;
|
||||
|
||||
import org.asteriskjava.fastagi.reply.AgiReply;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Contains the results of a speech recognition command.
|
||||
*
|
||||
* @see org.asteriskjava.fastagi.AgiChannel#speechRecognize(String, int)
|
||||
* @see org.asteriskjava.fastagi.AgiChannel#speechRecognize(String, int, int)
|
||||
* @see org.asteriskjava.fastagi.command.SpeechRecognizeCommand
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class SpeechRecognitionResult implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 0L;
|
||||
private final AgiReply agiReply;
|
||||
|
||||
public SpeechRecognitionResult(AgiReply agiReply)
|
||||
{
|
||||
this.agiReply = agiReply;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a DTMF digit was recieved.
|
||||
*
|
||||
* @return <code>true</code> if a DTMF digit was received, <code>false</code> otherwise.
|
||||
* @see #getDigit()
|
||||
*/
|
||||
public boolean isDtmf()
|
||||
{
|
||||
return "digit".equals(agiReply.getExtra());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether speech was recognized.
|
||||
*
|
||||
* @return <code>true</code> if speech was recognized, <code>false</code> otherwise.
|
||||
* @see #getText()
|
||||
* @see #getScore()
|
||||
* @see #getGrammar()
|
||||
*/
|
||||
public boolean isSpeech()
|
||||
{
|
||||
return "speech".equals(agiReply.getExtra());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a timeout was encountered and neither a DTMF digit was received nor speech was recognized.
|
||||
*
|
||||
* @return <code>true</code> a timeout was encountered, <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isTimeout()
|
||||
{
|
||||
return "timeout".equals(agiReply.getExtra());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DTMF digit that was received.
|
||||
*
|
||||
* @return the DTMF digit that was received or 0x0 if none was received.
|
||||
*/
|
||||
public char getDigit()
|
||||
{
|
||||
final String digit = agiReply.getAttribute("digit");
|
||||
if (digit == null || digit.length() == 0)
|
||||
{
|
||||
return 0x0;
|
||||
}
|
||||
return digit.charAt(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position where the prompt stopped playing because a DTMF digit was received or speech was
|
||||
* recognized (barge in).
|
||||
*
|
||||
* @return the position where the prompt stopped playing, 0 if it was played completely.
|
||||
*/
|
||||
public int getEndpos()
|
||||
{
|
||||
return Integer.valueOf(agiReply.getAttribute("endpos"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the confidence score for the first recognition result. This is an integer between 0 (lowest confidence)
|
||||
* and 1000 (highest confidence).
|
||||
*
|
||||
* @return the confidence score for the first recognition result or 0 if no speech was recognized.
|
||||
*/
|
||||
public int getScore()
|
||||
{
|
||||
final String score0 = agiReply.getAttribute("score0");
|
||||
return score0 == null ? 0 : Integer.valueOf(score0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text for the first recognition result. This is the text that was recognized by the speech engine.
|
||||
*
|
||||
* @return the text for the first recognition result or <code>null</code> if no speech was recognized.
|
||||
*/
|
||||
public String getText()
|
||||
{
|
||||
return agiReply.getAttribute("text0");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the grammar for the first recognition result. This is the grammar that was used by the speech engine.
|
||||
*
|
||||
* @return the grammar for the first recognition result or <code>null</code> if no speech was recognized.
|
||||
*/
|
||||
public String getGrammar()
|
||||
{
|
||||
return agiReply.getAttribute("grammar0");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many results have been recoginized. Usually there is only one result but if multiple rules in
|
||||
* the grammar match multiple results may be returned.
|
||||
*
|
||||
* @return the number of results recognized.
|
||||
*/
|
||||
public int getNumberOfResults()
|
||||
{
|
||||
final String numberOfResults = agiReply.getAttribute("results");
|
||||
return numberOfResults == null ? 0 : Integer.valueOf(numberOfResults);
|
||||
}
|
||||
|
||||
public List<SpeechResult> getAllResults()
|
||||
{
|
||||
final int numberOfResults = getNumberOfResults();
|
||||
final List<SpeechResult> results = new ArrayList<SpeechResult>(numberOfResults);
|
||||
|
||||
for (int i = 0; i < numberOfResults; i++)
|
||||
{
|
||||
SpeechResult result = new SpeechResult(
|
||||
Integer.valueOf(agiReply.getAttribute("score" + i)),
|
||||
agiReply.getAttribute("text" + i),
|
||||
agiReply.getAttribute("grammar" + i)
|
||||
);
|
||||
results.add(result);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder("SpeechRecognitionResult[");
|
||||
if (isDtmf())
|
||||
{
|
||||
sb.append("dtmf=true,");
|
||||
sb.append("digit=").append(getDigit()).append(",");
|
||||
}
|
||||
if (isSpeech())
|
||||
{
|
||||
sb.append("speech=true,");
|
||||
sb.append("score=").append(getScore()).append(",");
|
||||
sb.append("text='").append(getText()).append("',");
|
||||
sb.append("grammar='").append(getGrammar()).append("',");
|
||||
}
|
||||
if (isTimeout())
|
||||
{
|
||||
sb.append("timeout=true,");
|
||||
}
|
||||
|
||||
if (getNumberOfResults() > 1)
|
||||
{
|
||||
sb.append("numberOfResults=").append(getNumberOfResults()).append(",");
|
||||
sb.append("allResults=").append(getAllResults()).append(",");
|
||||
}
|
||||
|
||||
sb.append("endpos=").append(getEndpos()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Container class for recognized speech.
|
||||
*
|
||||
* @see SpeechRecognitionResult#getAllResults()
|
||||
*/
|
||||
public static class SpeechResult implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 0L;
|
||||
private final int score;
|
||||
private final String text;
|
||||
private final String grammar;
|
||||
|
||||
private SpeechResult(int score, String text, String grammar)
|
||||
{
|
||||
this.score = score;
|
||||
this.text = text;
|
||||
this.grammar = grammar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the confidence score. This is an integer between 0 (lowest confidence)
|
||||
* and 1000 (highest confidence).
|
||||
*
|
||||
* @return the confidence score.
|
||||
*/
|
||||
public int getScore()
|
||||
{
|
||||
return score;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text. This is the text that was recognized by the speech engine.
|
||||
*
|
||||
* @return the text
|
||||
*/
|
||||
public String getText()
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the grammar. This is the grammar that was used by the speech engine.
|
||||
*
|
||||
* @return the grammar
|
||||
*/
|
||||
public String getGrammar()
|
||||
{
|
||||
return grammar;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder("[");
|
||||
sb.append("score=").append(score).append(",");
|
||||
sb.append("text='").append(text).append("',");
|
||||
sb.append("grammar='").append(grammar).append("']");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package org.asteriskjava.fastagi;
|
||||
|
||||
/**
|
||||
* Mapping strategy that maps all requests to the same script instance.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class StaticMappingStrategy implements MappingStrategy
|
||||
{
|
||||
private AgiScript agiScript;
|
||||
|
||||
public StaticMappingStrategy()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new StaticMappingStrategy that maps all requests to the given script.
|
||||
*
|
||||
* @param agiScript the script to map to.
|
||||
*/
|
||||
public StaticMappingStrategy(AgiScript agiScript)
|
||||
{
|
||||
this.agiScript = agiScript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the AgiScript to map to.
|
||||
*
|
||||
* @param agiScript the AgiScript to map to.
|
||||
*/
|
||||
public void setAgiScript(AgiScript agiScript)
|
||||
{
|
||||
this.agiScript = agiScript;
|
||||
}
|
||||
|
||||
public AgiScript determineScript(AgiRequest request)
|
||||
{
|
||||
return agiScript;
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi.command;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Abstract base class that provides some convenience methods for
|
||||
* implementing AgiCommand classes.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AbstractAgiCommand.java 1013 2008-03-31 06:51:03Z srt $
|
||||
*/
|
||||
public abstract class AbstractAgiCommand implements Serializable, AgiCommand
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 3257849874518456633L;
|
||||
|
||||
public abstract String buildCommand();
|
||||
|
||||
/**
|
||||
* Escapes and quotes a given String according to the rules set by
|
||||
* Asterisk's AGI.
|
||||
*
|
||||
* @param s the String to escape and quote
|
||||
* @return the transformed String
|
||||
*/
|
||||
protected String escapeAndQuote(String s)
|
||||
{
|
||||
String tmp;
|
||||
|
||||
if (s == null)
|
||||
{
|
||||
return "\"\"";
|
||||
}
|
||||
|
||||
tmp = s;
|
||||
tmp = tmp.replaceAll("\\\"", "\\\\\""); // escape quotes
|
||||
tmp = tmp.replaceAll("\\\n", ""); // filter newline
|
||||
return "\"" + tmp + "\""; // add quotes
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer sb;
|
||||
|
||||
sb = new StringBuffer(getClass().getName()).append("[");
|
||||
sb.append("command='").append(buildCommand()).append("', ");
|
||||
sb.append("systemHashcode=").append(System.identityHashCode(this)).append("]");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi.command;
|
||||
|
||||
/**
|
||||
* AgiCommand that can be sent to Asterisk via the Asterisk Gateway Interface.<p>
|
||||
* This interface contains only one method that transforms the command to a
|
||||
* String representation understood by Asterisk.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AgiCommand.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public interface AgiCommand
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns a string suitable to be sent to asterisk.<p>
|
||||
*
|
||||
* @return a string suitable to be sent to asterisk.
|
||||
*/
|
||||
String buildCommand();
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi.command;
|
||||
|
||||
/**
|
||||
* Answers channel if not already in answer state.<p>
|
||||
* Returns -1 on channel failure, or 0 if successful.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AnswerCommand.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class AnswerCommand extends AbstractAgiCommand
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 3762248656229053753L;
|
||||
|
||||
/**
|
||||
* Creates a new AnswerCommand.
|
||||
*/
|
||||
public AnswerCommand()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCommand()
|
||||
{
|
||||
return "ANSWER";
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi.command;
|
||||
|
||||
/**
|
||||
* Breaks the Async AGI loop.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: AsyncAgiBreakCommand.java 1015 2008-04-04 21:56:36Z srt $
|
||||
*/
|
||||
public class AsyncAgiBreakCommand extends AbstractAgiCommand
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new AsyncAgiBreakCommand.
|
||||
*/
|
||||
public AsyncAgiBreakCommand()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCommand()
|
||||
{
|
||||
return "ASYNCAGI BREAK";
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi.command;
|
||||
|
||||
/**
|
||||
* Returns the status of the specified channel. If no channel name is given the
|
||||
* returns the status of the current channel.<p>
|
||||
* Return values:
|
||||
* <ul>
|
||||
* <li>0 Channel is down and available
|
||||
* <li>1 Channel is down, but reserved
|
||||
* <li>2 Channel is off hook
|
||||
* <li>3 Digits (or equivalent) have been dialed
|
||||
* <li>4 Line is ringing
|
||||
* <li>5 Remote end is ringing
|
||||
* <li>6 Line is up
|
||||
* <li>7 Line is busy
|
||||
* </ul>
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: ChannelStatusCommand.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class ChannelStatusCommand extends AbstractAgiCommand
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 3904959746380281145L;
|
||||
|
||||
/**
|
||||
* The name of the channel to query or <code>null</code> for the current
|
||||
* channel.
|
||||
*/
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* Creates a new ChannelStatusCommand that queries the current channel.
|
||||
*/
|
||||
public ChannelStatusCommand()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ChannelStatusCommand that queries the given channel.
|
||||
*
|
||||
* @param channel the name of the channel to query.
|
||||
*/
|
||||
public ChannelStatusCommand(String channel)
|
||||
{
|
||||
super();
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the channel to query.
|
||||
*
|
||||
* @return the name of the channel to query or <code>null</code> for the
|
||||
* current channel.
|
||||
*/
|
||||
public String getChannel()
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the channel to query.
|
||||
*
|
||||
* @param channel the name of the channel to query or <code>null</code>
|
||||
* for the current channel.
|
||||
*/
|
||||
public void setChannel(String channel)
|
||||
{
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCommand()
|
||||
{
|
||||
return "CHANNEL STATUS"
|
||||
+ (channel == null ? "" : " " + escapeAndQuote(channel));
|
||||
}
|
||||
}
|
@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi.command;
|
||||
|
||||
/**
|
||||
* Plays the given file, allowing playback to be interrupted by the given
|
||||
* digits, if any, and allows the listner to control the stream.<p>
|
||||
* If offset is provided then the audio will seek to sample offset before play
|
||||
* starts.<p>
|
||||
* Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
* numerical value of the digit if one was pressed, or -1 on error or if the
|
||||
* channel was disconnected. <p>
|
||||
* Remember, the file extension must not be included in the filename.<p>
|
||||
* Available since Asterisk 1.2
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: ControlStreamFileCommand.java 938 2007-12-31 03:23:38Z srt $
|
||||
* @since 0.2
|
||||
*/
|
||||
public class ControlStreamFileCommand extends AbstractAgiCommand
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 3978141041352128820L;
|
||||
|
||||
/**
|
||||
* The name of the file to stream.
|
||||
*/
|
||||
private String file;
|
||||
|
||||
/**
|
||||
* When one of these digits is pressed while streaming the command returns.
|
||||
*/
|
||||
private String escapeDigits;
|
||||
|
||||
/**
|
||||
* The offset samples to skip before streaming.
|
||||
*/
|
||||
private int offset;
|
||||
|
||||
private String forwardDigit;
|
||||
|
||||
private String rewindDigit;
|
||||
|
||||
private String pauseDigit;
|
||||
|
||||
/**
|
||||
* Creates a new ControlStreamFileCommand, streaming from the beginning. It
|
||||
* uses the default digit "#" for forward and "*" for rewind and does not
|
||||
* support pausing.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
*/
|
||||
public ControlStreamFileCommand(String file)
|
||||
{
|
||||
super();
|
||||
this.file = file;
|
||||
this.offset = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ControlStreamFileCommand, streaming from the beginning. It
|
||||
* uses the default digit "#" for forward and "*" for rewind and does not
|
||||
* support pausing.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
* @param escapeDigits contains the digits that allow the user to interrupt
|
||||
* this command.
|
||||
*/
|
||||
public ControlStreamFileCommand(String file, String escapeDigits)
|
||||
{
|
||||
super();
|
||||
this.file = file;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.offset = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ControlStreamFileCommand, streaming from the given offset.
|
||||
* It uses the default digit "#" for forward and "*" for rewind and does not
|
||||
* support pausing.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
* @param escapeDigits contains the digits that allow the user to interrupt
|
||||
* this command. May be <code>null</code> if you don't want the
|
||||
* user to interrupt.
|
||||
* @param offset the offset samples to skip before streaming.
|
||||
*/
|
||||
public ControlStreamFileCommand(String file, String escapeDigits, int offset)
|
||||
{
|
||||
super();
|
||||
this.file = file;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ControlStreamFileCommand, streaming from the given offset.
|
||||
* It allows the user to pause streaming by pressing the pauseDigit.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
* @param escapeDigits contains the digits that allow the user to interrupt
|
||||
* this command. May be <code>null</code> if you don't want the
|
||||
* user to interrupt.
|
||||
* @param offset the offset samples to skip before streaming.
|
||||
* @param forwardDigit the digit for fast forward.
|
||||
* @param rewindDigit the digit for rewind.
|
||||
* @param pauseDigit the digit for pause and unpause.
|
||||
*/
|
||||
public ControlStreamFileCommand(String file, String escapeDigits,
|
||||
int offset, String forwardDigit, String rewindDigit,
|
||||
String pauseDigit)
|
||||
{
|
||||
super();
|
||||
this.file = file;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.offset = offset;
|
||||
this.forwardDigit = forwardDigit;
|
||||
this.rewindDigit = rewindDigit;
|
||||
this.pauseDigit = pauseDigit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the file to stream.
|
||||
*
|
||||
* @return the name of the file to stream.
|
||||
*/
|
||||
public String getFile()
|
||||
{
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the file to stream.
|
||||
*
|
||||
* @param file the name of the file to stream, must not include extension.
|
||||
*/
|
||||
public void setFile(String file)
|
||||
{
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the digits that allow the user to interrupt this command.
|
||||
*
|
||||
* @return the digits that allow the user to interrupt this command.
|
||||
*/
|
||||
public String getEscapeDigits()
|
||||
{
|
||||
return escapeDigits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the digits that allow the user to interrupt this command.
|
||||
*
|
||||
* @param escapeDigits the digits that allow the user to interrupt this
|
||||
* command or <code>null</code> for none.
|
||||
*/
|
||||
public void setEscapeDigits(String escapeDigits)
|
||||
{
|
||||
this.escapeDigits = escapeDigits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offset samples to skip before streaming.
|
||||
*
|
||||
* @return the offset samples to skip before streaming.
|
||||
*/
|
||||
public int getOffset()
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the offset samples to skip before streaming.
|
||||
*
|
||||
* @param offset the offset samples to skip before streaming.
|
||||
*/
|
||||
public void setOffset(int offset)
|
||||
{
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the digit for fast forward.
|
||||
*
|
||||
* @return the digit for fast forward.
|
||||
*/
|
||||
public String getForwardDigit()
|
||||
{
|
||||
return forwardDigit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the digit for rewind.
|
||||
*
|
||||
* @return the digit for rewind.
|
||||
*/
|
||||
public String getRewindDigit()
|
||||
{
|
||||
return rewindDigit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retruns the digit for pause and unpause.
|
||||
*
|
||||
* @return the digit for pause and unpause.
|
||||
*/
|
||||
public String getPauseDigit()
|
||||
{
|
||||
return pauseDigit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the control digits for fast forward and rewind.
|
||||
*
|
||||
* @param forwardDigit the digit for fast forward.
|
||||
* @param rewindDigit the digit for rewind.
|
||||
*/
|
||||
public void setControlDigits(String forwardDigit, String rewindDigit)
|
||||
{
|
||||
this.forwardDigit = forwardDigit;
|
||||
this.rewindDigit = rewindDigit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the control digits for fast forward, rewind and pause.
|
||||
*
|
||||
* @param forwardDigit the digit for fast forward.
|
||||
* @param rewindDigit the digit for rewind.
|
||||
* @param pauseDigit the digit for pause and unpause.
|
||||
*/
|
||||
public void setControlDigits(String forwardDigit, String rewindDigit,
|
||||
String pauseDigit)
|
||||
{
|
||||
this.forwardDigit = forwardDigit;
|
||||
this.rewindDigit = rewindDigit;
|
||||
this.pauseDigit = pauseDigit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCommand()
|
||||
{
|
||||
StringBuffer sb;
|
||||
|
||||
sb = new StringBuffer("CONTROL STREAM FILE ");
|
||||
sb.append(escapeAndQuote(file));
|
||||
sb.append(" ");
|
||||
sb.append(escapeAndQuote(escapeDigits));
|
||||
if (offset >= 0)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(offset);
|
||||
}
|
||||
else if (forwardDigit != null || rewindDigit != null
|
||||
|| pauseDigit != null)
|
||||
{
|
||||
sb.append(" 0");
|
||||
}
|
||||
|
||||
if (forwardDigit != null || rewindDigit != null || pauseDigit != null)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(forwardDigit);
|
||||
}
|
||||
if (rewindDigit != null || pauseDigit != null)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(rewindDigit);
|
||||
}
|
||||
if (pauseDigit != null)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(pauseDigit);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi.command;
|
||||
|
||||
/**
|
||||
* Deletes a family or specific keytree within a family in the Asterisk
|
||||
* database.<p>
|
||||
* Returns 1 if successful, 0 otherwise.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: DatabaseDelCommand.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class DatabaseDelCommand extends AbstractAgiCommand
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 3256719598056387384L;
|
||||
|
||||
/**
|
||||
* The family (or family of the keytree) to delete.
|
||||
*/
|
||||
private String family;
|
||||
|
||||
/**
|
||||
* The keyTree to delete.
|
||||
*/
|
||||
private String keyTree;
|
||||
|
||||
/**
|
||||
* Creates a new DatabaseDelCommand to delete a family.
|
||||
*
|
||||
* @param family the family to delete.
|
||||
*/
|
||||
public DatabaseDelCommand(String family)
|
||||
{
|
||||
super();
|
||||
this.family = family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DatabaseDelCommand to delete a keytree.
|
||||
*
|
||||
* @param family the family of the keytree to delete.
|
||||
* @param keyTree the keytree to delete.
|
||||
*/
|
||||
public DatabaseDelCommand(String family, String keyTree)
|
||||
{
|
||||
super();
|
||||
this.family = family;
|
||||
this.keyTree = keyTree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the family (or family of the keytree) to delete.
|
||||
*
|
||||
* @return the family (or family of the keytree) to delete.
|
||||
*/
|
||||
public String getFamily()
|
||||
{
|
||||
return family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the family (or family of the keytree) to delete.
|
||||
*
|
||||
* @param family the family (or family of the keytree) to delete.
|
||||
*/
|
||||
public void setFamily(String family)
|
||||
{
|
||||
this.family = family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the the keytree to delete.
|
||||
*
|
||||
* @return the keytree to delete.
|
||||
*/
|
||||
public String getKeyTree()
|
||||
{
|
||||
return keyTree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the keytree to delete.
|
||||
*
|
||||
* @param keyTree the keytree to delete.
|
||||
*/
|
||||
public void setKeyTree(String keyTree)
|
||||
{
|
||||
this.keyTree = keyTree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCommand()
|
||||
{
|
||||
return "DATABASE DELTREE " + escapeAndQuote(family)
|
||||
+ (keyTree == null ? "" : " " + escapeAndQuote(keyTree));
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi.command;
|
||||
|
||||
/**
|
||||
* Deletes a family or specific keytree within a family in the Asterisk database.<p>
|
||||
* Returns 1 if successful, 0 otherwise.
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: DatabaseDelTreeCommand.java 1286 2009-04-04 09:40:40Z srt $
|
||||
*/
|
||||
public class DatabaseDelTreeCommand extends AbstractAgiCommand
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 3256719598056387384L;
|
||||
|
||||
/**
|
||||
* The family of the key to delete.
|
||||
*/
|
||||
private String family;
|
||||
|
||||
/**
|
||||
* The keytree to delete.
|
||||
*/
|
||||
private String keyTree;
|
||||
|
||||
/**
|
||||
* Creates a new DatabaseDelCommand to delete a whole family.
|
||||
*
|
||||
* @param family the family to delete.
|
||||
*/
|
||||
public DatabaseDelTreeCommand(String family)
|
||||
{
|
||||
super();
|
||||
this.family = family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DatabaseDelCommand to delete a keytree within a given family.
|
||||
*
|
||||
* @param family the family of the keytree to delete.
|
||||
* @param keyTree the keytree to delete.
|
||||
*/
|
||||
public DatabaseDelTreeCommand(String family, String keyTree)
|
||||
{
|
||||
super();
|
||||
this.family = family;
|
||||
this.keyTree = keyTree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the family of the key to delete.
|
||||
*
|
||||
* @return the family of the key to delete.
|
||||
*/
|
||||
public String getFamily()
|
||||
{
|
||||
return family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the family of the key to delete.
|
||||
*
|
||||
* @param family the family of the key to delete.
|
||||
*/
|
||||
public void setFamily(String family)
|
||||
{
|
||||
this.family = family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the the keytree to delete.
|
||||
*
|
||||
* @return the keytree to delete.
|
||||
*/
|
||||
public String getKeyTree()
|
||||
{
|
||||
return keyTree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the keytree to delete.
|
||||
*
|
||||
* @param keyTree the keytree to delete, <code>null</code> to delete the whole family.
|
||||
*/
|
||||
public void setKeyTree(String keyTree)
|
||||
{
|
||||
this.keyTree = keyTree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCommand()
|
||||
{
|
||||
if (keyTree == null)
|
||||
{
|
||||
return "DATABASE DELTREE " + escapeAndQuote(family) + " " + escapeAndQuote(keyTree);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "DATABASE DELTREE " + escapeAndQuote(family);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Stefan Reuter
|
||||
*
|
||||
* 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.asteriskjava.fastagi.command;
|
||||
|
||||
/**
|
||||
* Retrieves an entry in the Asterisk database for a given family and key.<p>
|
||||
* Returns 0 if is not set. Returns 1 if the variable is set and returns the
|
||||
* value in parenthesis.<p>
|
||||
* Example return code: 200 result=1 (testvariable)
|
||||
*
|
||||
* @author srt
|
||||
* @version $Id: DatabaseGetCommand.java 938 2007-12-31 03:23:38Z srt $
|
||||
*/
|
||||
public class DatabaseGetCommand extends AbstractAgiCommand
|
||||
{
|
||||
/**
|
||||
* Serial version identifier.
|
||||
*/
|
||||
private static final long serialVersionUID = 3256719598056387384L;
|
||||
|
||||
/**
|
||||
* The family of the key to retrieve.
|
||||
*/
|
||||
private String family;
|
||||
|
||||
/**
|
||||
* The key to retrieve.
|
||||
*/
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* Creates a new DatabaseGetCommand.
|
||||
*
|
||||
* @param family the family of the key to retrieve.
|
||||
* @param key the key to retrieve.
|
||||
*/
|
||||
public DatabaseGetCommand(String family, String key)
|
||||
{
|
||||
super();
|
||||
this.family = family;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the family of the key to retrieve.
|
||||
*
|
||||
* @return the family of the key to retrieve.
|
||||
*/
|
||||
public String getFamily()
|
||||
{
|
||||
return family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the family of the key to retrieve.
|
||||
*
|
||||
* @param family the family of the key to retrieve.
|
||||
*/
|
||||
public void setFamily(String family)
|
||||
{
|
||||
this.family = family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the the key to retrieve.
|
||||
*
|
||||
* @return the key to retrieve.
|
||||
*/
|
||||
public String getKey()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key to retrieve.
|
||||
*
|
||||
* @param key the key to retrieve.
|
||||
*/
|
||||
public void setKey(String key)
|
||||
{
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCommand()
|
||||
{
|
||||
return "DATABASE GET " + escapeAndQuote(family) + " "
|
||||
+ escapeAndQuote(key);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user