From 6c4d38399f71ad514af798b350d41de9ff15fdf1 Mon Sep 17 00:00:00 2001 From: Gustavo Felisberto Date: Tue, 12 Apr 2016 10:20:32 +0100 Subject: [PATCH 001/802] % DefaultAgiServer searches for fastagi.properties. --- README.md | 2 +- examples/{fastagi-mapping.properties => fastagi.properties} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename examples/{fastagi-mapping.properties => fastagi.properties} (100%) diff --git a/README.md b/README.md index 8f4be665e..b691e4c69 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ The file 'examples/ExampleCallIn.java' will answer the call and playback the aud } } -The file 'examples/fastagi-mapping.properties' maps your Asterisk diaplan context to the class you would like to invoke above. +The file 'examples/fastagi.properties' maps your Asterisk diaplan context to the class you would like to invoke above. callin.agi = ExampleCallIn diff --git a/examples/fastagi-mapping.properties b/examples/fastagi.properties similarity index 100% rename from examples/fastagi-mapping.properties rename to examples/fastagi.properties From 360e9dd808151a298ec2e8409974d77ca3c1b29a Mon Sep 17 00:00:00 2001 From: Gustavo Felisberto Date: Tue, 19 Apr 2016 09:48:50 +0100 Subject: [PATCH 002/802] % Typo --- src/main/java/org/asteriskjava/fastagi/AgiChannel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/AgiChannel.java b/src/main/java/org/asteriskjava/fastagi/AgiChannel.java index 1c6ea5388..f9082c703 100644 --- a/src/main/java/org/asteriskjava/fastagi/AgiChannel.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiChannel.java @@ -189,7 +189,7 @@ public interface AgiChannel /** * 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 + * digits. If none of the escape 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. * @@ -203,7 +203,7 @@ public interface AgiChannel /** * 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 + * digits. If none of the escape digits is pressed while streaming the file * it waits for the specified timeout still waiting for the user to press a * digit. * From 2b1927626924015d6e7f7d93cba054ec702a3e64 Mon Sep 17 00:00:00 2001 From: Gustavo Felisberto Date: Tue, 19 Apr 2016 09:49:20 +0100 Subject: [PATCH 003/802] Changed dial to use comma's to separate parameters --- .../java/org/asteriskjava/fastagi/command/DialCommand.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java index 7570ab0b5..be334a88a 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java @@ -24,13 +24,13 @@ public DialCommand(String target, int timeout, String options) @Override public String buildCommand() { - String command = "EXEC " + escapeAndQuote("dial") + " " + escapeAndQuote(target) + " " + String command = "EXEC " + escapeAndQuote("dial") + " " + escapeAndQuote(target) + "," + escapeAndQuote("" + timeout); if (options != null && options.length() > 0) { - command += " " + escapeAndQuote(options); + command += "," + escapeAndQuote(options); } - + //This should be in a log System.out.println(command); return command; From 271490417ca116a321ed96946c76cecb720bc2b7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 26 Apr 2016 13:41:21 +1000 Subject: [PATCH 004/802] suppress warnings, make path in pom relative --- pom.xml | 2 +- src/main/java/org/asteriskjava/Cli.java | 15 +++++++++------ .../util/internal/SocketConnectionFacadeImpl.java | 1 + 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 116554750..6a7eda570 100644 --- a/pom.xml +++ b/pom.xml @@ -151,7 +151,7 @@ 2.5.3 - src/main/assembly/bin.xml + ${project.basedir}/src/main/assembly/bin.xml diff --git a/src/main/java/org/asteriskjava/Cli.java b/src/main/java/org/asteriskjava/Cli.java index 62b85f590..d75cad3f8 100644 --- a/src/main/java/org/asteriskjava/Cli.java +++ b/src/main/java/org/asteriskjava/Cli.java @@ -7,16 +7,18 @@ import org.asteriskjava.fastagi.DefaultAgiServer; /** - * 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.

+ * 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. + *

* The command line interface supports the following options: *

- *
{@code -a}, {@code -agi [port]}
+ *
{@code -a}, {@code -agi [port]} + *
*
Starts a FastAGI server
- * - *
{@code -h}, {@code -help}
+ *
{@code -h}, {@code -help} + *
*
Displays the available options
- * *
{@code -v}, {@code -version}
*
Displays the version of Asterisk-Java
*
@@ -80,6 +82,7 @@ private void showVersion() System.out.println("Asterisk-Java " + getVersion()); } + @SuppressWarnings("resource") private String getVersion() { String version = ""; diff --git a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java index a08ba44f1..dc8f82c6d 100644 --- a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java +++ b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java @@ -123,6 +123,7 @@ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeou * for the socket * @throws IOException if the connection cannot be established. */ + @SuppressWarnings("resource") public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeout, int readTimeout, Charset encoding, Pattern lineDelimiter) throws IOException { From ec9af80329cb5f3e5d52144849fafd696970e5cc Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 26 Apr 2016 13:48:48 +1000 Subject: [PATCH 005/802] change system.out to logger --- .../org/asteriskjava/fastagi/command/DialCommand.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java index be334a88a..31a409932 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java @@ -1,5 +1,8 @@ package org.asteriskjava.fastagi.command; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + public class DialCommand extends AbstractAgiCommand { /** @@ -9,6 +12,7 @@ public class DialCommand extends AbstractAgiCommand private String options; private String target; private int timeout; + private final Log logger = LogFactory.getLog(getClass()); /** * Creates a new AnswerCommand. @@ -30,8 +34,8 @@ public String buildCommand() { command += "," + escapeAndQuote(options); } - //This should be in a log - System.out.println(command); + + logger.info(command); return command; From 3fa57c7c441d7ea90a0b813e92aaf519a5eb011f Mon Sep 17 00:00:00 2001 From: "adrian.videanu" Date: Wed, 4 May 2016 12:54:34 +0300 Subject: [PATCH 006/802] WARN [Asterisk-Java ManagerConnection-0-Reader-0] (AbstractBuilder.java:83) - Unable to set property 'incall' to '0' on org.asteriskjava.manager.event.QueueMemberStatusEvent: no setter. Please report at https://github.com/asterisk-java/asterisk-java/issues]] --- .../manager/event/QueueMemberStatusEvent.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java index 12cbb6037..4619cd2b6 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java @@ -29,8 +29,9 @@ public class QueueMemberStatusEvent extends QueueMemberEvent */ private static final long serialVersionUID = -2293926744791895763L; - String ringinuse; - String iface; + private String ringinuse; + private String iface; + private Integer incall; /** * @param source @@ -65,4 +66,16 @@ public void setRinginuse(String ringinuse) { this.ringinuse = ringinuse; } + + public Integer getIncall() + { + return incall; + } + + public void setIncall(Integer incall) + { + this.incall = incall; + } + + } From 11e387250eabc944b176a558e7cd8619f4ca9658 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 10 May 2016 14:49:02 +1000 Subject: [PATCH 007/802] add javadoc about alternate methods for deprecated methods suppress warning --- .../manager/event/AbstractMeetMeEvent.java | 3 ++- .../event/AbstractParkedCallEvent.java | 19 ++++++++++++------- .../manager/event/ConfbridgeStartEvent.java | 1 + 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java index e25947347..9a5efd0b6 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java @@ -112,7 +112,8 @@ public void setMeetMe(String meetMe) /** * Returns the index of the user in the conference. *

- * This can be used for the "meetme (mute|unmute|kick)" commands. + * This can be used for the "meetme (mute|unmute|kick)" commands. use + * getUser() instead * * @return the index of the user in the conference. */ diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java index 33648021f..5d27c2748 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java @@ -57,7 +57,8 @@ protected AbstractParkedCallEvent(Object source) } /** - * Returns the name of the channel that parked the call. + * Returns the name of the channel that parked the call. use + * getParkerDialString() instead */ @Deprecated public String getFrom() @@ -101,12 +102,11 @@ public void setParkingLot(String parkingLot) * Returns the unique id of the parked channel. *

* Note: This property is not set properly by all versions of Asterisk, see - * http://bugs.digium.com/ - * view.php?id=13323 and http://bugs.digium.com/view.php?id=13358 for more information. Use - * {@link #getChannel()} instead. + * http://bugs.digium. + * com/ view.php?id=13323 and + * http://bugs.digium. + * com/view.php?id=13358 for more information. Use {@link #getChannel()} + * instead. * * @return the unique id of the parked channel. */ @@ -126,6 +126,11 @@ public void setChannel(String channel) this.setParkeeChannel(channel); } + /** + * use getParkeeChannel() instead + * + * @return + */ @Deprecated public String getChannel() { diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeStartEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeStartEvent.java index e01dc6ad3..bd001c754 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeStartEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeStartEvent.java @@ -13,6 +13,7 @@ public class ConfbridgeStartEvent extends AbstractConfbridgeEvent */ private static final long serialVersionUID = 1L; + @SuppressWarnings("unused") private String conference; public ConfbridgeStartEvent(Object source) From 82f286237e45317a95005c2c81a4334cee66b0ad Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Wed, 18 May 2016 22:14:44 -0300 Subject: [PATCH 008/802] add Asterisk > 13.5 CallManager version and missing properties adding missing features for 13 branch --- .../manager/event/CoreShowChannelEvent.java | 32 +++++++++++++++++++ .../manager/event/QueueMemberEvent.java | 14 ++++++++ .../internal/ManagerConnectionImpl.java | 2 ++ 3 files changed, 48 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/CoreShowChannelEvent.java b/src/main/java/org/asteriskjava/manager/event/CoreShowChannelEvent.java index 80f2756ce..c401b272f 100644 --- a/src/main/java/org/asteriskjava/manager/event/CoreShowChannelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/CoreShowChannelEvent.java @@ -41,6 +41,9 @@ public class CoreShowChannelEvent extends ResponseEvent private String accountcode; private String bridgedChannel; private String bridgeid; + private String linkedid; + private String language; + public CoreShowChannelEvent(Object source) { @@ -206,4 +209,33 @@ public void setUniqueid(String uniqueid) this.uniqueid = uniqueid; } + + /** + * Returns the Channel LinkedID + * + * @return linkedid + */ + public String getLinkedid() { + return linkedid; + } + + public void setLinkedid(String linkedid) { + this.linkedid = linkedid; + } + + + /** + * Returns the Channel Language + * + * @return language + */ + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java index c9fe4f9db..5bd332f5c 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java @@ -59,6 +59,8 @@ public class QueueMemberEvent extends ResponseEvent private Integer status; private Boolean paused; private String stateinterface; + private Integer incall; + /** * @param source @@ -343,4 +345,16 @@ public void setStateinterface(String stateinterface) { this.stateinterface = stateinterface; } + + /** + * @return 1 if is incall 0 if not + */ + public Integer getIncall() { + return incall; + } + + public void setIncall(Integer incall) { + this.incall = incall; + } + } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 2ad3d465d..26ab00c01 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1384,6 +1384,8 @@ private void setProtocolIdentifier(final String identifier) // 13 && !"Asterisk Call Manager/2.7.0".equals(identifier) // Asterisk // 13.2 + && !"Asterisk Call Manager/2.8.0".equals(identifier) // Asterisk > 13.5 + && !"OpenPBX Call Manager/1.0".equals(identifier) && !"CallWeaver Call Manager/1.0".equals(identifier) && !(identifier != null && identifier.startsWith("Asterisk Call Manager Proxy/"))) { From b7cadbe359cd99a274eadad72844c640aa438a44 Mon Sep 17 00:00:00 2001 From: Martin Lundvall Date: Sun, 12 Jun 2016 12:12:02 +0200 Subject: [PATCH 009/802] Support delimiter variants other than ': ' --- .../manager/internal/ManagerReaderImpl.java | 30 ++++++------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java index 42c6fda16..f2ae1b6bf 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java @@ -190,35 +190,23 @@ public void run() if (line.length() > 0) { - int delimiterIndex; - int delimiterLength; - // begin of workaround for Astersik bug 13319 // see AJ-77 // Use this workaround only when line starts from "From " // and "To " - int isFromAtStart, isToAtStart; - isFromAtStart = line.indexOf("From "); - isToAtStart = line.indexOf("To "); - if (isFromAtStart == 0 || isToAtStart == 0) - { - delimiterIndex = line.indexOf(" "); - delimiterLength = 1; - } - else - { - delimiterIndex = line.indexOf(": "); - delimiterLength = 2; - } + int isFromAtStart = line.indexOf("From "); + int isToAtStart = line.indexOf("To "); + + int delimiterIndex = isFromAtStart == 0 || isToAtStart == 0 + ? line.indexOf(" ") : line.indexOf(":"); // end of workaround for Astersik bug 13319 + int delimiterLength = 1; + if (delimiterIndex > 0 && line.length() > delimiterIndex + delimiterLength) { - String name; - String value; - - name = line.substring(0, delimiterIndex).toLowerCase(Locale.ENGLISH); - value = line.substring(delimiterIndex + delimiterLength); + String name = line.substring(0, delimiterIndex).toLowerCase(Locale.ENGLISH).trim(); + String value = line.substring(delimiterIndex + delimiterLength).trim(); addToBuffer(buffer, name, value); // TODO tracing From 23bdef9f12c1cf84d1dd531c2ee75da984acbf0f Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Tue, 5 Jul 2016 19:00:15 -0300 Subject: [PATCH 010/802] add missing parameter incall parameter in astv13 --- .../manager/event/QueueMemberPauseEvent.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java index a1175dc47..254292f15 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java @@ -13,6 +13,7 @@ public class QueueMemberPauseEvent extends QueueMemberPausedEvent Boolean ringinuse; String iface; String stateInterface; + Integer incall; public QueueMemberPauseEvent(Object source) { @@ -148,4 +149,20 @@ public void setStateInterface(String stateInterface) this.stateInterface = stateInterface; } + /** + * @return get Incall + */ + public String getIncall() + { + return incall; + } + + /** + * @param setIncall the incall to set + */ + public void setIncall(String incall) + { + this.incall = incall; + } + } From 98b3031d3dd43aa248b47b8f40dd650559465f23 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Wed, 6 Jul 2016 10:38:47 -0300 Subject: [PATCH 011/802] fix previous commit datatypes fix datatypes --- .../org/asteriskjava/manager/event/QueueMemberPauseEvent.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java index 254292f15..154b0e1a2 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java @@ -152,7 +152,7 @@ public void setStateInterface(String stateInterface) /** * @return get Incall */ - public String getIncall() + public Integer getIncall() { return incall; } @@ -160,7 +160,7 @@ public String getIncall() /** * @param setIncall the incall to set */ - public void setIncall(String incall) + public void setIncall(Integer incall) { this.incall = incall; } From a60efbde5373c5e05ec5041f9d6b979ebd68bee6 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Wed, 6 Jul 2016 12:39:40 -0300 Subject: [PATCH 012/802] new properties new missing properties --- .../manager/event/PeerEntryEvent.java | 17 +++++++++++++++++ .../manager/event/QueueMemberEvent.java | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java index cac1c7b9b..782d435f5 100644 --- a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java @@ -59,6 +59,7 @@ public class PeerEntryEvent extends ResponseEvent private String autoComedia; private String autoForcerport; private String comedia; + private String description; /** * Creates a new instance. @@ -397,4 +398,20 @@ public void setComedia(String comedia) { this.comedia = comedia; } + + /** + * @return the description + */ + public String getDescription() + { + return description; + } + + /** + * @param the description to set + */ + public void setDescription(String description) + { + this.description = description; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java index 5bd332f5c..193ab6056 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java @@ -60,6 +60,7 @@ public class QueueMemberEvent extends ResponseEvent private Boolean paused; private String stateinterface; private Integer incall; + private String pausedreason; /** @@ -357,4 +358,12 @@ public void setIncall(Integer incall) { this.incall = incall; } + public String getPausedreason() { + return pausedreason; + } + + public void setPausedreason(String pausedreason) { + this.pausedreason = pausedreason; + } + } From eccffc24a413c5c18ff6976b392242886f09f791 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Wed, 6 Jul 2016 16:59:12 -0300 Subject: [PATCH 013/802] accountcodr Property for PeerEntry this is based on https://issues.asterisk.org/jira/browse/ASTERISK-26176 --- .../manager/event/PeerEntryEvent.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java index 782d435f5..a2b749d19 100644 --- a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java @@ -60,6 +60,7 @@ public class PeerEntryEvent extends ResponseEvent private String autoForcerport; private String comedia; private String description; + private String accountcode; /** * Creates a new instance. @@ -414,4 +415,24 @@ public void setDescription(String description) { this.description = description; } + + /** + * @return the accountcode + */ + public String getAccountcode() + { + return accountcode; + } + + /** + * @param the accountcode to set + */ + public void setAccountcode(String description) + { + this.accountcode = accountcode; + } + + + + } From 57ca27e144c1384dc881f40669906ced05c3e3a2 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Thu, 7 Jul 2016 18:35:06 -0300 Subject: [PATCH 014/802] fix property place --- .../asteriskjava/manager/event/QueueMemberEvent.java | 9 +-------- .../manager/event/QueueMemberPauseEvent.java | 10 ++++++++++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java index 193ab6056..dba517d29 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java @@ -60,7 +60,7 @@ public class QueueMemberEvent extends ResponseEvent private Boolean paused; private String stateinterface; private Integer incall; - private String pausedreason; + /** @@ -358,12 +358,5 @@ public void setIncall(Integer incall) { this.incall = incall; } - public String getPausedreason() { - return pausedreason; - } - - public void setPausedreason(String pausedreason) { - this.pausedreason = pausedreason; - } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java index 154b0e1a2..56e2f6d43 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java @@ -14,6 +14,7 @@ public class QueueMemberPauseEvent extends QueueMemberPausedEvent String iface; String stateInterface; Integer incall; + String pausedreason; public QueueMemberPauseEvent(Object source) { @@ -165,4 +166,13 @@ public void setIncall(Integer incall) this.incall = incall; } + public String getPausedreason() { + return pausedreason; + } + + public void setPausedreason(String pausedreason) { + this.pausedreason = pausedreason; + } + + } From 07ddc8c0bf9cfa6f876b3178e46763e6618f71b1 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Thu, 7 Jul 2016 18:41:39 -0300 Subject: [PATCH 015/802] both places has pausereason --- .../asteriskjava/manager/event/QueueMemberEvent.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java index dba517d29..cbb91f348 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java @@ -60,6 +60,7 @@ public class QueueMemberEvent extends ResponseEvent private Boolean paused; private String stateinterface; private Integer incall; + private String pausedreason; @@ -359,4 +360,13 @@ public void setIncall(Integer incall) { } + public String getPausedreason() { + return pausedreason; + } + + public void setPausedreason(String pausedreason) { + this.pausedreason = pausedreason; + } + + } From d103fe8031de8c8bcdc2f877c065bf0d2d09967d Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Fri, 8 Jul 2016 11:57:47 -0300 Subject: [PATCH 016/802] fix coding style --- .../org/asteriskjava/manager/event/QueueMemberPauseEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java index 56e2f6d43..e704e06f0 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java @@ -166,7 +166,7 @@ public void setIncall(Integer incall) this.incall = incall; } - public String getPausedreason() { + public String getPausedreason() { return pausedreason; } From 90c1e07b7be8d2232a7e98dffe2e71fbe3952657 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Mon, 11 Jul 2016 10:08:10 -0300 Subject: [PATCH 017/802] fix coding style part2 --- .../asteriskjava/manager/event/QueueMemberEvent.java | 12 ++++++++---- .../manager/event/QueueMemberPauseEvent.java | 6 ++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java index cbb91f348..a5ade6482 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java @@ -351,20 +351,24 @@ public void setStateinterface(String stateinterface) /** * @return 1 if is incall 0 if not */ - public Integer getIncall() { + public Integer getIncall() + { return incall; } - public void setIncall(Integer incall) { + public void setIncall(Integer incall) + { this.incall = incall; } - public String getPausedreason() { + public String getPausedreason() + { return pausedreason; } - public void setPausedreason(String pausedreason) { + public void setPausedreason(String pausedreason) + { this.pausedreason = pausedreason; } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java index e704e06f0..3b44bd2e1 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java @@ -166,11 +166,13 @@ public void setIncall(Integer incall) this.incall = incall; } - public String getPausedreason() { + public String getPausedreason() + { return pausedreason; } - public void setPausedreason(String pausedreason) { + public void setPausedreason(String pausedreason) + { this.pausedreason = pausedreason; } From d6fafc15f78a58289458fae46e54af6b1780e508 Mon Sep 17 00:00:00 2001 From: terwarf Date: Tue, 12 Jul 2016 11:23:36 +0200 Subject: [PATCH 018/802] Add missing methods for responsefield "statustext" --- .../manager/response/ExtensionStateResponse.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java b/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java index 5e86b97fd..1d55c6d77 100644 --- a/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java @@ -30,7 +30,8 @@ public class ExtensionStateResponse extends ManagerResponse private String context; private String hint; private Integer status; - + private String statustext; + public String getExten() { return exten; @@ -71,6 +72,18 @@ public void setStatus(Integer status) this.status = status; } + public String getStatustext() + { + return statustext; + } + + public void setStatustext(String statustext) + { + this.statustext = statustext; + } + + + @Override public String toString() { @@ -85,6 +98,7 @@ public String toString() sb.append("context='").append(getContext()).append("'; "); sb.append("hint='").append(getHint()).append("'; "); sb.append("status='").append(getStatus()).append("'; "); + sb.append("statustext='").append(getStatustext()).append("'; "); sb.append("systemHashcode=").append(System.identityHashCode(this)); return sb.toString(); From 3a0cbd6fad00acc0c105b4c595240408b3f2d9df Mon Sep 17 00:00:00 2001 From: terwarf Date: Thu, 14 Jul 2016 12:01:30 +0200 Subject: [PATCH 019/802] Fixed method and var names, updated indentation --- .../response/ExtensionStateResponse.java | 120 +++++++++--------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java b/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java index 1d55c6d77..086cf9635 100644 --- a/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java @@ -25,82 +25,82 @@ */ public class ExtensionStateResponse extends ManagerResponse { - private static final long serialVersionUID = -2044248427247227390L; - private String exten; - private String context; - private String hint; - private Integer status; - private String statustext; - - public String getExten() - { - return exten; - } + private static final long serialVersionUID = -2044248427247227390L; + private String exten; + private String context; + private String hint; + private Integer status; + private String statusText; - public void setExten(String exten) - { - this.exten = exten; - } + public String getExten() + { + return exten; + } + + public void setExten(String exten) + { + this.exten = exten; + } - public String getContext() - { - return context; - } + public String getContext() + { + return context; + } - public void setContext(String context) - { - this.context = context; - } + public void setContext(String context) + { + this.context = context; + } - public String getHint() - { - return hint; - } + public String getHint() + { + return hint; + } - public void setHint(String hint) - { - this.hint = hint; - } + public void setHint(String hint) + { + this.hint = hint; + } - public Integer getStatus() - { - return status; - } + public Integer getStatus() + { + return status; + } - public void setStatus(Integer status) - { - this.status = status; - } + public void setStatus(Integer status) + { + this.status = status; + } - public String getStatustext() + public String getStatusText() { - return statustext; + return statusText; } - public void setStatustext(String statustext) + public void setStatusText(String statusText) { - this.statustext = statustext; + this.statusText = statusText; } - @Override - public String toString() - { - StringBuilder sb; + @Override + public String toString() + { + StringBuilder sb; - sb = new StringBuilder(getClass().getName() + ": "); - sb.append("actionId='").append(getActionId()).append("'; "); - sb.append("message='").append(getMessage()).append("'; "); - sb.append("response='").append(getResponse()).append("'; "); - sb.append("uniqueId='").append(getUniqueId()).append("'; "); - sb.append("exten='").append(getExten()).append("'; "); - sb.append("context='").append(getContext()).append("'; "); - sb.append("hint='").append(getHint()).append("'; "); - sb.append("status='").append(getStatus()).append("'; "); - sb.append("statustext='").append(getStatustext()).append("'; "); - sb.append("systemHashcode=").append(System.identityHashCode(this)); + sb = new StringBuilder(getClass().getName() + ": "); + sb.append("actionId='").append(getActionId()).append("'; "); + sb.append("message='").append(getMessage()).append("'; "); + sb.append("response='").append(getResponse()).append("'; "); + sb.append("uniqueId='").append(getUniqueId()).append("'; "); + sb.append("exten='").append(getExten()).append("'; "); + sb.append("context='").append(getContext()).append("'; "); + sb.append("hint='").append(getHint()).append("'; "); + sb.append("status='").append(getStatus()).append("'; "); + sb.append("statustext='").append(getStatusText()).append("'; "); + sb.append("systemHashcode=").append(System.identityHashCode(this)); - return sb.toString(); - } + return sb.toString(); + } } From b3b3f9eca62a00bb51db7d9a4769fd2af6b56ca1 Mon Sep 17 00:00:00 2001 From: Brett Sutton Date: Thu, 14 Jul 2016 20:32:21 +1000 Subject: [PATCH 020/802] Create .editorconfig controls how github display tabs when viewing files. --- .editorconfig | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..5ff9f04f3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,2 @@ +indent_style = tab +indent_size = 4 From 4e128763a6f24b7ca763c93e4c93e45162eadd68 Mon Sep 17 00:00:00 2001 From: Brett Sutton Date: Thu, 14 Jul 2016 20:35:11 +1000 Subject: [PATCH 021/802] added file pattern match. --- .editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.editorconfig b/.editorconfig index 5ff9f04f3..f02d2801a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,2 +1,5 @@ +[*.{java,html}] +charset = utf-8 indent_style = tab indent_size = 4 +trim_trailing_whitespace = true From 9a05b113740b5a13d7779b709dbae1e8914d6352 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 14 Jul 2016 17:08:26 -0400 Subject: [PATCH 022/802] Replace ConcurrentHashMap with HashMap where appropriate BridgesActive & BridgeState are only ever accessed from the ManagerReader thread, so a ConcurrentHashMap buys us nothing here, so use HashMap instead. --- .../internal/backwardsCompatibility/bridge/BridgeState.java | 4 ++-- .../internal/backwardsCompatibility/bridge/BridgesActive.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 4555272ae..4732b8bf3 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -1,10 +1,10 @@ package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; import java.util.Date; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import org.asteriskjava.manager.event.BridgeCreateEvent; import org.asteriskjava.manager.event.BridgeDestroyEvent; @@ -27,7 +27,7 @@ public class BridgeState BridgeCreateEvent created; BridgeDestroyEvent destroyed; - private final Map members = new ConcurrentHashMap<>(); + private final Map members = new HashMap<>(); public BridgeState(BridgeCreateEvent event) { diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java index ff2e034fb..827eb7822 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java @@ -1,7 +1,7 @@ package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; +import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import org.asteriskjava.manager.event.BridgeCreateEvent; import org.asteriskjava.manager.event.BridgeDestroyEvent; @@ -29,7 +29,7 @@ public class BridgesActive // this map is shared (static) so that connections to asterisk that attach // late can // benefit from the known bridge information of older connections - final static Map activeBridges = new ConcurrentHashMap<>(); + final static Map activeBridges = new HashMap<>(); public ManagerEvent handleEvent(ManagerEvent event) { From adda4c4de9e66596d1c57f929d5150934202f4ab Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 14 Jul 2016 17:31:37 -0400 Subject: [PATCH 023/802] Make BridgeState methods more concise BridgeState.addMember and BridgeState.removeMember were a bit convoluted and did some allocations that were just going to get thrown away. This change makes the behavior more obvious and slightly more efficient. --- .../bridge/BridgeState.java | 84 +++++++++---------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 4732b8bf3..d5fa6cf45 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -1,8 +1,9 @@ package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; +import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -49,30 +50,21 @@ public ManagerEvent destroy(BridgeDestroyEvent event) */ public ManagerEvent addMember(BridgeEnterEvent event) { - final String channel = event.getChannel(); members.put(event.getChannel(), event); logger.info("Members size " + members.size() + " " + event); - List memberList = new LinkedList<>(); - memberList.addAll(members.values()); - if (memberList.size() == 2) + + if (members.size() != 2) { - BridgeEvent bridgeEvent = new BridgeEvent(this); - - bridgeEvent.setCallerId1(memberList.get(0).getCallerIdNum()); - bridgeEvent.setCallerId2(memberList.get(1).getCallerIdNum()); - bridgeEvent.setUniqueId1(memberList.get(0).getUniqueId()); - bridgeEvent.setUniqueId2(memberList.get(1).getUniqueId()); - bridgeEvent.setChannel1(memberList.get(0).getChannel()); - bridgeEvent.setChannel2(memberList.get(1).getChannel()); - bridgeEvent.setBridgeState(BridgeEvent.BRIDGE_STATE_LINK); - bridgeEvent.setDateReceived(new Date()); + return null; + } - logger.info("Bridge " + bridgeEvent.getChannel1() + " " + bridgeEvent.getChannel2()); + BridgeEvent bridgeEvent = buildBridgeEvent( + BridgeEvent.BRIDGE_STATE_LINK, + members.values()); - return bridgeEvent; - } - return null; + logger.info("Bridge " + bridgeEvent.getChannel1() + " " + bridgeEvent.getChannel2()); + return bridgeEvent; } /** @@ -84,35 +76,37 @@ public ManagerEvent addMember(BridgeEnterEvent event) public ManagerEvent removeMember(BridgeLeaveEvent event) { - BridgeEvent bridgeEvent = null; - for (BridgeEnterEvent member : members.values()) + BridgeEnterEvent removed = members.remove(event.getChannel()); + + // If we didn't remove anything, or we aren't at exactly 2 members, + // there's nothing else for us to do + if (removed == null || members.size() != 2) { - if (member.getChannel().equalsIgnoreCase(event.getChannel())) - { - List memberList = new LinkedList<>(); - memberList.addAll(members.values()); - if (memberList.size() == 2) - { - - bridgeEvent = new BridgeEvent(this); - - bridgeEvent.setCallerId1(memberList.get(0).getCallerIdNum()); - bridgeEvent.setCallerId2(memberList.get(1).getCallerIdNum()); - bridgeEvent.setUniqueId1(memberList.get(0).getUniqueId()); - bridgeEvent.setUniqueId2(memberList.get(1).getUniqueId()); - bridgeEvent.setChannel1(memberList.get(0).getChannel()); - bridgeEvent.setChannel2(memberList.get(1).getChannel()); - bridgeEvent.setBridgeState(BridgeEvent.BRIDGE_STATE_UNLINK); - bridgeEvent.setDateReceived(new Date()); - } - members.remove(member.getChannel()); - - return bridgeEvent; - - } + return null; } - return bridgeEvent; + return buildBridgeEvent( + BridgeEvent.BRIDGE_STATE_UNLINK, + members.values()); } + + private BridgeEvent buildBridgeEvent(String bridgeState, Collection events) + { + List remaining = new ArrayList<>(events); + + BridgeEvent bridgeEvent = new BridgeEvent(this); + + bridgeEvent.setCallerId1(remaining.get(0).getCallerIdNum()); + bridgeEvent.setUniqueId1(remaining.get(0).getUniqueId()); + bridgeEvent.setChannel1(remaining.get(0).getChannel()); + + bridgeEvent.setCallerId2(remaining.get(1).getCallerIdNum()); + bridgeEvent.setUniqueId2(remaining.get(1).getUniqueId()); + bridgeEvent.setChannel2(remaining.get(1).getChannel()); + bridgeEvent.setBridgeState(bridgeState); + bridgeEvent.setDateReceived(new Date()); + + return bridgeEvent; + } } From f748fc1b33ea101105cefde5507256a51520cd4c Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 14 Jul 2016 17:34:12 -0400 Subject: [PATCH 024/802] Make BridgeState package-private --- .../backwardsCompatibility/bridge/BridgeState.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index d5fa6cf45..e2c474a78 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -22,7 +22,7 @@ * * @author rsutton */ -public class BridgeState +class BridgeState { final Log logger = LogFactory.getLog(getClass()); @@ -35,11 +35,10 @@ public BridgeState(BridgeCreateEvent event) created = event; } - public ManagerEvent destroy(BridgeDestroyEvent event) + ManagerEvent destroy(BridgeDestroyEvent event) { destroyed = event; return null; - } /** @@ -48,7 +47,7 @@ public ManagerEvent destroy(BridgeDestroyEvent event) * @param event * @return */ - public ManagerEvent addMember(BridgeEnterEvent event) + ManagerEvent addMember(BridgeEnterEvent event) { members.put(event.getChannel(), event); logger.info("Members size " + members.size() + " " + event); @@ -74,7 +73,7 @@ public ManagerEvent addMember(BridgeEnterEvent event) * @return */ - public ManagerEvent removeMember(BridgeLeaveEvent event) + ManagerEvent removeMember(BridgeLeaveEvent event) { BridgeEnterEvent removed = members.remove(event.getChannel()); From cb20109c148aaa06c8b2880434daa6de07fcd561 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 14 Jul 2016 17:36:45 -0400 Subject: [PATCH 025/802] Remove unused BridgeState members They were being set but never read, so dump them. --- .../backwardsCompatibility/bridge/BridgeState.java | 10 ++-------- .../backwardsCompatibility/bridge/BridgesActive.java | 4 ++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index e2c474a78..a27b09f8b 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -7,8 +7,6 @@ import java.util.List; import java.util.Map; -import org.asteriskjava.manager.event.BridgeCreateEvent; -import org.asteriskjava.manager.event.BridgeDestroyEvent; import org.asteriskjava.manager.event.BridgeEnterEvent; import org.asteriskjava.manager.event.BridgeEvent; import org.asteriskjava.manager.event.BridgeLeaveEvent; @@ -26,18 +24,14 @@ class BridgeState { final Log logger = LogFactory.getLog(getClass()); - BridgeCreateEvent created; - BridgeDestroyEvent destroyed; private final Map members = new HashMap<>(); - public BridgeState(BridgeCreateEvent event) + public BridgeState() { - created = event; } - ManagerEvent destroy(BridgeDestroyEvent event) + ManagerEvent destroy() { - destroyed = event; return null; } diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java index 827eb7822..948f29d41 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java @@ -59,7 +59,7 @@ ManagerEvent createBridge(BridgeCreateEvent event) { if (activeBridges.get(event.getBridgeUniqueId()) == null) { - BridgeState state = new BridgeState(event); + BridgeState state = new BridgeState(); activeBridges.put(event.getBridgeUniqueId(), state); } return null; @@ -70,7 +70,7 @@ ManagerEvent destroyBridge(BridgeDestroyEvent event) BridgeState state = activeBridges.remove(event.getBridgeUniqueId()); if (state != null) { - return state.destroy(event); + return state.destroy(); } logger.info("Cant find bridge for id " + event.getBridgeUniqueId()); return null; From a6aeb2fe695a6c7a2cc82a8888fcf8d3aab587ac Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 14 Jul 2016 17:44:56 -0400 Subject: [PATCH 026/802] Cache the result of ReflectionUtil.getGetters This method is currently called twice for each action being built. --- .../manager/internal/ActionBuilderImpl.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java index 1260a6355..e1149b5d3 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java @@ -99,6 +99,8 @@ else if (action.getActionId() != null) ignore.add("action"); ignore.add("actionid"); ignore.add(ATTRIBUTES_PROPERTY_NAME); + + Map getters; // if this is a user event action, we need to grab the internal event, // otherwise do below as normal @@ -106,20 +108,22 @@ else if (action.getActionId() != null) { UserEvent userEvent = ((UserEventAction) action).getUserEvent(); appendUserEvent(sb, userEvent); + + getters = ReflectionUtil.getGetters(userEvent.getClass()); // eventually we may want to add more Map keys for events to ignore // when appending - appendGetters(sb, userEvent, ignore); + appendGetters(sb, userEvent, getters, ignore); } else { - appendGetters(sb, action, ignore); + getters = ReflectionUtil.getGetters(action.getClass()); + + appendGetters(sb, action, getters, ignore); } // actions that have the special getAttributes method will // have their Map appended without a singular key or separator - Map getters = ReflectionUtil.getGetters(action.getClass()); - if (getters.containsKey(ATTRIBUTES_PROPERTY_NAME)) { Method getter = getters.get(ATTRIBUTES_PROPERTY_NAME); @@ -261,9 +265,8 @@ private void appendUserEvent(StringBuilder sb, UserEvent event) } @SuppressWarnings("unchecked") - private void appendGetters(StringBuilder sb, Object action, Set membersToIgnore) + private void appendGetters(StringBuilder sb, Object action, Map getters, Set membersToIgnore) { - Map getters = ReflectionUtil.getGetters(action.getClass()); for (Map.Entry entry : getters.entrySet()) { final String name = entry.getKey(); From 7931756fe6675f64c28c7d1bd087362bfdfa2515 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 14 Jul 2016 17:48:01 -0400 Subject: [PATCH 027/802] Use Integer.compareTo instead of hand rolled implementation This is more a small clean-up than anything else. --- .../java/org/asteriskjava/AsteriskVersion.java | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 7e7b1636a..474a1f16a 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -116,21 +116,7 @@ public boolean isAtLeast(AsteriskVersion o) public int compareTo(AsteriskVersion o) { - int otherVersion; - - otherVersion = o.version; - if (version < otherVersion) - { - return -1; - } - else if (version > otherVersion) - { - return 1; - } - else - { - return 0; - } + return Integer.compare(version, o.version); } @Override From b33e7f3b48a203a039ff8d9b91099941990107f4 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 14 Jul 2016 17:54:55 -0400 Subject: [PATCH 028/802] Cache another re-used object The getter ignore HashSet is built everytime with the same content, so just build it one time. --- .../manager/internal/ActionBuilderImpl.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java index e1149b5d3..80733ed35 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java @@ -50,6 +50,7 @@ class ActionBuilderImpl implements ActionBuilder */ private final Log logger = LogFactory.getLog(getClass()); private AsteriskVersion targetVersion; + private final Set membersToIgnore = new HashSet<>(); /** * Creates a new ActionBuilder for Asterisk 1.0. @@ -57,6 +58,15 @@ class ActionBuilderImpl implements ActionBuilder ActionBuilderImpl() { this.targetVersion = AsteriskVersion.ASTERISK_1_0; + + /* + * When using the Reflection API to get all of the getters for building + * actions to send, we ignore some of the getters + */ + this.membersToIgnore.add("class"); + this.membersToIgnore.add("action"); + this.membersToIgnore.add("actionid"); + this.membersToIgnore.add(ATTRIBUTES_PROPERTY_NAME); } public void setTargetVersion(AsteriskVersion targetVersion) @@ -90,16 +100,6 @@ else if (action.getActionId() != null) sb.append(LINE_SEPARATOR); } - /* - * When using the Reflection API to get all of the getters for building - * actions to send, we ignore some of the getters - */ - Set ignore = new HashSet<>(); - ignore.add("class"); - ignore.add("action"); - ignore.add("actionid"); - ignore.add(ATTRIBUTES_PROPERTY_NAME); - Map getters; // if this is a user event action, we need to grab the internal event, @@ -113,13 +113,13 @@ else if (action.getActionId() != null) // eventually we may want to add more Map keys for events to ignore // when appending - appendGetters(sb, userEvent, getters, ignore); + appendGetters(sb, userEvent, getters); } else { getters = ReflectionUtil.getGetters(action.getClass()); - appendGetters(sb, action, getters, ignore); + appendGetters(sb, action, getters); } // actions that have the special getAttributes method will @@ -265,7 +265,7 @@ private void appendUserEvent(StringBuilder sb, UserEvent event) } @SuppressWarnings("unchecked") - private void appendGetters(StringBuilder sb, Object action, Map getters, Set membersToIgnore) + private void appendGetters(StringBuilder sb, Object action, Map getters) { for (Map.Entry entry : getters.entrySet()) { From c48226b9b6ec87e9dbd2759b9040c0897674ed49 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 14 Jul 2016 18:10:36 -0400 Subject: [PATCH 029/802] Make some ActionBuildImpl methods static --- .../manager/internal/ActionBuilderImpl.java | 8 ++++---- .../manager/internal/ActionBuilderImplTest.java | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java index 80733ed35..9de1dcf7a 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java @@ -309,7 +309,7 @@ else if (value instanceof String) } } - private String mapToAsterisk(Method getter) + private static String mapToAsterisk(Method getter) { AsteriskMapping annotation; @@ -361,7 +361,7 @@ private String mapToAsterisk(Method getter) return fieldName.toLowerCase(Locale.US); } - String determineSetterName(String getterName) + static String determineSetterName(String getterName) { if (getterName.startsWith("get")) { @@ -377,7 +377,7 @@ else if (getterName.startsWith("is")) } } - String determineFieldName(String accessorName) + static String determineFieldName(String accessorName) { if (accessorName.startsWith("get")) { @@ -403,7 +403,7 @@ else if (accessorName.startsWith("set")) * @param s the string to convert. * @return the converted string. */ - String lcFirst(String s) + private static String lcFirst(String s) { if (s == null || s.length() < 1) { diff --git a/src/test/java/org/asteriskjava/manager/internal/ActionBuilderImplTest.java b/src/test/java/org/asteriskjava/manager/internal/ActionBuilderImplTest.java index 84038a951..de6e1a015 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ActionBuilderImplTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/ActionBuilderImplTest.java @@ -261,8 +261,8 @@ public void testBuildActionWithAnnotatedGetter() @Test public void testDetermineSetterName() { - assertEquals("setProperty1", actionBuilder.determineSetterName("getProperty1")); - assertEquals("setProperty1", actionBuilder.determineSetterName("isProperty1")); + assertEquals("setProperty1", ActionBuilderImpl.determineSetterName("getProperty1")); + assertEquals("setProperty1", ActionBuilderImpl.determineSetterName("isProperty1")); } @Test @@ -278,9 +278,9 @@ public void testBuildActionWithAnnotatedSetter() @Test public void testDetermineFieldName() { - assertEquals("property1", actionBuilder.determineFieldName("getProperty1")); - assertEquals("property1", actionBuilder.determineFieldName("isProperty1")); - assertEquals("property1", actionBuilder.determineFieldName("setProperty1")); + assertEquals("property1", ActionBuilderImpl.determineFieldName("getProperty1")); + assertEquals("property1", ActionBuilderImpl.determineFieldName("isProperty1")); + assertEquals("property1", ActionBuilderImpl.determineFieldName("setProperty1")); } @Test From 3f972f429de994eed345816c93273490888b415f Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 14 Jul 2016 18:11:57 -0400 Subject: [PATCH 030/802] Prevent StringIndexOutOfBoundsException exception ActionBuilderImpl.lcFirst wasn't protecting the case where the string length was 1. --- .../asteriskjava/manager/internal/ActionBuilderImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java index 9de1dcf7a..e4423b4b5 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java @@ -405,12 +405,12 @@ else if (accessorName.startsWith("set")) */ private static String lcFirst(String s) { - if (s == null || s.length() < 1) + if (s == null || s.isEmpty()) { return s; } - char first = s.charAt(0); - return Character.toLowerCase(first) + s.substring(1); + return Character.toLowerCase(s.charAt(0)) + + (s.length() == 1 ? "" : s.substring(1)); } } From f5a87e43d6a28441924b7c67638cc33a26e897e4 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 14 Jul 2016 20:12:11 -0400 Subject: [PATCH 031/802] Bring back ConcurrentHashMap and properly synchronize Because the list of active bridges can be accessed from multiple threads, it does make more sense to use a ConcurrentHashMap, so bring it back. Also fix a CAS in BridgesActive.createBridge() and make activeBridges private so there are no shenanigans (it was already package-private, so this isn't that significant). For BridgeState, stick with a HashMap and use proper synchronization. This is necessary to synchronize the put/remove/size semantics present in addMember/removeMember. --- .../bridge/BridgeState.java | 61 ++++++++++++------- .../bridge/BridgesActive.java | 27 +++----- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index a27b09f8b..a16171c6a 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -1,7 +1,6 @@ package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; import java.util.ArrayList; -import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -25,13 +24,12 @@ class BridgeState final Log logger = LogFactory.getLog(getClass()); private final Map members = new HashMap<>(); - - public BridgeState() - { - } - + ManagerEvent destroy() { + synchronized (members) { + members.clear(); + } return null; } @@ -43,17 +41,27 @@ ManagerEvent destroy() */ ManagerEvent addMember(BridgeEnterEvent event) { - members.put(event.getChannel(), event); - logger.info("Members size " + members.size() + " " + event); - - if (members.size() != 2) + List remaining = null; + + synchronized (members) + { + if (members.put(event.getChannel(), event) == null + && members.size() == 2) + { + remaining = new ArrayList<>(members.values()); + } + } + + if (remaining == null) { return null; } + logger.info("Members size " + remaining.size() + " " + event); + BridgeEvent bridgeEvent = buildBridgeEvent( BridgeEvent.BRIDGE_STATE_LINK, - members.values()); + remaining); logger.info("Bridge " + bridgeEvent.getChannel1() + " " + bridgeEvent.getChannel2()); @@ -69,33 +77,40 @@ ManagerEvent addMember(BridgeEnterEvent event) ManagerEvent removeMember(BridgeLeaveEvent event) { - BridgeEnterEvent removed = members.remove(event.getChannel()); + List remaining = null; + + synchronized (members) + { + if (members.remove(event.getChannel()) != null + && members.size() == 2) + { + remaining = new ArrayList<>(members.values()); + } + } // If we didn't remove anything, or we aren't at exactly 2 members, // there's nothing else for us to do - if (removed == null || members.size() != 2) + if (remaining == null) { return null; } return buildBridgeEvent( BridgeEvent.BRIDGE_STATE_UNLINK, - members.values()); + remaining); } - private BridgeEvent buildBridgeEvent(String bridgeState, Collection events) + private BridgeEvent buildBridgeEvent(String bridgeState, List members) { - List remaining = new ArrayList<>(events); - BridgeEvent bridgeEvent = new BridgeEvent(this); - bridgeEvent.setCallerId1(remaining.get(0).getCallerIdNum()); - bridgeEvent.setUniqueId1(remaining.get(0).getUniqueId()); - bridgeEvent.setChannel1(remaining.get(0).getChannel()); + bridgeEvent.setCallerId1(members.get(0).getCallerIdNum()); + bridgeEvent.setUniqueId1(members.get(0).getUniqueId()); + bridgeEvent.setChannel1(members.get(0).getChannel()); - bridgeEvent.setCallerId2(remaining.get(1).getCallerIdNum()); - bridgeEvent.setUniqueId2(remaining.get(1).getUniqueId()); - bridgeEvent.setChannel2(remaining.get(1).getChannel()); + bridgeEvent.setCallerId2(members.get(1).getCallerIdNum()); + bridgeEvent.setUniqueId2(members.get(1).getUniqueId()); + bridgeEvent.setChannel2(members.get(1).getChannel()); bridgeEvent.setBridgeState(bridgeState); bridgeEvent.setDateReceived(new Date()); diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java index 948f29d41..11b042cac 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java @@ -1,7 +1,7 @@ package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; -import java.util.HashMap; -import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.asteriskjava.manager.event.BridgeCreateEvent; import org.asteriskjava.manager.event.BridgeDestroyEvent; @@ -26,10 +26,10 @@ public class BridgesActive { private final Log logger = LogFactory.getLog(BridgesActive.class); - // this map is shared (static) so that connections to asterisk that attach - // late can - // benefit from the known bridge information of older connections - final static Map activeBridges = new HashMap<>(); + // This map is shared (static) so that connections to asterisk that attach + // late can benefit from the known bridge information of older connections + private final static ConcurrentMap activeBridges = + new ConcurrentHashMap<>(); public ManagerEvent handleEvent(ManagerEvent event) { @@ -41,9 +41,7 @@ else if (event instanceof BridgeDestroyEvent) { return destroyBridge((BridgeDestroyEvent) event); } - else - - if (event instanceof BridgeEnterEvent) + else if (event instanceof BridgeEnterEvent) { return enterBridge((BridgeEnterEvent) event); } @@ -52,25 +50,20 @@ else if (event instanceof BridgeLeaveEvent) return leaveBridge((BridgeLeaveEvent) event); } return null; - } ManagerEvent createBridge(BridgeCreateEvent event) { - if (activeBridges.get(event.getBridgeUniqueId()) == null) - { - BridgeState state = new BridgeState(); - activeBridges.put(event.getBridgeUniqueId(), state); - } + activeBridges.putIfAbsent(event.getBridgeUniqueId(), new BridgeState()); return null; } ManagerEvent destroyBridge(BridgeDestroyEvent event) { - BridgeState state = activeBridges.remove(event.getBridgeUniqueId()); + BridgeState state = activeBridges.get(event.getBridgeUniqueId()); if (state != null) { - return state.destroy(); + state.destroy(); } logger.info("Cant find bridge for id " + event.getBridgeUniqueId()); return null; From 9626eb809db4acda3aba720d43d05679d7b69ff3 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 14 Jul 2016 20:24:19 -0400 Subject: [PATCH 032/802] Fix remaining bug in BridgesActive --- .../internal/backwardsCompatibility/bridge/BridgesActive.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java index 11b042cac..7ebe13854 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java @@ -60,10 +60,10 @@ ManagerEvent createBridge(BridgeCreateEvent event) ManagerEvent destroyBridge(BridgeDestroyEvent event) { - BridgeState state = activeBridges.get(event.getBridgeUniqueId()); + BridgeState state = activeBridges.remove(event.getBridgeUniqueId()); if (state != null) { - state.destroy(); + return state.destroy(); } logger.info("Cant find bridge for id " + event.getBridgeUniqueId()); return null; From 623b7dfd7b7fc686f69714e0e7864eac5bb08fd1 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 15 Jul 2016 08:23:29 -0400 Subject: [PATCH 033/802] Remove a check-then-act in ManagerReaderImpl --- .../asteriskjava/manager/internal/ManagerReaderImpl.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java index f2ae1b6bf..c7c6231f5 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java @@ -343,11 +343,7 @@ private ManagerResponse buildResponse(Map buffer) final String internalActionId = ManagerUtil.getInternalActionId(actionId); if (internalActionId != null) { - responseClass = expectedResponseClasses.get(internalActionId); - if (responseClass != null) - { - expectedResponseClasses.remove(internalActionId); - } + responseClass = expectedResponseClasses.remove(internalActionId); } final ManagerResponse response = responseBuilder.buildResponse(responseClass, buffer); From 9fab1173c6f6e4b0030a568517193551ff7d242c Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 15 Jul 2016 13:53:44 -0400 Subject: [PATCH 034/802] AgiServerThread: synchronize all access to agiServer --- src/main/java/org/asteriskjava/fastagi/AgiServerThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/fastagi/AgiServerThread.java b/src/main/java/org/asteriskjava/fastagi/AgiServerThread.java index 0799b8301..77a226cfe 100644 --- a/src/main/java/org/asteriskjava/fastagi/AgiServerThread.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiServerThread.java @@ -76,7 +76,7 @@ public AgiServerThread(AgiServer agiServer) * * @param agiServer the AgiServer to run. */ - public void setAgiServer(AgiServer agiServer) + public synchronized void setAgiServer(AgiServer agiServer) { this.agiServer = agiServer; } From 62344302d0c61ccdd90ad1563437e503e0776359 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 18 Jul 2016 14:57:58 -0400 Subject: [PATCH 035/802] Don't leak classes that are 'internal' There were two places that 'internal' classes were being published: 1. AgiChannelFactory is published via AbstractAgiServer and others. 2. AsteriskAgentImpl published via AsteriskServerListener. So we promote AgiChannelFactory to API - which requires us to also pull up AgiReader and AgiWriter - and we replace the reference to AsteriskAgentImpl with AsteriskAgent. Also updated bnd plugin to 3.2.0 --- pom.xml | 2 +- .../java/org/asteriskjava/fastagi/AbstractAgiServer.java | 1 - .../fastagi/{internal => }/AgiChannelFactory.java | 5 +---- .../org/asteriskjava/fastagi/{internal => }/AgiReader.java | 4 +--- .../org/asteriskjava/fastagi/{internal => }/AgiWriter.java | 2 +- src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java | 1 - src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java | 1 - .../org/asteriskjava/fastagi/internal/AgiChannelImpl.java | 2 ++ .../asteriskjava/fastagi/internal/AgiConnectionHandler.java | 3 +++ .../fastagi/internal/AsyncAgiConnectionHandler.java | 3 +++ .../org/asteriskjava/fastagi/internal/AsyncAgiReader.java | 1 + .../org/asteriskjava/fastagi/internal/AsyncAgiWriter.java | 1 + .../fastagi/internal/DefaultAgiChannelFactory.java | 3 +++ .../fastagi/internal/FastAgiConnectionHandler.java | 3 +++ .../org/asteriskjava/fastagi/internal/FastAgiReader.java | 1 + .../org/asteriskjava/fastagi/internal/FastAgiWriter.java | 1 + .../java/org/asteriskjava/live/AsteriskServerListener.java | 4 +--- .../asteriskjava/fastagi/internal/AgiChannelImplTest.java | 2 ++ .../org/asteriskjava/fastagi/internal/AgiReaderImplTest.java | 1 + .../org/asteriskjava/fastagi/internal/AgiWriterImplTest.java | 1 + 20 files changed, 27 insertions(+), 15 deletions(-) rename src/main/java/org/asteriskjava/fastagi/{internal => }/AgiChannelFactory.java (81%) rename src/main/java/org/asteriskjava/fastagi/{internal => }/AgiReader.java (90%) rename src/main/java/org/asteriskjava/fastagi/{internal => }/AgiWriter.java (96%) diff --git a/pom.xml b/pom.xml index 6a7eda570..22c84c72b 100644 --- a/pom.xml +++ b/pom.xml @@ -113,7 +113,7 @@ biz.aQute.bnd bnd-maven-plugin - 3.1.0 + 3.2.0 diff --git a/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java b/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java index 7e5d16ef9..76bedea20 100644 --- a/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java @@ -5,7 +5,6 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import org.asteriskjava.fastagi.internal.AgiChannelFactory; import org.asteriskjava.fastagi.internal.DefaultAgiChannelFactory; import org.asteriskjava.util.DaemonThreadFactory; import org.asteriskjava.util.Log; diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelFactory.java b/src/main/java/org/asteriskjava/fastagi/AgiChannelFactory.java similarity index 81% rename from src/main/java/org/asteriskjava/fastagi/internal/AgiChannelFactory.java rename to src/main/java/org/asteriskjava/fastagi/AgiChannelFactory.java index 2365a186d..100eca517 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelFactory.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiChannelFactory.java @@ -1,7 +1,4 @@ -package org.asteriskjava.fastagi.internal; - -import org.asteriskjava.fastagi.AgiChannel; -import org.asteriskjava.fastagi.AgiRequest; +package org.asteriskjava.fastagi; /** * An AgiChannelFactory creates instances of AgiChannels, diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiReader.java b/src/main/java/org/asteriskjava/fastagi/AgiReader.java similarity index 90% rename from src/main/java/org/asteriskjava/fastagi/internal/AgiReader.java rename to src/main/java/org/asteriskjava/fastagi/AgiReader.java index a29623ec9..68850f90e 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiReader.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiReader.java @@ -14,10 +14,8 @@ * limitations under the License. * */ -package org.asteriskjava.fastagi.internal; +package org.asteriskjava.fastagi; -import org.asteriskjava.fastagi.AgiException; -import org.asteriskjava.fastagi.AgiRequest; import org.asteriskjava.fastagi.reply.AgiReply; /** diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiWriter.java b/src/main/java/org/asteriskjava/fastagi/AgiWriter.java similarity index 96% rename from src/main/java/org/asteriskjava/fastagi/internal/AgiWriter.java rename to src/main/java/org/asteriskjava/fastagi/AgiWriter.java index 59d602f2e..0b4527f5a 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiWriter.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiWriter.java @@ -14,7 +14,7 @@ * limitations under the License. * */ -package org.asteriskjava.fastagi.internal; +package org.asteriskjava.fastagi; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.command.AgiCommand; diff --git a/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java b/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java index 98ee11723..335ad2c42 100644 --- a/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java @@ -4,7 +4,6 @@ import java.util.Map; import java.util.concurrent.RejectedExecutionException; -import org.asteriskjava.fastagi.internal.AgiChannelFactory; import org.asteriskjava.fastagi.internal.AsyncAgiConnectionHandler; import org.asteriskjava.fastagi.internal.DefaultAgiChannelFactory; import org.asteriskjava.manager.ManagerConnection; diff --git a/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java b/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java index 64a58bc92..82dd06ef5 100644 --- a/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java @@ -22,7 +22,6 @@ import java.util.ResourceBundle; import java.util.concurrent.RejectedExecutionException; -import org.asteriskjava.fastagi.internal.AgiChannelFactory; import org.asteriskjava.fastagi.internal.AgiConnectionHandler; import org.asteriskjava.fastagi.internal.DefaultAgiChannelFactory; import org.asteriskjava.fastagi.internal.FastAgiConnectionHandler; diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java index 913ab17e0..ba0171f83 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java @@ -19,8 +19,10 @@ import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.fastagi.AgiReader; import org.asteriskjava.fastagi.AgiRequest; import org.asteriskjava.fastagi.AgiSpeechException; +import org.asteriskjava.fastagi.AgiWriter; import org.asteriskjava.fastagi.InvalidCommandSyntaxException; import org.asteriskjava.fastagi.InvalidOrUnknownCommandException; import org.asteriskjava.fastagi.SpeechRecognitionResult; diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java index 222b9e461..3d20b8626 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java @@ -16,6 +16,9 @@ */ package org.asteriskjava.fastagi.internal; +import org.asteriskjava.fastagi.AgiWriter; +import org.asteriskjava.fastagi.AgiReader; +import org.asteriskjava.fastagi.AgiChannelFactory; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiConnectionHandler.java b/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiConnectionHandler.java index ceb6c64d5..930c35c40 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiConnectionHandler.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiConnectionHandler.java @@ -20,7 +20,10 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import org.asteriskjava.fastagi.AgiChannelFactory; import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiReader; +import org.asteriskjava.fastagi.AgiWriter; import org.asteriskjava.fastagi.MappingStrategy; import org.asteriskjava.fastagi.command.AsyncAgiBreakCommand; import org.asteriskjava.manager.ManagerConnection; diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiReader.java b/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiReader.java index af3cc2eeb..dc5880ffc 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiReader.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiReader.java @@ -4,6 +4,7 @@ import java.util.concurrent.BlockingQueue; import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiReader; import org.asteriskjava.fastagi.AgiRequest; import org.asteriskjava.fastagi.reply.AgiReply; import org.asteriskjava.manager.ManagerConnection; diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiWriter.java b/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiWriter.java index 692294bd9..4440bd60b 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiWriter.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AsyncAgiWriter.java @@ -3,6 +3,7 @@ import java.io.IOException; import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiWriter; import org.asteriskjava.fastagi.command.AgiCommand; import org.asteriskjava.manager.ManagerConnection; import org.asteriskjava.manager.TimeoutException; diff --git a/src/main/java/org/asteriskjava/fastagi/internal/DefaultAgiChannelFactory.java b/src/main/java/org/asteriskjava/fastagi/internal/DefaultAgiChannelFactory.java index 44ced44d0..59bda0e1e 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/DefaultAgiChannelFactory.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/DefaultAgiChannelFactory.java @@ -1,7 +1,10 @@ package org.asteriskjava.fastagi.internal; import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiChannelFactory; +import org.asteriskjava.fastagi.AgiReader; import org.asteriskjava.fastagi.AgiRequest; +import org.asteriskjava.fastagi.AgiWriter; /** * If no other factory is passed to DefaultAgiServer's constructor, diff --git a/src/main/java/org/asteriskjava/fastagi/internal/FastAgiConnectionHandler.java b/src/main/java/org/asteriskjava/fastagi/internal/FastAgiConnectionHandler.java index 139678a60..edd32d8aa 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/FastAgiConnectionHandler.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/FastAgiConnectionHandler.java @@ -18,6 +18,9 @@ import java.io.IOException; +import org.asteriskjava.fastagi.AgiChannelFactory; +import org.asteriskjava.fastagi.AgiReader; +import org.asteriskjava.fastagi.AgiWriter; import org.asteriskjava.fastagi.MappingStrategy; import org.asteriskjava.util.SocketConnectionFacade; diff --git a/src/main/java/org/asteriskjava/fastagi/internal/FastAgiReader.java b/src/main/java/org/asteriskjava/fastagi/internal/FastAgiReader.java index 8dca752db..e337321ad 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/FastAgiReader.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/FastAgiReader.java @@ -23,6 +23,7 @@ import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; import org.asteriskjava.fastagi.AgiNetworkException; +import org.asteriskjava.fastagi.AgiReader; import org.asteriskjava.fastagi.AgiRequest; import org.asteriskjava.fastagi.reply.AgiReply; import org.asteriskjava.util.SocketConnectionFacade; diff --git a/src/main/java/org/asteriskjava/fastagi/internal/FastAgiWriter.java b/src/main/java/org/asteriskjava/fastagi/internal/FastAgiWriter.java index 031f89f04..f7656bc79 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/FastAgiWriter.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/FastAgiWriter.java @@ -20,6 +20,7 @@ import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiNetworkException; +import org.asteriskjava.fastagi.AgiWriter; import org.asteriskjava.fastagi.command.AgiCommand; import org.asteriskjava.util.SocketConnectionFacade; diff --git a/src/main/java/org/asteriskjava/live/AsteriskServerListener.java b/src/main/java/org/asteriskjava/live/AsteriskServerListener.java index 99590375c..922369881 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskServerListener.java +++ b/src/main/java/org/asteriskjava/live/AsteriskServerListener.java @@ -1,7 +1,5 @@ package org.asteriskjava.live; -import org.asteriskjava.live.internal.AsteriskAgentImpl; - /** * You can register an AsteriskServerListener with an * {@link org.asteriskjava.live.AsteriskServer} to be notified about new @@ -36,7 +34,7 @@ public interface AsteriskServerListener * * @param agent */ - void onNewAgent(AsteriskAgentImpl agent); + void onNewAgent(AsteriskAgent agent); /** * Called whenever a queue entry ( ~ wapper over channel) joins a {@link org.asteriskjava.live.AsteriskQueue}. diff --git a/src/test/java/org/asteriskjava/fastagi/internal/AgiChannelImplTest.java b/src/test/java/org/asteriskjava/fastagi/internal/AgiChannelImplTest.java index 22267441a..83d5228a1 100644 --- a/src/test/java/org/asteriskjava/fastagi/internal/AgiChannelImplTest.java +++ b/src/test/java/org/asteriskjava/fastagi/internal/AgiChannelImplTest.java @@ -26,6 +26,8 @@ import java.util.List; import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiReader; +import org.asteriskjava.fastagi.AgiWriter; import org.asteriskjava.fastagi.InvalidCommandSyntaxException; import org.asteriskjava.fastagi.InvalidOrUnknownCommandException; import org.asteriskjava.fastagi.command.NoopCommand; diff --git a/src/test/java/org/asteriskjava/fastagi/internal/AgiReaderImplTest.java b/src/test/java/org/asteriskjava/fastagi/internal/AgiReaderImplTest.java index d26982bc8..fbf3a3b6a 100644 --- a/src/test/java/org/asteriskjava/fastagi/internal/AgiReaderImplTest.java +++ b/src/test/java/org/asteriskjava/fastagi/internal/AgiReaderImplTest.java @@ -26,6 +26,7 @@ import java.net.InetAddress; import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.fastagi.AgiReader; import org.asteriskjava.fastagi.AgiRequest; import org.asteriskjava.fastagi.reply.AgiReply; import org.asteriskjava.util.SocketConnectionFacade; diff --git a/src/test/java/org/asteriskjava/fastagi/internal/AgiWriterImplTest.java b/src/test/java/org/asteriskjava/fastagi/internal/AgiWriterImplTest.java index 30a058a69..1c934bab3 100644 --- a/src/test/java/org/asteriskjava/fastagi/internal/AgiWriterImplTest.java +++ b/src/test/java/org/asteriskjava/fastagi/internal/AgiWriterImplTest.java @@ -20,6 +20,7 @@ import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; +import org.asteriskjava.fastagi.AgiWriter; import org.asteriskjava.fastagi.command.StreamFileCommand; import org.asteriskjava.util.SocketConnectionFacade; import org.junit.Before; From 093e5ec6c243619c0bbb46ab3bae815d2119995c Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 18 Jul 2016 15:29:28 -0400 Subject: [PATCH 036/802] Turn off execute bit on source files --- .../org/asteriskjava/manager/AbstractManagerEventListener.java | 0 .../org/asteriskjava/manager/event/AbstractChannelStateEvent.java | 0 .../java/org/asteriskjava/manager/event/ChanSpyStartEvent.java | 0 .../java/org/asteriskjava/manager/event/ChanSpyStopEvent.java | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java mode change 100755 => 100644 src/main/java/org/asteriskjava/manager/event/AbstractChannelStateEvent.java mode change 100755 => 100644 src/main/java/org/asteriskjava/manager/event/ChanSpyStartEvent.java mode change 100755 => 100644 src/main/java/org/asteriskjava/manager/event/ChanSpyStopEvent.java diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java old mode 100755 new mode 100644 diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractChannelStateEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractChannelStateEvent.java old mode 100755 new mode 100644 diff --git a/src/main/java/org/asteriskjava/manager/event/ChanSpyStartEvent.java b/src/main/java/org/asteriskjava/manager/event/ChanSpyStartEvent.java old mode 100755 new mode 100644 diff --git a/src/main/java/org/asteriskjava/manager/event/ChanSpyStopEvent.java b/src/main/java/org/asteriskjava/manager/event/ChanSpyStopEvent.java old mode 100755 new mode 100644 From f51f8baec1731fe080b7ecabf6a4672b5e1abdaa Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Tue, 19 Jul 2016 12:37:02 -0300 Subject: [PATCH 037/802] missing properties fix issue #152 #153 --- .../manager/event/ParkedCallEvent.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java b/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java index d2584f461..9c6311988 100644 --- a/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java @@ -34,6 +34,8 @@ public class ParkedCallEvent extends AbstractParkedCallEvent private static final long serialVersionUID = 0L; private Integer timeout; + private String connectedlinenum; + private String connectedlinename; /** * @param source @@ -70,4 +72,29 @@ public void setUnqiueId(String unqiueId) { setUniqueId(unqiueId); } + + + public String getConnectedLinenum() + { + return connectedlinenum; + } + + + public void setConnectedLinenum(String connectedlinenum) + { + this.connectedlinenum = connectedlinenum; + } + + public String getConnectedLinename() + { + return connectedlinename; + } + + + public void setConnectedLinename(String connectedlinename) + { + this.connectedlinename = connectedlinename; + } + + } From 475daee6d658bf003d4b9694553c4c6989d6d9b1 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Tue, 19 Jul 2016 12:43:55 -0300 Subject: [PATCH 038/802] missing property fix issue #144 --- .../manager/event/OriginateResponseEvent.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java b/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java index 5576ba235..e5e88671a 100644 --- a/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java @@ -33,6 +33,7 @@ public class OriginateResponseEvent extends ResponseEvent private String channel; private String uniqueId; private Integer reason; + private String data; /** * @param source @@ -117,4 +118,14 @@ public void setCallerId(String callerId) setCallerIdNum(callerId); } } + + public String getData() + { + return data; + } + + public void setData(String data) + { + this.data = data; + } } From c3d7b91291a3c47f4835221a563b13d07e5f9ee2 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Tue, 19 Jul 2016 12:45:23 -0300 Subject: [PATCH 039/802] missing property fix issue #143 --- .../manager/event/OriginateResponseEvent.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java b/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java index e5e88671a..33ce8cb00 100644 --- a/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java @@ -34,6 +34,7 @@ public class OriginateResponseEvent extends ResponseEvent private String uniqueId; private Integer reason; private String data; + private String application; /** * @param source @@ -128,4 +129,14 @@ public void setData(String data) { this.data = data; } + + public String getApplication() + { + return application; + } + + public void setApplication(String application) + { + this.application = application; + } } From 8b38fcb29df3d526c3ab4e8d03f720483602c79a Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Tue, 19 Jul 2016 12:53:54 -0300 Subject: [PATCH 040/802] change source and target VM to 1.7 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 5243989b6..94e98f9a2 100644 --- a/build.gradle +++ b/build.gradle @@ -9,8 +9,8 @@ version = '2.0.0.CI-SNAPSHOT' description = """Asterisk-Java""" -sourceCompatibility = 1.6 -targetCompatibility = 1.6 +sourceCompatibility = 1.7 +targetCompatibility = 1.7 repositories { From a5c7ec127a49b27e6cf344c3f52c35273d8737e8 Mon Sep 17 00:00:00 2001 From: terwarf Date: Wed, 20 Jul 2016 08:50:41 +0200 Subject: [PATCH 041/802] Added setter for accountCode, fixed indentation --- .../manager/event/AgiExecEvent.java | 423 +++++++++--------- 1 file changed, 223 insertions(+), 200 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/AgiExecEvent.java b/src/main/java/org/asteriskjava/manager/event/AgiExecEvent.java index d40f851e1..4fc78bf87 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgiExecEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgiExecEvent.java @@ -19,203 +19,226 @@ */ public class AgiExecEvent extends ManagerEvent { - /** - * Serializable version identifier. - */ - static final long serialVersionUID = 0L; - - /** - * Execution of an AGI command has started. - */ - public static final String SUB_EVENT_START = "Start"; - - /** - * Execution of an AGI command has finished. - */ - public static final String SUB_EVENT_END = "End"; - - private String channel; - private String subEvent; - private String commandId; - private String command; - private Integer resultCode; - private String result; - - public String getUniqueId() { - return uniqueId; - } - - public void setUniqueId(String uniqueId) { - this.uniqueId = uniqueId; - } - - private String uniqueId; - - /** - * Creates a new AgiExecEvent. - * - * @param source - */ - public AgiExecEvent(Object source) - { - super(source); - } - - /** - * Returns the name of the channel this event occurred on. - * - * @return the name of the channel this event occurred on. - */ - public String getChannel() - { - return channel; - } - - /** - * Sets the name of the channel this event occurred on. - * - * @param channel the name of the channel this event occurred on. - */ - public void setChannel(String channel) - { - this.channel = channel; - } - - /** - * Returns the sub event type. This is either "Start" or "End". - * - * @return the sub event type. - * @see #SUB_EVENT_START - * @see #SUB_EVENT_END - */ - public String getSubEvent() - { - return subEvent; - } - - /** - * Sets the sub event type. - * - * @param subEvent the sub event type. - */ - public void setSubEvent(String subEvent) - { - this.subEvent = subEvent; - } - - /** - * Returns the command id. The command is a random number generated by Asterisk that allows - * matching the "End" sub event with the corresponding "Start" sub event. - * - * @return the command id. - */ - public String getCommandId() - { - return commandId; - } - - /** - * Sets the command id. - * - * @param commandId the command id. - */ - public void setCommandId(String commandId) - { - this.commandId = commandId; - } - - /** - * Returns the AGI command. - * - * @return the AGI command. - */ - public String getCommand() - { - return command; - } - - /** - * Sets the AGI command. - * - * @param command the AGI command. - */ - public void setCommand(String command) - { - this.command = command; - } - - /** - * Returns the result code. - * - * @return the result code. - */ - public Integer getResultCode() - { - return resultCode; - } - - /** - * Sets the result code. - * - * @param resultCode the result code. - */ - public void setResultCode(Integer resultCode) - { - this.resultCode = resultCode; - } - - /** - * Returns the result as a string.

- * They correspond to the numeric values returned by {@link #getResultCode()}. Usually you will want to - * stick with the numeric values.

- * Possible values are: - *

    - *
  • Failure (corresponds to result code -1)
  • - *
  • Success (corresponds to result code 200)
  • - *
  • KeepAlive (corresponds to result code 210)
  • - *
  • Command not permitted on a dead channel (corresponds to result code 511)
  • - *
  • Usage (corresponds to result code 520)
  • - *
- * - * @return a string respresentation of the result. - */ - public String getResult() - { - return result; - } - - /** - * Sets the string respresentation of the result. - * - * @param result a string respresentation of the result. - */ - public void setResult(String result) - { - this.result = result; - } - - /** - * Checks is this a start sub event. - * - * @return true if this is a "Start" sub event, false otherwise. - */ - public boolean isStart() - { - return isSubEvent(SUB_EVENT_START); - } - - /** - * Checks is this an end sub event. - * - * @return true if this is an "End" sub event, false otherwise. - */ - public boolean isEnd() - { - return isSubEvent(SUB_EVENT_END); - } - - private boolean isSubEvent(String subEvent) - { - return this.subEvent != null && this.subEvent.equalsIgnoreCase(subEvent); - } -} \ No newline at end of file + /** + * Serializable version identifier. + */ + static final long serialVersionUID = 0L; + + /** + * Execution of an AGI command has started. + */ + public static final String SUB_EVENT_START = "Start"; + + /** + * Execution of an AGI command has finished. + */ + public static final String SUB_EVENT_END = "End"; + + private String channel; + private String subEvent; + private String commandId; + private String command; + private Integer resultCode; + private String result; + private String accountCode; + + public String getUniqueId() + { + return uniqueId; + } + + public void setUniqueId(String uniqueId) + { + this.uniqueId = uniqueId; + } + + private String uniqueId; + + /** + * Creates a new AgiExecEvent. + * + * @param source + */ + public AgiExecEvent(Object source) + { + super(source); + } + + /** + * Returns the name of the channel this event occurred on. + * + * @return the name of the channel this event occurred on. + */ + public String getChannel() + { + return channel; + } + + /** + * Sets the name of the channel this event occurred on. + * + * @param channel the name of the channel this event occurred on. + */ + public void setChannel(String channel) + { + this.channel = channel; + } + + /** + * Returns the sub event type. This is either "Start" or "End". + * + * @return the sub event type. + * @see #SUB_EVENT_START + * @see #SUB_EVENT_END + */ + public String getSubEvent() + { + return subEvent; + } + + /** + * Sets the sub event type. + * + * @param subEvent the sub event type. + */ + public void setSubEvent(String subEvent) + { + this.subEvent = subEvent; + } + + /** + * Returns the command id. The command is a random number generated by Asterisk that allows matching the "End" sub event with the corresponding "Start" sub event. + * + * @return the command id. + */ + public String getCommandId() + { + return commandId; + } + + /** + * Sets the command id. + * + * @param commandId the command id. + */ + public void setCommandId(String commandId) + { + this.commandId = commandId; + } + + /** + * Returns the AGI command. + * + * @return the AGI command. + */ + public String getCommand() + { + return command; + } + + /** + * Sets the AGI command. + * + * @param command the AGI command. + */ + public void setCommand(String command) + { + this.command = command; + } + + /** + * Returns the result code. + * + * @return the result code. + */ + public Integer getResultCode() + { + return resultCode; + } + + /** + * Sets the result code. + * + * @param resultCode the result code. + */ + public void setResultCode(Integer resultCode) + { + this.resultCode = resultCode; + } + + /** + * Returns the result as a string.

+ * They correspond to the numeric values returned by {@link #getResultCode()}. Usually you will want to stick with the numeric values.

+ * Possible values are: + *

    + *
  • Failure (corresponds to result code -1)
  • + *
  • Success (corresponds to result code 200)
  • + *
  • KeepAlive (corresponds to result code 210)
  • + *
  • Command not permitted on a dead channel (corresponds to result code 511)
  • + *
  • Usage (corresponds to result code 520)
  • + *
+ * + * @return a string respresentation of the result. + */ + public String getResult() + { + return result; + } + + /** + * Sets the string respresentation of the result. + * + * @param result a string respresentation of the result. + */ + public void setResult(String result) + { + this.result = result; + } + + /** + * Returns the account code set for CDR. + * + * @return string + */ + public String getAccountCode() + { + return accountCode; + } + + /** + * Sets the account code used for billing in the CDR. + *
+ * This will be the filename asterisk stores the billing informations in, so it should only use lowercase letters, numbers, hyphen and underscore. + * + * @param accountCode + */ + public void setAccountCode(String accountCode) + { + this.accountCode = accountCode; + } + + /** + * Checks is this a start sub event. + * + * @return true if this is a "Start" sub event, false otherwise. + */ + public boolean isStart() + { + return isSubEvent(SUB_EVENT_START); + } + + /** + * Checks is this an end sub event. + * + * @return true if this is an "End" sub event, false otherwise. + */ + public boolean isEnd() + { + return isSubEvent(SUB_EVENT_END); + } + + private boolean isSubEvent(String subEvent) + { + return this.subEvent != null && this.subEvent.equalsIgnoreCase(subEvent); + } +} From 6d5f38a1c47f845774f7c57d8869bd25a3ea169c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 22 Aug 2016 15:41:46 +1000 Subject: [PATCH 042/802] add method to filter out specific manager events --- .../manager/DefaultManagerConnection.java | 44 +++++++----- .../manager/ManagerConnection.java | 69 ++++++++++--------- .../manager/internal/EventBuilder.java | 13 ++-- .../manager/internal/EventBuilderImpl.java | 28 ++++++++ .../internal/ManagerConnectionImpl.java | 13 ++++ .../manager/internal/ManagerReader.java | 16 +++-- .../manager/internal/ManagerReaderImpl.java | 9 +++ .../manager/internal/ManagerReaderMock.java | 15 ++-- 8 files changed, 143 insertions(+), 64 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java b/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java index 3cc02788a..732db2dc8 100644 --- a/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java @@ -24,6 +24,7 @@ import org.asteriskjava.manager.action.EventGeneratingAction; import org.asteriskjava.manager.action.ManagerAction; import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.internal.ManagerConnectionImpl; import org.asteriskjava.manager.response.ManagerResponse; @@ -170,7 +171,8 @@ public void setEncoding(Charset encoding) * @param defaultTimeout default timeout in milliseconds * @deprecated use {@link #setDefaultResponseTimeout(long)} instead */ - @Deprecated public void setDefaultTimeout(long defaultTimeout) + @Deprecated + public void setDefaultTimeout(long defaultTimeout) { impl.setDefaultResponseTimeout(defaultTimeout); } @@ -213,14 +215,15 @@ public void setDefaultEventTimeout(long defaultEventTimeout) * @deprecated no longer needed as we now use an interrupt based response * checking approach. */ - @Deprecated public void setSleepTime(long sleepTime) + @Deprecated + public void setSleepTime(long sleepTime) { } /** - * Set to true to try reconnecting to ther asterisk serve - * even if the reconnection attempt threw an AuthenticationFailedException. + * Set to true to try reconnecting to ther asterisk serve even + * if the reconnection attempt threw an AuthenticationFailedException. *

* Default is true. */ @@ -287,7 +290,7 @@ public int getRemotePort() return impl.getRemotePort(); } - public void registerUserEventClass(Class userEventClass) + public void registerUserEventClass(Class< ? extends ManagerEvent> userEventClass) { impl.registerUserEventClass(userEventClass); } @@ -307,8 +310,8 @@ public void login() throws IllegalStateException, IOException, AuthenticationFai impl.login(); } - public void login(String events) throws IllegalStateException, IOException, AuthenticationFailedException, - TimeoutException + public void login(String events) + throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException { impl.login(events); } @@ -318,32 +321,32 @@ public void logoff() throws IllegalStateException impl.logoff(); } - public ManagerResponse sendAction(ManagerAction action) throws IOException, TimeoutException, IllegalArgumentException, - IllegalStateException + public ManagerResponse sendAction(ManagerAction action) + throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException { return impl.sendAction(action); } - public ManagerResponse sendAction(ManagerAction action, long timeout) throws IOException, TimeoutException, - IllegalArgumentException, IllegalStateException + public ManagerResponse sendAction(ManagerAction action, long timeout) + throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException { return impl.sendAction(action, timeout); } - public void sendAction(ManagerAction action, SendActionCallback callbackHandler) throws IOException, - IllegalArgumentException, IllegalStateException + public void sendAction(ManagerAction action, SendActionCallback callbackHandler) + throws IOException, IllegalArgumentException, IllegalStateException { impl.sendAction(action, callbackHandler); } - public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws IOException, EventTimeoutException, - IllegalArgumentException, IllegalStateException + public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) + throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException { return impl.sendEventGeneratingAction(action); } - public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long timeout) throws IOException, - EventTimeoutException, IllegalArgumentException, IllegalStateException + public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long timeout) + throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException { return impl.sendEventGeneratingAction(action, timeout); } @@ -376,4 +379,11 @@ public String toString() sb.append("port=").append(getPort()).append("]"); return sb.toString(); } + + @Override + public void deregisterEventClass(Class eventClass) + { + impl.deregisterEventClass(eventClass); + + } } diff --git a/src/main/java/org/asteriskjava/manager/ManagerConnection.java b/src/main/java/org/asteriskjava/manager/ManagerConnection.java index fabbe06e7..9f094a3b7 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/ManagerConnection.java @@ -24,6 +24,7 @@ import org.asteriskjava.manager.action.EventGeneratingAction; import org.asteriskjava.manager.action.ManagerAction; import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.response.ManagerResponse; /** @@ -31,8 +32,8 @@ * API. *

* The ManagerConnection repesents a connection to an Asterisk server and is - * capable of sending {@link org.asteriskjava.manager.action.ManagerAction}s - * and receiving {@link org.asteriskjava.manager.response.ManagerResponse}s and + * capable of sending {@link org.asteriskjava.manager.action.ManagerAction}s and + * receiving {@link org.asteriskjava.manager.response.ManagerResponse}s and * {@link org.asteriskjava.manager.event.ManagerEvent}s. It does not add any * further functionality but rather provides a Java view to Asterisk's Manager * API (freeing you from TCP/IP connection and parsing stuff). @@ -92,8 +93,8 @@ public interface ManagerConnection AsteriskVersion getVersion(); /** - * Sets the encoding to use to connect to the Asterisk server (eg. important for manager/user events). - * All connections should use the same encoding. + * Sets the encoding to use to connect to the Asterisk server (eg. important + * for manager/user events). All connections should use the same encoding. * The default is UTF-8. * * @param encoding the encoding to use for manager/user events etc. @@ -101,9 +102,9 @@ public interface ManagerConnection void setEncoding(Charset encoding); /** - * Returns the encoding to use to connect to the Asterisk server (eg. important for manager/user events). - * All connections should use the same encoding. - * The default is UTF-8. + * Returns the encoding to use to connect to the Asterisk server (eg. + * important for manager/user events). All connections should use the same + * encoding. The default is UTF-8. * * @return the encoding to use for manager/user events etc. */ @@ -163,9 +164,9 @@ public interface ManagerConnection * registered event handlers. *

* Note: If you write your own Asterisk applications that use Asterisk's - * manager_event() function directly and don't use the - * channel and uniqueid attributes provided by UserEvent you can also - * register events that directly subclass {@link ManagerEvent}. + * manager_event() function directly and don't use the channel + * and uniqueid attributes provided by UserEvent you can also register + * events that directly subclass {@link ManagerEvent}. *

* The event class must be a concrete class with a default constructor (one * that takes no arguments). @@ -176,7 +177,7 @@ public interface ManagerConnection * @see org.asteriskjava.manager.event.UserEvent * @see ManagerEvent */ - void registerUserEventClass(Class userEventClass); + void registerUserEventClass(Class< ? extends ManagerEvent> userEventClass); /** * The timeout to use when connecting the the Asterisk server. @@ -284,8 +285,8 @@ public interface ManagerConnection * @see #sendAction(ManagerAction, long) * @see #sendAction(ManagerAction, SendActionCallback) */ - ManagerResponse sendAction(ManagerAction action) throws IOException, TimeoutException, IllegalArgumentException, - IllegalStateException; + ManagerResponse sendAction(ManagerAction action) + throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException; /** * Sends a ManagerAction to the Asterisk server and waits for the @@ -303,8 +304,8 @@ ManagerResponse sendAction(ManagerAction action) throws IOException, TimeoutExce * server. * @see #sendAction(ManagerAction, SendActionCallback) */ - ManagerResponse sendAction(ManagerAction action, long timeout) throws IOException, TimeoutException, - IllegalArgumentException, IllegalStateException; + ManagerResponse sendAction(ManagerAction action, long timeout) + throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException; /** * Sends a ManagerAction to the Asterisk server and registers a callback @@ -316,24 +317,24 @@ ManagerResponse sendAction(ManagerAction action, long timeout) throws IOExceptio * * @param action the action to send to the Asterisk server * @param callback the callback handler to call when the response is - * received or null if you are not interested in - * the response + * received or null if you are not interested in the + * response * @throws IOException if the network connection is disrupted. * @throws IllegalArgumentException if the action is null. * @throws IllegalStateException if you are not connected to the Asterisk * server. */ - void sendAction(ManagerAction action, SendActionCallback callback) throws IOException, IllegalArgumentException, - IllegalStateException; + void sendAction(ManagerAction action, SendActionCallback callback) + throws IOException, IllegalArgumentException, IllegalStateException; /** * Sends an {@link EventGeneratingAction} to the Asterisk server and waits * for the corresponding {@link ManagerResponse} and the * {@link org.asteriskjava.manager.event.ResponseEvent}s *

- * EventGeneratingActions are {@link ManagerAction}s that don't return - * their response in the corresponding {@link ManagerResponse} but send a - * series of events that contain the payload. + * EventGeneratingActions are {@link ManagerAction}s that don't return their + * response in the corresponding {@link ManagerResponse} but send a series + * of events that contain the payload. *

* This method will block until the correpsonding action complete event has * been received. The action complete event is determined by @@ -350,8 +351,8 @@ void sendAction(ManagerAction action, SendActionCallback callback) throws IOExce * @throws IOException if the network connection is disrupted. * @throws EventTimeoutException if no response or not all response events * are received within the given timeout period. - * @throws IllegalArgumentException if the action is null, - * the actionCompleteEventClass property of the action is + * @throws IllegalArgumentException if the action is null, the + * actionCompleteEventClass property of the action is * null or if actionCompleteEventClass is not a * ResponseEvent. * @throws IllegalStateException if you are not connected to an Asterisk @@ -360,17 +361,17 @@ void sendAction(ManagerAction action, SendActionCallback callback) throws IOExce * @see org.asteriskjava.manager.event.ResponseEvent * @since 0.2 */ - ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws IOException, EventTimeoutException, - IllegalArgumentException, IllegalStateException; + ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) + throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException; /** * Sends an {@link EventGeneratingAction} to the Asterisk server and waits * for the corresponding {@link ManagerResponse} and the * {@link org.asteriskjava.manager.event.ResponseEvent}s *

- * EventGeneratingActions are {@link ManagerAction}s that don't return - * their response in the corresponding {@link ManagerResponse} but send a - * series of events that contain the payload. + * EventGeneratingActions are {@link ManagerAction}s that don't return their + * response in the corresponding {@link ManagerResponse} but send a series + * of events that contain the payload. *

* This method will block until the correpsonding action complete event has * been received but no longer that timeout seconds. The action complete @@ -390,8 +391,8 @@ ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws IO * @throws IOException if the network connection is disrupted. * @throws EventTimeoutException if no response or not all response events * are received within the given timeout period. - * @throws IllegalArgumentException if the action is null, - * the actionCompleteEventClass property of the action is + * @throws IllegalArgumentException if the action is null, the + * actionCompleteEventClass property of the action is * null or if actionCompleteEventClass is not a * ResponseEvent. * @throws IllegalStateException if you are not connected to an Asterisk @@ -400,8 +401,8 @@ ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws IO * @see org.asteriskjava.manager.event.ResponseEvent * @since 0.2 */ - ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long timeout) throws IOException, - EventTimeoutException, IllegalArgumentException, IllegalStateException; + ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long timeout) + throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException; /** * Registers an event listener that is called whenever an @@ -426,4 +427,6 @@ ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long time * @see #addEventListener(ManagerEventListener) */ void removeEventListener(ManagerEventListener eventListener); + + void deregisterEventClass(Class eventClass); } diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java index 5db83f9c9..73bf30171 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java @@ -19,7 +19,7 @@ import java.util.Map; import org.asteriskjava.manager.event.ManagerEvent; - +import org.asteriskjava.manager.event.NewExtenEvent; /** * Transforms maps of attributes to instances of ManagerEvent. @@ -37,13 +37,14 @@ interface EventBuilder * org.asteriskjava.manager.event.JoinEvent is registered for * the event "Join". *

- * The event class must be a concrete class with a default constructor - * (one that takes no arguments). + * The event class must be a concrete class with a default constructor (one + * that takes no arguments). * - * @param clazz the event class to register, must extend {@link ManagerEvent}. + * @param clazz the event class to register, must extend + * {@link ManagerEvent}. * @throws IllegalArgumentException if clazz is not a valid event class */ - void registerEventClass(Class clazz) throws IllegalArgumentException; + void registerEventClass(Class< ? extends ManagerEvent> clazz) throws IllegalArgumentException; /** * Builds the event based on the given map of attributes and the registered @@ -55,4 +56,6 @@ interface EventBuilder * event class was registered for the event type. */ ManagerEvent buildEvent(Object source, Map attributes); + + void deregisterEventClass(Class eventClass); } diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index 9a26a4034..3573494f3 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import org.asteriskjava.manager.event.*; @@ -451,4 +452,31 @@ else if (value instanceof String && !"listitems".equals(key)) return event; } + + @Override + public void deregisterEventClass(Class eventClass) + { + + Set toRemove = new HashSet<>(); + for (Entry> registered : registeredEventClasses.entrySet()) + { + if (registered.getValue().equals(eventClass)) + { + toRemove.add(registered.getKey()); + } + } + if (toRemove.isEmpty()) + { + logger.error("Couldn't remove event type " + eventClass); + } + else + { + for (String key : toRemove) + { + registeredEventClasses.remove(key); + logger.warn("Removed event type " + key); + } + } + + } } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 2ad3d465d..f1ddc8d75 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -61,6 +61,7 @@ import org.asteriskjava.manager.event.DialEvent; import org.asteriskjava.manager.event.DisconnectEvent; import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.event.ProtocolIdentifierReceivedEvent; import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.manager.response.ChallengeResponse; @@ -1637,4 +1638,16 @@ private static class ProtocolIdentifierWrapper { String value; } + + @Override + public void deregisterEventClass(Class eventClass) + { + if (reader == null) + { + reader = createReader(this, this); + } + + reader.deregisterEventClass(eventClass); + + } } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java index fac94df34..dd07d0a62 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java @@ -19,13 +19,15 @@ import java.io.IOException; import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.SocketConnectionFacade; /** * The ManagerReader reads events and responses from the asterisk server, parses * them using EventBuilderImpl and ResponseBuilder and dispatches them to the - * associated ManagerConnection.

+ * associated ManagerConnection. + *

* Do not use this interface in your code, it is intended to be used only by the * DefaultManagerConnection. * @@ -47,16 +49,17 @@ public interface ManagerReader extends Runnable void setSocket(final SocketConnectionFacade socket); /** - * Registers a new event type with the underlying EventBuilderImpl.

+ * Registers a new event type with the underlying EventBuilderImpl. + *

* The eventClass must extend ManagerEvent. * * @param event class of the event to register. * @see EventBuilder * @see ManagerEvent */ - void registerEventClass(Class event); + void registerEventClass(Class< ? extends ManagerEvent> event); - void expectResponseClass(String internalActionId, Class responseClass); + void expectResponseClass(String internalActionId, Class< ? extends ManagerResponse> responseClass); /** * Terminates this reader. @@ -74,7 +77,10 @@ public interface ManagerReader extends Runnable /** * Returns the Exception that caused this reader to terminate if any. * - * @return the Exception that caused this reader to terminate if any or null if not. + * @return the Exception that caused this reader to terminate if any or + * null if not. */ IOException getTerminationException(); + + void deregisterEventClass(Class eventClass); } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java index 42c6fda16..ed5514059 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java @@ -26,6 +26,7 @@ import org.asteriskjava.manager.event.DisconnectEvent; import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.event.ProtocolIdentifierReceivedEvent; import org.asteriskjava.manager.internal.backwardsCompatibility.BackwardsCompatibilityForManagerEvents; import org.asteriskjava.manager.response.ManagerResponse; @@ -385,4 +386,12 @@ private ManagerEvent buildEvent(Object source, Map buffer) return event; } + + @Override + public void deregisterEventClass(Class eventClass) + { + + eventBuilder.deregisterEventClass(eventClass); + + } } diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java index b10c2bcff..20cfe5bbe 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java @@ -19,6 +19,7 @@ import java.io.IOException; import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.SocketConnectionFacade; @@ -33,7 +34,7 @@ public ManagerReaderMock() } - public void registerEventClass(Class event) + public void registerEventClass(Class< ? extends ManagerEvent> event) { throw new UnsupportedOperationException(); } @@ -43,9 +44,9 @@ public void setSocket(SocketConnectionFacade socket) setSocketCalls++; } - public void expectResponseClass(String actionId, Class responseClass) + public void expectResponseClass(String actionId, Class< ? extends ManagerResponse> responseClass) { - + } public void die() @@ -57,7 +58,7 @@ public boolean isDead() { return false; } - + public void run() { runCalls++; @@ -67,4 +68,10 @@ public IOException getTerminationException() { return null; } + + @Override + public void deregisterEventClass(Class eventClass) + { + + } } From b0ff4f3ae253bb93e8b8e2b106c6b51bf7421d62 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 24 Aug 2016 14:44:33 +1000 Subject: [PATCH 043/802] add isDebugEnabled to Log interface suppress logging of received manager events when leven isn't debug --- .../manager/internal/ManagerConnectionImpl.java | 10 ++++++++-- src/main/java/org/asteriskjava/util/Log.java | 10 +++++++++- .../util/internal/JavaLoggingLog.java | 12 +++++++++--- .../org/asteriskjava/util/internal/NullLog.java | 16 +++++++++++----- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index f1ddc8d75..6a14127b0 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1175,7 +1175,10 @@ public void dispatchResponse(ManagerResponse response) response.setActionId(ManagerUtil.stripInternalActionId(actionId)); } - logger.debug("Dispatching response with internalActionId '" + internalActionId + "':\n" + response); + if (logger.isDebugEnabled()) + { + logger.debug("Dispatching response with internalActionId '" + internalActionId + "':\n" + response); + } if (internalActionId != null) { @@ -1231,7 +1234,10 @@ public void dispatchEvent(ManagerEvent event) return; } dispatchLegacyEventIfNeeded(event); - logger.debug("Dispatching event:\n" + event.toString()); + if (logger.isDebugEnabled()) + { + logger.debug("Dispatching event:\n" + event.toString()); + } // Some events need special treatment besides forwarding them to the // registered eventListeners (clients) diff --git a/src/main/java/org/asteriskjava/util/Log.java b/src/main/java/org/asteriskjava/util/Log.java index 468e5cae1..4c9ca4389 100644 --- a/src/main/java/org/asteriskjava/util/Log.java +++ b/src/main/java/org/asteriskjava/util/Log.java @@ -17,7 +17,8 @@ package org.asteriskjava.util; /** - * Main interface used for logging throughout Asterisk-Java.

+ * Main interface used for logging throughout Asterisk-Java. + *

* Concrete instances of this interface are obtained by calling * {@link org.asteriskjava.util.LogFactory#getLog(Class)}. * @@ -27,9 +28,16 @@ public interface Log { void debug(Object obj); + void info(Object obj); + void warn(Object obj); + void warn(Object obj, Throwable exception); + void error(Object obj); + void error(Object obj, Throwable exception); + + public boolean isDebugEnabled(); } diff --git a/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java b/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java index c1fdcb966..c1967132e 100644 --- a/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java +++ b/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java @@ -23,8 +23,8 @@ import org.asteriskjava.util.Log; /** - * Implementation of {@link Log} that maps to the Logger of - * the java.util.logging package. + * Implementation of {@link Log} that maps to the Logger of the + * java.util.logging package. *

* Kindly donated by Sun's Steve Drach. * @@ -43,7 +43,7 @@ public class JavaLoggingLog implements Log * * @param clazz the class to log for. */ - public JavaLoggingLog(Class clazz) + public JavaLoggingLog(Class< ? > clazz) { log = Logger.getLogger(clazz.getName()); } @@ -144,4 +144,10 @@ private StackTraceElement getInvokerSTE() return null; } + @Override + public boolean isDebugEnabled() + { + return log.isLoggable(Level.FINE); + } + } diff --git a/src/main/java/org/asteriskjava/util/internal/NullLog.java b/src/main/java/org/asteriskjava/util/internal/NullLog.java index acfdf21df..bf4d8f43c 100644 --- a/src/main/java/org/asteriskjava/util/internal/NullLog.java +++ b/src/main/java/org/asteriskjava/util/internal/NullLog.java @@ -19,10 +19,10 @@ import org.asteriskjava.util.Log; /** - * A Log implementation that does nothing.

- * This logger is only used if neither log4j nor java.util.logging are - * available which should not happen anyway as Asterisk-Java depends on - * at least JDK 1.5. + * A Log implementation that does nothing. + *

+ * This logger is only used if neither log4j nor java.util.logging are available + * which should not happen anyway as Asterisk-Java depends on at least JDK 1.5. * * @author srt * @version $Id$ @@ -59,4 +59,10 @@ public void error(Object obj) public void error(Object obj, Throwable ex) { } -} \ No newline at end of file + + @Override + public boolean isDebugEnabled() + { + return false; + } +} From 00802e4550d5ee0fa68491834121972cd459dcf1 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 24 Aug 2016 16:22:24 +1000 Subject: [PATCH 044/802] change method signature of deregisterEvent from NewExtenEvent to ManagerEvent --- .../org/asteriskjava/manager/DefaultManagerConnection.java | 3 +-- src/main/java/org/asteriskjava/manager/ManagerConnection.java | 3 +-- .../java/org/asteriskjava/manager/internal/EventBuilder.java | 3 +-- .../org/asteriskjava/manager/internal/EventBuilderImpl.java | 2 +- .../asteriskjava/manager/internal/ManagerConnectionImpl.java | 3 +-- .../java/org/asteriskjava/manager/internal/ManagerReader.java | 3 +-- .../org/asteriskjava/manager/internal/ManagerReaderImpl.java | 3 +-- .../org/asteriskjava/manager/internal/ManagerReaderMock.java | 3 +-- 8 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java b/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java index 732db2dc8..032ee340d 100644 --- a/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java @@ -24,7 +24,6 @@ import org.asteriskjava.manager.action.EventGeneratingAction; import org.asteriskjava.manager.action.ManagerAction; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.internal.ManagerConnectionImpl; import org.asteriskjava.manager.response.ManagerResponse; @@ -381,7 +380,7 @@ public String toString() } @Override - public void deregisterEventClass(Class eventClass) + public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) { impl.deregisterEventClass(eventClass); diff --git a/src/main/java/org/asteriskjava/manager/ManagerConnection.java b/src/main/java/org/asteriskjava/manager/ManagerConnection.java index 9f094a3b7..8c6e613ce 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/ManagerConnection.java @@ -24,7 +24,6 @@ import org.asteriskjava.manager.action.EventGeneratingAction; import org.asteriskjava.manager.action.ManagerAction; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.response.ManagerResponse; /** @@ -428,5 +427,5 @@ ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long time */ void removeEventListener(ManagerEventListener eventListener); - void deregisterEventClass(Class eventClass); + void deregisterEventClass(Class< ? extends ManagerEvent> eventClass); } diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java index 73bf30171..8f1bfdc50 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java @@ -19,7 +19,6 @@ import java.util.Map; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.NewExtenEvent; /** * Transforms maps of attributes to instances of ManagerEvent. @@ -57,5 +56,5 @@ interface EventBuilder */ ManagerEvent buildEvent(Object source, Map attributes); - void deregisterEventClass(Class eventClass); + void deregisterEventClass(Class< ? extends ManagerEvent> eventClass); } diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index 3573494f3..51561966d 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -454,7 +454,7 @@ else if (value instanceof String && !"listitems".equals(key)) } @Override - public void deregisterEventClass(Class eventClass) + public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) { Set toRemove = new HashSet<>(); diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 6a14127b0..ea5034806 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -61,7 +61,6 @@ import org.asteriskjava.manager.event.DialEvent; import org.asteriskjava.manager.event.DisconnectEvent; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.event.ProtocolIdentifierReceivedEvent; import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.manager.response.ChallengeResponse; @@ -1646,7 +1645,7 @@ private static class ProtocolIdentifierWrapper } @Override - public void deregisterEventClass(Class eventClass) + public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) { if (reader == null) { diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java index dd07d0a62..4fe566ccd 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java @@ -19,7 +19,6 @@ import java.io.IOException; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.SocketConnectionFacade; @@ -82,5 +81,5 @@ public interface ManagerReader extends Runnable */ IOException getTerminationException(); - void deregisterEventClass(Class eventClass); + void deregisterEventClass(Class< ? extends ManagerEvent> eventClass); } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java index ed5514059..abb1a6c0e 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java @@ -26,7 +26,6 @@ import org.asteriskjava.manager.event.DisconnectEvent; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.event.ProtocolIdentifierReceivedEvent; import org.asteriskjava.manager.internal.backwardsCompatibility.BackwardsCompatibilityForManagerEvents; import org.asteriskjava.manager.response.ManagerResponse; @@ -388,7 +387,7 @@ private ManagerEvent buildEvent(Object source, Map buffer) } @Override - public void deregisterEventClass(Class eventClass) + public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) { eventBuilder.deregisterEventClass(eventClass); diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java index 20cfe5bbe..d3c8f0a0f 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java @@ -19,7 +19,6 @@ import java.io.IOException; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.SocketConnectionFacade; @@ -70,7 +69,7 @@ public IOException getTerminationException() } @Override - public void deregisterEventClass(Class eventClass) + public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) { } From e606ae4f955ab4c57f8e52bd7a1086706d40ade7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 13 Sep 2016 16:51:43 +1000 Subject: [PATCH 045/802] minor manager action fixes --- src/main/java/org/asteriskjava/Cli.java | 1 - .../fastagi/command/DialCommand.java | 3 +- .../fastagi/command/MeetmeCommand.java | 2 +- .../manager/action/RedirectAction.java | 77 +++++++++++-------- .../manager/event/ManagerEvent.java | 6 +- .../internal/SocketConnectionFacadeImpl.java | 1 - 6 files changed, 53 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/asteriskjava/Cli.java b/src/main/java/org/asteriskjava/Cli.java index d75cad3f8..82e49fcbd 100644 --- a/src/main/java/org/asteriskjava/Cli.java +++ b/src/main/java/org/asteriskjava/Cli.java @@ -82,7 +82,6 @@ private void showVersion() System.out.println("Asterisk-Java " + getVersion()); } - @SuppressWarnings("resource") private String getVersion() { String version = ""; diff --git a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java index 31a409932..d00ccdd63 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java @@ -28,7 +28,8 @@ public DialCommand(String target, int timeout, String options) @Override public String buildCommand() { - String command = "EXEC " + escapeAndQuote("dial") + " " + escapeAndQuote(target) + "," + + String command = "EXEC " + escapeAndQuote("dial") + " " + escapeAndQuote(target) + "|" + escapeAndQuote("" + timeout); if (options != null && options.length() > 0) { diff --git a/src/main/java/org/asteriskjava/fastagi/command/MeetmeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/MeetmeCommand.java index 8e254c71b..04024a28e 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/MeetmeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/MeetmeCommand.java @@ -25,7 +25,7 @@ public String buildCommand() String command = "EXEC " + escapeAndQuote("meetme") + " " + escapeAndQuote(room); if (options != null && options.length() > 0) { - command += " " + escapeAndQuote(options); + command += "|" + escapeAndQuote(options); } return command; diff --git a/src/main/java/org/asteriskjava/manager/action/RedirectAction.java b/src/main/java/org/asteriskjava/manager/action/RedirectAction.java index ea2cc5ebe..c67d86c0d 100644 --- a/src/main/java/org/asteriskjava/manager/action/RedirectAction.java +++ b/src/main/java/org/asteriskjava/manager/action/RedirectAction.java @@ -18,15 +18,17 @@ /** * Redirects a given channel (and an optional additional channel) to a new - * extension.

+ * extension. + *

* The additional channel is usually used when redirecting two bridged channel - * for example to a MeetMe room.

- * Note that BRIstuffed versions of Asterisk behave slightly different: - * While the standard version only allows redirecting the two channels to the same - * context, extension, priority the BRIstuffed version uses context, extension, - * priority only for the first channel and extraContext, extraExtension, - * extraPriority for the second channel. The standard version ignores the - * extraContext, extraExtension, extraPriority properties. + * for example to a MeetMe room. + *

+ * Note that BRIstuffed versions of Asterisk behave slightly different: While + * the standard version only allows redirecting the two channels to the same + * context, extension, priority the BRIstuffed version uses context, extension, + * priority only for the first channel and extraContext, extraExtension, + * extraPriority for the second channel. The standard version ignores the + * extraContext, extraExtension, extraPriority properties. * * @author srt * @version $Id$ @@ -65,8 +67,7 @@ public RedirectAction() * @param priority the destination priority * @since 0.2 */ - public RedirectAction(String channel, String context, String exten, - Integer priority) + public RedirectAction(String channel, String context, String exten, Integer priority) { this.channel = channel; this.context = context; @@ -76,11 +77,12 @@ public RedirectAction(String channel, String context, String exten, /** * Creates a new RedirectAction that redirects the given channels to the - * given context, extension, priority triple.

- * This constructor only works standard versions of Asterisk, i.e. non-BRIstuffed - * versions. - * When used with a BRIstuffed version (and not setting extraContext, extraExten and - * extraPriority) the second channel is just hung up. + * given context, extension, priority triple. + *

+ * This constructor only works standard versions of Asterisk, i.e. + * non-BRIstuffed versions. When used with a BRIstuffed version (and not + * setting extraContext, extraExten and extraPriority) the second channel is + * just hung up. * * @param channel the name of the first channel to redirect * @param extraChannel the name of the second channel to redirect @@ -89,8 +91,7 @@ public RedirectAction(String channel, String context, String exten, * @param priority the destination priority * @since 0.2 */ - public RedirectAction(String channel, String extraChannel, String context, - String exten, Integer priority) + public RedirectAction(String channel, String extraChannel, String context, String exten, Integer priority) { this.channel = channel; this.extraChannel = extraChannel; @@ -101,10 +102,11 @@ public RedirectAction(String channel, String extraChannel, String context, /** * Creates a new RedirectAction that redirects the given channels to the - * given context, extension, priority triples.

- * This constructor works for BRIstuffed versions of Asterisk, if used - * with a standard version the extraContext, extraExten and - * extraPriroity attributes are ignored. + * given context, extension, priority triples. + *

+ * This constructor works for BRIstuffed versions of Asterisk, if used with + * a standard version the extraContext, extraExten and extraPriroity + * attributes are ignored. * * @param channel the name of the first channel to redirect * @param extraChannel the name of the second channel to redirect @@ -116,9 +118,8 @@ public RedirectAction(String channel, String extraChannel, String context, * @param extraPriority the destination priority for the second channel * @since 0.3 */ - public RedirectAction(String channel, String extraChannel, String context, - String exten, Integer priority, String extraContext, - String extraExten, Integer extraPriority) + public RedirectAction(String channel, String extraChannel, String context, String exten, Integer priority, + String extraContext, String extraExten, Integer extraPriority) { this.channel = channel; this.extraChannel = extraChannel; @@ -128,13 +129,17 @@ public RedirectAction(String channel, String extraChannel, String context, this.extraContext = extraContext; this.extraExten = extraExten; this.extraPriority = extraPriority; + if (channel.equalsIgnoreCase(extraChannel)) + { + throw new RuntimeException("ExtraChannel = channel ... bad things will happen to asterisk"); + } } /** * Returns the name of this action, i.e. "Redirect". */ @Override - public String getAction() + public String getAction() { return "Redirect"; } @@ -177,6 +182,10 @@ public String getExtraChannel() public void setExtraChannel(String extraChannel) { this.extraChannel = extraChannel; + if (channel.equalsIgnoreCase(extraChannel)) + { + throw new RuntimeException("ExtraChannel = channel ... bad things will happen to asterisk"); + } } /** @@ -240,7 +249,8 @@ public void setPriority(Integer priority) } /** - * Returns the destination context for the additional channel.

+ * Returns the destination context for the additional channel. + *

* This property is only used by BRIstuffed Asterisk servers. * * @return the destination context for the additional channel. @@ -251,7 +261,8 @@ public String getExtraContext() } /** - * Sets the destination context for the additional channel.

+ * Sets the destination context for the additional channel. + *

* This property is only used by BRIstuffed Asterisk servers. * * @param extraContext the destination context for the additional channel. @@ -262,7 +273,8 @@ public void setExtraContext(String extraContext) } /** - * Sets the destination extension for the additional channel.

+ * Sets the destination extension for the additional channel. + *

* This property is only used by BRIstuffed Asterisk servers. * * @return the destination extension for the additional channel. @@ -273,7 +285,8 @@ public String getExtraExten() } /** - * Sets the destination extension for the additional channel.

+ * Sets the destination extension for the additional channel. + *

* This property is only used by BRIstuffed Asterisk servers. * * @param extraExten the destination extension for the additional channel. @@ -284,7 +297,8 @@ public void setExtraExten(String extraExten) } /** - * Returns the destination priority for the additional channel.

+ * Returns the destination priority for the additional channel. + *

* This property is only used by BRIstuffed Asterisk servers. * * @return the destination priority for the additional channel. @@ -295,7 +309,8 @@ public Integer getExtraPriority() } /** - * Sets the destination priority for the additional channel.

+ * Sets the destination priority for the additional channel. + *

* This property is only used by BRIstuffed Asterisk servers. * * @param extraPriority the destination priority for the additional channel. diff --git a/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java b/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java index 19938d973..3fa1af486 100644 --- a/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java @@ -230,8 +230,10 @@ public void setPrivilege(String privilege) /** * Returns the timestamp for this event.
* The timestamp property is available in Asterisk since 1.4 if enabled in - * manager.conf by setting timestampevents = yes.
- * In contains the time the event was generated in seconds since the epoch.
+ * manager.conf by setting timestampevents = yes. + *
+ * In contains the time the event was generated in seconds since the epoch. + *
* Example: 1159310429.569108 * * @return the timestamp for this event. diff --git a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java index dc8f82c6d..a08ba44f1 100644 --- a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java +++ b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java @@ -123,7 +123,6 @@ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeou * for the socket * @throws IOException if the connection cannot be established. */ - @SuppressWarnings("resource") public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeout, int readTimeout, Charset encoding, Pattern lineDelimiter) throws IOException { From 684be6fdf034940056026dc0bcba2f8f55bcbfc8 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 27 Sep 2016 12:50:20 +1000 Subject: [PATCH 046/802] add warning when setting very short originate timeouts --- .../manager/action/OriginateAction.java | 120 +++++++++++++----- 1 file changed, 89 insertions(+), 31 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java index 1267d9b5d..d5a4b1f2e 100644 --- a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java +++ b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java @@ -24,20 +24,24 @@ import org.asteriskjava.manager.event.OriginateResponseEvent; import org.asteriskjava.manager.event.ResponseEvent; - +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * The OriginateAction generates an outgoing call to the extension in the given * context with the given priority or to a given application with optional - * parameters.

+ * parameters. + *

* If you want to connect to an extension use the properties context, exten and * priority. If you want to connect to an application use the properties * application and data if needed. Note that no call detail record will be * written when directly connecting to an application, so it may be better to - * connect to an extension that starts the application you wish to connect to.

+ * connect to an extension that starts the application you wish to connect to. + *

* The response to this action is sent when the channel has been answered and * asterisk starts connecting it to the given extension. So be careful not to - * choose a too short timeout when waiting for the response.

+ * choose a too short timeout when waiting for the response. + *

* If you set async to true Asterisk reports an OriginateSuccess- * and OriginateFailureEvents. The action id of these events equals the action * id of this OriginateAction. @@ -48,6 +52,9 @@ */ public class OriginateAction extends AbstractManagerAction implements EventGeneratingAction { + + private final Log logger = LogFactory.getLog(getClass()); + /** * Serializable version identifier */ @@ -89,7 +96,8 @@ public String getAccount() } /** - * Sets the account code to use for the originated call.

+ * Sets the account code to use for the originated call. + *

* The account code is included in the call detail record generated for this * call and will be used for billing. * @@ -109,7 +117,8 @@ public String getCallerId() } /** - * Sets the caller id to set on the outgoing channel.

+ * Sets the caller id to set on the outgoing channel. + *

* This includes both the Caller*Id Number and Caller*Id Name in the form * "Jon Doe <1234>". * @@ -121,7 +130,8 @@ public void setCallerId(String callerId) } /** - * Returns the calling presentation for the outgoing channel.

+ * Returns the calling presentation for the outgoing channel. + *

* This property is only available on BRIstuffed Asterisk servers. * * @return the calling presentation for the outgoing channel. @@ -133,15 +143,21 @@ public Integer getCallingPres() } /** - * Sets the calling presentation for the outgoing channel.

- * The number is an octet and the only bits you need worry about are bits 1,2,6 and 7.

+ * Sets the calling presentation for the outgoing channel. + *

+ * The number is an octet and the only bits you need worry about are bits + * 1,2,6 and 7. + *

* Bits 1 and 2 define the screening indicator and bits 6 and 7 define the - * presentation indicator.

- * In essence, it says, 'Is the person who has been called allowed to see the callers number?' - * (presentation) and 'What authority was used to verify that this is a genuine number?' - * (screening).

+ * presentation indicator. + *

+ * In essence, it says, 'Is the person who has been called allowed to see + * the callers number?' (presentation) and 'What authority was used to + * verify that this is a genuine number?' (screening). + *

*
* Presentation indicator (Bits 6 and 7): + * *

      * Bits Meaning
      *  7 6
@@ -150,7 +166,9 @@ public Integer getCallingPres()
      *  1 0 Number not available due to interworking
      *  1 1 Reserved
      * 
+ * * Screening indicator (Bits 1 and 2): + * *
      * Bits Meaning
      *  2 1
@@ -159,13 +177,16 @@ public Integer getCallingPres()
      *  1 0 User-provided, verified and failed
      *  1 1 Network provided
      * 
+ * * Examples for some general settings: + * *
      * Presentation Allowed, Network Provided: 3 (00000011)
      * Presentation Restricted, User-provided, not screened: 32 (00100000)
      * Presentation Restricted, User-provided, verified, and passed: 33 (00100001)
      * Presentation Restricted, Network Provided: 35 (00100011)
      * 
+ * * This property is only available on BRIstuffed Asterisk servers. * * @param callingPres the calling presentation for the outgoing channel. @@ -184,7 +205,8 @@ public String getChannel() } /** - * Sets the name of the channel to connect to the outgoing call.

+ * Sets the name of the channel to connect to the outgoing call. + *

* This property is mandatory. */ public void setChannel(String channel) @@ -201,7 +223,8 @@ public String getContext() } /** - * Sets the name of the context of the extension to connect to.

+ * Sets the name of the context of the extension to connect to. + *

* If you set the context you also have to set the exten and priority * properties. */ @@ -219,7 +242,8 @@ public String getExten() } /** - * Sets the extension to connect to.

+ * Sets the extension to connect to. + *

* If you set the extension you also have to set the context and priority * properties. */ @@ -286,42 +310,74 @@ public Long getTimeout() } /** - * Sets the timeout (in milliseconds) for the origination.

+ * Sets the timeout (in milliseconds) for the origination. + *

* The channel must be answered within this time, otherwise the origination - * is considered to have failed and an OriginateFailureEvent is generated.

+ * is considered to have failed and an OriginateFailureEvent is generated. + *

* If not set, Asterisk assumes a default value of 30000 meaning 30 seconds. * * @param timeout the timeout in milliseconds * @deprecated use {@link #setTimeout(Long)} instead. */ - @Deprecated public void setTimeout(Integer timeout) + @Deprecated + public void setTimeout(Integer timeout) { + if (timeout != null) + { + if (timeout < 1000) + { + logger.error("A timeout of 1000 will cause the originate to almost cretainly fail!"); + } + if (timeout < 10000) + { + logger.warn( + "A timeout of less than 100000 will cause the originate to fail if not answered within 10 seconds!"); + } + } this.timeout = timeout.longValue(); } /** - * Sets the timeout (in milliseconds) for the origination.

+ * Sets the timeout (in milliseconds) for the origination. + *

* The channel must be answered within this time, otherwise the origination - * is considered to have failed and an OriginateFailureEvent is generated.

+ * is considered to have failed and an OriginateFailureEvent is generated. + *

* If not set, Asterisk assumes a default value of 30000 meaning 30 seconds. * * @param timeout the timeout in milliseconds */ public void setTimeout(Long timeout) { + if (timeout != null) + { + if (timeout < 1000) + { + logger.error("A timeout of 1000 will cause the originate to almost cretainly fail!"); + } + if (timeout < 10000) + { + logger.warn( + "A timeout of less than 100000 will cause the originate to fail if not answered within 10 seconds!"); + } + } this.timeout = timeout; } /** - * Sets the variables to set on the originated call.

+ * Sets the variables to set on the originated call. + *

* Variable assignments are of the form "VARNAME=VALUE". You can specify - * multiple variable assignments separated by the '|' character.

+ * multiple variable assignments separated by the '|' character. + *

* Example: "VAR1=abc|VAR2=def" sets the channel variables VAR1 to "abc" and * VAR2 to "def". * * @deprecated use {@link #setVariables(Map)} instead. */ - @Deprecated public void setVariable(String variable) + @Deprecated + public void setVariable(String variable) { final StringTokenizer st; @@ -352,7 +408,7 @@ public void setTimeout(Long timeout) /** * Sets an variable on the originated call. * - * @param name the name of the variable to set. + * @param name the name of the variable to set. * @param value the value of the variable to set. * @since 0.3 */ @@ -369,8 +425,8 @@ public void setVariable(String name, String value) /** * Returns the variables to set on the originated call. * - * @return a Map containing the variable names as key and their - * values as value. + * @return a Map containing the variable names as key and their values as + * value. * @since 0.2 */ public Map getVariables() @@ -382,7 +438,7 @@ public Map getVariables() * Sets the variables to set on the originated call. * * @param variables a Map containing the variable names as key and their - * values as value. + * values as value. * @since 0.2 */ public void setVariables(Map variables) @@ -419,7 +475,8 @@ public String getCodecs() } /** - * Sets the codecs to use for the call. For example "alaw, ulaw, h264".

+ * Sets the codecs to use for the call. For example "alaw, ulaw, h264". + *

* Available since Asterisk 1.6. * * @param codecs comma separated list of codecs to use for the call. @@ -431,7 +488,8 @@ public void setCodecs(String codecs) } /** - * Sets the codecs to use for the call.

+ * Sets the codecs to use for the call. + *

* Available since Asterisk 1.6. * * @param codecs list of codecs to use for the call. @@ -454,7 +512,7 @@ public void setCodecs(List codecs) this.codecs = buffer.toString(); } - public Class getActionCompleteEventClass() + public Class< ? extends ResponseEvent> getActionCompleteEventClass() { return OriginateResponseEvent.class; } From 49d4ad04310dcb9ef7cc97baa0ba44d2ecfd3a79 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 6 Oct 2016 10:18:28 +1100 Subject: [PATCH 047/802] fix broken assignment of property value --- .../java/org/asteriskjava/manager/event/PeerEntryEvent.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java index a2b749d19..0e8b9b64e 100644 --- a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java @@ -427,12 +427,9 @@ public String getAccountcode() /** * @param the accountcode to set */ - public void setAccountcode(String description) + public void setAccountcode(String accountcode) { this.accountcode = accountcode; } - - - } From 3becc75322344d5e182495815ef88d7af0638639 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Oct 2016 16:47:49 +1100 Subject: [PATCH 048/802] added PBX abstraction --- .../manager/action/OriginateAction.java | 8 +- .../manager/response/SipShowPeerResponse.java | 4 +- .../java/org/asteriskjava/pbx/Activity.java | 21 + .../asteriskjava/pbx/ActivityCallback.java | 39 + src/main/java/org/asteriskjava/pbx/Call.java | 98 ++ .../org/asteriskjava/pbx/CallDirection.java | 56 ++ .../asteriskjava/pbx/CallHangupListener.java | 8 + .../java/org/asteriskjava/pbx/CallImpl.java | 894 ++++++++++++++++++ .../asteriskjava/pbx/CallStateAnswered.java | 23 + .../org/asteriskjava/pbx/CallStateData.java | 9 + .../pbx/CallStateDataNewInbound.java | 29 + .../asteriskjava/pbx/CallStateDataParked.java | 17 + .../pbx/CallStateDataTransfer.java | 50 + .../org/asteriskjava/pbx/CallbackAdaptor.java | 24 + .../java/org/asteriskjava/pbx/CallerID.java | 40 + .../java/org/asteriskjava/pbx/Channel.java | 190 ++++ .../org/asteriskjava/pbx/ChannelFactory.java | 23 + .../pbx/ChannelHangupListener.java | 13 + .../asteriskjava/pbx/CompletionAdaptor.java | 50 + .../java/org/asteriskjava/pbx/DTMFTone.java | 27 + .../java/org/asteriskjava/pbx/EndPoint.java | 71 ++ .../asteriskjava/pbx/NewChannelListener.java | 24 + .../pbx/NewExtensionListener.java | 15 + src/main/java/org/asteriskjava/pbx/PBX.java | 307 ++++++ .../org/asteriskjava/pbx/PBXException.java | 25 + .../java/org/asteriskjava/pbx/PBXFactory.java | 14 + .../org/asteriskjava/pbx/PhoneNumber.java | 18 + src/main/java/org/asteriskjava/pbx/Tech.java | 6 + src/main/java/org/asteriskjava/pbx/Trunk.java | 10 + .../pbx/activities/ActivityHelper.java | 153 +++ .../pbx/activities/BlindTransferActivity.java | 64 ++ .../activities/BlindTransferActivityImpl.java | 308 ++++++ .../pbx/activities/BridgeActivity.java | 8 + .../pbx/activities/BridgeActivityImpl.java | 163 ++++ .../pbx/activities/DialActivity.java | 49 + .../pbx/activities/DialActivityImpl.java | 273 ++++++ .../pbx/activities/DialToAgiActivity.java | 18 + .../pbx/activities/DialToAgiActivityImpl.java | 225 +++++ .../pbx/activities/HoldActivity.java | 8 + .../pbx/activities/HoldActivityImpl.java | 81 ++ .../pbx/activities/JoinActivity.java | 10 + .../pbx/activities/JoinActivityImpl.java | 175 ++++ .../pbx/activities/ParkActivity.java | 16 + .../pbx/activities/ParkActivityImpl.java | 186 ++++ .../pbx/activities/SplitActivity.java | 32 + .../pbx/activities/SplitActivityImpl.java | 260 +++++ .../pbx/internal/agi/ActivityAgi.java | 107 +++ .../agi/AgiChannelActivityAction.java | 16 + .../agi/AgiChannelActivityBlindTransfer.java | 49 + .../agi/AgiChannelActivityBridge.java | 63 ++ .../internal/agi/AgiChannelActivityDial.java | 57 ++ .../agi/AgiChannelActivityHangup.java | 46 + .../internal/agi/AgiChannelActivityHold.java | 65 ++ .../agi/AgiChannelActivityHoldForBridge.java | 50 + .../agi/AgiChannelActivityMeetme.java | 98 ++ .../internal/agi/AgiChannelActivityQueue.java | 89 ++ .../agi/AgiChannelActivityVoicemail.java | 36 + .../pbx/internal/agi/NJAgiScript.java | 49 + .../pbx/internal/agi/RateLimiter.java | 38 + .../internal/asterisk/AsteriskSettings.java | 30 + .../pbx/internal/asterisk/CallerIDImpl.java | 125 +++ .../internal/asterisk/InvalidChannelName.java | 12 + .../pbx/internal/asterisk/MeetmeRoom.java | 184 ++++ .../internal/asterisk/MeetmeRoomControl.java | 410 ++++++++ .../internal/asterisk/NoMeetmeException.java | 12 + .../internal/asterisk/PBXSettingsManager.java | 28 + .../wrap/actions/AbstractManagerAction.java | 38 + .../asterisk/wrap/actions/BridgeAction.java | 31 + .../asterisk/wrap/actions/CommandAction.java | 32 + .../wrap/actions/ConfbridgeListAction.java | 22 + .../asterisk/wrap/actions/DbGetAction.java | 33 + .../wrap/actions/EventGeneratingAction.java | 8 + .../asterisk/wrap/actions/GetVarAction.java | 33 + .../asterisk/wrap/actions/HangupAction.java | 37 + .../wrap/actions/ListCommandsAction.java | 24 + .../asterisk/wrap/actions/ManagerAction.java | 9 + .../asterisk/wrap/actions/MonitorAction.java | 36 + .../wrap/actions/OriginateAction.java | 142 +++ .../asterisk/wrap/actions/PingAction.java | 23 + .../asterisk/wrap/actions/PlayDtmfAction.java | 35 + .../asterisk/wrap/actions/RedirectAction.java | 87 ++ .../asterisk/wrap/actions/SetVarAction.java | 42 + .../asterisk/wrap/actions/SipPeersAction.java | 29 + .../wrap/actions/SipShowPeerAction.java | 30 + .../asterisk/wrap/actions/StatusAction.java | 54 ++ .../wrap/actions/UserEventAction.java | 28 + .../events/AbstractChannelStateEvent.java | 36 + .../wrap/events/AbstractMeetMeEvent.java | 34 + .../wrap/events/AbstractParkedCallEvent.java | 34 + .../wrap/events/AgentCalledEvent.java | 36 + .../wrap/events/AgentConnectEvent.java | 36 + .../asterisk/wrap/events/BridgeEvent.java | 78 ++ .../asterisk/wrap/events/ChannelEvent.java | 9 + .../asterisk/wrap/events/ChannelState.java | 42 + .../events/ConfbridgeListCompleteEvent.java | 12 + .../wrap/events/ConfbridgeListEvent.java | 26 + .../asterisk/wrap/events/ConnectEvent.java | 28 + .../wrap/events/DbGetResponseEvent.java | 39 + .../asterisk/wrap/events/DialEvent.java | 55 ++ .../asterisk/wrap/events/DisconnectEvent.java | 15 + .../asterisk/wrap/events/DndStateEvent.java | 45 + .../wrap/events/ExtensionStatusEvent.java | 95 ++ .../asterisk/wrap/events/HangupEvent.java | 62 ++ .../asterisk/wrap/events/LinkEvent.java | 17 + .../asterisk/wrap/events/ManagerEvent.java | 19 + .../asterisk/wrap/events/MasqueradeEvent.java | 194 ++++ .../asterisk/wrap/events/MeetMeJoinEvent.java | 32 + .../wrap/events/MeetMeLeaveEvent.java | 39 + .../asterisk/wrap/events/NewChannelEvent.java | 45 + .../asterisk/wrap/events/NewExtenEvent.java | 67 ++ .../asterisk/wrap/events/NewStateEvent.java | 28 + .../wrap/events/OriginateResponseEvent.java | 101 ++ .../asterisk/wrap/events/ParkedCallEvent.java | 55 ++ .../asterisk/wrap/events/PeerEntryEvent.java | 30 + .../asterisk/wrap/events/PeerStatusEvent.java | 31 + .../wrap/events/PeerlistCompleteEvent.java | 15 + .../wrap/events/QueueCallerLeaveEvent.java | 28 + .../asterisk/wrap/events/RenameEvent.java | 59 ++ .../asterisk/wrap/events/ResponseEvent.java | 32 + .../asterisk/wrap/events/ResponseEvents.java | 27 + .../wrap/events/StatusCompleteEvent.java | 15 + .../asterisk/wrap/events/StatusEvent.java | 115 +++ .../asterisk/wrap/events/UnlinkEvent.java | 17 + .../wrap/events/UnparkedCallEvent.java | 32 + .../asterisk/wrap/events/VarSetEvent.java | 50 + .../wrap/response/CommandResponse.java | 25 + .../asterisk/wrap/response/ManagerError.java | 16 + .../wrap/response/ManagerResponse.java | 86 ++ .../asterisk/wrap/userEvents/UserEvent.java | 37 + .../pbx/internal/core/ActiveCallListener.java | 17 + .../pbx/internal/core/AsteriskPBX.java | 867 +++++++++++++++++ .../pbx/internal/core/CallEndedListener.java | 15 + .../pbx/internal/core/CallTracker.java | 210 ++++ .../pbx/internal/core/ChannelEventHelper.java | 59 ++ .../pbx/internal/core/ChannelImpl.java | 841 ++++++++++++++++ .../pbx/internal/core/ChannelProxy.java | 389 ++++++++ .../internal/core/CoherentEventFactory.java | 261 +++++ .../core/CoherentManagerConnection.java | 631 ++++++++++++ .../core/CoherentManagerEventListener.java | 16 + .../core/CoherentManagerEventQueue.java | 322 +++++++ .../internal/core/DialLocalToAgiActivity.java | 243 +++++ .../pbx/internal/core/DialPlanExtension.java | 111 +++ .../pbx/internal/core/EndPointImpl.java | 229 +++++ .../core/FilteredManagerListener.java | 46 + .../pbx/internal/core/ListenerPriority.java | 35 + .../pbx/internal/core/LiveChannelManager.java | 311 ++++++ .../asteriskjava/pbx/internal/core/Peer.java | 328 +++++++ .../pbx/internal/core/PeerMonitor.java | 385 ++++++++ .../pbx/internal/core/PeerState.java | 111 +++ .../pbx/internal/core/TechType.java | 91 ++ .../internal/eventQueue/EventLifeMonitor.java | 38 + .../eventQueue/ManagerEventQueue.java | 131 +++ .../pbx/internal/managerAPI/Connector.java | 98 ++ .../pbx/internal/managerAPI/Dial.java | 175 ++++ .../pbx/internal/managerAPI/DialToAgi.java | 124 +++ .../managerAPI/EventListenerBaseClass.java | 89 ++ .../pbx/internal/managerAPI/HoldAtAgi.java | 70 ++ .../pbx/internal/managerAPI/MonitorCall.java | 55 ++ .../managerAPI/OriginateBaseClass.java | 579 ++++++++++++ .../internal/managerAPI/OriginateResult.java | 65 ++ .../managerAPI/OriginateToExtension.java | 77 ++ .../pbx/internal/managerAPI/RedirectCall.java | 75 ++ .../internal/managerAPI/RedirectToMeetMe.java | 51 + .../org/asteriskjava/pbx/util/LogTime.java | 22 + .../pbx/internal/agi/RateLimiterTest.java | 28 + 165 files changed, 15565 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/Activity.java create mode 100644 src/main/java/org/asteriskjava/pbx/ActivityCallback.java create mode 100644 src/main/java/org/asteriskjava/pbx/Call.java create mode 100644 src/main/java/org/asteriskjava/pbx/CallDirection.java create mode 100644 src/main/java/org/asteriskjava/pbx/CallHangupListener.java create mode 100644 src/main/java/org/asteriskjava/pbx/CallImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/CallStateAnswered.java create mode 100644 src/main/java/org/asteriskjava/pbx/CallStateData.java create mode 100644 src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java create mode 100644 src/main/java/org/asteriskjava/pbx/CallStateDataParked.java create mode 100644 src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java create mode 100644 src/main/java/org/asteriskjava/pbx/CallbackAdaptor.java create mode 100644 src/main/java/org/asteriskjava/pbx/CallerID.java create mode 100644 src/main/java/org/asteriskjava/pbx/Channel.java create mode 100644 src/main/java/org/asteriskjava/pbx/ChannelFactory.java create mode 100644 src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java create mode 100644 src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java create mode 100644 src/main/java/org/asteriskjava/pbx/DTMFTone.java create mode 100644 src/main/java/org/asteriskjava/pbx/EndPoint.java create mode 100644 src/main/java/org/asteriskjava/pbx/NewChannelListener.java create mode 100644 src/main/java/org/asteriskjava/pbx/NewExtensionListener.java create mode 100644 src/main/java/org/asteriskjava/pbx/PBX.java create mode 100644 src/main/java/org/asteriskjava/pbx/PBXException.java create mode 100644 src/main/java/org/asteriskjava/pbx/PBXFactory.java create mode 100644 src/main/java/org/asteriskjava/pbx/PhoneNumber.java create mode 100644 src/main/java/org/asteriskjava/pbx/Tech.java create mode 100644 src/main/java/org/asteriskjava/pbx/Trunk.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivityImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/BridgeActivity.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/BridgeActivityImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/DialActivity.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivityImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/HoldActivityImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/JoinActivity.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/JoinActivityImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/ParkActivity.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/SplitActivity.java create mode 100644 src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/ActivityAgi.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBlindTransfer.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBridge.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityDial.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHangup.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHold.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHoldForBridge.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityMeetme.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityQueue.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityVoicemail.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/NJAgiScript.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/agi/RateLimiter.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/AsteriskSettings.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/InvalidChannelName.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/NoMeetmeException.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/PBXSettingsManager.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/AbstractManagerAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/BridgeAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/CommandAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ConfbridgeListAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/DbGetAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/EventGeneratingAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/GetVarAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/HangupAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ListCommandsAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ManagerAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/MonitorAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/OriginateAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PingAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PlayDtmfAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/RedirectAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SetVarAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipPeersAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipShowPeerAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/StatusAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/UserEventAction.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractChannelStateEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractMeetMeEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractParkedCallEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentCalledEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentConnectEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/BridgeEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelState.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListCompleteEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConnectEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DbGetResponseEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DialEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DisconnectEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DndStateEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ExtensionStatusEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/HangupEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/LinkEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ManagerEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MasqueradeEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeJoinEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeLeaveEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewChannelEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewExtenEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewStateEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/OriginateResponseEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ParkedCallEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerEntryEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerStatusEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerlistCompleteEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/QueueCallerLeaveEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/RenameEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvents.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusCompleteEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnlinkEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnparkedCallEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/VarSetEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/CommandResponse.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerError.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerResponse.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/userEvents/UserEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/ActiveCallListener.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/ChannelEventHelper.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/DialPlanExtension.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/ListenerPriority.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/Peer.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/TechType.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java create mode 100644 src/main/java/org/asteriskjava/pbx/util/LogTime.java create mode 100644 src/test/java/org/asteriskjava/pbx/internal/agi/RateLimiterTest.java diff --git a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java index d5a4b1f2e..fe5b510fe 100644 --- a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java +++ b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java @@ -332,10 +332,14 @@ public void setTimeout(Integer timeout) if (timeout < 10000) { logger.warn( - "A timeout of less than 100000 will cause the originate to fail if not answered within 10 seconds!"); + "A timeout of less than 10000 will cause the originate to fail if not answered within 10 seconds!"); } + this.timeout = timeout.longValue(); + } + else + { + this.timeout = null; } - this.timeout = timeout.longValue(); } /** diff --git a/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java b/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java index 91354f2d7..cab680b14 100644 --- a/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java @@ -384,10 +384,12 @@ public void setSipT38MaxDtgrm(Long sipT38MaxDtgrm) * so I'm taking a long and then changing it to -1 if required */ if (sipT38MaxDtgrm == 4294967295L) + { this.sipT38MaxDtgrm = -1L; + } else { - if (sipT38MaxDtgrm != null && sipT38MaxDtgrm < Integer.MAX_VALUE && sipT38MaxDtgrm > Integer.MIN_VALUE) + if (sipT38MaxDtgrm < Integer.MAX_VALUE && sipT38MaxDtgrm > Integer.MIN_VALUE) { this.sipT38MaxDtgrm = sipT38MaxDtgrm; } diff --git a/src/main/java/org/asteriskjava/pbx/Activity.java b/src/main/java/org/asteriskjava/pbx/Activity.java new file mode 100644 index 000000000..393dc2992 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/Activity.java @@ -0,0 +1,21 @@ +package org.asteriskjava.pbx; + +public interface Activity +{ + /** + * If an activity fails the getLastError contains a description of the cause + * of the error. This method should be called from the 'complete' method of + * the iCallBack listener. + * + * @return error message which caused the activity to fail. + */ + Throwable getLastException(); + + /** + * Set to true once the activity has suceeded. + * + * @return + */ + boolean isSuccess(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/ActivityCallback.java b/src/main/java/org/asteriskjava/pbx/ActivityCallback.java new file mode 100644 index 000000000..62286d202 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/ActivityCallback.java @@ -0,0 +1,39 @@ +package org.asteriskjava.pbx; + +/** + * Provides a generic callback mechansim which allows tracking of the progress + * of any of the async methods provided by iPBX. + */ + +public interface ActivityCallback +{ + /** + * Called as soon as the task being tracked is started. + * + * @param activity + * - the activity which is being monitored + */ + void start(T activity); + + /** + * Called periodically to indicate progress with the task being tracked. The + * number of progress messages sent is dependant on the task. Some tasks may + * not send any progress messages. + * + * @param activity + * - the activity which is being monitored + * @param message + */ + void progess(T activity, String message); + + /** + * Called when the task being tracked has completed. + * + * @param activity + * - the activity which is being monitored + * @param success + * - true if the activity completed successfully. + */ + void completed(T activity, boolean success); + +} diff --git a/src/main/java/org/asteriskjava/pbx/Call.java b/src/main/java/org/asteriskjava/pbx/Call.java new file mode 100644 index 000000000..0184397b1 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/Call.java @@ -0,0 +1,98 @@ +package org.asteriskjava.pbx; + +import java.util.Date; +import java.util.List; + +public interface Call +{ + /** + * Used to identify which channel of a call an operation is to be performed + * on. This is designed to stop the mis-use of some methods which operate on + * a specific channel of a call. The Operand allows the caller to specify + * which channel to operate on without having to explicitly pass in the + * channel. Without this enum they could potentially pass in a channel which + * is not owned by the call. + * + * @author bsutton + */ + + public enum OperandChannel + { + /** + * this party received (did not originate) the call + */ + ACCEPTING_PARTY, + + /** + * this party originated (dialled) the call + */ + ORIGINATING_PARTY, + + TRANSFER_TARGET_PARTY, + + /** + * is an end point that is on an external trunk + */ + REMOTE_PARTY, + /** + * a local call is a handset attached directly (via sip) to the pbx + */ + LOCAL_PARTY + } + + boolean contains(Channel parkChannel); + + // public void callIsAnswering(iEndPoint answeredBy) throws PBXException; + + CallerID getAcceptingPartyCallerID(); + + CallerID getOriginatingPartyCallerID(); + + CallerID getRemotePartyCallerID(); + + // void callDialedIn(iCallerID callerCallerID) throws PBXException; + + // void transferDeclined() throws PBXException; + + Date getCallStartTime(); + + // Collection getChannels(); + + Channel getOriginatingParty(); + + Channel getAcceptingParty(); + + Channel getTransferTargetParty(); + + /** + * retrieves the channel associated with the give Operand. + * + * @param lhs + * @return + */ + Channel getOperandChannel(OperandChannel lhs); + + /** + * This method use the CallDirection to determine which leg of the call is + * the local call and which is the called/calling party. It then returns the + * called/calling party. + * + * @return + */ + Channel getRemoteParty(); + + /** + * This method use the CallDirection to determine which leg of the call is + * the local call and which is the called/calling party. It then returns the + * local call . + * + * @return + */ + public Channel getLocalParty(); + + boolean canSplit(); + + CallDirection getDirection(); + + List getChannels(); +} diff --git a/src/main/java/org/asteriskjava/pbx/CallDirection.java b/src/main/java/org/asteriskjava/pbx/CallDirection.java new file mode 100644 index 000000000..80baa9fc8 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/CallDirection.java @@ -0,0 +1,56 @@ +package org.asteriskjava.pbx; + +/** + * Describes the direction of the call. + * + * @author bsutton + */ +public enum CallDirection +{ + /** + * INBOUND - call + */ + INBOUND(0), + /** + * OUTBOUND - call. + */ + OUTBOUND(1); + // /** + // * JOIN - call was created by joining two existing calls + // */ + // JOIN(2), + // + // /** + // * Often temporary channels are brought up for actions such as parking a + // * call. These calls don't really have a direction in their own right. + // * + // * TODO: is this really need, should the originating call be the + // controlling + // * entity. The problem is that currently we really track 'channels' rather + // * than Calls. + // */ + // TRANSIENT(3); + + private final int dbValue; + + private CallDirection(final int dbValue) + { + this.dbValue = dbValue; + } + + public static CallDirection valueOf(final int dbValue) + { + CallDirection result = null; + + for (final CallDirection direction : CallDirection.values()) + { + if (direction.dbValue == dbValue) + { + result = direction; + break; + } + } + return result; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/CallHangupListener.java b/src/main/java/org/asteriskjava/pbx/CallHangupListener.java new file mode 100644 index 000000000..e0dcb79a2 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/CallHangupListener.java @@ -0,0 +1,8 @@ +package org.asteriskjava.pbx; + +public interface CallHangupListener +{ + + void callHungup(Call call); + +} diff --git a/src/main/java/org/asteriskjava/pbx/CallImpl.java b/src/main/java/org/asteriskjava/pbx/CallImpl.java new file mode 100644 index 000000000..7cf4765cf --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/CallImpl.java @@ -0,0 +1,894 @@ +package org.asteriskjava.pbx; + +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.activities.BlindTransferActivity; + +/** + * Holds a call which may consist of 0, 1, 2 or 3 channels. When dialing out a + * call The 1st channel is always the call 'originator'. Channel 2 is + * 'accepting' party Channel 3 is a 'third party' which has joined the call via + * a conference mode. The concept of a Call is independent of a particular PBX. + * All channels of a Call must belong to the same PBX as we have no way of + * bridging calls across multiple PBX's anyway. Calls can be established by: 1) + * When a call arrives at the NJR Management inbound context 2) Dialing 3) + * Joining two existing calls The 'originating' channel is the first channel + * introduced to the call and is stored in the zeroth element of the channel + * list. + * + * @author bsutton + */ + +public class CallImpl implements ChannelHangupListener, Call +{ + static Logger logger = Logger.getLogger(CallImpl.class); + + /** + * We give every call a unique call id to help track the calls when checking + * logs + */ + private static int global_call_identifier_index = 0; + + /** + * A id that uniquely identifies this call. + */ + private int _uniquecallID; + + /* + * transfer types + */ + public enum TransferType + { + NONE, ASSISTED, BLIND; + } + + /** + * The 1st channel is always the call 'originator'. + */ + private Channel _originatingParty; + + /** + * Channel 2 is 'accepting' party + */ + + private Channel _acceptingParty; + + /** + * Channel 3 is a 'third party' which has joined the call via a conference + * mode which would normally be created during a transfer attempt. + */ + private Channel _transferTargetParty; + + /** + * The direct of the call. If it is OUTBOUND then the originating party is + * the local call . If it is INBOUND then the originationg party is the + * caller. + */ + final private CallDirection _direction; + + private CallerID _originatingPartyCallerID = null; + + private CallerID _acceptingPartyCallerID = null; + + /** + * When we attempt to transfer a call to a third party we save the transfer + * target. This allows us to automatically re-try the transfer if the + * initial attempt failed. + */ + private EndPoint _transferTarget = null; + + private TransferType transferType = TransferType.NONE; + + private CallerID _transferTargetCallerID = null; + + private Date _callStarted; + + private Date _holdStarted = null; + + private EndPoint _parkingLot = null; + + private Date _timeAtDialin = null; + + private boolean _parked = false; + + /** + * The primary key for the Contact record. + * + * @return + */ + private Integer _contactId; + + private ArrayList _hangupListeners = new ArrayList<>(); + + /** + * Used to indicate the ownership of the call. SELF - this instance of NJR + * has answered the call and is now considered the owner. REMOTE - some + * other instance of NJR has answered the call. UNOWNED - the call has + * entered the inbound extension but has not been answered by any instance + * of NJR. Note: a calls ownership can change over time. All calls start as + * UNOWNED. If we answer a call it becomes SELF. If we put a call on hold + * and another NJR instances answers it then it can then become REMOTE. + * + * @author bsutton + */ + public enum OWNER + { + SELF + } + + private OWNER _owner; + + protected BlindTransferActivity _transferActivity; + + public CallImpl(Channel originatingChannel, CallDirection direction) throws PBXException + { + logger.debug("Created call=" + originatingChannel + " direction=" + direction); //$NON-NLS-1$ //$NON-NLS-2$ + this._owner = OWNER.SELF; + this._direction = direction; + this._callStarted = new Date(); + this.setUID(); + this.setOriginatingParty(originatingChannel); + + } + + public CallImpl(Channel originatingChannel, Channel acceptingChannel, CallDirection direction) throws PBXException + { + logger.debug("Created call=" + originatingChannel + " direction=" + direction); //$NON-NLS-1$ //$NON-NLS-2$ + this._owner = OWNER.SELF; + this._direction = direction; + this._callStarted = new Date(); + this.setUID(); + this.setOriginatingParty(originatingChannel); + this.setAcceptingParty(acceptingChannel); + + } + + public CallImpl(Channel agent, Channel callee) throws PBXException + { + this._owner = OWNER.SELF; + this._direction = CallDirection.OUTBOUND; + this._callStarted = new Date(); + this.setUID(); + this.setOriginatingParty(agent); + this.setAcceptingParty(callee); + + } + + /** + * Joins a specific channel from this call with a specific channel from + * another call which results in a new Call object being created. Channels + * that do not participate in the join are left in their original Call. + * + * @param originatingOperand the channel from this call that will + * participate in the join as the originating Channel + * @param rhs the call we are joining to. + * @param acceptingOperand the channel from the rhs call that will + * participate in the join as the accepting channel. + * @return + * @throws PBXException + */ + public CallImpl join(OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, + CallDirection direction) throws PBXException + { + CallImpl joinTo = (CallImpl) rhs; + + Channel originatingParty = null; + Channel acceptingParty = null; + + // Pull the originating party from the this call. + originatingParty = this.getOperandChannel(originatingOperand); + if (originatingParty != null && originatingParty.isLive()) + originatingParty.removeListener(this); + + // Pull the accepting party from the other 'call' as the accepting + // party. + acceptingParty = rhs.getOperandChannel(acceptingOperand); + if (acceptingParty != null && acceptingParty.isLive()) + acceptingParty.removeListener((CallImpl) rhs); + + if (originatingParty == null || !originatingParty.isLive() || acceptingParty == null || !acceptingParty.isLive()) + throw new PBXException("Call.HangupDuringJoin"); //$NON-NLS-1$ + + CallImpl joined = new CallImpl(originatingParty, direction); + joined.setAcceptingParty(acceptingParty); + joined._owner = OWNER.SELF; + + joined._callStarted = minDate(this._callStarted, joinTo._callStarted); + + joined._holdStarted = minDate(this._holdStarted, joinTo._holdStarted); + + joined._timeAtDialin = minDate(this._timeAtDialin, joinTo._timeAtDialin); + + logger.debug("Joined two calls lhs=" + this + ", rhs=" + joinTo); //$NON-NLS-1$//$NON-NLS-2$ + + return joined; + } + + private Date minDate(Date d1, Date d2) + { + + if (d1 == null) + { + return d2; + } + if (d2 == null) + { + return d1; + } + if (d1.before(d2)) + { + return d1; + } + return d2; + } + + // + // /** + // * Joins a specific channel from this call with a specific channel from + // another call which results in a new Call object + // * being created. + // * + // * Channels that do not participate in the join are left in their original + // Call. + // * + // * @param lhsOperand the channel from this call that will participate in + // the join + // * @param rhs the call we are joining to. + // * @param rhsOperand the channel from the rhs call that will participate + // in the join. + // * @return + // * @throws PBXException + // */ + // public Call join(OperandChannel lhsOperand, iCall rhs, OperandChannel + // rhsOperand) throws PBXException + // { + // Call joinTo = (Call) rhs; + // + // // // Check there is no transfer party. + // // if (this._transferTargetParty != null || joinTo._transferTargetParty + // != null) + //// throw new IllegalArgumentException("Neither call in a 'Join' may have a + // third party"); //$NON-NLS-1$ + // // + // // // Check that we only have one active party + // // if (this._originatingParty != null && this._acceptingParty != null) + // // throw new IllegalArgumentException( + //// "The call " + this + " has more than one active channel which is not + // allowed."); //$NON-NLS-1$ //$NON-NLS-2$ + // // + // // if (joinTo._originatingParty != null && joinTo._acceptingParty != + // null) + // // throw new IllegalArgumentException( + //// "The call " + joinTo + " has more than one active channel which is not + // allowed."); //$NON-NLS-1$ //$NON-NLS-2$ + // + // iChannel originatingParty = null; + // iChannel acceptingParty = null; + // + // // First select the remote party from this call. + // // For no particular reason we use 'this' as the originating party. + // originatingParty = this.getRemoteParty(); + // if (originatingParty != null && originatingParty.isLive()) + // originatingParty.removeListener(this); + // + // // Now select the remote party from the other 'call' as the accepting + // // party. + // acceptingParty = rhs.getRemoteParty(); + // if (acceptingParty != null && acceptingParty.isLive()) + // acceptingParty.removeListener((Call) rhs); + // + // if (originatingParty == null || acceptingParty == null) + // throw new PBXException(Messages.getString("Call.HangupDuringJoin")); + // //$NON-NLS-1$ + // + // /** + // * We just choose one of the directions as it doesn't really matter + // */ + // Call joined = new Call(originatingParty, this._direction); + // joined.setAcceptingParty(acceptingParty); + // joined._owner = OWNER.SELF; + // + // + // joined._callStarted = DateUtils.min(this._callStarted, + // joinTo._callStarted); + // + // joined._holdStarted = DateUtils.min(this._holdStarted, + // joinTo._holdStarted); + // + // joined._timeAtDialin = DateUtils.min(this._timeAtDialin, + // joinTo._timeAtDialin); + // + // // The selection of _didEntity is arbitrary + // if (this._didEntity != null) + // joined._didEntity = this._didEntity; + // else + // joined._didEntity = joinTo._didEntity; + // + // logger.debug("Joined two calls lhs=" + this + ", rhs=" + joinTo); + // //$NON-NLS-1$//$NON-NLS-2$ + // + // return joined; + // } + + /** + * Splits a channel out of a call into a separate call. This method should + * only be called from the SplitActivity. + * + * @return the resulting call. + * @throws PBXException + */ + public Call split(OperandChannel channelToSplit) throws PBXException + { + Channel channel = this.getOperandChannel(channelToSplit); + channel.removeListener(this); + + CallDirection direction = CallDirection.INBOUND; + + // If this is the operator channel we need to flip the default + // direction. + if (this.getLocalParty() != null && this.getLocalParty().isSame(channel)) + { + direction = CallDirection.OUTBOUND; + } + + CallImpl call = new CallImpl(channel, direction); + call._owner = OWNER.SELF; + + // clear the channel have just split out. + switch (channelToSplit) + { + case ACCEPTING_PARTY : + this.setAcceptingParty(null); + break; + case LOCAL_PARTY : + if (this._direction == CallDirection.INBOUND) + { + this.setAcceptingParty(null); + } + else + { + this.setOriginatingParty(null); + } + break; + case ORIGINATING_PARTY : + this.setOriginatingParty(null); + break; + case REMOTE_PARTY : + if (this._direction == CallDirection.INBOUND) + this.setOriginatingParty(null); + else + this.setAcceptingParty(null); + break; + case TRANSFER_TARGET_PARTY : + this.setTransferTargetParty(null); + break; + default : + break; + } + + return call; + } + + public Call split(Channel channelToSplit) throws PBXException + { + channelToSplit.removeListener(this); + CallDirection direction = CallDirection.INBOUND; + // If this is the operator channel we need to flip the default + // direction. + if (this.getLocalParty() != null && this.getLocalParty().isSame(channelToSplit)) + { + direction = CallDirection.OUTBOUND; + } + + CallImpl call = new CallImpl(channelToSplit, direction); + call._owner = OWNER.SELF; + if (_acceptingParty != null && _acceptingParty.isSame(channelToSplit)) + _acceptingParty = null; + if (_originatingParty != null && _originatingParty.isSame(channelToSplit)) + _originatingParty = null; + if (_transferTargetParty != null && _transferTargetParty.isSame(channelToSplit)) + _transferTargetParty = null; + return call; + + } + + @Override + public void channelHangup(Channel channel, Integer cause, String causeText) + { + try + { + if (isSameChannel(this._originatingParty, channel)) + { + this.setOriginatingParty(null); + logger.debug("Removed originatingParty=" + channel + " from Call=" + this._uniquecallID //$NON-NLS-1$ //$NON-NLS-2$ + + " as channel was hung up"); //$NON-NLS-1$ + } + + else if (isSameChannel(this._acceptingParty, channel)) + { + this.setAcceptingParty(null); + logger.debug("Removed acceptingParty=" + channel + " from Call=" + this._uniquecallID //$NON-NLS-1$ //$NON-NLS-2$ + + " as channel was hung up"); //$NON-NLS-1$ + + } + + else if (isSameChannel(this._transferTargetParty, channel)) + { + this.setTransferTargetParty(null); + logger.debug("Removed transferTarget=" + channel + " from Call=" + this._uniquecallID //$NON-NLS-1$ //$NON-NLS-2$ + + " as channel was hung up"); //$NON-NLS-1$ + } + + else + { + logger.warn("Received hangup for unknown channel=" + channel.getChannelId() + " on Call=" //$NON-NLS-1$ //$NON-NLS-2$ + + this._uniquecallID + " as channel was hung up"); //$NON-NLS-1$ + } + if (!this.isLive()) + { + notifyCallHangupListeners(); + } + } + catch (PBXException e) + { + // not much we can do here so just log it + logger.error(e, e); + } + } + + private boolean isSameChannel(Channel lhs, Channel rhs) + { + return lhs != null && rhs != null && lhs.isSame(rhs); + } + + // private int findChannel(iChannel channel) + // { + // int index = -1; + // + // synchronized (this.channelList) + // { + // for (int i = 0; i < this.channelList.size(); i++) + // { + // iChannel aChannel = this.channelList.get(i); + // if (aChannel.isSame(channel)) + // { + // index = i; + // break; + // } + // } + // } + // return index; + // } + + private void notifyCallHangupListeners() + { + for (CallHangupListener listener : this._hangupListeners) + { + listener.callHungup(this); + } + + } + + /** + * Returns the originating channel for this call. e.g. the first channel + * that came up. Whilst a call must always start with an originating channel + * as a call is shutting down it will get to the point where it will have no + * channels. In these cases the return will be null. + * + * @return null or the originating channel. + */ + + @Override + public Channel getOriginatingParty() + { + return this._originatingParty; + } + + // /** + // * Call this method to mark this call as owned by another instance of NJR + // as + // * that instance has answered the call. The only time a calls ownership + // can + // * transition is when the call is answered by an instances of NJR or the + // * call is transfered to the vacant transfer extension. Roaming calls are + // * still owned by the NJR instance that originally answered the call. + // */ + // public void callAnsweredRemotely() + // { + // this._owner = OWNER.REMOTE; + // + // } + + // private void callIsTransferring() throws PBXException + // { + // if (this.holdStarted == null) + // { + // this.holdStarted = new Date(); + // } + // this._state = Call.CallState.TRANSFER; + // } + + /** + * Call this method to indicate that this is an outbound call originated by + * this NJR instance. These type of calls are not seen by a remote operator + * unless they are put on hold. + * + * @param remoteChannel - the remote channel this call connected to when + * dialing. + * @throws PBXException + */ + public void callDialedOut(Channel remoteChannel, CallerID fromClid, CallerID toClid) throws PBXException + { + + // -- moved to ANSWER + } + + @Override + public Date getCallStartTime() + { + return this._callStarted; + } + + public Integer getContactId() + { + return this._contactId; + } + + /** + * The current transfer target. + * + * @return + */ + public EndPoint getTransferTarget() + { + return this._transferTarget; + } + + public CallerID getTransferTargetCallerID() + { + return this._transferTargetCallerID; + } + + @Override + public CallerID getAcceptingPartyCallerID() + { + return this._acceptingPartyCallerID; + } + + @Override + public CallerID getOriginatingPartyCallerID() + { + return this._originatingPartyCallerID; + } + + @Override + public CallerID getRemotePartyCallerID() + { + CallerID remoteCallerID = null; + + if (this.getDirection() == CallDirection.INBOUND) + { + remoteCallerID = this.getOriginatingPartyCallerID(); + } + else + { + remoteCallerID = this.getAcceptingPartyCallerID(); + } + return remoteCallerID; + } + + public Date getHoldStartTime() + { + return this._holdStarted; + } + + public EndPoint getParkingLot() + { + return this._parkingLot; + } + + public Date getTimeAtDialIn() + { + return this._timeAtDialin; + } + + public TransferType getTransferType() + { + return this.transferType; + } + + public String getUniqueCallID() + { + /* + * this is a unique call identifier. + */ + return "" + this._uniquecallID; //$NON-NLS-1$ + } + + public boolean isCallParked() + { + return this._parked; + } + + private void setOriginatingParty(Channel originatingParty) throws PBXException + { + this._originatingParty = originatingParty; + + if (originatingParty != null) + { + if (!this._originatingParty.canDetectHangup() && this._acceptingParty != null + && !this._acceptingParty.canDetectHangup()) + throw new PBXException("Call.BothWithNoHangupDetection"); //$NON-NLS-1$ + + this._originatingParty.addHangupListener(this); + } + } + + private void setAcceptingParty(Channel acceptingParty) throws PBXException + { + this._acceptingParty = acceptingParty; + + if (acceptingParty != null) + { + if (!this._acceptingParty.canDetectHangup() && this._originatingParty != null + && !this._originatingParty.canDetectHangup()) + throw new PBXException("Call.BothWithNoHangupDetection"); //$NON-NLS-1$ + + this._acceptingParty.addHangupListener(this); + } + } + + private void setTransferTargetParty(Channel transferTargetParty) + { + this._transferTargetParty = transferTargetParty; + + if (transferTargetParty != null) + { + this._transferTargetParty.addHangupListener(this); + } + } + + /** + * The contact id is just used when refilling the list of contacts so we + * know which one is selected at the moment. It probably should be stored + * here! + * + * @param _contactId + */ + public void setContactId(final Integer _contactId) + { + this._contactId = _contactId; + + } + + // private void setTransferType(final TransferType tType) + // { + // this.transferType = tType; + // } + + /** + * + */ + private synchronized void setUID() + { + this._uniquecallID = CallImpl.global_call_identifier_index++; + if (CallImpl.global_call_identifier_index > 99) + { + CallImpl.global_call_identifier_index = 0; + } + } + + @Override + public CallDirection getDirection() + { + return this._direction; + } + + /** + * Call this method to get a notification when this call hangs up. + * + * @param listener + * @return true if the hangup listener was added. False if the call has + * already been hungup. + */ + public boolean addHangupListener(CallHangupListener listener) + { + boolean callStillUp = true; + + if ((this._originatingParty != null && this._originatingParty.isLive()) + || (this._acceptingParty != null && this._acceptingParty.isLive()) + || (this._transferTargetParty != null && this._transferTargetParty.isLive())) + this._hangupListeners.add(listener); + else + callStillUp = false; + return callStillUp; + + } + + /** + * returns true if the call has any active channels. + * + * @return + */ + public boolean isLive() + { + boolean live = false; + if ((this._originatingParty != null && this._originatingParty.isLive()) + || (this._acceptingParty != null && this._acceptingParty.isLive()) + || (this._transferTargetParty != null && this._transferTargetParty.isLive())) + live = true; + return live; + } + + /** + * @return true if this call is owned by another instance of NJR. + */ + public OWNER getOwner() + { + return this._owner; + } + + // /** + // * Returns a shallow clone of the list of channels. + // */ + // @SuppressWarnings("unchecked") + // @Override + // public Collection getChannels() + // { + // synchronized (this.channelList) + // { + // return (Collection) this.channelList.clone(); + // } + // } + + @Override + public String toString() + { + return "State: Originating Channel:" + getOriginatingParty() + " Direction: " //$NON-NLS-1$ //$NON-NLS-2$ + // //$NON-NLS-3$ + + this.getDirection() + " accepting:" + this._acceptingParty; //$NON-NLS-1$ + } + + @Override + public boolean contains(Channel parkChannel) + { + boolean found = false; + + if (isSameChannel(this._originatingParty, parkChannel)) + { + found = true; + } + else if (isSameChannel(this._acceptingParty, parkChannel)) + { + found = true; + } + + else if (isSameChannel(this._transferTargetParty, parkChannel)) + { + found = true; + } + + return found; + } + + @Override + public Channel getAcceptingParty() + { + return this._acceptingParty; + } + + @Override + public Channel getTransferTargetParty() + { + return this._transferTargetParty; + } + + @Override + /** + * This method use the CallDirection to determine which leg of the call is + * the local call and which is the called/calling party. It then returns the + * called/calling party. + * + * @return + */ + public Channel getRemoteParty() + { + Channel remoteChannel = null; + + if (this.getDirection() == CallDirection.INBOUND) + { + remoteChannel = this.getOriginatingParty(); + } + else + { + remoteChannel = this.getAcceptingParty(); + } + if (remoteChannel == null) + { + logger.error("remoteChannel is null for {}" + this.getDirection()); + } + return remoteChannel; + + } + + /** + * This method use the CallDirection to determine which leg of the call is + * the local call and which is the called/calling party. It then returns the + * local call . + * + * @return + */ + @Override + public Channel getLocalParty() + { + + if (this.getDirection() == CallDirection.OUTBOUND) + return this.getOriginatingParty(); + + return this.getAcceptingParty(); + + } + + @Override + public boolean canSplit() + { + return (this._originatingParty != null && this._acceptingParty != null && this._transferTargetParty == null); + } + + @Override + public Channel getOperandChannel(OperandChannel operand) + { + final Channel channel; + + switch (operand) + { + case ACCEPTING_PARTY : + channel = this._acceptingParty; + break; + case ORIGINATING_PARTY : + channel = this._originatingParty; + break; + case REMOTE_PARTY : + channel = getRemoteParty(); + break; + case TRANSFER_TARGET_PARTY : + channel = this._transferTargetParty; + break; + case LOCAL_PARTY : + channel = this.getLocalParty(); + break; + default : + // should never happen + throw new IllegalArgumentException("An unsupported operand was passed:" + operand); //$NON-NLS-1$ + } + if (channel == null) + { + Exception e = new Exception("failed to get channel for {}" + operand); + logger.warn(e, e); + } + return channel; + } + + public boolean isSame(Call rhs) + { + return this._uniquecallID == ((CallImpl) rhs)._uniquecallID; + } + + @Override + public List getChannels() + { + List channels = new LinkedList<>(); + if (_acceptingParty != null) + channels.add(_acceptingParty); + if (_originatingParty != null) + channels.add(_originatingParty); + if (_transferTargetParty != null) + channels.add(_transferTargetParty); + return channels; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/CallStateAnswered.java b/src/main/java/org/asteriskjava/pbx/CallStateAnswered.java new file mode 100644 index 000000000..f7a9e273b --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/CallStateAnswered.java @@ -0,0 +1,23 @@ +package org.asteriskjava.pbx; + +import org.apache.log4j.Logger; + +public class CallStateAnswered extends CallStateData +{ + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(CallStateAnswered.class); + + // The channel that accepted the call. + private Channel _acceptingParty; + + public CallStateAnswered(Channel acceptingParty) + { + this._acceptingParty = acceptingParty; + } + + public Channel getAcceptingParty() + { + return this._acceptingParty; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/CallStateData.java b/src/main/java/org/asteriskjava/pbx/CallStateData.java new file mode 100644 index 000000000..3a58c0183 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/CallStateData.java @@ -0,0 +1,9 @@ +package org.asteriskjava.pbx; + +import org.apache.log4j.Logger; + +public class CallStateData +{ + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(CallStateData.class); +} diff --git a/src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java b/src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java new file mode 100644 index 000000000..34942a24d --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java @@ -0,0 +1,29 @@ +package org.asteriskjava.pbx; + +import org.apache.log4j.Logger; + +public class CallStateDataNewInbound extends CallStateData +{ + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(CallStateDataNewInbound.class); + + CallerID _originatingPartyCallerID; + + private final String _fromDID; + + public CallStateDataNewInbound(String fromDID, CallerID originatingPartyCallerID) + { + this._originatingPartyCallerID = originatingPartyCallerID; + this._fromDID = fromDID; + } + + public CallerID getOriginatingPartyCallerID() + { + return this._originatingPartyCallerID; + } + + public String getFromDID() + { + return this._fromDID; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/CallStateDataParked.java b/src/main/java/org/asteriskjava/pbx/CallStateDataParked.java new file mode 100644 index 000000000..579a9aaa1 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/CallStateDataParked.java @@ -0,0 +1,17 @@ +package org.asteriskjava.pbx; + +import org.apache.log4j.Logger; + +public class CallStateDataParked extends CallStateData +{ + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(CallStateDataParked.class); + + EndPoint _parkingLot; + + public CallStateDataParked(EndPoint parkingLot) + { + this._parkingLot = parkingLot; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java b/src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java new file mode 100644 index 000000000..cda21f04b --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java @@ -0,0 +1,50 @@ +package org.asteriskjava.pbx; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.CallImpl.TransferType; +import org.asteriskjava.pbx.activities.BlindTransferActivity; + +public class CallStateDataTransfer extends CallStateData +{ + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(CallStateDataTransfer.class); + + private TransferType _transferType; + /** + * the end point we are attempting to transfer the call to. + */ + private EndPoint _transferTarget; + + private CallerID _transferTargetCallerID; + + private BlindTransferActivity _transferActivity; + + public CallStateDataTransfer(TransferType transferType, EndPoint transferTarget, CallerID transferTargetCallerID, + BlindTransferActivity transferActivity) + { + this._transferType = transferType; + this._transferTarget = transferTarget; + this._transferTargetCallerID = transferTargetCallerID; + this._transferActivity = transferActivity; + } + + public EndPoint getTransferTarget() + { + return this._transferTarget; + } + + public CallerID getTransferTargetCallerID() + { + return this._transferTargetCallerID; + } + + public TransferType getTransferType() + { + return this._transferType; + } + + public BlindTransferActivity getActivity() + { + return this._transferActivity; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/CallbackAdaptor.java b/src/main/java/org/asteriskjava/pbx/CallbackAdaptor.java new file mode 100644 index 000000000..c38e64ce9 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/CallbackAdaptor.java @@ -0,0 +1,24 @@ +package org.asteriskjava.pbx; + +public class CallbackAdaptor implements ActivityCallback +{ + @Override + public void start(final T activity) + { + // NOOP + } + + @Override + public void progess(final T activity, final String message) + { + // NOOP + + } + + @Override + public void completed(final T activity, final boolean success) + { + // NOOP + + } +} diff --git a/src/main/java/org/asteriskjava/pbx/CallerID.java b/src/main/java/org/asteriskjava/pbx/CallerID.java new file mode 100644 index 000000000..833edd5f3 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/CallerID.java @@ -0,0 +1,40 @@ +package org.asteriskjava.pbx; + +public interface CallerID +{ + /** + * Gets the number component of the caller id. + * + * @return the callerid's number + */ + String getNumber(); + + /** + * Gets the name component of the caller id. + * + * @return the callerid's name + */ + String getName(); + + /** + * Controls whether this caller id should be presented to the remote end. + * + * @param hide + * - if true then the caller id will be hidden. + */ + void setHideCallerID(boolean hide); + + /** + * + * @return true if the caller id is marked as hidden. + */ + boolean isHideCallerID(); + + /** + * Returns true if the caller id number is blank or equal to 'unknown'. + * + * @return + */ + boolean isUnknown(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/Channel.java b/src/main/java/org/asteriskjava/pbx/Channel.java new file mode 100644 index 000000000..82ef417b7 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/Channel.java @@ -0,0 +1,190 @@ +package org.asteriskjava.pbx; + +import java.util.concurrent.TimeUnit; + +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; + +/** + * Provides an abstraction for an channel object which is independant of the + * underlying PBX. + * + * @author bsutton + */ +public interface Channel +{ + /** + * Compares if two channels are the same logical channel on the pbx. This + * comparison uses the full unique name of the channel not just the + * abbreviated peer name. e.g. SIP/100-00000100 + * + * @param rhs + * @return + */ + boolean isSame(Channel rhs); + + boolean isSame(String channelName, String uniqueID); + + /* + * This comparision uses just the peer name. e.g. SIP/100 + */ + boolean sameEndPoint(Channel rhs); + + /* + * This comparision uses just the peer name. e.g. SIP/100 + */ + boolean sameEndPoint(EndPoint extensionRoaming); + + /** + * Compares if this channel is the same as the named channel. + * + * @param channelName + * @return + */ + boolean sameExtenededChannelName(String channelName); + + /** + * This method does not actually change the state of the channel, rather it + * is intended to be used to record the fact that the state has changed. + * + * @see public iPBX.iParkCallActivity park(iChannel channel, Direction + * direction, boolean parkState) for a method which actually parks the + * channel. + */ + void setParked(boolean parked); + + /** + * This method does not actually change the state of the channel, rather it + * is intended to be used to record the fact that the state has changed. + * + * @see public iPBX.iMuteCallActivity mute(iChannel channel, Direction + * direction, boolean muteState) for a method which actually mutes the + * channel. + */ + void setMute(boolean muteState); + + /** + * Each channel is assigned a unique PBX independent id to help track the + * channels when logging. + * + * @return + */ + long getChannelId(); + + /** + * Returns true if the channel is alive. A channel is considered to be alive + * from the moment it is created until we get a notification that it has + * been hungup. + * + * @return + */ + boolean isLive(); + + /** + * Adds a listener to the channel. The channel will send a hungup + * notification to the listener when it hungup. A channel must be able to + * support multiple listeners. + * + * @param call + */ + void addHangupListener(ChannelHangupListener listener); + + void removeListener(ChannelHangupListener listener); + + /** + * Returns true if the given endpont is currently connected to this channel. + * + * @param extension + * @return + */ + boolean isConnectedTo(EndPoint endPoint); + + /** + * returns a fully qualifed channel name which includes the tech. e.g. + * SIP/100-00000342 + * + * @return + */ + String getChannelName(); + + EndPoint getEndPoint(); + + /** + * Checks if this channel is currently mute. A channel is mute if the party + * connected to this channel cannot hear any audio. + * + * @return + */ + boolean isMute(); + + /** + * In Asterisk speak, this method returns true if it is a LOCAL/ channel Not + * quite certain how this will map to other pbx's + * + * @return + */ + boolean isLocal(); + + /** + * @return true if the channel is currently parked. + */ + boolean isParked(); + + /** + * Returns true if the channel has been marked as in a zombie state. + * + * @return + */ + boolean isZombie(); + + /** + * @return true if the channel was originated from the console + * (Console/DSP). + */ + boolean isConsole(); + + /** + * Returns the current callerid for this channel. Note: on some systems this + * involves a round trip to the pbx. + * + * @return + */ + CallerID getCallerID(); + + /** + * Called to rename a channel + * + * @param newname + * the new name of the channel + * @throws InvalidChannelName + */ + void rename(String newName) throws InvalidChannelName; + + /** + * Returns a PBX specific version of the Channel name. + * + * @return + */ + String getExtendedChannelName(); + + void notifyHangupListeners(Integer cause, String causeText); + + boolean canDetectHangup(); + + boolean isQuiescent(); + + boolean hasCallerID(); + + AgiChannelActivityAction getCurrentActivityAction(); + + public void setCurrentActivityAction(AgiChannelActivityAction action); + + void setIsInAgi(boolean b); + + boolean isInAgi(); + + String getUniqueId(); + + boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException; + +} diff --git a/src/main/java/org/asteriskjava/pbx/ChannelFactory.java b/src/main/java/org/asteriskjava/pbx/ChannelFactory.java new file mode 100644 index 000000000..7d1d0f75a --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/ChannelFactory.java @@ -0,0 +1,23 @@ +package org.asteriskjava.pbx; + +import org.apache.log4j.Logger; + +/** + * Currently this factories only purposes is to serve up globally unique channel + * id's which every new channel must be assigned. + * + * @author bsutton + * + */ +public class ChannelFactory +{ + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(ChannelFactory.class); + + private static long nextChannelId = 0; + + public static synchronized long getNextChannelId() + { + return ++ChannelFactory.nextChannelId; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java b/src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java new file mode 100644 index 000000000..ad180faa0 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java @@ -0,0 +1,13 @@ +package org.asteriskjava.pbx; + +/** + * Used to notify channel listeners of state changes to a channel. + * + * @author bsutton + * + */ +public interface ChannelHangupListener +{ + // Called by the channel when it is being hungup + void channelHangup(Channel channel, Integer cause, String causeText); +} diff --git a/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java b/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java new file mode 100644 index 000000000..06dd5320c --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java @@ -0,0 +1,50 @@ +package org.asteriskjava.pbx; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; + +/** + * This is a utility class designed to wait for an activity to complete. + * + * When starting an activity for that you want to wait until completion pass + * this class as the iCallback listener and then call waitForCompletion. + * waitForCompletion will not return until the activity completes. + * + * @author bsutton + * + * @param + */ +public class CompletionAdaptor extends CallbackAdaptor +{ + private static final Logger logger = Logger.getLogger(CompletionAdaptor.class); + + CountDownLatch _latch = new CountDownLatch(1); + + @Override + public void completed(final T activity, final boolean success) + { + _latch.countDown(); + } + + public void waitForCompletion(long timeout, TimeUnit unit) + { + // wait until the activity completes + try + { + if (!_latch.await(timeout, unit)) + { + Exception e = new Exception("Timeout waiting for activity to complete (" + timeout + " " + unit + ")"); + logger.error(e, e); + } + } + catch (final InterruptedException e) + { + // should never happen + CompletionAdaptor.logger.error(e, e); + } + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/DTMFTone.java b/src/main/java/org/asteriskjava/pbx/DTMFTone.java new file mode 100644 index 000000000..ab6166e02 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/DTMFTone.java @@ -0,0 +1,27 @@ +package org.asteriskjava.pbx; + +/** + * Used to indicate the set of possible DTMF tones which can be sent. + * + * @author bsutton + * + */ +public enum DTMFTone +{ + ZERO('0'), ONE('1'), TWO('2'), THREE('3'), FOUR('4'), FIVE('5'), SIX('6'), SEVEN('7'), EIGHT('8'), NINE('9'), + HASH('#'), STAR('*'); + + private final String character; + + DTMFTone(final char character) + { + this.character = new String(new char[] { character }); + } + + @Override + public String toString() + { + return this.character; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/EndPoint.java b/src/main/java/org/asteriskjava/pbx/EndPoint.java new file mode 100644 index 000000000..f08e39e3f --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/EndPoint.java @@ -0,0 +1,71 @@ +package org.asteriskjava.pbx; + +import org.asteriskjava.pbx.internal.core.TechType; + +/** + * Provides an abstract interface for entities which can be dialed. + * + * This encompasses entities such as: Phone extensions SIPPeers Asterisk + * extensions External phone numbers + * + * @author bsutton + * + */ +public interface EndPoint extends Comparable +{ + public boolean isSame(EndPoint rhs); + + public boolean isLocal(); + + public boolean isSIP(); + + /** + * Returns the fully qualified name of the EndPoint including the tech. e.g. + * SIP/100 + * + * @return + */ + public String getFullyQualifiedName(); + + /** + * Returns the simple name of the EndPoint sans the tech. e.g. SIP/100 would + * be returned as 100. + * + * @return + */ + public String getSimpleName(); + + /** + * Returns the simple name of a SIP EndPoint sans the tech. e.g. SIP/100 + * would be returned as 100. If the endpoint is not actually a SIP end point + * then this method returns the full end point name. + * + * + * @return + */ + public String getSIPSimpleName(); + + /** + * Returns true if the tech is not know for this end point. + * + * @return + */ + public boolean isUnknown(); + + /** + * Returns the Tech that is used to reach this endpoint. + * + * @return + */ + public TechType getTech(); + + public boolean isEmpty(); + + /** + * Sets the tech on the end point to the specified tech. + * + * @param sip + */ + // public void setTech(Tech tech); + +} diff --git a/src/main/java/org/asteriskjava/pbx/NewChannelListener.java b/src/main/java/org/asteriskjava/pbx/NewChannelListener.java new file mode 100644 index 000000000..c4725b1ac --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/NewChannelListener.java @@ -0,0 +1,24 @@ +package org.asteriskjava.pbx; + +public interface NewChannelListener +{ + /** + * Allows a listener to be informed as new channels come up during an + * originate. + * + * The OriginateBase class will call this for each channel that comes up (as + * a result of the originate). + * + * Intermediate channels (local etc) that the underlying pbx may create on + * the way through are ignored with only the final channels being notified. + * + * This listener should be used by anyone that needs to have the channel at + * the earliest possible moment. + * + * Listeners should not run long lived process from this call as it will + * stall the dialer. + * + * @param channel + */ + void channelUpdate(Channel channel); +} diff --git a/src/main/java/org/asteriskjava/pbx/NewExtensionListener.java b/src/main/java/org/asteriskjava/pbx/NewExtensionListener.java new file mode 100644 index 000000000..5bce30e85 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/NewExtensionListener.java @@ -0,0 +1,15 @@ +package org.asteriskjava.pbx; + +/** + * Used to notify interested parties when a new extension has been read from the + * pbx configuration. + * + * @author bsutton + * + */ +public interface NewExtensionListener +{ + + void newExtension(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/PBX.java b/src/main/java/org/asteriskjava/pbx/PBX.java new file mode 100644 index 000000000..e69952950 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/PBX.java @@ -0,0 +1,307 @@ +package org.asteriskjava.pbx; + +import java.util.List; + +import org.asteriskjava.pbx.Call.OperandChannel; +import org.asteriskjava.pbx.activities.BlindTransferActivity; +import org.asteriskjava.pbx.activities.DialActivity; +import org.asteriskjava.pbx.activities.HoldActivity; +import org.asteriskjava.pbx.activities.JoinActivity; +import org.asteriskjava.pbx.activities.ParkActivity; +import org.asteriskjava.pbx.activities.SplitActivity; +import org.asteriskjava.pbx.internal.core.TechType; + +/** + * Provides an abstracted interface for communicating with a PBX. + * + * @author bsutton + */ +public interface PBX +{ + + /** + * Call this method when shutting down the PBX interface to allow it to + * cleanup. + */ + public void shutdown(); + + /** + * Returns true if the bridge function is supported. + */ + boolean isBridgeSupported(); + + /** + * The BlindTransferActivity is used by the AsteriksPBX to transfer a live + * channel to an endpoint that may need to be dialed. Note: this action is a + * long running action which is dependent on a user action to complete. The + * action will only complete when the call is answered by the tranferTarget. + * It is recommended that you use the blindTransfer method which takes a + * callback as there is no way to cancel this action. Until the + * transferTarget answers the call or the blind transfer times out. + * + * @param channelToTransfer the channel which is to be blind transfered + * @param transferTarget the endPoint to which the channel is to be + * tranferred. + * @param toCallerID - the callerID to display to the transferTarget during + * the transfer. + * @param autoAnswer - if true then the transferTarget is to be sent an auto + * answer header + * @param timeout - timeout for the blind transfer attempt. When the timeout + * is reached the Blind Transfer will be cancelled. + * @param ActivityCallback + */ + BlindTransferActivity blindTransfer(final Call call, OperandChannel channelToTransfer, final EndPoint transferTarget, + final CallerID toCallerID, boolean autoAnswer, long timeout); + + /** + * The BlindTransferActivity is used by the AsteriksPBX to transfer a live + * channel to an endpoint that may need to be dialed. Note: this action is a + * long running action which is defendant on a user action to complete. The + * action will only complete when the call is answered by the tranferTarget. + * You can cancel the action at any time by using the activity object + * returned from the callback start method. + * + * @param channelToTransfer the channel which is to be blind transfered + * @param transferTarget the endPoint to which the channel is to be + * transferred. + * @param toCallerID - the callerID to display to the transferTarget during + * the transfer. + * @param autoAnswer - if true then the transferTarget is to be sent an auto + * answer header + * @param timeout - timeout for the blind transfer attempt. When the timeout + * is reached the Blind Transfer will be cancelled. + */ + BlindTransferActivity blindTransfer(Call call, OperandChannel channelToTransfer, final EndPoint transferTarget, + final CallerID toCallerID, boolean autoAnswer, long timeout, ActivityCallback callback); + + /** + * Sends a DTMF tone to given channel. Not returning until the tone has been + * sent. + * + * @param channel + */ + void conference(Channel channelOne, Channel channelTwo, Channel channelThree); + + /** + * Sends a DTMF tone to the given channel. This method returns immediately + * with progress information passed to the given callback. Note: the + * callback method will be called from a different thread. + * + * @param channel + * @param callback + */ + void conference(Channel channelOne, Channel channelTwo, Channel channelThree, ActivityCallback callback); + + /** + * Dials the given phone number using the specified trunk. Not returning + * until the call has been dialled. The dial will return as soon as the + * trunk comes up, it does not wait for remote end to answer. + * + * @param trunk - the trunk to dial out on. If null the default trunk will + * be used. + * @return Call - the call resulting from dialing the number. + */ + DialActivity dial(Trunk trunk, EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID); + + /** + * Dials the given phone number using the specified trunk. Not returning + * until the call has been dialled. The dial will return as soon as the + * trunk comes up, it does not wait for remote end to answer. + * + * @param trunk - the trunk to dial out on. If null the default trunk will + * be used. + * @return Call the call resulting from dialing the number. + */ + DialActivity dial(Trunk trunk, EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID, + ActivityCallback callback); + + /** + * Hangs up the given channel. Not returning until the call is hungup. + * + * @param channel + * @throws PBXException + */ + void hangup(Channel channel) throws PBXException; + + /** + * Hangs up the given channel. This method returns immediately with progress + * information passed to the given callback. Note: the callback method will + * be called from a different thread. + * + * @param channel + * @param callback + */ + void hangup(Channel channel, ActivityCallback callback); + + /** + * Put the given channel on hold. + * + * @param channel + * @return + */ + HoldActivity hold(Channel channel); + + /** + * Returns true if the mute function is supported. + */ + boolean isMuteSupported(); + + /** + * Parks a call by moving the parkChannel to the parking lot and hanging up + * the hangupChannel. This method will not return until the park has + * completed. The park expects two channels which are two legs legs of the + * same call. The parkChannel will be redirect to the njr-park extension. + * The hangupChannel (the second leg of the call) will be hung up. The + * (obvious?) limitation is that we can't park something like a conference + * call as it has more than two channels. The returned iParkActivty can be + * used to obtain the extension the call was parked on. + * + * @param the call which is to be parked. + * @param parkChannel - the channel which is going to be redirect to the + * njr-park extension. + * @param hangupChannel - the channel which is going to be hungup. + */ + ParkActivity park(Call call, Channel parkChannel); + + /** + * Parks a call by moving the parkChannel to the parking lot and hanging up + * the hangupChannel. This method returns almost immediately call progress + * can be tracked via the callback. The park expects two channels which are + * two legs legs of the same call. The parkChannel will be redirect to the + * njr-park extension. The hangupChannel (the second leg of the call) will + * be hung up. The (obvious?) limitation is that we can't park something + * like a conference call as it has more than two channels. The returned + * iParkActivty can be used to obtain the extension the call was parked on. + * + * @param the call which is to be parked. + * @param parkChannel - the channel which is going to be redirect to the + * njr-park extension. + */ + ParkActivity park(Call call, Channel parkChannel, ActivityCallback callback); + + /** + * Sends a DTMF tone to given channel. Not returning until the tone has been + * sent. + * + * @param channel + * @throws PBXException + */ + void sendDTMF(Channel channel, DTMFTone tone) throws PBXException; + + /** + * Sends a DTMF tone to the given channel. This method returns immediately + * with progress information passed to the given callback. Note: the + * callback method will be called from a different thread. + * + * @param channel + * @param callback + */ + void sendDTMF(Channel channel, DTMFTone tone, ActivityCallback callback); + + // + // /** + // * Splits a call (with two channels) sending the originating channel to + // the + // * originatingTarget and other channel to the secondaryTarget. + // * + // * This call returns once the split action has completed. + // * + // * @param callToSplit + // * @param originatingTarget + // * @param secondaryTarget + // * @return + // * @throws PBXException + // */ + // iSplitActivity split(iCall callToSplit, iEndPoint originatingTarget, + // iEndPoint secondaryTarget) throws PBXException; + // + // + // /** + // * Splits a call (with two channels) sending the originating channel to + // the + // * originatingTarget and other channel to the secondaryTarget. + // * + // * This method returns immediately with progress information passed to the + // * given callback. Note: the callback method will be called from a + // different + // * thread. + // * + // * @param callToSplit + // * @param originatingTarget + // * @param secondaryTarget + // * @return + // */ + // public iSplitActivity split(final iCall callToSplit, final iEndPoint + // originatingTarget, + // final iEndPoint secondaryTarget, final iCallback + // listener); + + public SplitActivity split(final Call callToSplit, final ActivityCallback listener) throws PBXException; + + public SplitActivity split(final Call callToSplit) throws PBXException; + + /** + * Joins two calls not returning until the join completes. Each call must + * only have one active channel + */ + public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, + CallDirection direction); + + public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, + CallDirection direction, ActivityCallback listener); + + /** + * Returns the channel currently attached to the given end point, if one + * exists. If no channel is attached to the given end point then null is + * returned. + * + * @return the channel attached to the end point or null if the endpoint is + * not currently in a call. + */ + Channel getChannelByEndPoint(EndPoint endPoint); + + // /** + // * Converts a String representation of an extension into an extension + // object. + // * + // * The conversion is PBX specific. + // * + // * @param extension + // * @return + // */ + // iExtension getExtension(String extension); + + /** + * Builds an end point from a fully qualified end point name. A fully + * qualified name includes the tech. How the tech is encoded is pbx + * specific. + * + * @param fullyQualifiedEndPointName + * @return + */ + EndPoint buildEndPoint(String fullyQualifiedEndPointName); + + /** + * Builds an iEndPoint from an end point name. If the tech isn't passed in + * the endPointName the tech is set to the defaultTech The encoding for an + * end point name is pbx specific. + * + * @param endPointName + * @return + */ + EndPoint buildEndPoint(String endPointName, TechType defaultTech); + + void transferToMusicOnHold(Channel channel) throws PBXException; + + CallerID buildCallerID(String number, String name); + + boolean isChannel(String channel); + + boolean waitForChannelsToQuiescent(List channels, long timeout); + + EndPoint getExtensionAgi(); + + public boolean waitForChannelToQuiescent(Channel channel, int timeout); + + +} diff --git a/src/main/java/org/asteriskjava/pbx/PBXException.java b/src/main/java/org/asteriskjava/pbx/PBXException.java new file mode 100644 index 000000000..fe754e0ca --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/PBXException.java @@ -0,0 +1,25 @@ +package org.asteriskjava.pbx; + +import org.apache.log4j.Logger; + +public class PBXException extends Exception +{ + private static final long serialVersionUID = 1L; + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(PBXException.class); + + public PBXException(String message, final Exception e) + { + super(message, e); + } + + public PBXException(final String message) + { + super(message); + } + + public PBXException(Throwable e) + { + super(e); + } +} diff --git a/src/main/java/org/asteriskjava/pbx/PBXFactory.java b/src/main/java/org/asteriskjava/pbx/PBXFactory.java new file mode 100644 index 000000000..d111a5070 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/PBXFactory.java @@ -0,0 +1,14 @@ +package org.asteriskjava.pbx; + +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class PBXFactory +{ + + public static PBX getActivePBX() + { + return AsteriskPBX.SELF; + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/PhoneNumber.java b/src/main/java/org/asteriskjava/pbx/PhoneNumber.java new file mode 100644 index 000000000..31c99e165 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/PhoneNumber.java @@ -0,0 +1,18 @@ +package org.asteriskjava.pbx; + +/** + * Provides an abstraction of a phone number. This allows different PBX's to + * store the phone numbers in a way that may be specific to the pbx. + * + * In general most PBX's there is no need for a special abstraction, however + * using the interface just makes the code clearer that we are passing a phone + * number. + * + * @author bsutton + * + */ +public interface PhoneNumber +{ + // TODO + +} diff --git a/src/main/java/org/asteriskjava/pbx/Tech.java b/src/main/java/org/asteriskjava/pbx/Tech.java new file mode 100644 index 000000000..954834e22 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/Tech.java @@ -0,0 +1,6 @@ +package org.asteriskjava.pbx; + +public interface Tech +{ + // TODO: do we need this? +} diff --git a/src/main/java/org/asteriskjava/pbx/Trunk.java b/src/main/java/org/asteriskjava/pbx/Trunk.java new file mode 100644 index 000000000..f2f475f9d --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/Trunk.java @@ -0,0 +1,10 @@ +package org.asteriskjava.pbx; + +/** + * Provides an abstraction of a trunk * @author bsutton + * + */ +public interface Trunk +{ + // TODO: implement +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java b/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java new file mode 100644 index 000000000..27aec8bf1 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java @@ -0,0 +1,153 @@ +package org.asteriskjava.pbx.activities; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Activity; +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SetVarAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; + +public abstract class ActivityHelper extends EventListenerBaseClass implements Runnable, Activity +{ + static private Logger logger = Logger.getLogger(ActivityHelper.class); + + /** + * If the activity fails due to an exception then lastException will contain + * the final exception that was thrown. + */ + private PBXException lastException; + + /** + * Set to true once the activity succeeds. + */ + private volatile boolean _success = false; + + private final ActivityCallback callback; + + private final String activityName; + + private boolean _sendEvents; + + Exception callSite = new Exception("Invoked from here"); + + public ActivityHelper(final String activityName, final ActivityCallback callback) + { + super(activityName); + this.callback = callback; + this.activityName = activityName; + } + + @SuppressWarnings("unchecked") + public void startActivity(final boolean sendEvents) + { + this._sendEvents = sendEvents; + if (this.callback != null) + { + this.callback.start((T) this); + } + + final Thread thread = new Thread(this, this.activityName); + thread.setDaemon(true); + thread.start(); + + } + + @Override + @SuppressWarnings("unchecked") + public void run() + { + try (EventListenerBaseClass.AutoClose closer = new EventListenerBaseClass.AutoClose(this, this._sendEvents)) + { + this._success = this.doActivity(); + } + catch (final PBXException e) + { + this.lastException = e; + ActivityHelper.logger.error(e, e); + logger.error(callSite, callSite); + } + catch (final Throwable e) + { + this.lastException = new PBXException(e); + ActivityHelper.logger.error(callSite, callSite); + logger.error(e, e); + } + finally + { + if (this.callback != null) + { + if (this._success) + { + this.callback.completed((T) this, true); + } + else + { + // This went badly so make certain we hang everything up + this.callback.completed((T) this, false); + } + } + } + + } + + abstract protected boolean doActivity() throws PBXException; + + /* + * Attempt to set a variable on the channel to see if it's up. + * + * @param channel the channel which is to be tested. + */ + public boolean validateChannel(final Channel channel) + { + + boolean ret = false; + final SetVarAction var = new SetVarAction(channel, "testState", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + + ManagerResponse response = null; + try + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + response = pbx.sendAction(var, 500); + } + catch (final Exception e) + { + ActivityHelper.logger.debug(e, e); + ActivityHelper.logger.error("getVariable: " + e); //$NON-NLS-1$ + } + if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) //$NON-NLS-1$ //$NON-NLS-2$ + { + ret = true; + } + + return ret; + + } + + @Override + public boolean isSuccess() + { + return this._success; + } + + protected void setLastException(final PBXException e) + { + this.lastException = e; + } + + @Override + public Throwable getLastException() + { + return this.lastException; + } + + public void progess(final T activity, final String message) + { + this.callback.progess(activity, message); + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java b/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java new file mode 100644 index 000000000..e18527f6e --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java @@ -0,0 +1,64 @@ +package org.asteriskjava.pbx.activities; + +import org.asteriskjava.pbx.Activity; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBXException; + +public interface BlindTransferActivity extends Activity +{ + /** + * A bridged call is a successful transfer all other options are a failed + * transfer. + * + * @author bsutton + * + */ + enum CompletionCause + { + // The call was bridged. + BRIDGED("Connected") + // The call hungup + , HANGUP("Transfer Failed, Caller Hungup or Destination Busy") + // A timeout occur during the transfer + // which essentially means the transferTarget didn't answer the phone + , TIMEOUT("Transfer Failed, Timeout") + // The cancel method was called. + , CANCELLED("Transfer Cancelled"); + + String message; + + CompletionCause(String message) + { + this.message = message; + } + + public String getMessage() + { + return message; + } + } + + Channel getChannelToTransfer(); + + CallerID getTransferTargetCallerID(); + + EndPoint getTransferTarget(); + + Channel getTransferTargetChannel(); + + CompletionCause getCompletionCause(); + + void cancel(); + + /** + * The call created as a result of the blind transfer being answered. + * + * @return + * @throws PBXException + */ + Call getNewCall() throws PBXException; + +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivityImpl.java new file mode 100644 index 000000000..7b3e4f655 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivityImpl.java @@ -0,0 +1,308 @@ +package org.asteriskjava.pbx.activities; + +import java.util.HashSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.Call.OperandChannel; +import org.asteriskjava.pbx.CallDirection; +import org.asteriskjava.pbx.CallImpl; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityBlindTransfer; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.DialEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.LinkEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ChannelProxy; +import org.asteriskjava.pbx.internal.core.ListenerPriority; + +/** + * The BlindTransferActivity is used by the AsteriksPBX to transfer a live + * channel to an endpoint that may need to be dialed. + * + * @author bsutton + */ +public class BlindTransferActivityImpl extends ActivityHelper implements BlindTransferActivity +{ + static Logger logger = Logger.getLogger(BlindTransferActivityImpl.class); + + private Call _call; + + private Call.OperandChannel _channelToTransfer; + + private EndPoint _transferTarget; + + private CallerID _toCallerID; + + private boolean _autoAnswer; + + private CountDownLatch _latch; + + private CompletionCause _completionCause; + + private long _timeout; + + /** + * The new channel that was originated for the transferTarget endpoint. + */ + private Channel _transferTargetChannel; + + private CallImpl _newCall; + + private ChannelProxy dialedChannel; + + final Channel actualChannelToTransfer; + + /** + * Blind transfers a live channel to a given endpoint which may need to be + * dialed. When we dial the endpoint we display the 'toCallerID'. + * + * @param channelToTransfer The channel which is being transfered + * @param transferTarget The target to transfer (connect) the channel to. + * @param toCallerID The caller id to display on the target endpoint. + * @param timeout The time to wait (in seconds) for the activity to + * complete. + * @param listener + */ + public BlindTransferActivityImpl(Call call, final Call.OperandChannel channelToTransfer, final EndPoint transferTarget, + final CallerID toCallerID, boolean autoAnswer, long timeout, + final ActivityCallback listener) + { + super("BlindTransferActivity", listener); //$NON-NLS-1$ + + this._call = call; + this._channelToTransfer = channelToTransfer; + this._transferTarget = transferTarget; + this._toCallerID = toCallerID; + this._autoAnswer = autoAnswer; + this._timeout = timeout; + + actualChannelToTransfer = _call.getOperandChannel(this._channelToTransfer); + + this.startActivity(true); + } + + public BlindTransferActivityImpl(Channel agentChannel, EndPoint transferTarget, CallerID toCallerID, boolean autoAnswer, + int timeout, ActivityCallback iCallback) throws PBXException + { + super("BlindTransferActivity", iCallback); //$NON-NLS-1$ + + this._transferTarget = transferTarget; + this._toCallerID = toCallerID; + this._autoAnswer = autoAnswer; + this._timeout = timeout; + actualChannelToTransfer = agentChannel; + _channelToTransfer = OperandChannel.ORIGINATING_PARTY; + this._call = new CallImpl(agentChannel, CallDirection.OUTBOUND); + this.startActivity(true); + + } + + @Override + public boolean doActivity() throws PBXException + { + + boolean success = false; + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + /* + * initiate a blind transfer of the call , to the specified destination. + * when a link event occurs this call will be removed from the active + * call list. + */ + try + { + + logger.info("*******************************************************************************"); //$NON-NLS-1$ + logger.info("*********** begin blind transfer ****************"); //$NON-NLS-1$ + logger.info("*********** " + this._channelToTransfer //$NON-NLS-1$ + + " ****************"); //$NON-NLS-1$ + logger.info("*********** " + this._transferTarget //$NON-NLS-1$ + + " ****************"); //$NON-NLS-1$ + logger.info("*********** " + this._toCallerID + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + logger.info("*******************************************************************************"); //$NON-NLS-1$ + + if (!pbx.moveChannelToAgi(actualChannelToTransfer)) + { + throw new PBXException("Channel: " + this._channelToTransfer + " couldn't be moved to agi"); + } + + if (!pbx.waitForChannelToQuiescent(actualChannelToTransfer, 3000)) + throw new PBXException( + "Channel: " + this._channelToTransfer + " cannot be transfered as it is still in transition."); + + // Set or clear the auto answer header. + // Clearing is important as it may have been set during the + // initial answer sequence. If we don't clear it then then transfer + // target will be auto-answered, which is fun but bad. + String sipHeader = null; + if (this._autoAnswer) + { + sipHeader = PBXSettingsManager.getActiveProfile().getAutoAnswer(); + } + actualChannelToTransfer.setCurrentActivityAction( + new AgiChannelActivityBlindTransfer(this._transferTarget.getFullyQualifiedName(), sipHeader)); + + // TODO: At one point we were adding the /n option to the end of the + // channel to get around + // secondary transfer options. Need to review if this is still + // required. + // TODO control the caller id. + this._latch = new CountDownLatch(1); + + success = this._latch.await(this._timeout, TimeUnit.SECONDS); + if (!success) + { + this._completionCause = CompletionCause.TIMEOUT; + } + else if (_completionCause == CompletionCause.CANCELLED) + { + pbx.hangup(dialedChannel); + } + + else + { + Call call = ((CallImpl) _call).split(actualChannelToTransfer); + Call rhsCall = new CallImpl(_transferTargetChannel, CallDirection.OUTBOUND); + try + { + _newCall = ((CallImpl) call).join(OperandChannel.ORIGINATING_PARTY, rhsCall, + OperandChannel.ORIGINATING_PARTY, CallDirection.OUTBOUND); + } + catch (Exception e) + { + logger.error("New call doesn't seem to exist!?"); + } + } + } + catch (final Exception e) + { + logger.error("error occurred in blindtransfer", e); //$NON-NLS-1$ + this.setLastException(new PBXException(e)); + } + + return this._completionCause == CompletionCause.BRIDGED; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + required.add(BridgeEvent.class); + required.add(LinkEvent.class); + required.add(UnlinkEvent.class); + required.add(HangupEvent.class); + required.add(DialEvent.class); + return required; + } + + @Override + synchronized public void onManagerEvent(final ManagerEvent event) + { + if (event instanceof BridgeEvent) + { + BridgeEvent bridge = (BridgeEvent) event; + if (bridge.isLink()) + { + if (bridge.getChannel1().isSame(_call.getOperandChannel(this._channelToTransfer))) + { + this._completionCause = CompletionCause.BRIDGED; + this._transferTargetChannel = bridge.getChannel2(); + this._latch.countDown(); + } + else if (bridge.getChannel2().isSame(_call.getOperandChannel(this._channelToTransfer))) + { + this._completionCause = CompletionCause.BRIDGED; + this._transferTargetChannel = bridge.getChannel1(); + this._latch.countDown(); + } + } + } + else if (event instanceof HangupEvent) + { + HangupEvent hangup = (HangupEvent) event; + if (hangup.getChannel().isSame(_call.getOperandChannel(this._channelToTransfer))) + { + this._completionCause = CompletionCause.HANGUP; + this._latch.countDown(); + } + if (hangup.getChannel().isSame(dialedChannel)) + { + this._completionCause = CompletionCause.HANGUP; + this._latch.countDown(); + } + } + else if (event instanceof DialEvent) + { + if (((DialEvent) event).getChannel().isSame(_call.getOperandChannel(_channelToTransfer))) + { + DialEvent de = (DialEvent) event; + dialedChannel = de.getDestination(); + } + } + + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + @Override + public CompletionCause getCompletionCause() + { + return this._completionCause; + } + + /** + * cancels the BlindTransfer. + */ + @Override + public void cancel() + { + this._completionCause = CompletionCause.CANCELLED; + this._latch.countDown(); + } + + @Override + public Channel getChannelToTransfer() + { + return _call.getOperandChannel(this._channelToTransfer); + } + + @Override + public CallerID getTransferTargetCallerID() + { + return this._toCallerID; + } + + @Override + public EndPoint getTransferTarget() + { + return this._transferTarget; + } + + @Override + public Channel getTransferTargetChannel() + { + return this._transferTargetChannel; + } + + @Override + public Call getNewCall() throws PBXException + { + return _newCall; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/BridgeActivity.java b/src/main/java/org/asteriskjava/pbx/activities/BridgeActivity.java new file mode 100644 index 000000000..11fbd13dc --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/BridgeActivity.java @@ -0,0 +1,8 @@ +package org.asteriskjava.pbx.activities; + +import org.asteriskjava.pbx.Activity; + +public interface BridgeActivity extends Activity +{ + // TODO +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/BridgeActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/BridgeActivityImpl.java new file mode 100644 index 000000000..3dd51b96b --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/BridgeActivityImpl.java @@ -0,0 +1,163 @@ +package org.asteriskjava.pbx.activities; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityBridge; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHoldForBridge; +import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusCompleteEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ListenerPriority; +import org.asteriskjava.pbx.internal.managerAPI.RedirectToMeetMe; + +public class BridgeActivityImpl extends ActivityHelper implements BridgeActivity +{ + static Logger logger = Logger.getLogger(BridgeActivityImpl.class); + private final Channel _lhsChannel; + private final Channel _rhsChannel; + + private CountDownLatch _bridgeLatch; + + public BridgeActivityImpl(final Channel lhsChannel, final Channel rhsChannel, + final ActivityCallback callback) + { + super("Bridge", callback); //$NON-NLS-1$ + + this._lhsChannel = lhsChannel; + this._rhsChannel = rhsChannel; + this.startActivity(true); + } + + @Override + public boolean doActivity() throws PBXException + { + boolean success = false; + + BridgeActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + BridgeActivityImpl.logger.info("*********** begin Bridge ****************"); //$NON-NLS-1$ + BridgeActivityImpl.logger.info("*********** lhs:" + this._lhsChannel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + BridgeActivityImpl.logger.info("*********** rhs:" + this._rhsChannel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + BridgeActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + try + { + + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + if (!pbx.moveChannelToAgi(_lhsChannel)) + { + throw new PBXException("Channel: " + _lhsChannel + " couldn't be moved to agi"); + } + if (!pbx.moveChannelToAgi(_rhsChannel)) + { + throw new PBXException("Channel: " + _rhsChannel + " couldn't be moved to agi"); + } + + List channels = new LinkedList<>(); + channels.add(this._lhsChannel); + channels.add(_rhsChannel); + if (!pbx.waitForChannelsToQuiescent(channels, 3000)) + throw new PBXException( + "Channel: " + this._lhsChannel + " cannot be held as it is still in transition."); + try + { + if (pbx.isBridgeSupported()) + { + + this._bridgeLatch = new CountDownLatch(1); + final AgiChannelActivityBridge action = new AgiChannelActivityBridge(_lhsChannel); + _lhsChannel.setCurrentActivityAction(new AgiChannelActivityHoldForBridge(action)); + _rhsChannel.setCurrentActivityAction(action); + + // now wait for the bridge event to arrive. + success = this._bridgeLatch.await(3, TimeUnit.SECONDS); + + } + else if (pbx.isMeetmeInstalled()) + { + // As bridge isn't supported we need to do the bridge using + // a + // meetme + // room + + final RedirectToMeetMe meetmeTransfer = new RedirectToMeetMe(); + // meetme room is empty + // find a new available room. + MeetmeRoom room = pbx.acquireMeetmeRoom(); + + // redirect the lhs to meetme + meetmeTransfer.redirectToMeetme(_lhsChannel, room.getRoomNumber(), true); + + // redirect destination this is not the marked call + // as we want this to be hung up if no other calls are left + // in + // this + // room + final boolean markedCall = !_rhsChannel.canDetectHangup(); + meetmeTransfer.redirectToMeetme(_rhsChannel, room.getRoomNumber(), markedCall); + + // TODO put some logic to check that the meetme actually + // completes. + success = true; + + } + else + throw new PBXException( + "Cannot bridge two calls as neither the BridgeAction nor Meetme is available"); //$NON-NLS-1$ + } + catch (IllegalArgumentException | IllegalStateException | InterruptedException e) + { + throw new PBXException(e); + } + + } + catch (IllegalArgumentException | IllegalStateException e) + { + BridgeActivityImpl.logger.error(e, e); + BridgeActivityImpl.logger.error(e, e); + throw new PBXException(e); + } + return success; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + required.add(StatusCompleteEvent.class); + required.add(StatusEvent.class); + required.add(BridgeEvent.class); + return required; + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + + if (event instanceof BridgeEvent) + { + BridgeEvent bridge = (BridgeEvent) event; + if (bridge.isLink() + && (bridge.getChannel1().isSame(this._lhsChannel) || bridge.getChannel1().isSame(this._rhsChannel)) + && (bridge.getChannel2().isSame(this._lhsChannel) || bridge.getChannel2().isSame(this._rhsChannel))) + this._bridgeLatch.countDown(); + } + } +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialActivity.java b/src/main/java/org/asteriskjava/pbx/activities/DialActivity.java new file mode 100644 index 000000000..1e618634f --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/DialActivity.java @@ -0,0 +1,49 @@ +package org.asteriskjava.pbx.activities; + +import org.asteriskjava.pbx.Activity; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; + +public interface DialActivity extends Activity +{ + /** + * Returns the end point which originated the dial. + */ + EndPoint getOriginatingEndPoint(); + + /** + * Returns the end point which is being dialed. This is available even + * before the dial commences. + */ + EndPoint getAcceptingEndPoint(); + + /** + * Returns the 'originating' channel which is brought up as part of the dial + * activity. The 'originating' channel may return null if the channel is not + * up. + * + * @return the 'originating' channel if it has been brought up otherwise + * null. + */ + Channel getOriginatingChannel(); + + /** + * Returns the 'accepting' channel which is brought up as part of the dial + * activity. The accepting party is the party that answers the call. The + * 'accepting' channel may return null if the channel is not up. + * + * @return the 'accepting' channel if it has been brought up otherwise null + */ + Channel getAcceptingChannel(); + + /** + * Call markCancelled if you want to stop a dial which is in progress from + * completing. This allows a user to cancel a dial. + */ + void markCancelled(); + + boolean cancelledByOperator(); + + Call getNewCall(); +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java new file mode 100644 index 000000000..a3bf0f5fb --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java @@ -0,0 +1,273 @@ +package org.asteriskjava.pbx.activities; + +import java.util.HashSet; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.CallDirection; +import org.asteriskjava.pbx.CallImpl; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.NewChannelListener; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.Trunk; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SetVarAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ListenerPriority; +import org.asteriskjava.pbx.internal.managerAPI.Dial; +import org.asteriskjava.pbx.internal.managerAPI.OriginateResult; + +public class DialActivityImpl extends ActivityHelper implements DialActivity, NewChannelListener +{ + static Logger logger = Logger.getLogger(DialActivityImpl.class); + + private final boolean hideToCallerId; + + private boolean cancelledByOperator; + + @SuppressWarnings("unused") + private final Trunk trunk; + + private final EndPoint _originating; + + /** + * Once the 'from' channel has been brought up this is set. + */ + private Channel originatingChannel; + + private final EndPoint _accepting; + + private final CallerID toCallerID; + + /** + * Once the 'to' channel has been brought up this is set. + */ + private Channel acceptingChannel; + + private CallImpl newCall; + + private Map channelVarsToSet; + + public DialActivityImpl(final Trunk trunk, final EndPoint originating, final EndPoint accepting, + final CallerID toCallerID, final boolean hideToCallerID, final ActivityCallback listener, + Map channelVarsToSet) + { + super("Dial", listener); //$NON-NLS-1$ + this.trunk = trunk; + this._originating = originating; + this._accepting = accepting; + this.toCallerID = toCallerID; + this.hideToCallerId = hideToCallerID; + this.cancelledByOperator = false; + this.channelVarsToSet = channelVarsToSet; + + this.startActivity(false); + } + + @Override + public boolean doActivity() throws PBXException + { + boolean success = false; + + try (Dial nr = new Dial(this.toCallerID.toString())) + { + DialActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + DialActivityImpl.logger.info("*********** begin dial out ****************"); //$NON-NLS-1$ + DialActivityImpl.logger.info("*********** " + this._accepting //$NON-NLS-1$ + + " ****************"); //$NON-NLS-1$ + DialActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + + final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + + final OriginateResult[] resultChannels = nr.dial(this, this._originating, this._accepting, + profile.getManagementContext(), this.toCallerID, this.hideToCallerId, channelVarsToSet); + + if ((resultChannels[0] == null) || (resultChannels[1] == null)) + { + // the dial failed + + // so notify the operator. + // Unless the operated cancelled the call + if (!this.cancelledByOperator) + { + this.setLastException(new PBXException(("OperatorEndedCall")));//$NON-NLS-1$ + DialActivityImpl.logger.error("dialout to " + this._accepting.getFullyQualifiedName() + " failed."); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + else + { + // Dial succeeded. + + // - get new channel name from result + this.originatingChannel = resultChannels[0].getChannel(); + this.acceptingChannel = resultChannels[1].getChannel(); + + newCall = new CallImpl(originatingChannel, acceptingChannel, CallDirection.OUTBOUND); + + DialActivityImpl.logger.debug("dialout succeeded: dest channel is :" + this.acceptingChannel); //$NON-NLS-1$ + + if (this.validateChannel(this.acceptingChannel) == false) + { + this.setLastException(new PBXException(("dialed extension hungup unexpectedly")));//$NON-NLS-1$ + DialActivityImpl.logger.error("dialed extension hungup unexpectedly"); //$NON-NLS-1$ + } + else + { + success = true; + } + } + } + finally + { + if (success != true) + { + this.hangup(); + } + } + return success; + } + + private void hangup() + { + try + { + final PBX pbx = PBXFactory.getActivePBX(); + if (this.acceptingChannel != null) + { + pbx.hangup(this.acceptingChannel); + } + if (this.originatingChannel != null) + { + pbx.hangup(this.originatingChannel); + } + } + catch (final Exception e) + { + DialActivityImpl.logger.error(e, e); + } + } + + /** + * Called if the user cancels the call after starting it. The caller must + * also hangup the trc channel. + */ + @Override + public void markCancelled() + { + this.cancelledByOperator = true; + } + + @Override + public Channel getOriginatingChannel() + { + return this.originatingChannel; + } + + @Override + public Channel getAcceptingChannel() + { + return this.acceptingChannel; + } + + @Override + public EndPoint getOriginatingEndPoint() + { + return this._originating; + } + + @Override + public EndPoint getAcceptingEndPoint() + { + return this._accepting; + } + + @Override + public void channelUpdate(final Channel channel) + { + if (channel.sameEndPoint(this._accepting)) + { + this.acceptingChannel = channel; + } + + if (channel.sameEndPoint(this._originating)) + { + this.originatingChannel = channel; + } + + super.progess(this, "Channel for " + channel.getEndPoint().getSIPSimpleName() + " is now up."); //$NON-NLS-1$ //$NON-NLS-2$ + + } + + /* + * Attempt to set a variable on the channel to see if it's up. + * @param channel the channel which is to be tested. + */ + @Override + public boolean validateChannel(final Channel channel) + { + + boolean ret = false; + final SetVarAction var = new SetVarAction(channel, "testState", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + + ManagerResponse response = null; + try + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + response = pbx.sendAction(var, 500); + } + catch (final Exception e) + { + DialActivityImpl.logger.debug(e, e); + DialActivityImpl.logger.error("getVariable: " + e); //$NON-NLS-1$ + } + if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) //$NON-NLS-1$ //$NON-NLS-2$ + { + ret = true; + } + + return ret; + + } + + @Override + public boolean cancelledByOperator() + { + return this.cancelledByOperator; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + // no required. + return required; + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + // NOOP + } + + @Override + public Call getNewCall() + { + return newCall; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java new file mode 100644 index 000000000..db557e4fb --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java @@ -0,0 +1,18 @@ +package org.asteriskjava.pbx.activities; + +import org.asteriskjava.pbx.Activity; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; + +public interface DialToAgiActivity extends Activity +{ + + void markCancelled(); + + boolean cancelledByOperator(); + + EndPoint getOriginatingEndPoint(); + + Channel getOriginatingChannel(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivityImpl.java new file mode 100644 index 000000000..2b9748769 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivityImpl.java @@ -0,0 +1,225 @@ +package org.asteriskjava.pbx.activities; + +import java.util.HashSet; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.NewChannelListener; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SetVarAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ListenerPriority; +import org.asteriskjava.pbx.internal.managerAPI.DialToAgi; +import org.asteriskjava.pbx.internal.managerAPI.OriginateResult; + +public class DialToAgiActivityImpl extends ActivityHelper implements DialToAgiActivity, NewChannelListener +{ + static Logger logger = Logger.getLogger(DialToAgiActivityImpl.class); + + private final boolean hideToCallerId; + + private boolean cancelledByOperator; + + private final EndPoint _originating; + + /** + * Once the 'from' channel has been brought up this is set. + */ + private Channel originatingChannel; + + private final CallerID toCallerID; + + private Map channelVarsToSet; + + private AgiChannelActivityAction action; + + public DialToAgiActivityImpl(final EndPoint originating, final CallerID toCallerID, final boolean hideToCallerID, + final ActivityCallback listener, Map channelVarsToSet, + AgiChannelActivityAction action) + { + super("Dial", listener); //$NON-NLS-1$ + + this.action = action; + this._originating = originating; + this.toCallerID = toCallerID; + this.hideToCallerId = hideToCallerID; + this.cancelledByOperator = false; + this.channelVarsToSet = channelVarsToSet; + + this.startActivity(false); + } + + @Override + public boolean doActivity() throws PBXException + { + boolean success = false; + + try (DialToAgi nr = new DialToAgi(this.toCallerID.toString())) + { + DialToAgiActivityImpl.logger.info("**************************************************************************"); + DialToAgiActivityImpl.logger.info("*********** begin dial out ***********"); + DialToAgiActivityImpl.logger.info("*********** to agi ***********"); + DialToAgiActivityImpl.logger.info("**************************************************************************"); + + final OriginateResult[] resultChannels = nr.dial(this, this._originating, this.action, this.toCallerID, + this.hideToCallerId, channelVarsToSet); + + if (resultChannels[0] == null || !resultChannels[0].isSuccess()) + { + // the dial failed + + // so notify the operator. + // Unless the operated cancelled the call + if (!this.cancelledByOperator) + { + this.setLastException(new PBXException(("OperatorEndedCall"))); + logger.error("dialout to failed."); + } + } + else + { + // Dial succeeded. + + // - get new channel name from result + this.originatingChannel = resultChannels[0].getChannel(); + + DialToAgiActivityImpl.logger.debug("dialout succeeded"); + + success = true; + + } + } + catch (InterruptedException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + finally + { + if (success != true) + { + this.hangup(); + } + } + return success; + } + + private void hangup() + { + try + { + final PBX pbx = PBXFactory.getActivePBX(); + + if (this.originatingChannel != null) + { + pbx.hangup(this.originatingChannel); + } + } + catch (final Exception e) + { + DialToAgiActivityImpl.logger.error(e, e); + } + } + + /** + * Called if the user cancels the call after starting it. The caller must + * also hangup the trc channel. + */ + @Override + public void markCancelled() + { + this.cancelledByOperator = true; + } + + @Override + public Channel getOriginatingChannel() + { + return this.originatingChannel; + } + + @Override + public EndPoint getOriginatingEndPoint() + { + return this._originating; + } + + @Override + public void channelUpdate(final Channel channel) + { + + if (channel.sameEndPoint(this._originating)) + { + this.originatingChannel = channel; + } + + super.progess(this, "Channel for " + channel.getEndPoint().getSIPSimpleName() + " is now up."); //$NON-NLS-1$ //$NON-NLS-2$ + + } + + /* + * Attempt to set a variable on the channel to see if it's up. + * @param channel the channel which is to be tested. + */ + @Override + public boolean validateChannel(final Channel channel) + { + + boolean ret = false; + final SetVarAction var = new SetVarAction(channel, "testState", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + + ManagerResponse response = null; + try + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + response = pbx.sendAction(var, 500); + } + catch (final Exception e) + { + DialToAgiActivityImpl.logger.debug(e, e); + DialToAgiActivityImpl.logger.error("getVariable: " + e); //$NON-NLS-1$ + } + if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) //$NON-NLS-1$ //$NON-NLS-2$ + { + ret = true; + } + + return ret; + + } + + @Override + public boolean cancelledByOperator() + { + return this.cancelledByOperator; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + // no required. + return required; + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + // NOOP + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java b/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java new file mode 100644 index 000000000..8f372c711 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java @@ -0,0 +1,8 @@ +package org.asteriskjava.pbx.activities; + +import org.asteriskjava.pbx.Activity; + +public interface HoldActivity extends Activity +{ + // TODO +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/HoldActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/HoldActivityImpl.java new file mode 100644 index 000000000..dfa6eee33 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/HoldActivityImpl.java @@ -0,0 +1,81 @@ +package org.asteriskjava.pbx.activities; + +import java.util.HashSet; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHold; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ListenerPriority; + +public class HoldActivityImpl extends ActivityHelper implements HoldActivity +{ + static Logger logger = Logger.getLogger(HoldActivityImpl.class); + private final Channel _channel; + + public HoldActivityImpl(final Channel channel, final ActivityCallback callback) + { + super("HoldCall", callback); //$NON-NLS-1$ + + this._channel = channel; + this.startActivity(false); + } + + @Override + public boolean doActivity() throws PBXException + { + boolean success = false; + + HoldActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + HoldActivityImpl.logger.info("*********** begin Hold Audio ****************"); //$NON-NLS-1$ + HoldActivityImpl.logger.info("*********** " + this._channel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + HoldActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + try + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + if (!pbx.moveChannelToAgi(_channel)) + { + throw new PBXException("Channel: " + _channel + " couldn't be moved to agi"); + } + + _channel.setCurrentActivityAction(new AgiChannelActivityHold()); + success = true; + + } + catch (IllegalArgumentException | IllegalStateException e) + { + HoldActivityImpl.logger.error(e, e); + HoldActivityImpl.logger.error(e, e); + throw new PBXException(e); + } + return success; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + // no events requried. + + return required; + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + // NOOP + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/JoinActivity.java b/src/main/java/org/asteriskjava/pbx/activities/JoinActivity.java new file mode 100644 index 000000000..30acf65cd --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/JoinActivity.java @@ -0,0 +1,10 @@ +package org.asteriskjava.pbx.activities; + +import org.asteriskjava.pbx.Activity; +import org.asteriskjava.pbx.Call; + +public interface JoinActivity extends Activity +{ + Call getJoinedCall(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/JoinActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/JoinActivityImpl.java new file mode 100644 index 000000000..3f7f49d13 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/JoinActivityImpl.java @@ -0,0 +1,175 @@ +package org.asteriskjava.pbx.activities; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.CallDirection; +import org.asteriskjava.pbx.CallImpl; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.Call.OperandChannel; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ListenerPriority; + +/** + * The JoinActivity is used by the AsteriksPBX implementation to Join two + * channels into a single call. The join activity expects two channels which are + * each a leg of a different call it will then join those two channels into a + * single call.iChannel hangupChannel, The channels that remain in the + * originating calls will be hungup implicitly. + * + * @author bsutton + */ +public class JoinActivityImpl extends ActivityHelper implements JoinActivity +{ + + static Logger logger = Logger.getLogger(JoinActivityImpl.class); + + private final Call _lhsCall; + private final OperandChannel _originatingOperand; + + private final Call _rhsCall; + private final OperandChannel _acceptingOperand; + private final CallDirection _direction; + + private Call _joined; + + private Exception callSite; + + /** + * Joins a specific channel from this call with a specific channel from + * another call which results in a new Call object being created. Channels + * that do not participate in the join are left in their original Call. + * + * @param lhsCall one of the calls we are joining + * @param originatingOperand the channel from lhsCall call that will + * participate in the join as the originating Channel + * @param rhsCall the other call we are joining. + * @param acceptingOperand the channel from the rhsCall that will + * participate in the join as the accepting channel. + * @return + * @throws PBXException + */ + public JoinActivityImpl(final Call lhsCall, OperandChannel originatingOperand, final Call rhsCall, + OperandChannel acceptingOperand, CallDirection direction, final ActivityCallback listener) + { + super("JoinActivity", listener); //$NON-NLS-1$ + + callSite = new Exception("Call site"); + + this._lhsCall = lhsCall; + this._originatingOperand = originatingOperand; + this._rhsCall = rhsCall; + this._acceptingOperand = acceptingOperand; + this._direction = direction; + + if (this._lhsCall == null) + { + throw new IllegalArgumentException("lhsCall may not be null"); //$NON-NLS-1$ + } + + if (this._originatingOperand == null) + { + throw new IllegalArgumentException("lhsOperand may not be null"); //$NON-NLS-1$ + } + + if (this._rhsCall == null) + { + throw new IllegalArgumentException("rhsCall may not be null"); //$NON-NLS-1$ + } + + if (this._acceptingOperand == null) + { + throw new IllegalArgumentException("rhsOperand may not be null"); //$NON-NLS-1$ + } + + + this.startActivity(true); + } + + @Override + public boolean doActivity() throws PBXException + { + boolean success = false; + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + JoinActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + JoinActivityImpl.logger.info("*********** begin join ****************"); //$NON-NLS-1$ + JoinActivityImpl.logger.info("*********** " + this._lhsCall + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + JoinActivityImpl.logger.info("*********** " + this._rhsCall + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + JoinActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + + try + { + final Channel rhsChannel = this._rhsCall.getOperandChannel(this._acceptingOperand); + final Channel lhsChannel = this._lhsCall.getOperandChannel(this._originatingOperand); + + if (!pbx.moveChannelToAgi(rhsChannel)) + { + throw new PBXException("Channel: " + rhsChannel + " couldn't be moved to agi"); + } + if (!pbx.moveChannelToAgi(lhsChannel)) + { + throw new PBXException("Channel: " + lhsChannel + " couldn't be moved to agi"); + } + + List channels = new LinkedList<>(); + channels.add(lhsChannel); + channels.add(rhsChannel); + if (!pbx.waitForChannelsToQuiescent(channels, 3000)) + { + logger.error(callSite, callSite); + throw new PBXException("Channel: " + rhsChannel + + " cannot be joined as it is still in transition."); + } + // Now do the actual join on the pbx. + pbx.bridge(lhsChannel, + rhsChannel); + this._joined = ((CallImpl) this._lhsCall).join(this._originatingOperand, this._rhsCall, this._acceptingOperand, + this._direction); + success = true; + + } + catch (RuntimeException e) + { + logger.error(e, e); + logger.error(callSite, callSite); + throw new PBXException(e); + + } + return success; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + return required; + } + + @Override + synchronized public void onManagerEvent(final ManagerEvent event) + { + // NOOP + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + @Override + public Call getJoinedCall() + { + return this._joined; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/ParkActivity.java b/src/main/java/org/asteriskjava/pbx/activities/ParkActivity.java new file mode 100644 index 000000000..5d4282115 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/ParkActivity.java @@ -0,0 +1,16 @@ +package org.asteriskjava.pbx.activities; + +import org.asteriskjava.pbx.Activity; +import org.asteriskjava.pbx.EndPoint; + +public interface ParkActivity extends Activity +{ + + /** + * Returns the endpoint (parking lot) that the call was park on. + * + * @return + */ + EndPoint getParkingLot(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java new file mode 100644 index 000000000..2508d591c --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java @@ -0,0 +1,186 @@ +package org.asteriskjava.pbx.activities; + +import java.io.IOException; +import java.util.HashSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.asteriskjava.manager.TimeoutException; +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.CallDirection; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ParkedCallEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ListenerPriority; +import org.asteriskjava.pbx.internal.core.TechType; + +/** + * The ParkActivity is used by the AsteriksPBX implementation to park a channel. + * The park activity expects two channels which are two legs legs of the same + * call. The parkChannel will be redirect to the njr-park extension. The + * hangupChannel (the second leg of the call) will be hung up. The (obvious?) + * limitation is that we can't park something like a conference call as it has + * more than two channels. + * + * @author bsutton + */ +public class ParkActivityImpl extends ActivityHelper implements ParkActivity +{ + static Logger logger = Logger.getLogger(ParkActivityImpl.class); + + /** + * call - the call which is being packed. + */ + private final Call _call; + + /** + * parkChannel - the channel from the above call which is going to be + * parked. extension. + */ + private final Channel _parkChannel; + + private volatile EndPoint _parkingLot; + + private final CountDownLatch _latch = new CountDownLatch(1); + + /* + * @param call the that is being parked. + * @param parkChannel the channel from the call which is the one which will + * be parked. All other channels in the call will be hungup. + */ + public ParkActivityImpl(final Call call, final Channel parkChannel, final ActivityCallback listener) + { + super("ParkActivity", listener); //$NON-NLS-1$ + + if (call == null) + { + throw new IllegalArgumentException("call may not be null"); //$NON-NLS-1$ + } + if (parkChannel == null) + { + throw new IllegalArgumentException("parkChannel may not be null"); //$NON-NLS-1$ + } + this._parkChannel = parkChannel; + this._call = call; + + if (!this._call.contains(parkChannel)) + throw new IllegalArgumentException("The parkChannel must be from the call."); //$NON-NLS-1$ + + this.startActivity(true); + } + + @Override + public boolean doActivity() throws PBXException + { + boolean success = false; + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + ParkActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + ParkActivityImpl.logger.info("*********** begin park ****************"); //$NON-NLS-1$ + ParkActivityImpl.logger.info("*********** " + this._parkChannel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + ParkActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + + try + { + final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + + if (!pbx.waitForChannelToQuiescent(this._parkChannel, 3000)) + throw new PBXException("Channel: " + this._parkChannel + " cannot be parked as it is still in transition."); + + // The extension must be a non-qualified name as + // otherwise it would be of the form DIALPLAN/njr-park + final RedirectAction redirect = new RedirectAction(this._parkChannel, profile.getManagementContext(), + pbx.getExtensionPark(), 1); + + final ManagerResponse response = pbx.sendAction(redirect, 1000); + if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0))//$NON-NLS-1$ + { + // Hangup the call as we have parked the other side of + // the call. + if (this._call.getDirection() == CallDirection.INBOUND) + pbx.hangup(this._call.getAcceptingParty()); + else + pbx.hangup(this._call.getOriginatingParty()); + success = true; + } + + } + catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) + { + ParkActivityImpl.logger.error(e, e); + throw new PBXException(e); + + } + finally + { + // we wait at most 2 seconds for the parking extension to + // arrive. + try + { + if (success) + { + this._latch.await(2, TimeUnit.SECONDS); + } + + if (this._parkingLot == null) + { + success = false; + ParkActivityImpl.logger.warn("ParkCallEvent not recieved within 2 seconds of parking call."); //$NON-NLS-1$ + this.setLastException(new PBXException("ParkCallEvent not recieved within 2 seconds of parking call.")); //$NON-NLS-1$ + } + } + catch (final InterruptedException e) + { + ParkActivityImpl.logger.error(e, e); + + } + + } + return success; + } + + @Override + public EndPoint getParkingLot() + { + return this._parkingLot; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + required.add(ParkedCallEvent.class); + + return required; + } + + @Override + synchronized public void onManagerEvent(final ManagerEvent event) + { + assert event instanceof ParkedCallEvent : "Unexpected event"; //$NON-NLS-1$ + + final ParkedCallEvent parkedEvent = (ParkedCallEvent) event; + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this._parkingLot = pbx.buildEndPoint(parkedEvent.getExten(), TechType.LOCAL); + this._latch.countDown(); + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/SplitActivity.java b/src/main/java/org/asteriskjava/pbx/activities/SplitActivity.java new file mode 100644 index 000000000..cfd99fcd9 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/SplitActivity.java @@ -0,0 +1,32 @@ +package org.asteriskjava.pbx.activities; + +import org.asteriskjava.pbx.Activity; +import org.asteriskjava.pbx.Call; + +public interface SplitActivity extends Activity +{ + + /** + * After a call has been split we get a new calls. The call created as a + * result of the lhsOperandChannel being split can be retrieved by calling + * this method. + * + * @return the call which holds the call associated with the + * lhsOperandChannel + */ + Call getLHSCall(); + + /** + * After a call has been split we get a new calls. The call created as a + * result of the rhsOperandChannel being split can be retrieved by calling + * this method. + * + * This method will return now if split was called with only a single + * operand channel. + * + * @return the call which holds the call associated with the + * lhsOperandChannel + */ + Call getRHSCall(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java new file mode 100644 index 000000000..4ffa02b23 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java @@ -0,0 +1,260 @@ +package org.asteriskjava.pbx.activities; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.CallImpl; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHold; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ChannelProxy; +import org.asteriskjava.pbx.internal.core.ListenerPriority; + +/** + * The SplitActivity is used by the AsteriksPBX to split a call and place the + * component channels into two separate destination extension. The SplitActivity + * can only split a call with two channels. The (obvious?) limitation is that we + * can't split something a conference call as it has more than two channels. + * + * @author bsutton + */ +public class SplitActivityImpl extends ActivityHelper implements SplitActivity +{ + static Logger logger = Logger.getLogger(SplitActivityImpl.class); + + private Call _callToSplit; + + private Channel channel1; + + private Channel channel2; + + private Call _lhsCall; + + private Call _rhsCall; + + /** + * Splits a call by moving each of its two channels to different target + * endpoints. The split does not perform a dial so the endpoints need to + * dial plan extensions. + * + * @param callToSplit The call to split + * @param originatingTarget The target to move the calls originating channel + * to. + * @param secondaryTarget The target to move the calls secondary channel to + * @param listener + */ + // public SplitActivity(final iChannel lhs, final iEndPoint + // originatingTarget, final iChannel rhs, final iEndPoint secondaryTarget, + // final iCallback listener) + + /** + * Splits two channels out of a call redirecting each call to a new + * iEndPoint. If the original call only had two channels then it will be + * discarded. + * + * @param callToSplit + * @param listener + */ + public SplitActivityImpl(final Call callToSplit, final ActivityCallback listener) + { + super("SplitActivity", listener); //$NON-NLS-1$ + + this._callToSplit = callToSplit; + + channel1 = callToSplit.getChannels().get(0); + channel2 = callToSplit.getChannels().get(1); + + callToSplit.getChannels(); + + this.startActivity(true); + } + + @Override + public boolean doActivity() throws PBXException + { + + SplitActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + SplitActivityImpl.logger.info("*********** begin split ****************"); //$NON-NLS-1$ + SplitActivityImpl.logger.info("*********** " + this.channel1 + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + SplitActivityImpl.logger.info("*********** " + this.channel2 + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + SplitActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + + // Splits the originating and secondary channels by moving each of them + // into the associated + // target. + boolean success = false; + + if (this.channel2 != null) + { + success = splitTwo(); + + // Now update the call to reflect the split + if (success) + { + this._lhsCall = ((CallImpl) this._callToSplit).split(channel1); + this._rhsCall = ((CallImpl) this._callToSplit).split(channel2); + } + } + // else + // { + // success = + // splitOne(this._callToSplit.getOperandChannel(this._lhsChannel), + // this._lhsTarget, + // profile.getManagementContext()); + // // Now update the call to reflect the split + // if (success) + // this._lhsCall = ((Call) this._callToSplit).split(this._lhsChannel); + // + // } + return success; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + // No events required. + return required; + } + + @Override + synchronized public void onManagerEvent(final ManagerEvent event) + { + // NOOP + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + /** + * After a call has been split we get two new calls. One will hold the + * original remote party and the other will hold the original local party. + * + * @return the call which holds the original remote party. + */ + @Override + public Call getLHSCall() + { + return this._lhsCall; + } + + /** + * After a call has been split we get two new calls. One will hold the + * original remote party and the other will hold the original local party. + * + * @return the call which holds the original local party. + */ + @Override + public Call getRHSCall() + { + return this._rhsCall; + } + + /** + * Splits two channels moving them to defined endpoints. + * + * @param lhs + * @param lhsTarget + * @param lhsTargetContext + * @param rhs + * @param rhsTarget + * @param rhsTargetContext + * @return + * @throws PBXException + */ + private boolean splitTwo() throws PBXException + { + final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + if (channel1 == channel2) + { + throw new NullPointerException( + "channel1 is the same as channel2. if I let this happen, asterisk will core dump :)"); + } + + List channels = new LinkedList<>(); + channels.add(channel1); + channels.add(channel2); + if (!pbx.waitForChannelsToQuiescent(channels, 3000)) + { + logger.error(callSite, callSite); + throw new PBXException( + "Channel: " + channel1 + " or " + channel2 + " cannot be split as they are still in transition."); + } + + /* + * redirects the specified channels to the specified endpoints. Returns + * true or false reflecting success. + */ + + AgiChannelActivityHold agi1 = new AgiChannelActivityHold(); + AgiChannelActivityHold agi2 = new AgiChannelActivityHold(); + + pbx.setVariable(channel1, "proxyId", "" + ((ChannelProxy) channel1).getIdentity()); + pbx.setVariable(channel2, "proxyId", "" + ((ChannelProxy) channel2).getIdentity()); + + channel1.setCurrentActivityAction(agi1); + channel2.setCurrentActivityAction(agi2); + + final String agiExten = profile.getAgiExtension(); + final String agiContext = profile.getManagementContext(); + logger.debug("splitTwo channel lhs:" + channel1 + " to " + agiExten + " in context " + agiContext + " from " + + this._callToSplit); + + final EndPoint extensionAgi = pbx.getExtensionAgi(); + final RedirectAction redirect = new RedirectAction(channel1, agiContext, extensionAgi, 1); + redirect.setExtraChannel(channel2); + redirect.setExtraContext(agiContext); + redirect.setExtraExten(extensionAgi); + redirect.setExtraPriority(1); + // logger.error(redirect); + + boolean ret = false; + { + try + { + + // final ManagerResponse response = + pbx.sendAction(redirect, 1000); + double ctr = 0; + while ((!agi1.hasCallReachedAgi() || !agi2.hasCallReachedAgi()) && ctr < 10) + { + Thread.sleep(100); + ctr += 100.0 / 1000.0; + if (!agi1.hasCallReachedAgi()) + { + logger.error("Waiting on (agi1) " + channel1); + } + if (!agi2.hasCallReachedAgi()) + { + logger.error("Waiting on (agi2) " + channel2); + } + } + ret = agi1.hasCallReachedAgi() && agi2.hasCallReachedAgi(); + + } + catch (final Exception e) + { + logger.error(e, e); + } + } + return ret; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/internal/agi/ActivityAgi.java new file mode 100644 index 000000000..9a2f41b7e --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/ActivityAgi.java @@ -0,0 +1,107 @@ +package org.asteriskjava.pbx.internal.agi; + +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.ChannelHangupListener; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ChannelProxy; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class ActivityAgi extends NJAgiScript +{ + + private final Log logger = LogFactory.getLog(this.getClass()); + + @Override + public void service() throws AgiException + { + ChannelProxy channelProxy = null; + String channelName = channel.getName(); + + try + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + String proxyId = getVariable("proxyId"); + if (proxyId != null && proxyId.length() > 0) + { + channelProxy = pbx.getProxyById(proxyId); + } + if (channelProxy == null) + { + logger.warn("'proxyId' var not set or proxy doesn't exist anymore, trying to match the channel name... " + + channelName); + channelProxy = pbx.registerChannel(channel.getName(), null); + + } + + logger.info("Channel " + channelName + " arrived in agi"); + + channelProxy.setIsInAgi(true); + channelProxy.addHangupListener(new ChannelHangupListener() + { + + @Override + public void channelHangup(Channel channel, Integer cause, String causeText) + { + final AgiChannelActivityAction currentActivityAction = channel.getCurrentActivityAction(); + if (currentActivityAction != null) + { + currentActivityAction.cancel(channel); + } + + } + }); + + AgiChannelActivityAction action = channelProxy.getCurrentActivityAction(); + if (action == null) + { + action = new AgiChannelActivityHold(); + } + + boolean isAlive = true; + RateLimiter rateLimiter = new RateLimiter(2); + while (!action.isDisconnect() && isAlive) + { + + action.execute(this.channel, channelProxy); + + action = channelProxy.getCurrentActivityAction(); + logger.info("Action for proxy " + channelProxy + " is " + action.getClass().getSimpleName()); + isAlive = checkChannelIsStillUp(); + rateLimiter.acquire(); + } + + } + catch (AgiHangupException e) + { + logger.warn("Channel hungup " + channelName); + } + catch (InvalidChannelName | InterruptedException e) + { + logger.error(e, e); + } + + logger.info("Channel leaving agi " + channelName); + + } + + private boolean checkChannelIsStillUp() + { + try + + { + this.answer(); + return true; + } + catch (Exception e) + { + + } + return false; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityAction.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityAction.java new file mode 100644 index 000000000..d4d936d00 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityAction.java @@ -0,0 +1,16 @@ +package org.asteriskjava.pbx.internal.agi; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.pbx.Channel; + +public interface AgiChannelActivityAction +{ + + void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException; + + boolean isDisconnect(); + + void cancel(Channel channel); + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBlindTransfer.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBlindTransfer.java new file mode 100644 index 000000000..569f1d87e --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBlindTransfer.java @@ -0,0 +1,49 @@ +package org.asteriskjava.pbx.internal.agi; + +import java.util.concurrent.CountDownLatch; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.pbx.Channel; + +public class AgiChannelActivityBlindTransfer implements AgiChannelActivityAction +{ + + CountDownLatch latch = new CountDownLatch(1); + private String target; + private String sipHeader; + int timeout = 30; + + public AgiChannelActivityBlindTransfer(String fullyQualifiedName, String sipHeader) + { + this.target = fullyQualifiedName; + this.sipHeader = sipHeader; + if (sipHeader == null) + { + this.sipHeader = ""; + } + } + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + + channel.setVariable("__SIPADDHEADER", sipHeader); + ichannel.setCurrentActivityAction(new AgiChannelActivityHold()); + channel.dial(target, timeout, ""); + + } + + @Override + public boolean isDisconnect() + { + return false; + } + + @Override + public void cancel(Channel channel) + { + latch.countDown(); + + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBridge.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBridge.java new file mode 100644 index 000000000..934b97dfe --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBridge.java @@ -0,0 +1,63 @@ +package org.asteriskjava.pbx.internal.agi; + +import java.util.concurrent.CountDownLatch; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class AgiChannelActivityBridge implements AgiChannelActivityAction +{ + + private Channel target; + private final Log logger = LogFactory.getLog(this.getClass()); + + CountDownLatch latch = new CountDownLatch(1); + + public AgiChannelActivityBridge(Channel target) + { + this.target = target; + } + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + try + { + + channel.bridge(target.getChannelName(), ""); + channel.hangup(); + } + catch (AgiHangupException e) + { + logger.warn(e); + } + finally + { + latch.countDown(); + } + } + + @Override + public boolean isDisconnect() + { + return false; + } + + @Override + public void cancel(Channel channel) + { + latch.countDown(); + + } + // Logger logger = LogManager.getLogger(); + + public void sleepWhileBridged() throws InterruptedException + { + latch.await(); + + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityDial.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityDial.java new file mode 100644 index 000000000..846dcda4d --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityDial.java @@ -0,0 +1,57 @@ +package org.asteriskjava.pbx.internal.agi; + +import java.util.concurrent.CountDownLatch; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.pbx.Channel; + +public class AgiChannelActivityDial implements AgiChannelActivityAction +{ + + CountDownLatch latch = new CountDownLatch(1); + private String target; + private String sipHeader; + + public AgiChannelActivityDial(String target) + { + this.target = target; + } + + public AgiChannelActivityDial(String fullyQualifiedName, String sipHeader) + { + target = fullyQualifiedName; + this.sipHeader = sipHeader; + } + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + if (sipHeader != null) + { + channel.setVariable("__SIPADDHEADER", sipHeader); + } + // setting the activity to hold, means that when the call falls out of + // the dial it'll go to hold. + + // also if some other code sets and activity and then redirects, we + // won't over write it on the way out (if we did it after the dial + // command) + ichannel.setCurrentActivityAction(new AgiChannelActivityHold()); + channel.dial(target, 30, ""); + + } + + @Override + public boolean isDisconnect() + { + return false; + } + + @Override + public void cancel(Channel channel) + { + latch.countDown(); + + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHangup.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHangup.java new file mode 100644 index 000000000..4cc9b1aab --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHangup.java @@ -0,0 +1,46 @@ +package org.asteriskjava.pbx.internal.agi; + +import java.util.concurrent.CountDownLatch; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class AgiChannelActivityHangup implements AgiChannelActivityAction +{ + private final Log logger = LogFactory.getLog(this.getClass()); + + CountDownLatch latch = new CountDownLatch(1); + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + try + { + + channel.hangup(); + logger.info("Hungup"); + } + catch (AgiHangupException e) + { + // don't care + } + + } + + @Override + public boolean isDisconnect() + { + return false; + } + + @Override + public void cancel(Channel channel) + { + latch.countDown(); + + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHold.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHold.java new file mode 100644 index 000000000..a680f1430 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHold.java @@ -0,0 +1,65 @@ +package org.asteriskjava.pbx.internal.agi; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class AgiChannelActivityHold implements AgiChannelActivityAction +{ + private final Log logger = LogFactory.getLog(this.getClass()); + + CountDownLatch latch = new CountDownLatch(1); + volatile boolean callReachedAgi = false; + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + try + { + callReachedAgi = true; + channel.answer(); + channel.playMusicOnHold(); + logger.info(ichannel + " is still on hold"); + if (latch.await(10, TimeUnit.SECONDS)) + { + try + { + channel.stopMusicOnHold(); + } + catch (Exception e) + { + logger.warn(e); + } + } + } + catch (AgiHangupException e) + { + logger.warn(e); + } + + } + + @Override + public boolean isDisconnect() + { + return false; + } + + @Override + public void cancel(Channel channel) + { + latch.countDown(); + + } + + public boolean hasCallReachedAgi() + { + return callReachedAgi; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHoldForBridge.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHoldForBridge.java new file mode 100644 index 000000000..2f897ce17 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHoldForBridge.java @@ -0,0 +1,50 @@ +package org.asteriskjava.pbx.internal.agi; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class AgiChannelActivityHoldForBridge implements AgiChannelActivityAction +{ + private final Log logger = LogFactory.getLog(this.getClass()); + private AgiChannelActivityBridge bridgeActivity; + + public AgiChannelActivityHoldForBridge(AgiChannelActivityBridge bridgeActivity) + { + this.bridgeActivity = bridgeActivity; + } + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + try + { + channel.playMusicOnHold(); + bridgeActivity.sleepWhileBridged(); + + channel.hangup(); + } + catch (AgiHangupException e) + { + logger.warn(e.getMessage() + " " + channel.getName()); + } + + } + + @Override + public boolean isDisconnect() + { + return false; + } + + @Override + public void cancel(Channel channel) + { + // TODO Auto-generated method stub + + } + // Logger logger = LogManager.getLogger(); +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityMeetme.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityMeetme.java new file mode 100644 index 000000000..37b187d0b --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityMeetme.java @@ -0,0 +1,98 @@ +package org.asteriskjava.pbx.internal.agi; + +import java.io.IOException; +import java.util.concurrent.CountDownLatch; + +import org.asteriskjava.AsteriskVersion; +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.manager.TimeoutException; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class AgiChannelActivityMeetme implements AgiChannelActivityAction +{ + private final Log logger = LogFactory.getLog(this.getClass()); + + CountDownLatch latch = new CountDownLatch(1); + private String room; + private volatile boolean hangup = true; + // volatile private iChannel ichannel; + + private String options; + + public AgiChannelActivityMeetme(String room, String options) + { + this.room = room; + this.options = options; + } + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + if (ichannel == null) + { + throw new NullPointerException("ichannel cannot be null"); + } + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) + { + channel.confbridge(room, "transfer"); + } + else + { + channel.meetme(room, options); + } + if (hangup) + { + try + { + channel.hangup(); + } + catch (Exception e) + { + logger.warn(e); + } + } + logger.info(ichannel + " left the meetme"); + + } + + @Override + public boolean isDisconnect() + { + return false; + } + + @Override + public void cancel(Channel channel) + { + + if (channel == null) + { + throw new NullPointerException("channel cannot be null"); + } + + hangup = false; + final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + final RedirectAction redirect = new RedirectAction(channel, profile.getManagementContext(), pbx.getExtensionAgi(), + 1); + try + { + pbx.sendAction(redirect, 1000); + } + catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) + { + logger.error(e, e); + } + + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityQueue.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityQueue.java new file mode 100644 index 000000000..355eef767 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityQueue.java @@ -0,0 +1,89 @@ +package org.asteriskjava.pbx.internal.agi; + +import java.io.IOException; +import java.util.concurrent.CountDownLatch; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.manager.TimeoutException; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class AgiChannelActivityQueue implements AgiChannelActivityAction +{ + + private final Log logger = LogFactory.getLog(this.getClass()); + + CountDownLatch latch = new CountDownLatch(1); + + final private String queue; + private volatile boolean hangup = true; + // volatile private iChannel ichannel; + + public AgiChannelActivityQueue(String queue) + { + this.queue = queue; + } + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + channel.queue(queue); + if (hangup) + { + try + { + channel.hangup(); + } + catch (AgiHangupException e) + { + logger.warn("Channel " + channel.getName() + " hungup"); + } + catch (Exception e) + { + logger.warn(e); + } + } + logger.info(ichannel + " left the queue"); + + } + + @Override + public boolean isDisconnect() + { + return false; + } + + @Override + public void cancel(Channel channel) + { + if (channel == null) + { + throw new NullPointerException("channel cannot be null"); + } + + hangup = false; + final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + final RedirectAction redirect = new RedirectAction(channel, profile.getManagementContext(), pbx.getExtensionAgi(), + 1); + try + { + + pbx.sendAction(redirect, 1000); + } + catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) + { + logger.error(e, e); + } + + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityVoicemail.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityVoicemail.java new file mode 100644 index 000000000..13153ee12 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityVoicemail.java @@ -0,0 +1,36 @@ +package org.asteriskjava.pbx.internal.agi; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.pbx.Channel; + +public class AgiChannelActivityVoicemail implements AgiChannelActivityAction +{ + + public AgiChannelActivityVoicemail(String mailbox) + { + // TODO Auto-generated constructor stub + } + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + // TODO Auto-generated method stub + + } + + @Override + public boolean isDisconnect() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public void cancel(Channel channel) + { + // TODO Auto-generated method stub + + } + // Logger logger = LogManager.getLogger(); +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/NJAgiScript.java b/src/main/java/org/asteriskjava/pbx/internal/agi/NJAgiScript.java new file mode 100644 index 000000000..2df64d949 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/NJAgiScript.java @@ -0,0 +1,49 @@ +package org.asteriskjava.pbx.internal.agi; + +import org.apache.log4j.Logger; +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiRequest; +import org.asteriskjava.fastagi.BaseAgiScript; + +abstract public class NJAgiScript extends BaseAgiScript +{ + static transient Logger logger = Logger.getLogger(NJAgiScript.class); + protected AgiRequest request; + protected AgiChannel channel; + + public synchronized void service(AgiRequest request, AgiChannel channel) throws AgiException + { + this.request = request; + this.channel = channel; + service(); + } + + /** + * field variables request and channel will be set prior to calling + * service() AgiRequest request AgiChannel channel + * + * @throws AgiException + */ + + public abstract void service() throws AgiException; + + protected String required(String name, String parameter) throws AgiException + { + if (parameter == null || parameter.length() == 0) + throw new AgiException("Required parameter " + name + " missing."); + return parameter; + } + + protected String getParameter(String name) throws AgiException + { + return required(name, request.getParameter(name)); + } + + public void setVariable(String name, String value) throws AgiException + { + logger.debug("AGIVar set: " + name + "=(" + value + ")"); + super.setVariable(name, value); + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/RateLimiter.java b/src/main/java/org/asteriskjava/pbx/internal/agi/RateLimiter.java new file mode 100644 index 000000000..97bdc6ee5 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/RateLimiter.java @@ -0,0 +1,38 @@ +package org.asteriskjava.pbx.internal.agi; + +import java.util.LinkedList; +import java.util.List; + +public class RateLimiter +{ + private static final long ONE_THOUSAND_MILLIS = 1000L; + List available = new LinkedList<>(); + + /** + * this is NOT thread safe! + * + * @param perSecond - number of 'acquire()' calls allowed per second, a call + * to acquire() will block(sleep) if the per second limit is + * exceeded + */ + RateLimiter(int perSecond) + { + long now = System.currentTimeMillis(); + for (int i = 0; i < perSecond; i++) + { + available.add(now - ONE_THOUSAND_MILLIS); + } + } + + void acquire() throws InterruptedException + { + long now = System.currentTimeMillis(); + Long next = available.remove(0); + long timeRemaining = next - now; + if (timeRemaining > 0) + { + Thread.sleep(timeRemaining); + } + available.add(System.currentTimeMillis() + ONE_THOUSAND_MILLIS); + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/AsteriskSettings.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/AsteriskSettings.java new file mode 100644 index 000000000..0f318ca32 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/AsteriskSettings.java @@ -0,0 +1,30 @@ +package org.asteriskjava.pbx.internal.asterisk; + +public interface AsteriskSettings +{ + + int getManagerPortNo(); + + String getManagerPassword(); + + String getManagerUsername(); + + String getAsteriskIP(); + + Integer getMeetmeBaseAddress(); + + boolean getDisableBridge(); + + String getManagementContext(); + + String getExtensionPark(); + + int getDialTimeout(); + + String getAutoAnswer(); + + String getAgiExtension(); + + boolean getCanDetectHangup(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java new file mode 100644 index 000000000..8bb4ab35e --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java @@ -0,0 +1,125 @@ +package org.asteriskjava.pbx.internal.asterisk; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.PBXFactory; + +public class CallerIDImpl implements CallerID +{ + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(CallerIDImpl.class); + private final String number; + private final String name; + private boolean hideCallerID = false; + + /** + * Creates a caller ID. + * + * @param number + * - if null then we store an empty string. + * @param name + * - if null then we store an empty string. + */ + public CallerIDImpl(final String number, final String name) + { + this.number = (number == null ? "" : number.trim()); //$NON-NLS-1$ + this.name = (name == null ? "" : name.trim()); //$NON-NLS-1$ + } + + @Override + public String getNumber() + { + return this.number; + } + + @Override + public String getName() + { + return this.name; + } + + /** + * This is a little helper class which will buid the name component of a + * clid from the first and lastnames. + * + * If both firstname and lastname are null then the name component will be + * an empty string. + * + * @param firstname + * the person's firstname, may be null. + * @param lastname + * the person's lastname, may be null + * @param number + * the phone number. + * @return + */ + public static CallerID buildFromComponents(final String firstname, final String lastname, final String number) + { + String name = ""; //$NON-NLS-1$ + if (firstname != null) + { + name += firstname.trim(); + } + + if (lastname != null) + { + if (name.length() > 0) + { + name += " "; //$NON-NLS-1$ + } + name += lastname.trim(); + } + + return PBXFactory.getActivePBX().buildCallerID(number, name); + } + + /** + * Formats and returns the caller ID in an asterisk specific format suitable + * for passing to the likes of the originate action. The format is: name + * + * + * @return a formatted clid. + */ + public String formatted() + { + String callerID = ""; //$NON-NLS-1$ + if (this.name != null) + { + callerID += this.name; + } + if (this.number != null) + { + if (callerID.length() > 1) + { + callerID += " "; //$NON-NLS-1$ + } + callerID += "<" + this.number + ">"; //$NON-NLS-1$ //$NON-NLS-2$ + } + return callerID; + } + + @Override + public void setHideCallerID(final boolean hide) + { + this.hideCallerID = hide; + + } + + @Override + public boolean isHideCallerID() + { + return this.hideCallerID; + } + + @Override + public String toString() + { + return this.formatted(); + } + + @Override + public boolean isUnknown() + { + return (this.number.length() == 0) || (this.number.compareToIgnoreCase("unknown") == 0); //$NON-NLS-1$ + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/InvalidChannelName.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/InvalidChannelName.java new file mode 100644 index 000000000..5af9695ae --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/InvalidChannelName.java @@ -0,0 +1,12 @@ +package org.asteriskjava.pbx.internal.asterisk; + +public class InvalidChannelName extends Exception +{ + private static final long serialVersionUID = 1L; + + public InvalidChannelName(final String message) + { + super(message); + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java new file mode 100644 index 000000000..9a223f3da --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java @@ -0,0 +1,184 @@ +package org.asteriskjava.pbx.internal.asterisk; + +import java.util.Date; +import java.util.LinkedList; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; + +/* + * This class tracks the status, channel names and number of participants in + * a meetme room. The hangup function will hangup all known participants in + * this meetme room. + */ +public class MeetmeRoom +{ + /** + * The asterisk room number. This will be value offset from the Meetme Base. + * e.g. if the base is 3750 and this is the third allocated room, then the + * roomNumber will equal 3753. + */ + private final int roomNumber; + + static Logger logger = Logger.getLogger(MeetmeRoom.class); + + LinkedList channels = new LinkedList<>(); + + private int channelCount = 0; + + private boolean active = false; + + private boolean forceClose = false; + + private Date lastUpdated = null; + + public MeetmeRoom(final int number) + { + this.roomNumber = number; + } + + /* + * returns true if the channel was added to the list of channels in this + * meetme. if the channel is already in the meetme, returns false + */ + synchronized public boolean addChannel(final Channel channel) + { + boolean newChannel = false; + if (!this.channels.contains(channel)) + { + this.channels.add(channel); + this.channelCount++; + newChannel = true; + } + else + MeetmeRoom.logger.error("rejecting " + channel + " already in meetme."); //$NON-NLS-1$ //$NON-NLS-2$ + return newChannel; + } + + synchronized public int getChannelCount() + { + return this.channelCount; + } + + synchronized public Channel[] getChannels() + { + final Channel list[] = new Channel[this.channels.size()]; + + int cnt = 0; + for (final Channel channel : this.channels) + { + list[cnt++] = channel; + } + return list; + } + + public boolean getForceClose() + { + return this.forceClose; + } + + public Date getLastUpdated() + { + return this.lastUpdated; + } + + public String getRoomNumber() + { + return ("" + this.roomNumber); //$NON-NLS-1$ + } + + /** + * returns true if the meetme room is active, false if it is available + * + * @return + */ + public boolean getStatus() + { + return this.active; + } + + synchronized public void removeChannel(final Channel channel) + { + final boolean channelCountInSync = this.channelCount == this.channels.size(); + final boolean removed = this.channels.remove(channel); + + if (!removed) + { + MeetmeRoom.logger.error( + "An attempt to remove an non-existing channel " + channel + " from Meetme Room " + this.getRoomNumber()); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (channelCountInSync && removed) + { + this.channelCount--; + } + + // If the channel count is not insync then we decrement the channel + // count even if the remove was for a non-existent channel. + // We do this as if the channel count is out of sync it means that we + // have polled asterisk (usually during startup) + // and our local count was out of sync with asterisk. Asterisk is the + // definitive source. If we then get a remove + // channel then its probably a channel that asterisk knows about but + // which we don't know about. + // In that case our channelCount will also have come from asterisk so + // decrementing it keeps us in sync with asterisk + // and eventually we will get back in sync (hopefully). + if (!channelCountInSync && removed) + { + this.channelCount--; + } + + if ((this.channels.size() < 2) && (this.channels.size() > 0)) + { + if (!this.channels.get(0).isLocal()) + { + logger.warn("One channel left in the meet me room " + this.channels.get(0) + " room " + this.roomNumber); //$NON-NLS-1$ + } + } + + } + + public void setActive() + { + this.active = true; + } + + public void setForceClose(final boolean canClose) + { + this.forceClose = canClose; + } + + public void setInactive() + { + this.active = false; + this.channels.clear(); + this.forceClose = false; + this.lastUpdated = null; + + } + + public void setLastUpdated() + { + this.lastUpdated = new Date(); + } + + /** + * This method should only be called if asterisk is reporting a channel + * count for this meetme room which does not match our local channel count. + * This could happen if it was restarted whilst a call was active. + * + * @param channelCount + */ + public void resetChannelCount(final int resetChannelCount) + { + this.channelCount = resetChannelCount; + + } + + public boolean isActive() + { + return this.active; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java new file mode 100644 index 000000000..ad1d895c9 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -0,0 +1,410 @@ +package org.asteriskjava.pbx.internal.asterisk; + +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.log4j.Logger; +import org.asteriskjava.AsteriskVersion; +import org.asteriskjava.live.ManagerCommunicationException; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.CommandAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ConfbridgeListAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ConfbridgeListEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.MeetMeJoinEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.MeetMeLeaveEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ResponseEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ResponseEvents; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.CommandResponse; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.CoherentManagerEventListener; +import org.asteriskjava.pbx.internal.core.ListenerPriority; +import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; + +public class MeetmeRoomControl extends EventListenerBaseClass implements CoherentManagerEventListener +{ + /* + * listens for a channel entering or leaving meetme rooms. when there is + * only 1 channel left in a room it sets it as inactive .It will not set to + * inactive unless okToKill is set to true. It is set to false by + * default.Also manages the available room list. + */ + + static Logger logger = Logger.getLogger(MeetmeRoomControl.class); + + private Integer meetmeBaseAddress; + + private MeetmeRoom rooms[]; + + private int roomCount; + + private boolean meetmeInstalled = false; + + private final static AtomicReference self = new AtomicReference<>(); + + synchronized public static void init(PBX pbx, final int roomCount) throws NoMeetmeException + { + if (MeetmeRoomControl.self.get() != null) + { + logger.warn("The MeetmeRoomControl has already been initialised."); //$NON-NLS-1$ + } + else + { + MeetmeRoomControl.self.set(new MeetmeRoomControl(pbx, roomCount)); + } + } + + public static MeetmeRoomControl getInstance() + { + if (MeetmeRoomControl.self.get() == null) + { + throw new IllegalStateException( + "Thee MeetmeRoomControl has not been initialised. Please call MeetmeRoomControl.init()."); //$NON-NLS-1$ + } + + return MeetmeRoomControl.self.get(); + + } + + private MeetmeRoomControl(PBX pbx, final int roomCount) throws NoMeetmeException + { + super("MeetmeRoomControl"); //$NON-NLS-1$ + this.roomCount = roomCount; + final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + this.meetmeBaseAddress = settings.getMeetmeBaseAddress(); + this.rooms = new MeetmeRoom[roomCount]; + this.configure((AsteriskPBX) pbx); + + this.startListener(pbx); + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + required.add(MeetMeJoinEvent.class); + required.add(MeetMeLeaveEvent.class); + + return required; + } + + /* + * returns the next available meetme room, or null if no rooms are + * available. + */ + public synchronized MeetmeRoom findAvailableRoom() + { + int count = 0; + for (final MeetmeRoom room : this.rooms) + { + if (MeetmeRoomControl.logger.isDebugEnabled()) + { + MeetmeRoomControl.logger.debug("room " + room.getRoomNumber() + " count " + count); //$NON-NLS-1$ //$NON-NLS-2$ + } + /* + * new code to attempt to recover uncleared meetme rooms safely + */ + try + { + final Date lastUpdated = room.getLastUpdated(); + final long now = new Date().getTime(); + if (lastUpdated != null) + { + final long elapsedTime = now - lastUpdated.getTime(); + MeetmeRoomControl.logger.debug("room: " + room.getRoomNumber() + " count: " + count + " elapsed: " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + elapsedTime); + if ((elapsedTime > 7200000) && (room.getChannelCount() == 1)) + { + MeetmeRoomControl.logger.debug("clearing room"); //$NON-NLS-1$ + room.setInactive(); + } + } + } + catch (final Exception e) + { + /* + * attempt to make this new change safe + */ + MeetmeRoomControl.logger.error(e, e); + } + + if (room.getChannelCount() == 0) + { + room.setInactive(); + } + if (room.getStatus() == false) + { + MeetmeRoomControl.logger.debug("Returning available room base+" + room.getRoomNumber()); //$NON-NLS-1$ + return room; + } + count++; + } + MeetmeRoomControl.logger.error("no more available rooms"); //$NON-NLS-1$ + return null; + } + + /** + * Returns the MeetmeRoom for the given room number. The room number will be + * an integer value offset from the meetme base address. + * + * @param roomNumber the meetme room number + * @return + */ + synchronized private MeetmeRoom findMeetmeRoom(final String roomNumber) + { + MeetmeRoom foundRoom = null; + for (final MeetmeRoom room : this.rooms) + { + if (room.getRoomNumber().compareToIgnoreCase(roomNumber) == 0) + { + foundRoom = room; + break; + } + } + return foundRoom; + } + + synchronized MeetmeRoom getRoom(final int room) + { + return this.rooms[room]; + } + + @Override + public void onManagerEvent(final ManagerEvent event) + { + MeetmeRoom room; + if (event instanceof MeetMeJoinEvent) + { + final MeetMeJoinEvent evt = (MeetMeJoinEvent) event; + room = this.findMeetmeRoom(evt.getMeetMe()); + final Channel channel = evt.getChannel(); + if (room != null) + { + if (room.addChannel(channel)) + { + MeetmeRoomControl.logger.debug(channel + " has joined the conference " //$NON-NLS-1$ + + room.getRoomNumber() + " channelCount " + (room.getChannelCount())); //$NON-NLS-1$ + room.setLastUpdated(); + } + } + } + if (event instanceof MeetMeLeaveEvent) + { + final MeetMeLeaveEvent evt = (MeetMeLeaveEvent) event; + room = this.findMeetmeRoom(evt.getMeetMe()); + final Channel channel = evt.getChannel(); + if (room != null) + { + // ignore local dummy channels// && + // !channel.toUpperCase().startsWith("LOCAL/")) { + + if (MeetmeRoomControl.logger.isDebugEnabled()) + { + MeetmeRoomControl.logger.debug(channel + " has left the conference " //$NON-NLS-1$ + + room.getRoomNumber() + " channel count " + (room.getChannelCount())); //$NON-NLS-1$ + } + room.removeChannel(channel); + room.setLastUpdated(); + if ((room.getChannelCount() < 2) && (room.getForceClose() == true)) + { + this.hangupChannels(room); + room.setInactive(); + } + + if (room.getChannelCount() < 1) + { + room.setInactive(); + } + } + } + } + + public void hangupChannels(final MeetmeRoom room) + { + + final Channel Channels[] = room.getChannels(); + if (room.getStatus() == true) + { + PBX pbx = PBXFactory.getActivePBX(); + + for (final Channel channel : Channels) + { + room.removeChannel(channel); + + try + { + pbx.hangup(channel); + } + catch (IllegalArgumentException | IllegalStateException | PBXException e) + { + logger.error(e, e); + + } + } + } + } + + private void configure(AsteriskPBX pbx) throws NoMeetmeException + { + final int base = this.meetmeBaseAddress; + for (int r = 0; r < this.roomCount; r++) + { + this.rooms[r] = new MeetmeRoom(r + base); + } + + try + { + String command; + if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) + { + command = "ConfBridge list"; //$NON-NLS-1$ + ConfbridgeListAction action = new ConfbridgeListAction(); + final ResponseEvents response = pbx.sendEventGeneratingAction(action, 3000); + Map roomChannelCount = new HashMap<>(); + for (ResponseEvent event : response.getEvents()) + { + + ConfbridgeListEvent e = (ConfbridgeListEvent) event; + Integer current = roomChannelCount.get(e.getConference()); + if (current == null) + { + roomChannelCount.put(e.getConference(), 1); + } + else + { + roomChannelCount.put(e.getConference(), current + 1); + } + } + for (Entry entry : roomChannelCount.entrySet()) + { + setRoomCount(entry.getKey(), entry.getValue(), Integer.parseInt(entry.getKey())); + + } + this.meetmeInstalled = true; + + } + else + { + if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) + { + command = "meetme list"; //$NON-NLS-1$ + } + else + { + command = "meetme"; //$NON-NLS-1$ + } + final CommandAction commandAction = new CommandAction(command); + final ManagerResponse response = pbx.sendAction(commandAction, 3000); + if (!(response instanceof CommandResponse)) + { + throw new ManagerCommunicationException(response.getMessage(), null); + } + + final CommandResponse commandResponse = (CommandResponse) response; + MeetmeRoomControl.logger.debug("parsing active meetme rooms"); //$NON-NLS-1$ + for (final String line : commandResponse.getResult()) + { + this.parseMeetme(line); + this.meetmeInstalled = true; + MeetmeRoomControl.logger.debug(line); + } + } + } + catch (final NoMeetmeException e) + { + throw e; + } + catch (final Exception e) + { + MeetmeRoomControl.logger.error(e, e); + throw new NoMeetmeException(e.getLocalizedMessage()); + } + } + + private synchronized void parseMeetme(final String line) throws NoMeetmeException + { + + if (line != null) + { + if (line.toLowerCase().startsWith("no such command 'meetme'") == true) //$NON-NLS-1$ + { + throw new NoMeetmeException("Asterisk is not configured correctly! Please enable the MeetMe app"); //$NON-NLS-1$ + } + + if ((line.toLowerCase().startsWith("no active meetme conferences.") == false) //$NON-NLS-1$ + && (line.toLowerCase().startsWith("conf num") == false) //$NON-NLS-1$ + && (line.toLowerCase().startsWith("* total number") == false) //$NON-NLS-1$ + && (line.toLowerCase().startsWith("no such conference") == false) //$NON-NLS-1$ + && (line.toLowerCase().startsWith("no such command 'meetme'") == false) //$NON-NLS-1$ + ) + { + // Update the stats on each meetme + final String roomNumber = line.substring(0, 10).trim(); + final String tmp = line.substring(11, 25).trim(); + final int channelCount = Integer.parseInt(tmp); + + final int roomNo = Integer.valueOf(roomNumber); + setRoomCount(roomNumber, channelCount, roomNo); + } + } + } + + private void setRoomCount(final String roomNumber, final int channelCount, final int roomNo) + { + Integer base = this.meetmeBaseAddress; + // First check if its one of our rooms. + if ((roomNo >= base) && (roomNo < (base + this.roomCount))) + { + final MeetmeRoom room = this.findMeetmeRoom(roomNumber); + if (room != null) + { + if (room.getChannelCount() != channelCount) + { + /* + * After a restart there may have been meetme rooms left up + * and running with live calls. We need to identify any + * active rooms so we don't accidentally re-use an active + * room which would result in a crossed channel. + */ + MeetmeRoomControl.logger.warn("Room number: " + room.getRoomNumber() //$NON-NLS-1$ + + " has a server side channel count = " + channelCount //$NON-NLS-1$ + + " when the channel count for that room is: " + room.getChannelCount() //$NON-NLS-1$ + + " the server side channel count will be reset."); //$NON-NLS-1$ + } + room.resetChannelCount(channelCount); + room.setActive(); + } + // else "Found roomNumber:" + roomNumber + " but it was not + // in the list of rooms managed by MeetmeRoomControl."); + // //$NON-NLS-1$ //$NON-NLS-2$ + + } + } + + public void stop() + { + this.close(); + + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + public boolean isMeetmeInstalled() + { + return this.meetmeInstalled; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/NoMeetmeException.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/NoMeetmeException.java new file mode 100644 index 000000000..eb666a2d5 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/NoMeetmeException.java @@ -0,0 +1,12 @@ +package org.asteriskjava.pbx.internal.asterisk; + +public class NoMeetmeException extends Exception +{ + private static final long serialVersionUID = 1L; + + public NoMeetmeException(final String message) + { + super(message); + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/PBXSettingsManager.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/PBXSettingsManager.java new file mode 100644 index 000000000..40a90219f --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/PBXSettingsManager.java @@ -0,0 +1,28 @@ +package org.asteriskjava.pbx.internal.asterisk; + +import java.util.concurrent.atomic.AtomicReference; + +public class PBXSettingsManager +{ + + final static AtomicReference profile = new AtomicReference<>(); + + public static void setAsteriskSettings(AsteriskSettings profile) + { + PBXSettingsManager.profile.set(profile); + + } + + public static AsteriskSettings getActiveProfile() + { + AsteriskSettings activeProfile = profile.get(); + if (activeProfile == null) + { + throw new RuntimeException( + "you must call setAsteriskSettings() before getActiveProfile() is called the first time"); + } + + return activeProfile; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/AbstractManagerAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/AbstractManagerAction.java new file mode 100644 index 000000000..878f019e6 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/AbstractManagerAction.java @@ -0,0 +1,38 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +/** + * Automatically generates a globally unique action id (based on the systems mac + * address + * + * @author bsutton + * + */ +abstract public class AbstractManagerAction implements ManagerAction +{ + + private static long _nextActionId = 1; + + private String _actionId; + + AbstractManagerAction() + { + this._actionId = generateActionId(); + } + + public String getActionId() + { + return this._actionId; + } + + synchronized public String generateActionId() + { + + return "" + _nextActionId++; + } + + protected void setActionId(String actionId) + { + this._actionId = actionId; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/BridgeAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/BridgeAction.java new file mode 100644 index 000000000..691773bb5 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/BridgeAction.java @@ -0,0 +1,31 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.asteriskjava.pbx.Channel; + +public class BridgeAction extends AbstractManagerAction +{ + + private final Channel _lhs; + private final Channel _rhs; + + public BridgeAction(final Channel lhs, final Channel rhs) + { + this._lhs = lhs; + this._rhs = rhs; + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.BridgeAction action = new org.asteriskjava.manager.action.BridgeAction(); + action.setActionId(this.getActionId()); + action.setChannel1(this._lhs.getChannelName()); + action.setChannel2(this._rhs.getChannelName()); + return action; + } + + public String toString() + { + return "BridgeAction: lhs=" + this._lhs + " rhs=" + this._rhs; //$NON-NLS-1$ //$NON-NLS-2$ + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/CommandAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/CommandAction.java new file mode 100644 index 000000000..4cb0130f5 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/CommandAction.java @@ -0,0 +1,32 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +public class CommandAction extends AbstractManagerAction +{ + + private String _command; + + public CommandAction(final String command) + { + this._command = command; + } + + public CommandAction() + { + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.CommandAction action = new org.asteriskjava.manager.action.CommandAction(); + action.setCommand(this._command); + action.setActionId(this.getActionId()); + + return action; + } + + public String toString() + { + return "CommandAction: command=" + this._command; //$NON-NLS-1$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ConfbridgeListAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ConfbridgeListAction.java new file mode 100644 index 000000000..0fc8d9c08 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ConfbridgeListAction.java @@ -0,0 +1,22 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.asteriskjava.manager.action.ManagerAction; + +public class ConfbridgeListAction extends AbstractManagerAction implements EventGeneratingAction +{ + + @Override + public ManagerAction getAJAction() + { + return new org.asteriskjava.manager.action.ConfbridgeListAction(); + } + // Logger logger = LogManager.getLogger(); + + @Override + public org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction() + { + org.asteriskjava.manager.action.ConfbridgeListAction action = new org.asteriskjava.manager.action.ConfbridgeListAction(); + action.setActionId(this.getActionId()); + return action; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/DbGetAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/DbGetAction.java new file mode 100644 index 000000000..5c3f3809e --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/DbGetAction.java @@ -0,0 +1,33 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.asteriskjava.manager.action.ManagerAction; + +public class DbGetAction extends AbstractManagerAction +{ + + private final String _key; + private final String _family; + + public DbGetAction(final String family, final String key) + { + this._family = family; + this._key = key; + } + + @Override + public ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.DbGetAction action = new org.asteriskjava.manager.action.DbGetAction(); + action.setActionId(this.getActionId()); + action.setKey(this._key); + action.setFamily(this._family); + + return action; + } + + public String toString() + { + return "DbGetAction: key=" + this._key + " family=" + this._family; //$NON-NLS-1$ //$NON-NLS-2$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/EventGeneratingAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/EventGeneratingAction.java new file mode 100644 index 000000000..73047bd5a --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/EventGeneratingAction.java @@ -0,0 +1,8 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +public interface EventGeneratingAction +{ + + org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/GetVarAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/GetVarAction.java new file mode 100644 index 000000000..fdbcc4f96 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/GetVarAction.java @@ -0,0 +1,33 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.asteriskjava.pbx.Channel; + +public class GetVarAction extends AbstractManagerAction +{ + + private final Channel _channel; + private String _variableName; + + public GetVarAction(final Channel channel, String variableName) + { + this._channel = channel; + this._variableName = variableName; + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.GetVarAction action = new org.asteriskjava.manager.action.GetVarAction(); + action.setActionId(this.getActionId()); + action.setChannel(this._channel.getChannelName()); + action.setVariable(this._variableName); + + return action; + } + + public String toString() + { + return "GetVarAction: channel=" + this._channel + " variableName=" + this._variableName; //$NON-NLS-1$ //$NON-NLS-2$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/HangupAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/HangupAction.java new file mode 100644 index 000000000..b5dd8423f --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/HangupAction.java @@ -0,0 +1,37 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.asteriskjava.pbx.Channel; + +public class HangupAction extends AbstractManagerAction +{ + + private final Channel _channel; + private Integer _cause; + + public HangupAction(final Channel channel) + { + this._channel = channel; + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.HangupAction action = new org.asteriskjava.manager.action.HangupAction(); + action.setActionId(this.getActionId()); + action.setCause(this._cause); + action.setChannel(this._channel.getChannelName()); + + return action; + } + + public Channel getChannel() + { + return this._channel; + } + + public String toString() + { + return "HangupAction: channel=" + this._channel + " cause=" + this._cause; //$NON-NLS-1$ //$NON-NLS-2$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ListCommandsAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ListCommandsAction.java new file mode 100644 index 000000000..46a010e98 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ListCommandsAction.java @@ -0,0 +1,24 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.apache.log4j.Logger; + +public class ListCommandsAction extends AbstractManagerAction +{ + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(ListCommandsAction.class); + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.ListCommandsAction action = new org.asteriskjava.manager.action.ListCommandsAction(); + action.setActionId(this.getActionId()); + + return action; + } + + public String toString() + { + return "ListCommandsAction"; //$NON-NLS-1$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ManagerAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ManagerAction.java new file mode 100644 index 000000000..9198c9128 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ManagerAction.java @@ -0,0 +1,9 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +public interface ManagerAction +{ + + // Converts an iManagerAction into an asterisk-java ManagerAction. + org.asteriskjava.manager.action.ManagerAction getAJAction(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/MonitorAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/MonitorAction.java new file mode 100644 index 000000000..7a01d95a0 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/MonitorAction.java @@ -0,0 +1,36 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.asteriskjava.pbx.Channel; + +public class MonitorAction extends AbstractManagerAction +{ + + private final Channel _channel; + private final String _file; + private final String _format; + private final boolean _mix; + + public MonitorAction(final Channel channel, final String file, final String format, final boolean mix) + { + this._channel = channel; + this._file = file; + this._format = format; + this._mix = mix; + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.MonitorAction action = new org.asteriskjava.manager.action.MonitorAction( + this._channel.getChannelName(), this._file, this._format, this._mix); + action.setActionId(this.getActionId()); + + return action; + } + + public String toString() + { + return "MonitorAction: channel=" + this._channel + " file=" + this._file; //$NON-NLS-1$ //$NON-NLS-2$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/OriginateAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/OriginateAction.java new file mode 100644 index 000000000..5ccfd0c3d --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/OriginateAction.java @@ -0,0 +1,142 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import java.util.Map; + +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.internal.asterisk.CallerIDImpl; + +public class OriginateAction extends AbstractManagerAction +{ + + /** + * Asterisk uses the term channel but it actually appears to be an endpoint + * or a channel. Hence we support both. + * + * Either of the following may be set but NOT BOTH. + */ + private EndPoint _endPoint; + private Channel _channel; + + private String _option; + + private String _context; + + private EndPoint _extension; + + private int _priority; + + private int _callingPres; + + private CallerID _callerID; + + private Map _variables; + + private Boolean _async; + + private long _timeout; + + public OriginateAction() + { + } + + public String toString() + { + return "OriginateAction: endPoint/Channel=" + (this._endPoint == null ? this._channel : this._endPoint) + " context=" + this._context //$NON-NLS-1$ //$NON-NLS-2$ + + " extension=" + this._extension + " callerId=" + this._callerID; //$NON-NLS-1$ //$NON-NLS-2$ + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.OriginateAction action = new org.asteriskjava.manager.action.OriginateAction(); + action.setActionId(getActionId()); + + // Was the channel or an end point passed. + String channel = (this._channel != null ? this._channel.getChannelName() : this._endPoint + .getFullyQualifiedName()); + if (this._option != null) + { + channel += this._option; + } + action.setChannel((channel)); + action.setContext(this._context); + action.setExten(this._extension.getFullyQualifiedName()); + action.setPriority(this._priority); + action.setCallingPres(this._callingPres); + action.setCallerId(((CallerIDImpl) this._callerID).formatted()); + action.setVariables(this._variables); + action.setAsync(this._async); + action.setTimeout(this._timeout); + + return action; + } + + public void setEndPoint(final EndPoint endPoint) + { + this._endPoint = endPoint; + this._channel = null; + } + + public void setChannel(Channel channel) + { + this._channel = channel; + this._endPoint = null; + + } + + public void setOption(final String option) + { + this._option = option; + + } + + public void setContext(final String context) + { + this._context = context; + + } + + public void setExten(final EndPoint extension) + { + this._extension = extension; + + } + + public void setPriority(final int priority) + { + this._priority = priority; + + } + + public void setCallingPres(final int callingPres) + { + this._callingPres = callingPres; + + } + + public void setCallerId(final CallerID callerID) + { + this._callerID = callerID; + + } + + public void setVariables(final Map variables) + { + this._variables = variables; + + } + + public void setAsync(final boolean async) + { + this._async = async; + + } + + public void setTimeout(final long timeout) + { + this._timeout = timeout; + + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PingAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PingAction.java new file mode 100644 index 000000000..d74bc0465 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PingAction.java @@ -0,0 +1,23 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.apache.log4j.Logger; + +public class PingAction extends AbstractManagerAction +{ + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(PingAction.class); + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.PingAction action = new org.asteriskjava.manager.action.PingAction(); + action.setActionId(this.getActionId()); + return action; + } + + public String toString() + { + return "PingAction"; //$NON-NLS-1$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PlayDtmfAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PlayDtmfAction.java new file mode 100644 index 000000000..6f96a8cec --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PlayDtmfAction.java @@ -0,0 +1,35 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.asteriskjava.manager.action.ManagerAction; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.DTMFTone; + +public class PlayDtmfAction extends AbstractManagerAction +{ + + private final Channel _channel; + private final DTMFTone _tone; + + public PlayDtmfAction(final Channel channel, final DTMFTone tone) + { + this._channel = channel; + this._tone = tone; + } + + @Override + public ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.PlayDtmfAction action = new org.asteriskjava.manager.action.PlayDtmfAction(); + action.setActionId(this.getActionId()); + action.setChannel(this._channel.getChannelName()); + action.setDigit(this._tone.toString()); + + return action; + } + + public String toString() + { + return "PlayDtmfAction: channel=" + this._channel + " tone=" + this._tone; //$NON-NLS-1$ //$NON-NLS-2$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/RedirectAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/RedirectAction.java new file mode 100644 index 000000000..0fdbda90a --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/RedirectAction.java @@ -0,0 +1,87 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; + +public class RedirectAction extends AbstractManagerAction +{ + + private final Channel _channel; + private final String _context; + private final EndPoint _exten; + private final Integer _priority; + private Channel _extraChannel; + private String _extraContext; + private EndPoint _extraExten; + private Integer _extraPriority; + + public RedirectAction(final Channel channel, final String context, final EndPoint extension, final int priority) + { + if (channel == null) + { + throw new NullPointerException("channel cannot be null"); + } + if (context == null) + { + throw new NullPointerException("context cannot be null"); + } + if (extension == null) + { + throw new NullPointerException("extension cannot be null"); + } + + this._channel = channel; + this._context = context; + this._exten = extension; + this._priority = priority; + } + + @Override + public String toString() + { + return "RedirectAction: chanel=" + this._channel + " context=" + this._context //$NON-NLS-1$ //$NON-NLS-2$ + + " exten=" + this._exten + " priority=" + this._priority //$NON-NLS-1$ //$NON-NLS-2$ + + " extraContext=" + this._extraContext //$NON-NLS-1$ + + " extraChannel=" + this._extraChannel //$NON-NLS-1$ + + " extraExten=" + this._extraExten; //$NON-NLS-1$ + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.RedirectAction action = new org.asteriskjava.manager.action.RedirectAction(); + action.setActionId(this.getActionId()); + action.setChannel(this._channel.getChannelName()); + action.setContext(this._context); + action.setExten(this._exten.getFullyQualifiedName()); + action.setPriority(this._priority); + if (this._extraChannel != null) + action.setExtraChannel(this._extraChannel.getChannelName()); + action.setExtraContext(this._extraContext); + if (this._extraExten != null) + action.setExtraExten(this._extraExten.getFullyQualifiedName()); + action.setExtraPriority(this._extraPriority); + + return action; + } + + public void setExtraChannel(final Channel extraChannel) + { + this._extraChannel = extraChannel; + } + + public void setExtraContext(final String extraContext) + { + this._extraContext = extraContext; + } + + public void setExtraExten(final EndPoint extraExten) + { + this._extraExten = extraExten; + } + + public void setExtraPriority(final int priority) + { + this._extraPriority = priority; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SetVarAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SetVarAction.java new file mode 100644 index 000000000..5862312b9 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SetVarAction.java @@ -0,0 +1,42 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.asteriskjava.pbx.Channel; + +public class SetVarAction extends AbstractManagerAction +{ + + private final Channel _channel; + private String _variableName; + private final String _value; + + public SetVarAction(final Channel channel, final String variableName, final String value) + { + this._channel = channel; + this._variableName = variableName; + this._value = value; + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.SetVarAction action = new org.asteriskjava.manager.action.SetVarAction(); + action.setActionId(this.getActionId()); + action.setChannel(this._channel.getChannelName()); + action.setVariable(this._variableName); + action.setValue(this._value); + + return action; + } + + public void setVariable(final String variableName) + { + this._variableName = variableName; + + } + + public String toString() + { + return "SetVarAction: channel=" + this._channel + " variableName=" + this._variableName + " value=" + this._value; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipPeersAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipPeersAction.java new file mode 100644 index 000000000..71f0a2d3a --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipPeersAction.java @@ -0,0 +1,29 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +public class SipPeersAction extends AbstractManagerAction implements EventGeneratingAction +{ + + public SipPeersAction() + { + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + return new org.asteriskjava.manager.action.SipPeersAction(); + } + + @Override + public org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction() + { + org.asteriskjava.manager.action.SipPeersAction action = new org.asteriskjava.manager.action.SipPeersAction(); + action.setActionId(this.getActionId()); + return action; + } + + public String toString() + { + return "SipPeersAction"; //$NON-NLS-1$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipShowPeerAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipShowPeerAction.java new file mode 100644 index 000000000..fca71b3a0 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipShowPeerAction.java @@ -0,0 +1,30 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.asteriskjava.manager.action.ManagerAction; +import org.asteriskjava.pbx.EndPoint; + +public class SipShowPeerAction extends AbstractManagerAction +{ + + private final EndPoint _peer; + + public SipShowPeerAction(final EndPoint peer) + { + this._peer = peer; + } + + @Override + public ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.SipShowPeerAction action = new org.asteriskjava.manager.action.SipShowPeerAction(); + action.setActionId(this.getActionId()); + action.setPeer(this._peer.getSimpleName()); + return action; + } + + public String toString() + { + return "SipShowPeerAction: peer=" + this._peer; //$NON-NLS-1$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/StatusAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/StatusAction.java new file mode 100644 index 000000000..26ec849a1 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/StatusAction.java @@ -0,0 +1,54 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.asteriskjava.AsteriskVersion; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class StatusAction extends AbstractManagerAction implements EventGeneratingAction +{ + // used when the status of a single channel has been requested. + final private Channel _channel; + + public StatusAction() + { + this._channel = null; + } + + public StatusAction(Channel channel) + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + // channel specific request only available since 1.6 + if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) + this._channel = channel; + else + this._channel = null; + } + + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.StatusAction action; + if (_channel == null) + action = new org.asteriskjava.manager.action.StatusAction(); + else + action = new org.asteriskjava.manager.action.StatusAction(_channel.getChannelName()); + + return action; + } + + @Override + public org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction() + { + final org.asteriskjava.manager.action.StatusAction action = (org.asteriskjava.manager.action.StatusAction) getAJAction(); + action.setActionId(getActionId()); + + return action; + } + + public String toString() + { + return "StatusAction"; //$NON-NLS-1$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/UserEventAction.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/UserEventAction.java new file mode 100644 index 000000000..525434854 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/UserEventAction.java @@ -0,0 +1,28 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.actions; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.wrap.userEvents.UserEvent; + +abstract public class UserEventAction extends AbstractManagerAction +{ + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(UserEventAction.class); + + private String _actionId; + + public UserEventAction(UserEvent event) + { + // NOOP + } + + public void setActionId(String actionId) + { + this._actionId = actionId; + } + + public String getActionId() + { + return this._actionId; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractChannelStateEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractChannelStateEvent.java new file mode 100644 index 000000000..4d627ee37 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractChannelStateEvent.java @@ -0,0 +1,36 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.ChannelEventHelper; + +public abstract class AbstractChannelStateEvent extends ChannelEventHelper +{ + + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(AbstractChannelStateEvent.class); + + private final ChannelState channelState; + private final String channelStateDesc; + + AbstractChannelStateEvent(final org.asteriskjava.manager.event.AbstractChannelStateEvent event) + throws InvalidChannelName + { + super(event); + this.channelState = ChannelState.valueOfDesc(event.getChannelStateDesc()); + this.channelStateDesc = event.getChannelStateDesc(); + } + + public ChannelState getChannelState() + { + return this.channelState; + } + + public String getChannelStateDesc() + { + return this.channelStateDesc; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractMeetMeEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractMeetMeEvent.java new file mode 100644 index 000000000..925357c9c --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractMeetMeEvent.java @@ -0,0 +1,34 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.ChannelEventHelper; + +public class AbstractMeetMeEvent extends ChannelEventHelper +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(AbstractMeetMeEvent.class); + + private final String meetMe; + private final Integer userNum; + + public AbstractMeetMeEvent(final org.asteriskjava.manager.event.AbstractMeetMeEvent event) throws InvalidChannelName + { + super(event.getChannel(), event.getUniqueId()); + this.meetMe = event.getMeetMe(); + this.userNum = event.getUser(); + } + + public String getMeetMe() + { + return this.meetMe; + } + + public Integer getUserNum() + { + return this.userNum; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractParkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractParkedCallEvent.java new file mode 100644 index 000000000..f940dd4b3 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractParkedCallEvent.java @@ -0,0 +1,34 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.ChannelEventHelper; + +public class AbstractParkedCallEvent extends ChannelEventHelper +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(AbstractParkedCallEvent.class); + + private final String exten; + private final String parkingLot; + + AbstractParkedCallEvent(final org.asteriskjava.manager.event.AbstractParkedCallEvent event) + throws InvalidChannelName + { + super(event.getParkeeChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + this.exten = event.getExten(); + this.parkingLot = event.getParkingLot(); + } + + public String getExten() + { + return this.exten; + } + + public String getParkingLot() + { + return this.parkingLot; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentCalledEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentCalledEvent.java new file mode 100644 index 000000000..e954d08a0 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentCalledEvent.java @@ -0,0 +1,36 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.ChannelEventHelper; + +public class AgentCalledEvent extends ChannelEventHelper +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(AgentCalledEvent.class); + + private String queue; + + private String agentInterface; + + public AgentCalledEvent(final org.asteriskjava.manager.event.AgentCalledEvent event) throws InvalidChannelName + { + super(event.getChannelCalling(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + + agentInterface = event.getAgentCalled(); + queue = event.getQueue(); + } + + public String getQueueName() + { + return queue; + } + + public String getAgentInterface() + { + return agentInterface; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentConnectEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentConnectEvent.java new file mode 100644 index 000000000..12950efbc --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentConnectEvent.java @@ -0,0 +1,36 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.ChannelEventHelper; + +public class AgentConnectEvent extends ChannelEventHelper +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(AgentConnectEvent.class); + + private String queue; + + private String agentInterface; + + public AgentConnectEvent(final org.asteriskjava.manager.event.AgentConnectEvent event) throws InvalidChannelName + { + super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + + agentInterface = event.getInterface(); + queue = event.getQueue(); + } + + public String getQueueName() + { + return queue; + } + + public String getAgentInterface() + { + return agentInterface; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/BridgeEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/BridgeEvent.java new file mode 100644 index 000000000..09b10f206 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/BridgeEvent.java @@ -0,0 +1,78 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ChannelProxy; + +public class BridgeEvent extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(BridgeEvent.class); + + enum BridgeState + { + Link, Unlink + } + + private final BridgeState bridgeState; + private final ChannelProxy channel1; + private final ChannelProxy channel2; + + public BridgeEvent(final org.asteriskjava.manager.event.BridgeEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this.bridgeState = BridgeState.valueOf(event.getBridgeState()); + this.channel1 = pbx.registerChannel(event.getChannel1(), event.getUniqueId1()); + this.channel2 = pbx.registerChannel(event.getChannel2(), event.getUniqueId2()); + } + + public BridgeState getBridgeState() + { + return this.bridgeState; + } + + public ChannelProxy getChannel1() + { + return this.channel1; + } + + public ChannelProxy getChannel2() + { + return this.channel2; + } + + /** + * Returns whether the two channels have been linked. + * + * @return true the two channels have been linked, + * false if they have been unlinked. + * @since 1.0.0 + */ + public boolean isLink() + { + return this.bridgeState == BridgeState.Link; + } + + /** + * Returns whether the two channels have been unlinked. + * + * @return true the two channels have been unlinked, + * false if they have been linked. + * @since 1.0.0 + */ + public boolean isUnlink() + { + return this.bridgeState == BridgeState.Unlink; + } + + public String toString() + { + return "BridgeEvent: channel1:" + this.channel1 + " channel2:" + this.channel2 + " bridgeState:" + this.bridgeState; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelEvent.java new file mode 100644 index 000000000..c7b15975b --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelEvent.java @@ -0,0 +1,9 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.asteriskjava.pbx.Channel; + +public interface ChannelEvent +{ + public Channel getChannel(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelState.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelState.java new file mode 100644 index 000000000..0fad8139b --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelState.java @@ -0,0 +1,42 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +/** + * Holds the state of a channel as used by NewStateEvent and NewChannelEvent. + * + * @author bsutton + * + */ +public enum ChannelState +{ + Down, Rsrvd, OffHook, Dialing, Ring, Ringing, Up, Busy, DialingOffhook("Dialing Offhook"), PreRing("Pre-ring"); //$NON-NLS-1$ //$NON-NLS-2$ + + String _text; + + static ChannelState valueOfDesc(String description) + { + ChannelState theState = null; + + for (ChannelState aState : ChannelState.values()) + { + if (aState._text.compareToIgnoreCase(description) == 0) + { + theState = aState; + break; + } + } + + return theState; + + } + + ChannelState(String text) + { + this._text = text; + } + + ChannelState() + { + this._text = this.name(); + } + +} \ No newline at end of file diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListCompleteEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListCompleteEvent.java new file mode 100644 index 000000000..8c844cc61 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListCompleteEvent.java @@ -0,0 +1,12 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +public class ConfbridgeListCompleteEvent extends ManagerEvent +{ + + private static final long serialVersionUID = 1L; + + public ConfbridgeListCompleteEvent(org.asteriskjava.manager.event.ConfbridgeListCompleteEvent source) + { + super(source); + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListEvent.java new file mode 100644 index 000000000..4d0f981d2 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListEvent.java @@ -0,0 +1,26 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +public class ConfbridgeListEvent extends ResponseEvent +{ + + private static final long serialVersionUID = 1L; + private String conference; + private String channel; + + public ConfbridgeListEvent(org.asteriskjava.manager.event.ConfbridgeListEvent source) + { + super(source); + conference = source.getConference(); + channel = source.getChannel(); + } + + public String getChannel() + { + return channel; + } + + public String getConference() + { + return conference; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConnectEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConnectEvent.java new file mode 100644 index 000000000..6e2947872 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConnectEvent.java @@ -0,0 +1,28 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; + +public class ConnectEvent extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(ConnectEvent.class); + + /** + * The version of the manager protocol. + */ + private final String protocolIdentifier; + + public ConnectEvent(final org.asteriskjava.manager.event.ConnectEvent event) + { + super(event); + this.protocolIdentifier = event.getProtocolIdentifier(); + } + + public String getProtocolIdentifier() + { + return this.protocolIdentifier; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DbGetResponseEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DbGetResponseEvent.java new file mode 100644 index 000000000..d320a540f --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DbGetResponseEvent.java @@ -0,0 +1,39 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; + +public class DbGetResponseEvent extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(DbGetResponseEvent.class); + + private final String family; + private final String key; + private final String val; + + DbGetResponseEvent(final org.asteriskjava.manager.event.DbGetResponseEvent event) + { + super(event); + this.family = event.getFamily(); + this.key = event.getKey(); + this.val = event.getVal(); + } + + public String getVal() + { + return this.val; + } + + public String getFamily() + { + return this.family; + } + + public String getKey() + { + return this.key; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DialEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DialEvent.java new file mode 100644 index 000000000..6d6fa490a --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DialEvent.java @@ -0,0 +1,55 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ChannelEventHelper; +import org.asteriskjava.pbx.internal.core.ChannelProxy; + +public class DialEvent extends ChannelEventHelper +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(DialEvent.class); + + /** + * The name of the destination channel. + */ + private final ChannelProxy destination; + + private final String dialString; + private final String dialStatus; + + public DialEvent(final org.asteriskjava.manager.event.DialEvent event) throws InvalidChannelName + { + super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + if (event.getDestination() != null) + this.destination = pbx.registerChannel(event.getDestination(), event.getDestUniqueId()); + else + this.destination = null; + + this.dialString = event.getDialString(); + this.dialStatus = event.getDialStatus(); + + } + + public ChannelProxy getDestination() + { + return this.destination; + } + + public String getDialString() + { + return this.dialString; + } + + public String getDialStatus() + { + return this.dialStatus; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DisconnectEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DisconnectEvent.java new file mode 100644 index 000000000..3db4bac29 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DisconnectEvent.java @@ -0,0 +1,15 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; + +public class DisconnectEvent extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(DisconnectEvent.class); + + public DisconnectEvent(final org.asteriskjava.manager.event.DisconnectEvent event) + { + super(event); + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DndStateEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DndStateEvent.java new file mode 100644 index 000000000..2275b88b0 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DndStateEvent.java @@ -0,0 +1,45 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ChannelImpl; + +public class DndStateEvent extends ManagerEvent implements ChannelEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(DndStateEvent.class); + + /** + * The name of the channel. + */ + private final Channel channel; + + /** + * The DND state of the channel. + */ + private final Boolean state; + + public DndStateEvent(final org.asteriskjava.manager.event.DndStateEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + this.channel = pbx.registerChannel(event.getChannel(), ChannelImpl.UNKNOWN_UNIQUE_ID); + this.state = event.getState(); + } + + @Override + public Channel getChannel() + { + return this.channel; + } + + public Boolean getState() + { + return this.state; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ExtensionStatusEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ExtensionStatusEvent.java new file mode 100644 index 000000000..d6a4fdb20 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ExtensionStatusEvent.java @@ -0,0 +1,95 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; + +public class ExtensionStatusEvent extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(ExtensionStatusEvent.class); + + enum Status + { + + /** + * No device INUSE or BUSY. + */ + NOT_INUSE(org.asteriskjava.manager.event.ExtensionStatusEvent.NOT_INUSE), + + /** + * One or more devices INUSE. + */ + INUSE(org.asteriskjava.manager.event.ExtensionStatusEvent.INUSE), + + /** + * All devices BUSY. + */ + BUSY(org.asteriskjava.manager.event.ExtensionStatusEvent.BUSY), + + /** + * All devices UNAVAILABLE/UNREGISTERED. + */ + UNAVAILABLE(org.asteriskjava.manager.event.ExtensionStatusEvent.UNAVAILABLE), + + /** + * One or more devices RINGING. + */ + RINGING(org.asteriskjava.manager.event.ExtensionStatusEvent.RINGING); + + int _status; + + Status(int status) + { + this._status = status; + } + + static Status valueOf(Integer status) + { + Status theStatus = null; + for (Status aStatus : Status.values()) + { + if (aStatus._status == status) + { + theStatus = aStatus; + break; + } + } + return theStatus; + } + } + + private final String exten; + private final String context; + private final String hint; + private final Status status; + + public ExtensionStatusEvent(final org.asteriskjava.manager.event.ExtensionStatusEvent event) + { + super(event); + this.exten = event.getExten(); + this.context = event.getContext(); + this.hint = event.getHint(); + this.status = Status.valueOf(event.getStatus()); + } + + public String getExten() + { + return this.exten; + } + + public String getContext() + { + return this.context; + } + + public String getHint() + { + return this.hint; + } + + public Status getStatus() + { + return this.status; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/HangupEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/HangupEvent.java new file mode 100644 index 000000000..b84f24bd2 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/HangupEvent.java @@ -0,0 +1,62 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class HangupEvent extends ManagerEvent implements ChannelEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(HangupEvent.class); + + /** + * The name of the channel. + */ + private final Channel channel; + + private final Integer cause; + private final String causeTxt; + private final String uniqueId; + + public HangupEvent(final org.asteriskjava.manager.event.HangupEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this.channel = pbx.registerHangupChannel(event.getChannel(), event.getUniqueId()); + this.cause = event.getCause(); + this.causeTxt = event.getCauseTxt(); + this.uniqueId = event.getUniqueId(); + + } + + public Integer getCause() + { + return this.cause; + } + + public String getCauseTxt() + { + return this.causeTxt; + } + + @Override + public Channel getChannel() + { + return this.channel; + } + + public String getUniqueId() + { + return this.uniqueId; + } + + public String toString() + { + return "HangupEvent: channel:" + this.channel + " cause:" + this.causeTxt; //$NON-NLS-1$//$NON-NLS-2$ + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/LinkEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/LinkEvent.java new file mode 100644 index 000000000..7f3d0a969 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/LinkEvent.java @@ -0,0 +1,17 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; + +public class LinkEvent extends BridgeEvent +{ + private static final long serialVersionUID = 1L; + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(LinkEvent.class); + + @SuppressWarnings("deprecation") + public LinkEvent(final org.asteriskjava.manager.event.LinkEvent event) throws InvalidChannelName + { + super(event); + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ManagerEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ManagerEvent.java new file mode 100644 index 000000000..e4b3c086a --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ManagerEvent.java @@ -0,0 +1,19 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import java.util.EventObject; + +import org.apache.log4j.Logger; + +public class ManagerEvent extends EventObject +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(ManagerEvent.class); + + public ManagerEvent(Object source) + { + super(source); + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MasqueradeEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MasqueradeEvent.java new file mode 100644 index 000000000..c6fdb6af7 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MasqueradeEvent.java @@ -0,0 +1,194 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ChannelImpl; + +/** + * A Masquerade is used when a new channel is created to replace an existing + * channel. The typical cause of this is an action such as a Redirect, Park etc. + * + * During the Redirect a new channel will be created which has the same name as + * the existing channel but with a Suffix attached such as ASYNCGOTO. The suffix + * selected will depend on the actual action that cause the masquerade. + * + * As we proxy all channels a key goal for us is for the existing proxy to end + * up containing the new channel. + * + * The existing channel will eventually be renamed with a suffix and then + * go on to become a zombie before it is hungup. + * + * The masquerade event is associated a NewEvent, three renames and one hangup + * event. + * + * The terminology used by asterisk is quite confusing. + * + * The 'original channel' is the channel created as a result of the action + * (redirect, park etc). The 'clone' channel is the pre-existing channel that + * was acted upon. + * + * New Event: Original - the Original channel is currently holding the active + * call due to the transfer/park.. event. - the Original name will be something + * like ASYNCGOTO/SIP/101-0000002D:1351178863.121 + * + * Masquerade Event: Clone, Original (e.g. SIP/101-0000002D:1351178863.121, + * ASYNCGOTO/SIP/101-0000002D:1351178863.121) - swap the guts of the two + * channels - for us this means that we swap the channels between the two parent + * proxies. Some channel information is also copied from the clone to the + * original channel (yes this terminology appears to be arse about. Remember the + * 'clone' is the pre-existing channel). + * + * Rename: Clone to Clone (e.g. rename the pre-existing channel + * SIP/101-0000002D:1351178863.121 to SIP/101-0000002D:1351178863.121 - + * start shutting down the clone (pre-existing channel). Rename: Original to + * Clone's initial name Name (e.g rename + * ASYNCGOTO/SIP/101-0000002D:1351178863.121, SIP/101-0000002D:1351178863.121) + * Rename:Clone to Clone (e.g. rename + * SIP/101-0000002D:1351178863.121 to + * SIP/101-0000002D:1351178863.121 Hangup: Clone (e.g. hangup + * SIP/101-0000002D:1351178863.121 + * + * Example sequence: + * + * RedirectAction: chanel=(proxy=2) SIP/101-0000002F:1351181832.124 + * context=njr-operator exten=njr-musiconhold priority=1 extraContext=null + * extraChannel=null extraExten=null Dump of LiveChannels, cause:Add: (proxy=3) + * ASYNCGOTO/SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=1) + * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) + * SIP/101-0000002F:1351181832.124 ChannelProxy: (proxy=3) + * ASYNCGOTO/SIP/101-0000002F:1351181837.125 + * + * dispatch=NewChannelEvent: channel: (proxy=3) + * ASYNCGOTO/SIP/101-0000002F:1351181837.125 context=from-internal exten=null + * state=Up + * + * dispatch=MasqueradeEvent: originalChannel:(proxy=3) + * ASYNCGOTO/SIP/101-0000002F:1351181837.125 cloned from:(proxy=2) + * SIP/101-0000002F:1351181832.124 Dump of LiveChannels, cause:Masquerade: + * (proxy=2) ASYNCGOTO/SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=1) + * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) + * ASYNCGOTO/SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=3) + * SIP/101-0000002F:1351181832.124 + * + * RenameEvent: existing channel: (proxy=3) SIP/101-0000002F:1351181832.124 + * newname=SIP/101-0000002frawExisting:SIP/101-0000002f + * rawNewname:SIP/101-0000002frawUniquID:1351181832.124 Dump of + * LiveChannels, cause:RenameEvent: (proxy=3) + * SIP/101-0000002F:1351181832.124 ChannelProxy: (proxy=1) + * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) + * ASYNCGOTO/SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=3) + * SIP/101-0000002F:1351181832.124 + * + * dispatch=RenameEvent: existing channel: (proxy=2) + * ASYNCGOTO/SIP/101-0000002F:1351181837.125 + * newname=SIP/101-0000002frawExisting:AsyncGoto/SIP/101-0000002f + * rawNewname:SIP/101-0000002frawUniquID:1351181837.125 Dump of LiveChannels, + * cause:RenameEvent: (proxy=2) SIP/101-0000002F:1351181837.125 ChannelProxy: + * (proxy=1) SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) + * SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=3) + * SIP/101-0000002F:1351181832.124 + * + * dispatch=RenameEvent: existing channel: (proxy=3) + * SIP/101-0000002F:1351181832.124 + * newname=AsyncGoto/SIP/101-0000002frawExisting:SIP/101-0000002f + * rawNewname:AsyncGoto/SIP/101-0000002frawUniquID:1351181832.124 + * + * Dump of LiveChannels, cause:RenameEvent: (proxy=3) + * ASYNCGOTO/SIP/101-0000002F:1351181832.124 ChannelProxy: (proxy=1) + * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) + * SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=3) + * ASYNCGOTO/SIP/101-0000002F:1351181832.124 + * + * dispatch=BridgeEvent: channel1:(proxy=1) SIP/110-0000002E:1351181832.123 + * channel2:(proxy=3) ASYNCGOTO/SIP/101-0000002F:1351181832.124 + * bridgeState:Unlink + * + * dispatch=HangupEvent: channel:(proxy=3) + * ASYNCGOTO/SIP/101-0000002F:1351181832.124 cause:Normal Clearing Dump + * of LiveChannels, cause:Removing: (proxy=3) + * ASYNCGOTO/SIP/101-0000002F:1351181832.124 ChannelProxy: (proxy=1) + * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) + * SIP/101-0000002F:1351181837.125 + * + * dispatch=HangupEvent: channel:(proxy=1) SIP/110-0000002E:1351181832.123 + * cause:Normal Clearing Dump of LiveChannels, cause:Removing: (proxy=1) + * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) + * SIP/101-0000002F:1351181837.125 + * + * The end result is that the original (new) channel ends up with the clones + * (pre-existing) channel name. + * + * The pre-existing proxy ends up holding the original channel with the + * pre-existing channel's initial name. + * + * The masquerade event then is about ripping the guts out of the clone + * (pre-existing channel) and swapping with the original (new) channel. At the + * end of the swap the original (new) channel is left active (as it has the + * clones guts) and the clone (pre-existing) is inactive so we can hangup the + * clone as it is no longer needed. + * + * + * + * @author bsutton + * + */ +public class MasqueradeEvent extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(MasqueradeEvent.class); + + private final Channel _original; + + private final Channel _clone; + + private ChannelState cloneState; + + private ChannelState originalState; + + public MasqueradeEvent(final org.asteriskjava.manager.event.MasqueradeEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this._original = pbx.registerChannel(event.getOriginal(), ChannelImpl.UNKNOWN_UNIQUE_ID); + this._clone = pbx.registerChannel(event.getClone(), ChannelImpl.UNKNOWN_UNIQUE_ID); + this.originalState = ChannelState.valueOf(event.getOriginalStateDesc()); + this.cloneState = ChannelState.valueOf(event.getCloneStateDesc()); + } + + /** + * Returns the original channel + * + * @return + */ + public Channel getOriginal() + { + return this._original; + } + + public Channel getClone() + { + return this._clone; + } + + public ChannelState getCloneState() + { + return this.cloneState; + } + + public ChannelState getOriginalState() + { + return this.originalState; + } + + public String toString() + { + // Even though it talks about the original channel + return "MasqueradeEvent: originalChannel(new):" + this._original + " cloned from (pre-existing):" + this._clone; //$NON-NLS-1$//$NON-NLS-2$ + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeJoinEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeJoinEvent.java new file mode 100644 index 000000000..a562d8d00 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeJoinEvent.java @@ -0,0 +1,32 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; + +public class MeetMeJoinEvent extends AbstractMeetMeEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(MeetMeJoinEvent.class); + + CallerID callerID; + + public MeetMeJoinEvent(final org.asteriskjava.manager.event.MeetMeJoinEvent event) throws InvalidChannelName + { + super(event); + final PBX pbx = PBXFactory.getActivePBX(); + + pbx.buildCallerID(event.getCallerIdNum(), event.getCallerIdName()); + + } + + public CallerID getCallerID() + { + return this.callerID; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeLeaveEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeLeaveEvent.java new file mode 100644 index 000000000..657d90fd6 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeLeaveEvent.java @@ -0,0 +1,39 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; + +public class MeetMeLeaveEvent extends AbstractMeetMeEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(MeetMeLeaveEvent.class); + + private final CallerID callerID; + private final Long duration; + + public MeetMeLeaveEvent(final org.asteriskjava.manager.event.MeetMeLeaveEvent event) throws InvalidChannelName + { + super(event); + + final PBX pbx = PBXFactory.getActivePBX(); + + this.callerID = pbx.buildCallerID(event.getCallerIdNum(), event.getCallerIdName()); + this.duration = event.getDuration(); + } + + public CallerID getCallerID() + { + return this.callerID; + } + + public Long getDuration() + { + return this.duration; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewChannelEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewChannelEvent.java new file mode 100644 index 000000000..801f639ff --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewChannelEvent.java @@ -0,0 +1,45 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; + +public class NewChannelEvent extends AbstractChannelStateEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(NewChannelEvent.class); + + private final String accountCode; + private final String context; + private final String exten; + + public NewChannelEvent(final org.asteriskjava.manager.event.NewChannelEvent event) throws InvalidChannelName + { + super(event); + this.accountCode = event.getAccountCode(); + this.context = event.getContext(); + this.exten = event.getExten(); + } + + public String getAccountCode() + { + return this.accountCode; + } + + public String getContext() + { + return this.context; + } + + public String getExten() + { + return this.exten; + } + + public String toString() + { + return "NewChannelEvent: channel: " + this.getChannel() + " context=" + this.context + " exten=" + this.exten + " state=" + this.getChannelStateDesc(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewExtenEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewExtenEvent.java new file mode 100644 index 000000000..58c97e3af --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewExtenEvent.java @@ -0,0 +1,67 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class NewExtenEvent extends ManagerEvent implements ChannelEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(NewExtenEvent.class); + + private final String context; + private final String extension; + private final String application; + private final String appData; + private final Integer priority; + private final Channel channel; + + public NewExtenEvent(final org.asteriskjava.manager.event.NewExtenEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this.channel = pbx.registerChannel(event.getChannel(), event.getUniqueId()); + this.context = event.getContext(); + this.extension = event.getExtension(); + this.application = event.getApplication(); + this.appData = event.getAppData(); + this.priority = event.getPriority(); + } + + public String getContext() + { + return this.context; + } + + public String getExtension() + { + return this.extension; + } + + public String getApplication() + { + return this.application; + } + + public String getAppData() + { + return this.appData; + } + + public Integer getPriority() + { + return this.priority; + } + + @Override + public Channel getChannel() + { + return this.channel; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewStateEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewStateEvent.java new file mode 100644 index 000000000..349d54c88 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewStateEvent.java @@ -0,0 +1,28 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.ChannelProxy; + +public class NewStateEvent extends AbstractChannelStateEvent +{ + private static final long serialVersionUID = 1L; + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(NewStateEvent.class); + private ChannelProxy destChannel; + + public NewStateEvent(final org.asteriskjava.manager.event.NewStateEvent event) throws InvalidChannelName + { + super(event); + } + + public ChannelProxy getDestination() + { + return destChannel; + } + + public String toString() + { + return "NewStateEvent: channel:" + this.getChannel() + " channelState:" + this.getChannelState(); //$NON-NLS-1$//$NON-NLS-2$ + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/OriginateResponseEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/OriginateResponseEvent.java new file mode 100644 index 000000000..45d273fe2 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/OriginateResponseEvent.java @@ -0,0 +1,101 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.ChannelEventHelper; +import org.asteriskjava.pbx.internal.core.ChannelImpl; +import org.asteriskjava.pbx.internal.core.TechType; + +public class OriginateResponseEvent extends ResponseEvent implements ChannelEvent +{ + + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(OriginateResponseEvent.class); + + // reflects whether we have a iChannel or an iEndPoint. We can't have both. + private final boolean isChannel; + private final Channel channel; + private final EndPoint endPoint; + private final String response; + private final String context; + private final String exten; + private final Integer reason; + + public OriginateResponseEvent(final org.asteriskjava.manager.event.OriginateResponseEvent event) + throws InvalidChannelName + { + super(event); + + PBX pbx = PBXFactory.getActivePBX(); + + // The doco says this should be a channel but under 1.4 it comes up as + // an endpoint. + this.isChannel = pbx.isChannel(event.getChannel()); + if (this.isChannel) + { + this.channel = ChannelEventHelper.registerChannel(event.getChannel(), + (event.getUniqueId() == null ? ChannelImpl.UNKNOWN_UNIQUE_ID : event.getUniqueId()), + event.getCallerIdNum(), event.getCallerIdName()); + this.endPoint = null; + } + else + { + this.endPoint = pbx.buildEndPoint(event.getChannel(), TechType.SIP); + this.channel = null; + } + + this.response = event.getResponse(); + this.context = event.getContext(); + this.exten = event.getExten(); + this.reason = event.getReason(); + + } + + public String getResponse() + { + return this.response; + } + + public String getContext() + { + return this.context; + } + + public String getExten() + { + return this.exten; + } + + public Integer getReason() + { + return this.reason; + } + + public boolean isChannel() + { + return this.isChannel; + } + + @Override + public Channel getChannel() + { + return this.channel; + } + + public EndPoint getEndPoint() + { + return this.endPoint; + } + + public boolean isSuccess() + { + return "Success".equalsIgnoreCase(this.response); //$NON-NLS-1$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ParkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ParkedCallEvent.java new file mode 100644 index 000000000..dcd821088 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ParkedCallEvent.java @@ -0,0 +1,55 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ChannelImpl; + +public class ParkedCallEvent extends ManagerEvent +{ + + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(ParkedCallEvent.class); + + private final Channel fromChannel; + private final Integer timeout; + private String exten; + + public ParkedCallEvent(final org.asteriskjava.manager.event.ParkedCallEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + if (event.getParkerDialString() != null) + this.fromChannel = pbx.registerChannel(event.getParkerDialString(), ChannelImpl.UNKNOWN_UNIQUE_ID); + else + this.fromChannel = null; + this.timeout = event.getTimeout(); + this.exten = event.getExten(); + } + + /** + * The channel that parked the call. In some circumstances this can be null. + * + * @return + */ + public Channel getFromChannel() + { + return this.fromChannel; + } + + public Integer getTimeout() + { + return this.timeout; + } + + public String getExten() + { + return this.exten; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerEntryEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerEntryEvent.java new file mode 100644 index 000000000..dcf86e3e2 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerEntryEvent.java @@ -0,0 +1,30 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.core.TechType; + +public class PeerEntryEvent extends ResponseEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(PeerEntryEvent.class); + + private final EndPoint peer; + + public PeerEntryEvent(final org.asteriskjava.manager.event.PeerEntryEvent event) + { + super(event); + + PBX pbx = PBXFactory.getActivePBX(); + this.peer = pbx.buildEndPoint(event.getObjectName(), TechType.valueOf(event.getChannelType())); + } + + public EndPoint getPeer() + { + return this.peer; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerStatusEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerStatusEvent.java new file mode 100644 index 000000000..e5367dd8e --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerStatusEvent.java @@ -0,0 +1,31 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class PeerStatusEvent extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(PeerStatusEvent.class); + + private final EndPoint peer; + + public PeerStatusEvent(final org.asteriskjava.manager.event.PeerStatusEvent event) + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this.peer = pbx.buildEndPoint(event.getPeer());// registerChannel(event.getPeer(), + // Channel.UNKNOWN_UNIQUE_ID); + } + + public EndPoint getPeer() + { + return this.peer; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerlistCompleteEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerlistCompleteEvent.java new file mode 100644 index 000000000..2f7534b95 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerlistCompleteEvent.java @@ -0,0 +1,15 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; + +public class PeerlistCompleteEvent extends ResponseEvent +{ + private static final long serialVersionUID = 1L; + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(PeerlistCompleteEvent.class); + + public PeerlistCompleteEvent(final org.asteriskjava.manager.event.PeerlistCompleteEvent event) + { + super(event); + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/QueueCallerLeaveEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/QueueCallerLeaveEvent.java new file mode 100644 index 000000000..c2b0a1668 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/QueueCallerLeaveEvent.java @@ -0,0 +1,28 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.ChannelEventHelper; + +public class QueueCallerLeaveEvent extends ChannelEventHelper +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(QueueCallerLeaveEvent.class); + + private String queue; + + public QueueCallerLeaveEvent(final org.asteriskjava.manager.event.QueueCallerLeaveEvent event) throws InvalidChannelName + { + super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + + queue = event.getQueue(); + } + + public String getQueueName() + { + return queue; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/RenameEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/RenameEvent.java new file mode 100644 index 000000000..d2da6e2b7 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/RenameEvent.java @@ -0,0 +1,59 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ChannelProxy; + +public class RenameEvent extends ManagerEvent implements ChannelEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(RenameEvent.class); + + /** + * The existing channel which is about to be renamed. + */ + private final Channel _channel; + + /** + * New name of the channel after renaming occurred. + */ + private final String _newName; + + public RenameEvent(final org.asteriskjava.manager.event.RenameEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this._channel = pbx.registerChannel(event.getChannel(), event.getUniqueId()); + this._newName = event.getNewname(); + + assert ((ChannelProxy) this._channel).getRealChannel().getUniqueId() + .compareToIgnoreCase(event.getUniqueId()) == 0 : "Rename registered against incorrect channel"; //$NON-NLS-1$ + } + + @Override + public final Channel getChannel() + { + return this._channel; + } + + public final String getNewName() + { + return this._newName; + } + + @Override + public String toString() + { + org.asteriskjava.manager.event.RenameEvent rawEvent = (org.asteriskjava.manager.event.RenameEvent) getSource(); + return "RenameEvent: existing channel: " + this._channel + " newname=" + this._newName //$NON-NLS-1$ //$NON-NLS-2$ + + "rawExisting:" + rawEvent.getChannel() + " rawNewname:" + rawEvent.getNewname() //$NON-NLS-1$ //$NON-NLS-2$ + + "rawUniquID:" + rawEvent.getUniqueId(); //$NON-NLS-1$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvent.java new file mode 100644 index 000000000..33da1f7e7 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvent.java @@ -0,0 +1,32 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; + +public class ResponseEvent extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(ResponseEvent.class); + + private final String actionId; + private final String internalActionId; + + public ResponseEvent(final org.asteriskjava.manager.event.ResponseEvent event) + { + super(event); + this.actionId = event.getActionId(); + this.internalActionId = event.getInternalActionId(); + } + + public String getActionId() + { + return this.actionId; + } + + public String getInternalActionId() + { + return this.internalActionId; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvents.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvents.java new file mode 100644 index 000000000..07b965892 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvents.java @@ -0,0 +1,27 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import java.util.ArrayList; +import java.util.Collection; + +public class ResponseEvents +{ + + ArrayList events = new ArrayList<>(); + + /** + * Returns a Collection of ManagerEvents that have been received including + * the last one that indicates completion. + * + * @return a Collection of ManagerEvents received. + */ + public Collection getEvents() + { + return this.events; + } + + public void add(ResponseEvent event) + { + this.events.add(event); + + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusCompleteEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusCompleteEvent.java new file mode 100644 index 000000000..50a2c9311 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusCompleteEvent.java @@ -0,0 +1,15 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; + +public class StatusCompleteEvent extends ResponseEvent +{ + private static final long serialVersionUID = 1L; + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(StatusCompleteEvent.class); + + public StatusCompleteEvent(final org.asteriskjava.manager.event.StatusCompleteEvent event) + { + super(event); + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusEvent.java new file mode 100644 index 000000000..d046483bc --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusEvent.java @@ -0,0 +1,115 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import java.util.Map; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.DialPlanExtension; + +public class StatusEvent extends ResponseEvent implements ChannelEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(StatusEvent.class); + + private final Channel channel; + private final CallerID callerId; + private final String accountCode; + private final ChannelState channelState; + private final String channelStateDesc; + private final String context; + private final DialPlanExtension extension; + private final Integer priority; + private final Integer seconds; + private final Channel bridgedChannel; + private final Map variables; + private final String uniqueId; + + public StatusEvent(final org.asteriskjava.manager.event.StatusEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this.channel = pbx.registerChannel(event.getChannel(), event.getUniqueId()); + this.callerId = pbx.buildCallerID(event.getCallerIdNum(), event.getCallerIdName()); + this.accountCode = event.getAccountCode(); + this.channelState = ChannelState.valueOfDesc(event.getChannelStateDesc()); + this.channelStateDesc = event.getChannelStateDesc(); + this.context = event.getContext(); + this.extension = pbx.buildDialPlanExtension(event.getExtension()); + this.priority = event.getPriority(); + this.seconds = event.getSeconds(); + if (event.getBridgedChannel() != null) + this.bridgedChannel = pbx.registerChannel(event.getBridgedChannel(), event.getBridgedUniqueId()); + else + this.bridgedChannel = null; + this.variables = event.getVariables(); + this.uniqueId = event.getUniqueId(); + } + + @Override + public final Channel getChannel() + { + return this.channel; + } + + public final CallerID getCallerId() + { + return this.callerId; + } + + public final String getAccountCode() + { + return this.accountCode; + } + + public final ChannelState getState() + { + return this.channelState; + } + + public final String getChannelStateDesc() + { + return this.channelStateDesc; + } + + public final String getContext() + { + return this.context; + } + + public final DialPlanExtension getExtension() + { + return this.extension; + } + + public final Integer getPriority() + { + return this.priority; + } + + public final Integer getSeconds() + { + return this.seconds; + } + + public final Channel getBridgedChannel() + { + return this.bridgedChannel; + } + + public final Map getVariables() + { + return this.variables; + } + + public String getUniqueId() + { + return this.uniqueId; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnlinkEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnlinkEvent.java new file mode 100644 index 000000000..17c6a7c32 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnlinkEvent.java @@ -0,0 +1,17 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; + +public class UnlinkEvent extends BridgeEvent +{ + private static final long serialVersionUID = 1L; + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(UnlinkEvent.class); + + @SuppressWarnings("deprecation") + public UnlinkEvent(final org.asteriskjava.manager.event.UnlinkEvent event) throws InvalidChannelName + { + super(event); + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnparkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnparkedCallEvent.java new file mode 100644 index 000000000..2545c8e23 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnparkedCallEvent.java @@ -0,0 +1,32 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ChannelImpl; + +public class UnparkedCallEvent extends AbstractParkedCallEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(UnparkedCallEvent.class); + + private final Channel fromChannel; + + public UnparkedCallEvent(final org.asteriskjava.manager.event.UnparkedCallEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this.fromChannel = pbx.registerChannel(event.getParkerDialString(), ChannelImpl.UNKNOWN_UNIQUE_ID); + } + + public Channel getFromChannel() + { + return this.fromChannel; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/VarSetEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/VarSetEvent.java new file mode 100644 index 000000000..be67ffdb9 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/VarSetEvent.java @@ -0,0 +1,50 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class VarSetEvent extends ManagerEvent implements ChannelEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(VarSetEvent.class); + + /** + * The name of the channel. + */ + private final Channel _channel; + + private String _variableName; + + private String _variableValue; + + public VarSetEvent(final org.asteriskjava.manager.event.VarSetEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + this._channel = pbx.registerChannel(event.getChannel(), event.getUniqueId()); + this._variableName = event.getVariable(); + this._variableValue = event.getValue(); + } + + @Override + public Channel getChannel() + { + return this._channel; + } + + public String getVariableName() + { + return this._variableName; + } + + public String getVariableValue() + { + return this._variableValue; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/CommandResponse.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/CommandResponse.java new file mode 100644 index 000000000..00af9f3d1 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/CommandResponse.java @@ -0,0 +1,25 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.response; + +import java.util.List; + +import org.apache.log4j.Logger; + +public class CommandResponse extends ManagerResponse +{ + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(CommandResponse.class); + private List result; + + public CommandResponse(org.asteriskjava.manager.response.CommandResponse response) + { + super(response); + this.result = response.getResult(); + + } + + public List getResult() + { + return this.result; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerError.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerError.java new file mode 100644 index 000000000..9b22661c9 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerError.java @@ -0,0 +1,16 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.response; + +import org.apache.log4j.Logger; + +public class ManagerError extends ManagerResponse +{ + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(ManagerError.class); + + public ManagerError(org.asteriskjava.manager.response.ManagerError error) + { + super(error); + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerResponse.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerResponse.java new file mode 100644 index 000000000..e99afa2c4 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerResponse.java @@ -0,0 +1,86 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.response; + +import java.util.Date; +import java.util.Locale; +import java.util.Map; + +public class ManagerResponse +{ + + private Date _dateReceived; + private String _actionId; + + /** + * The server from which this response has been received (only used with + * AstManProxy). + */ + final private String _server; + final private String _response; + final private String _eventList; + final private String message; + final private String _uniqueId; + final private Map _attributes; + + public ManagerResponse(org.asteriskjava.manager.response.ManagerResponse response) + { + this._dateReceived = response.getDateReceived(); + this._actionId = response.getActionId(); + this._server = response.getServer(); + this._response = response.getResponse(); + this._eventList = response.getEventList(); + this._uniqueId = response.getUniqueId(); + this._attributes = response.getAttributes(); + this.message = response.getMessage(); + } + + public Date getDateReceived() + { + return this._dateReceived; + } + + public String getActionId() + { + return this._actionId; + } + + public String getServer() + { + return this._server; + } + + public String getResponse() + { + return this._response; + } + + public String getEventList() + { + return this._eventList; + } + + public String getMessage() + { + return this.message; + } + + public String getUniqueId() + { + return this._uniqueId; + } + + public Map getAttributes() + { + return this._attributes; + } + + public String getAttribute(String key) + { + return (String) this._attributes.get(key.toLowerCase(Locale.ENGLISH)); + } + + public boolean isSuccess() + { + return this._response.compareToIgnoreCase("Success") == 0; //$NON-NLS-1$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/userEvents/UserEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/userEvents/UserEvent.java new file mode 100644 index 000000000..9216e2699 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/userEvents/UserEvent.java @@ -0,0 +1,37 @@ +package org.asteriskjava.pbx.internal.asterisk.wrap.userEvents; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class UserEvent extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(UserEvent.class); + + private Channel channel; + + public UserEvent(org.asteriskjava.manager.event.UserEvent source, Channel channel) + { + super(source); + this.channel = channel; + } + + public UserEvent(org.asteriskjava.manager.event.UserEvent event) throws InvalidChannelName + { + super(event); + + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + this.channel = pbx.registerChannel(event.getChannel(), event.getUniqueId()); + } + + public Channel getChannel() + { + return this.channel; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ActiveCallListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/ActiveCallListener.java new file mode 100644 index 000000000..1a4c44d22 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ActiveCallListener.java @@ -0,0 +1,17 @@ +package org.asteriskjava.pbx.internal.core; + +import org.asteriskjava.pbx.Call; + +/** + * Used to notify a listener that the status of a call has changed. For instance + * the call may have just been parked. + * + * @author bsutton + * + */ +public interface ActiveCallListener +{ + + void callStatusChanged(Call call, boolean isHidden); + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java new file mode 100644 index 000000000..08bb9892a --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -0,0 +1,867 @@ +package org.asteriskjava.pbx.internal.core; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.asteriskjava.AsteriskVersion; +import org.asteriskjava.manager.AuthenticationFailedException; +import org.asteriskjava.manager.EventTimeoutException; +import org.asteriskjava.manager.ManagerConnectionState; +import org.asteriskjava.manager.TimeoutException; +import org.asteriskjava.manager.event.AbstractChannelEvent; +import org.asteriskjava.pbx.Activity; +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.Call.OperandChannel; +import org.asteriskjava.pbx.CallDirection; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.ChannelHangupListener; +import org.asteriskjava.pbx.CompletionAdaptor; +import org.asteriskjava.pbx.DTMFTone; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.Trunk; +import org.asteriskjava.pbx.activities.BlindTransferActivity; +import org.asteriskjava.pbx.activities.BlindTransferActivityImpl; +import org.asteriskjava.pbx.activities.BridgeActivity; +import org.asteriskjava.pbx.activities.BridgeActivityImpl; +import org.asteriskjava.pbx.activities.DialActivity; +import org.asteriskjava.pbx.activities.DialActivityImpl; +import org.asteriskjava.pbx.activities.DialToAgiActivity; +import org.asteriskjava.pbx.activities.DialToAgiActivityImpl; +import org.asteriskjava.pbx.activities.HoldActivity; +import org.asteriskjava.pbx.activities.HoldActivityImpl; +import org.asteriskjava.pbx.activities.JoinActivity; +import org.asteriskjava.pbx.activities.JoinActivityImpl; +import org.asteriskjava.pbx.activities.ParkActivity; +import org.asteriskjava.pbx.activities.ParkActivityImpl; +import org.asteriskjava.pbx.activities.SplitActivity; +import org.asteriskjava.pbx.activities.SplitActivityImpl; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHangup; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHold; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.CallerIDImpl; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; +import org.asteriskjava.pbx.internal.asterisk.MeetmeRoomControl; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.EventGeneratingAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.HangupAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ManagerAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.PlayDtmfAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ResponseEvents; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.internal.managerAPI.RedirectCall; + +public enum AsteriskPBX implements PBX, ChannelHangupListener +{ + + SELF; + + private final Logger logger = Logger.getLogger(AsteriskPBX.class); + private boolean muteSupported; + private boolean bridgeSupport; + + private static final int MAX_MEETME_ROOMS = 50; + + private LiveChannelManager liveChannels; + + AsteriskPBX() + { + try + { + CoherentManagerConnection.init(); + + this.muteSupported = CoherentManagerConnection.getInstance().isMuteAudioSupported(); + this.bridgeSupport = CoherentManagerConnection.getInstance().isBridgeSupported(); + + try + { + MeetmeRoomControl.init(this, AsteriskPBX.MAX_MEETME_ROOMS); + } + catch (Throwable e) + { + logger.error(e, e); + } + + this.liveChannels = new LiveChannelManager(); + + } + catch (IllegalStateException | IOException | AuthenticationFailedException | TimeoutException e1) + { + logger.error(e1, e1); + } + + } + + /** + * Call this method when shutting down the PBX interface to allow it to + * cleanup. + */ + @Override + public void shutdown() + { + MeetmeRoomControl.getInstance().stop(); + CoherentManagerConnection.getInstance().shutDown(); + } + + @Override + public boolean isBridgeSupported() + { + return this.bridgeSupport; + } + + @Override + public BlindTransferActivity blindTransfer(Call call, Call.OperandChannel channelToTransfer, EndPoint transferTarget, + CallerID toCallerID, boolean autoAnswer, long timeout) + { + final CompletionAdaptor completion = new CompletionAdaptor<>(); + + final BlindTransferActivityImpl transfer = new BlindTransferActivityImpl(call, channelToTransfer, transferTarget, + toCallerID, autoAnswer, timeout, completion); + + completion.waitForCompletion(timeout + 2, TimeUnit.SECONDS); + + return transfer; + + } + + @Override + public BlindTransferActivity blindTransfer(Call call, Call.OperandChannel channelToTransfer, EndPoint transferTarget, + CallerID toCallerID, boolean autoAnswer, long timeout, ActivityCallback listener) + { + return new BlindTransferActivityImpl(call, channelToTransfer, transferTarget, toCallerID, autoAnswer, timeout, + listener); + + } + + public BlindTransferActivity blindTransfer(Channel agentChannel, EndPoint transferTarget, CallerID toCallerID, + boolean autoAnswer, int timeout, ActivityCallback iCallback) throws PBXException + { + return new BlindTransferActivityImpl(agentChannel, transferTarget, toCallerID, autoAnswer, timeout, iCallback); + + } + + /** + * Utility method to bridge two channels + * + * @param lhsChannel + * @param rhsChannel + * @param direction + * @throws PBXException + */ + public BridgeActivity bridge(final Channel lhsChannel, final Channel rhsChannel) throws PBXException + { + final CompletionAdaptor completion = new CompletionAdaptor<>(); + + final BridgeActivityImpl bridge = new BridgeActivityImpl(lhsChannel, rhsChannel, completion); + + completion.waitForCompletion(10, TimeUnit.SECONDS); + + return bridge; + + } + + @Override + public SplitActivity split(final Call callToSplit) throws PBXException + { + final CompletionAdaptor completion = new CompletionAdaptor<>(); + + final SplitActivityImpl split = new SplitActivityImpl(callToSplit, completion); + + completion.waitForCompletion(10, TimeUnit.SECONDS); + + return split; + } + + @Override + public SplitActivity split(final Call callToSplit, final ActivityCallback listener) + { + + return new SplitActivityImpl(callToSplit, listener); + } + + // private SplitActivity _split(final iCall callToSplit, final iEndPoint + // remotePartyTarget, + // final iEndPoint locaPartyTarget, final iCallback + // listener) + // { + // if (!callToSplit.canSplit()) + // throw new IllegalStateException("The call must have exactly two channels + // to be split."); //$NON-NLS-1$ + // + // iChannel remote = callToSplit.getRemoteParty(); + // iChannel local = callToSplit.getLocalParty(); + // + // final SplitActivity split = new SplitActivity(remote, remotePartyTarget, + // local, locaPartyTarget, listener); + // return split; + // } + // + // private SplitActivity _split(final iChannel lhs, final iEndPoint + // lhsTarget, + // final iChannel rhs, final iEndPoint rhsTarget, final + // iCallback listener) + // { + // final SplitActivity split = new SplitActivity(lhs, lhsTarget, rhs, + // rhsTarget, listener); + // return split; + // } + // + /** + * Joins two calls not returning until the join completes. The join will + * complete almost immediately as it is a simple bridging of two active + * channels. Each call must only have one active channel + */ + @Override + public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, + CallDirection direction) + { + final CompletionAdaptor completion = new CompletionAdaptor<>(); + + final JoinActivityImpl join = new JoinActivityImpl(lhs, originatingOperand, rhs, acceptingOperand, direction, + completion); + + completion.waitForCompletion(10, TimeUnit.SECONDS); + + return join; + + } + + /** + * Joins two calls not returning until the join completes. The join will + * complete almost immediately as it is a simple bridging of two active + * channels. Each call must only have one active channel + */ + @Override + public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, + CallDirection direction, ActivityCallback listener) + { + final JoinActivityImpl join = new JoinActivityImpl(lhs, originatingOperand, rhs, acceptingOperand, direction, + listener); + + return join; + } + + @Override + public void conference(final Channel channelOne, final Channel channelTwo, final Channel channelThree) + { + // TODO Auto-generated method stub + + } + + @Override + public void conference(final Channel channelOne, final Channel channelTwo, final Channel channelThree, + final ActivityCallback callback) + { + // TODO Auto-generated method stub + + } + + @Override + public DialActivity dial(final Trunk trunk, final EndPoint from, final CallerID fromCallerID, final EndPoint to, + final CallerID toCallerID) + { + final CompletionAdaptor completion = new CompletionAdaptor<>(); + + final DialActivityImpl dialer = new DialActivityImpl(trunk, from, to, toCallerID, false, completion, null); + + completion.waitForCompletion(3, TimeUnit.MINUTES); + + return dialer; + } + + public DialLocalToAgiActivity dialLocalToAgi(final EndPoint from, final CallerID fromCallerID, + ActivityCallback callback, Map channelVarsToSet) + { + return new DialLocalToAgiActivity(from, fromCallerID, callback, channelVarsToSet); + } + + public DialActivity dial(final Trunk trunk, final EndPoint from, final CallerID fromCallerID, final EndPoint to, + final CallerID toCallerID, final ActivityCallback callback, Map channelVarsToSet) + { + final DialActivityImpl dialer = new DialActivityImpl(trunk, from, to, toCallerID, false, callback, channelVarsToSet); + return dialer; + } + + @Override + public DialActivity dial(final Trunk trunk, final EndPoint from, final CallerID fromCallerID, final EndPoint to, + final CallerID toCallerID, final ActivityCallback callback) + { + final DialActivityImpl dialer = new DialActivityImpl(trunk, from, to, toCallerID, false, callback, null); + return dialer; + } + + @Override + public void hangup(final Channel channel) throws PBXException + { + if (channel.isLive()) + { + logger.debug("Sending hangup action for channel: " + channel); //$NON-NLS-1$ + + PBX pbx = PBXFactory.getActivePBX(); + if (!pbx.waitForChannelToQuiescent(channel, 3000)) + throw new PBXException("Channel: " + channel + " cannot be retrieved as it is still in transition."); + + final HangupAction hangup = new HangupAction(channel); + try + { + channel.setCurrentActivityAction(new AgiChannelActivityHangup()); + CoherentManagerConnection.sendAction(hangup, 1000); + } + catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) + { + logger.error(e, e); + throw new PBXException(e); + } + } + else + logger.debug("Suppressed hangup for " + channel + " as it was already hungup"); //$NON-NLS-1$ //$NON-NLS-2$ + + } + + @Override + public void hangup(final Channel channel, final ActivityCallback callback) + { + throw new UnsupportedOperationException("Not yet implemented."); //$NON-NLS-1$ + } + + @Override + public HoldActivity hold(final Channel channel) + { + final CompletionAdaptor completion = new CompletionAdaptor<>(); + + HoldActivity activity = null; + try + { + activity = new HoldActivityImpl(channel, completion); + completion.waitForCompletion(10, TimeUnit.SECONDS); + + } + catch (final Exception e) + { + logger.error(e, e); + + } + return activity; + } + + @Override + public boolean isMuteSupported() + { + return this.muteSupported; + } + + @Override + public ParkActivity park(final Call call, final Channel parkChannel) + { + final CompletionAdaptor completion = new CompletionAdaptor<>(); + + final ParkActivity activity = new ParkActivityImpl(call, parkChannel, completion); + parkChannel.setParked(true); + + completion.waitForCompletion(10, TimeUnit.SECONDS); + return activity; + } + + @Override + public ParkActivity park(final Call call, final Channel parkChannel, final ActivityCallback callback) + { + final ParkActivity activity = new ParkActivityImpl(call, parkChannel, callback); + return activity; + } + + @Override + public void sendDTMF(final Channel channel, final DTMFTone tone) throws PBXException + { + try + { + if (!waitForChannelToQuiescent(channel, 3000)) + throw new PBXException("Channel: " + channel + " cannot play dtmf as it is still in transition."); + + CoherentManagerConnection.sendAction(new PlayDtmfAction(channel, tone), 1000); + } + catch (final Exception e) + { + logger.error(e, e); + throw new PBXException(e); + } + } + + @Override + public void sendDTMF(final Channel channel, final DTMFTone tone, final ActivityCallback callback) + { + // TODO Auto-generated method stub + + } + + @Override + public void transferToMusicOnHold(final Channel channel) throws PBXException + { + final RedirectCall transfer = new RedirectCall(); + transfer.redirect(channel, new AgiChannelActivityHold()); + } + + public String getManagementContext() + { + final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + return settings.getManagementContext(); + } + + @Override + public ChannelProxy getChannelByEndPoint(final EndPoint endPoint) + { + return this.liveChannels.getChannelByEndPoint(endPoint); + } + + @Override + public void channelHangup(Channel channel, Integer cause, String causeText) + { + this.liveChannels.remove((ChannelProxy) channel); + } + + public DialPlanExtension getExtensionPark() + { + final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + return this.buildDialPlanExtension(settings.getExtensionPark()); + } + + @Override + public EndPoint getExtensionAgi() + { + final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + return this.buildDialPlanExtension(settings.getAgiExtension()); + } + + /** + * Builds an end point from a fully qualified end point name. If the + * endpoint name doesn't have a tech then it is considered invalid and null + * is returned. + */ + + @Override + public EndPoint buildEndPoint(final String fullyQualifiedEndPoint) + { + EndPoint endPoint = null; + try + { + endPoint = new EndPointImpl(fullyQualifiedEndPoint); + } + catch (final IllegalArgumentException e) + { + logger.warn(e, e); + } + return endPoint; + } + + /** + * Builds an end point from an end point name. If the endpoint name doesn't + * have a tech specified then the defaultTech is used. + */ + @Override + public EndPoint buildEndPoint(final String endPointName, final TechType defaultTech) + { + EndPoint endPoint = null; + try + { + if (endPointName == null || endPointName.trim().length() == 0) + endPoint = new EndPointImpl(); + else + endPoint = new EndPointImpl(endPointName, defaultTech); + } + catch (final IllegalArgumentException e) + { + logger.error(e, e); + } + return endPoint; + + } + + /** + * Builds an end point from an end point name. If the endpoint name doesn't + * have a tech specified then the defaultTech is used. + */ + public DialPlanExtension buildDialPlanExtension(final String extension) + { + DialPlanExtension dialPlan = null; + try + { + dialPlan = new DialPlanExtension(extension); + } + catch (final IllegalArgumentException e) + { + logger.error(e, e); + } + return dialPlan; + + } + + @Override + public CallerID buildCallerID(final String number, final String name) + { + return new CallerIDImpl(number, name); + } + + /** + * Convenience method to build a call id from an event. + * + * @param event + */ + public CallerID buildCallerID(final AbstractChannelEvent event) + { + final String number = event.getCallerIdNum(); + final String name = event.getCallerIdName(); + return this.buildCallerID(number, name); + } + + public ChannelProxy registerChannel(final String channelName, final String uniqueID) throws InvalidChannelName + { + ChannelProxy proxy = null; + synchronized (this.liveChannels) + { + String localUniqueID = (uniqueID == null ? ChannelImpl.UNKNOWN_UNIQUE_ID : uniqueID); + proxy = this.findChannel(cleanChannelName(channelName), localUniqueID); + if (proxy == null) + { + proxy = new ChannelProxy(new ChannelImpl(channelName, localUniqueID)); + this.liveChannels.add(proxy); + proxy.addHangupListener(this); + } + } + return proxy; + } + + /** + * Cleans up the channel name by applying the following: 1) trim any + * whitespace 2) convert to upper case for easy string comparisions 3) strip + * of the masquerade prefix if it exists 4) strip the zombie suffix. + * + * @param name + * @return + */ + private String cleanChannelName(final String name) + { + String cleanedName = name.trim().toUpperCase(); + + for (final String prefix : ChannelImpl._actions) + { + if (cleanedName.startsWith(prefix)) + { + cleanedName = cleanedName.substring(prefix.length()); + break; + } + } + + return name; + } + + public Channel registerHangupChannel(String channel, String uniqueId) throws InvalidChannelName + { + Channel newChannel = null; + synchronized (this.liveChannels) + { + newChannel = this.findChannel(channel, uniqueId); + if (channel == null) + { + // WE don't add this channel to the liveChannels as it is in the + // process + // of being hungup so we don't need to track it. + // If we tried to track it that would likely cause a problem + // as the livechannel manager would never be able to discard it + // as + // it relies on the hangup event which is being processed right + // now. + newChannel = new ChannelProxy(new ChannelImpl(channel, uniqueId)); + } + } + return newChannel; + } + + // @Override + // public iChannel registerChannel(AsteriskChannel asteriskChannel) throws + // InvalidChannelName + // { + // ChannelProxy proxy = null; + // synchronized (this.liveChannels) + // { + // proxy = this.findChannel(asteriskChannel.getName(), + // asteriskChannel.getId()); + // if (proxy == null) + // { + // proxy = new ChannelProxy(new Channel(asteriskChannel)); + // this.liveChannels.add(proxy); + // proxy.addListener(this); + // } + // else + // { + // // update the channel + // proxy.getRealChannel().updateAsteriskChannel(asteriskChannel); + // } + // } + // return proxy; + // + // } + + // public void onNewChannel(AsteriskChannel asteriskChannel) throws + // InvalidChannelName + // { + // registerChannel(asteriskChannel); + // } + // + public ChannelProxy findChannel(final String channelName, final String uniqueID) + { + return this.liveChannels.findChannel(channelName, uniqueID); + } + + public MeetmeRoom acquireMeetmeRoom() + { + return MeetmeRoomControl.getInstance().findAvailableRoom(); + } + + public void addListener(FilteredManagerListener listener) + { + CoherentManagerConnection connection = CoherentManagerConnection.getInstance(); + connection.addListener(listener); + } + + public void removeListener(FilteredManagerListener listener) + { + CoherentManagerConnection connection = CoherentManagerConnection.getInstance(); + connection.removeListener(listener); + } + + /** + * sends an action with a default timeout of 30 seconds. + * + * @param theAction + * @return + * @throws IllegalArgumentException + * @throws IllegalStateException + * @throws IOException + * @throws TimeoutException + */ + public ManagerResponse sendAction(ManagerAction theAction) + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException + { + return CoherentManagerConnection.sendAction(theAction, 30000); + } + + public ManagerResponse sendAction(ManagerAction theAction, int timeout) + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException + { + return CoherentManagerConnection.sendAction(theAction, timeout); + } + + public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) + throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException + { + ResponseEvents events = CoherentManagerConnection.sendEventGeneratingAction(action); + return events; + + } + + public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, int timeout) + throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException + { + return CoherentManagerConnection.sendEventGeneratingAction(action, timeout); + + } + + public void setVariable(Channel channel, String name, String value) throws PBXException + { + CoherentManagerConnection.getInstance().setVariable(channel, name, value); + + } + + public void sendActionNoWait(final ManagerAction action) + { + CoherentManagerConnection.sendActionNoWait(action); + + } + + public String getVariable(Channel channel, String name) + { + return CoherentManagerConnection.getInstance().getVariable(channel, name); + } + + public AsteriskVersion getVersion() + { + return CoherentManagerConnection.getInstance().getVersion(); + } + + public boolean isConnected() + { + return ((CoherentManagerConnection.managerConnection != null) + && (CoherentManagerConnection.managerConnection.getState() == ManagerConnectionState.CONNECTED)); + } + + public boolean isMeetmeInstalled() + { + return MeetmeRoomControl.getInstance().isMeetmeInstalled(); + } + + @Override + public boolean isChannel(String channelName) + { + boolean isChannel = false; + try + { + registerChannel(channelName, ChannelImpl.UNKNOWN_UNIQUE_ID); + isChannel = true; + } + catch (InvalidChannelName e) + { + // if we get here then its not avalid channel name. + } + return isChannel; + } + + static public String getSIPADDHeader(final boolean inherit, final boolean targetIsSIP) + { + String sipHeader = "SIPADDHEADER"; //$NON-NLS-1$ + if (!targetIsSIP || inherit) + { + sipHeader = "__" + sipHeader; //$NON-NLS-1$ + } + return sipHeader; + } + + /** + * Waits for a channel to become quiescent. A Quiescent channel is one that + * is not in the middle of a name change (e.g. masquerade) + * + * @param channel + * @param timeout the time to wait (in milliseconds) for the channel to + * become quiescent. + */ + @Override + public boolean waitForChannelsToQuiescent(List channels, long timeout) + { + + while (timeout > 0 && !channelsAreQuiesent(channels)) + { + try + { + Thread.sleep(200); + } + catch (InterruptedException e) + { + logger.error(e, e); + } + timeout -= 200; + } + + return timeout > 0; + } + + private boolean channelsAreQuiesent(List channels) + { + boolean ret = true; + for (Channel channel : channels) + { + ret &= channel.isQuiescent(); + } + return ret; + } + + public boolean moveChannelToAgi(Channel channel) throws PBXException + { + if (!waitForChannelToQuiescent(channel, 3000)) + throw new PBXException("Channel: " + channel + " cannot be transfered as it is still in transition."); + + boolean isInAgi = channel.isInAgi(); + if (!isInAgi) + { + final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + + channel.setCurrentActivityAction(new AgiChannelActivityHold()); + final RedirectAction redirect = new RedirectAction(channel, profile.getManagementContext(), getExtensionAgi(), + 1); + + logger.error("Issuing redirect on channel " + channel + " to move it to the agi"); + + try + { + final ManagerResponse response = sendAction(redirect, 1000); + if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0))//$NON-NLS-1$ + { + int limit = 50; + while (!channel.isInAgi() && limit-- > 0) + { + Thread.sleep(100); + } + isInAgi = channel.isInAgi(); + if (!isInAgi) + { + logger.error("Failed to move channel"); + } + } + + } + catch (final Exception e) + { + logger.error(e, e); + } + + } + return isInAgi; + + } + + public void moveChannelTo(Channel channel, String context, String exten, int prio) + { + + DialPlanExtension ext = this.buildDialPlanExtension(exten); + + channel.setCurrentActivityAction(new AgiChannelActivityHold()); + final RedirectAction redirect = new RedirectAction(channel, context, ext, prio); + + try + { + sendAction(redirect, 1000); + + } + catch (final Exception e) + { + logger.error(e, e); + } + + } + + @Override + public boolean waitForChannelToQuiescent(Channel channel, int timeout) + { + List channels = new LinkedList<>(); + channels.add(channel); + return waitForChannelsToQuiescent(channels, timeout); + } + + public ChannelProxy getProxyById(String id) + { + return liveChannels.findProxyById(id); + } + + public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, AgiChannelActivityHold action, + ActivityCallback iCallback) + { + + final CompletionAdaptor completion = new CompletionAdaptor<>(); + + final DialToAgiActivityImpl dialer = new DialToAgiActivityImpl(endPoint, callerID, false, completion, null, action); + + completion.waitForCompletion(3, TimeUnit.MINUTES); + iCallback.completed(dialer, dialer.isSuccess()); + + return dialer; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java new file mode 100644 index 000000000..3071596cf --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java @@ -0,0 +1,15 @@ +package org.asteriskjava.pbx.internal.core; + +/** + * Used to notify a listener that a Call (CallTracker) has ended. + * + * This generally means the last channel has hungup. + * + * @author bsutton + * + */ +public interface CallEndedListener +{ + public void callEnded(CallTracker listener); + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java new file mode 100644 index 000000000..3b6e7df4b --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java @@ -0,0 +1,210 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.ChannelHangupListener; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ChannelState; + +/** + * This is a fairly simple class which is used by a Peer to track what calls are + * live for the given Peer. + * + * It should be noted that the Peer must keep track of all calls regardless of + * whether they are associated with NJR. The reason for this is that a Peer + * needs to track the status of the associated endpoint so that it can show if a + * handset is on a call. In this way the operator can tell if a person is busy + * even before they call them. + * + * Essentially all this calls does is track the set of channels associated with + * a call. + * + * @author bsutton + * + */ +public class CallTracker implements ChannelHangupListener +{ + private static final Logger logger = Logger.getLogger(CallTracker.class); + + /** + * The list of channels associated with this call. + */ + ArrayList _associatedChannels = new ArrayList<>(); + + /** + * The state of this call. + */ + PeerState _state; + + private CallEndedListener listener; + + CallTracker(Peer peer, Channel initialChannel) + { + this._associatedChannels.add(initialChannel); + initialChannel.addHangupListener(this); + this.listener = peer; + + } + + /** + * Used to merge two calls into a single call. This is required as during a + * masquerade a new channel is created an initially we will create a + * CallTracker for it. When the masquerade event finally turns up we will + * realise it belongs to an existing CallTracker and as such we need to + * merge the two CallTrackers. + * + * @param rhs + */ + void mergeCalls(CallTracker rhs) + { + synchronized (this._associatedChannels) + { + for (Channel channel : rhs._associatedChannels) + this._associatedChannels.add(channel); + // not certain this is necessary but lets just tidy up a bit. + rhs._associatedChannels.clear(); + } + } + + public PeerState getState() + { + return this._state; + } + + /** + * @param s + */ + public void setState(final ChannelState channelState) + { + this._state = PeerState.valueByChannelState(channelState); + } + + public int findChannel(Channel newChannel) + { + int index = -1; + synchronized (this._associatedChannels) + { + + for (int i = 0; i < this._associatedChannels.size(); i++) + { + Channel channel = this._associatedChannels.get(i); + if (channel.isSame(newChannel)) + { + index = i; + break; + } + } + } + + return index; + } + + /** + * Remove a channel from the call. + * + * @param channel + */ + public void remove(Channel channel) + { + synchronized (this._associatedChannels) + { + int index = findChannel(channel); + if (index != -1) + { + if (logger.isDebugEnabled()) + logger.debug("CallTracker removing channel: " + this.toString() + " " + channel.getExtendedChannelName()); //$NON-NLS-1$ //$NON-NLS-2$ + + this._associatedChannels.remove(index); + } + } + + } + + public void startSweep() + { + synchronized (this._associatedChannels) + { + for (final Channel channel : this._associatedChannels) + { + ((ChannelProxy) channel).getRealChannel().startSweep(); + } + } + } + + public void endSweep() + { + final List toremove = new LinkedList<>(); + synchronized (this._associatedChannels) + { + for (final Channel channel : this._associatedChannels) + { + if (!((ChannelProxy) channel).getRealChannel().wasMarkedDuringSweep()) + { + toremove.add(channel); + logger.warn("removing channel " + this.hashCode() + " " + channel.getChannelName());//$NON-NLS-1$ //$NON-NLS-2$ + } + } + + this._associatedChannels.removeAll(toremove); + } + + // Now tell each of the channels it has been hungup + for (final Channel channel : toremove) + { + ((ChannelProxy) channel).getRealChannel().notifyHangupListeners(-1, + "Lingering channel probably due to missed hangup event"); + } + + } + + void dumpChannelList() + { + if (logger.isDebugEnabled()) + { + logger.debug("CallTracker: dump channellist:" + this); //$NON-NLS-1$ + synchronized (this._associatedChannels) + { + for (final Channel channel : this._associatedChannels) + { + logger.debug("--> " + channel.toString()); //$NON-NLS-1$ + } + } + } + } + + public boolean hasEnded() + { + synchronized (this._associatedChannels) + { + return this._associatedChannels.size() == 0; + } + } + + @Override + public void channelHangup(Channel channel, Integer cause, String causeText) + { + remove(channel); + synchronized (this._associatedChannels) + { + if (this._associatedChannels.size() == 0) + { + this._state = PeerState.NOTSET; + notifyCallEndedListener(); + } + } + } + + private void notifyCallEndedListener() + { + this.listener.callEnded(this); + } + + public String toString() + { + return this.listener + " : " + this._state; //$NON-NLS-1$ + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelEventHelper.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelEventHelper.java new file mode 100644 index 000000000..052950fd9 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelEventHelper.java @@ -0,0 +1,59 @@ +package org.asteriskjava.pbx.internal.core; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ChannelEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; + +public abstract class ChannelEventHelper extends ManagerEvent implements ChannelEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(ChannelEventHelper.class); + + /** + * The name of the channel. + */ + private final ChannelProxy channel; + + protected ChannelEventHelper(final org.asteriskjava.manager.event.AbstractChannelEvent event) + throws InvalidChannelName + { + this(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + } + + protected ChannelEventHelper(final String channel, final String uniqueId, final String callerIdNum, + final String callerIdName) throws InvalidChannelName + { + super(channel); // we must have a source but since don't have one pass + // anything. + this.channel = ChannelEventHelper.registerChannel(channel, uniqueId, callerIdNum, callerIdName); + } + + public ChannelEventHelper(final String channel, final String uniqueId) throws InvalidChannelName + { + super(channel);// we must have a source but since don't have one pass + // anything. + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this.channel = pbx.registerChannel(channel, uniqueId); + } + + @Override + public ChannelProxy getChannel() + { + return this.channel; + } + + public static ChannelProxy registerChannel(final String channelName, final String uniqueId, + final String callerIdNum, final String callerIdName) throws InvalidChannelName + { + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + final ChannelProxy channel = pbx.registerChannel(channelName, uniqueId); + channel.getRealChannel().setCallerId(pbx.buildCallerID(callerIdNum, callerIdName)); + return channel; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java new file mode 100644 index 000000000..e70e4ad45 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -0,0 +1,841 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.ChannelFactory; +import org.asteriskjava.pbx.ChannelHangupListener; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; + +/** + * TODO set the channel unique id when registering against an existing channel + * which doesn't have its unique id set. Create a single asterisk event source. + * All users of MyBaseEventCalls will become listeners to this class rather than + * talking to asterisk directly. Each listener will have events queued to it. It + * can process these events in a separate thread. Key feature is that one a + * 'rename' event arrives we must pause all of the queues wait for them to empty + * and for the queue clients to quiescent, then apply the rename before resuming + * pushing data in to the queues. Additionally we need to redo the asterisk + * events classes with our own classes that pass around an iChannel rather than + * a raw channel name. By doing this the rename affectively becomes global + * updating every instance of the channel (because they actually only have an + * instance handle). + * + * @author bsutton + */ +public class ChannelImpl implements Channel +{ + public static final String ZOMBIE = ""; //$NON-NLS-1$ + public static final String MASQ = ""; //$NON-NLS-1$ + + public static final String UNKNOWN_UNIQUE_ID = "-1"; //$NON-NLS-1$ + + private static Logger logger = Logger.getLogger(ChannelImpl.class); + private static int logCounter = 100; + + /** + * The channel name including the tech and the channel sequence number but + * not the masquerade prefix and not the zombie suffix. Forced to upper case + * for comparisons. + */ + private String _channelName; + + /** + * A unique id created by Asterisk to uniquely identify this channel. Often + * a channel can be 're-created' on the fly. In this case the channels name + * will be the same but the unique id will change. + */ + final private String _uniqueID; + /** + * This is an abbreviated form of the channel name obtained by removing + * everything after the '-' in the channel name. + */ + private EndPoint _endPoint; + + /** + * The caller id for this channel. If this is an inbound channel then it the + * callerid received from the remote end. If this is an outbound channel + * then this is the caller id we are to present to the remote end. + */ + private CallerID _callerID; + + /** + * A globally unique id assigned to each channel as it is created + */ + private long _channelId; + + private boolean _muted = false; + + private boolean _parked = false; + + private boolean _isZombie = false; + + /** + * A channel is live if it has not been hungup. + */ + private boolean _isLive = true; + + /** + * Indicates that the channel is being masquerading by another channel. + * Masqueraded channels have an extra suffix after the sequence + * number e.g. SIP/100-000009823 + */ + private boolean _isMasqueraded = false; + + /** + * Indicates that the channel is undergoing an action such as being parked. + * Action channels have an extra prefix before the tech e.g. + * Parked/SIP/100-000009823 + */ + private boolean _isInAction = false; + + /** + * Indicates that the channel has been originated directly from the Asterisk + * console. We can generally ignore these cases. + */ + private boolean _isConsole = false; + + /** + * The prefix added to a channel during some type of action: e.g. + * Parked/SIP/100-0000032323 In this case the prefix is Parked. + */ + private String _actionPrefix = null; + + public static final String[] _actions = new String[]{"PARKED/", "ASYNCGOTO/", "BRIDGE/"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + /** + * There should be only one hangup listener which is the ChannelProxy that + * wraps this channel. + */ + private ChannelHangupListener hangupListener; + + /** + * When validating channels the start time is set in the _sweepStartTime. as + * a channel is validated the _mark field is set to true. if new channels + * are created as the sweep is in progress the _sweepStartTime will not be + * set so they won't be cleaned up. + */ + private Long _sweepStartTime = null; + private boolean _marked = false; + + /** + * Creates a channel from a channelName
+ *
+ * Channel names are one of the following formats: + * [Action/]Tech/EndPointName-[][ ] + * DAHDI/i/[:]-
+ *
+ * Where: [Action/] is an action that is being performed on a channel. e.g. + * Parked Tech is the Tech used to reach the end point.
+ *
+ * The set of supported techs are defined by the enum Tech.
+ *
+ * EndPointName the name of the endpoint.
+ *
+ * '' the optional terminating '' which indicates the channel is + * now being masqueraded. A masqueraded channel is one that has been cloned. + * The original channel is marked as being masqueraded and will hangup + * shortly. It plays no further part in the Call.
+ *
+ * '' the optional terminating '' which indicates the + * channel is now a zombie. A zombie channel is one that has been hungup and + * is awaiting final cleanup. I believe the zombie channel is used by the + * hangup extension 'h' in the dialplan.
+ *
+ * The channel name is stripped of the Action, MASQ and ZOMBIE elements. + * + * @param asteriskStateName + * @throws InvalidChannelName + */ + ChannelImpl(final String channelName, final String uniqueID) throws InvalidChannelName + { + if (uniqueID == null) + throw new IllegalArgumentException("The UniqueID may not be null."); //$NON-NLS-1$ + + if (channelName == null) + throw new IllegalArgumentException("The channelName may not be null."); //$NON-NLS-1$ + + if (uniqueID.compareToIgnoreCase("-1") == 0) + { + logger.info("uniqueID is -1"); + } + + this._uniqueID = uniqueID; + + this.setChannelName(channelName); + + } + + /** + * designed for use by the ChannelProxy when a channel is being cloned as a + * result of Asterisk undertaking an Masquerade. This is not intended to be + * a complete clone just the key elements that we generally track on our + * side rather than getting directly from asterisk. + */ + void masquerade(Channel channel) + { + // If the channel doesn't have a caller id + // preserve the existing one (as given this is a clone they should be + // identical). + // Asterisk doesn't always pass the caller ID on the channel hence this + // protects us from Asterisk accidentally clearing the caller id. + if (channel.hasCallerID()) + { + this._callerID = channel.getCallerID(); + } + else if (this._callerID != null && ((ChannelImpl) channel)._callerID != null) + { + // Force the caller id back into the channel so it has one as well. + PBX pbx = PBXFactory.getActivePBX(); + if (this._callerID != null) + { + ((ChannelImpl) channel)._callerID = pbx.buildCallerID(this._callerID.getNumber(), this._callerID.getName()); + } + } + + this._muted = channel.isMute(); + + this._parked = channel.isParked(); + + // just in case the original channel is part way through a sweep by the + // PeerMonitor + // marking the sweep as true will stop the new clone being hungup as it + // may not have been around when the sweep started. + this._marked = true; + this._sweepStartTime = null; + } + + private void setChannelName(final String channelName) throws InvalidChannelName + { + this._channelName = this.cleanChannelName(channelName); + this.validateChannelName(this._channelName); + + this._channelId = ChannelFactory.getNextChannelId(); + this._endPoint = new EndPointImpl(this.extractPeerName(this._channelName)); + + // After stripping everything from the channel name after the hypen + // we should have the endpoint name which shouldn't match the + // channel name + // unless its a channel caused by a console dial (Console/dsp) which + // we don't really care about. + // If the peer name still matches then we have a malformed channel + // name. + if ((this._channelName.compareTo(this.getEndPoint().getFullyQualifiedName()) == 0) && !this._isConsole) + { + if (ChannelImpl.logCounter > 0) + { + ChannelImpl.logger.warn("Invalid channel name " + this._channelName); //$NON-NLS-1$ + ChannelImpl.logCounter--; + } + else if (ChannelImpl.logCounter == 0) + { + ChannelImpl.logger.warn("Further Invalid channel name warnings suppressed"); //$NON-NLS-1$ + ChannelImpl.logCounter--; + } + } + } + + @Override + public void rename(final String newName) throws InvalidChannelName + { + this.setChannelName(newName); + + } + + /** + * validates the channel name. Validate is to be called after the channel + * has been cleaned. + * + * @param channelName + * @throws InvalidChannelName + */ + private void validateChannelName(final String channelName) throws InvalidChannelName + { + if (!this._isConsole) + { + if (!TechType.hasValidTech(channelName)) + { + throw new InvalidChannelName("Invalid channelName: " + channelName + ". Unknown tech."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check we have the expected hypen + final int hypen = channelName.indexOf("-"); //$NON-NLS-1$ + if (hypen == -1) + { + throw new InvalidChannelName("Invalid channelName: " + channelName + ". Missing hypen."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check we have the expected slash + final int slash = channelName.indexOf("/"); //$NON-NLS-1$ + if (slash == -1) + { + throw new InvalidChannelName("Invalid channelName: " + channelName + ". Missing slash."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check that the hypen is after the slash. + if (hypen < slash) + { + throw new InvalidChannelName("Invalid channelName: " + channelName + ". Hypen must be after the slash."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check that there is at least one characters between the hypen and + // the + // slash + if ((hypen - slash) < 2) + { + throw new InvalidChannelName("Invalid channelName: " + channelName //$NON-NLS-1$ + + ". Must be one character between the hypen and the slash."); //$NON-NLS-1$ + } + + // Check that the channel sequence number is at least 1 character + // long. + if ((channelName.length() - hypen) < 2) + { + throw new InvalidChannelName("Invalid channelName: " + channelName //$NON-NLS-1$ + + ". The channel sequence number must be at least 1 character."); //$NON-NLS-1$ + } + } + + } + + /** + * Cleans up the channel name by applying the following: 1) trim any + * whitespace 2) convert to upper case for easy string comparisions 3) strip + * of the masquerade prefix if it exists and mark the channel as + * masquerading 4) strip the zombie suffix and mark it as being a zombie. + * + * @param name + * @return + */ + private String cleanChannelName(final String name) + { + String cleanedName = name.trim().toUpperCase(); + + // If if the channel is the console + this._isConsole = false; + if (name.compareToIgnoreCase("Console/dsp") == 0) //$NON-NLS-1$ + { + this._isConsole = true; + } + + // Check if the channel is in an action + boolean wasInAction = this._isInAction; + this._isInAction = false; + for (final String prefix : ChannelImpl._actions) + { + if (cleanedName.startsWith(prefix)) + { + this._isInAction = true; + this._actionPrefix = cleanedName.substring(0, prefix.length() - 1); + cleanedName = cleanedName.substring(prefix.length()); + break; + } + } + if (wasInAction != this._isInAction) + { + logger.info("Channel " + this + " : inaction status changed from " + wasInAction + " to " + this._isInAction); + } + + // Channels can be marked as in a zombie state + // so we need to strip of the zombie suffix and just mark the channel + // as a + // zombie. + this._isZombie = false; + if (cleanedName.contains(ChannelImpl.ZOMBIE)) + { + this._isZombie = true; + cleanedName = cleanedName.substring(0, cleanedName.indexOf(ChannelImpl.ZOMBIE)); + } + + // Channels can be marked as in a MASQ state + // This happens during transfers (and other times) when the channel is + // replaced + // by a new channel in the call. The old channel is renamed with the + // word + // added as a suffix. + this._isMasqueraded = false; + if (cleanedName.contains(ChannelImpl.MASQ)) + { + this._isMasqueraded = true; + cleanedName = cleanedName.substring(0, cleanedName.indexOf(ChannelImpl.MASQ)); + } + + return cleanedName; + } + + @Override + public String getChannelName() + { + return this._channelName; + } + + @Override + public EndPoint getEndPoint() + { + return this._endPoint; + } + + /* + * Extracts the peer name from a full channel name. The channel name is + * created by asterisk and consists of the peer name a hypen and a unique + * sequence number. e.g. SIP/100-000000123 * For SIP channels the Peer name + * is of the form: SIP/100 For dahdi channels the channel name is of the + * form: DAHDI/i/[:]-0000000123 With the peer name + * of the form: DAHDI/i/[:] + */ + private final String extractPeerName(final String channelName) + { + // Find the start of the sequence number + int channelNameEndPoint = channelName.lastIndexOf("-"); //$NON-NLS-1$ + if (channelNameEndPoint == -1) + { + channelNameEndPoint = channelName.length(); + } + // return the peer name which is everything before the sequence number + // (and its hypen). + return channelName.substring(0, channelNameEndPoint); + } + + boolean wasMarkedDuringSweep() + { + boolean ret = false; + if ((this._sweepStartTime == null) || (this._marked == true)) + { + this._sweepStartTime = null; + ret = true; + } + return ret; + } + + void setCallerId(final CallerID callerId) + { + this._callerID = callerId; + } + + /** + * Used to start the Mark and Sweep process by setting the marked status to + * false. At the end of the sweep the marked flag should have been set to + * true. If not then this channel has been hungup. + */ + void startSweep() + { + this._sweepStartTime = new Date().getTime(); + this._marked = false; + } + + /** + * The channel was found to be active on asterisk so it is still alive. + */ + void markChannel() + { + this._marked = true; + + } + + /** + * ************************************************************************* + * ************************** The remaining methods are bridging methods to + * the new abstract PBX classes. + * ************************************************************************* + * ************************** + */ + @Override + public boolean isSame(final Channel _rhs) + { + boolean equals = false; + + if (_rhs == null) + { + logger.warn("isSame called with null"); + return false; + } + ChannelImpl rhs; + if (_rhs instanceof ChannelImpl) + { + rhs = (ChannelImpl) _rhs; + } + else + { + rhs = ((ChannelProxy) _rhs).getRealChannel(); + } + // If we have unique id's for both channels then we can compare the id's + // directly. + if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) + && (rhs._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) + { + if (this._uniqueID.compareToIgnoreCase(rhs._uniqueID) == 0) + { + equals = true; + } + } + else + { + boolean ok = (this._channelName != null) && (rhs._channelName != null); + final boolean namesMatch = (ok && (this._channelName.compareToIgnoreCase(rhs._channelName) == 0)); + + if (namesMatch) + { + // check if the actions match + if (this._isInAction != rhs._isInAction) + { + ok = false; + } + else if (this._isInAction) + { + ok = this._actionPrefix.compareTo(rhs._actionPrefix) == 0; + } + } + + if (ok && namesMatch) + { + // check if the zombie match + if (this._isZombie != rhs._isZombie) + { + ok = false; + } + } + + if (ok && namesMatch) + { + // check if the masquerade match + if (this._isMasqueraded != rhs._isMasqueraded) + { + ok = false; + } + } + + equals = ok & namesMatch; + } + return equals; + } + + @Override + public boolean isSame(final String extendedChannelName, final String uniqueID) + { + boolean equals = false; + if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) + && (uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) + { + if (this._uniqueID.compareTo(uniqueID) == 0) + { + equals = true; + } + } + else + { + equals = this.sameExtenededChannelName(extendedChannelName); + } + + return equals; + } + + @Override + public boolean sameExtenededChannelName(final String extendedChannelName) + { + boolean ok = (this.getExtendedChannelName() != null) && (extendedChannelName != null); + + return ok && (this.getExtendedChannelName().compareToIgnoreCase(extendedChannelName) == 0); + } + + /** + * Try to match a channel based solely on its unique ID + * + * @param uniqueID + * @return + */ + boolean sameUniqueID(String uniqueID) + { + boolean equals = false; + if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) + && (uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) + { + if (this._uniqueID.compareTo(uniqueID) == 0) + { + equals = true; + } + } + + return equals; + } + + @Override + public boolean sameEndPoint(final Channel rhs) + { + return this.sameEndPoint(rhs.getEndPoint()); + } + + @Override + public boolean sameEndPoint(final EndPoint rhs) + { + boolean ok = (this._endPoint != null) && (rhs != null); + return ok && this._endPoint.isSame(rhs); + } + + @Override + public long getChannelId() + { + return this._channelId; + } + + @Override + public boolean isLive() + { + return this._isLive; + } + + @Override + public void addHangupListener(final ChannelHangupListener listener) + { + if (this.hangupListener != null) + throw new IllegalStateException("This channel may only have ONE listener which should be its ChannelProxy"); //$NON-NLS-1$ + + this.hangupListener = listener; + } + + @Override + public void removeListener(final ChannelHangupListener listener) + { + + if (this.hangupListener != listener) + throw new IllegalStateException("An invalid attempt was made to remove a non-existant listener."); //$NON-NLS-1$ + + this.hangupListener = null; + + } + + /** + * Called by Peer when we have been hungup. This can happen when Peer + * receives a HangupEvent or during a periodic sweep done by PeerMonitor to + * find the status of all channels. Notify any listeners that this channel + * has been hung up. + */ + @Override + public void notifyHangupListeners(Integer cause, String causeText) + { + this._isLive = false; + if (this.hangupListener != null) + { + this.hangupListener.channelHangup(this, cause, causeText); + } + else + { + logger.warn("Hangup listener is null"); + } + } + + @Override + public boolean isConnectedTo(final EndPoint endPoint) + { + return this._endPoint.isSame(endPoint); + } + + @Override + public boolean isMute() + { + return this._muted; + } + + @Override + public void setMute(final boolean mutedState) + { + this._muted = mutedState; + } + + @Override + public void setParked(final boolean parked) + { + this._parked = parked; + + } + + @Override + public boolean isParked() + { + return this._parked; + } + + @Override + public String toString() + { + return this.getExtendedChannelName() + ":" + this._uniqueID; //$NON-NLS-1$ + } + + /** + * Returns the full channel name including the masquerade prefix and the + * zombie suffix. + * + * @return + */ + @Override + public String getExtendedChannelName() + { + final StringBuilder name = new StringBuilder(); + + if (this._isInAction) + { + name.append(this._actionPrefix); + name.append("/"); //$NON-NLS-1$ + } + name.append(this._channelName); + + if (this._isMasqueraded) + { + name.append(ChannelImpl.MASQ); + } + + if (this._isZombie) + { + name.append(ChannelImpl.ZOMBIE); + } + + return name.toString(); + + } + + @Override + public boolean isLocal() + { + return this._endPoint.isLocal(); + } + + @Override + public boolean isZombie() + { + return this._isZombie; + } + + @Override + public boolean isConsole() + { + return this._isConsole; + } + + TechType getTech() + { + return this._endPoint.getTech(); + } + + /** + * Returns the actionPrefix for the channel or an empty string if the + * channel is not doing an action. + * + * @return + */ + String getActionPrefix() + { + return this._isInAction ? this._actionPrefix : ""; //$NON-NLS-1$ + } + + boolean isInAction() + { + return this._isInAction; + } + + boolean isMasqueraded() + { + return this._isMasqueraded; + } + + @Override + public boolean hasCallerID() + { + return this._callerID != null && !this._callerID.isUnknown(); + } + + @Override + public CallerID getCallerID() + { + if (this._callerID == null) + { + final CoherentManagerConnection smc = CoherentManagerConnection.getInstance(); + final String number = smc.getVariable(this, "CALLERID(number)"); //$NON-NLS-1$ + final String name = smc.getVariable(this, "CALLERID(name)"); //$NON-NLS-1$ + final PBX pbx = PBXFactory.getActivePBX(); + this._callerID = pbx.buildCallerID(number, name); + } + + return this._callerID; + + } + + @Override + public String getUniqueId() + { + return this._uniqueID; + } + + /* + * Returns true if this channel can detect hangups A SIP channel can always + * detect a hangup if its not channel then we need to check the profile to + * see if hangup detection is available. Hangup detection is important as we + * don't want to connect two channels both of which can't do hangup + * detection. If this happened then we would end up with a call which would + * never hangup. + */ + @Override + public boolean canDetectHangup() + { + boolean canDetectHangup = true; + + AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + final boolean detect = profile.getCanDetectHangup(); + if (!this.getEndPoint().isSIP() && !detect) + { + canDetectHangup = false; + } + return canDetectHangup; + } + + /** + * Returns true if the channel is quiescent. A quescent channel is one that + * is current not going through a transition (name change) such as MASQ, + * ZOMBIE, ASYNC, PARK + * + * @return + */ + @Override + public boolean isQuiescent() + { + return !(_isInAction || _isMasqueraded || _isZombie); + } + + @Override + public AgiChannelActivityAction getCurrentActivityAction() + { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public void setCurrentActivityAction(AgiChannelActivityAction action) + { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public void setIsInAgi(boolean b) + { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public boolean isInAgi() + { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException + { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java new file mode 100644 index 000000000..c547d0dc2 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -0,0 +1,389 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.ChannelHangupListener; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHold; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; + +/** + * The ChannelProxy exists to deal with the fact that Asterisk will often + * replace a channel during a call. This is referred to as Masquerading. When a + * channel is to be Masqueraded we get a Masquerade event. The ChannelProxy + * class acts as a level of indirection for an iChannel. Rather than holding an + * iChannel directly you can instead hold a ChannelProxy. If the underlying + * iChannel is replaced the ChannelProxy will be updated with the new iChannel. + * + * @author bsutton + */ +public class ChannelProxy implements Channel, ChannelHangupListener +{ + + private static final Logger logger = Logger.getLogger(ChannelProxy.class); + + /** + * We give each proxy a unique identity to help track them when debugging. + */ + private static final AtomicInteger _nextIdentity = new AtomicInteger(); + + private int _identity = _nextIdentity.incrementAndGet(); + + private ChannelImpl _channel; + + private List listeners = new CopyOnWriteArrayList<>(); + + public ChannelProxy(ChannelImpl channel) + { + this._channel = channel; + currentActivityAction.set(new AgiChannelActivityHold()); + + channel.addHangupListener(this); + + } + + /** + * returns the current channel + * + * @return + */ + public Channel getChannel() + { + return this._channel; + } + + @Override + public boolean isSame(Channel rhs) + { + return this._channel.isSame(rhs); + } + + @Override + public boolean isSame(String extendedChannelName, String uniqueID) + { + return this._channel.isSame(extendedChannelName, uniqueID); + } + + public boolean sameUniqueID(String uniqueID) + { + return this._channel.sameUniqueID(uniqueID); + } + + @Override + public boolean sameEndPoint(Channel rhs) + { + return this._channel.sameEndPoint(rhs); + } + + @Override + public boolean sameEndPoint(EndPoint extensionRoaming) + { + return this._channel.sameEndPoint(extensionRoaming); + } + + @Override + public boolean sameExtenededChannelName(String channelName) + { + return this._channel.sameExtenededChannelName(channelName); + } + + @Override + public void setParked(boolean parked) + { + this._channel.setParked(parked); + } + + @Override + public void setMute(boolean muteState) + { + this._channel.setMute(muteState); + + } + + @Override + public long getChannelId() + { + return this._channel.getChannelId(); + } + + @Override + public boolean isLive() + { + return this._channel.isLive(); + } + + @Override + public void addHangupListener(ChannelHangupListener listener) + { + this.listeners.add(listener); + + } + + @Override + public void removeListener(ChannelHangupListener listener) + { + this.listeners.remove(listener); + + } + + @Override + public boolean isConnectedTo(EndPoint endPoint) + { + return this._channel.isConnectedTo(endPoint); + } + + @Override + public String getChannelName() + { + return this._channel.getChannelName(); + } + + @Override + public EndPoint getEndPoint() + { + return this._channel.getEndPoint(); + } + + @Override + public boolean isMute() + { + return this._channel.isMute(); + } + + @Override + public boolean isLocal() + { + return this._channel.isLocal(); + } + + @Override + public boolean isZombie() + { + return this._channel.isZombie(); + } + + @Override + public boolean isConsole() + { + return this._channel.isConsole(); + } + + @Override + public CallerID getCallerID() + { + return this._channel.getCallerID(); + } + + @Override + public void rename(String newName) throws InvalidChannelName + { + this._channel.rename(newName); + } + + @Override + public boolean isParked() + { + return this._channel.isParked(); + } + + /** + * Used to handle a MasqueradeEvent. We essentially swap the two underlying + * channels between the two proxies. + * + * @param cloneProxy + * @throws InvalidChannelName + */ + public void masquerade(ChannelProxy cloneProxy) throws InvalidChannelName + { + ChannelImpl originalChannel = this._channel; + ChannelImpl cloneChannel = cloneProxy._channel; + + cloneChannel.masquerade(this._channel); + + // detach the hangup listeners + originalChannel.removeListener(this); + cloneChannel.removeListener(cloneProxy); + + // Now we swap the channels. + this._channel = cloneChannel; + cloneProxy._channel = originalChannel; + + // Now re-attach the hangup listeners + this._channel.addHangupListener(this); + cloneProxy._channel.addHangupListener(cloneProxy); + + logger.info("Channel proxy now points to " + this._channel); + } + + public ChannelImpl getRealChannel() + { + return this._channel; + } + + @Override + public String getExtendedChannelName() + { + return this._channel.getExtendedChannelName(); + } + + @Override + public void notifyHangupListeners(Integer cause, String causeText) + { + for (ChannelHangupListener listener : this.listeners) + { + listener.channelHangup(this, cause, causeText); + } + + } + + @Override + public String toString() + { + return "(proxy=" + this._identity + ") " + this._channel.toString(); //$NON-NLS-1$ //$NON-NLS-2$ + } + + @Override + public void channelHangup(Channel channel, Integer cause, String causeText) + { + // When the underlying channel hangs up we need to notify all of the + // proxy listeners. + if (channel == this._channel) + notifyHangupListeners(cause, causeText); + + } + + @Override + public boolean canDetectHangup() + { + return this._channel.canDetectHangup(); + } + + @Override + public boolean isQuiescent() + { + return this._channel.isQuiescent(); + } + + @Override + public boolean hasCallerID() + { + return this._channel.hasCallerID(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + _identity; + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof ChannelProxy)) + { + return false; + } + ChannelProxy other = (ChannelProxy) obj; + if (_identity != other._identity) + { + return false; + } + return true; + } + + private AtomicReference currentActivityAction = new AtomicReference<>(); + volatile private boolean isInAgi; + + @Override + public AgiChannelActivityAction getCurrentActivityAction() + { + return currentActivityAction.get(); + } + + @Override + public void setCurrentActivityAction(AgiChannelActivityAction action) + { + AgiChannelActivityAction previousAction = currentActivityAction.get(); + + logger.info("Setting action to " + action.getClass().getSimpleName() + " for " + this); + + // Exception e = new Exception("Setting action to " + + // action.getClass().getSimpleName() + " for " + this); + // logger.warn(e, e); + + currentActivityAction.set(action); + if (previousAction != null) + { + // when we cancel the previous action, the new one will be invoked + previousAction.cancel(this); + } + } + + @Override + public void setIsInAgi(boolean b) + { + if (b) + { + hasReachedAgi.countDown(); + } + isInAgi = b; + logger.info("Setting is in agi to " + b + " for channel " + this); + + } + + @Override + public boolean isInAgi() + { + return isInAgi; + } + + final CountDownLatch hasReachedAgi = new CountDownLatch(1); + + @Override + public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException + { + return hasReachedAgi.await(timeout, timeunit); + } + + @Override + public String getUniqueId() + { + return _channel.getUniqueId(); + } + + public int getIdentity() + { + return _identity; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java new file mode 100644 index 000000000..6050bd66e --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java @@ -0,0 +1,261 @@ +package org.asteriskjava.pbx.internal.core; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Hashtable; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ManagerAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.AgentCalledEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.AgentConnectEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ConfbridgeListCompleteEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ConfbridgeListEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ConnectEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.DialEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.DisconnectEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.DndStateEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ExtensionStatusEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.LinkEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.MasqueradeEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.MeetMeJoinEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.MeetMeLeaveEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewChannelEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewStateEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.OriginateResponseEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ParkedCallEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerEntryEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerStatusEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerlistCompleteEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.QueueCallerLeaveEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.RenameEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ResponseEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusCompleteEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.UnparkedCallEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.VarSetEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.CommandResponse; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerError; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; + +/** + * This class maps asterisk-java events to our internal events that use iChannel + * rather than raw channel names. + * + * @author bsutton + */ +@SuppressWarnings("deprecation") +public class CoherentEventFactory +{ + private static final Logger logger = Logger.getLogger(CoherentEventFactory.class); + + // Events + static Hashtable, Class< ? extends ManagerEvent>> mapEvents = new Hashtable<>(); + + // Response + static Hashtable, Class< ? extends ResponseEvent>> mapResponses = new Hashtable<>(); + + // Actions + // static Hashtable, Class> mapActions = new + // Hashtable<>(); + + // static initialiser + static + { + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.AgentCalledEvent.class, AgentCalledEvent.class); + + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.AgentConnectEvent.class, AgentConnectEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.QueueCallerLeaveEvent.class, + QueueCallerLeaveEvent.class); + + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.BridgeEvent.class, BridgeEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ConnectEvent.class, ConnectEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.DialEvent.class, DialEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.DisconnectEvent.class, DisconnectEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.DndStateEvent.class, DndStateEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ExtensionStatusEvent.class, + ExtensionStatusEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.HangupEvent.class, HangupEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.LinkEvent.class, LinkEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.MasqueradeEvent.class, MasqueradeEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.MeetMeJoinEvent.class, MeetMeJoinEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.MeetMeLeaveEvent.class, MeetMeLeaveEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.NewChannelEvent.class, NewChannelEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.NewStateEvent.class, NewStateEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ParkedCallEvent.class, ParkedCallEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.PeerStatusEvent.class, PeerStatusEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.RenameEvent.class, RenameEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ResponseEvent.class, ResponseEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.UnlinkEvent.class, UnlinkEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.UnparkedCallEvent.class, UnparkedCallEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.VarSetEvent.class, VarSetEvent.class); + + // response events + CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.OriginateResponseEvent.class, + OriginateResponseEvent.class); + CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.PeerEntryEvent.class, PeerEntryEvent.class); + CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.PeerlistCompleteEvent.class, + PeerlistCompleteEvent.class); + CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.ResponseEvent.class, ResponseEvent.class); + CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.StatusCompleteEvent.class, + StatusCompleteEvent.class); + CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.StatusEvent.class, StatusEvent.class); + + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ConfbridgeListEvent.class, + ConfbridgeListEvent.class); + CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ConfbridgeListCompleteEvent.class, + ConfbridgeListCompleteEvent.class); + + // Actions + // CoherentEventFactory.mapActions.put( BridgeAction.class, + // org.asteriskjava.manager.action.BridgeAction.class); + // CoherentEventFactory.mapActions.put( CommandAction.class, + // org.asteriskjava.manager.action.CommandAction.class); + // CoherentEventFactory.mapActions.put( DbGetAction.class, + // org.asteriskjava.manager.action.DbGetAction.class); + // CoherentEventFactory.mapActions.put( GetVarAction.class, + // org.asteriskjava.manager.action.GetVarAction.class); + // CoherentEventFactory.mapActions.put( HangupAction.class, + // org.asteriskjava.manager.action.HangupAction.class); + // CoherentEventFactory.mapActions.put( ListCommandsAction.class, + // org.asteriskjava.manager.action.ListCommandsAction.class); + // CoherentEventFactory.mapActions.put( MonitorAction.class, + // org.asteriskjava.manager.action.MonitorAction.class); + // CoherentEventFactory.mapActions.put( MuteAudioAction.class, + // org.asteriskjava.manager.action.MuteAudioAction.class); + // CoherentEventFactory.mapActions.put( OriginateAction.class, + // org.asteriskjava.manager.action.OriginateAction.class); + // CoherentEventFactory.mapActions.put( PingAction.class, + // org.asteriskjava.manager.action.PingAction.class); + // CoherentEventFactory.mapActions.put( PlayDtmfAction.class, + // org.asteriskjava.manager.action.PlayDtmfAction.class); + // CoherentEventFactory.mapActions.put( RedirectAction.class, + // org.asteriskjava.manager.action.RedirectAction.class); + // CoherentEventFactory.mapActions.put( SetVarAction.class, + // org.asteriskjava.manager.action.SetVarAction.class); + // CoherentEventFactory.mapActions.put( SipPeersAction.class, + // org.asteriskjava.manager.action.SipPeersAction.class); + // CoherentEventFactory.mapActions.put( SipShowPeerAction.class, + // org.asteriskjava.manager.action.SipShowPeerAction.class); + // CoherentEventFactory.mapActions.put( StatusAction.class, + // org.asteriskjava.manager.action.StatusAction.class); + // CoherentEventFactory.mapActions.put( UpdateConfigAction.class, + // org.asteriskjava.manager.action.UpdateConfigAction.class); + + } + + public static Class< ? extends ManagerEvent> getShadowEvent(org.asteriskjava.manager.event.ManagerEvent event) + { + Class< ? extends ManagerEvent> result = CoherentEventFactory.mapEvents.get(event.getClass()); + if (result == null) + { + Class< ? extends ResponseEvent> response = CoherentEventFactory.mapResponses.get(event.getClass()); + result = response; + } + + return result; + + } + + public static ManagerEvent build(final org.asteriskjava.manager.event.ManagerEvent event) + { + ManagerEvent iEvent = null; + + Class< ? extends ManagerEvent> target = null; + + if (event instanceof org.asteriskjava.manager.event.ResponseEvent) + target = CoherentEventFactory.mapResponses.get(event.getClass()); + else + target = CoherentEventFactory.mapEvents.get(event.getClass()); + + if (target == null) + { + logger.warn("The given event " + event.getClass().getName() + " is not supported "); //$NON-NLS-1$ //$NON-NLS-2$ + } + else + { + + try + { + iEvent = target.getDeclaredConstructor(event.getClass()).newInstance(event); + } + catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) + { + CoherentEventFactory.logger.error(e, e); + + } + } + return iEvent; + } + + public static ResponseEvent build(org.asteriskjava.manager.event.ResponseEvent event) + { + ResponseEvent response = null; + + final Class< ? extends ResponseEvent> target = CoherentEventFactory.mapResponses.get(event.getClass()); + + if (target == null) + { + logger.warn("The given event " + event.getClass().getName() + " is not supported "); //$NON-NLS-1$ //$NON-NLS-2$ + } + else + { + + try + { + final Constructor< ? extends ResponseEvent> declaredConstructor = target + .getDeclaredConstructor(event.getClass()); + response = declaredConstructor.newInstance(event); + } + catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) + { + CoherentEventFactory.logger.error(e, e); + + } + } + return response; + } + + public static ManagerResponse build(org.asteriskjava.manager.response.ManagerResponse response) + { + ManagerResponse result; + if (response instanceof org.asteriskjava.manager.response.CommandResponse) + result = new CommandResponse((org.asteriskjava.manager.response.CommandResponse) response); + else if (response instanceof org.asteriskjava.manager.response.ManagerError) + result = new ManagerError((org.asteriskjava.manager.response.ManagerError) response); + else + result = new ManagerResponse(response); + return result; + + } + + public static org.asteriskjava.manager.action.ManagerAction build(ManagerAction action) + { + org.asteriskjava.manager.action.ManagerAction result = null; + + // final Class + // target = CoherentEventFactory.mapActions.get(action.getClass()); + + if (logger.isDebugEnabled()) + logger.debug("Action " + action); //$NON-NLS-1$ + + // if (target == null) + // { + // logger.warn("The given action " + action.getClass().getName() + " is + // not supported "); //$NON-NLS-1$ //$NON-NLS-2$ + // } + // else + { + result = action.getAJAction(); + } + return result; + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java new file mode 100644 index 000000000..6651c19ff --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -0,0 +1,631 @@ +package org.asteriskjava.pbx.internal.core; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.naming.OperationNotSupportedException; + +import org.apache.log4j.Logger; +import org.asteriskjava.AsteriskVersion; +import org.asteriskjava.manager.AuthenticationFailedException; +import org.asteriskjava.manager.EventTimeoutException; +import org.asteriskjava.manager.ManagerConnection; +import org.asteriskjava.manager.ManagerConnectionState; +import org.asteriskjava.manager.TimeoutException; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.EventGeneratingAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.GetVarAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ListCommandsAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ManagerAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SetVarAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ConnectEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.DisconnectEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ResponseEvents; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.internal.managerAPI.Connector; + +/** + * This is a wrapper class for the asterisk manager.
+ *
+ * It handles the hot swap of an asterisk server and distributes events to event + * listeners.
+ *
+ * The CoherentManagerConnection should be used whenever manager events need to + * be received either for short or extended periods of time.
+ *
+ * The CoherentManagerConnection uses the ManagerEventQueue to queue events to + * each listener.
+ *
+ * The ManagerEventQueue dispatches the events to the set of listeners using a + * separate thread (shared by all of the listeners).
+ *
+ * This means that we are always responsive to asterisk when receiving events, + * if we are not responsive then asterisk will drop the connection.
+ *
+ * It should be noted that as all events are dispatch from a single thread that + * a single tardy listener can block all other listeners.
+ *
+ * If your listener is likely to be slow in handling events then you should wrap + * the listener in its own ManagerEventQueue.
+ *
+ * It is critical that you use the ManagerEventQueue is it forms an intrinsic + * part of this classes ability to ensure that channel/event processing is + * coherent.
+ *
+ * For connections that generate large number of events you should use + * + * @see org.asteriskjava.pbx.internal.core.CoherentManagerEventQueue Note: + * events for any action are distributed to all listeners! + */ +class CoherentManagerConnection implements FilteredManagerListener +{ + + static private Logger logger = Logger.getLogger(CoherentManagerConnection.class); + + static Map eventStatistics = new HashMap<>(); + + /** + * Used to instantiate the manager connection including the initial login. + */ + static Connector connector = null; + + /** + * The actual manager connection. AJ actually maintains two socket + * connections one for reading events and the other writing events. + */ + static ManagerConnection managerConnection = null; + + /** + * We operate two separate event queues each of which dispatches events via + * its own thread. All ListenerPriority.REALTIME events are dispatch via the + * realtime queue. REALTIME events cannot rely on the LiveChannelManager as + * it will may have been updated (renames, masquerades) when the realtime + * listener processes its event. + */ + private CoherentManagerEventQueue eventQueue; + + private CoherentManagerEventQueue realtimeEventQueue; + + // private List> realtimeListeners = + // new CopyOnWriteArrayList<>(); + + // True if the AMI function 'Bridge' is available. + private boolean canBridge; + + // True if the AMI function 'MuteAudio' is available. + private boolean canMuteAudio; + + private static CoherentManagerConnection self = null; + + // latch used for reconnections. + // We create an initial latch incase we get connect before we are really + // ready to wait for one. + private CountDownLatch _reconnectLatch = new CountDownLatch(0); + + public static synchronized void init() + throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException + { + if (self != null) + logger.warn("The CoherentManagerConnection has already been initialised"); //$NON-NLS-1$ + else + { + self = new CoherentManagerConnection(); + self.checkFeatures(); + } + + self.checkConnection(); + } + + public static void reset() + { + self = null; + } + + public static synchronized CoherentManagerConnection getInstance() + { + if (self == null) + throw new IllegalStateException("The CoherentManagerConnection has not been initialised"); //$NON-NLS-1$ + + self.checkConnection(); + + return self; + } + + private CoherentManagerConnection() + throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException + { + super(); + connector = new Connector(); + this.configureConnection(); + } + + public AsteriskVersion getVersion() throws IllegalStateException + { + return CoherentManagerConnection.managerConnection.getVersion(); + } + + public void setVariable(final Channel channel, final String variableName, final String value) throws PBXException + { + try + { + /* + * Sets the specified variable on the specified channel to the + * specified value. + */ + final SetVarAction setVariable = new SetVarAction(channel, variableName, value); + ManagerResponse response; + + PBX pbx = PBXFactory.getActivePBX(); + if (!pbx.waitForChannelToQuiescent(channel, 3000)) + throw new PBXException("Channel: " + channel + " cannot be retrieved as it is still in transition."); + + response = sendAction(setVariable, 500); + if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0)) //$NON-NLS-1$ + { + // $NON-NLS-1$ + + CoherentManagerConnection.logger.debug("set variable " + variableName + " to " + value //$NON-NLS-1$ //$NON-NLS-2$ + + " on " + channel); //$NON-NLS-1$ + } + else + { + throw new PBXException("failed to set variable '" + variableName + "' on channel " + channel + " to '" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + value + "'" + (response != null ? " Error:" + response.getMessage() : "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } + catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) + { + logger.error(e, e); + throw new PBXException(e); + + } + + } + + /** + * Retrieves and returns the value of a variable associated with a channel. + * If the variable is empty or null then an empty string is returned. + * + * @param channel + * @param variableName + * @return + */ + public String getVariable(final Channel channel, final String variableName) + { + String value = ""; + final GetVarAction var = new GetVarAction(channel, variableName); + + try + { + PBX pbx = PBXFactory.getActivePBX(); + if (!pbx.waitForChannelToQuiescent(channel, 3000)) + throw new PBXException("Channel: " + channel + " cannot be retrieved as it is still in transition."); + + ManagerResponse convertedResponse = sendAction(var, 500); + if (convertedResponse != null) + { + value = convertedResponse.getAttribute("value"); //$NON-NLS-1$ + if (value == null) + value = ""; + CoherentManagerConnection.logger.debug("getVarAction returned name:" + variableName + " value:" + value); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + catch (final Exception e) + { + CoherentManagerConnection.logger.debug(e, e); + CoherentManagerConnection.logger.error("getVariable: " + e); //$NON-NLS-1$ + } + return value; + } + + /** + * Allows the caller to send an action to asterisk without waiting for the + * response. You should only use this if you don't care whether the action + * actually succeeds. + * + * @param sa + */ + public static void sendActionNoWait(final ManagerAction action) + { + final Thread background = new Thread() + { + @Override + public void run() + { + try + { + CoherentManagerConnection.sendAction(action, 5000); + } + catch (final Exception e) + { + CoherentManagerConnection.logger.error(e, e); + } + } + }; + background.setName("sendActionNoWait"); //$NON-NLS-1$ + background.setDaemon(true); + background.start(); + } + + public static ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) + throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException + { + org.asteriskjava.manager.ResponseEvents events = CoherentManagerConnection.managerConnection + .sendEventGeneratingAction(action.getAJEventGeneratingAction()); + + ResponseEvents convertedEvents = new ResponseEvents(); + for (org.asteriskjava.manager.event.ResponseEvent event : events.getEvents()) + { + convertedEvents.add(CoherentEventFactory.build(event)); + } + return convertedEvents; + + } + + public static ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, int timeout) + throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException + { + org.asteriskjava.manager.ResponseEvents events = CoherentManagerConnection.managerConnection + .sendEventGeneratingAction(action.getAJEventGeneratingAction(), timeout); + + ResponseEvents convertedEvents = new ResponseEvents(); + for (org.asteriskjava.manager.event.ResponseEvent event : events.getEvents()) + { + convertedEvents.add(CoherentEventFactory.build(event)); + } + return convertedEvents; + + } + + /** + * Sends an Asterisk action and waits for a ManagerRespose. + * + * @param action + * @param timeout timeout in milliseconds + * @return + * @throws IllegalArgumentException + * @throws IllegalStateException + * @throws IOException + * @throws TimeoutException + * @throws OperationNotSupportedException + */ + public static ManagerResponse sendAction(final ManagerAction action, final int timeout) + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException + { + if (logger.isDebugEnabled()) + CoherentManagerConnection.logger.debug("Sending Action: " + action.toString()); //$NON-NLS-1$ + + CoherentManagerConnection.getInstance(); + if ((CoherentManagerConnection.managerConnection != null) + && (CoherentManagerConnection.managerConnection.getState() == ManagerConnectionState.CONNECTED)) + { + final org.asteriskjava.manager.action.ManagerAction ajAction = action.getAJAction(); + + org.asteriskjava.manager.response.ManagerResponse response = CoherentManagerConnection.managerConnection + .sendAction(ajAction, timeout); + ManagerResponse convertedResponse = null; + + // UserEventActions always return a null + if (response != null) + convertedResponse = CoherentEventFactory.build(response); + + if ((convertedResponse != null) && (convertedResponse.getResponse().compareToIgnoreCase("Error") == 0))//$NON-NLS-1$ + { + CoherentManagerConnection.logger.warn("Action '" + ajAction + "' failed, Response: " //$NON-NLS-1$ //$NON-NLS-2$ + + convertedResponse.getResponse() + " Message: " + convertedResponse.getMessage()); //$NON-NLS-1$ + } + return convertedResponse; + } + + throw new IllegalStateException("not connected."); //$NON-NLS-1$ + } + + private void checkConnection() + { + int trys = 3; + + this._reconnectLatch = new CountDownLatch(1); + while ((trys > 0) && ((CoherentManagerConnection.managerConnection == null) + || (CoherentManagerConnection.managerConnection.getState() != ManagerConnectionState.CONNECTED))) + { + if (trys == 3) + { + CoherentManagerConnection.logger.warn("Awaiting Manager connection"); //$NON-NLS-1$ + } + try + { + + this._reconnectLatch.await(300, TimeUnit.MILLISECONDS); + } + catch (final InterruptedException e) + { + CoherentManagerConnection.logger.error(e, e); + } + trys--; + } + } + + public ManagerConnectionState getState() + { + return CoherentManagerConnection.managerConnection.getState(); + } + + private void configureConnection() + throws IOException, AuthenticationFailedException, TimeoutException, IllegalStateException + { + final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + CoherentManagerConnection.managerConnection = CoherentManagerConnection.connector.connect(profile); + + // After a reconnect we will have duplicate eventQueues and + // realtimeEventQueues but + // the original queues will be drained quite quickly (on the small + // chance + // that it hasn't already) + // and should have no duplicate events. Once drained the queue will be + // garbage collected. + CoherentManagerEventQueue newRealtime = new CoherentManagerEventQueue("Realtime"); //$NON-NLS-1$ + if (this.realtimeEventQueue != null) + { + this.realtimeEventQueue.stop(); + newRealtime.transferListeners(this.realtimeEventQueue); + } + this.realtimeEventQueue = newRealtime; + + CoherentManagerEventQueue newStandard = new CoherentManagerEventQueue("Standard"); //$NON-NLS-1$ + if (this.eventQueue != null) + { + this.eventQueue.stop(); + newStandard.transferListeners(this.eventQueue); + } + this.eventQueue = newStandard; + } + + private void checkFeatures() throws IOException, TimeoutException + { + final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + + // Determine if the Bridge and Mute events are available. + final ListCommandsAction lca = new ListCommandsAction(); + ManagerResponse convertedResponse = sendAction(lca, 500); + boolean bridgeFound = false; + boolean muteAudioFound = false; + for (final String command : convertedResponse.getAttributes().keySet()) + { + if (command.toLowerCase().contains("bridge")) //$NON-NLS-1$ + { + bridgeFound = true; + } + if (command.toLowerCase().contains("muteaudio")) //$NON-NLS-1$ + { + muteAudioFound = true; + } + + } + this.canMuteAudio = muteAudioFound; + if (profile.getDisableBridge()) + { + this.canBridge = false; + } + else + { + this.canBridge = bridgeFound; + } + } + + // @SuppressWarnings("unused") + // private boolean ping(final int timeout) + // { + // boolean result = false; + // + // try + // { + // // logger.debug("ping"); + // final PingAction pa = new PingAction(); + // result = true; + // } + // catch (final Exception e) + // { + // // logger.warn("ping failed asterisk connection may have been lost"); + // + // } + // return result; + // + // } + + // // TODO consider putting the ping logic back in. + // // Having said that the ping command doesn't appear to have been working + // for + // // some time + // // as it was always returning true. + // public void run() + // { + // // Establish the initial connection. + // this.connector = new Connector(); + // try + // { + // this.managerListener = this.con.connect(this.profile); + // this.queue = new ManagerEventQueue(this); + // + // this.managerListener.addEventListener(this.queue); + // + // this.managerWriter = this.con.connect(this.profile); + // + // } + // catch (final Exception e) + // { + // logger.error(e, e); + // } + // + // // Monitor the connection by doing an asterisk ping. + // while (this.stop == false) + // { + // if (!this.ping(200)) + // { + // if (!this.ping(90)) + // { + // if (!this.ping(90)) + // { + // logger.error("Asterisk connection lost, attempting reconnect"); + // //$NON-NLS-1$ + // // The ping has failed so we need to force a reconnect. + // this.reconnect(); + // } + // } + // } + // try + // { + // Thread.sleep(500); + // } + // catch (final InterruptedException e) + // { + // CallMarker.logger.error(e, e); + // } + // + // } + // + // } + + private void reconnect() + { + final ManagerConnection oldConnection = CoherentManagerConnection.managerConnection; + try + { + try + { + final InetAddress address = InetAddress.getByName(CoherentManagerConnection.managerConnection.getHostname()); + int counter = 0; + while (!address.isReachable(100)) + { + if (counter % 10 == 0) + CoherentManagerConnection.logger.debug("Testing for host " //$NON-NLS-1$ + + CoherentManagerConnection.managerConnection.getHostname()); + counter++; + } + } + catch (final Exception e2) + { + CoherentManagerConnection.logger.error(e2, e2); + } + try + { + CoherentManagerConnection.logger.debug("reconnecting to asterisk"); //$NON-NLS-1$ + + connector = new Connector(); + this.configureConnection(); + CoherentManagerConnection.logger.debug("asterisk reconnection complete"); //$NON-NLS-1$ + } + catch (final Exception e1) + { + + CoherentManagerConnection.logger.error(e1, e1); + } + } + finally + { + oldConnection.logoff(); + } + } + + public void shutDown() + { + CoherentManagerConnection.managerConnection.removeEventListener(this.eventQueue); + this.eventQueue.stop(); + try + { + CoherentManagerConnection.managerConnection.logoff(); + } + catch (final Exception e) + { + CoherentManagerConnection.logger.debug("Manager logging off"); //$NON-NLS-1$ + CoherentManagerConnection.logger.debug(e, e); + } + } + + public boolean isBridgeSupported() + { + return this.canBridge; + } + + public boolean isMuteAudioSupported() + { + return this.canMuteAudio; + } + + public void removeListener(FilteredManagerListener listener) + { + if (listener.getPriority() == ListenerPriority.REALTIME) + this.realtimeEventQueue.removeListener(listener); + else + this.eventQueue.removeListener(listener); + + } + + public void addListener(FilteredManagerListener listener) + { + if (listener.getPriority() == ListenerPriority.REALTIME) + this.realtimeEventQueue.addListener(listener); + else + this.eventQueue.addListener(listener); + + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + required.add(ConnectEvent.class); + required.add(DisconnectEvent.class); + return required; + } + + @Override + public String getName() + { + return "CoherentManagerConnection"; //$NON-NLS-1$ + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.REALTIME; + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + // Special handler for the connect event in case we are + // wait()ing for + // the connection to complete. This wakes the code up in the shortest + // time possible + // by notifying it of the connection. + if (event instanceof ConnectEvent) + { + logger.warn("****************** Asterisk manager connection acquired **************************"); //$NON-NLS-1$ + this._reconnectLatch.countDown(); + } + else if (event instanceof DisconnectEvent) + { + logger.warn("****************** Asterisk manager connection lost **************************"); //$NON-NLS-1$ + new Thread(new Runnable() + { + public void run() + { + reconnect(); + } + }); + } + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java new file mode 100644 index 000000000..9e97aad94 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java @@ -0,0 +1,16 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.EventListener; + +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; + +public interface CoherentManagerEventListener extends EventListener +{ + /** + * This method is called when an event is received. + * + * @param event + * the event that has been received + */ + void onManagerEvent(ManagerEvent event); +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java new file mode 100644 index 000000000..f36542c76 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -0,0 +1,322 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.asteriskjava.manager.ManagerEventListener; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.eventQueue.EventLifeMonitor; +import org.asteriskjava.pbx.util.LogTime; + +/** + * This class provides a method of accepting, queueing and delivering manager + * events. + * + * Asterisk is very sensitive to delays in receiving events. This class ensures + * that events are received and queued rapidly. A separate thread dequeues them + * and delivers them to the manager listener. + * + * Used this queue as follows: + * + * manager.addEventListener(new CoherentManagerEventQueue(originalListener)); + * + * This affectively daisy changes the originalListener via our queue. + * + * @author bsutton + * + */ +class CoherentManagerEventQueue implements ManagerEventListener, Runnable +{ + static Logger logger = Logger.getLogger(CoherentManagerEventQueue.class); + + private class Listener + { + FilteredManagerListener _listener; + Set> requiredEvents; + + public Listener(FilteredManagerListener listener) + { + this._listener = listener; + this.requiredEvents = listener.requiredEvents(); + } + + @Override + public String toString() + { + return this._listener.getName(); + } + + } + + private final TreeSet listeners = new TreeSet<>(new ListenerPriorityComparator()); + + private boolean _stop = false; + private final Thread _th; + private final BlockingQueue> _eventQueue = new LinkedBlockingQueue<>(); + + private int _queueMaxSize; + + private long _queueSum; + + private long _queueCount; + + private HashSet> globalEvents = new HashSet<>(); + + public CoherentManagerEventQueue(String name) + { + CoherentManagerConnection.managerConnection.addEventListener(this); + + this._th = new Thread(this); + this._th.setName("EventQueue: " + name);//$NON-NLS-1$ + this._th.setDaemon(true); + this._th.start(); + } + + /** + * handles manager events passed to us in our role as a listener. + * + * We queue the event so that it can be read, by the run method of this + * class, and subsequently passed on to the original listener. + */ + @Override + public void onManagerEvent(final org.asteriskjava.manager.event.ManagerEvent event) + { + + // logger.error(event); + boolean wanted = false; + /** + * Dump any events we arn't interested in ASAP to minimise the + * processing overhead of these events. + */ + // Only enqueue the events that are of interest to one of our listeners. + synchronized (this.globalEvents) + { + Class shadowEvent = CoherentEventFactory.getShadowEvent(event); + if (this.globalEvents.contains(shadowEvent)) + { + wanted = true; + } + } + + if (wanted) + { + + // We don't support all events. + this._eventQueue.add(new EventLifeMonitor<>(event)); + final int queueSize = this._eventQueue.size(); + if (this._queueMaxSize < queueSize) + { + this._queueMaxSize = queueSize; + } + this._queueSum += queueSize; + this._queueCount++; + + if (CoherentManagerEventQueue.logger.isDebugEnabled()) + { + if (this._eventQueue.size() > ((this._queueMaxSize + (this._queueSum / this._queueCount)) / 2)) + { + CoherentManagerEventQueue.logger.debug("queue gtr max avg: size=" + queueSize + " max:" //$NON-NLS-1$ //$NON-NLS-2$ + + this._queueMaxSize + " avg:" + (this._queueSum / this._queueCount)); //$NON-NLS-1$ + } + } + } + } + + @Override + public void run() + { + + while (this._stop == false) + { + try + { + final EventLifeMonitor elm = this._eventQueue.poll(2, + TimeUnit.SECONDS); + if (elm != null) + { + // A poison queue event means its time to shutdown. + if (elm.getEvent().getClass() == PoisonQueueEvent.class) + break; + + final ManagerEvent iEvent = CoherentEventFactory.build(elm.getEvent()); + if (iEvent != null) + { + dispatchEvent(iEvent); + elm.assessAge(); + } + } + } + catch (final Exception e) + { + /** + * If an exception is thrown whilst we are shutting down then we + * don't care. If it is thrown when we aren't shutting down then + * we have a problem and we need to log it. + */ + if (this._stop == false) + { + CoherentManagerEventQueue.logger.error(e, e); + } + } + + } + + } + + class PoisonQueueEvent extends org.asteriskjava.manager.event.ManagerEvent + { + private static final long serialVersionUID = 1L; + + public PoisonQueueEvent() + { + super("PoisonQueueEvent"); //$NON-NLS-1$ + } + + } + + public void stop() + { + this._stop = true; + try + { + this._eventQueue + .put(new EventLifeMonitor(new PoisonQueueEvent())); + } + catch (InterruptedException e) + { + logger.error(e, e); + + } + } + + /** + * Events are sent here from the CoherentManagerEventQueue after being + * converted from a ManagerEvent to an ManagerEvent. This method is called + * from a dedicated thread attached to the event queue which it uses for + * dispatching events. + */ + public void dispatchEvent(final ManagerEvent event) + { + if (logger.isDebugEnabled()) + { + logger.debug("dispatch=" + event.toString()); //$NON-NLS-1$ + } + + // take a copy of the listeners so they can be modified whilst we + // iterate over them + // The iteration may call some long running processes. + final TreeSet listenerCopy = new TreeSet<>(new ListenerPriorityComparator()); + synchronized (this.listeners) + { + listenerCopy.addAll(this.listeners); + } + + for (final Listener filter : listenerCopy) + { + if (filter.requiredEvents.contains(event.getClass())) + { + final LogTime time = new LogTime(); + + filter._listener.onManagerEvent(event); + if (time.timeTaken() > 500) + { + logger.warn("ManagerListener :" + filter._listener.getName() //$NON-NLS-1$ + + " is taken too long to process events " + " time taken: " + time.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + } + } + + /** + * Adds a listener which will be sent all events that its filterEvent + * handler will accept. All events are dispatch by way of a shared queue + * which is read via a thread which is shared by all listeners. Whilst poor + * performance of you listener can affect other listeners you can't affect + * the read thread which takes events from asterisk and enqueues them. + * + * @param listener + */ + public void addListener(final FilteredManagerListener listener) + { + synchronized (this.listeners) + { + this.listeners.add(new Listener(listener)); + synchronized (this.globalEvents) + { + this.globalEvents.addAll(listener.requiredEvents()); + } + } + logger.debug("listener added"); //$NON-NLS-1$ + } + + public void removeListener(final FilteredManagerListener melf) + { + synchronized (this.listeners) + { + if (melf != null) + { + for (Listener container : this.listeners) + { + if (container._listener == melf) + { + this.listeners.remove(container); + + // When we remove a listener we must unfortunately + // completely + // recalculate the set of required events. + synchronized (this.globalEvents) + { + this.globalEvents.clear(); + for (Listener readdContainer : this.listeners) + { + this.globalEvents.addAll(readdContainer._listener.requiredEvents()); + } + } + break; + } + } + } + } + } + + final class ListenerPriorityComparator implements Comparator + { + @Override + public int compare(Listener lhs, Listener rhs) + { + + int result = lhs._listener.getPriority().compare(rhs._listener.getPriority()); + + if (result == 0) + result = (lhs._listener.equals(rhs._listener) ? 0 : 1); + + return result; + } + } + + /** + * transfers the listeners from one queue to another. + * + * @param eventQueue + */ + public void transferListeners(CoherentManagerEventQueue eventQueue) + { + synchronized (this.listeners) + { + synchronized (eventQueue.listeners) + { + for (Listener listener : eventQueue.listeners) + { + this.addListener(listener._listener); + } + eventQueue.listeners.clear(); + } + } + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java new file mode 100644 index 000000000..573ec88fb --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -0,0 +1,243 @@ +package org.asteriskjava.pbx.internal.core; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.asteriskjava.manager.TimeoutException; +import org.asteriskjava.pbx.Activity; +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.GetVarAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.OriginateAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewChannelEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.OriginateResponseEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; +import org.asteriskjava.pbx.internal.managerAPI.OriginateBaseClass; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class DialLocalToAgiActivity extends EventListenerBaseClass implements Runnable, Activity +{ + + private EndPoint from; + private CallerID fromCallerID; + private Thread thread; + private final Log logger = LogFactory.getLog(this.getClass()); + private String originateId; + + CountDownLatch latch = new CountDownLatch(1); + private List channels = new LinkedList<>(); + private ActivityCallback callback; + private Map channelVarsToSet; + + public DialLocalToAgiActivity(EndPoint from, CallerID fromCallerID, ActivityCallback callback, + Map channelVarsToSet) + { + super("Dial " + from + " to AGI"); + this.from = from; + this.fromCallerID = fromCallerID; + this.callback = callback; + this.channelVarsToSet = channelVarsToSet; + + this.startListener(PBXFactory.getActivePBX()); + thread = new Thread(this, "Dial " + from + " to AGI"); + thread.start(); + } + // Logger logger = LogManager.getLogger(); + + @Override + public void run() + { + logger.info("*******************************************************************************"); + logger.info("*********** begin dial local to AGI ****************"); + logger.info("*********** " + " ****************"); + logger.info("*******************************************************************************"); + final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + final OriginateAction originate = new OriginateAction(); + originate.setEndPoint(from); + originate.setContext(settings.getManagementContext()); + originate.setExten(pbx.getExtensionAgi()); + originate.setPriority(1); + originate.setCallerId(fromCallerID); + originate.setTimeout(30000); + originateId = originate.getActionId(); + + Map myVars = new HashMap<>(); + + myVars.put("__" + OriginateBaseClass.NJR_ORIGINATE_ID, this.originateId); + if (channelVarsToSet != null) + { + myVars.putAll(channelVarsToSet); + } + + originate.setVariables(myVars); + + try + { + pbx.sendAction(originate, 30000); + latch.await(30, TimeUnit.SECONDS); + callback.completed(this, true); + + } + catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) + { + // TODO Auto-generated catch block + logger.error(e, e); + } + catch (InterruptedException e) + { + // TODO Auto-generated catch block + logger.error(e, e); + } + + } + + public void abort(final String reason) + { + logger.debug("Aborting originate ");//$NON-NLS-1$ + this.close(); + + for (Channel channel : channels) + { + PBX pbx = PBXFactory.getActivePBX(); + try + { + pbx.hangup(channel); + } + catch (IllegalArgumentException | IllegalStateException | PBXException e) + { + logger.error(e, e); + + } + } + latch.countDown(); + + } + + @Override + synchronized public void onManagerEvent(final ManagerEvent event) + { + if (event instanceof HangupEvent) + { + this.close(); + } + if (event instanceof NewChannelEvent) + { + final NewChannelEvent newState = (NewChannelEvent) event; + final Channel channel = newState.getChannel(); + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); + + ManagerResponse response; + try + { + if (channel.isLocal()) + { + int wait = 5; + while (wait > 0) + { + wait--; + response = pbx.sendAction(var, 500); + String channelsOriginateId = response.getAttribute("value"); + if (originateId.equalsIgnoreCase(channelsOriginateId)) + { + logger.info("Found the local channel " + channel); + channels.add(channel); + wait = 0; + if (channels.size() == 2) + { + latch.countDown(); + } + } + else if (channelsOriginateId == null || channelsOriginateId.length() == 0) + + { + Thread.sleep(100); + logger.error("Waiting for variables on " + channel); + } + else + { + logger.error("Didn't match " + channel + " " + channelsOriginateId + "!=" + originateId); + + wait = 0; + } + } + } + } + catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) + { + // TODO Auto-generated catch block + logger.error(e, e); + } + catch (InterruptedException e) + { + // TODO Auto-generated catch block + logger.error(e, e); + } + + } + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + required.add(OriginateResponseEvent.class); + required.add(HangupEvent.class); + required.add(NewChannelEvent.class); + + return required; + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + @Override + public Throwable getLastException() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isSuccess() + { + // TODO Auto-generated method stub + return channels.size() == 2; + } + + public Channel getChannel1() + { + return channels.get(0); + + } + + public Channel getChannel2() + { + return channels.get(1); + + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialPlanExtension.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialPlanExtension.java new file mode 100644 index 000000000..8b3980441 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialPlanExtension.java @@ -0,0 +1,111 @@ +package org.asteriskjava.pbx.internal.core; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.EndPoint; + +/** + * Represents an asterisk dial plan extension such eg. + * + * [njr-operator] njr-inbound,1,xxxxx + * + * In the above example njr-inbound is the dialplan extension. + * + * This class primarily exists to stop common mistakes that can occur if we pass + * this around as a simple string. + * + * @author bsutton + * + */ +public class DialPlanExtension implements EndPoint +{ + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(DialPlanExtension.class); + + // the dial plan extension. + String _extension; + final boolean _empty; + + public DialPlanExtension(String extension) + { + if (extension == null || extension.trim().length() == 0) + { + this._empty = true; + this._extension = ""; + } + else + { + this._extension = extension.trim(); + this._empty = false; + } + } + + @Override + public int compareTo(EndPoint rhs) + { + return this._extension.compareTo(rhs.getSimpleName()); + } + + @Override + public boolean isSame(EndPoint rhs) + { + return this.compareTo(rhs) == 0; + } + + @Override + public boolean isLocal() + { + return false; + } + + @Override + public boolean isSIP() + { + return false; + } + + /** + * The same as getSimpleName as in this case the Tech is really just an + * identifier rather than a legitimate tech that the pbx understands. + */ + @Override + public String getFullyQualifiedName() + { + return this._extension; + } + + @Override + public String getSimpleName() + { + return this._extension; + } + + @Override + public String getSIPSimpleName() + { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isUnknown() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public TechType getTech() + { + return TechType.DIALPLAN; + } + + public String toString() + { + return this._extension; + } + + @Override + public boolean isEmpty() + { + return false; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java new file mode 100644 index 000000000..3bf4b7f2f --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java @@ -0,0 +1,229 @@ +package org.asteriskjava.pbx.internal.core; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.EndPoint; + +public class EndPointImpl implements EndPoint +{ + private static final String DELIMITER = "/"; //$NON-NLS-1$ + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(EndPointImpl.class); + + final private TechType _tech; + + final private String _endPointName; + + final private String _fullyQualifiedName; + + // If true then this is an empty end point e.g. blank name and unknown tech. + final private boolean _empty; + + /** + * Creates a EndPoint from a fully qualified peer name of the form: SIP/NNN + * LOCAL/NNN + * + * TODO: the tech encoding should probably be specific to a particular pbx + * Implementation. + * + * @param fullyQualifiedPeerName + */ + public EndPointImpl(final String fullyQualifiedEndPoint) + { + if (fullyQualifiedEndPoint == null) + { + throw new IllegalArgumentException("The fullyQualifiedEndPoint may not be null"); //$NON-NLS-1$ + } + + final String cleaned = this.clean(fullyQualifiedEndPoint); + this._tech = TechType.getTech(cleaned); + this._endPointName = cleaned.substring(this._tech.name().length() + 1); + + if (this._tech == TechType.DIALPLAN) + { + this._fullyQualifiedName = this._endPointName; + } + else + { + this._fullyQualifiedName = this._tech.name() + EndPointImpl.DELIMITER + this._endPointName; + } + this._empty = false; + } + + /** + * Creates a empty end point. + */ + public EndPointImpl() + { + this._empty = true; + this._tech = TechType.UNKNOWN; + this._endPointName = ""; + this._fullyQualifiedName = ""; + } + + /** + * Creates an EndPoint from from a simple endpoint name and a tech. + * + * @param _tech + * @param peerName + */ + // EndPoint(String endPointName, String tech) + // { + // if (endPointName == null) + // throw new IllegalArgumentException("The endPoint Name may not be null"); + // + // if (tech == null) + // throw new IllegalArgumentException("The endPoint Tehc may not be null"); + // + // String cleaned = clean(endPointName); + // // Tech must be upper case to match the enum but + // // the simple name must be lower case to matcht the context extension + // // names. + // this.tech = Tech.valueOf(tech.toUpperCase()); + // this.endPointName = cleaned; + // } + + public EndPointImpl(final String endPointName, final TechType defaultTech) + { + if (endPointName == null) + { + throw new IllegalArgumentException("The endPointName may not be null"); //$NON-NLS-1$ + } + + final String cleaned = this.clean(endPointName); + + if (cleaned.length() == 0) + { + throw new IllegalArgumentException("The endPointName may not be empty"); //$NON-NLS-1$ + } + + // If tech is unknown then attempt to extract the tech from the + // endPointName. + if (TechType.hasTech(cleaned)) + { + this._tech = TechType.getTech(cleaned); + this._endPointName = cleaned.substring(this._tech.name().length() + 1); + + } + else + { + this._tech = defaultTech; + this._endPointName = cleaned; + } + + if (this._tech == TechType.DIALPLAN) + { + this._fullyQualifiedName = this._endPointName; + } + else + { + this._fullyQualifiedName = this._tech.name() + EndPointImpl.DELIMITER + this._endPointName; + } + this._empty = false; + } + + /** + * Returns the fully qualified endPoint. + */ + @Override + public String getFullyQualifiedName() + { + return this._fullyQualifiedName; + } + + @Override + public boolean isSame(final EndPoint rhs) + { + return this.compareTo(rhs) == 0; + } + + @Override + public int compareTo(EndPoint rhs) + { + return this.getFullyQualifiedName().compareTo(rhs.getFullyQualifiedName()); + } + + @Override + public boolean isLocal() + { + return this._tech == TechType.LOCAL; + } + + /** + * For the purposes of asterisk IAX and SIP are both considered SIP. + */ + @Override + public boolean isSIP() + { + return this._tech == TechType.SIP || this._tech == TechType.IAX || this._tech == TechType.IAX2; + } + + public boolean isDAHDI() + { + return this._tech == TechType.DAHDI; + } + + @Override + public String getSimpleName() + { + return this._endPointName; + } + + @Override + public boolean isUnknown() + { + return this._tech == TechType.UNKNOWN; + } + + /** + * Cleans up an endpoint name by removing all whitespace (including internal + * whitespace) as well as making the string lower case. + * + * @param _endPointName + * @return + */ + private String clean(final String _endPointName) + { + String localTo = _endPointName.trim(); + + // strip all white space from within the name as some source + // pass in a formatted phone number (e.g. 03 8320 8100) + int tmp = localTo.indexOf(" "); //$NON-NLS-1$ + while (tmp != -1) + { + localTo = localTo.substring(0, tmp) + localTo.substring(tmp + 1, localTo.length()); + tmp = localTo.indexOf(" "); //$NON-NLS-1$ + } + return localTo.toLowerCase(); + } + + @Override + public TechType getTech() + { + return this._tech; + } + + @Override + public String toString() + { + return this.getFullyQualifiedName(); + } + + @Override + public String getSIPSimpleName() + { + String name; + + if (isSIP()) + name = getSimpleName(); + else + name = getFullyQualifiedName(); + return name; + } + + public boolean isEmpty() + { + return this._empty; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java new file mode 100644 index 000000000..09afe9b5a --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java @@ -0,0 +1,46 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.Set; + +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; + +/** + * Allows a object to receive Manager event notification which are pre-filtered. + * + * @author bsutton + * + */ +public interface FilteredManagerListener +{ + /** + * Provides a unique name for the listener. + * + * @return a unique name for the listener. + */ + abstract String getName(); + + /** + * Called whenever the listener is first added and any time any listener is + * removed to refresh the list of required events. + * + * @return list of required events. + */ + abstract public Set> requiredEvents(); + + /** + * Called for each manager event that the connection receives for which the + * filterEvent returned true. + * + * @param event + */ + abstract void onManagerEvent(T event); + + /** + * Set the listeners priority. Higher priority listeners have events + * dispatched to them before lower priority listeners. + * + * @return + */ + abstract ListenerPriority getPriority(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerPriority.java b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerPriority.java new file mode 100644 index 000000000..853e39ab5 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerPriority.java @@ -0,0 +1,35 @@ +package org.asteriskjava.pbx.internal.core; + +public enum ListenerPriority +{ + /** + * Provide access to events in near real time for specialised services that + * need priority access to events. Realtime events are sent before any other + * listeners get a chance to process the events. With the event dispatcher + * running in its own thread. This means that they are passed without delay. + * You must also ensure that you don't delay the processing of these + * messages as there may be real time event listeners. If you are concerned + * that you are going to delay the processing then you need to add in your + * own ManagerEventQueue to insulate other priority listeners from your + * tardiness. NOTE: you cannot rely on the LiveChannelManager as it + * processes events from the standard event queue. This means that Rename + * and Masquerade events MAY (very likely) not have been process when the + * realtime listener recieves an event. + */ + + REALTIME(100), CRITICAL(10), HIGH(8), NORMAL(6), LOW(4); + + // The priority of the listeners. Higher priority listeners receive + // events first. + private int _priority; + + ListenerPriority(int priority) + { + this._priority = priority; + } + + public int compare(ListenerPriority rhs) + { + return rhs._priority - this._priority; + } +} \ No newline at end of file diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java new file mode 100644 index 000000000..0e323b8ca --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -0,0 +1,311 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.MasqueradeEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.RenameEvent; + +/** + * The LiveChannelManager keeps a list of all of the live channels present on an + * asterisk system. For this to work it needs to control the stream of asterisk + * events consumed by others. This need is caused by the fact that Asterisk can + * rename a channel many times after its comes up. When a channel is renamed + * Asterisk sends a rename event. After the rename event all future asterisk + * events will refer to the channel by its new name. Masquerade events pose + * further issues in that a channel can be replaced mid way through a call. The + * LiveChannelManager works with the ChannelProxy to manage this process. The + * issue is that if multiple classes are accessing the LiveChannelManager and + * those classes are consuming asterisk events form their own direct source then + * they may be behind or ahead of the LiveChannelManager in processing events. + * The result is that when attempting to access a channel by name from the + * LiveChannelManager the channel name may not match as the LiveChannelManager + * may have processed a rename event whilst the consumer may still be processing + * older events which are still referring to the channel via its old name. The + * first part of the solution is to wrap the asterisk-java events with our own + * events which pass an iChannel interface rather than a raw channel name. + * Because the iChannel interface is a handle to a channel managed via the + * LiveChannelManager then the name will be updated during the rename. To ensure + * that events are processed in an orderly fashion you MUST only obtain an event + * listener via AsteriskPBX.addListener(); The second part of the solution is + * the ChannelProxy. The ChannelProxy handles masquerading of channels where in + * a live channel is replaced with a new channel part way through a call. This + * can happen when transfering a call, parking a call or other similar actions. + * The ChannelProxy implements the iChannel interface and is affectively hidden + * from consumers of iChannels. The LiveChannelManager uses the proxy to replace + * a live channel during a masqurade event. A consumer holding an iChannel + * handle will not even be aware (and does not need to be) that the underlying + * channel has been replaced. + * + * @author bsutton + */ +public class LiveChannelManager implements FilteredManagerListener +{ + private static final Logger logger = Logger.getLogger(LiveChannelManager.class); + + /** + * A collection of all of the live proxies in the system. We monitor the + * channels and remove them as they hangup. The hash is keyed by the + * channel's name. e.g. SIP/100-000000100 + */ + private final List _liveChannels = new CopyOnWriteArrayList<>(); + + public LiveChannelManager() + { + CoherentManagerConnection.getInstance().addListener(this); + } + + public ChannelProxy getChannelByEndPoint(EndPoint endPoint) + { + ChannelProxy connectedChannel = null; + for (final ChannelProxy channel : _liveChannels) + { + if (channel.isConnectedTo(endPoint)) + { + connectedChannel = channel; + break; + } + + } + return connectedChannel; + } + + public void add(ChannelProxy proxy) + { + synchronized (this._liveChannels) + { + ChannelProxy index = findProxy(proxy); + if (index == null) + this._liveChannels.add(proxy); + } + logger.info("Adding liveChannel " + proxy); + + dumpProxies(proxy, "Add"); //$NON-NLS-1$ + + } + + private void dumpProxies(ChannelProxy proxy, String cause) + { + if (logger.isDebugEnabled()) + { + logger.debug("Dump of LiveChannels, cause:" + cause + ": " + proxy); //$NON-NLS-1$ //$NON-NLS-2$ + for (ChannelProxy aProxy : _liveChannels) + { + logger.debug("ChannelProxy: " + aProxy); //$NON-NLS-1$ + } + } + } + + public void remove(ChannelProxy proxy) + { + + ChannelProxy index = findProxy(proxy); + if (index != null) + { + logger.error("Removing liveChannel " + proxy); + this._liveChannels.remove(index); + } + dumpProxies(proxy, "Removing"); //$NON-NLS-1$ + + } + + public ChannelProxy findChannel(String extendedChannelName, String uniqueID) + { + ChannelProxy proxy = null; + + String localUniqueId = uniqueID; + if (localUniqueId == null) + localUniqueId = ChannelImpl.UNKNOWN_UNIQUE_ID; + + // In order to get the 'best' match we first match each by unique id. + // Sometimes we can have two channels with the same name but + // different + + if (localUniqueId.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) + { + + for (ChannelProxy aChannel : _liveChannels) + { + if (aChannel.sameUniqueID(localUniqueId)) + { + proxy = aChannel; + break; + } + } + } + + // If we don't have a match from the first pass and the new uniqueID + // is unknown + // then do a search matching by name. + if (proxy == null) + { + for (ChannelProxy aChannel : _liveChannels) + { + + if (aChannel.isSame(extendedChannelName, localUniqueId)) + { + proxy = aChannel; + break; + } + } + } + + return proxy; + } + + private ChannelProxy findProxy(Channel original) + { + for (ChannelProxy aChannel : _liveChannels) + { + if (aChannel.isSame(original)) + { + return aChannel; + } + } + return null; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + required.add(MasqueradeEvent.class); + required.add(RenameEvent.class); + required.add(HangupEvent.class); + + return required; + } + + ChannelProxy findProxyById(String id) + { + for (ChannelProxy aChannel : _liveChannels) + { + if (("" + aChannel.getIdentity()).equals(id)) + { + return aChannel; + } + } + return null; + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + if (event instanceof MasqueradeEvent) + { + MasqueradeEvent masq = (MasqueradeEvent) event; + ChannelProxy originalIndex = findProxy(masq.getOriginal()); + ChannelProxy cloneIndex = findProxy(masq.getClone()); + if (originalIndex != null && cloneIndex != null) + { + ChannelProxy originalProxy = (ChannelProxy) masq.getOriginal(); + ChannelProxy cloneProxy = (ChannelProxy) masq.getClone(); + try + { + // After the masquerade the two underlying channels will + // have been switched + // between the two proxies. + // At this point the cloneProxy will be owned by a Peer + // (as they process NewChannelEvents) + // as such we cannot just discard the cloneProxy. The + // simplest solution then + // is to put the clone channel into the existing + // channel, as this is the core reason we have a proxy, + // and then put the original channel into the + // cloneProxy. At the end of this manuvour + // the Peer will still have two proxy which point to the + // two different channels. + // This is fine for the Peer as it doesn't attach any + // special meaning to any channel + // it just needs a list of all channels associated with + // the Peer. + // The original channel will shortly receive a hangup in + // which case the Peer will + // remove it from its list of channels and the Peer will + // be back to having + // one channel which will be the clone channel which is + // now the active channel + // and everyone will be happy. + originalProxy.masquerade(cloneProxy); + dumpProxies(cloneProxy, "Masquerade"); //$NON-NLS-1$ + } + catch (InvalidChannelName e) + { + logger.error(e, e); + + } + + } + else + logger.error("Either the clone or original channelProxy was missing during a masquerade: cloneIndex=" //$NON-NLS-1$ + + cloneIndex + " originalIndex=" + originalIndex); //$NON-NLS-1$ + + } + if (event instanceof RenameEvent) + { + RenameEvent rename = (RenameEvent) event; + + ChannelProxy oldChannel = findProxy(rename.getChannel()); + if (oldChannel != null) + { + try + { + oldChannel.rename(rename.getNewName()); + dumpProxies(oldChannel, "RenameEvent"); //$NON-NLS-1$ + } + catch (InvalidChannelName e) + { + logger.error(e, e); + } + } + } + else if (event instanceof HangupEvent) + { + // We need to process every hangup event that goes through the + // system + // as the LiveChannelManager has a Channel added for every channel + // that is created via Asterisk even if it has nothing to + // do with NJR. This is because channels are created + // whenever an event arrives before we actually can determine + // if we are interested in the event and its associated channels. + HangupEvent hangup = (HangupEvent) event; + // Yes I've seen a hangup where the channel was null, who knows + // why? + + if (hangup.getChannel() != null) + { + + ChannelProxy proxy = findProxy(hangup.getChannel()); + if (proxy != null) + { + this._liveChannels.remove(proxy); + logger.info("Removing liveChannel " + proxy); + proxy.getChannel().notifyHangupListeners(hangup.getCause(), hangup.getCauseTxt()); + dumpProxies(proxy, "HangupEvent"); //$NON-NLS-1$ + } + + } + } + } + + @Override + public String getName() + { + return "LiveChannelManager"; //$NON-NLS-1$ + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.CRITICAL; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java new file mode 100644 index 000000000..f471ee5ba --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java @@ -0,0 +1,328 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.LinkedList; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.MasqueradeEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewChannelEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewStateEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusEvent; + +/* + * this class tracks the status of a Peer on asterisk. T + * + * Peers are created by the PeerMonitor which also sends asterisk events to + * the peer. + * + */ + +public class Peer implements CallEndedListener +{ + static private Logger logger = Logger.getLogger(Peer.class); + + private final EndPoint peerEndPoint; + + /** + * Used to track the list of channels associated with this peer. + * + * I think there would normally only be a single channel unless we are in + * the middle of a transfer or the phone has two calls up. + */ + private final LinkedList callList = new LinkedList<>(); + + private PeerState _state = PeerState.NOTSET; + private boolean dnd = false; + + public Peer(final EndPoint endPoint) + { + this.peerEndPoint = endPoint; + } + + public boolean isSame(final Peer rhs) + { + return this.peerEndPoint.isSame(rhs.getEndPoint()); + } + + private CallTracker registerChannel(final Channel newChannel) + { + CallTracker associatedCall = null; + boolean found = false; + synchronized (this.callList) + { + for (final CallTracker call : this.callList) + { + if (call.findChannel(newChannel) != -1) + { + found = true; + associatedCall = call; + break; + } + } + if (!found) + { + if (logger.isDebugEnabled()) + logger.debug("Peer adding Call: " + this.toString() + " " + newChannel.getExtendedChannelName()); //$NON-NLS-1$ //$NON-NLS-2$ + associatedCall = createCallTracker(newChannel); + this.dumpCallList(); + } + } + return associatedCall; + } + + private CallTracker createCallTracker(final Channel newChannel) + { + CallTracker newCall; + synchronized (this.callList) + { + newCall = new CallTracker(this, newChannel); + this.callList.add(newCall); + } + return newCall; + } + + public boolean getDND() + { + return this.dnd; + } + + // public String getFullChannelName() + // { + // String channelName = null; + // synchronized (this.callList) + // { + // if (this.callList.size() > 0) + // { + // channelName = this.callList.get(0).getChannelName(); + // } + // } + // + // return channelName; + // } + + public PeerState getState() + { + return this._state; + } + + /** + * Determines if the given channel is connected to this peer. + * + * @param channel + * @return + */ + private boolean isConnectedToSelf(final Channel channel) + { + return this.getEndPoint().isSame(channel.getEndPoint()); + } + + /** + * We handle the masqurade event is it contains channel state information. + * During a masquerade we will have two channels for the one peer, the + * original and the clone. As the clone is taking over from the original + * peer we now need to use that as true indicator of state. + * + * @param b + * @throws Exception + */ + public void handleEvent(final MasqueradeEvent b) + { + if (this.isConnectedToSelf(b.getClone())) + { + // At this point we will actually have two CallTrackers + // which we now need to merge into a single CallTracker. + CallTracker original = findCall(b.getOriginal()); + CallTracker clone = findCall(b.getClone()); + if (original != null && clone != null) + { + clone.mergeCalls(original); + clone.setState(b.getCloneState()); + this.evaluateState(); + } + else + logger.warn("When processing masquradeEvent we could not find the expected calls. event=" //$NON-NLS-1$ + + b.toString() + " original=" + original + " clone=" + clone); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + /** + * When a new channel comes up associated it with the peer. + * + * Be warned a peer can have multiple calls associated with it. + * + * @param b + * @throws Exception + */ + public void handleEvent(final NewChannelEvent b) + { + // Very occasionally we get a null channel which we can't do anything + // with so just throw the event away. + // If we get a Console/dsp channel name it means that someone has + // dialled from the asterisk + // console. We just ignore these. + if ((b.getChannel() == null) || (b.getChannel().isConsole())) + { + return; + } + + if (this.isConnectedToSelf(b.getChannel())) + { + CallTracker call = this.registerChannel(b.getChannel()); + if (call != null) + { + call.setState(b.getChannelState()); + this.evaluateState(); + } + } + } + + public void handleEvent(final NewStateEvent b) + { + if (this.isConnectedToSelf(b.getChannel())) + { + CallTracker call = this.registerChannel(b.getChannel()); + if (call != null) + { + call.setState(b.getChannelState()); + this.evaluateState(); + } + } + } + + public void handleEvent(final StatusEvent b) + { + final Channel channel = b.getChannel(); + if (this.isConnectedToSelf(channel)) + { + ((ChannelProxy) channel).getRealChannel().markChannel(); + + CallTracker call = findCall(channel); + if (call != null) + { + call.setState(b.getState()); + this.evaluateState(); + } + } + } + + private CallTracker findCall(Channel channel) + { + CallTracker result = null; + synchronized (this.callList) + { + for (CallTracker call : this.callList) + { + if (call.findChannel(channel) != -1) + { + result = call; + break; + } + } + + } + return result; + } + + public void setDND(final boolean on) + { + this.dnd = on; + } + + public void startSweep() + { + Peer.logger.debug("Starting sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ + synchronized (this.callList) + { + for (final CallTracker call : this.callList) + { + call.startSweep(); + } + } + } + + public void endSweep() + { + Peer.logger.debug("Ending sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ + synchronized (this.callList) + { + for (final CallTracker call : this.callList) + { + call.endSweep(); + } + } + this.evaluateState(); + } + + /** + * Called each time the state of a call changes to determine the Peers + * overall state. + */ + private void evaluateState() + { + synchronized (this.callList) + { + // Get the highest prioirty state from the set of calls. + PeerState newState = PeerState.NOTSET; + for (CallTracker call : this.callList) + { + if (call.getState().getPriority() > newState.getPriority()) + newState = call.getState(); + } + + this._state = newState; + } + } + + public EndPoint getEndPoint() + { + return this.peerEndPoint; + } + + @Override + public String toString() + { + return this.getEndPoint().toString(); + } + + private void dumpCallList() + { + if (logger.isDebugEnabled()) + { + Peer.logger.debug("Peer: dump CallList:" + this); //$NON-NLS-1$ + for (final CallTracker call : this.callList) + { + call.dumpChannelList(); + } + } + } + + @Override + public void callEnded(CallTracker call) + { + boolean found = false; + synchronized (this.callList) + { + for (final CallTracker aCall : this.callList) + { + if (call == aCall) + { + found = true; + if (logger.isDebugEnabled()) + logger.debug("peer Removing call " + call); //$NON-NLS-1$ + this.callList.remove(call); + this.evaluateState(); + this.dumpCallList(); + break; + } + } + if (!found) + { + logger.error("Error call not found removing call from peer: call=" + call + " peer=" + this); //$NON-NLS-1$ //$NON-NLS-2$ + this.dumpCallList(); + } + } + + } + +} \ No newline at end of file diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java new file mode 100644 index 000000000..6e7fed882 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java @@ -0,0 +1,385 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.NewExtensionListener; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SipPeersAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.StatusAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.DndStateEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.MasqueradeEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewChannelEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewStateEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerEntryEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerStatusEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerlistCompleteEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusCompleteEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; + +/* + * this class tracks the status of all peers on asterisk. + */ +public class PeerMonitor extends EventListenerBaseClass implements Runnable +{ + + static Logger logger = Logger.getLogger(PeerMonitor.class); + + LinkedList peerList = new LinkedList<>(); + + boolean initSip = false; + + private final Thread markAndSweepThread; + + private static PeerMonitor self; + + private static NewExtensionListener listener; + + /** + * needs to notify PhoneBookDisplayController.getInstance().addExtensions(); + * + * @param _listener + */ + public synchronized static void init(final NewExtensionListener _listener) + { + PeerMonitor.listener = _listener; + + if (PeerMonitor.self == null) + { + PeerMonitor.self = new PeerMonitor(); + } + else if (_listener != null) + { + logger.error("Call to PeerMonitor.init, but it's already initialized. Listener will not be set"); + } + } + + public static synchronized PeerMonitor getInstance() + { + if (PeerMonitor.self == null) + { + throw new IllegalStateException("You must call PeerMonitor.init()"); //$NON-NLS-1$ + } + return PeerMonitor.self; + } + + private PeerMonitor() + { + super("PeerMonitor"); //$NON-NLS-1$ + this.peerList = new LinkedList<>(); + this.startListener(PBXFactory.getActivePBX()); + this.addSipsToMonitor(); + try + { + if (PeerMonitor.listener != null) + { + PeerMonitor.listener.newExtension(); + } + else + { + logger.warn("Peer monitor listener is null"); + } + } + catch (final Exception e) + { + PeerMonitor.logger.error(e, e); + } + + this.markAndSweepThread = new Thread(this); + this.markAndSweepThread.setName("PeerMonitor-MarkAndSweep"); //$NON-NLS-1$ + this.markAndSweepThread.setDaemon(true); + this.markAndSweepThread.start(); + + } + + public void addSipsToMonitor() + { + /* + * request asterisk to send a list of sip peers. The monitor will + * dynamically add the peers to its list + */ + this.initSip = false; + + final StatusAction sa = new StatusAction(); + final SipPeersAction t = new SipPeersAction(); + try + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + pbx.sendAction(t, 5000); + pbx.sendAction(sa, 5000); + } + catch (final Exception e) + { + PeerMonitor.logger.error(e, e); + } + + } + + synchronized public Peer registerPeer(final Channel newChannel) + { + final Peer peer = this.registerPeer(newChannel.getEndPoint()); + return peer; + } + + synchronized public Peer registerPeer(final EndPoint endPoint) + { + if (endPoint.isLocal()) + { + return null; + } + + Peer peer = this.findPeer(endPoint); + if (peer == null) + { + peer = new Peer(endPoint); + this.peerList.add(peer); + } + + return peer; + } + + synchronized public Peer findPeer(final EndPoint peerEndPoint) + { + Peer found = null; + + for (final Peer peer : this.peerList) + { + if (peer.getEndPoint().isSame(peerEndPoint)) + { + found = peer; + break; + } + } + return found; + } + + @SuppressWarnings("unchecked") + public Iterator getIterator() + { + final List clone = (LinkedList) this.peerList.clone(); + final List tmpList = clone; + return tmpList.iterator(); + + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + required.add(NewChannelEvent.class); + required.add(PeerStatusEvent.class); + required.add(PeerEntryEvent.class); + required.add(PeerlistCompleteEvent.class); + required.add(NewStateEvent.class); + required.add(StatusEvent.class); + required.add(StatusCompleteEvent.class); + required.add(DndStateEvent.class); + + return required; + } + + @Override + synchronized public void onManagerEvent(final ManagerEvent event) + { + /* + * This function is called from the base class. Here we process events + * we are interested in. + */ + + if (event instanceof PeerStatusEvent) + { + this.handleEvent((PeerStatusEvent) event); + } + else if (event instanceof PeerlistCompleteEvent) + { + this.handleEvent((PeerlistCompleteEvent) event); + } + else if (event instanceof PeerEntryEvent) + { + this.handleEvent((PeerEntryEvent) event); + } + else if (event instanceof NewChannelEvent) + { + this.handleEvent((NewChannelEvent) event); + } + else if (event instanceof MasqueradeEvent) + { + this.handleEvent((MasqueradeEvent) event); + } + else if (event instanceof StatusEvent) + { + this.handleEvent((StatusEvent) event); + } + else if (event instanceof StatusCompleteEvent) + { + this.handleEvent((StatusCompleteEvent) event); + } + else if (event instanceof NewStateEvent) + { + this.handleEvent((NewStateEvent) event); + } + } + + private void handleEvent(NewStateEvent event) + { + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } + } + + private void handleEvent(final NewChannelEvent event) + { + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } + } + + private void handleEvent(final MasqueradeEvent event) + { + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } + } + + private void handleEvent(final StatusEvent event) + { + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } + } + + private void handleEvent(final PeerEntryEvent event) + { + final EndPoint endPoint = event.getPeer(); + this.registerPeer(endPoint); + } + + private void handleEvent(final PeerlistCompleteEvent b) + { + this.initSip = true; + } + + /** + * @param event + */ + private void handleEvent(final PeerStatusEvent event) + { + this.registerPeer(event.getPeer()); + } + + /** + * We receive the StatusComplete event once the Mark and Sweep channel + * operation has completed. We now call endSweep which will remove any + * channels that were not marked during the operation. + * + * @param event + */ + private synchronized void handleEvent(final StatusCompleteEvent event) + { + + for (final Peer peer : this.peerList) + { + peer.endSweep(); + } + PeerMonitor.logger.debug("Channel Mark and Sweep complete"); //$NON-NLS-1$ + } + + boolean isInitialized() + { + return this.initSip; + } + + public void stop() + { + this.close(); + + } + + /************************************************************************************** + * + * Mark and Sweep logic follows + * + **************************************************************************************/ + + /** + * Runs the mark and sweep operation every 120 seconds on all channels to + * clean up any channels that have died and for which (for some reason) we + * missed the hangup event. + * + */ + @Override + public void run() + { + while (true) + { + try + { + Thread.sleep(120000); + PeerMonitor.getInstance().startSweep(); + } + catch (final InterruptedException e) + { + PeerMonitor.logger.error(e, e); + + } + } + + } + + /** + * Check every channel to make certain they are still active. We do this in + * case we missed a hangup event along the way somewhere. This allows us to + * cleanup any old channels. We start by clearing the mark on all channels + * and then generates a Asterisk status message for every active channel. At + * the end of the process any channels which haven't been marked are then + * discarded. + */ + public void startSweep() + { + PeerMonitor.logger.debug("Starting channel mark and sweep"); //$NON-NLS-1$ + + // Mark every channel as 'clearing' + synchronized (PeerMonitor.class) + { + for (final Peer peer : this.peerList) + { + peer.startSweep(); + } + } + + /** + * Request Asterisk to send us a status update for every channel. + * + */ + final StatusAction sa = new StatusAction(); + try + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + pbx.sendAction(sa, 5000); + } + catch (final Exception e) + { + PeerMonitor.logger.error(e, e); + } + + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.HIGH; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java new file mode 100644 index 000000000..666d4c9a2 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java @@ -0,0 +1,111 @@ +package org.asteriskjava.pbx.internal.core; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ChannelState; + +public enum PeerState +{ + DOWN(1,"Down", "OnHook", false), //$NON-NLS-1$ //$NON-NLS-2$ + UP(2,"Up", "OnPhone", true), //$NON-NLS-1$ //$NON-NLS-2$ + UNKNOWN(0,"Unknown", "Unknown", false), //$NON-NLS-1$ //$NON-NLS-2$ + NOTSET(0, "Not Set", "", false), //$NON-NLS-1$ //$NON-NLS-2$ + UNMONITORED(0, "Unmonitored", "Unmonitored", true), //$NON-NLS-1$ //$NON-NLS-2$ + DND(3,"DND", "DND", true), //$NON-NLS-1$ //$NON-NLS-2$ + RINGING(4,"Ringing", "Ringing", true), //$NON-NLS-1$ //$NON-NLS-2$ + OFF_LINE(1,"Off line", "Offline", true), //$NON-NLS-1$ //$NON-NLS-2$ + UNREGISTERED(0,"Unregistered", "Unregistered", true), //$NON-NLS-1$ //$NON-NLS-2$ + REGISTERED(0,"Registered", "Registered", false), //$NON-NLS-1$ //$NON-NLS-2$ + BUSY(2,"Busy", "Busy", true), //$NON-NLS-1$//$NON-NLS-2$ + RING(4,"Ring", "Dialing", true), //$NON-NLS-1$ //$NON-NLS-2$ + EXTERNAL(0,"External", "External", false);//$NON-NLS-1$ //$NON-NLS-2$ + + static private final Logger logger = Logger.getLogger(PeerState.class); + + final String _asteriskStateName; + + final String label; + + /** + * Controls whether the state should be displayed to the end user or just + * hidden. + * + */ + private boolean _visible; + + /** + * The priority ranks the PeerStates relative to each other. When a Peer has + * multiple active calls we need to display the call state from the call + * with the highest priority. e.g. If one call is UP and another is RINGING + * then we need to display the RINGING state as this is more interesting. + */ + private int _priority; + + public static PeerState valueByName(final String value) + { + PeerState status = NOTSET; + + for (PeerState aState : PeerState.values()) + { + + if (aState.getAsteriskStateName().compareToIgnoreCase(value) == 0) + { + status = aState; + break; + } + } + return status; + } + + private String getAsteriskStateName() + { + return this._asteriskStateName; + } + + public static PeerState valueByChannelState(final ChannelState state) + { + PeerState status = NOTSET; + + for (PeerState aState : PeerState.values()) + { + + if (aState.getAsteriskStateName().compareToIgnoreCase(state.name()) == 0) + { + status = aState; + break; + } + } + + if (status == NOTSET) + logger.warn("Unknown channelState: " + state + " recieved", new Throwable("Unknown channelState")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + return status; + } + + PeerState(int priority, final String asteriskStateName, final String label, boolean visible) + { + this._asteriskStateName = asteriskStateName; + this.label = label; + this._visible = visible; + this._priority = priority; + } + + public String getLabel() + { + return this.label; + } + + @Override + public String toString() + { + return this.label; + } + + public boolean isVisible() + { + return this._visible; + } + + public int getPriority() + { + return this._priority; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/TechType.java b/src/main/java/org/asteriskjava/pbx/internal/core/TechType.java new file mode 100644 index 000000000..2edf3031e --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/TechType.java @@ -0,0 +1,91 @@ +package org.asteriskjava.pbx.internal.core; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Tech; + +public enum TechType implements Tech +{ + + // + UNKNOWN, SIP, DAHDI, LOCAL, IAX, IAX2 + // The DIALPLAN tech is used to suppresses output of the tech + // when obtaining the fully qualified name of the endpoint. + // Basically if you want to call into an asterisk dialplan extension + // then the tech needs to be suppressed. + , DIALPLAN + // CONSOLE is sent when a call is made from the asterisk console. + // These type of channels are ignored. + , CONSOLE; + + private static final Logger logger = Logger.getLogger(TechType.class); + + /** + * Extracts the technology from a fully qualified endpoint string of the + * form: TECH/NNNN + * + * @param fullyQualifiedEndPoint + * @return + */ + public static TechType getTech(final String fullyQualifiedEndPoint) + { + if (!TechType.hasValidTech(fullyQualifiedEndPoint)) + { + throw new IllegalArgumentException("The provided end point '" //$NON-NLS-1$ + + fullyQualifiedEndPoint + "' must contain a tech prefix. e.g. SIP/100"); //$NON-NLS-1$ + } + + final String techName = fullyQualifiedEndPoint.substring(0, fullyQualifiedEndPoint.indexOf("/")); //$NON-NLS-1$ + return TechType.valueOf(techName.toUpperCase()); + } + + /** + * returns true if the endPoint name contains a valid tech descriptor. + * + * @param endPointName + * @return + */ + public static boolean hasValidTech(final String endPointName) + { + TechType tech = UNKNOWN; + final int index = endPointName.indexOf("/"); //$NON-NLS-1$ + + if (index >= 1) + { + final String techName = endPointName.substring(0, index); + try + { + tech = TechType.valueOf(techName.toUpperCase()); + } + catch (final IllegalArgumentException e) + { + TechType.logger.error("Invalid tech for endpoint:" + endPointName); //$NON-NLS-1$ + } + } + + return tech != UNKNOWN; + + } + + /** + * returns true if the endPoint name contains a tech descriptor even if it + * isn't a known descriptor. + * + * @param endPointName + * @return + */ + public static boolean hasTech(final String endPointName) + { + boolean hasTech = false; + + final int index = endPointName.indexOf("/"); //$NON-NLS-1$ + + if (index != -1) + { + hasTech = true; + } + + return hasTech; + + } + +} \ No newline at end of file diff --git a/src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java b/src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java new file mode 100644 index 000000000..a49dc43b8 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java @@ -0,0 +1,38 @@ +package org.asteriskjava.pbx.internal.eventQueue; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.util.LogTime; + +public class EventLifeMonitor +{ + static Logger logger = Logger.getLogger(EventLifeMonitor.class); + + /* + * this class is used to hold an event while its in the queue and calculate + * how long it spent in the que before being processed. + */ + + private final T theEvent; + + private final LogTime age; + + public EventLifeMonitor(final T event) + { + this.theEvent = event; + this.age = new LogTime(); + } + + public void assessAge() + { + if (this.age.timeTaken() > 2000) + { + EventLifeMonitor.logger.warn("event age : " + this.age.timeTaken()); //$NON-NLS-1$ + } + + } + + public T getEvent() + { + return this.theEvent; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java new file mode 100644 index 000000000..3339e9ce1 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java @@ -0,0 +1,131 @@ +package org.asteriskjava.pbx.internal.eventQueue; + +/** + * This class provides a method of accepting, queueing and delivering manager + * events. + * + * Asterisk is very sensitive to delays in receiving events. This class ensures + * that events are received and queued rapidly. A separate thread dequeues them + * and delivers them to the manager listener. + * + * Used this queue as follows: + * + * manager.addEventListener(new ManagerEventQueue(originalListener)); + * + * This affectively daisy changes the originalListener via our queue. + * + * @author bsutton + * @deprecated use CoherentManagerEventQueue + */ +public class ManagerEventQueue // implements ManagerEventListener, Runnable +{ + // static Logger logger = Logger.getLogger(ManagerEventQueue.class); + // + // private final ManagerEventListener listener; + // private boolean stop = false; + // private final Thread th; + // private final BlockingQueue> eventQueue = + // new LinkedBlockingQueue<>(); + // + // private int queueMaxSize; + // + // private long queueSum; + // + // private long queueCount; + // + // public ManagerEventQueue(final ManagerEventListener listener) + // { + // this.listener = listener; + // this.th = new Thread(this); + // this.th.setName("EventQueue: " + listener.getClass().getSimpleName());//$NON-NLS-1$ + // this.th.setDaemon(true); + // this.th.start(); + // } + // + // /** + // * handles manager events passed to us in our role as a listener. + // * + // * We queue the event so that it can be read, by the run method of this + // * class, and subsequently passed on to the original listener. + // */ + // @Override + // public void onManagerEvent(final ManagerEvent event) + // { + // // if ((event instanceof DisconnectEvent) || (event instanceof + // // ConnectEvent) || (event instanceof HangupEvent) + // // || (event instanceof NewExtenEvent)) + // // { + // + // if (event instanceof NewExtenEvent) + // return; + // + // this.eventQueue.add(new EventLifeMonitor<>(event)); + // final int queueSize = this.eventQueue.size(); + // if (this.queueMaxSize < queueSize) + // { + // this.queueMaxSize = queueSize; + // } + // this.queueSum += queueSize; + // this.queueCount++; + // + // if (ManagerEventQueue.logger.isDebugEnabled()) + // { + // if (this.eventQueue.size() > ((this.queueMaxSize + (this.queueSum / + // this.queueCount)) / 2)) + // { + // ManagerEventQueue.logger.debug("queue size max avg"); //$NON-NLS-1$ + // ManagerEventQueue.logger + // .debug(" " + queueSize + " " + this.queueMaxSize + " " + (this.queueSum / this.queueCount)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + // } + // + // ManagerEventQueue.logger.debug("queue size " + this.eventQueue.size());//$NON-NLS-1$ + // } + // // } + // + // } + // + // @Override + // public void run() + // { + // + // while (this.stop == false) + // { + // try + // { + // final EventLifeMonitor elm = this.eventQueue.poll(2, + // TimeUnit.SECONDS); + // if (elm != null) + // { + // // Re-add the following line if you want to log every event. + // // logger.error(elm.getEvent()); + // this.listener.onManagerEvent(elm.getEvent()); + // elm.assessAge(); + // } + // } + // catch (final Exception e) + // { + // /** + // * If an exception is thrown whilst we are shutting down then we + // * don't care. If it is thrown when we aren't shutting down then + // * we have a problem and we need to log it. + // */ + // if (this.stop == false) + // { + // ManagerEventQueue.logger.error(e, e); + // } + // } + // + // } + // + // } + // + // public void stop() + // { + // this.stop = true; + // synchronized (this.eventQueue) + // { + // this.eventQueue.notify(); + // } + // } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java new file mode 100644 index 000000000..a0b74d8f3 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java @@ -0,0 +1,98 @@ +package org.asteriskjava.pbx.internal.managerAPI; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import org.apache.log4j.Logger; +import org.asteriskjava.manager.AuthenticationFailedException; +import org.asteriskjava.manager.ManagerConnection; +import org.asteriskjava.manager.ManagerConnectionFactory; +import org.asteriskjava.manager.TimeoutException; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; + +/* + * this class is a very thin wrapper around the manager connection class + */ +public class Connector +{ + private ManagerConnection managerConnection; + static Logger logger = Logger.getLogger(Connector.class); + + /** + * Establishes a Asterisk ManagerConnection as well as performing the + * 'login' required by Asterisk. + * + * @param asteriskSettings + * @return + * @throws IOException + * @throws AuthenticationFailedException + * @throws TimeoutException + * @throws IllegalStateException + */ + public ManagerConnection connect(final AsteriskSettings asteriskSettings) + throws IOException, AuthenticationFailedException, TimeoutException, IllegalStateException + { + checkIfAsteriskRunning(asteriskSettings); + this.makeConnection(asteriskSettings); + return this.managerConnection; + } + + /** + * This method will try to make a simple tcp connection to the asterisk + * manager to establish it is up. We do this as the default makeConnection + * doesn't have a timeout and will sit trying to connect for a minute or so. + * By using method when the user realises they have a problem on start up + * they can go to the asterisk panel. Fix the problem and then we can retry + * with the new connection settings within a couple of seconds rather than + * waiting a minute for a timeout. + * + * @param asteriskSettings + * @throws UnknownHostException + * @throws IOException + */ + private void checkIfAsteriskRunning(AsteriskSettings asteriskSettings) throws UnknownHostException, IOException + { + try (Socket socket = new Socket();) + { + socket.setSoTimeout(2000); + + InetSocketAddress asteriskHost = new InetSocketAddress(asteriskSettings.getAsteriskIP(), + asteriskSettings.getManagerPortNo()); + socket.connect(asteriskHost, 2000); + } + + } + + /** + * @param socketReadTimeout + * @throws IOException + * @throws AuthenticationFailedException + * @throws TimeoutException + * @throws InsufficientPermissionsException + * @throws IllegalStateException + */ + private void makeConnection(final AsteriskSettings asteriskSettings) + throws IOException, AuthenticationFailedException, TimeoutException, IllegalStateException + { + ManagerConnectionFactory factory = null; + if (asteriskSettings.getManagerPortNo() == -1) + { + Connector.logger.debug("Using default port 5038."); //$NON-NLS-1$ + factory = new ManagerConnectionFactory(asteriskSettings.getAsteriskIP(), asteriskSettings.getManagerUsername(), + asteriskSettings.getManagerPassword()); + } + else + { + factory = new ManagerConnectionFactory(asteriskSettings.getAsteriskIP(), asteriskSettings.getManagerPortNo(), + asteriskSettings.getManagerUsername(), asteriskSettings.getManagerPassword()); + + } + + this.managerConnection = factory.createManagerConnection(); + // this.managerConnection.setSocketReadTimeout(socketReadTimeout); + // this.managerConnection.setSocketTimeout(socketReadTimeout); + this.managerConnection.login(); + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java new file mode 100644 index 000000000..5cbd4c42b --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java @@ -0,0 +1,175 @@ +package org.asteriskjava.pbx.internal.managerAPI; + +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.NewChannelListener; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityDial; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.LinkEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ListenerPriority; + +public class Dial extends EventListenerBaseClass +{ + private final static Logger logger = Logger.getLogger(Dial.class); + + private final OriginateResult result[] = new OriginateResult[2]; + + private CountDownLatch _latch; + + public Dial(final String descriptiveName) + { + super(descriptiveName); + this.startListener(PBXFactory.getActivePBX()); + } + + /** + * Dials the targetEndPoint connecting the call to the localHandset. The + * dial is done in two parts as we need to set the auto answer header + * differently for each phone. For the localHandset we set auto answer on, + * whilst for the remote targetEndPoint we MUST not auto answer the phone. + * + * @param localHandset the users handset we are going to dial from (e.g. + * receptionist phone). + * @param targetEndPoint - the remote handset we are going to connect the + * localHandset to. + * @param dialContext - context we are going to dial from. + * @param hideCallerId + * @param channelVarsToSet + * @param callerId - the callerID to display on the targetEndPoint. + * @return + * @throws PBXException + */ + public OriginateResult[] dial(final NewChannelListener listener, final EndPoint localHandset, + final EndPoint targetEndPoint, final String dialContext, final CallerID callerID, final boolean hideCallerId, + Map channelVarsToSet) throws PBXException + { + final PBX pbx = PBXFactory.getActivePBX(); + + try (final OriginateToExtension originate = new OriginateToExtension(listener);) + { + + // First bring the operator's handset up and connect it to the + // 'njr-dial' extension where they can + // wait whilst we complete the second leg + final OriginateResult trcResult = originate.originate(localHandset, pbx.getExtensionAgi(), true, + ((AsteriskPBX) pbx).getManagementContext(), callerID, hideCallerId, channelVarsToSet); + + this.result[0] = trcResult; + if (trcResult.isSuccess() == true) + { + + try + { + if (targetEndPoint instanceof HoldAtAgi) + { + if (trcResult.getChannel().waitForChannelToReachAgi(30, TimeUnit.SECONDS)) + { + // call is now in agi + System.out.println("Call is in agi"); + } + else + { + // call never reached agi + System.out.println("Call never reached agi"); + } + } + else + { + + // The call is now up, so connect it to + // the + // destination. + this._latch = new CountDownLatch(1); + + trcResult.getChannel().setCurrentActivityAction( + new AgiChannelActivityDial(targetEndPoint.getFullyQualifiedName())); + + this._latch.await(30, TimeUnit.SECONDS); + + } + } + catch (final InterruptedException e) + { + // noop + } + } + + return this.result; + } + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + required.add(BridgeEvent.class); + // bridge event is a subclass of linkevent, so we need link & unlink in + // our list of events to support Asterisk 1.4 + required.add(LinkEvent.class); + required.add(UnlinkEvent.class); + required.add(HangupEvent.class); + + return required; + } + + @Override + public void onManagerEvent(final ManagerEvent event) + { + if (event instanceof BridgeEvent) + { + final BridgeEvent link = (BridgeEvent) event; + + if ((link.getChannel1() != null) && (this.result[0] != null) + && link.getChannel1().isSame(this.result[0].getChannel())) + { + + Dial.logger.debug("Dial out bridged on " + link.getChannel1() + " to " + link.getChannel2()); //$NON-NLS-1$ //$NON-NLS-2$ + this.result[1] = new OriginateResult(); + + this.result[1].setChannelData(link.getChannel2()); + this._latch.countDown(); + } + } + else if (event instanceof HangupEvent) + { + final HangupEvent hangup = (HangupEvent) event; + final Channel hangupChannel = hangup.getChannel(); + + if (Dial.logger.isDebugEnabled()) + { + Dial.logger.debug("hangup :" + hangupChannel); //$NON-NLS-1$ + Dial.logger.debug("channel 0:" + this.result[0]); //$NON-NLS-1$ + Dial.logger.debug("channel 1:" + this.result[1]); //$NON-NLS-1$ + } + if ((this.result[0] != null) && this.result[0].isSuccess() && hangupChannel.isSame(this.result[0].getChannel())) + { + if (this._latch != null) + { + this._latch.countDown(); + } + } + } + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java new file mode 100644 index 000000000..495b5dbda --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -0,0 +1,124 @@ +package org.asteriskjava.pbx.internal.managerAPI; + +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.NewChannelListener; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ListenerPriority; + +public class DialToAgi extends EventListenerBaseClass +{ + private final static Logger logger = Logger.getLogger(DialToAgi.class); + + private final OriginateResult result[] = new OriginateResult[2]; + + private volatile boolean hangupDetected = false; + + public DialToAgi(final String descriptiveName) + { + super(descriptiveName); + this.startListener(PBXFactory.getActivePBX()); + } + + /** + * Dials the targetEndPoint connecting the call to the localHandset. The + * dial is done in two parts as we need to set the auto answer header + * differently for each phone. For the localHandset we set auto answer on, + * whilst for the remote targetEndPoint we MUST not auto answer the phone. + * + * @param localHandset the users handset we are going to dial from (e.g. + * receptionist phone). + * @param targetEndPoint - the remote handset we are going to connect the + * localHandset to. + * @param dialContext - context we are going to dial from. + * @param hideCallerId + * @param channelVarsToSet + * @param callerId - the callerID to display on the targetEndPoint. + * @return + * @throws PBXException + */ + public OriginateResult[] dial(final NewChannelListener listener, final EndPoint localHandset, + final AgiChannelActivityAction action, final CallerID callerID, final boolean hideCallerId, + Map channelVarsToSet) throws PBXException, InterruptedException + { + final PBX pbx = PBXFactory.getActivePBX(); + + try (final OriginateToExtension originate = new OriginateToExtension(listener);) + { + + // First bring the operator's handset up and connect it to the + // 'njr-dial' extension where they can + // wait whilst we complete the second leg + final OriginateResult trcResult = originate.originate(localHandset, pbx.getExtensionAgi(), true, + ((AsteriskPBX) pbx).getManagementContext(), callerID, hideCallerId, channelVarsToSet); + + this.result[0] = trcResult; + if (trcResult.isSuccess() == true) + { + + trcResult.getChannel().setCurrentActivityAction(action); + if (trcResult.getChannel().waitForChannelToReachAgi(30, TimeUnit.SECONDS)) + { + logger.info("Call reached AGI"); + } + else + { + logger.error("Call never reached agi"); + } + + } + logger.info("Hangup status is " + hangupDetected); + + return this.result; + } + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + required.add(HangupEvent.class); + + return required; + } + + @Override + public void onManagerEvent(final ManagerEvent event) + { + if (event instanceof HangupEvent) + { + final HangupEvent hangup = (HangupEvent) event; + final Channel hangupChannel = hangup.getChannel(); + + if (DialToAgi.logger.isDebugEnabled()) + { + DialToAgi.logger.debug("hangup :" + hangupChannel); //$NON-NLS-1$ + DialToAgi.logger.debug("channel 0:" + this.result[0]); //$NON-NLS-1$ + DialToAgi.logger.debug("channel 1:" + this.result[1]); //$NON-NLS-1$ + } + if ((this.result[0] != null) && this.result[0].isSuccess() && hangupChannel.isSame(this.result[0].getChannel())) + { + hangupDetected = true; + } + } + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java new file mode 100644 index 000000000..4d89e9380 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java @@ -0,0 +1,89 @@ +package org.asteriskjava.pbx.internal.managerAPI; + +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.FilteredManagerListener; + +/* + * This is the basic abstract event listener class. It implements a thread + * and queue. + */ +public abstract class EventListenerBaseClass implements FilteredManagerListener, AutoCloseable +{ + + private final String name; + + protected EventListenerBaseClass(final String descriptiveName) + { + this.name = descriptiveName; + } + + @Override + public String getName() + { + return this.name; + } + + /** + * we have to take the pbx as an arg here as we sometimes this is called + * during the creation phase of for the pbx, and the factory can't give out + * the pbx at that point event though it is initialised. + */ + + public void startListener(PBX iPBX) + { + + ((AsteriskPBX) iPBX).addListener(this); + } + + /** + * Stops the listener. + */ + @Override + public void close() + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + pbx.removeListener(this); + } + + /** + * This class exists so we can start and stop the listener using the new + * try-with-resource of JRE7. Whilst the parent class is Autoclosable we + * can't always use it directly in a try block (e.g. it is the base class). + * In those cases you can use this class. + * + * @author bsutton + */ + public class AutoClose implements java.lang.AutoCloseable + { + EventListenerBaseClass listener; + + public AutoClose(final EventListenerBaseClass listener) + { + this(listener, true); + } + + public AutoClose(final EventListenerBaseClass listener, final boolean sendEvents) + { + if (listener == null) + { + throw new IllegalArgumentException("listener may not be null"); //$NON-NLS-1$ + } + + this.listener = listener; + if (sendEvents) + { + listener.startListener(PBXFactory.getActivePBX()); + } + } + + @Override + public void close() + { + this.listener.close(); + + } + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java new file mode 100644 index 000000000..38b84224a --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java @@ -0,0 +1,70 @@ +package org.asteriskjava.pbx.internal.managerAPI; + +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.internal.core.TechType; + +public class HoldAtAgi implements EndPoint +{ + + @Override + public int compareTo(EndPoint arg0) + { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean isSame(EndPoint rhs) + { + return rhs instanceof HoldAtAgi; + } + + @Override + public boolean isLocal() + { + return false; + } + + @Override + public boolean isSIP() + { + return false; + } + + @Override + public String getFullyQualifiedName() + { + return ""; + } + + @Override + public String getSimpleName() + { + return ""; + } + + @Override + public String getSIPSimpleName() + { + return ""; + } + + @Override + public boolean isUnknown() + { + return false; + } + + @Override + public TechType getTech() + { + return null; + } + + @Override + public boolean isEmpty() + { + return true; + } + // Logger logger = LogManager.getLogger(); +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java new file mode 100644 index 000000000..18368850f --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java @@ -0,0 +1,55 @@ +package org.asteriskjava.pbx.internal.managerAPI; + +import java.util.Date; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.MonitorAction; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class MonitorCall +{ + static Logger logger = Logger.getLogger(MonitorCall.class); + + static long id = 1; + + private String file = null; + + public MonitorCall(final Call call) + { + super(); + + try + { + this.setFile(); + final MonitorAction monitorAction = new MonitorAction(call.getRemoteParty(), this.file, "gsm", true); //$NON-NLS-1$ + + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + pbx.sendAction(monitorAction, 1000); + + } + catch (final Exception e) + { + MonitorCall.logger.error(e, e); + } + } + + public String getFilename() + { + return this.file + ".gsm"; //$NON-NLS-1$ + } + + private synchronized void setFile() + { + long no = (new Date()).getTime(); + no = no / 1000; + final String unq = Long.toHexString(no); + + this.file = "njr" + unq + "-" + MonitorCall.id; //$NON-NLS-1$ //$NON-NLS-2$ + MonitorCall.id++; + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java new file mode 100644 index 000000000..6bbc10afa --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -0,0 +1,579 @@ +package org.asteriskjava.pbx.internal.managerAPI; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.asteriskjava.live.ManagerCommunicationException; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.NewChannelListener; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.GetVarAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.OriginateAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.LinkEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewChannelEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.OriginateResponseEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public abstract class OriginateBaseClass extends EventListenerBaseClass +{ + // Used to set a + public static final String NJR_ORIGINATE_ID = "njrOriginateID"; //$NON-NLS-1$ + + /* + * this class generates and issues ActionEvents to asterisk through the + * manager. This is the asterisk coal face. + */ + static Logger logger = Logger.getLogger(OriginateBaseClass.class); + + private volatile String originateID; + + private boolean originateSuccess; + + private final Channel monitorChannel1; + + private boolean hungup = false; + + private Channel newChannel; + + private final Channel monitorChannel2; + + private final OriginateResult result; + + /** + * The following two variables together are used to determine if the + * originated channel has come up. This is to overcome the problem that the + * OriginateResponseEvent and the NewChannelEvent can occur in any order + * (although the NewChannelEvent will occur first in most circumstances). + * Note: we get many NewChannelEvents but we are only interested in a very + * specific one. + */ + // Used to track if the originate event has been seen. + private boolean originateSeen = false; + + // Used to track if the new (final) channel has been seen. + private boolean channelSeen = false; + + private final NewChannelListener listener; + + private final CountDownLatch originateLatch = new CountDownLatch(1); + + protected OriginateBaseClass(final NewChannelListener listener, final Channel monitor, final Channel monitor2) + { + super("NewOrginateClass"); //$NON-NLS-1$ + this.listener = listener; + this.monitorChannel1 = monitor; + this.monitorChannel2 = monitor2; + this.result = new OriginateResult(); + + // Just add us as an asterisk event listener. + this.startListener(PBXFactory.getActivePBX()); + + } + + /** + * @param local + * @param target + * @param myVars + * @param callerId the caller id to set when initiating this call. + * @param hideCallerId + * @param context + * @return + */ + protected OriginateResult originate(final EndPoint local, final EndPoint target, final HashMap myVars, + final CallerID callerID, final Integer timeout, final boolean hideCallerId, final String context) + { + OriginateBaseClass.logger.debug("originate called"); //$NON-NLS-1$ + this.originateSeen = false; + this.channelSeen = false; + + if (this.hungup == true) + { + // the monitored channel already hungup so just return false and + // shutdown + this.close(); + return null; + } + + OriginateBaseClass.logger.debug("originate connection endPoint \n" + local + " to endPoint " + target //$NON-NLS-1$ //$NON-NLS-2$ + + " vars " + myVars); //$NON-NLS-1$ + ManagerResponse response = null; + + final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + + final OriginateAction originate = new OriginateAction(); + this.originateID = originate.getActionId(); + + // the double under score "__" is to cause the variable to propagate + // forward to the new channel when using local/ + myVars.put("__" + OriginateBaseClass.NJR_ORIGINATE_ID, this.originateID); //$NON-NLS-1$ + + Integer localTimeout = timeout; + + if (timeout == null) + { + localTimeout = 30000; + try + { + localTimeout = settings.getDialTimeout() * 1000; + } + catch (final Exception e) + { + OriginateBaseClass.logger.error("Invalid dial timeout value"); //$NON-NLS-1$ + } + } + + // Whilst the originate document says that it takes a channel it + // actually takes an + // end point. I haven't check but I'm skeptical that you can actually + // originate to + // a channel as the doco talks about 'dialing the channel'. I suspect + // this + // may be part of asterisk's sloppy terminology. + if (local.isLocal()) + { + originate.setEndPoint(local); + originate.setOption("/n"); //$NON-NLS-1$ + } + else + { + originate.setEndPoint(local); + } + + originate.setContext(context); + originate.setExten(target); + originate.setPriority(1); + + // Set the caller id. + if (hideCallerId) + { + // hide callerID + originate.setCallingPres(32); + } + else + { + originate.setCallerId(callerID); + } + + originate.setVariables(myVars); + originate.setAsync(true); + originate.setTimeout(localTimeout); + + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + try + { + response = pbx.sendAction(originate, localTimeout); + OriginateBaseClass.logger.debug("Originate.sendAction completed"); //$NON-NLS-1$ + if (response.getResponse().compareToIgnoreCase("Success") != 0)//$NON-NLS-1$ + { + OriginateBaseClass.logger + .error("Error Originating call" + originate.toString() + " : " + response.getMessage());//$NON-NLS-1$//$NON-NLS-2$ + throw new ManagerCommunicationException(response.getMessage(), null); + } + + originateLatch.await(localTimeout + 1000, TimeUnit.MILLISECONDS); // wait + // the + // set + // timeout + // +1 + // second to + // allow for + // asterisk to start the originate + } + catch (final InterruptedException e) + { + OriginateBaseClass.logger.debug(e, e); + } + catch (final Exception e) + { + OriginateBaseClass.logger.error(e, e); + } + finally + { + this.close(); + } + + if (this.originateSuccess == true) + { + this.result.setSuccess(true); + this.result.setChannelData(this.newChannel); + OriginateBaseClass.logger.debug("new channel ok: " + this.newChannel); //$NON-NLS-1$ + } + else + { + OriginateBaseClass.logger.error("originate failed connecting endPoint: " + local + " to ext " + target); //$NON-NLS-1$//$NON-NLS-2$ + + if (this.newChannel != null) + { + try + { + pbx.hangup(this.newChannel); + } + catch (IllegalArgumentException | IllegalStateException | PBXException e) + { + logger.error(e, e); + + } + } + } + return this.result; + } + + void abort(final String reason) + { + OriginateBaseClass.logger.debug("Aborting originate ");//$NON-NLS-1$ + this.close(); + this.originateSuccess = false; + this.result.setAbortReason(reason); + this.hungup = true; + if (this.newChannel != null) + { + OriginateBaseClass.logger.debug("Aborted, Hangup up on the way out");//$NON-NLS-1$ + this.result.setChannelHungup(true); + + PBX pbx = PBXFactory.getActivePBX(); + try + { + pbx.hangup(this.newChannel); + } + catch (IllegalArgumentException | IllegalStateException | PBXException e) + { + logger.error(e, e); + + } + } + originateLatch.countDown(); + + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + required.add(OriginateResponseEvent.class); + required.add(BridgeEvent.class); + // bridge event is a subclass of linkevent, so we need link & unlink in + // our list of events to support Asterisk 1.4 + required.add(LinkEvent.class); + required.add(UnlinkEvent.class); + required.add(HangupEvent.class); + required.add(NewChannelEvent.class); + + return required; + } + + /** + * It is important that this method is synchronised as there is some + * interaction between the events and we need to ensure we process one at a + * time. + */ + @Override + synchronized public void onManagerEvent(final ManagerEvent event) + { + if (event instanceof HangupEvent) + { + final HangupEvent hangupEvt = (HangupEvent) event; + final Channel hangupChannel = hangupEvt.getChannel(); + + if ((this.newChannel != null) && (hangupChannel.isSame(this.newChannel))) + { + this.originateSuccess = false; + OriginateBaseClass.logger.error("Dest channel " + this.newChannel + " hungup after answer"); //$NON-NLS-1$//$NON-NLS-2$ + originateLatch.countDown(); + } + if ((this.monitorChannel1 != null) && (hangupChannel.isSame(this.monitorChannel1))) + { + this.originateSuccess = false; + this.hungup = true; + if (this.newChannel != null) + { + OriginateBaseClass.logger.debug("hanging up " + this.newChannel);//$NON-NLS-1$ + this.result.setChannelHungup(true); + + PBX pbx = PBXFactory.getActivePBX(); + try + { + pbx.hangup(this.newChannel); + } + catch (IllegalArgumentException | IllegalStateException | PBXException e) + { + logger.error(e, e); + + } + } + OriginateBaseClass.logger.debug("notify channel 1 hungup");//$NON-NLS-1$ + originateLatch.countDown(); + } + if ((this.monitorChannel2 != null) && (hangupChannel.isSame(this.monitorChannel2))) + { + this.originateSuccess = false; + this.hungup = true; + if (this.newChannel != null) + { + OriginateBaseClass.logger.debug("Hanging up channel " + this.newChannel);//$NON-NLS-1$ + this.result.setChannelHungup(true); + + PBX pbx = PBXFactory.getActivePBX(); + try + { + pbx.hangup(this.newChannel); + } + catch (IllegalArgumentException | IllegalStateException | PBXException e) + { + logger.error(e, e); + + } + } + OriginateBaseClass.logger.debug("Notify channel 2 (" + this.monitorChannel2 + ") hungup");//$NON-NLS-1$//$NON-NLS-2$ + originateLatch.countDown(); + } + + } + if (event instanceof OriginateResponseEvent) + { + OriginateBaseClass.logger.debug("response : " + this.newChannel); //$NON-NLS-1$ + + final OriginateResponseEvent response = (OriginateResponseEvent) event; + OriginateBaseClass.logger.debug("OriginateResponseEvent: channel=" //$NON-NLS-1$ + + (response.isChannel() ? response.getChannel() : response.getEndPoint()) + " originateID:" //$NON-NLS-1$ + + this.originateID); + OriginateBaseClass.logger.debug("{" + response.getReason() + ":" + response.getResponse() + "}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + if (this.originateID != null) + { + if (this.originateID.compareToIgnoreCase(response.getActionId()) == 0) + { + this.originateSuccess = response.isSuccess(); + OriginateBaseClass.logger.debug("OriginateResponse: matched actionId, success=" + this.originateSuccess //$NON-NLS-1$ + + " channelSeen=" + this.channelSeen); //$NON-NLS-1$ + + this.originateSeen = true; + + // if we have also seen the channel then we can notify + // the + // originate() method + // that the call is up. Otherwise we will rely on the + // NewChannelEvent doing the + // notify. + if (this.channelSeen == true) + { + OriginateBaseClass.logger.debug("notify originate response event 305 " + this.originateSuccess);//$NON-NLS-1$ + originateLatch.countDown(); + } + } + } + else + { + OriginateBaseClass.logger.warn("actionid is null");//$NON-NLS-1$ + } + } + + // Look for the channel events that tell us that both sides of the + // call + // are up. + // We will see a number of channels come up as the call progresses. + // The LOCAL/ channels are just internal workings of Asterisk so we + // need + // to ignore these. + if (event instanceof NewChannelEvent) + { + final NewChannelEvent newState = (NewChannelEvent) event; + final Channel channel = newState.getChannel(); + final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); + + OriginateBaseClass.logger.debug("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-1$//$NON-NLS-2$ + + " state =" + newState.getChannelStateDesc() + " state =" + newState.getChannelState()); //$NON-NLS-1$ //$NON-NLS-2$ + + // Now try to get the NJR_ORIGINATE_ID's value to see if this is + // an + // event for our channel + // If it is for our channel then the NJR_ORIGINATE_ID will match + // our + // originateID. + // We need to try several times as it can take some time to + // appear + // within asterisk. + int ctr = 0; + String __originateID = null; + while ((ctr < 5) && (__originateID == null)) + { + try + { + ctr++; + /* + * wait 100ms to allow asterisk time to make the channel + * variables available. If you request the channel variables + * too soon asterisk responds with channel not found. + */ + Thread.sleep(100); + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + final ManagerResponse response = pbx.sendAction(var, 500); + __originateID = response.getAttribute("value"); //$NON-NLS-1$ + + if ((__originateID != null)) + { + // Check if the event is for our channel by checking + // the + // originateIDs match. + if (__originateID.compareToIgnoreCase(this.originateID) == 0) + { + if ((this.newChannel == null) && !channel.isLocal()) + { + this.newChannel = channel; + this.channelSeen = true; + + OriginateBaseClass.logger.debug("new channel name " + channel); //$NON-NLS-1$ } + if (this.listener != null) + { + /* + * sometimes it's not actually the NJR phone + * we're originating. Otherwise update the + * NJR phone channel to allow the call to be + * cancelled before it's answered. + */ + this.listener.channelUpdate(channel); + } + + if (this.originateSeen == true) + { + OriginateBaseClass.logger.debug("notifying success 362");//$NON-NLS-1$ + originateLatch.countDown(); + } + } + } + else + { + // So we got an originate but it wasn't for us which + // means this channel isn't ours. + // so we can ignore the event. + OriginateBaseClass.logger.debug("originateID " + __originateID); //$NON-NLS-1$ + } + } + } + catch (final Exception e) + { + // We only care about error if we are on the last + // attempt. + if ((this.originateSuccess == false) && (ctr == 4)) + { + OriginateBaseClass.logger.error(e, e); + } + } + } + } + + // Look for the channel events that tell us that both sides of the + // call + // are up. + // We will see a number of channels come up as the call progresses. + // The LOCAL/ channels are just internal workings of Asterisk so we + // need + // to ignore these. + if (event instanceof BridgeEvent) + { + final BridgeEvent bridgeEvent = (BridgeEvent) event; + Channel channel = bridgeEvent.getChannel1(); + if (bridgeEvent.getChannel1().isLocal()) + { + channel = bridgeEvent.getChannel2(); + } + final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); + + OriginateBaseClass.logger.debug("new channel event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-1$//$NON-NLS-2$ + + " channel2 =" + bridgeEvent.getChannel2()); //$NON-NLS-1$ + + // Now try to get the NJR_ORIGINATE_ID's value to see if this is + // an + // event for our channel + // If it is for our channel then the NJR_ORIGINATE_ID will match + // our + // originateID. + // We need to try several times as it can take some time to + // appear + // within asterisk. + int ctr = 0; + String __originateID = null; + while ((ctr < 5) && (__originateID == null)) + { + try + { + ctr++; + /* + * wait 100ms to allow asterisk time to make the channel + * variables available. If you request the channel variables + * too soon asterisk responds with channel not found. + */ + Thread.sleep(100); + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + final ManagerResponse response = pbx.sendAction(var, 500); + __originateID = response.getAttribute("value"); //$NON-NLS-1$ + + if ((__originateID != null)) + { + // Check if the event is for our channel by checking + // the + // originateIDs match. + if ((this.originateID != null) && (__originateID.compareToIgnoreCase(this.originateID) == 0)) + { + if ((this.newChannel == null) && !channel.isLocal()) + { + this.newChannel = channel; + this.channelSeen = true; + + OriginateBaseClass.logger.debug("new channel name " + channel); //$NON-NLS-1$ } + if (this.listener != null) + { + /* + * sometimes it's not actually the NJR phone + * we're originating. Otherwise update the + * NJR phone channel to allow the call to be + * cancelled before it's answered. + */ + this.listener.channelUpdate(channel); + } + + if (this.originateSeen == true) + { + OriginateBaseClass.logger.debug("notifying success 362");//$NON-NLS-1$ + originateLatch.countDown(); + } + } + } + } + else + { + // So we got an originate but it wasn't for us which + // means this channel isn't ours. + // so we can ignore the event. + OriginateBaseClass.logger.debug("originateID " + __originateID); //$NON-NLS-1$ + } + } + catch (final Exception e) + { + // We only care about error if we are on the last + // attempt. + if ((this.originateSuccess == false) && (ctr == 4)) + { + OriginateBaseClass.logger.error(e, e); + } + } + } + } + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java new file mode 100644 index 000000000..880ccb07b --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java @@ -0,0 +1,65 @@ +package org.asteriskjava.pbx.internal.managerAPI; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; + +public class OriginateResult +{ + static Logger logger = Logger.getLogger(OriginateResult.class); + + private boolean channelHungup = false; + + private boolean success = false; + + private Channel newChannel = null; + + private String abortReason; + + OriginateResult() + { + // not used + } + + public String getAbortReason() + { + return this.abortReason; + } + + void setAbortReason(final String reason) + { + this.abortReason = reason; + + } + + public void setChannelData(final Channel channel) + { + this.newChannel = channel; + } + + public Channel getChannel() + { + + return this.newChannel; + } + + public boolean isSuccess() + { + return this.success; + } + + public void setSuccess(boolean success) + { + this.success = success; + } + + public boolean isChannelHungup() + { + return this.channelHungup; + } + + public void setChannelHungup(boolean channel1Hungup) + { + this.channelHungup = channel1Hungup; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java new file mode 100644 index 000000000..f3d2eeaf4 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java @@ -0,0 +1,77 @@ +package org.asteriskjava.pbx.internal.managerAPI; + +import java.util.HashMap; +import java.util.Map; + +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.NewChannelListener; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.core.ListenerPriority; + +public class OriginateToExtension extends OriginateBaseClass +{ + + /* + * this class generates and issues ActionEvents to asterisk through the + * manager. This is the asterisk coal face. + */ + + public OriginateToExtension(final NewChannelListener listener) + { + super(listener, null, null); + + } + + public OriginateResult originate(final EndPoint localHandset, final EndPoint targetExtension, final boolean autoAnswer, + final CallerID callerID, final String context) + { + /* + * A new call is originated on the nominated channel to the specified + * extension. + */ + OriginateBaseClass.logger.debug("originate connecting localHandset " + localHandset + " to Extension " //$NON-NLS-1$ //$NON-NLS-2$ + + targetExtension + " autoAnswer " + autoAnswer); //$NON-NLS-1$ + final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + + final HashMap myVars = new HashMap<>(1); + if (autoAnswer == true) + { + RedirectCall.setAutoAnswer(myVars, profile); + } + + return this.originate(localHandset, targetExtension, myVars, callerID, null, false, context); + } + + public OriginateResult originate(final EndPoint localHandset, final EndPoint targetExtension, final boolean autoAnswer, + final String context, final CallerID callerID, final boolean hideCallerId, Map channelVarsToSet) + { + /* + * A new call is originated on the nominated channel to the specified + * extension. + */ + OriginateBaseClass.logger.debug("originate connection localHandset " + localHandset + " to Extension " //$NON-NLS-1$ //$NON-NLS-2$ + + targetExtension + " autoAnswer " + autoAnswer); //$NON-NLS-1$ + final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + + final HashMap myVars = new HashMap<>(1); + if (autoAnswer == true) + { + RedirectCall.setAutoAnswer(myVars, profile); + } + if (channelVarsToSet != null) + { + myVars.putAll(channelVarsToSet); + } + + return this.originate(localHandset, targetExtension, myVars, callerID, null, hideCallerId, context); + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java new file mode 100644 index 000000000..b634672ad --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java @@ -0,0 +1,75 @@ +package org.asteriskjava.pbx.internal.managerAPI; + +import java.util.HashMap; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityDial; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityVoicemail; +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class RedirectCall +{ + /* + * this class generates and issues ActionEvents to asterisk through the + * manager. This is the asterisk coal face. + */ + static Logger logger = Logger.getLogger(RedirectCall.class); + static public void setAutoAnswer(final HashMap myVars, final AsteriskSettings settings) + { + myVars.put(AsteriskPBX.getSIPADDHeader(false, true), settings.getAutoAnswer()); + RedirectCall.logger.debug("auto answer"); //$NON-NLS-1$ + } + + public boolean redirect(final Channel channel, final EndPoint targetEndPoint, final String context, + final boolean autoAnswer) throws PBXException + { + // Set or clear the auto answer header. + // Clearing is important as it may have been set during the + // initial answer sequence. If we don't clear it then then transfer + // target will be auto-answered, which is fun but bad. + String sipHeader = ""; + if (autoAnswer) + { + sipHeader = PBXSettingsManager.getActiveProfile().getAutoAnswer(); + } + + /* + * redirects the specified channel to the specified extension. Returns + * true or false reflecting success. + */ + redirect(channel, new AgiChannelActivityDial(targetEndPoint.getFullyQualifiedName(), sipHeader)); + + RedirectCall.logger.debug("redirected " + channel + " to " + targetEndPoint); //$NON-NLS-1$ //$NON-NLS-2$ + return true; + } + + public boolean redirectToVoicemail(final Channel channel, final EndPoint mailbox) throws PBXException + { + + redirect(channel, new AgiChannelActivityVoicemail(mailbox.getFullyQualifiedName())); + return true; + } + + public void redirect(Channel channel, AgiChannelActivityAction channelActivityHold) throws PBXException + { + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + if (!pbx.moveChannelToAgi(channel)) + { + throw new PBXException("Channel: " + channel + " couldn't be moved to agi"); + } + if (!pbx.waitForChannelToQuiescent(channel, 3000)) + throw new PBXException("Channel: " + channel + " cannot be redirected as it is still in transition."); + + channel.setCurrentActivityAction(channelActivityHold); + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java new file mode 100644 index 000000000..5c615ab0b --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java @@ -0,0 +1,51 @@ +package org.asteriskjava.pbx.internal.managerAPI; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.agi.AgiChannelActivityMeetme; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class RedirectToMeetMe +{ + static Logger logger = Logger.getLogger(RedirectToMeetMe.class); + + public RedirectToMeetMe() + { + super(); + } + + public boolean redirectToMeetme(final Channel channel, final String room, final boolean markedUser) throws PBXException + { + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + /* + * this procedure rediects the specified channel to the specified meetme + * room. This is achieved through the dial plan. q option - don't + * announce new members to meetme d option - dynamically create meetme x + * option - close the conference when last marked user exits A options - + * set marked user + */ + + RedirectToMeetMe.logger.info("redirect to Meetme channel " + channel + " room " + room //$NON-NLS-1$ //$NON-NLS-2$ + + " markedUser " + markedUser); //$NON-NLS-1$ + String options = new String(); + if (markedUser == true) + { + options = "qdxAF"; //$NON-NLS-1$ + } + else + { + options = "qdxF"; //$NON-NLS-1$ + } + + if (!pbx.moveChannelToAgi(channel)) + { + throw new PBXException("Channel: " + channel + " couldn't be moved to agi"); + } + channel.setCurrentActivityAction(new AgiChannelActivityMeetme(room, options)); + + return true; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/util/LogTime.java b/src/main/java/org/asteriskjava/pbx/util/LogTime.java new file mode 100644 index 000000000..fd2261e4c --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/util/LogTime.java @@ -0,0 +1,22 @@ +/* + * Created on 2/03/2005 + * + */ +package org.asteriskjava.pbx.util; + +/** + * @author work shop + */ +public class LogTime +{ + public Long dStartTime = System.currentTimeMillis(); + + public long timeTaken() + { + // returns the time taken from construction til now in milliseconds + // Date dStartTime = new Date(); + + return System.currentTimeMillis() - this.dStartTime; + + } +} diff --git a/src/test/java/org/asteriskjava/pbx/internal/agi/RateLimiterTest.java b/src/test/java/org/asteriskjava/pbx/internal/agi/RateLimiterTest.java new file mode 100644 index 000000000..0ff84f2a9 --- /dev/null +++ b/src/test/java/org/asteriskjava/pbx/internal/agi/RateLimiterTest.java @@ -0,0 +1,28 @@ +package org.asteriskjava.pbx.internal.agi; + +import static org.junit.Assert.assertTrue; + +import org.asteriskjava.pbx.internal.agi.RateLimiter; +import org.junit.Test; + +public class RateLimiterTest +{ + + @Test + public void test() throws InterruptedException + { + long now = System.currentTimeMillis(); + RateLimiter limiter = new RateLimiter(3); + for (int i = 0; i < 15; i++) + { + limiter.acquire(); + + System.out.println(System.currentTimeMillis()); + Thread.sleep(100); + } + + // this should have taken around 5 seconds + assertTrue(System.currentTimeMillis() - now > 4000L); + } + +} From a83400f2d0b4d1dcd1419610d6a4e79e01b7bd22 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Oct 2016 16:53:10 +1100 Subject: [PATCH 049/802] add some helpful info --- .../org/asteriskjava/pbx/internal/core/ChannelImpl.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index e70e4ad45..474bad93b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -130,6 +130,13 @@ public class ChannelImpl implements Channel /** * Creates a channel from a channelName
*
+ * This constructor is package private for a reason, and is called from + * AsteriskPBX... If you need to add a channel to the PBX do it like + * this
+ *
+ * AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX();
+ * final Channel channel = pbx.registerChannel(channelName, uniqueId);
+ *
* Channel names are one of the following formats: * [Action/]Tech/EndPointName-[][ ] * DAHDI/i/[:]-
From baf04070ead9d6cb5686cabd4414b30577aad425 Mon Sep 17 00:00:00 2001 From: pet Date: Fri, 7 Oct 2016 10:46:34 +0200 Subject: [PATCH 050/802] setAccountcode used wrong variable --- .../java/org/asteriskjava/manager/event/PeerEntryEvent.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java index a2b749d19..c102ce9c6 100644 --- a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java @@ -427,8 +427,7 @@ public String getAccountcode() /** * @param the accountcode to set */ - public void setAccountcode(String description) - { + public void setAccountcode(String accountcode) { this.accountcode = accountcode; } From 1bfbaff08e47d7cd12215d1c4d179558d8921b8a Mon Sep 17 00:00:00 2001 From: Brett Sutton Date: Mon, 10 Oct 2016 21:33:10 +1100 Subject: [PATCH 051/802] Update README.md --- README.md | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b691e4c69..f207080af 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,26 @@ 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](http://asterisk.org). Asterisk-Java supports both interfaces that Asterisk provides for this scenario: The [FastAGI](https://wiki.asterisk.org/wiki/display/AST/Application_AGI) protocol and the [Manager API](https://wiki.asterisk.org/wiki/display/AST/The+Asterisk+Manager+TCP+IP+API). +FastAGI +------- +FastAGI lets you create a service that manages a call in a similar way to what a webserver handles a http request. FastAGI can be (and should be) used to replace dialplan. FastAGI is thousands of times faster than dialplan, easier to debug and lets you do call control in a language that you are fimilar with. + The FastAGI implementation supports all commands currently available from Asterisk. +Manager API +----------- 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). - +If you like, the Manager API allows you start and manipulate calls. A complete list of the available events and actions is available in the javadocs. +Activities +---------- +Activities are new to asterisk-java 2.0. The aim of Activities is to provide a high level interface to interactions with Asterisk. Whist Activities use both FastAGI and the Manager API you would normally consider Activities as a replacement for the Manager API. + +Activities provide a simple and consistent method of interaction with Asterisk without having to worry about issues such as connection management and without having to understand the intricacies of Asterisk Manager Actions and Events. + + + See docs/tutorial.html for examples. GETTING ASTERISK-JAVA @@ -21,11 +35,19 @@ Asterisk-Java is available from [here](https://github.com/asterisk-java/asterisk Maven Dependency ---------------- +Asterisk 1.0 + + + org.asteriskjava + asterisk-java + 1.0.0-final + +Asterisk 2.0 - org.asteriskjava - asterisk-java - 1.0.0-final + org.asteriskjava + asterisk-java + 2.0.0-final INSTALLATION FROM SOURCE From 218d6cc07cf9c804ab18df4e12ae3b4b1998ab11 Mon Sep 17 00:00:00 2001 From: Brett Sutton Date: Mon, 10 Oct 2016 23:05:24 +1100 Subject: [PATCH 052/802] Start work on creating a number of Activity examples and cleaning up the java doc. --- src/main/java/org/asteriskjava/pbx/Call.java | 31 +++-- .../java/org/asteriskjava/pbx/CallImpl.java | 3 + src/main/java/org/asteriskjava/pbx/PBX.java | 47 ++----- .../pbx/activities/DialActivity.java | 4 + .../pbx/activities/DialActivityImpl.java | 4 +- .../pbx/activities/HoldActivity.java | 4 +- .../pbx/activities/HoldActivityImpl.java | 5 + .../pbx/activities/SplitActivityImpl.java | 37 +----- .../pbx/internal/core/AsteriskPBX.java | 27 ---- .../core/CoherentManagerConnection.java | 6 +- .../examples/activities/BlindTransfer.java | 104 ++++++++++++++++ .../examples/activities/Dial.java | 115 ++++++++++++++++++ .../examples/activities/Hold.java | 82 +++++++++++++ .../examples/fastagi}/ExampleCallIn.java | 2 + .../examples/fastagi}/fastagi.properties | 0 15 files changed, 359 insertions(+), 112 deletions(-) create mode 100644 src/test/java/org/asteriskjava/examples/activities/BlindTransfer.java create mode 100644 src/test/java/org/asteriskjava/examples/activities/Dial.java create mode 100644 src/test/java/org/asteriskjava/examples/activities/Hold.java rename {examples => src/test/java/org/asteriskjava/examples/fastagi}/ExampleCallIn.java (94%) rename {examples => src/test/java/org/asteriskjava/examples/fastagi}/fastagi.properties (100%) diff --git a/src/main/java/org/asteriskjava/pbx/Call.java b/src/main/java/org/asteriskjava/pbx/Call.java index 0184397b1..31813a5b8 100644 --- a/src/main/java/org/asteriskjava/pbx/Call.java +++ b/src/main/java/org/asteriskjava/pbx/Call.java @@ -40,26 +40,25 @@ public enum OperandChannel LOCAL_PARTY } - boolean contains(Channel parkChannel); - - // public void callIsAnswering(iEndPoint answeredBy) throws PBXException; + // Returns true of the given channel is part of this call. + boolean contains(Channel channel); + // The caller id of the party that accepted (answered) the call. CallerID getAcceptingPartyCallerID(); + // The caller id of the party that dialed the call. CallerID getOriginatingPartyCallerID(); + // The caller id of the remote party. CallerID getRemotePartyCallerID(); - // void callDialedIn(iCallerID callerCallerID) throws PBXException; - - // void transferDeclined() throws PBXException; - + // The date/time the call started. Date getCallStartTime(); - // Collection getChannels(); - + // The channel associated with the party that originated (dialed) the call. Channel getOriginatingParty(); + // The channel associated with the part that accepted (answered) the call. Channel getAcceptingParty(); Channel getTransferTargetParty(); @@ -90,9 +89,23 @@ public enum OperandChannel */ public Channel getLocalParty(); + /** + * Returns true of the Call can be split into two (or more) separate calls. + * @return + */ boolean canSplit(); + /** + * Returns the direction of the call. + * The call Direction can be a little esoteric as a call can + * come in and then be transferred out again. So is this an inbound or outbound call? + * @return + */ CallDirection getDirection(); + /** + * Returns a list of the Channels associated with this call. + * @return + */ List getChannels(); } diff --git a/src/main/java/org/asteriskjava/pbx/CallImpl.java b/src/main/java/org/asteriskjava/pbx/CallImpl.java index 7cf4765cf..4f2ee7503 100644 --- a/src/main/java/org/asteriskjava/pbx/CallImpl.java +++ b/src/main/java/org/asteriskjava/pbx/CallImpl.java @@ -878,6 +878,9 @@ public boolean isSame(Call rhs) return this._uniquecallID == ((CallImpl) rhs)._uniquecallID; } + /** + * Returns all of the Channels associated with this call. + */ @Override public List getChannels() { diff --git a/src/main/java/org/asteriskjava/pbx/PBX.java b/src/main/java/org/asteriskjava/pbx/PBX.java index e69952950..78cbf569a 100644 --- a/src/main/java/org/asteriskjava/pbx/PBX.java +++ b/src/main/java/org/asteriskjava/pbx/PBX.java @@ -46,7 +46,7 @@ public interface PBX * the transfer. * @param autoAnswer - if true then the transferTarget is to be sent an auto * answer header - * @param timeout - timeout for the blind transfer attempt. When the timeout + * @param timeout - timeout (in seconds) for the blind transfer attempt. When the timeout * is reached the Blind Transfer will be cancelled. * @param ActivityCallback */ @@ -198,44 +198,13 @@ DialActivity dial(Trunk trunk, EndPoint from, CallerID fromCallerID, EndPoint to */ void sendDTMF(Channel channel, DTMFTone tone, ActivityCallback callback); - // - // /** - // * Splits a call (with two channels) sending the originating channel to - // the - // * originatingTarget and other channel to the secondaryTarget. - // * - // * This call returns once the split action has completed. - // * - // * @param callToSplit - // * @param originatingTarget - // * @param secondaryTarget - // * @return - // * @throws PBXException - // */ - // iSplitActivity split(iCall callToSplit, iEndPoint originatingTarget, - // iEndPoint secondaryTarget) throws PBXException; - // - // - // /** - // * Splits a call (with two channels) sending the originating channel to - // the - // * originatingTarget and other channel to the secondaryTarget. - // * - // * This method returns immediately with progress information passed to the - // * given callback. Note: the callback method will be called from a - // different - // * thread. - // * - // * @param callToSplit - // * @param originatingTarget - // * @param secondaryTarget - // * @return - // */ - // public iSplitActivity split(final iCall callToSplit, final iEndPoint - // originatingTarget, - // final iEndPoint secondaryTarget, final iCallback - // listener); - + + /** + * Splits a call (with two channels) + * + * This call returns once the split action has completed. + */ + public SplitActivity split(final Call callToSplit, final ActivityCallback listener) throws PBXException; public SplitActivity split(final Call callToSplit) throws PBXException; diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialActivity.java b/src/main/java/org/asteriskjava/pbx/activities/DialActivity.java index 1e618634f..46a7ceab4 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/DialActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/DialActivity.java @@ -43,6 +43,10 @@ public interface DialActivity extends Activity */ void markCancelled(); + /** + * Returns true if markCancelled was called during the dial attempt. + * @return + */ boolean cancelledByOperator(); Call getNewCall(); diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java index a3bf0f5fb..ea21b09b2 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java @@ -157,8 +157,8 @@ private void hangup() } /** - * Called if the user cancels the call after starting it. The caller must - * also hangup the trc channel. + * Called to cancels the dial before it fully comes up. The caller must + * also hangup the associated channels. */ @Override public void markCancelled() diff --git a/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java b/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java index 8f372c711..812c927be 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java @@ -1,8 +1,10 @@ package org.asteriskjava.pbx.activities; import org.asteriskjava.pbx.Activity; +import org.asteriskjava.pbx.Channel; public interface HoldActivity extends Activity { - // TODO + // Returns the Channel that is on hold + public Channel getChannel(); } diff --git a/src/main/java/org/asteriskjava/pbx/activities/HoldActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/HoldActivityImpl.java index dfa6eee33..059aca09f 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/HoldActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/activities/HoldActivityImpl.java @@ -56,6 +56,11 @@ public boolean doActivity() throws PBXException return success; } + public Channel getChannel() + { + return this._channel; + } + @Override public HashSet> requiredEvents() { diff --git a/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java index 4ffa02b23..416270df5 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java @@ -23,9 +23,9 @@ /** * The SplitActivity is used by the AsteriksPBX to split a call and place the - * component channels into two separate destination extension. The SplitActivity + * component channels into the specialist Activity fastagi. The SplitActivity * can only split a call with two channels. The (obvious?) limitation is that we - * can't split something a conference call as it has more than two channels. + * can't split something in a conference call as it has more than two channels. * * @author bsutton */ @@ -44,26 +44,12 @@ public class SplitActivityImpl extends ActivityHelper implements private Call _rhsCall; /** - * Splits a call by moving each of its two channels to different target - * endpoints. The split does not perform a dial so the endpoints need to - * dial plan extensions. + * Splits a call by moving each of its two channels into the Activity agi. + * The channels will sit in the agi (with no audio) until something is done with them. + * As such you should leave them split for too long. * - * @param callToSplit The call to split - * @param originatingTarget The target to move the calls originating channel - * to. - * @param secondaryTarget The target to move the calls secondary channel to - * @param listener - */ - // public SplitActivity(final iChannel lhs, final iEndPoint - // originatingTarget, final iChannel rhs, final iEndPoint secondaryTarget, - // final iCallback listener) - - /** - * Splits two channels out of a call redirecting each call to a new - * iEndPoint. If the original call only had two channels then it will be - * discarded. * - * @param callToSplit + * @param callToSplit The call to split * @param listener */ public SplitActivityImpl(final Call callToSplit, final ActivityCallback listener) @@ -106,17 +92,6 @@ public boolean doActivity() throws PBXException this._rhsCall = ((CallImpl) this._callToSplit).split(channel2); } } - // else - // { - // success = - // splitOne(this._callToSplit.getOperandChannel(this._lhsChannel), - // this._lhsTarget, - // profile.getManagementContext()); - // // Now update the call to reflect the split - // if (success) - // this._lhsCall = ((Call) this._callToSplit).split(this._lhsChannel); - // - // } return success; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 08bb9892a..cc82559af 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -190,33 +190,6 @@ public SplitActivity split(final Call callToSplit, final ActivityCallback - // listener) - // { - // if (!callToSplit.canSplit()) - // throw new IllegalStateException("The call must have exactly two channels - // to be split."); //$NON-NLS-1$ - // - // iChannel remote = callToSplit.getRemoteParty(); - // iChannel local = callToSplit.getLocalParty(); - // - // final SplitActivity split = new SplitActivity(remote, remotePartyTarget, - // local, locaPartyTarget, listener); - // return split; - // } - // - // private SplitActivity _split(final iChannel lhs, final iEndPoint - // lhsTarget, - // final iChannel rhs, final iEndPoint rhsTarget, final - // iCallback listener) - // { - // final SplitActivity split = new SplitActivity(lhs, lhsTarget, rhs, - // rhsTarget, listener); - // return split; - // } - // /** * Joins two calls not returning until the join completes. The join will * complete almost immediately as it is a simple bridging of two active diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java index 6651c19ff..bdf4acfbe 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -53,15 +53,15 @@ * This means that we are always responsive to asterisk when receiving events, * if we are not responsive then asterisk will drop the connection.
*
- * It should be noted that as all events are dispatch from a single thread that + * It should be noted that as all events are dispatch from a single thread and as such * a single tardy listener can block all other listeners.
*
* If your listener is likely to be slow in handling events then you should wrap * the listener in its own ManagerEventQueue.
*
- * It is critical that you use the ManagerEventQueue is it forms an intrinsic + * It is critical that you use the ManagerEventQueue as it forms an intrinsic * part of this classes ability to ensure that channel/event processing is - * coherent.
+ * coherent (i.e events are processed in the correct order).
*
* For connections that generate large number of events you should use * diff --git a/src/test/java/org/asteriskjava/examples/activities/BlindTransfer.java b/src/test/java/org/asteriskjava/examples/activities/BlindTransfer.java new file mode 100644 index 000000000..502616d13 --- /dev/null +++ b/src/test/java/org/asteriskjava/examples/activities/BlindTransfer.java @@ -0,0 +1,104 @@ +package org.asteriskjava.examples.activities; + +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.Call.OperandChannel; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.activities.BlindTransferActivity; +import org.asteriskjava.pbx.activities.DialActivity; +import org.asteriskjava.pbx.internal.core.TechType; + +/** + * dial somebody and then blind transfer the call to a third party. + * + * @author bsutton + * + */ +public class BlindTransfer +{ + + static public void main(String[] args) + { + blindTransfer(); + } + + static private void blindTransfer() + { + PBX pbx = PBXFactory.getActivePBX(); + + // We are going to dial from extension 100 + EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + // The caller ID to show on extension 100. + CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); + + // The caller ID to display on the called parties phone + CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); + // The party we are going to call. + EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); + + // Start the dial and return immediately. + // progress is provided via the ActivityCallback. + pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() + { + @Override + public void start(DialActivity activity) + { + System.out.println("The dial has started"); + // We can stop it progress further by cancelling the dial + // activity.markCancelled(); + } + + @Override + public void progess(DialActivity activity, String message) + { + System.out.println("Dial status: " + message); + } + + @Override + public void completed(DialActivity activity, boolean success) + { + if (success) + { + System.out.println("Dial all good so lets do a blind transfer"); + PBX pbx = PBXFactory.getActivePBX(); + // Call is up + Call call = activity.getNewCall(); + CallerID toCallerID = pbx.buildCallerID("101", "I'm calling you"); + EndPoint transferTarget = pbx.buildEndPoint("101", TechType.SIP); + pbx.blindTransfer(call, OperandChannel.REMOTE_PARTY, transferTarget, toCallerID, false, 30L, + new ActivityCallback() + { + + @Override + public void start(BlindTransferActivity activity) + { + // TODO Auto-generated method stub + + } + + @Override + public void progess(BlindTransferActivity activity, String message) + { + // TODO Auto-generated method stub + + } + + @Override + public void completed(BlindTransferActivity activity, boolean success) + { + // if success the blind transfer completed. + } + }); + } + else + System.out.println("Oops something bad happened when we dialed."); + } + }); + + } + +} diff --git a/src/test/java/org/asteriskjava/examples/activities/Dial.java b/src/test/java/org/asteriskjava/examples/activities/Dial.java new file mode 100644 index 000000000..53c5d64aa --- /dev/null +++ b/src/test/java/org/asteriskjava/examples/activities/Dial.java @@ -0,0 +1,115 @@ +package org.asteriskjava.examples.activities; + +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.activities.DialActivity; +import org.asteriskjava.pbx.internal.core.TechType; + +public class Dial +{ + static public void main(String[] args) + { + syncDial(); + asyncDial(); + + } + + /** + * Simple synchronous dial. The dial method won't return until the dial starts. + * Using this method will lockup your UI until the dial starts. + * For better control use the async Dial method below. + */ + static private void syncDial() + { + try + { + PBX pbx = PBXFactory.getActivePBX(); + + // We are going to dial from extension 100 + EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + // The caller ID to show on extension 100. + CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); + + // The caller ID to display on the called parties phone + CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); + // The party we are going to call. + EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); + + // Trunk is currently ignored so set to null + // The call is dialed and only returns when the call comes up (it + // doesn't wait for the remote end to answer). + DialActivity dial = pbx.dial(null, from, fromCallerID, to, toCallerID); + + Call call = dial.getNewCall(); + + pbx.hangup(call.getOriginatingParty()); + } + catch (PBXException e) + { + System.out.println(e); + } + } + + static private void asyncDial() + { + PBX pbx = PBXFactory.getActivePBX(); + + // We are going to dial from extension 100 + EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + // The caller ID to show on extension 100. + CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); + + // The caller ID to display on the called parties phone + CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); + // The party we are going to call. + EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); + + // Start the dial and return immediately. + // progress is provided via the ActivityCallback. + pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() + { + @Override + public void start(DialActivity activity) + { + System.out.println("The dial has started"); + // We can stop it progress further by cancelling the dial + // activity.markCancelled(); + } + + @Override + public void progess(DialActivity activity, String message) + { + System.out.println("Dial status: " + message); + } + + @Override + public void completed(DialActivity activity, boolean success) + { + if (success) + { + System.out.println("Dial all good"); + try + { + // Call is up + Call call = activity.getNewCall(); + // So lets just hangup the call + PBXFactory.getActivePBX().hangup(call.getOriginatingParty()); + } + catch (PBXException e) + { + System.out.println(e); + } + } + else + System.out.println("Oops something bad happened when we dialed."); + } + }); + + } + +} diff --git a/src/test/java/org/asteriskjava/examples/activities/Hold.java b/src/test/java/org/asteriskjava/examples/activities/Hold.java new file mode 100644 index 000000000..ff66e97b8 --- /dev/null +++ b/src/test/java/org/asteriskjava/examples/activities/Hold.java @@ -0,0 +1,82 @@ +package org.asteriskjava.examples.activities; + +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.PBX; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.activities.DialActivity; +import org.asteriskjava.pbx.activities.HoldActivity; +import org.asteriskjava.pbx.internal.core.TechType; + +/** + * dial somebody and then put them on hold. + * + * @author bsutton + * + */ +public class Hold +{ + + static public void main(String[] args) + { + hold(); + } + + static private void hold() + { + PBX pbx = PBXFactory.getActivePBX(); + + // We are going to dial from extension 100 + EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + // The caller ID to show on extension 100. + CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); + + // The caller ID to display on the called parties phone + CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); + // The party we are going to call. + EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); + + // Start the dial and return immediately. + // progress is provided via the ActivityCallback. + pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() + { + @Override + public void start(DialActivity activity) + { + System.out.println("The dial has started"); + // We can stop it progress further by cancelling the dial + // activity.markCancelled(); + } + + @Override + public void progess(DialActivity activity, String message) + { + System.out.println("Dial status: " + message); + } + + @Override + public void completed(DialActivity activity, boolean success) + { + if (success) + { + System.out.println("Dial all good so lets place them on hold"); + PBX pbx = PBXFactory.getActivePBX(); + // Call is up + Call call = activity.getNewCall(); + + // Place the remote party on hold. + HoldActivity hold = pbx.hold(call.getRemoteParty()); + + Channel heldChannel = hold.getChannel(); + } + else + System.out.println("Oops something bad happened when we dialed."); + } + }); + + } + +} diff --git a/examples/ExampleCallIn.java b/src/test/java/org/asteriskjava/examples/fastagi/ExampleCallIn.java similarity index 94% rename from examples/ExampleCallIn.java rename to src/test/java/org/asteriskjava/examples/fastagi/ExampleCallIn.java index 041b666a2..debdd01ae 100644 --- a/examples/ExampleCallIn.java +++ b/src/test/java/org/asteriskjava/examples/fastagi/ExampleCallIn.java @@ -1,3 +1,5 @@ +package org.asteriskjava.examples.fastagi; + /* Cloudvox - answer and control a phone call with Java Place and receive phone calls via open API: http://cloudvox.com/ Learn about call scripting, Asterisk/AGI, voice apps: http://help.cloudvox.com/ diff --git a/examples/fastagi.properties b/src/test/java/org/asteriskjava/examples/fastagi/fastagi.properties similarity index 100% rename from examples/fastagi.properties rename to src/test/java/org/asteriskjava/examples/fastagi/fastagi.properties From 7e6b5c610d8a664b9f06f0043817d702201c49af Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Oct 2016 09:18:52 +1100 Subject: [PATCH 053/802] change PBXSettingsManager - moved into PBXFactory --- .../java/org/asteriskjava/pbx/PBXFactory.java | 23 +++++++++++++++ .../activities/BlindTransferActivityImpl.java | 3 +- .../pbx/activities/DialActivityImpl.java | 3 +- .../pbx/activities/ParkActivityImpl.java | 3 +- .../pbx/activities/SplitActivityImpl.java | 3 +- .../agi/AgiChannelActivityMeetme.java | 3 +- .../internal/agi/AgiChannelActivityQueue.java | 3 +- .../internal/asterisk/MeetmeRoomControl.java | 2 +- .../internal/asterisk/PBXSettingsManager.java | 28 ------------------- .../pbx/internal/core/AsteriskPBX.java | 9 +++--- .../pbx/internal/core/ChannelImpl.java | 3 +- .../core/CoherentManagerConnection.java | 5 ++-- .../internal/core/DialLocalToAgiActivity.java | 3 +- .../managerAPI/OriginateBaseClass.java | 3 +- .../managerAPI/OriginateToExtension.java | 6 ++-- .../pbx/internal/managerAPI/RedirectCall.java | 14 +++++----- 16 files changed, 49 insertions(+), 65 deletions(-) delete mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/PBXSettingsManager.java diff --git a/src/main/java/org/asteriskjava/pbx/PBXFactory.java b/src/main/java/org/asteriskjava/pbx/PBXFactory.java index d111a5070..840f15cf3 100644 --- a/src/main/java/org/asteriskjava/pbx/PBXFactory.java +++ b/src/main/java/org/asteriskjava/pbx/PBXFactory.java @@ -1,5 +1,8 @@ package org.asteriskjava.pbx; +import java.util.concurrent.atomic.AtomicReference; + +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class PBXFactory @@ -11,4 +14,24 @@ public static PBX getActivePBX() } + final static AtomicReference profile = new AtomicReference<>(); + + public static void init(AsteriskSettings newProfile) + { + profile.set(newProfile); + + } + + public static AsteriskSettings getActiveProfile() + { + AsteriskSettings activeProfile = profile.get(); + if (activeProfile == null) + { + throw new RuntimeException( + "you must call setAsteriskSettings() before getActiveProfile() is called the first time"); + } + + return activeProfile; + } + } diff --git a/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivityImpl.java index 7b3e4f655..6be6cd56d 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivityImpl.java @@ -16,7 +16,6 @@ import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.agi.AgiChannelActivityBlindTransfer; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.asterisk.wrap.events.BridgeEvent; import org.asteriskjava.pbx.internal.asterisk.wrap.events.DialEvent; import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; @@ -148,7 +147,7 @@ public boolean doActivity() throws PBXException String sipHeader = null; if (this._autoAnswer) { - sipHeader = PBXSettingsManager.getActiveProfile().getAutoAnswer(); + sipHeader = PBXFactory.getActiveProfile().getAutoAnswer(); } actualChannelToTransfer.setCurrentActivityAction( new AgiChannelActivityBlindTransfer(this._transferTarget.getFullyQualifiedName(), sipHeader)); diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java index a3bf0f5fb..29348e497 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java @@ -17,7 +17,6 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.Trunk; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SetVarAction; import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; @@ -86,7 +85,7 @@ public boolean doActivity() throws PBXException + " ****************"); //$NON-NLS-1$ DialActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ - final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings profile = PBXFactory.getActiveProfile(); final OriginateResult[] resultChannels = nr.dial(this, this._originating, this._accepting, profile.getManagementContext(), this.toCallerID, this.hideToCallerId, channelVarsToSet); diff --git a/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java index 2508d591c..72bec700a 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java @@ -15,7 +15,6 @@ import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.asterisk.wrap.events.ParkedCallEvent; @@ -92,7 +91,7 @@ public boolean doActivity() throws PBXException try { - final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings profile = PBXFactory.getActiveProfile(); if (!pbx.waitForChannelToQuiescent(this._parkChannel, 3000)) throw new PBXException("Channel: " + this._parkChannel + " cannot be parked as it is still in transition."); diff --git a/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java index 4ffa02b23..36b0c0a31 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java @@ -14,7 +14,6 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHold; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; @@ -179,7 +178,7 @@ public Call getRHSCall() */ private boolean splitTwo() throws PBXException { - final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings profile = PBXFactory.getActiveProfile(); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); if (channel1 == channel2) diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityMeetme.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityMeetme.java index 37b187d0b..56ca01f3b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityMeetme.java +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityMeetme.java @@ -10,7 +10,6 @@ import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; @@ -80,7 +79,7 @@ public void cancel(Channel channel) } hangup = false; - final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings profile = PBXFactory.getActiveProfile(); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); final RedirectAction redirect = new RedirectAction(channel, profile.getManagementContext(), pbx.getExtensionAgi(), diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityQueue.java b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityQueue.java index 355eef767..f751e77a4 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityQueue.java @@ -10,7 +10,6 @@ import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; @@ -70,7 +69,7 @@ public void cancel(Channel channel) } hangup = false; - final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings profile = PBXFactory.getActiveProfile(); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); final RedirectAction redirect = new RedirectAction(channel, profile.getManagementContext(), pbx.getExtensionAgi(), diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index ad1d895c9..f7337fd2a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -78,7 +78,7 @@ private MeetmeRoomControl(PBX pbx, final int roomCount) throws NoMeetmeException { super("MeetmeRoomControl"); //$NON-NLS-1$ this.roomCount = roomCount; - final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings settings = PBXFactory.getActiveProfile(); this.meetmeBaseAddress = settings.getMeetmeBaseAddress(); this.rooms = new MeetmeRoom[roomCount]; this.configure((AsteriskPBX) pbx); diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/PBXSettingsManager.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/PBXSettingsManager.java deleted file mode 100644 index 40a90219f..000000000 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/PBXSettingsManager.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.asteriskjava.pbx.internal.asterisk; - -import java.util.concurrent.atomic.AtomicReference; - -public class PBXSettingsManager -{ - - final static AtomicReference profile = new AtomicReference<>(); - - public static void setAsteriskSettings(AsteriskSettings profile) - { - PBXSettingsManager.profile.set(profile); - - } - - public static AsteriskSettings getActiveProfile() - { - AsteriskSettings activeProfile = profile.get(); - if (activeProfile == null) - { - throw new RuntimeException( - "you must call setAsteriskSettings() before getActiveProfile() is called the first time"); - } - - return activeProfile; - } - -} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 08bb9892a..df18295b3 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -51,7 +51,6 @@ import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoomControl; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.EventGeneratingAction; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.HangupAction; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ManagerAction; @@ -413,7 +412,7 @@ public void transferToMusicOnHold(final Channel channel) throws PBXException public String getManagementContext() { - final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings settings = PBXFactory.getActiveProfile(); return settings.getManagementContext(); } @@ -431,14 +430,14 @@ public void channelHangup(Channel channel, Integer cause, String causeText) public DialPlanExtension getExtensionPark() { - final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings settings = PBXFactory.getActiveProfile(); return this.buildDialPlanExtension(settings.getExtensionPark()); } @Override public EndPoint getExtensionAgi() { - final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings settings = PBXFactory.getActiveProfile(); return this.buildDialPlanExtension(settings.getAgiExtension()); } @@ -781,7 +780,7 @@ public boolean moveChannelToAgi(Channel channel) throws PBXException boolean isInAgi = channel.isInAgi(); if (!isInAgi) { - final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings profile = PBXFactory.getActiveProfile(); channel.setCurrentActivityAction(new AgiChannelActivityHold()); final RedirectAction redirect = new RedirectAction(channel, profile.getManagementContext(), getExtensionAgi(), diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index 474bad93b..f82974308 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -14,7 +14,6 @@ import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; /** * TODO set the channel unique id when registering against an existing channel @@ -793,7 +792,7 @@ public boolean canDetectHangup() { boolean canDetectHangup = true; - AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + AsteriskSettings profile = PBXFactory.getActiveProfile(); final boolean detect = profile.getCanDetectHangup(); if (!this.getEndPoint().isSIP() && !detect) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java index 6651c19ff..92eb04c63 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -22,7 +22,6 @@ import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.EventGeneratingAction; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.GetVarAction; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ListCommandsAction; @@ -364,7 +363,7 @@ public ManagerConnectionState getState() private void configureConnection() throws IOException, AuthenticationFailedException, TimeoutException, IllegalStateException { - final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings profile = PBXFactory.getActiveProfile(); CoherentManagerConnection.managerConnection = CoherentManagerConnection.connector.connect(profile); // After a reconnect we will have duplicate eventQueues and @@ -393,7 +392,7 @@ private void configureConnection() private void checkFeatures() throws IOException, TimeoutException { - final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings profile = PBXFactory.getActiveProfile(); // Determine if the Bridge and Mute events are available. final ListCommandsAction lca = new ListCommandsAction(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java index 573ec88fb..b1285d90f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -19,7 +19,6 @@ import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.GetVarAction; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.OriginateAction; import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; @@ -68,7 +67,7 @@ public void run() logger.info("*********** begin dial local to AGI ****************"); logger.info("*********** " + " ****************"); logger.info("*******************************************************************************"); - final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings settings = PBXFactory.getActiveProfile(); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 6bbc10afa..67f915119 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -15,7 +15,6 @@ import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.GetVarAction; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.OriginateAction; import org.asteriskjava.pbx.internal.asterisk.wrap.events.BridgeEvent; @@ -112,7 +111,7 @@ protected OriginateResult originate(final EndPoint local, final EndPoint target, + " vars " + myVars); //$NON-NLS-1$ ManagerResponse response = null; - final AsteriskSettings settings = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings settings = PBXFactory.getActiveProfile(); final OriginateAction originate = new OriginateAction(); this.originateID = originate.getActionId(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java index f3d2eeaf4..cf0a5efb6 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java @@ -6,8 +6,8 @@ import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.NewChannelListener; +import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.core.ListenerPriority; public class OriginateToExtension extends OriginateBaseClass @@ -33,7 +33,7 @@ public OriginateResult originate(final EndPoint localHandset, final EndPoint tar */ OriginateBaseClass.logger.debug("originate connecting localHandset " + localHandset + " to Extension " //$NON-NLS-1$ //$NON-NLS-2$ + targetExtension + " autoAnswer " + autoAnswer); //$NON-NLS-1$ - final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings profile = PBXFactory.getActiveProfile(); final HashMap myVars = new HashMap<>(1); if (autoAnswer == true) @@ -53,7 +53,7 @@ public OriginateResult originate(final EndPoint localHandset, final EndPoint tar */ OriginateBaseClass.logger.debug("originate connection localHandset " + localHandset + " to Extension " //$NON-NLS-1$ //$NON-NLS-2$ + targetExtension + " autoAnswer " + autoAnswer); //$NON-NLS-1$ - final AsteriskSettings profile = PBXSettingsManager.getActiveProfile(); + final AsteriskSettings profile = PBXFactory.getActiveProfile(); final HashMap myVars = new HashMap<>(1); if (autoAnswer == true) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java index b634672ad..9446789ea 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java @@ -11,7 +11,6 @@ import org.asteriskjava.pbx.internal.agi.AgiChannelActivityDial; import org.asteriskjava.pbx.internal.agi.AgiChannelActivityVoicemail; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.PBXSettingsManager; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class RedirectCall @@ -21,11 +20,12 @@ public class RedirectCall * manager. This is the asterisk coal face. */ static Logger logger = Logger.getLogger(RedirectCall.class); - static public void setAutoAnswer(final HashMap myVars, final AsteriskSettings settings) - { - myVars.put(AsteriskPBX.getSIPADDHeader(false, true), settings.getAutoAnswer()); - RedirectCall.logger.debug("auto answer"); //$NON-NLS-1$ - } + + static public void setAutoAnswer(final HashMap myVars, final AsteriskSettings settings) + { + myVars.put(AsteriskPBX.getSIPADDHeader(false, true), settings.getAutoAnswer()); + RedirectCall.logger.debug("auto answer"); //$NON-NLS-1$ + } public boolean redirect(final Channel channel, final EndPoint targetEndPoint, final String context, final boolean autoAnswer) throws PBXException @@ -37,7 +37,7 @@ public boolean redirect(final Channel channel, final EndPoint targetEndPoint, fi String sipHeader = ""; if (autoAnswer) { - sipHeader = PBXSettingsManager.getActiveProfile().getAutoAnswer(); + sipHeader = PBXFactory.getActiveProfile().getAutoAnswer(); } /* From c8e2500c6775cd1e715c431c48d449d8cf055dfc Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Oct 2016 09:37:59 +1100 Subject: [PATCH 054/802] refactor AsteriskPBX configuration --- .../pbx/internal/core/AsteriskPBX.java | 57 ++++++ .../examples/activities/BlindTransfer.java | 168 +++++++++--------- .../activities/ExamplesAsteriskSettings.java | 92 ++++++++++ 3 files changed, 236 insertions(+), 81 deletions(-) create mode 100644 src/test/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 11d199cbe..ba36eac7b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -51,6 +51,7 @@ import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoomControl; +import org.asteriskjava.pbx.internal.asterisk.wrap.actions.CommandAction; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.EventGeneratingAction; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.HangupAction; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ManagerAction; @@ -58,6 +59,7 @@ import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.asterisk.wrap.events.ResponseEvents; +import org.asteriskjava.pbx.internal.asterisk.wrap.response.CommandResponse; import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.managerAPI.RedirectCall; @@ -836,4 +838,59 @@ public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, Agi return dialer; } + /** + * Creates the set of extensions required to test NJR during the + * installation. The context must already exist in the dialplan. + * + * @param profile + * @param dialContext + * @return + * @throws IllegalStateException + * @throws IOException + * @throws AuthenticationFailedException + * @throws TimeoutException + */ + public String createAgiEntryPoint() throws IOException, AuthenticationFailedException, TimeoutException + { + + try + { + + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + AsteriskSettings profile = PBXFactory.getActiveProfile(); + + String agi = profile.getAgiExtension(); + pbx.addAsteriskExtension(agi, 1, "AGI(agi://127.0.0.1/activityAgi), into " + profile.getManagementContext()); + pbx.addAsteriskExtension(agi, 2, "wait(0.5), into " + profile.getManagementContext()); + pbx.addAsteriskExtension(agi, 3, "goto(" + agi + ",1), into " + profile.getManagementContext()); + + } + catch (Exception e) + { + logger.error(e); + + return e.getLocalizedMessage(); + } + return null; + + } + + public String addAsteriskExtension(String extNumber, int priority, String command) throws Exception + + { + String ext = "dialplan add extension " + extNumber + "," + priority + "," + command; + + CommandAction action = new CommandAction(ext); + CommandResponse response = (CommandResponse) sendAction(action, 30000); + + List line = response.getResult(); + String answer = line.get(0); + String tmp = "Extension '" + extNumber + "," + priority + ","; + if (answer.substring(0, tmp.length()).compareToIgnoreCase(tmp) == 0) + return "OK"; //$NON-NLS-1$ + + throw new Exception("InitiateAction.AddExtentionFailed" + ext); + } + } diff --git a/src/test/java/org/asteriskjava/examples/activities/BlindTransfer.java b/src/test/java/org/asteriskjava/examples/activities/BlindTransfer.java index 502616d13..e6cc244b6 100644 --- a/src/test/java/org/asteriskjava/examples/activities/BlindTransfer.java +++ b/src/test/java/org/asteriskjava/examples/activities/BlindTransfer.java @@ -1,104 +1,110 @@ package org.asteriskjava.examples.activities; +import java.io.IOException; + +import org.asteriskjava.manager.AuthenticationFailedException; +import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.Call.OperandChannel; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.activities.BlindTransferActivity; import org.asteriskjava.pbx.activities.DialActivity; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.TechType; /** * dial somebody and then blind transfer the call to a third party. * * @author bsutton - * */ public class BlindTransfer { - static public void main(String[] args) - { - blindTransfer(); - } - - static private void blindTransfer() - { - PBX pbx = PBXFactory.getActivePBX(); - - // We are going to dial from extension 100 - EndPoint from = pbx.buildEndPoint("100", TechType.SIP); - // The caller ID to show on extension 100. - CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); - - // The caller ID to display on the called parties phone - CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); - // The party we are going to call. - EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); - - // Start the dial and return immediately. - // progress is provided via the ActivityCallback. - pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() - { - @Override - public void start(DialActivity activity) - { - System.out.println("The dial has started"); - // We can stop it progress further by cancelling the dial - // activity.markCancelled(); - } - - @Override - public void progess(DialActivity activity, String message) - { - System.out.println("Dial status: " + message); - } - - @Override - public void completed(DialActivity activity, boolean success) - { - if (success) - { - System.out.println("Dial all good so lets do a blind transfer"); - PBX pbx = PBXFactory.getActivePBX(); - // Call is up - Call call = activity.getNewCall(); - CallerID toCallerID = pbx.buildCallerID("101", "I'm calling you"); - EndPoint transferTarget = pbx.buildEndPoint("101", TechType.SIP); - pbx.blindTransfer(call, OperandChannel.REMOTE_PARTY, transferTarget, toCallerID, false, 30L, - new ActivityCallback() - { - - @Override - public void start(BlindTransferActivity activity) - { - // TODO Auto-generated method stub - - } - - @Override - public void progess(BlindTransferActivity activity, String message) - { - // TODO Auto-generated method stub - - } - - @Override - public void completed(BlindTransferActivity activity, boolean success) - { - // if success the blind transfer completed. - } - }); - } - else - System.out.println("Oops something bad happened when we dialed."); - } - }); - - } + static public void main(String[] args) throws IOException, AuthenticationFailedException, TimeoutException + { + PBXFactory.init(new ExamplesAsteriskSettings()); + AsteriskPBX asteriskPbx = (AsteriskPBX) PBXFactory.getActivePBX(); + asteriskPbx.createAgiEntryPoint(); + blindTransfer(); + } + + static private void blindTransfer() + { + PBX pbx = PBXFactory.getActivePBX(); + + // We are going to dial from extension 100 + EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + // The caller ID to show on extension 100. + CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); + + // The caller ID to display on the called parties phone + CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); + // The party we are going to call. + EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); + + // Start the dial and return immediately. + // progress is provided via the ActivityCallback. + pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() + { + @Override + public void start(DialActivity activity) + { + System.out.println("The dial has started"); + // We can stop it progress further by cancelling the dial + // activity.markCancelled(); + } + + @Override + public void progess(DialActivity activity, String message) + { + System.out.println("Dial status: " + message); + } + + @Override + public void completed(DialActivity activity, boolean success) + { + if (success) + { + System.out.println("Dial all good so lets do a blind transfer"); + PBX pbx = PBXFactory.getActivePBX(); + // Call is up + Call call = activity.getNewCall(); + CallerID toCallerID = pbx.buildCallerID("101", "I'm calling you"); + EndPoint transferTarget = pbx.buildEndPoint("101", TechType.SIP); + pbx.blindTransfer(call, OperandChannel.REMOTE_PARTY, transferTarget, toCallerID, false, 30L, + new ActivityCallback() + { + + @Override + public void start(BlindTransferActivity activity) + { + // TODO Auto-generated method stub + + } + + @Override + public void progess(BlindTransferActivity activity, String message) + { + // TODO Auto-generated method stub + + } + + @Override + public void completed(BlindTransferActivity activity, boolean success) + { + // if success the blind transfer completed. + } + }); + } + else + System.out.println("Oops something bad happened when we dialed."); + } + }); + + } } diff --git a/src/test/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java b/src/test/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java new file mode 100644 index 000000000..7114eda29 --- /dev/null +++ b/src/test/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java @@ -0,0 +1,92 @@ +package org.asteriskjava.examples.activities; + +import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; + +public class ExamplesAsteriskSettings implements AsteriskSettings +{ + + @Override + public int getManagerPortNo() + { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getManagerPassword() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getManagerUsername() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getAsteriskIP() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public Integer getMeetmeBaseAddress() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean getDisableBridge() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public String getManagementContext() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getExtensionPark() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getDialTimeout() + { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getAutoAnswer() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getAgiExtension() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean getCanDetectHangup() + { + // TODO Auto-generated method stub + return false; + } + +} From e4c787b4e76290cf412c31abb80aec8cec37b027 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Oct 2016 09:38:30 +1100 Subject: [PATCH 055/802] moved examples to main --- .../java/org/asteriskjava/examples/activities/BlindTransfer.java | 0 .../java/org/asteriskjava/examples/activities/Dial.java | 0 .../examples/activities/ExamplesAsteriskSettings.java | 0 .../java/org/asteriskjava/examples/activities/Hold.java | 0 .../java/org/asteriskjava/examples/fastagi/ExampleCallIn.java | 0 .../java/org/asteriskjava/examples/fastagi/fastagi.properties | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename src/{test => main}/java/org/asteriskjava/examples/activities/BlindTransfer.java (100%) rename src/{test => main}/java/org/asteriskjava/examples/activities/Dial.java (100%) rename src/{test => main}/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java (100%) rename src/{test => main}/java/org/asteriskjava/examples/activities/Hold.java (100%) rename src/{test => main}/java/org/asteriskjava/examples/fastagi/ExampleCallIn.java (100%) rename src/{test => main}/java/org/asteriskjava/examples/fastagi/fastagi.properties (100%) diff --git a/src/test/java/org/asteriskjava/examples/activities/BlindTransfer.java b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java similarity index 100% rename from src/test/java/org/asteriskjava/examples/activities/BlindTransfer.java rename to src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java diff --git a/src/test/java/org/asteriskjava/examples/activities/Dial.java b/src/main/java/org/asteriskjava/examples/activities/Dial.java similarity index 100% rename from src/test/java/org/asteriskjava/examples/activities/Dial.java rename to src/main/java/org/asteriskjava/examples/activities/Dial.java diff --git a/src/test/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java b/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java similarity index 100% rename from src/test/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java rename to src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java diff --git a/src/test/java/org/asteriskjava/examples/activities/Hold.java b/src/main/java/org/asteriskjava/examples/activities/Hold.java similarity index 100% rename from src/test/java/org/asteriskjava/examples/activities/Hold.java rename to src/main/java/org/asteriskjava/examples/activities/Hold.java diff --git a/src/test/java/org/asteriskjava/examples/fastagi/ExampleCallIn.java b/src/main/java/org/asteriskjava/examples/fastagi/ExampleCallIn.java similarity index 100% rename from src/test/java/org/asteriskjava/examples/fastagi/ExampleCallIn.java rename to src/main/java/org/asteriskjava/examples/fastagi/ExampleCallIn.java diff --git a/src/test/java/org/asteriskjava/examples/fastagi/fastagi.properties b/src/main/java/org/asteriskjava/examples/fastagi/fastagi.properties similarity index 100% rename from src/test/java/org/asteriskjava/examples/fastagi/fastagi.properties rename to src/main/java/org/asteriskjava/examples/fastagi/fastagi.properties From e630b13f25e71fefe45c6c5c0d7830a38ac89746 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Oct 2016 10:06:13 +1100 Subject: [PATCH 056/802] refactored ActivityCallback to be lambda friendly --- .../examples/activities/BlindTransfer.java | 36 +-- .../examples/activities/Dial.java | 186 ++++++------ .../examples/activities/Hold.java | 91 +++--- .../asteriskjava/pbx/ActivityCallback.java | 37 +-- .../asteriskjava/pbx/ActivityStatusEnum.java | 18 ++ .../org/asteriskjava/pbx/CallbackAdaptor.java | 24 -- .../asteriskjava/pbx/CompletionAdaptor.java | 66 ++--- .../pbx/activities/ActivityHelper.java | 274 +++++++++--------- .../pbx/internal/core/AsteriskPBX.java | 15 +- .../internal/core/DialLocalToAgiActivity.java | 3 +- 10 files changed, 346 insertions(+), 404 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/ActivityStatusEnum.java delete mode 100644 src/main/java/org/asteriskjava/pbx/CallbackAdaptor.java diff --git a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java index e6cc244b6..1d3803e28 100644 --- a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java +++ b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java @@ -5,6 +5,7 @@ import org.asteriskjava.manager.AuthenticationFailedException; import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.ActivityStatusEnum; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.Call.OperandChannel; import org.asteriskjava.pbx.CallerID; @@ -50,24 +51,11 @@ static private void blindTransfer() // progress is provided via the ActivityCallback. pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() { - @Override - public void start(DialActivity activity) - { - System.out.println("The dial has started"); - // We can stop it progress further by cancelling the dial - // activity.markCancelled(); - } @Override - public void progess(DialActivity activity, String message) + public void progress(DialActivity activity, ActivityStatusEnum status, String message) { - System.out.println("Dial status: " + message); - } - - @Override - public void completed(DialActivity activity, boolean success) - { - if (success) + if (status == ActivityStatusEnum.SUCCESS) { System.out.println("Dial all good so lets do a blind transfer"); PBX pbx = PBXFactory.getActivePBX(); @@ -80,27 +68,13 @@ public void completed(DialActivity activity, boolean success) { @Override - public void start(BlindTransferActivity activity) - { - // TODO Auto-generated method stub - - } - - @Override - public void progess(BlindTransferActivity activity, String message) - { - // TODO Auto-generated method stub - - } - - @Override - public void completed(BlindTransferActivity activity, boolean success) + public void progress(BlindTransferActivity activity, ActivityStatusEnum status, String message) { // if success the blind transfer completed. } }); } - else + if (status == ActivityStatusEnum.FAILURE) System.out.println("Oops something bad happened when we dialed."); } }); diff --git a/src/main/java/org/asteriskjava/examples/activities/Dial.java b/src/main/java/org/asteriskjava/examples/activities/Dial.java index 53c5d64aa..7667d00bd 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Dial.java +++ b/src/main/java/org/asteriskjava/examples/activities/Dial.java @@ -1,6 +1,7 @@ package org.asteriskjava.examples.activities; import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.ActivityStatusEnum; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.EndPoint; @@ -12,104 +13,91 @@ public class Dial { - static public void main(String[] args) - { - syncDial(); - asyncDial(); - - } - - /** - * Simple synchronous dial. The dial method won't return until the dial starts. - * Using this method will lockup your UI until the dial starts. - * For better control use the async Dial method below. - */ - static private void syncDial() - { - try - { - PBX pbx = PBXFactory.getActivePBX(); - - // We are going to dial from extension 100 - EndPoint from = pbx.buildEndPoint("100", TechType.SIP); - // The caller ID to show on extension 100. - CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); - - // The caller ID to display on the called parties phone - CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); - // The party we are going to call. - EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); - - // Trunk is currently ignored so set to null - // The call is dialed and only returns when the call comes up (it - // doesn't wait for the remote end to answer). - DialActivity dial = pbx.dial(null, from, fromCallerID, to, toCallerID); - - Call call = dial.getNewCall(); - - pbx.hangup(call.getOriginatingParty()); - } - catch (PBXException e) - { - System.out.println(e); - } - } - - static private void asyncDial() - { - PBX pbx = PBXFactory.getActivePBX(); - - // We are going to dial from extension 100 - EndPoint from = pbx.buildEndPoint("100", TechType.SIP); - // The caller ID to show on extension 100. - CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); - - // The caller ID to display on the called parties phone - CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); - // The party we are going to call. - EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); - - // Start the dial and return immediately. - // progress is provided via the ActivityCallback. - pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() - { - @Override - public void start(DialActivity activity) - { - System.out.println("The dial has started"); - // We can stop it progress further by cancelling the dial - // activity.markCancelled(); - } - - @Override - public void progess(DialActivity activity, String message) - { - System.out.println("Dial status: " + message); - } - - @Override - public void completed(DialActivity activity, boolean success) - { - if (success) - { - System.out.println("Dial all good"); - try - { - // Call is up - Call call = activity.getNewCall(); - // So lets just hangup the call - PBXFactory.getActivePBX().hangup(call.getOriginatingParty()); - } - catch (PBXException e) - { - System.out.println(e); - } - } - else - System.out.println("Oops something bad happened when we dialed."); - } - }); - - } + static public void main(String[] args) + { + syncDial(); + asyncDial(); + + } + + /** + * Simple synchronous dial. The dial method won't return until the dial + * starts. Using this method will lockup your UI until the dial starts. For + * better control use the async Dial method below. + */ + static private void syncDial() + { + try + { + PBX pbx = PBXFactory.getActivePBX(); + + // We are going to dial from extension 100 + EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + // The caller ID to show on extension 100. + CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); + + // The caller ID to display on the called parties phone + CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); + // The party we are going to call. + EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); + + // Trunk is currently ignored so set to null + // The call is dialed and only returns when the call comes up (it + // doesn't wait for the remote end to answer). + DialActivity dial = pbx.dial(null, from, fromCallerID, to, toCallerID); + + Call call = dial.getNewCall(); + + pbx.hangup(call.getOriginatingParty()); + } + catch (PBXException e) + { + System.out.println(e); + } + } + + static private void asyncDial() + { + PBX pbx = PBXFactory.getActivePBX(); + + // We are going to dial from extension 100 + EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + // The caller ID to show on extension 100. + CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); + + // The caller ID to display on the called parties phone + CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); + // The party we are going to call. + EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); + + // Start the dial and return immediately. + // progress is provided via the ActivityCallback. + pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() + { + + @Override + public void progress(DialActivity activity, ActivityStatusEnum status, String message) + { + if (status == ActivityStatusEnum.SUCCESS) + { + System.out.println("Dial all good"); + try + { + // Call is up + Call call = activity.getNewCall(); + // So lets just hangup the call + PBXFactory.getActivePBX().hangup(call.getOriginatingParty()); + } + catch (PBXException e) + { + System.out.println(e); + } + } + if (status == ActivityStatusEnum.FAILURE) + System.out.println("Oops something bad happened when we dialed."); + } + }); + + } } diff --git a/src/main/java/org/asteriskjava/examples/activities/Hold.java b/src/main/java/org/asteriskjava/examples/activities/Hold.java index ff66e97b8..21943540e 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Hold.java +++ b/src/main/java/org/asteriskjava/examples/activities/Hold.java @@ -1,6 +1,7 @@ package org.asteriskjava.examples.activities; import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.ActivityStatusEnum; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; @@ -15,68 +16,54 @@ * dial somebody and then put them on hold. * * @author bsutton - * */ public class Hold { - static public void main(String[] args) - { - hold(); - } + static public void main(String[] args) + { + hold(); + } - static private void hold() - { - PBX pbx = PBXFactory.getActivePBX(); + static private void hold() + { + PBX pbx = PBXFactory.getActivePBX(); - // We are going to dial from extension 100 - EndPoint from = pbx.buildEndPoint("100", TechType.SIP); - // The caller ID to show on extension 100. - CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); + // We are going to dial from extension 100 + EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + // The caller ID to show on extension 100. + CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); - // The caller ID to display on the called parties phone - CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); - // The party we are going to call. - EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); + // The caller ID to display on the called parties phone + CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); + // The party we are going to call. + EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); - // Start the dial and return immediately. - // progress is provided via the ActivityCallback. - pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() - { - @Override - public void start(DialActivity activity) - { - System.out.println("The dial has started"); - // We can stop it progress further by cancelling the dial - // activity.markCancelled(); - } + // Start the dial and return immediately. + // progress is provided via the ActivityCallback. + pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() + { - @Override - public void progess(DialActivity activity, String message) - { - System.out.println("Dial status: " + message); - } + @Override + public void progress(DialActivity activity, ActivityStatusEnum status, String message) + { + if (status == ActivityStatusEnum.SUCCESS) + { + System.out.println("Dial all good so lets place them on hold"); + PBX pbx = PBXFactory.getActivePBX(); + // Call is up + Call call = activity.getNewCall(); - @Override - public void completed(DialActivity activity, boolean success) - { - if (success) - { - System.out.println("Dial all good so lets place them on hold"); - PBX pbx = PBXFactory.getActivePBX(); - // Call is up - Call call = activity.getNewCall(); - - // Place the remote party on hold. - HoldActivity hold = pbx.hold(call.getRemoteParty()); - - Channel heldChannel = hold.getChannel(); - } - else - System.out.println("Oops something bad happened when we dialed."); - } - }); + // Place the remote party on hold. + HoldActivity hold = pbx.hold(call.getRemoteParty()); - } + Channel heldChannel = hold.getChannel(); + } + if (status == ActivityStatusEnum.FAILURE) + System.out.println("Oops something bad happened when we dialed."); + } + }); + + } } diff --git a/src/main/java/org/asteriskjava/pbx/ActivityCallback.java b/src/main/java/org/asteriskjava/pbx/ActivityCallback.java index 62286d202..de6627fbc 100644 --- a/src/main/java/org/asteriskjava/pbx/ActivityCallback.java +++ b/src/main/java/org/asteriskjava/pbx/ActivityCallback.java @@ -7,33 +7,18 @@ public interface ActivityCallback { - /** - * Called as soon as the task being tracked is started. - * - * @param activity - * - the activity which is being monitored - */ - void start(T activity); - /** - * Called periodically to indicate progress with the task being tracked. The - * number of progress messages sent is dependant on the task. Some tasks may - * not send any progress messages. - * - * @param activity - * - the activity which is being monitored - * @param message - */ - void progess(T activity, String message); + /** + * Called periodically to indicate progress with the task being tracked. The + * number of progress messages sent is dependant on the task. Every activity + * will see a ActivityStatusEnum.START and either ActivityStatusEnum.SUCCESS + * or ActivityStatusEnum.FAILURE + * + * @param activity - the activity which is being monitored + * @param status TODO + * @param message + */ - /** - * Called when the task being tracked has completed. - * - * @param activity - * - the activity which is being monitored - * @param success - * - true if the activity completed successfully. - */ - void completed(T activity, boolean success); + void progress(T activity, ActivityStatusEnum status, String message); } diff --git a/src/main/java/org/asteriskjava/pbx/ActivityStatusEnum.java b/src/main/java/org/asteriskjava/pbx/ActivityStatusEnum.java new file mode 100644 index 000000000..c4af0a31a --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/ActivityStatusEnum.java @@ -0,0 +1,18 @@ +package org.asteriskjava.pbx; + +public enum ActivityStatusEnum +{ + START("Starting"), PROGRESS("Progress"), SUCCESS("Success"), FAILURE("Failure"); + + String defaultMessage; + + ActivityStatusEnum(String defaultMessage) + { + this.defaultMessage = defaultMessage; + } + + public String getDefaultMessage() + { + return defaultMessage; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/CallbackAdaptor.java b/src/main/java/org/asteriskjava/pbx/CallbackAdaptor.java deleted file mode 100644 index c38e64ce9..000000000 --- a/src/main/java/org/asteriskjava/pbx/CallbackAdaptor.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.asteriskjava.pbx; - -public class CallbackAdaptor implements ActivityCallback -{ - @Override - public void start(final T activity) - { - // NOOP - } - - @Override - public void progess(final T activity, final String message) - { - // NOOP - - } - - @Override - public void completed(final T activity, final boolean success) - { - // NOOP - - } -} diff --git a/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java b/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java index 06dd5320c..b11cf29b5 100644 --- a/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java +++ b/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java @@ -6,45 +6,43 @@ import org.apache.log4j.Logger; /** - * This is a utility class designed to wait for an activity to complete. - * - * When starting an activity for that you want to wait until completion pass - * this class as the iCallback listener and then call waitForCompletion. + * This is a utility class designed to wait for an activity to complete. When + * starting an activity for that you want to wait until completion pass this + * class as the iCallback listener and then call waitForCompletion. * waitForCompletion will not return until the activity completes. * * @author bsutton - * * @param */ -public class CompletionAdaptor extends CallbackAdaptor +public class CompletionAdaptor implements ActivityCallback { - private static final Logger logger = Logger.getLogger(CompletionAdaptor.class); - - CountDownLatch _latch = new CountDownLatch(1); - - @Override - public void completed(final T activity, final boolean success) - { - _latch.countDown(); - } - - public void waitForCompletion(long timeout, TimeUnit unit) - { - // wait until the activity completes - try - { - if (!_latch.await(timeout, unit)) - { - Exception e = new Exception("Timeout waiting for activity to complete (" + timeout + " " + unit + ")"); - logger.error(e, e); - } - } - catch (final InterruptedException e) - { - // should never happen - CompletionAdaptor.logger.error(e, e); - } - - } + private static final Logger logger = Logger.getLogger(CompletionAdaptor.class); + + CountDownLatch _latch = new CountDownLatch(1); + + @Override + public void progress(final T activity, ActivityStatusEnum status, String message) + { + _latch.countDown(); + } + + public void waitForCompletion(long timeout, TimeUnit unit) + { + // wait until the activity completes + try + { + if (!_latch.await(timeout, unit)) + { + Exception e = new Exception("Timeout waiting for activity to complete (" + timeout + " " + unit + ")"); + logger.error(e, e); + } + } + catch (final InterruptedException e) + { + // should never happen + CompletionAdaptor.logger.error(e, e); + } + + } } diff --git a/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java b/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java index 27aec8bf1..b4a01fa3e 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java +++ b/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java @@ -3,6 +3,7 @@ import org.apache.log4j.Logger; import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.ActivityStatusEnum; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; @@ -13,141 +14,142 @@ public abstract class ActivityHelper extends EventListenerBaseClass implements Runnable, Activity { - static private Logger logger = Logger.getLogger(ActivityHelper.class); - - /** - * If the activity fails due to an exception then lastException will contain - * the final exception that was thrown. - */ - private PBXException lastException; - - /** - * Set to true once the activity succeeds. - */ - private volatile boolean _success = false; - - private final ActivityCallback callback; - - private final String activityName; - - private boolean _sendEvents; - - Exception callSite = new Exception("Invoked from here"); - - public ActivityHelper(final String activityName, final ActivityCallback callback) - { - super(activityName); - this.callback = callback; - this.activityName = activityName; - } - - @SuppressWarnings("unchecked") - public void startActivity(final boolean sendEvents) - { - this._sendEvents = sendEvents; - if (this.callback != null) - { - this.callback.start((T) this); - } - - final Thread thread = new Thread(this, this.activityName); - thread.setDaemon(true); - thread.start(); - - } - - @Override - @SuppressWarnings("unchecked") - public void run() - { - try (EventListenerBaseClass.AutoClose closer = new EventListenerBaseClass.AutoClose(this, this._sendEvents)) - { - this._success = this.doActivity(); - } - catch (final PBXException e) - { - this.lastException = e; - ActivityHelper.logger.error(e, e); - logger.error(callSite, callSite); - } - catch (final Throwable e) - { - this.lastException = new PBXException(e); - ActivityHelper.logger.error(callSite, callSite); - logger.error(e, e); - } - finally - { - if (this.callback != null) - { - if (this._success) - { - this.callback.completed((T) this, true); - } - else - { - // This went badly so make certain we hang everything up - this.callback.completed((T) this, false); - } - } - } - - } - - abstract protected boolean doActivity() throws PBXException; - - /* - * Attempt to set a variable on the channel to see if it's up. - * - * @param channel the channel which is to be tested. - */ - public boolean validateChannel(final Channel channel) - { - - boolean ret = false; - final SetVarAction var = new SetVarAction(channel, "testState", "1"); //$NON-NLS-1$ //$NON-NLS-2$ - - ManagerResponse response = null; - try - { - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - response = pbx.sendAction(var, 500); - } - catch (final Exception e) - { - ActivityHelper.logger.debug(e, e); - ActivityHelper.logger.error("getVariable: " + e); //$NON-NLS-1$ - } - if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) //$NON-NLS-1$ //$NON-NLS-2$ - { - ret = true; - } - - return ret; - - } - - @Override - public boolean isSuccess() - { - return this._success; - } - - protected void setLastException(final PBXException e) - { - this.lastException = e; - } - - @Override - public Throwable getLastException() - { - return this.lastException; - } - - public void progess(final T activity, final String message) - { - this.callback.progess(activity, message); - - } + static private Logger logger = Logger.getLogger(ActivityHelper.class); + + /** + * If the activity fails due to an exception then lastException will contain + * the final exception that was thrown. + */ + private PBXException lastException; + + /** + * Set to true once the activity succeeds. + */ + private volatile boolean _success = false; + + private final ActivityCallback callback; + + private final String activityName; + + private boolean _sendEvents; + + Exception callSite = new Exception("Invoked from here"); + + public ActivityHelper(final String activityName, final ActivityCallback callback) + { + super(activityName); + this.callback = callback; + this.activityName = activityName; + } + + @SuppressWarnings("unchecked") + public void startActivity(final boolean sendEvents) + { + this._sendEvents = sendEvents; + if (this.callback != null) + { + this.callback.progress((T) this, ActivityStatusEnum.START, ActivityStatusEnum.START.getDefaultMessage()); + } + + final Thread thread = new Thread(this, this.activityName); + thread.setDaemon(true); + thread.start(); + + } + + @Override + @SuppressWarnings("unchecked") + public void run() + { + try (EventListenerBaseClass.AutoClose closer = new EventListenerBaseClass.AutoClose(this, this._sendEvents)) + { + this._success = this.doActivity(); + } + catch (final PBXException e) + { + this.lastException = e; + ActivityHelper.logger.error(e, e); + logger.error(callSite, callSite); + } + catch (final Throwable e) + { + this.lastException = new PBXException(e); + ActivityHelper.logger.error(callSite, callSite); + logger.error(e, e); + } + finally + { + if (this.callback != null) + { + if (this._success) + { + this.callback.progress((T) this, ActivityStatusEnum.SUCCESS, + ActivityStatusEnum.SUCCESS.getDefaultMessage()); + } + else + { + // This went badly so make certain we hang everything up + this.callback.progress((T) this, ActivityStatusEnum.FAILURE, + ActivityStatusEnum.FAILURE.getDefaultMessage()); + } + } + } + + } + + abstract protected boolean doActivity() throws PBXException; + + /* + * Attempt to set a variable on the channel to see if it's up. + * @param channel the channel which is to be tested. + */ + public boolean validateChannel(final Channel channel) + { + + boolean ret = false; + final SetVarAction var = new SetVarAction(channel, "testState", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + + ManagerResponse response = null; + try + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + response = pbx.sendAction(var, 500); + } + catch (final Exception e) + { + ActivityHelper.logger.debug(e, e); + ActivityHelper.logger.error("getVariable: " + e); //$NON-NLS-1$ + } + if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) //$NON-NLS-1$ //$NON-NLS-2$ + { + ret = true; + } + + return ret; + + } + + @Override + public boolean isSuccess() + { + return this._success; + } + + protected void setLastException(final PBXException e) + { + this.lastException = e; + } + + @Override + public Throwable getLastException() + { + return this.lastException; + } + + public void progess(final T activity, final String message) + { + this.callback.progress(activity, ActivityStatusEnum.PROGRESS, message); + + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index ba36eac7b..50f4bcaa6 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -15,6 +15,7 @@ import org.asteriskjava.manager.event.AbstractChannelEvent; import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.ActivityStatusEnum; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.Call.OperandChannel; import org.asteriskjava.pbx.CallDirection; @@ -833,7 +834,19 @@ public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, Agi final DialToAgiActivityImpl dialer = new DialToAgiActivityImpl(endPoint, callerID, false, completion, null, action); completion.waitForCompletion(3, TimeUnit.MINUTES); - iCallback.completed(dialer, dialer.isSuccess()); + + final ActivityStatusEnum status; + + if (dialer.isSuccess()) + { + status = ActivityStatusEnum.SUCCESS; + } + else + { + status = ActivityStatusEnum.FAILURE; + } + + iCallback.progress(dialer, status, status.getDefaultMessage()); return dialer; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java index b1285d90f..8eb02e8c4 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -12,6 +12,7 @@ import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.ActivityStatusEnum; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; @@ -94,7 +95,7 @@ public void run() { pbx.sendAction(originate, 30000); latch.await(30, TimeUnit.SECONDS); - callback.completed(this, true); + callback.progress(this, ActivityStatusEnum.SUCCESS, ActivityStatusEnum.SUCCESS.getDefaultMessage()); } catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) From 1e3de12b7c3b5b242dff9ccd6e5341ee8ffc18b3 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Oct 2016 12:29:56 +1100 Subject: [PATCH 057/802] refactor ActivityHelper so it doesn't extend AutoCloseable --- .../examples/activities/BlindTransfer.java | 6 +- .../examples/activities/Dial.java | 8 +- .../examples/activities/Hold.java | 4 +- .../pbx/ChannelHangupListener.java | 6 +- .../asteriskjava/pbx/CompletionAdaptor.java | 5 +- src/main/java/org/asteriskjava/pbx/PBX.java | 36 +- src/main/java/org/asteriskjava/pbx/Trunk.java | 3 +- .../pbx/activities/ActivityHelper.java | 58 +- .../pbx/activities/DialActivityImpl.java | 13 +- .../pbx/activities/ParkActivityImpl.java | 2 +- .../wrap/events/OriginateResponseEvent.java | 2 +- .../asterisk/wrap/events/PeerEntryEvent.java | 2 +- .../pbx/internal/core/AsteriskPBX.java | 61 +- .../pbx/internal/core/ChannelProxy.java | 710 +++++++++--------- .../pbx/internal/core/EndPointImpl.java | 484 ++++++------ 15 files changed, 754 insertions(+), 646 deletions(-) diff --git a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java index 1d3803e28..47945fa74 100644 --- a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java +++ b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java @@ -38,7 +38,7 @@ static private void blindTransfer() PBX pbx = PBXFactory.getActivePBX(); // We are going to dial from extension 100 - EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + EndPoint from = pbx.buildEndPoint(TechType.SIP, "100"); // The caller ID to show on extension 100. CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); @@ -49,7 +49,7 @@ static private void blindTransfer() // Start the dial and return immediately. // progress is provided via the ActivityCallback. - pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() + pbx.dial(from, fromCallerID, to, toCallerID, new ActivityCallback() { @Override @@ -62,7 +62,7 @@ public void progress(DialActivity activity, ActivityStatusEnum status, String me // Call is up Call call = activity.getNewCall(); CallerID toCallerID = pbx.buildCallerID("101", "I'm calling you"); - EndPoint transferTarget = pbx.buildEndPoint("101", TechType.SIP); + EndPoint transferTarget = pbx.buildEndPoint(TechType.SIP, "101"); pbx.blindTransfer(call, OperandChannel.REMOTE_PARTY, transferTarget, toCallerID, false, 30L, new ActivityCallback() { diff --git a/src/main/java/org/asteriskjava/examples/activities/Dial.java b/src/main/java/org/asteriskjava/examples/activities/Dial.java index 7667d00bd..b6393bf7c 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Dial.java +++ b/src/main/java/org/asteriskjava/examples/activities/Dial.java @@ -32,7 +32,7 @@ static private void syncDial() PBX pbx = PBXFactory.getActivePBX(); // We are going to dial from extension 100 - EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + EndPoint from = pbx.buildEndPoint(TechType.SIP, "100"); // The caller ID to show on extension 100. CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); @@ -61,18 +61,18 @@ static private void asyncDial() PBX pbx = PBXFactory.getActivePBX(); // We are going to dial from extension 100 - EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + EndPoint from = pbx.buildEndPoint(TechType.SIP, "100"); // The caller ID to show on extension 100. CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); // The caller ID to display on the called parties phone CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); // The party we are going to call. - EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); + EndPoint to = pbx.buildEndPoint(TechType.SIP, pbx.buildTrunk("default"), "5551234"); // Start the dial and return immediately. // progress is provided via the ActivityCallback. - pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() + pbx.dial(from, fromCallerID, to, toCallerID, new ActivityCallback() { @Override diff --git a/src/main/java/org/asteriskjava/examples/activities/Hold.java b/src/main/java/org/asteriskjava/examples/activities/Hold.java index 21943540e..dce9f2a46 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Hold.java +++ b/src/main/java/org/asteriskjava/examples/activities/Hold.java @@ -30,7 +30,7 @@ static private void hold() PBX pbx = PBXFactory.getActivePBX(); // We are going to dial from extension 100 - EndPoint from = pbx.buildEndPoint("100", TechType.SIP); + EndPoint from = pbx.buildEndPoint(TechType.SIP, "100"); // The caller ID to show on extension 100. CallerID fromCallerID = pbx.buildCallerID("100", "My Phone"); @@ -41,7 +41,7 @@ static private void hold() // Start the dial and return immediately. // progress is provided via the ActivityCallback. - pbx.dial(null, from, fromCallerID, to, toCallerID, new ActivityCallback() + pbx.dial(from, fromCallerID, to, toCallerID, new ActivityCallback() { @Override diff --git a/src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java b/src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java index ad180faa0..9f0abc4f1 100644 --- a/src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java +++ b/src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java @@ -4,10 +4,10 @@ * Used to notify channel listeners of state changes to a channel. * * @author bsutton - * */ public interface ChannelHangupListener { - // Called by the channel when it is being hungup - void channelHangup(Channel channel, Integer cause, String causeText); + // Called by the channel when it is being hungup + void channelHangup(Channel channel, Integer cause, String causeText); + } diff --git a/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java b/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java index b11cf29b5..f17271d68 100644 --- a/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java +++ b/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java @@ -23,7 +23,10 @@ public class CompletionAdaptor implements ActivityCallback callback); + void blindTransfer(Call call, OperandChannel channelToTransfer, final EndPoint transferTarget, final CallerID toCallerID, + boolean autoAnswer, long timeout, ActivityCallback callback); /** * Sends a DTMF tone to given channel. Not returning until the tone has been @@ -108,11 +109,9 @@ BlindTransferActivity blindTransfer(Call call, OperandChannel channelToTransfer, * until the call has been dialled. The dial will return as soon as the * trunk comes up, it does not wait for remote end to answer. * - * @param trunk - the trunk to dial out on. If null the default trunk will - * be used. * @return Call the call resulting from dialing the number. */ - DialActivity dial(Trunk trunk, EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID, + void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID, ActivityCallback callback); /** @@ -177,7 +176,7 @@ DialActivity dial(Trunk trunk, EndPoint from, CallerID fromCallerID, EndPoint to * @param parkChannel - the channel which is going to be redirect to the * njr-park extension. */ - ParkActivity park(Call call, Channel parkChannel, ActivityCallback callback); + void park(Call call, Channel parkChannel, ActivityCallback callback); /** * Sends a DTMF tone to given channel. Not returning until the tone has been @@ -198,16 +197,14 @@ DialActivity dial(Trunk trunk, EndPoint from, CallerID fromCallerID, EndPoint to */ void sendDTMF(Channel channel, DTMFTone tone, ActivityCallback callback); - - /** - * Splits a call (with two channels) - * - * This call returns once the split action has completed. + /** + * Splits a call (with two channels) This call returns once the split action + * has completed. */ - + public SplitActivity split(final Call callToSplit, final ActivityCallback listener) throws PBXException; - public SplitActivity split(final Call callToSplit) throws PBXException; + public void split(final Call callToSplit) throws PBXException; /** * Joins two calls not returning until the join completes. Each call must @@ -216,7 +213,7 @@ DialActivity dial(Trunk trunk, EndPoint from, CallerID fromCallerID, EndPoint to public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, CallDirection direction); - public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, + public void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, CallDirection direction, ActivityCallback listener); /** @@ -258,7 +255,9 @@ public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, * @param endPointName * @return */ - EndPoint buildEndPoint(String endPointName, TechType defaultTech); + EndPoint buildEndPoint(TechType defaultTech, String endPointName); + + EndPoint buildEndPoint(TechType tech, Trunk trunk, String endPointName); void transferToMusicOnHold(Channel channel) throws PBXException; @@ -272,5 +271,6 @@ public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, public boolean waitForChannelToQuiescent(Channel channel, int timeout); - + public Trunk buildTrunk(String string); + } diff --git a/src/main/java/org/asteriskjava/pbx/Trunk.java b/src/main/java/org/asteriskjava/pbx/Trunk.java index f2f475f9d..981591102 100644 --- a/src/main/java/org/asteriskjava/pbx/Trunk.java +++ b/src/main/java/org/asteriskjava/pbx/Trunk.java @@ -2,9 +2,8 @@ /** * Provides an abstraction of a trunk * @author bsutton - * */ public interface Trunk { - // TODO: implement + String getTrunkAsString(); } diff --git a/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java b/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java index b4a01fa3e..34003cd12 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java +++ b/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java @@ -1,5 +1,8 @@ package org.asteriskjava.pbx.activities; +import java.util.HashSet; +import java.util.Set; + import org.apache.log4j.Logger; import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.ActivityCallback; @@ -8,11 +11,13 @@ import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SetVarAction; +import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ListenerPriority; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; -public abstract class ActivityHelper extends EventListenerBaseClass implements Runnable, Activity +public abstract class ActivityHelper implements Runnable, Activity { static private Logger logger = Logger.getLogger(ActivityHelper.class); @@ -37,11 +42,52 @@ public abstract class ActivityHelper extends EventListenerBa public ActivityHelper(final String activityName, final ActivityCallback callback) { - super(activityName); + this.callback = callback; this.activityName = activityName; } + private AutoCloseable getManagerListener() + { + if (!_sendEvents) + { + return new AutoCloseable() + { + + @Override + public void close() throws Exception + { + // do nothing, we never started anything + } + }; + } + EventListenerBaseClass listener = new EventListenerBaseClass(activityName) + { + + @Override + public Set> requiredEvents() + { + return ActivityHelper.this.requiredEvents(); + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + ActivityHelper.this.onManagerEvent(event); + + } + + @Override + public ListenerPriority getPriority() + { + return ActivityHelper.this.getPriority(); + } + }; + listener.startListener(PBXFactory.getActivePBX()); + return listener; + + } + @SuppressWarnings("unchecked") public void startActivity(final boolean sendEvents) { @@ -61,7 +107,7 @@ public void startActivity(final boolean sendEvents) @SuppressWarnings("unchecked") public void run() { - try (EventListenerBaseClass.AutoClose closer = new EventListenerBaseClass.AutoClose(this, this._sendEvents)) + try (AutoCloseable closer = getManagerListener()) { this._success = this.doActivity(); } @@ -152,4 +198,10 @@ public void progess(final T activity, final String message) } + abstract HashSet> requiredEvents(); + + abstract void onManagerEvent(final ManagerEvent event); + + abstract public ListenerPriority getPriority(); + } diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java index 5efe3523b..5b790aa35 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java @@ -15,7 +15,6 @@ import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.Trunk; import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SetVarAction; import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; @@ -33,9 +32,6 @@ public class DialActivityImpl extends ActivityHelper implements Di private boolean cancelledByOperator; - @SuppressWarnings("unused") - private final Trunk trunk; - private final EndPoint _originating; /** @@ -56,12 +52,11 @@ public class DialActivityImpl extends ActivityHelper implements Di private Map channelVarsToSet; - public DialActivityImpl(final Trunk trunk, final EndPoint originating, final EndPoint accepting, - final CallerID toCallerID, final boolean hideToCallerID, final ActivityCallback listener, + public DialActivityImpl(final EndPoint originating, final EndPoint accepting, final CallerID toCallerID, + final boolean hideToCallerID, final ActivityCallback listener, Map channelVarsToSet) { super("Dial", listener); //$NON-NLS-1$ - this.trunk = trunk; this._originating = originating; this._accepting = accepting; this.toCallerID = toCallerID; @@ -156,8 +151,8 @@ private void hangup() } /** - * Called to cancels the dial before it fully comes up. The caller must - * also hangup the associated channels. + * Called to cancels the dial before it fully comes up. The caller must also + * hangup the associated channels. */ @Override public void markCancelled() diff --git a/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java index 72bec700a..5bc48071c 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java @@ -172,7 +172,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) final ParkedCallEvent parkedEvent = (ParkedCallEvent) event; final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - this._parkingLot = pbx.buildEndPoint(parkedEvent.getExten(), TechType.LOCAL); + this._parkingLot = pbx.buildEndPoint(TechType.LOCAL, parkedEvent.getExten()); this._latch.countDown(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/OriginateResponseEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/OriginateResponseEvent.java index 45d273fe2..2f720fef1 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/OriginateResponseEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/OriginateResponseEvent.java @@ -46,7 +46,7 @@ public OriginateResponseEvent(final org.asteriskjava.manager.event.OriginateResp } else { - this.endPoint = pbx.buildEndPoint(event.getChannel(), TechType.SIP); + this.endPoint = pbx.buildEndPoint(TechType.SIP, event.getChannel()); this.channel = null; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerEntryEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerEntryEvent.java index dcf86e3e2..250a710af 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerEntryEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerEntryEvent.java @@ -20,7 +20,7 @@ public PeerEntryEvent(final org.asteriskjava.manager.event.PeerEntryEvent event) super(event); PBX pbx = PBXFactory.getActivePBX(); - this.peer = pbx.buildEndPoint(event.getObjectName(), TechType.valueOf(event.getChannelType())); + this.peer = pbx.buildEndPoint(TechType.valueOf(event.getChannelType()), event.getObjectName()); } public EndPoint getPeer() diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 50f4bcaa6..060733e3c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -138,11 +138,10 @@ public BlindTransferActivity blindTransfer(Call call, Call.OperandChannel channe } @Override - public BlindTransferActivity blindTransfer(Call call, Call.OperandChannel channelToTransfer, EndPoint transferTarget, - CallerID toCallerID, boolean autoAnswer, long timeout, ActivityCallback listener) + public void blindTransfer(Call call, Call.OperandChannel channelToTransfer, EndPoint transferTarget, CallerID toCallerID, + boolean autoAnswer, long timeout, ActivityCallback listener) { - return new BlindTransferActivityImpl(call, channelToTransfer, transferTarget, toCallerID, autoAnswer, timeout, - listener); + new BlindTransferActivityImpl(call, channelToTransfer, transferTarget, toCallerID, autoAnswer, timeout, listener); } @@ -174,7 +173,7 @@ public BridgeActivity bridge(final Channel lhsChannel, final Channel rhsChannel) } @Override - public SplitActivity split(final Call callToSplit) throws PBXException + public void split(final Call callToSplit) throws PBXException { final CompletionAdaptor completion = new CompletionAdaptor<>(); @@ -182,7 +181,6 @@ public SplitActivity split(final Call callToSplit) throws PBXException completion.waitForCompletion(10, TimeUnit.SECONDS); - return split; } @Override @@ -218,13 +216,11 @@ public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, * channels. Each call must only have one active channel */ @Override - public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, + public void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, CallDirection direction, ActivityCallback listener) { - final JoinActivityImpl join = new JoinActivityImpl(lhs, originatingOperand, rhs, acceptingOperand, direction, - listener); + new JoinActivityImpl(lhs, originatingOperand, rhs, acceptingOperand, direction, listener); - return join; } @Override @@ -248,7 +244,7 @@ public DialActivity dial(final Trunk trunk, final EndPoint from, final CallerID { final CompletionAdaptor completion = new CompletionAdaptor<>(); - final DialActivityImpl dialer = new DialActivityImpl(trunk, from, to, toCallerID, false, completion, null); + final DialActivityImpl dialer = new DialActivityImpl(from, to, toCallerID, false, completion, null); completion.waitForCompletion(3, TimeUnit.MINUTES); @@ -264,16 +260,16 @@ public DialLocalToAgiActivity dialLocalToAgi(final EndPoint from, final CallerID public DialActivity dial(final Trunk trunk, final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID, final ActivityCallback callback, Map channelVarsToSet) { - final DialActivityImpl dialer = new DialActivityImpl(trunk, from, to, toCallerID, false, callback, channelVarsToSet); + final DialActivityImpl dialer = new DialActivityImpl(from, to, toCallerID, false, callback, channelVarsToSet); return dialer; } @Override - public DialActivity dial(final Trunk trunk, final EndPoint from, final CallerID fromCallerID, final EndPoint to, - final CallerID toCallerID, final ActivityCallback callback) + public void dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID, + final ActivityCallback callback) { - final DialActivityImpl dialer = new DialActivityImpl(trunk, from, to, toCallerID, false, callback, null); - return dialer; + new DialActivityImpl(from, to, toCallerID, false, callback, null); + } @Override @@ -349,10 +345,10 @@ public ParkActivity park(final Call call, final Channel parkChannel) } @Override - public ParkActivity park(final Call call, final Channel parkChannel, final ActivityCallback callback) + public void park(final Call call, final Channel parkChannel, final ActivityCallback callback) { - final ParkActivity activity = new ParkActivityImpl(call, parkChannel, callback); - return activity; + new ParkActivityImpl(call, parkChannel, callback); + } @Override @@ -443,7 +439,7 @@ public EndPoint buildEndPoint(final String fullyQualifiedEndPoint) * have a tech specified then the defaultTech is used. */ @Override - public EndPoint buildEndPoint(final String endPointName, final TechType defaultTech) + public EndPoint buildEndPoint(final TechType defaultTech, final String endPointName) { EndPoint endPoint = null; try @@ -451,7 +447,7 @@ public EndPoint buildEndPoint(final String endPointName, final TechType defaultT if (endPointName == null || endPointName.trim().length() == 0) endPoint = new EndPointImpl(); else - endPoint = new EndPointImpl(endPointName, defaultTech); + endPoint = new EndPointImpl(defaultTech, endPointName); } catch (final IllegalArgumentException e) { @@ -461,6 +457,13 @@ public EndPoint buildEndPoint(final String endPointName, final TechType defaultT } + @Override + public EndPoint buildEndPoint(final TechType defaultTech, final Trunk trunk, final String endPointName) + { + return new EndPointImpl(defaultTech, trunk, endPointName); + + } + /** * Builds an end point from an end point name. If the endpoint name doesn't * have a tech specified then the defaultTech is used. @@ -901,9 +904,23 @@ public String addAsteriskExtension(String extNumber, int priority, String comman String answer = line.get(0); String tmp = "Extension '" + extNumber + "," + priority + ","; if (answer.substring(0, tmp.length()).compareToIgnoreCase(tmp) == 0) - return "OK"; //$NON-NLS-1$ + return "OK"; throw new Exception("InitiateAction.AddExtentionFailed" + ext); } + @Override + public Trunk buildTrunk(final String trunk) + { + return new Trunk() + { + + @Override + public String getTrunkAsString() + { + return trunk; + } + }; + } + } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index c547d0dc2..4aae04dd2 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -29,361 +29,359 @@ public class ChannelProxy implements Channel, ChannelHangupListener { - private static final Logger logger = Logger.getLogger(ChannelProxy.class); - - /** - * We give each proxy a unique identity to help track them when debugging. - */ - private static final AtomicInteger _nextIdentity = new AtomicInteger(); - - private int _identity = _nextIdentity.incrementAndGet(); - - private ChannelImpl _channel; - - private List listeners = new CopyOnWriteArrayList<>(); - - public ChannelProxy(ChannelImpl channel) - { - this._channel = channel; - currentActivityAction.set(new AgiChannelActivityHold()); - - channel.addHangupListener(this); - - } - - /** - * returns the current channel - * - * @return - */ - public Channel getChannel() - { - return this._channel; - } - - @Override - public boolean isSame(Channel rhs) - { - return this._channel.isSame(rhs); - } - - @Override - public boolean isSame(String extendedChannelName, String uniqueID) - { - return this._channel.isSame(extendedChannelName, uniqueID); - } - - public boolean sameUniqueID(String uniqueID) - { - return this._channel.sameUniqueID(uniqueID); - } - - @Override - public boolean sameEndPoint(Channel rhs) - { - return this._channel.sameEndPoint(rhs); - } - - @Override - public boolean sameEndPoint(EndPoint extensionRoaming) - { - return this._channel.sameEndPoint(extensionRoaming); - } - - @Override - public boolean sameExtenededChannelName(String channelName) - { - return this._channel.sameExtenededChannelName(channelName); - } - - @Override - public void setParked(boolean parked) - { - this._channel.setParked(parked); - } - - @Override - public void setMute(boolean muteState) - { - this._channel.setMute(muteState); - - } - - @Override - public long getChannelId() - { - return this._channel.getChannelId(); - } - - @Override - public boolean isLive() - { - return this._channel.isLive(); - } - - @Override - public void addHangupListener(ChannelHangupListener listener) - { - this.listeners.add(listener); - - } - - @Override - public void removeListener(ChannelHangupListener listener) - { - this.listeners.remove(listener); - - } - - @Override - public boolean isConnectedTo(EndPoint endPoint) - { - return this._channel.isConnectedTo(endPoint); - } - - @Override - public String getChannelName() - { - return this._channel.getChannelName(); - } - - @Override - public EndPoint getEndPoint() - { - return this._channel.getEndPoint(); - } - - @Override - public boolean isMute() - { - return this._channel.isMute(); - } - - @Override - public boolean isLocal() - { - return this._channel.isLocal(); - } - - @Override - public boolean isZombie() - { - return this._channel.isZombie(); - } - - @Override - public boolean isConsole() - { - return this._channel.isConsole(); - } - - @Override - public CallerID getCallerID() - { - return this._channel.getCallerID(); - } - - @Override - public void rename(String newName) throws InvalidChannelName - { - this._channel.rename(newName); - } - - @Override - public boolean isParked() - { - return this._channel.isParked(); - } - - /** - * Used to handle a MasqueradeEvent. We essentially swap the two underlying - * channels between the two proxies. - * - * @param cloneProxy - * @throws InvalidChannelName - */ - public void masquerade(ChannelProxy cloneProxy) throws InvalidChannelName - { - ChannelImpl originalChannel = this._channel; - ChannelImpl cloneChannel = cloneProxy._channel; - - cloneChannel.masquerade(this._channel); - - // detach the hangup listeners - originalChannel.removeListener(this); - cloneChannel.removeListener(cloneProxy); - - // Now we swap the channels. - this._channel = cloneChannel; - cloneProxy._channel = originalChannel; - - // Now re-attach the hangup listeners - this._channel.addHangupListener(this); - cloneProxy._channel.addHangupListener(cloneProxy); - - logger.info("Channel proxy now points to " + this._channel); - } - - public ChannelImpl getRealChannel() - { - return this._channel; - } - - @Override - public String getExtendedChannelName() - { - return this._channel.getExtendedChannelName(); - } - - @Override - public void notifyHangupListeners(Integer cause, String causeText) - { - for (ChannelHangupListener listener : this.listeners) - { - listener.channelHangup(this, cause, causeText); - } - - } - - @Override - public String toString() - { - return "(proxy=" + this._identity + ") " + this._channel.toString(); //$NON-NLS-1$ //$NON-NLS-2$ - } - - @Override - public void channelHangup(Channel channel, Integer cause, String causeText) - { - // When the underlying channel hangs up we need to notify all of the - // proxy listeners. - if (channel == this._channel) - notifyHangupListeners(cause, causeText); - - } - - @Override - public boolean canDetectHangup() - { - return this._channel.canDetectHangup(); - } - - @Override - public boolean isQuiescent() - { - return this._channel.isQuiescent(); - } - - @Override - public boolean hasCallerID() - { - return this._channel.hasCallerID(); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + _identity; - return result; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof ChannelProxy)) - { - return false; - } - ChannelProxy other = (ChannelProxy) obj; - if (_identity != other._identity) - { - return false; - } - return true; - } - - private AtomicReference currentActivityAction = new AtomicReference<>(); - volatile private boolean isInAgi; - - @Override - public AgiChannelActivityAction getCurrentActivityAction() - { - return currentActivityAction.get(); - } - - @Override - public void setCurrentActivityAction(AgiChannelActivityAction action) - { - AgiChannelActivityAction previousAction = currentActivityAction.get(); - - logger.info("Setting action to " + action.getClass().getSimpleName() + " for " + this); - - // Exception e = new Exception("Setting action to " + - // action.getClass().getSimpleName() + " for " + this); - // logger.warn(e, e); - - currentActivityAction.set(action); - if (previousAction != null) - { - // when we cancel the previous action, the new one will be invoked - previousAction.cancel(this); - } - } - - @Override - public void setIsInAgi(boolean b) - { - if (b) - { - hasReachedAgi.countDown(); - } - isInAgi = b; - logger.info("Setting is in agi to " + b + " for channel " + this); - - } - - @Override - public boolean isInAgi() - { - return isInAgi; - } - - final CountDownLatch hasReachedAgi = new CountDownLatch(1); - - @Override - public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException - { - return hasReachedAgi.await(timeout, timeunit); - } - - @Override - public String getUniqueId() - { - return _channel.getUniqueId(); - } - - public int getIdentity() - { - return _identity; - } + private static final Logger logger = Logger.getLogger(ChannelProxy.class); + + /** + * We give each proxy a unique identity to help track them when debugging. + */ + private static final AtomicInteger _nextIdentity = new AtomicInteger(); + + private int _identity = _nextIdentity.incrementAndGet(); + + private ChannelImpl _channel; + + private List listeners = new CopyOnWriteArrayList<>(); + + public ChannelProxy(ChannelImpl channel) + { + this._channel = channel; + currentActivityAction.set(new AgiChannelActivityHold()); + + channel.addHangupListener(this); + + } + + /** + * returns the current channel + * + * @return + */ + public Channel getChannel() + { + return this._channel; + } + + @Override + public boolean isSame(Channel rhs) + { + return this._channel.isSame(rhs); + } + + @Override + public boolean isSame(String extendedChannelName, String uniqueID) + { + return this._channel.isSame(extendedChannelName, uniqueID); + } + + public boolean sameUniqueID(String uniqueID) + { + return this._channel.sameUniqueID(uniqueID); + } + + @Override + public boolean sameEndPoint(Channel rhs) + { + return this._channel.sameEndPoint(rhs); + } + + @Override + public boolean sameEndPoint(EndPoint extensionRoaming) + { + return this._channel.sameEndPoint(extensionRoaming); + } + + @Override + public boolean sameExtenededChannelName(String channelName) + { + return this._channel.sameExtenededChannelName(channelName); + } + + @Override + public void setParked(boolean parked) + { + this._channel.setParked(parked); + } + + @Override + public void setMute(boolean muteState) + { + this._channel.setMute(muteState); + + } + + @Override + public long getChannelId() + { + return this._channel.getChannelId(); + } + + @Override + public boolean isLive() + { + return this._channel.isLive(); + } + + @Override + public void addHangupListener(ChannelHangupListener listener) + { + this.listeners.add(listener); + + } + + @Override + public void removeListener(ChannelHangupListener listener) + { + this.listeners.remove(listener); + + } + + @Override + public boolean isConnectedTo(EndPoint endPoint) + { + return this._channel.isConnectedTo(endPoint); + } + + @Override + public String getChannelName() + { + return this._channel.getChannelName(); + } + + @Override + public EndPoint getEndPoint() + { + return this._channel.getEndPoint(); + } + + @Override + public boolean isMute() + { + return this._channel.isMute(); + } + + @Override + public boolean isLocal() + { + return this._channel.isLocal(); + } + + @Override + public boolean isZombie() + { + return this._channel.isZombie(); + } + + @Override + public boolean isConsole() + { + return this._channel.isConsole(); + } + + @Override + public CallerID getCallerID() + { + return this._channel.getCallerID(); + } + + @Override + public void rename(String newName) throws InvalidChannelName + { + this._channel.rename(newName); + } + + @Override + public boolean isParked() + { + return this._channel.isParked(); + } + + /** + * Used to handle a MasqueradeEvent. We essentially swap the two underlying + * channels between the two proxies. + * + * @param cloneProxy + * @throws InvalidChannelName + */ + public void masquerade(ChannelProxy cloneProxy) throws InvalidChannelName + { + ChannelImpl originalChannel = this._channel; + ChannelImpl cloneChannel = cloneProxy._channel; + + cloneChannel.masquerade(this._channel); + + // detach the hangup listeners + originalChannel.removeListener(this); + cloneChannel.removeListener(cloneProxy); + + // Now we swap the channels. + this._channel = cloneChannel; + cloneProxy._channel = originalChannel; + + // Now re-attach the hangup listeners + this._channel.addHangupListener(this); + cloneProxy._channel.addHangupListener(cloneProxy); + + logger.info("Channel proxy now points to " + this._channel); + } + + public ChannelImpl getRealChannel() + { + return this._channel; + } + + @Override + public String getExtendedChannelName() + { + return this._channel.getExtendedChannelName(); + } + + @Override + public void notifyHangupListeners(Integer cause, String causeText) + { + for (ChannelHangupListener listener : this.listeners) + { + listener.channelHangup(this, cause, causeText); + } + + } + + @Override + public String toString() + { + return "(proxy=" + this._identity + ") " + this._channel.toString(); //$NON-NLS-1$ //$NON-NLS-2$ + } + + @Override + public void channelHangup(Channel channel, Integer cause, String causeText) + { + // When the underlying channel hangs up we need to notify all of the + // proxy listeners. + if (channel == this._channel) + notifyHangupListeners(cause, causeText); + + } + + @Override + public boolean canDetectHangup() + { + return this._channel.canDetectHangup(); + } + + @Override + public boolean isQuiescent() + { + return this._channel.isQuiescent(); + } + + @Override + public boolean hasCallerID() + { + return this._channel.hasCallerID(); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + _identity; + return result; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof ChannelProxy)) + { + return false; + } + ChannelProxy other = (ChannelProxy) obj; + if (_identity != other._identity) + { + return false; + } + return true; + } + + private AtomicReference currentActivityAction = new AtomicReference<>(); + volatile private boolean isInAgi; + + @Override + public AgiChannelActivityAction getCurrentActivityAction() + { + return currentActivityAction.get(); + } + + @Override + public void setCurrentActivityAction(AgiChannelActivityAction action) + { + AgiChannelActivityAction previousAction = currentActivityAction.get(); + + logger.info("Setting action to " + action.getClass().getSimpleName() + " for " + this); + + // Exception e = new Exception("Setting action to " + + // action.getClass().getSimpleName() + " for " + this); + // logger.warn(e, e); + + currentActivityAction.set(action); + if (previousAction != null) + { + // when we cancel the previous action, the new one will be invoked + previousAction.cancel(this); + } + } + + @Override + public void setIsInAgi(boolean b) + { + if (b) + { + hasReachedAgi.countDown(); + } + isInAgi = b; + logger.info("Setting is in agi to " + b + " for channel " + this); + + } + + @Override + public boolean isInAgi() + { + return isInAgi; + } + + final CountDownLatch hasReachedAgi = new CountDownLatch(1); + + @Override + public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException + { + return hasReachedAgi.await(timeout, timeunit); + } + + @Override + public String getUniqueId() + { + return _channel.getUniqueId(); + } + + public int getIdentity() + { + return _identity; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java index 3bf4b7f2f..23afa97fc 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java @@ -2,228 +2,272 @@ import org.apache.log4j.Logger; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.Trunk; public class EndPointImpl implements EndPoint { - private static final String DELIMITER = "/"; //$NON-NLS-1$ - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(EndPointImpl.class); - - final private TechType _tech; - - final private String _endPointName; - - final private String _fullyQualifiedName; - - // If true then this is an empty end point e.g. blank name and unknown tech. - final private boolean _empty; - - /** - * Creates a EndPoint from a fully qualified peer name of the form: SIP/NNN - * LOCAL/NNN - * - * TODO: the tech encoding should probably be specific to a particular pbx - * Implementation. - * - * @param fullyQualifiedPeerName - */ - public EndPointImpl(final String fullyQualifiedEndPoint) - { - if (fullyQualifiedEndPoint == null) - { - throw new IllegalArgumentException("The fullyQualifiedEndPoint may not be null"); //$NON-NLS-1$ - } - - final String cleaned = this.clean(fullyQualifiedEndPoint); - this._tech = TechType.getTech(cleaned); - this._endPointName = cleaned.substring(this._tech.name().length() + 1); - - if (this._tech == TechType.DIALPLAN) - { - this._fullyQualifiedName = this._endPointName; - } - else - { - this._fullyQualifiedName = this._tech.name() + EndPointImpl.DELIMITER + this._endPointName; - } - this._empty = false; - } - - /** - * Creates a empty end point. - */ - public EndPointImpl() - { - this._empty = true; - this._tech = TechType.UNKNOWN; - this._endPointName = ""; - this._fullyQualifiedName = ""; - } - - /** - * Creates an EndPoint from from a simple endpoint name and a tech. - * - * @param _tech - * @param peerName - */ - // EndPoint(String endPointName, String tech) - // { - // if (endPointName == null) - // throw new IllegalArgumentException("The endPoint Name may not be null"); - // - // if (tech == null) - // throw new IllegalArgumentException("The endPoint Tehc may not be null"); - // - // String cleaned = clean(endPointName); - // // Tech must be upper case to match the enum but - // // the simple name must be lower case to matcht the context extension - // // names. - // this.tech = Tech.valueOf(tech.toUpperCase()); - // this.endPointName = cleaned; - // } - - public EndPointImpl(final String endPointName, final TechType defaultTech) - { - if (endPointName == null) - { - throw new IllegalArgumentException("The endPointName may not be null"); //$NON-NLS-1$ - } - - final String cleaned = this.clean(endPointName); - - if (cleaned.length() == 0) - { - throw new IllegalArgumentException("The endPointName may not be empty"); //$NON-NLS-1$ - } - - // If tech is unknown then attempt to extract the tech from the - // endPointName. - if (TechType.hasTech(cleaned)) - { - this._tech = TechType.getTech(cleaned); - this._endPointName = cleaned.substring(this._tech.name().length() + 1); - - } - else - { - this._tech = defaultTech; - this._endPointName = cleaned; - } - - if (this._tech == TechType.DIALPLAN) - { - this._fullyQualifiedName = this._endPointName; - } - else - { - this._fullyQualifiedName = this._tech.name() + EndPointImpl.DELIMITER + this._endPointName; - } - this._empty = false; - } - - /** - * Returns the fully qualified endPoint. - */ - @Override - public String getFullyQualifiedName() - { - return this._fullyQualifiedName; - } - - @Override - public boolean isSame(final EndPoint rhs) - { - return this.compareTo(rhs) == 0; - } - - @Override - public int compareTo(EndPoint rhs) - { - return this.getFullyQualifiedName().compareTo(rhs.getFullyQualifiedName()); - } - - @Override - public boolean isLocal() - { - return this._tech == TechType.LOCAL; - } - - /** - * For the purposes of asterisk IAX and SIP are both considered SIP. - */ - @Override - public boolean isSIP() - { - return this._tech == TechType.SIP || this._tech == TechType.IAX || this._tech == TechType.IAX2; - } - - public boolean isDAHDI() - { - return this._tech == TechType.DAHDI; - } - - @Override - public String getSimpleName() - { - return this._endPointName; - } - - @Override - public boolean isUnknown() - { - return this._tech == TechType.UNKNOWN; - } - - /** - * Cleans up an endpoint name by removing all whitespace (including internal - * whitespace) as well as making the string lower case. - * - * @param _endPointName - * @return - */ - private String clean(final String _endPointName) - { - String localTo = _endPointName.trim(); - - // strip all white space from within the name as some source - // pass in a formatted phone number (e.g. 03 8320 8100) - int tmp = localTo.indexOf(" "); //$NON-NLS-1$ - while (tmp != -1) - { - localTo = localTo.substring(0, tmp) + localTo.substring(tmp + 1, localTo.length()); - tmp = localTo.indexOf(" "); //$NON-NLS-1$ - } - return localTo.toLowerCase(); - } - - @Override - public TechType getTech() - { - return this._tech; - } - - @Override - public String toString() - { - return this.getFullyQualifiedName(); - } - - @Override - public String getSIPSimpleName() - { - String name; - - if (isSIP()) - name = getSimpleName(); - else - name = getFullyQualifiedName(); - return name; - } - - public boolean isEmpty() - { - return this._empty; - } + private static final String DELIMITER = "/"; //$NON-NLS-1$ + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(EndPointImpl.class); + + final private TechType _tech; + + final private String _endPointName; + + final private String _fullyQualifiedName; + + // If true then this is an empty end point e.g. blank name and unknown tech. + final private boolean _empty; + + private Trunk _trunk; + + /** + * Creates a EndPoint from a fully qualified peer name of the form: SIP/NNN + * LOCAL/NNN TODO: the tech encoding should probably be specific to a + * particular pbx Implementation. + * + * @param fullyQualifiedPeerName + */ + public EndPointImpl(final String fullyQualifiedEndPoint) + { + if (fullyQualifiedEndPoint == null) + { + throw new IllegalArgumentException("The fullyQualifiedEndPoint may not be null"); //$NON-NLS-1$ + } + + final String cleaned = this.clean(fullyQualifiedEndPoint); + this._tech = TechType.getTech(cleaned); + this._endPointName = cleaned.substring(this._tech.name().length() + 1); + + if (this._tech == TechType.DIALPLAN) + { + this._fullyQualifiedName = this._endPointName; + } + else + { + this._fullyQualifiedName = this._tech.name() + EndPointImpl.DELIMITER + this._endPointName; + } + this._empty = false; + } + + /** + * Creates a empty end point. + */ + public EndPointImpl() + { + this._empty = true; + this._tech = TechType.UNKNOWN; + this._endPointName = ""; + this._fullyQualifiedName = ""; + } + + /** + * Creates an EndPoint from from a simple endpoint name and a tech. + * + * @param _tech + * @param peerName + */ + // EndPoint(String endPointName, String tech) + // { + // if (endPointName == null) + // throw new IllegalArgumentException("The endPoint Name may not be null"); + // + // if (tech == null) + // throw new IllegalArgumentException("The endPoint Tehc may not be null"); + // + // String cleaned = clean(endPointName); + // // Tech must be upper case to match the enum but + // // the simple name must be lower case to matcht the context extension + // // names. + // this.tech = Tech.valueOf(tech.toUpperCase()); + // this.endPointName = cleaned; + // } + + public EndPointImpl(final TechType defaultTech, final String endPointName) + { + if (endPointName == null) + { + throw new IllegalArgumentException("The endPointName may not be null"); //$NON-NLS-1$ + } + + final String cleaned = this.clean(endPointName); + + if (cleaned.length() == 0) + { + throw new IllegalArgumentException("The endPointName may not be empty"); //$NON-NLS-1$ + } + + // If tech is unknown then attempt to extract the tech from the + // endPointName. + if (TechType.hasTech(cleaned)) + { + this._tech = TechType.getTech(cleaned); + this._endPointName = cleaned.substring(this._tech.name().length() + 1); + + } + else + { + this._tech = defaultTech; + this._endPointName = cleaned; + } + + if (this._tech == TechType.DIALPLAN) + { + this._fullyQualifiedName = this._endPointName; + } + else + { + this._fullyQualifiedName = this._tech.name() + EndPointImpl.DELIMITER + this._endPointName; + } + this._empty = false; + } + + public EndPointImpl(TechType defaultTech, Trunk trunk, String endPointName) + { + if (endPointName == null) + { + throw new IllegalArgumentException("The endPointName may not be null"); //$NON-NLS-1$ + } + + final String cleaned = this.clean(endPointName); + + if (cleaned.length() == 0) + { + throw new IllegalArgumentException("The endPointName may not be empty"); //$NON-NLS-1$ + } + + // If tech is unknown then attempt to extract the tech from the + // endPointName. + if (TechType.hasTech(cleaned)) + { + throw new IllegalArgumentException("endPointName may not contain a Tech"); + + } + + this._tech = defaultTech; + this._endPointName = cleaned; + this._trunk = trunk; + + if (this._tech == TechType.DIALPLAN || this._tech == TechType.CONSOLE || this._tech == TechType.LOCAL) + { + throw new IllegalArgumentException("defaultTech may not be DIALPLAN, LOCAL or CONSOLE"); + } + + this._fullyQualifiedName = this._tech.name() + EndPointImpl.DELIMITER + trunk + EndPointImpl.DELIMITER + + this._endPointName; + + this._empty = false; + + } + + /** + * Returns the fully qualified endPoint. + */ + @Override + public String getFullyQualifiedName() + { + return this._fullyQualifiedName; + } + + public Trunk getTrunk() + { + return _trunk; + } + + @Override + public boolean isSame(final EndPoint rhs) + { + return this.compareTo(rhs) == 0; + } + + @Override + public int compareTo(EndPoint rhs) + { + return this.getFullyQualifiedName().compareTo(rhs.getFullyQualifiedName()); + } + + @Override + public boolean isLocal() + { + return this._tech == TechType.LOCAL; + } + + /** + * For the purposes of asterisk IAX and SIP are both considered SIP. + */ + @Override + public boolean isSIP() + { + return this._tech == TechType.SIP || this._tech == TechType.IAX || this._tech == TechType.IAX2; + } + + public boolean isDAHDI() + { + return this._tech == TechType.DAHDI; + } + + @Override + public String getSimpleName() + { + return this._endPointName; + } + + @Override + public boolean isUnknown() + { + return this._tech == TechType.UNKNOWN; + } + + /** + * Cleans up an endpoint name by removing all whitespace (including internal + * whitespace) as well as making the string lower case. + * + * @param _endPointName + * @return + */ + private String clean(final String _endPointName) + { + String localTo = _endPointName.trim(); + + // strip all white space from within the name as some source + // pass in a formatted phone number (e.g. 03 8320 8100) + int tmp = localTo.indexOf(" "); //$NON-NLS-1$ + while (tmp != -1) + { + localTo = localTo.substring(0, tmp) + localTo.substring(tmp + 1, localTo.length()); + tmp = localTo.indexOf(" "); //$NON-NLS-1$ + } + return localTo.toLowerCase(); + } + + @Override + public TechType getTech() + { + return this._tech; + } + + @Override + public String toString() + { + return this.getFullyQualifiedName(); + } + + @Override + public String getSIPSimpleName() + { + String name; + + if (isSIP()) + name = getSimpleName(); + else + name = getFullyQualifiedName(); + return name; + } + + public boolean isEmpty() + { + return this._empty; + } } From 29574fa52f03e9fe61b439255fc7c2b9120aac8c Mon Sep 17 00:00:00 2001 From: Brett Sutton Date: Tue, 18 Oct 2016 23:06:53 +1100 Subject: [PATCH 058/802] Improved the documentation --- .../examples/activities/BlindTransfer.java | 11 +++ .../internal/asterisk/AsteriskSettings.java | 71 ++++++++++++++++++- .../pbx/internal/core/DialPlanExtension.java | 5 +- 3 files changed, 84 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java index 47945fa74..fcccc9bd4 100644 --- a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java +++ b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java @@ -27,9 +27,20 @@ public class BlindTransfer static public void main(String[] args) throws IOException, AuthenticationFailedException, TimeoutException { + /** + * Initialise the PBX Factory. You need to implement your own AsteriskSettings class. + */ PBXFactory.init(new ExamplesAsteriskSettings()); + + /** + * Activities utilise an agi entry point in your dial plan. + * You can create your own entry point in dialplan or have + * asterisk-java add it automatically + */ AsteriskPBX asteriskPbx = (AsteriskPBX) PBXFactory.getActivePBX(); asteriskPbx.createAgiEntryPoint(); + + // We are all configured lets try and do a blind transfer. blindTransfer(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/AsteriskSettings.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/AsteriskSettings.java index 0f318ca32..983c538e6 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/AsteriskSettings.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/AsteriskSettings.java @@ -3,28 +3,97 @@ public interface AsteriskSettings { + /** + * The port no. that the asterisk manager api listens on. + * This should be 5060 unless you have re-configured the manager api. + * @return the port no. + */ int getManagerPortNo(); + /** + * This password MUST match the password (secret=) in manager.conf + * @return + */ String getManagerPassword(); + /** + * This MUST match the section header (e.g. '[myconnection]') in manager.conf + * @return + */ String getManagerUsername(); + /** + * The IP address of FQND of the Asterisk PBX + * @return IP address or FQDN. + */ String getAsteriskIP(); + + /** + * Asterisk-Java uses conference rooms for a variety of purposes. + * Just make certain that the base address doesn't overlap any conference + * rooms you are currently running on your pbx. + * You should probably allow 200 conference rooms here e.g. (3000-3200) + * Actions like transfers (and conference calls) use a conference room. + * @return meetme base address + */ Integer getMeetmeBaseAddress(); + + /** + * Return true if you Asterisk version doesn't support bridging channels. + * All version after 1.8 support bridging so normally you should returm false; + * + * @return false if you asterisk version supports bridging channels. + */ boolean getDisableBridge(); - + + + /** + * This is an asterisk dialplan context. + * Simply pick a context which doesn't already exist + * and use AsteriskPBX.createAgiEntryPoint() + * to inject the necessary dialplan used by asterisk-java + * @return an unused asterisk dialplan context. e.g. "asteriskjava" + */ String getManagementContext(); + /** + * Return an asterisk dialplan extension (within the above Management Context) + * that will be used to park calls. + * Just ensure that its a unique asterisk dialplan extension name. + */ String getExtensionPark(); + /** + * The time (in seconds) to wait for a dial attempt to be answered before giving up. + * Recommend a value of 30. + * @return + */ int getDialTimeout(); + /** + * Return the SIP header to be used to force a handset to auto-answer when dialed. + * e.g. For Yealink/Snom use return "Call-Info:\; answer-after=0"; + * @return + */ String getAutoAnswer(); + /** + * + * Return an asterisk dialplan extension (within the Management Context) + * that will be used to inject the agi dialplan entry point used by Activites.. + * Just ensure that its a unique asterisk dialplan extension name. + * @return "asterisk-java-agi" + */ String getAgiExtension(); + + /** + * Return true if the telephony tech you are dialing from can reliably detect + * hangups. (for SIP set to true, POTS set false). + * @return + */ boolean getCanDetectHangup(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialPlanExtension.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialPlanExtension.java index 8b3980441..719a39292 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialPlanExtension.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialPlanExtension.java @@ -4,9 +4,10 @@ import org.asteriskjava.pbx.EndPoint; /** - * Represents an asterisk dial plan extension such eg. + * Represents an asterisk dial plan extension such as: * - * [njr-operator] njr-inbound,1,xxxxx + * [njr-operator] + * njr-inbound,1,xxxxx * * In the above example njr-inbound is the dialplan extension. * From d2eed5662b5cf588b02825f0c58b5ffa80aece3d Mon Sep 17 00:00:00 2001 From: Brett Sutton Date: Tue, 18 Oct 2016 23:21:34 +1100 Subject: [PATCH 059/802] Removed 'Trunk' from the dial method as it is being ignored and we now build trunk into the endpoint. --- .../examples/activities/BlindTransfer.java | 8 +++++++- .../org/asteriskjava/examples/activities/Dial.java | 10 ++++++++-- src/main/java/org/asteriskjava/pbx/PBX.java | 4 +--- .../asteriskjava/pbx/internal/core/AsteriskPBX.java | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java index fcccc9bd4..8a735b519 100644 --- a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java +++ b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java @@ -12,6 +12,7 @@ import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.Trunk; import org.asteriskjava.pbx.activities.BlindTransferActivity; import org.asteriskjava.pbx.activities.DialActivity; import org.asteriskjava.pbx.internal.core.AsteriskPBX; @@ -47,6 +48,11 @@ static public void main(String[] args) throws IOException, AuthenticationFailedE static private void blindTransfer() { PBX pbx = PBXFactory.getActivePBX(); + + // The trunk MUST match the section header (e.g. [default]) that appears + // in your /etc/asterisk/sip.d file (assuming you are using a SIP trunk). + // The trunk is used to select which SIP trunk to dial through. + Trunk trunk = pbx.buildTrunk("default"); // We are going to dial from extension 100 EndPoint from = pbx.buildEndPoint(TechType.SIP, "100"); @@ -56,7 +62,7 @@ static private void blindTransfer() // The caller ID to display on the called parties phone CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); // The party we are going to call. - EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); + EndPoint to = pbx.buildEndPoint(TechType.SIP, trunk, "5551234"); // Start the dial and return immediately. // progress is provided via the ActivityCallback. diff --git a/src/main/java/org/asteriskjava/examples/activities/Dial.java b/src/main/java/org/asteriskjava/examples/activities/Dial.java index b6393bf7c..cb8377664 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Dial.java +++ b/src/main/java/org/asteriskjava/examples/activities/Dial.java @@ -8,6 +8,7 @@ import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.Trunk; import org.asteriskjava.pbx.activities.DialActivity; import org.asteriskjava.pbx.internal.core.TechType; @@ -31,6 +32,11 @@ static private void syncDial() { PBX pbx = PBXFactory.getActivePBX(); + // The trunk MUST match the section header (e.g. [default]) that appears + // in your /etc/asterisk/sip.d file (assuming you are using a SIP trunk). + // The trunk is used to select which SIP trunk to dial through. + Trunk trunk = pbx.buildTrunk("default"); + // We are going to dial from extension 100 EndPoint from = pbx.buildEndPoint(TechType.SIP, "100"); // The caller ID to show on extension 100. @@ -39,12 +45,12 @@ static private void syncDial() // The caller ID to display on the called parties phone CallerID toCallerID = pbx.buildCallerID("83208100", "Asterisk Java is calling"); // The party we are going to call. - EndPoint to = pbx.buildEndPoint("SIP/default/5551234"); + EndPoint to = pbx.buildEndPoint(TechType.SIP, trunk, "5551234"); // Trunk is currently ignored so set to null // The call is dialed and only returns when the call comes up (it // doesn't wait for the remote end to answer). - DialActivity dial = pbx.dial(null, from, fromCallerID, to, toCallerID); + DialActivity dial = pbx.dial(from, fromCallerID, to, toCallerID); Call call = dial.getNewCall(); diff --git a/src/main/java/org/asteriskjava/pbx/PBX.java b/src/main/java/org/asteriskjava/pbx/PBX.java index cd8119d6b..a72ca8fe4 100644 --- a/src/main/java/org/asteriskjava/pbx/PBX.java +++ b/src/main/java/org/asteriskjava/pbx/PBX.java @@ -98,11 +98,9 @@ void blindTransfer(Call call, OperandChannel channelToTransfer, final EndPoint t * until the call has been dialled. The dial will return as soon as the * trunk comes up, it does not wait for remote end to answer. * - * @param trunk - the trunk to dial out on. If null the default trunk will - * be used. * @return Call - the call resulting from dialing the number. */ - DialActivity dial(Trunk trunk, EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID); + DialActivity dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID); /** * Dials the given phone number using the specified trunk. Not returning diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 060733e3c..5d0c3a27a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -239,7 +239,7 @@ public void conference(final Channel channelOne, final Channel channelTwo, final } @Override - public DialActivity dial(final Trunk trunk, final EndPoint from, final CallerID fromCallerID, final EndPoint to, + public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID) { final CompletionAdaptor completion = new CompletionAdaptor<>(); @@ -257,7 +257,7 @@ public DialLocalToAgiActivity dialLocalToAgi(final EndPoint from, final CallerID return new DialLocalToAgiActivity(from, fromCallerID, callback, channelVarsToSet); } - public DialActivity dial(final Trunk trunk, final EndPoint from, final CallerID fromCallerID, final EndPoint to, + public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID, final ActivityCallback callback, Map channelVarsToSet) { final DialActivityImpl dialer = new DialActivityImpl(from, to, toCallerID, false, callback, channelVarsToSet); From 647cf6e90632bac4aed3cf8cd13c5f620e0fdbb9 Mon Sep 17 00:00:00 2001 From: Brett Sutton Date: Tue, 18 Oct 2016 23:28:42 +1100 Subject: [PATCH 060/802] Added method to directly hangup a call rather than the user having to extract the channel. --- .../java/org/asteriskjava/examples/activities/Dial.java | 6 ++++-- src/main/java/org/asteriskjava/pbx/PBX.java | 7 +++++++ .../org/asteriskjava/pbx/internal/core/AsteriskPBX.java | 9 +++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/examples/activities/Dial.java b/src/main/java/org/asteriskjava/examples/activities/Dial.java index cb8377664..48a4028dc 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Dial.java +++ b/src/main/java/org/asteriskjava/examples/activities/Dial.java @@ -53,10 +53,12 @@ static private void syncDial() DialActivity dial = pbx.dial(from, fromCallerID, to, toCallerID); Call call = dial.getNewCall(); + + Thread.sleep(20000); - pbx.hangup(call.getOriginatingParty()); + pbx.hangup(call); } - catch (PBXException e) + catch (PBXException | InterruptedException e) { System.out.println(e); } diff --git a/src/main/java/org/asteriskjava/pbx/PBX.java b/src/main/java/org/asteriskjava/pbx/PBX.java index a72ca8fe4..48198842a 100644 --- a/src/main/java/org/asteriskjava/pbx/PBX.java +++ b/src/main/java/org/asteriskjava/pbx/PBX.java @@ -130,6 +130,12 @@ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID */ void hangup(Channel channel, ActivityCallback callback); + /** + * Hangup the given call, not returning until the call is hungup. + * @param call + */ + public void hangup(Call call) throws PBXException; + /** * Put the given channel on hold. * @@ -271,4 +277,5 @@ public void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandC public Trunk buildTrunk(String string); + } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 5d0c3a27a..c594bf50b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -272,6 +272,15 @@ public void dial(final EndPoint from, final CallerID fromCallerID, final EndPoin } + /** + * Convenience method to hangup the call without having to extract the + * channel yourself. + */ + public void hangup(Call call) throws PBXException + { + this.hangup(call.getOriginatingParty()); + } + @Override public void hangup(final Channel channel) throws PBXException { From 9f6d1058df6a057e0d33e0fad2a4851f4a1068a8 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 25 Oct 2016 09:59:11 +1100 Subject: [PATCH 061/802] minor fixes --- .../org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java | 4 ++++ .../pbx/internal/managerAPI/OriginateBaseClass.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index 495b5dbda..37d6b12f2 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -79,6 +79,10 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint } } + else + { + logger.error("Originate failed: " + trcResult.getAbortReason()); + } logger.info("Hangup status is " + hangupDetected); return this.result; diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 67f915119..87823e8c6 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -40,7 +40,7 @@ public abstract class OriginateBaseClass extends EventListenerBaseClass private volatile String originateID; - private boolean originateSuccess; + volatile private boolean originateSuccess; private final Channel monitorChannel1; From 9fa47a902060eab4a6620b753aff2a28e1483a55 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 25 Oct 2016 16:17:03 +1100 Subject: [PATCH 062/802] fixes for inconsistent behaviour in pbx --- .../pbx/internal/agi/ActivityAgi.java | 2 +- .../pbx/internal/asterisk/MeetmeRoom.java | 2 +- .../asterisk/wrap/events/BridgeEvent.java | 112 ++-- .../asterisk/wrap/events/DialEvent.java | 64 +- .../asterisk/wrap/events/DndStateEvent.java | 66 +- .../asterisk/wrap/events/MasqueradeEvent.java | 211 +++---- .../asterisk/wrap/events/NewExtenEvent.java | 90 +-- .../asterisk/wrap/events/ParkedCallEvent.java | 82 +-- .../asterisk/wrap/events/RenameEvent.java | 93 +-- .../asterisk/wrap/events/StatusEvent.java | 200 +++--- .../wrap/events/UnparkedCallEvent.java | 28 +- .../asterisk/wrap/events/VarSetEvent.java | 76 +-- .../asterisk/wrap/userEvents/UserEvent.java | 38 +- .../pbx/internal/core/AsteriskPBX.java | 100 ++- .../pbx/internal/core/ChannelEventHelper.java | 95 ++- .../pbx/internal/core/ChannelImpl.java | 27 +- .../pbx/internal/core/ChannelProxy.java | 2 +- .../pbx/internal/core/LiveChannelManager.java | 572 ++++++++++-------- 18 files changed, 936 insertions(+), 924 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/internal/agi/ActivityAgi.java index 9a2f41b7e..9e994a1d3 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/agi/ActivityAgi.java @@ -34,7 +34,7 @@ public void service() throws AgiException { logger.warn("'proxyId' var not set or proxy doesn't exist anymore, trying to match the channel name... " + channelName); - channelProxy = pbx.registerChannel(channel.getName(), null); + channelProxy = pbx.internalRegisterChannel(channel.getName(), channel.getUniqueId()); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java index 9a223f3da..7a7eaa377 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java @@ -104,7 +104,7 @@ synchronized public void removeChannel(final Channel channel) if (!removed) { - MeetmeRoom.logger.error( + MeetmeRoom.logger.warn( "An attempt to remove an non-existing channel " + channel + " from Meetme Room " + this.getRoomNumber()); //$NON-NLS-1$ //$NON-NLS-2$ } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/BridgeEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/BridgeEvent.java index 09b10f206..bb803779b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/BridgeEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/BridgeEvent.java @@ -8,71 +8,71 @@ public class BridgeEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(BridgeEvent.class); + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(BridgeEvent.class); - enum BridgeState - { - Link, Unlink - } + enum BridgeState + { + Link, Unlink + } - private final BridgeState bridgeState; - private final ChannelProxy channel1; - private final ChannelProxy channel2; + private final BridgeState bridgeState; + private final ChannelProxy channel1; + private final ChannelProxy channel2; - public BridgeEvent(final org.asteriskjava.manager.event.BridgeEvent event) throws InvalidChannelName - { - super(event); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + public BridgeEvent(final org.asteriskjava.manager.event.BridgeEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - this.bridgeState = BridgeState.valueOf(event.getBridgeState()); - this.channel1 = pbx.registerChannel(event.getChannel1(), event.getUniqueId1()); - this.channel2 = pbx.registerChannel(event.getChannel2(), event.getUniqueId2()); - } + this.bridgeState = BridgeState.valueOf(event.getBridgeState()); + this.channel1 = pbx.internalRegisterChannel(event.getChannel1(), event.getUniqueId1()); + this.channel2 = pbx.internalRegisterChannel(event.getChannel2(), event.getUniqueId2()); + } - public BridgeState getBridgeState() - { - return this.bridgeState; - } + public BridgeState getBridgeState() + { + return this.bridgeState; + } - public ChannelProxy getChannel1() - { - return this.channel1; - } + public ChannelProxy getChannel1() + { + return this.channel1; + } - public ChannelProxy getChannel2() - { - return this.channel2; - } + public ChannelProxy getChannel2() + { + return this.channel2; + } - /** - * Returns whether the two channels have been linked. - * - * @return true the two channels have been linked, - * false if they have been unlinked. - * @since 1.0.0 - */ - public boolean isLink() - { - return this.bridgeState == BridgeState.Link; - } + /** + * Returns whether the two channels have been linked. + * + * @return true the two channels have been linked, + * false if they have been unlinked. + * @since 1.0.0 + */ + public boolean isLink() + { + return this.bridgeState == BridgeState.Link; + } - /** - * Returns whether the two channels have been unlinked. - * - * @return true the two channels have been unlinked, - * false if they have been linked. - * @since 1.0.0 - */ - public boolean isUnlink() - { - return this.bridgeState == BridgeState.Unlink; - } + /** + * Returns whether the two channels have been unlinked. + * + * @return true the two channels have been unlinked, + * false if they have been linked. + * @since 1.0.0 + */ + public boolean isUnlink() + { + return this.bridgeState == BridgeState.Unlink; + } - public String toString() - { - return "BridgeEvent: channel1:" + this.channel1 + " channel2:" + this.channel2 + " bridgeState:" + this.bridgeState; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ - } + public String toString() + { + return "BridgeEvent: channel1:" + this.channel1 + " channel2:" + this.channel2 + " bridgeState:" + this.bridgeState; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DialEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DialEvent.java index 6d6fa490a..4d7479a73 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DialEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DialEvent.java @@ -9,47 +9,47 @@ public class DialEvent extends ChannelEventHelper { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(DialEvent.class); + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(DialEvent.class); - /** - * The name of the destination channel. - */ - private final ChannelProxy destination; + /** + * The name of the destination channel. + */ + private final ChannelProxy destination; - private final String dialString; - private final String dialStatus; + private final String dialString; + private final String dialStatus; - public DialEvent(final org.asteriskjava.manager.event.DialEvent event) throws InvalidChannelName - { - super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + public DialEvent(final org.asteriskjava.manager.event.DialEvent event) throws InvalidChannelName + { + super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - if (event.getDestination() != null) - this.destination = pbx.registerChannel(event.getDestination(), event.getDestUniqueId()); - else - this.destination = null; + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + if (event.getDestination() != null) + this.destination = pbx.internalRegisterChannel(event.getDestination(), event.getDestUniqueId()); + else + this.destination = null; - this.dialString = event.getDialString(); - this.dialStatus = event.getDialStatus(); + this.dialString = event.getDialString(); + this.dialStatus = event.getDialStatus(); - } + } - public ChannelProxy getDestination() - { - return this.destination; - } + public ChannelProxy getDestination() + { + return this.destination; + } - public String getDialString() - { - return this.dialString; - } + public String getDialString() + { + return this.dialString; + } - public String getDialStatus() - { - return this.dialStatus; - } + public String getDialStatus() + { + return this.dialStatus; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DndStateEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DndStateEvent.java index 2275b88b0..24d6daf12 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DndStateEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DndStateEvent.java @@ -9,37 +9,37 @@ public class DndStateEvent extends ManagerEvent implements ChannelEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(DndStateEvent.class); - - /** - * The name of the channel. - */ - private final Channel channel; - - /** - * The DND state of the channel. - */ - private final Boolean state; - - public DndStateEvent(final org.asteriskjava.manager.event.DndStateEvent event) throws InvalidChannelName - { - super(event); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - this.channel = pbx.registerChannel(event.getChannel(), ChannelImpl.UNKNOWN_UNIQUE_ID); - this.state = event.getState(); - } - - @Override - public Channel getChannel() - { - return this.channel; - } - - public Boolean getState() - { - return this.state; - } + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(DndStateEvent.class); + + /** + * The name of the channel. + */ + private final Channel channel; + + /** + * The DND state of the channel. + */ + private final Boolean state; + + public DndStateEvent(final org.asteriskjava.manager.event.DndStateEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + this.channel = pbx.internalRegisterChannel(event.getChannel(), ChannelImpl.UNKNOWN_UNIQUE_ID); + this.state = event.getState(); + } + + @Override + public Channel getChannel() + { + return this.channel; + } + + public Boolean getState() + { + return this.state; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MasqueradeEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MasqueradeEvent.java index c6fdb6af7..7fc5e20ae 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MasqueradeEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MasqueradeEvent.java @@ -10,185 +10,146 @@ /** * A Masquerade is used when a new channel is created to replace an existing * channel. The typical cause of this is an action such as a Redirect, Park etc. - * * During the Redirect a new channel will be created which has the same name as * the existing channel but with a Suffix attached such as ASYNCGOTO. The suffix - * selected will depend on the actual action that cause the masquerade. - * - * As we proxy all channels a key goal for us is for the existing proxy to end - * up containing the new channel. - * - * The existing channel will eventually be renamed with a suffix and then - * go on to become a zombie before it is hungup. - * + * selected will depend on the actual action that cause the masquerade. As we + * proxy all channels a key goal for us is for the existing proxy to end up + * containing the new channel. The existing channel will eventually be renamed + * with a suffix and then go on to become a zombie before it is hungup. * The masquerade event is associated a NewEvent, three renames and one hangup - * event. - * - * The terminology used by asterisk is quite confusing. - * - * The 'original channel' is the channel created as a result of the action - * (redirect, park etc). The 'clone' channel is the pre-existing channel that - * was acted upon. - * + * event. The terminology used by asterisk is quite confusing. The 'original + * channel' is the channel created as a result of the action (redirect, park + * etc). The 'clone' channel is the pre-existing channel that was acted upon. * New Event: Original - the Original channel is currently holding the active * call due to the transfer/park.. event. - the Original name will be something - * like ASYNCGOTO/SIP/101-0000002D:1351178863.121 - * - * Masquerade Event: Clone, Original (e.g. SIP/101-0000002D:1351178863.121, + * like ASYNCGOTO/SIP/101-0000002D:1351178863.121 Masquerade Event: Clone, + * Original (e.g. SIP/101-0000002D:1351178863.121, * ASYNCGOTO/SIP/101-0000002D:1351178863.121) - swap the guts of the two * channels - for us this means that we swap the channels between the two parent * proxies. Some channel information is also copied from the clone to the * original channel (yes this terminology appears to be arse about. Remember the - * 'clone' is the pre-existing channel). - * - * Rename: Clone to Clone (e.g. rename the pre-existing channel - * SIP/101-0000002D:1351178863.121 to SIP/101-0000002D:1351178863.121 - - * start shutting down the clone (pre-existing channel). Rename: Original to - * Clone's initial name Name (e.g rename - * ASYNCGOTO/SIP/101-0000002D:1351178863.121, SIP/101-0000002D:1351178863.121) - * Rename:Clone to Clone (e.g. rename - * SIP/101-0000002D:1351178863.121 to + * 'clone' is the pre-existing channel). Rename: Clone to Clone (e.g. + * rename the pre-existing channel SIP/101-0000002D:1351178863.121 to + * SIP/101-0000002D:1351178863.121 - start shutting down the clone + * (pre-existing channel). Rename: Original to Clone's initial name Name (e.g + * rename ASYNCGOTO/SIP/101-0000002D:1351178863.121, + * SIP/101-0000002D:1351178863.121) Rename:Clone to Clone (e.g. + * rename SIP/101-0000002D:1351178863.121 to * SIP/101-0000002D:1351178863.121 Hangup: Clone (e.g. hangup - * SIP/101-0000002D:1351178863.121 - * - * Example sequence: - * - * RedirectAction: chanel=(proxy=2) SIP/101-0000002F:1351181832.124 - * context=njr-operator exten=njr-musiconhold priority=1 extraContext=null - * extraChannel=null extraExten=null Dump of LiveChannels, cause:Add: (proxy=3) + * SIP/101-0000002D:1351178863.121 Example sequence: RedirectAction: + * chanel=(proxy=2) SIP/101-0000002F:1351181832.124 context=njr-operator + * exten=njr-musiconhold priority=1 extraContext=null extraChannel=null + * extraExten=null Dump of LiveChannels, cause:Add: (proxy=3) * ASYNCGOTO/SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=1) * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) * SIP/101-0000002F:1351181832.124 ChannelProxy: (proxy=3) - * ASYNCGOTO/SIP/101-0000002F:1351181837.125 - * - * dispatch=NewChannelEvent: channel: (proxy=3) - * ASYNCGOTO/SIP/101-0000002F:1351181837.125 context=from-internal exten=null - * state=Up - * - * dispatch=MasqueradeEvent: originalChannel:(proxy=3) + * ASYNCGOTO/SIP/101-0000002F:1351181837.125 dispatch=NewChannelEvent: channel: + * (proxy=3) ASYNCGOTO/SIP/101-0000002F:1351181837.125 context=from-internal + * exten=null state=Up dispatch=MasqueradeEvent: originalChannel:(proxy=3) * ASYNCGOTO/SIP/101-0000002F:1351181837.125 cloned from:(proxy=2) * SIP/101-0000002F:1351181832.124 Dump of LiveChannels, cause:Masquerade: * (proxy=2) ASYNCGOTO/SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=1) * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) * ASYNCGOTO/SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=3) + * SIP/101-0000002F:1351181832.124 RenameEvent: existing channel: (proxy=3) * SIP/101-0000002F:1351181832.124 - * - * RenameEvent: existing channel: (proxy=3) SIP/101-0000002F:1351181832.124 * newname=SIP/101-0000002frawExisting:SIP/101-0000002f * rawNewname:SIP/101-0000002frawUniquID:1351181832.124 Dump of * LiveChannels, cause:RenameEvent: (proxy=3) * SIP/101-0000002F:1351181832.124 ChannelProxy: (proxy=1) * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) * ASYNCGOTO/SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=3) - * SIP/101-0000002F:1351181832.124 - * - * dispatch=RenameEvent: existing channel: (proxy=2) - * ASYNCGOTO/SIP/101-0000002F:1351181837.125 + * SIP/101-0000002F:1351181832.124 dispatch=RenameEvent: existing channel: + * (proxy=2) ASYNCGOTO/SIP/101-0000002F:1351181837.125 * newname=SIP/101-0000002frawExisting:AsyncGoto/SIP/101-0000002f * rawNewname:SIP/101-0000002frawUniquID:1351181837.125 Dump of LiveChannels, * cause:RenameEvent: (proxy=2) SIP/101-0000002F:1351181837.125 ChannelProxy: * (proxy=1) SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) * SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=3) - * SIP/101-0000002F:1351181832.124 - * - * dispatch=RenameEvent: existing channel: (proxy=3) - * SIP/101-0000002F:1351181832.124 + * SIP/101-0000002F:1351181832.124 dispatch=RenameEvent: existing channel: + * (proxy=3) SIP/101-0000002F:1351181832.124 * newname=AsyncGoto/SIP/101-0000002frawExisting:SIP/101-0000002f - * rawNewname:AsyncGoto/SIP/101-0000002frawUniquID:1351181832.124 - * - * Dump of LiveChannels, cause:RenameEvent: (proxy=3) + * rawNewname:AsyncGoto/SIP/101-0000002frawUniquID:1351181832.124 Dump + * of LiveChannels, cause:RenameEvent: (proxy=3) * ASYNCGOTO/SIP/101-0000002F:1351181832.124 ChannelProxy: (proxy=1) * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) * SIP/101-0000002F:1351181837.125 ChannelProxy: (proxy=3) - * ASYNCGOTO/SIP/101-0000002F:1351181832.124 - * - * dispatch=BridgeEvent: channel1:(proxy=1) SIP/110-0000002E:1351181832.123 - * channel2:(proxy=3) ASYNCGOTO/SIP/101-0000002F:1351181832.124 - * bridgeState:Unlink - * + * ASYNCGOTO/SIP/101-0000002F:1351181832.124 dispatch=BridgeEvent: + * channel1:(proxy=1) SIP/110-0000002E:1351181832.123 channel2:(proxy=3) + * ASYNCGOTO/SIP/101-0000002F:1351181832.124 bridgeState:Unlink * dispatch=HangupEvent: channel:(proxy=3) * ASYNCGOTO/SIP/101-0000002F:1351181832.124 cause:Normal Clearing Dump * of LiveChannels, cause:Removing: (proxy=3) * ASYNCGOTO/SIP/101-0000002F:1351181832.124 ChannelProxy: (proxy=1) * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) - * SIP/101-0000002F:1351181837.125 - * - * dispatch=HangupEvent: channel:(proxy=1) SIP/110-0000002E:1351181832.123 - * cause:Normal Clearing Dump of LiveChannels, cause:Removing: (proxy=1) - * SIP/110-0000002E:1351181832.123 ChannelProxy: (proxy=2) - * SIP/101-0000002F:1351181837.125 - * - * The end result is that the original (new) channel ends up with the clones - * (pre-existing) channel name. - * - * The pre-existing proxy ends up holding the original channel with the - * pre-existing channel's initial name. - * - * The masquerade event then is about ripping the guts out of the clone - * (pre-existing channel) and swapping with the original (new) channel. At the - * end of the swap the original (new) channel is left active (as it has the - * clones guts) and the clone (pre-existing) is inactive so we can hangup the - * clone as it is no longer needed. - * - * + * SIP/101-0000002F:1351181837.125 dispatch=HangupEvent: channel:(proxy=1) + * SIP/110-0000002E:1351181832.123 cause:Normal Clearing Dump of LiveChannels, + * cause:Removing: (proxy=1) SIP/110-0000002E:1351181832.123 ChannelProxy: + * (proxy=2) SIP/101-0000002F:1351181837.125 The end result is that the original + * (new) channel ends up with the clones (pre-existing) channel name. The + * pre-existing proxy ends up holding the original channel with the pre-existing + * channel's initial name. The masquerade event then is about ripping the guts + * out of the clone (pre-existing channel) and swapping with the original (new) + * channel. At the end of the swap the original (new) channel is left active (as + * it has the clones guts) and the clone (pre-existing) is inactive so we can + * hangup the clone as it is no longer needed. * * @author bsutton - * */ public class MasqueradeEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(MasqueradeEvent.class); + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(MasqueradeEvent.class); - private final Channel _original; + private final Channel _original; - private final Channel _clone; + private final Channel _clone; - private ChannelState cloneState; + private ChannelState cloneState; - private ChannelState originalState; + private ChannelState originalState; - public MasqueradeEvent(final org.asteriskjava.manager.event.MasqueradeEvent event) throws InvalidChannelName - { - super(event); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + public MasqueradeEvent(final org.asteriskjava.manager.event.MasqueradeEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - this._original = pbx.registerChannel(event.getOriginal(), ChannelImpl.UNKNOWN_UNIQUE_ID); - this._clone = pbx.registerChannel(event.getClone(), ChannelImpl.UNKNOWN_UNIQUE_ID); - this.originalState = ChannelState.valueOf(event.getOriginalStateDesc()); - this.cloneState = ChannelState.valueOf(event.getCloneStateDesc()); - } + this._original = pbx.internalRegisterChannel(event.getOriginal(), ChannelImpl.UNKNOWN_UNIQUE_ID); + this._clone = pbx.internalRegisterChannel(event.getClone(), ChannelImpl.UNKNOWN_UNIQUE_ID); + this.originalState = ChannelState.valueOf(event.getOriginalStateDesc()); + this.cloneState = ChannelState.valueOf(event.getCloneStateDesc()); + } - /** - * Returns the original channel - * - * @return - */ - public Channel getOriginal() - { - return this._original; - } + /** + * Returns the original channel + * + * @return + */ + public Channel getOriginal() + { + return this._original; + } - public Channel getClone() - { - return this._clone; - } + public Channel getClone() + { + return this._clone; + } - public ChannelState getCloneState() - { - return this.cloneState; - } + public ChannelState getCloneState() + { + return this.cloneState; + } - public ChannelState getOriginalState() - { - return this.originalState; - } + public ChannelState getOriginalState() + { + return this.originalState; + } - public String toString() - { - // Even though it talks about the original channel - return "MasqueradeEvent: originalChannel(new):" + this._original + " cloned from (pre-existing):" + this._clone; //$NON-NLS-1$//$NON-NLS-2$ - } + public String toString() + { + // Even though it talks about the original channel + return "MasqueradeEvent: originalChannel(new):" + this._original + " cloned from (pre-existing):" + this._clone; //$NON-NLS-1$//$NON-NLS-2$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewExtenEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewExtenEvent.java index 58c97e3af..174077423 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewExtenEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewExtenEvent.java @@ -8,60 +8,60 @@ public class NewExtenEvent extends ManagerEvent implements ChannelEvent { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(NewExtenEvent.class); + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(NewExtenEvent.class); - private final String context; - private final String extension; - private final String application; - private final String appData; - private final Integer priority; - private final Channel channel; + private final String context; + private final String extension; + private final String application; + private final String appData; + private final Integer priority; + private final Channel channel; - public NewExtenEvent(final org.asteriskjava.manager.event.NewExtenEvent event) throws InvalidChannelName - { - super(event); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + public NewExtenEvent(final org.asteriskjava.manager.event.NewExtenEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - this.channel = pbx.registerChannel(event.getChannel(), event.getUniqueId()); - this.context = event.getContext(); - this.extension = event.getExtension(); - this.application = event.getApplication(); - this.appData = event.getAppData(); - this.priority = event.getPriority(); - } + this.channel = pbx.internalRegisterChannel(event.getChannel(), event.getUniqueId()); + this.context = event.getContext(); + this.extension = event.getExtension(); + this.application = event.getApplication(); + this.appData = event.getAppData(); + this.priority = event.getPriority(); + } - public String getContext() - { - return this.context; - } + public String getContext() + { + return this.context; + } - public String getExtension() - { - return this.extension; - } + public String getExtension() + { + return this.extension; + } - public String getApplication() - { - return this.application; - } + public String getApplication() + { + return this.application; + } - public String getAppData() - { - return this.appData; - } + public String getAppData() + { + return this.appData; + } - public Integer getPriority() - { - return this.priority; - } + public Integer getPriority() + { + return this.priority; + } - @Override - public Channel getChannel() - { - return this.channel; - } + @Override + public Channel getChannel() + { + return this.channel; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ParkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ParkedCallEvent.java index dcd821088..5beb1e5cb 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ParkedCallEvent.java @@ -10,46 +10,46 @@ public class ParkedCallEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(ParkedCallEvent.class); - - private final Channel fromChannel; - private final Integer timeout; - private String exten; - - public ParkedCallEvent(final org.asteriskjava.manager.event.ParkedCallEvent event) throws InvalidChannelName - { - super(event); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - - if (event.getParkerDialString() != null) - this.fromChannel = pbx.registerChannel(event.getParkerDialString(), ChannelImpl.UNKNOWN_UNIQUE_ID); - else - this.fromChannel = null; - this.timeout = event.getTimeout(); - this.exten = event.getExten(); - } - - /** - * The channel that parked the call. In some circumstances this can be null. - * - * @return - */ - public Channel getFromChannel() - { - return this.fromChannel; - } - - public Integer getTimeout() - { - return this.timeout; - } - - public String getExten() - { - return this.exten; - } + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(ParkedCallEvent.class); + + private final Channel fromChannel; + private final Integer timeout; + private String exten; + + public ParkedCallEvent(final org.asteriskjava.manager.event.ParkedCallEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + if (event.getParkerDialString() != null) + this.fromChannel = pbx.internalRegisterChannel(event.getParkerDialString(), ChannelImpl.UNKNOWN_UNIQUE_ID); + else + this.fromChannel = null; + this.timeout = event.getTimeout(); + this.exten = event.getExten(); + } + + /** + * The channel that parked the call. In some circumstances this can be null. + * + * @return + */ + public Channel getFromChannel() + { + return this.fromChannel; + } + + public Integer getTimeout() + { + return this.timeout; + } + + public String getExten() + { + return this.exten; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/RenameEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/RenameEvent.java index d2da6e2b7..97f64072a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/RenameEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/RenameEvent.java @@ -9,51 +9,52 @@ public class RenameEvent extends ManagerEvent implements ChannelEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(RenameEvent.class); - - /** - * The existing channel which is about to be renamed. - */ - private final Channel _channel; - - /** - * New name of the channel after renaming occurred. - */ - private final String _newName; - - public RenameEvent(final org.asteriskjava.manager.event.RenameEvent event) throws InvalidChannelName - { - super(event); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - - this._channel = pbx.registerChannel(event.getChannel(), event.getUniqueId()); - this._newName = event.getNewname(); - - assert ((ChannelProxy) this._channel).getRealChannel().getUniqueId() - .compareToIgnoreCase(event.getUniqueId()) == 0 : "Rename registered against incorrect channel"; //$NON-NLS-1$ - } - - @Override - public final Channel getChannel() - { - return this._channel; - } - - public final String getNewName() - { - return this._newName; - } - - @Override - public String toString() - { - org.asteriskjava.manager.event.RenameEvent rawEvent = (org.asteriskjava.manager.event.RenameEvent) getSource(); - return "RenameEvent: existing channel: " + this._channel + " newname=" + this._newName //$NON-NLS-1$ //$NON-NLS-2$ - + "rawExisting:" + rawEvent.getChannel() + " rawNewname:" + rawEvent.getNewname() //$NON-NLS-1$ //$NON-NLS-2$ - + "rawUniquID:" + rawEvent.getUniqueId(); //$NON-NLS-1$ - } + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(RenameEvent.class); + + /** + * The existing channel which is about to be renamed. + */ + private final Channel _channel; + + /** + * New name of the channel after renaming occurred. + */ + private final String _newName; + + public RenameEvent(final org.asteriskjava.manager.event.RenameEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this._channel = pbx.internalRegisterChannel(event.getChannel(), event.getUniqueId()); + this._newName = event.getNewname(); + + assert ((ChannelProxy) this._channel).getRealChannel().getUniqueId() + .compareToIgnoreCase(event.getUniqueId()) == 0 : "Rename registered against incorrect channel"; //$NON-NLS-1$ + + } + + @Override + public final Channel getChannel() + { + return this._channel; + } + + public final String getNewName() + { + return this._newName; + } + + @Override + public String toString() + { + org.asteriskjava.manager.event.RenameEvent rawEvent = (org.asteriskjava.manager.event.RenameEvent) getSource(); + return "RenameEvent: existing channel: " + this._channel + " newname=" + this._newName //$NON-NLS-1$ //$NON-NLS-2$ + + "rawExisting:" + rawEvent.getChannel() + " rawNewname:" + rawEvent.getNewname() //$NON-NLS-1$ //$NON-NLS-2$ + + "rawUniquID:" + rawEvent.getUniqueId(); //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusEvent.java index d046483bc..9a0b2bc36 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusEvent.java @@ -12,104 +12,104 @@ public class StatusEvent extends ResponseEvent implements ChannelEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(StatusEvent.class); - - private final Channel channel; - private final CallerID callerId; - private final String accountCode; - private final ChannelState channelState; - private final String channelStateDesc; - private final String context; - private final DialPlanExtension extension; - private final Integer priority; - private final Integer seconds; - private final Channel bridgedChannel; - private final Map variables; - private final String uniqueId; - - public StatusEvent(final org.asteriskjava.manager.event.StatusEvent event) throws InvalidChannelName - { - super(event); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - - this.channel = pbx.registerChannel(event.getChannel(), event.getUniqueId()); - this.callerId = pbx.buildCallerID(event.getCallerIdNum(), event.getCallerIdName()); - this.accountCode = event.getAccountCode(); - this.channelState = ChannelState.valueOfDesc(event.getChannelStateDesc()); - this.channelStateDesc = event.getChannelStateDesc(); - this.context = event.getContext(); - this.extension = pbx.buildDialPlanExtension(event.getExtension()); - this.priority = event.getPriority(); - this.seconds = event.getSeconds(); - if (event.getBridgedChannel() != null) - this.bridgedChannel = pbx.registerChannel(event.getBridgedChannel(), event.getBridgedUniqueId()); - else - this.bridgedChannel = null; - this.variables = event.getVariables(); - this.uniqueId = event.getUniqueId(); - } - - @Override - public final Channel getChannel() - { - return this.channel; - } - - public final CallerID getCallerId() - { - return this.callerId; - } - - public final String getAccountCode() - { - return this.accountCode; - } - - public final ChannelState getState() - { - return this.channelState; - } - - public final String getChannelStateDesc() - { - return this.channelStateDesc; - } - - public final String getContext() - { - return this.context; - } - - public final DialPlanExtension getExtension() - { - return this.extension; - } - - public final Integer getPriority() - { - return this.priority; - } - - public final Integer getSeconds() - { - return this.seconds; - } - - public final Channel getBridgedChannel() - { - return this.bridgedChannel; - } - - public final Map getVariables() - { - return this.variables; - } - - public String getUniqueId() - { - return this.uniqueId; - } + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(StatusEvent.class); + + private final Channel channel; + private final CallerID callerId; + private final String accountCode; + private final ChannelState channelState; + private final String channelStateDesc; + private final String context; + private final DialPlanExtension extension; + private final Integer priority; + private final Integer seconds; + private final Channel bridgedChannel; + private final Map variables; + private final String uniqueId; + + public StatusEvent(final org.asteriskjava.manager.event.StatusEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this.channel = pbx.internalRegisterChannel(event.getChannel(), event.getUniqueId()); + this.callerId = pbx.buildCallerID(event.getCallerIdNum(), event.getCallerIdName()); + this.accountCode = event.getAccountCode(); + this.channelState = ChannelState.valueOfDesc(event.getChannelStateDesc()); + this.channelStateDesc = event.getChannelStateDesc(); + this.context = event.getContext(); + this.extension = pbx.buildDialPlanExtension(event.getExtension()); + this.priority = event.getPriority(); + this.seconds = event.getSeconds(); + if (event.getBridgedChannel() != null) + this.bridgedChannel = pbx.internalRegisterChannel(event.getBridgedChannel(), event.getBridgedUniqueId()); + else + this.bridgedChannel = null; + this.variables = event.getVariables(); + this.uniqueId = event.getUniqueId(); + } + + @Override + public final Channel getChannel() + { + return this.channel; + } + + public final CallerID getCallerId() + { + return this.callerId; + } + + public final String getAccountCode() + { + return this.accountCode; + } + + public final ChannelState getState() + { + return this.channelState; + } + + public final String getChannelStateDesc() + { + return this.channelStateDesc; + } + + public final String getContext() + { + return this.context; + } + + public final DialPlanExtension getExtension() + { + return this.extension; + } + + public final Integer getPriority() + { + return this.priority; + } + + public final Integer getSeconds() + { + return this.seconds; + } + + public final Channel getBridgedChannel() + { + return this.bridgedChannel; + } + + public final Map getVariables() + { + return this.variables; + } + + public String getUniqueId() + { + return this.uniqueId; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnparkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnparkedCallEvent.java index 2545c8e23..ba66e85c9 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnparkedCallEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnparkedCallEvent.java @@ -9,24 +9,24 @@ public class UnparkedCallEvent extends AbstractParkedCallEvent { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(UnparkedCallEvent.class); + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(UnparkedCallEvent.class); - private final Channel fromChannel; + private final Channel fromChannel; - public UnparkedCallEvent(final org.asteriskjava.manager.event.UnparkedCallEvent event) throws InvalidChannelName - { - super(event); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + public UnparkedCallEvent(final org.asteriskjava.manager.event.UnparkedCallEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - this.fromChannel = pbx.registerChannel(event.getParkerDialString(), ChannelImpl.UNKNOWN_UNIQUE_ID); - } + this.fromChannel = pbx.internalRegisterChannel(event.getParkerDialString(), ChannelImpl.UNKNOWN_UNIQUE_ID); + } - public Channel getFromChannel() - { - return this.fromChannel; - } + public Channel getFromChannel() + { + return this.fromChannel; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/VarSetEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/VarSetEvent.java index be67ffdb9..2fa547a66 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/VarSetEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/VarSetEvent.java @@ -8,43 +8,43 @@ public class VarSetEvent extends ManagerEvent implements ChannelEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(VarSetEvent.class); - - /** - * The name of the channel. - */ - private final Channel _channel; - - private String _variableName; - - private String _variableValue; - - public VarSetEvent(final org.asteriskjava.manager.event.VarSetEvent event) throws InvalidChannelName - { - super(event); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - this._channel = pbx.registerChannel(event.getChannel(), event.getUniqueId()); - this._variableName = event.getVariable(); - this._variableValue = event.getValue(); - } - - @Override - public Channel getChannel() - { - return this._channel; - } - - public String getVariableName() - { - return this._variableName; - } - - public String getVariableValue() - { - return this._variableValue; - } + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(VarSetEvent.class); + + /** + * The name of the channel. + */ + private final Channel _channel; + + private String _variableName; + + private String _variableValue; + + public VarSetEvent(final org.asteriskjava.manager.event.VarSetEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + this._channel = pbx.internalRegisterChannel(event.getChannel(), event.getUniqueId()); + this._variableName = event.getVariable(); + this._variableValue = event.getValue(); + } + + @Override + public Channel getChannel() + { + return this._channel; + } + + public String getVariableName() + { + return this._variableName; + } + + public String getVariableValue() + { + return this._variableValue; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/userEvents/UserEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/userEvents/UserEvent.java index 9216e2699..58157b81d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/userEvents/UserEvent.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/userEvents/UserEvent.java @@ -9,29 +9,29 @@ public class UserEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(UserEvent.class); + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(UserEvent.class); - private Channel channel; + private Channel channel; - public UserEvent(org.asteriskjava.manager.event.UserEvent source, Channel channel) - { - super(source); - this.channel = channel; - } + public UserEvent(org.asteriskjava.manager.event.UserEvent source, Channel channel) + { + super(source); + this.channel = channel; + } - public UserEvent(org.asteriskjava.manager.event.UserEvent event) throws InvalidChannelName - { - super(event); + public UserEvent(org.asteriskjava.manager.event.UserEvent event) throws InvalidChannelName + { + super(event); - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - this.channel = pbx.registerChannel(event.getChannel(), event.getUniqueId()); - } + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + this.channel = pbx.internalRegisterChannel(event.getChannel(), event.getUniqueId()); + } - public Channel getChannel() - { - return this.channel; - } + public Channel getChannel() + { + return this.channel; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index c594bf50b..a351b7ce7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -239,8 +239,7 @@ public void conference(final Channel channelOne, final Channel channelTwo, final } @Override - public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, - final CallerID toCallerID) + public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID) { final CompletionAdaptor completion = new CompletionAdaptor<>(); @@ -257,8 +256,8 @@ public DialLocalToAgiActivity dialLocalToAgi(final EndPoint from, final CallerID return new DialLocalToAgiActivity(from, fromCallerID, callback, channelVarsToSet); } - public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, - final CallerID toCallerID, final ActivityCallback callback, Map channelVarsToSet) + public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID, + final ActivityCallback callback, Map channelVarsToSet) { final DialActivityImpl dialer = new DialActivityImpl(from, to, toCallerID, false, callback, channelVarsToSet); return dialer; @@ -276,10 +275,10 @@ public void dial(final EndPoint from, final CallerID fromCallerID, final EndPoin * Convenience method to hangup the call without having to extract the * channel yourself. */ - public void hangup(Call call) throws PBXException - { - this.hangup(call.getOriginatingParty()); - } + public void hangup(Call call) throws PBXException + { + this.hangup(call.getOriginatingParty()); + } @Override public void hangup(final Channel channel) throws PBXException @@ -511,15 +510,50 @@ public CallerID buildCallerID(final AbstractChannelEvent event) } public ChannelProxy registerChannel(final String channelName, final String uniqueID) throws InvalidChannelName + { + ChannelProxy proxy = findChannel(cleanChannelName(channelName), null); + if (proxy == null) + { + logger.info("Couldn't find the channel " + channelName + ", creating it"); + proxy = internalRegisterChannel(channelName, uniqueID); + } + else + { + if (uniqueID != null && !uniqueID.equals(proxy.getUniqueId())) + { + logger.warn( + "Found the channel(" + proxy.getUniqueId() + "), but with a different uniqueId (" + uniqueID + ")"); + + } + } + liveChannels.sanityCheck(); + + return proxy; + } + + /** + * This method is not part of the public API.
+ *
+ * Use registerChannel instead calling this method with an incorrect or + * stale uniqueId will cause inconsistent behaviour. + * + * @param channelName + * @param uniqueID + * @return + * @throws InvalidChannelName + */ + public ChannelProxy internalRegisterChannel(final String channelName, final String uniqueID) throws InvalidChannelName { ChannelProxy proxy = null; synchronized (this.liveChannels) { + String localUniqueID = (uniqueID == null ? ChannelImpl.UNKNOWN_UNIQUE_ID : uniqueID); proxy = this.findChannel(cleanChannelName(channelName), localUniqueID); if (proxy == null) { proxy = new ChannelProxy(new ChannelImpl(channelName, localUniqueID)); + logger.info("Creating new Channel Proxy " + proxy); this.liveChannels.add(proxy); proxy.addHangupListener(this); } @@ -528,9 +562,7 @@ public ChannelProxy registerChannel(final String channelName, final String uniqu } /** - * Cleans up the channel name by applying the following: 1) trim any - * whitespace 2) convert to upper case for easy string comparisions 3) strip - * of the masquerade prefix if it exists 4) strip the zombie suffix. + * remove white space * * @param name * @return @@ -539,16 +571,7 @@ private String cleanChannelName(final String name) { String cleanedName = name.trim().toUpperCase(); - for (final String prefix : ChannelImpl._actions) - { - if (cleanedName.startsWith(prefix)) - { - cleanedName = cleanedName.substring(prefix.length()); - break; - } - } - - return name; + return cleanedName; } public Channel registerHangupChannel(String channel, String uniqueId) throws InvalidChannelName @@ -557,7 +580,7 @@ public Channel registerHangupChannel(String channel, String uniqueId) throws Inv synchronized (this.liveChannels) { newChannel = this.findChannel(channel, uniqueId); - if (channel == null) + if (newChannel == null) { // WE don't add this channel to the liveChannels as it is in the // process @@ -573,37 +596,6 @@ public Channel registerHangupChannel(String channel, String uniqueId) throws Inv return newChannel; } - // @Override - // public iChannel registerChannel(AsteriskChannel asteriskChannel) throws - // InvalidChannelName - // { - // ChannelProxy proxy = null; - // synchronized (this.liveChannels) - // { - // proxy = this.findChannel(asteriskChannel.getName(), - // asteriskChannel.getId()); - // if (proxy == null) - // { - // proxy = new ChannelProxy(new Channel(asteriskChannel)); - // this.liveChannels.add(proxy); - // proxy.addListener(this); - // } - // else - // { - // // update the channel - // proxy.getRealChannel().updateAsteriskChannel(asteriskChannel); - // } - // } - // return proxy; - // - // } - - // public void onNewChannel(AsteriskChannel asteriskChannel) throws - // InvalidChannelName - // { - // registerChannel(asteriskChannel); - // } - // public ChannelProxy findChannel(final String channelName, final String uniqueID) { return this.liveChannels.findChannel(channelName, uniqueID); @@ -702,7 +694,7 @@ public boolean isChannel(String channelName) boolean isChannel = false; try { - registerChannel(channelName, ChannelImpl.UNKNOWN_UNIQUE_ID); + internalRegisterChannel(channelName, ChannelImpl.UNKNOWN_UNIQUE_ID); isChannel = true; } catch (InvalidChannelName e) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelEventHelper.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelEventHelper.java index 052950fd9..8810965b4 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelEventHelper.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelEventHelper.java @@ -8,52 +8,51 @@ public abstract class ChannelEventHelper extends ManagerEvent implements ChannelEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(ChannelEventHelper.class); - - /** - * The name of the channel. - */ - private final ChannelProxy channel; - - protected ChannelEventHelper(final org.asteriskjava.manager.event.AbstractChannelEvent event) - throws InvalidChannelName - { - this(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); - } - - protected ChannelEventHelper(final String channel, final String uniqueId, final String callerIdNum, - final String callerIdName) throws InvalidChannelName - { - super(channel); // we must have a source but since don't have one pass - // anything. - this.channel = ChannelEventHelper.registerChannel(channel, uniqueId, callerIdNum, callerIdName); - } - - public ChannelEventHelper(final String channel, final String uniqueId) throws InvalidChannelName - { - super(channel);// we must have a source but since don't have one pass - // anything. - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - - this.channel = pbx.registerChannel(channel, uniqueId); - } - - @Override - public ChannelProxy getChannel() - { - return this.channel; - } - - public static ChannelProxy registerChannel(final String channelName, final String uniqueId, - final String callerIdNum, final String callerIdName) throws InvalidChannelName - { - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - - final ChannelProxy channel = pbx.registerChannel(channelName, uniqueId); - channel.getRealChannel().setCallerId(pbx.buildCallerID(callerIdNum, callerIdName)); - return channel; - } + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(ChannelEventHelper.class); + + /** + * The name of the channel. + */ + private final ChannelProxy channel; + + protected ChannelEventHelper(final org.asteriskjava.manager.event.AbstractChannelEvent event) throws InvalidChannelName + { + this(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + } + + protected ChannelEventHelper(final String channel, final String uniqueId, final String callerIdNum, + final String callerIdName) throws InvalidChannelName + { + super(channel); // we must have a source but since don't have one pass + // anything. + this.channel = ChannelEventHelper.registerChannel(channel, uniqueId, callerIdNum, callerIdName); + } + + public ChannelEventHelper(final String channel, final String uniqueId) throws InvalidChannelName + { + super(channel);// we must have a source but since don't have one pass + // anything. + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this.channel = pbx.internalRegisterChannel(channel, uniqueId); + } + + @Override + public ChannelProxy getChannel() + { + return this.channel; + } + + public static ChannelProxy registerChannel(final String channelName, final String uniqueId, final String callerIdNum, + final String callerIdName) throws InvalidChannelName + { + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + final ChannelProxy channel = pbx.internalRegisterChannel(channelName, uniqueId); + channel.getRealChannel().setCallerId(pbx.buildCallerID(callerIdNum, callerIdName)); + return channel; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index f82974308..5f9b48735 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -17,17 +17,21 @@ /** * TODO set the channel unique id when registering against an existing channel - * which doesn't have its unique id set. Create a single asterisk event source. - * All users of MyBaseEventCalls will become listeners to this class rather than - * talking to asterisk directly. Each listener will have events queued to it. It - * can process these events in a separate thread. Key feature is that one a - * 'rename' event arrives we must pause all of the queues wait for them to empty - * and for the queue clients to quiescent, then apply the rename before resuming - * pushing data in to the queues. Additionally we need to redo the asterisk - * events classes with our own classes that pass around an iChannel rather than - * a raw channel name. By doing this the rename affectively becomes global - * updating every instance of the channel (because they actually only have an - * instance handle). + * which doesn't have its unique id set.
+ *
+ * Create a single asterisk event source. All users of MyBaseEventCalls will + * become listeners to this class rather than talking to asterisk directly. Each + * listener will have events queued to it. It can process these events in a + * separate thread.
+ *
+ * Key feature is that one a 'rename' event arrives we must pause all of the + * queues wait for them to empty and for the queue clients to quiescent, then + * apply the rename before resuming pushing data in to the queues.
+ *
+ * Additionally we need to redo the asterisk events classes with our own classes + * that pass around an iChannel rather than a raw channel name. By doing this + * the rename affectively becomes global updating every instance of the channel + * (because they actually only have an instance handle). * * @author bsutton */ @@ -222,6 +226,7 @@ else if (this._callerID != null && ((ChannelImpl) channel)._callerID != null) private void setChannelName(final String channelName) throws InvalidChannelName { + logger.info("Renamed channel from " + this._channelName + " to " + channelName); this._channelName = this.cleanChannelName(channelName); this.validateChannelName(this._channelName); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index 4aae04dd2..aac42341b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -221,7 +221,7 @@ public void masquerade(ChannelProxy cloneProxy) throws InvalidChannelName this._channel.addHangupListener(this); cloneProxy._channel.addHangupListener(cloneProxy); - logger.info("Channel proxy now points to " + this._channel); + logger.info(originalChannel + " Channel proxy now points to " + this._channel); } public ChannelImpl getRealChannel() diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index 0e323b8ca..a3a6c8be1 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -2,9 +2,11 @@ import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import org.apache.log4j.Logger; +import org.apache.log4j.Priority; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; @@ -48,264 +50,316 @@ */ public class LiveChannelManager implements FilteredManagerListener { - private static final Logger logger = Logger.getLogger(LiveChannelManager.class); - - /** - * A collection of all of the live proxies in the system. We monitor the - * channels and remove them as they hangup. The hash is keyed by the - * channel's name. e.g. SIP/100-000000100 - */ - private final List _liveChannels = new CopyOnWriteArrayList<>(); - - public LiveChannelManager() - { - CoherentManagerConnection.getInstance().addListener(this); - } - - public ChannelProxy getChannelByEndPoint(EndPoint endPoint) - { - ChannelProxy connectedChannel = null; - for (final ChannelProxy channel : _liveChannels) - { - if (channel.isConnectedTo(endPoint)) - { - connectedChannel = channel; - break; - } - - } - return connectedChannel; - } - - public void add(ChannelProxy proxy) - { - synchronized (this._liveChannels) - { - ChannelProxy index = findProxy(proxy); - if (index == null) - this._liveChannels.add(proxy); - } - logger.info("Adding liveChannel " + proxy); - - dumpProxies(proxy, "Add"); //$NON-NLS-1$ - - } - - private void dumpProxies(ChannelProxy proxy, String cause) - { - if (logger.isDebugEnabled()) - { - logger.debug("Dump of LiveChannels, cause:" + cause + ": " + proxy); //$NON-NLS-1$ //$NON-NLS-2$ - for (ChannelProxy aProxy : _liveChannels) - { - logger.debug("ChannelProxy: " + aProxy); //$NON-NLS-1$ - } - } - } - - public void remove(ChannelProxy proxy) - { - - ChannelProxy index = findProxy(proxy); - if (index != null) - { - logger.error("Removing liveChannel " + proxy); - this._liveChannels.remove(index); - } - dumpProxies(proxy, "Removing"); //$NON-NLS-1$ - - } - - public ChannelProxy findChannel(String extendedChannelName, String uniqueID) - { - ChannelProxy proxy = null; - - String localUniqueId = uniqueID; - if (localUniqueId == null) - localUniqueId = ChannelImpl.UNKNOWN_UNIQUE_ID; - - // In order to get the 'best' match we first match each by unique id. - // Sometimes we can have two channels with the same name but - // different - - if (localUniqueId.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) - { - - for (ChannelProxy aChannel : _liveChannels) - { - if (aChannel.sameUniqueID(localUniqueId)) - { - proxy = aChannel; - break; - } - } - } - - // If we don't have a match from the first pass and the new uniqueID - // is unknown - // then do a search matching by name. - if (proxy == null) - { - for (ChannelProxy aChannel : _liveChannels) - { - - if (aChannel.isSame(extendedChannelName, localUniqueId)) - { - proxy = aChannel; - break; - } - } - } - - return proxy; - } - - private ChannelProxy findProxy(Channel original) - { - for (ChannelProxy aChannel : _liveChannels) - { - if (aChannel.isSame(original)) - { - return aChannel; - } - } - return null; - } - - @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); - - required.add(MasqueradeEvent.class); - required.add(RenameEvent.class); - required.add(HangupEvent.class); - - return required; - } - - ChannelProxy findProxyById(String id) - { - for (ChannelProxy aChannel : _liveChannels) - { - if (("" + aChannel.getIdentity()).equals(id)) - { - return aChannel; - } - } - return null; - } - - @Override - public void onManagerEvent(ManagerEvent event) - { - if (event instanceof MasqueradeEvent) - { - MasqueradeEvent masq = (MasqueradeEvent) event; - ChannelProxy originalIndex = findProxy(masq.getOriginal()); - ChannelProxy cloneIndex = findProxy(masq.getClone()); - if (originalIndex != null && cloneIndex != null) - { - ChannelProxy originalProxy = (ChannelProxy) masq.getOriginal(); - ChannelProxy cloneProxy = (ChannelProxy) masq.getClone(); - try - { - // After the masquerade the two underlying channels will - // have been switched - // between the two proxies. - // At this point the cloneProxy will be owned by a Peer - // (as they process NewChannelEvents) - // as such we cannot just discard the cloneProxy. The - // simplest solution then - // is to put the clone channel into the existing - // channel, as this is the core reason we have a proxy, - // and then put the original channel into the - // cloneProxy. At the end of this manuvour - // the Peer will still have two proxy which point to the - // two different channels. - // This is fine for the Peer as it doesn't attach any - // special meaning to any channel - // it just needs a list of all channels associated with - // the Peer. - // The original channel will shortly receive a hangup in - // which case the Peer will - // remove it from its list of channels and the Peer will - // be back to having - // one channel which will be the clone channel which is - // now the active channel - // and everyone will be happy. - originalProxy.masquerade(cloneProxy); - dumpProxies(cloneProxy, "Masquerade"); //$NON-NLS-1$ - } - catch (InvalidChannelName e) - { - logger.error(e, e); - - } - - } - else - logger.error("Either the clone or original channelProxy was missing during a masquerade: cloneIndex=" //$NON-NLS-1$ - + cloneIndex + " originalIndex=" + originalIndex); //$NON-NLS-1$ - - } - if (event instanceof RenameEvent) - { - RenameEvent rename = (RenameEvent) event; - - ChannelProxy oldChannel = findProxy(rename.getChannel()); - if (oldChannel != null) - { - try - { - oldChannel.rename(rename.getNewName()); - dumpProxies(oldChannel, "RenameEvent"); //$NON-NLS-1$ - } - catch (InvalidChannelName e) - { - logger.error(e, e); - } - } - } - else if (event instanceof HangupEvent) - { - // We need to process every hangup event that goes through the - // system - // as the LiveChannelManager has a Channel added for every channel - // that is created via Asterisk even if it has nothing to - // do with NJR. This is because channels are created - // whenever an event arrives before we actually can determine - // if we are interested in the event and its associated channels. - HangupEvent hangup = (HangupEvent) event; - // Yes I've seen a hangup where the channel was null, who knows - // why? - - if (hangup.getChannel() != null) - { - - ChannelProxy proxy = findProxy(hangup.getChannel()); - if (proxy != null) - { - this._liveChannels.remove(proxy); - logger.info("Removing liveChannel " + proxy); - proxy.getChannel().notifyHangupListeners(hangup.getCause(), hangup.getCauseTxt()); - dumpProxies(proxy, "HangupEvent"); //$NON-NLS-1$ - } - - } - } - } - - @Override - public String getName() - { - return "LiveChannelManager"; //$NON-NLS-1$ - } - - @Override - public ListenerPriority getPriority() - { - return ListenerPriority.CRITICAL; - } + private static final Logger logger = Logger.getLogger(LiveChannelManager.class); + + /** + * A collection of all of the live proxies in the system. We monitor the + * channels and remove them as they hangup. The hash is keyed by the + * channel's name. e.g. SIP/100-000000100 + */ + private final List _liveChannels = new CopyOnWriteArrayList<>(); + + public LiveChannelManager() + { + CoherentManagerConnection.getInstance().addListener(this); + } + + public ChannelProxy getChannelByEndPoint(EndPoint endPoint) + { + ChannelProxy connectedChannel = null; + for (final ChannelProxy channel : _liveChannels) + { + if (channel.isConnectedTo(endPoint)) + { + connectedChannel = channel; + break; + } + + } + return connectedChannel; + } + + public void add(ChannelProxy proxy) + { + synchronized (this._liveChannels) + { + ChannelProxy index = findProxy(proxy); + if (index == null) + this._liveChannels.add(proxy); + } + logger.info("Adding liveChannel " + proxy); + + dumpProxies(proxy, "Add"); //$NON-NLS-1$ + sanityCheck(); + + } + + private void dumpProxies(ChannelProxy proxy, String cause) + { + if (logger.isDebugEnabled()) + { + logger.debug("Dump of LiveChannels, cause:" + cause + ": " + proxy); //$NON-NLS-1$ //$NON-NLS-2$ + for (ChannelProxy aProxy : _liveChannels) + { + logger.debug("ChannelProxy: " + aProxy); //$NON-NLS-1$ + } + } + } + + public void remove(ChannelProxy proxy) + { + + ChannelProxy index = findProxy(proxy); + if (index != null) + { + logger.info("Removing liveChannel " + proxy); + this._liveChannels.remove(index); + } + dumpProxies(proxy, "Removing"); //$NON-NLS-1$ + + } + + public ChannelProxy findChannel(String extendedChannelName, String uniqueID) + { + ChannelProxy proxy = null; + logger.info("Trying to find channel " + extendedChannelName + " " + uniqueID); + + String localUniqueId = uniqueID; + if (localUniqueId == null) + localUniqueId = ChannelImpl.UNKNOWN_UNIQUE_ID; + + // In order to get the 'best' match we first match each by unique id. + // Sometimes we can have two channels with the same name but + // different + + if (localUniqueId.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) + { + + for (ChannelProxy aChannel : _liveChannels) + { + if (aChannel.sameUniqueID(localUniqueId)) + { + proxy = aChannel; + break; + } + } + } + + // If we don't have a match from the first pass and the new uniqueID + // is unknown + // then do a search matching by name. + if (proxy == null) + { + for (ChannelProxy aChannel : _liveChannels) + { + + if (aChannel.isSame(extendedChannelName, localUniqueId)) + { + proxy = aChannel; + break; + } + } + } + + if (proxy == null) + { + logger.info("Failed to match channel to any of..."); + for (ChannelProxy aChannel : _liveChannels) + { + logger.info(aChannel); + } + + } + + return proxy; + } + + private ChannelProxy findProxy(Channel original) + { + for (ChannelProxy aChannel : _liveChannels) + { + if (aChannel.isSame(original)) + { + return aChannel; + } + } + return null; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + required.add(MasqueradeEvent.class); + required.add(RenameEvent.class); + required.add(HangupEvent.class); + + return required; + } + + ChannelProxy findProxyById(String id) + { + for (ChannelProxy aChannel : _liveChannels) + { + if (("" + aChannel.getIdentity()).equals(id)) + { + return aChannel; + } + } + return null; + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + if (event instanceof MasqueradeEvent) + { + MasqueradeEvent masq = (MasqueradeEvent) event; + ChannelProxy originalIndex = findProxy(masq.getOriginal()); + ChannelProxy cloneIndex = findProxy(masq.getClone()); + if (originalIndex != null && cloneIndex != null) + { + ChannelProxy originalProxy = (ChannelProxy) masq.getOriginal(); + ChannelProxy cloneProxy = (ChannelProxy) masq.getClone(); + try + { + // After the masquerade the two underlying channels will + // have been switched + // between the two proxies. + // At this point the cloneProxy will be owned by a Peer + // (as they process NewChannelEvents) + // as such we cannot just discard the cloneProxy. The + // simplest solution then + // is to put the clone channel into the existing + // channel, as this is the core reason we have a proxy, + // and then put the original channel into the + // cloneProxy. At the end of this manuvour + // the Peer will still have two proxy which point to the + // two different channels. + // This is fine for the Peer as it doesn't attach any + // special meaning to any channel + // it just needs a list of all channels associated with + // the Peer. + // The original channel will shortly receive a hangup in + // which case the Peer will + // remove it from its list of channels and the Peer will + // be back to having + // one channel which will be the clone channel which is + // now the active channel + // and everyone will be happy. + originalProxy.masquerade(cloneProxy); + dumpProxies(cloneProxy, "Masquerade"); //$NON-NLS-1$ + sanityCheck(); + } + catch (InvalidChannelName e) + { + logger.error(e, e); + + } + + } + else + logger.error("Either the clone or original channelProxy was missing during a masquerade: cloneIndex=" //$NON-NLS-1$ + + cloneIndex + " originalIndex=" + originalIndex); //$NON-NLS-1$ + + } + if (event instanceof RenameEvent) + { + RenameEvent rename = (RenameEvent) event; + + ChannelProxy oldChannel = findProxy(rename.getChannel()); + if (oldChannel != null) + { + try + { + oldChannel.rename(rename.getNewName()); + dumpProxies(oldChannel, "RenameEvent"); //$NON-NLS-1$ + sanityCheck(); + } + catch (InvalidChannelName e) + { + logger.error(e, e); + } + } + else + { + logger.warn("Unable to rename channel -> Failed to find channel " + rename.getChannel()); + } + } + else if (event instanceof HangupEvent) + { + // We need to process every hangup event that goes through the + // system + // as the LiveChannelManager has a Channel added for every channel + // that is created via Asterisk even if it has nothing to + // do with NJR. This is because channels are created + // whenever an event arrives before we actually can determine + // if we are interested in the event and its associated channels. + HangupEvent hangup = (HangupEvent) event; + // Yes I've seen a hangup where the channel was null, who knows + // why? + + if (hangup.getChannel() != null) + { + + ChannelProxy proxy = findProxy(hangup.getChannel()); + if (proxy != null) + { + this._liveChannels.remove(proxy); + logger.info("Removing liveChannel " + proxy); + proxy.getChannel().notifyHangupListeners(hangup.getCause(), hangup.getCauseTxt()); + dumpProxies(proxy, "HangupEvent"); //$NON-NLS-1$ + } + + } + else + { + logger.error("Didn't remove hungup channel"); + } + } + } + + @Override + public String getName() + { + return "LiveChannelManager"; //$NON-NLS-1$ + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.CRITICAL; + } + + @SuppressWarnings("deprecation") + public void sanityCheck() + { + + if (logger.isEnabledFor(Priority.INFO)) + { + logger.error("Performing Sanity Check"); + Set channels = new HashSet<>(); + for (ChannelProxy channel : _liveChannels) + { + if (!channels.add(channel.getChannel().getExtendedChannelName())) + { + logger.error( + "Multiple channels by the name " + channel.getChannel().getExtendedChannelName() + " exist"); + for (ChannelProxy channel2 : _liveChannels) + { + if (channel2.getChannel().getExtendedChannelName() + .equals(channel.getChannel().getExtendedChannelName())) + { + logger.error(channel2); + } + } + Exception ex = new Exception("called from here"); + logger.error(ex, ex); + } + + } + } + } } From 5db12d2b1022a34ae3f523ea39df24287501ee37 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 26 Oct 2016 10:09:16 +1100 Subject: [PATCH 063/802] fix for trunk string --- .../java/org/asteriskjava/pbx/internal/core/EndPointImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java index 23afa97fc..172babbd7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java @@ -154,8 +154,8 @@ public EndPointImpl(TechType defaultTech, Trunk trunk, String endPointName) throw new IllegalArgumentException("defaultTech may not be DIALPLAN, LOCAL or CONSOLE"); } - this._fullyQualifiedName = this._tech.name() + EndPointImpl.DELIMITER + trunk + EndPointImpl.DELIMITER - + this._endPointName; + this._fullyQualifiedName = this._tech.name() + EndPointImpl.DELIMITER + trunk.getTrunkAsString() + + EndPointImpl.DELIMITER + this._endPointName; this._empty = false; From 47a5b84e2c01311f9ae429c76829c68bae67bc03 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 26 Oct 2016 13:42:16 +1100 Subject: [PATCH 064/802] refactored to satisfy the bnd requirements --- .../examples/activities/BlindTransfer.java | 2 +- .../examples/activities/Dial.java | 2 +- .../activities/ExamplesAsteriskSettings.java | 2 +- .../examples/activities/Hold.java | 2 +- .../agi => }/AgiChannelActivityAction.java | 3 +- .../asterisk => }/AsteriskSettings.java | 2 +- .../java/org/asteriskjava/pbx/Channel.java | 350 +++++++++--------- .../core => }/DialPlanExtension.java | 3 +- .../java/org/asteriskjava/pbx/EndPoint.java | 2 - .../asterisk => }/InvalidChannelName.java | 2 +- .../{internal/core => }/ListenerPriority.java | 2 +- src/main/java/org/asteriskjava/pbx/PBX.java | 1 - .../java/org/asteriskjava/pbx/PBXFactory.java | 1 - .../pbx/{internal/core => }/TechType.java | 3 +- .../pbx/{internal => }/agi/ActivityAgi.java | 8 +- .../agi/AgiChannelActivityBlindTransfer.java | 3 +- .../agi/AgiChannelActivityBridge.java | 3 +- .../agi/AgiChannelActivityDial.java | 3 +- .../agi/AgiChannelActivityHangup.java | 3 +- .../agi/AgiChannelActivityHold.java | 3 +- .../agi/AgiChannelActivityHoldForBridge.java | 3 +- .../agi/AgiChannelActivityMeetme.java | 7 +- .../agi/AgiChannelActivityQueue.java | 7 +- .../agi/AgiChannelActivityVoicemail.java | 3 +- .../pbx/{internal => }/agi/NJAgiScript.java | 2 +- .../pbx/{internal => }/agi/RateLimiter.java | 2 +- .../wrap/actions/AbstractManagerAction.java | 2 +- .../asterisk/wrap/actions/BridgeAction.java | 2 +- .../asterisk/wrap/actions/CommandAction.java | 2 +- .../wrap/actions/ConfbridgeListAction.java | 2 +- .../asterisk/wrap/actions/DbGetAction.java | 2 +- .../wrap/actions/EventGeneratingAction.java | 2 +- .../asterisk/wrap/actions/GetVarAction.java | 2 +- .../asterisk/wrap/actions/HangupAction.java | 2 +- .../wrap/actions/ListCommandsAction.java | 2 +- .../asterisk/wrap/actions/ManagerAction.java | 2 +- .../asterisk/wrap/actions/MonitorAction.java | 2 +- .../wrap/actions/OriginateAction.java | 2 +- .../asterisk/wrap/actions/PingAction.java | 2 +- .../asterisk/wrap/actions/PlayDtmfAction.java | 2 +- .../asterisk/wrap/actions/RedirectAction.java | 2 +- .../asterisk/wrap/actions/SetVarAction.java | 2 +- .../asterisk/wrap/actions/SipPeersAction.java | 2 +- .../wrap/actions/SipShowPeerAction.java | 2 +- .../asterisk/wrap/actions/StatusAction.java | 2 +- .../wrap/actions/UserEventAction.java | 4 +- .../events/AbstractChannelStateEvent.java | 5 +- .../wrap/events/AbstractMeetMeEvent.java | 5 +- .../wrap/events/AbstractParkedCallEvent.java | 5 +- .../wrap/events/AgentCalledEvent.java | 5 +- .../wrap/events/AgentConnectEvent.java | 5 +- .../asterisk/wrap/events/BridgeEvent.java | 14 +- .../asterisk/wrap/events/ChannelEvent.java | 2 +- .../wrap/events}/ChannelEventHelper.java | 18 +- .../asterisk/wrap/events/ChannelState.java | 2 +- .../events/ConfbridgeListCompleteEvent.java | 2 +- .../wrap/events/ConfbridgeListEvent.java | 2 +- .../asterisk/wrap/events/ConnectEvent.java | 2 +- .../wrap/events/DbGetResponseEvent.java | 2 +- .../asterisk/wrap/events/DialEvent.java | 11 +- .../asterisk/wrap/events/DisconnectEvent.java | 2 +- .../asterisk/wrap/events/DndStateEvent.java | 4 +- .../wrap/events/ExtensionStatusEvent.java | 2 +- .../asterisk/wrap/events/HangupEvent.java | 4 +- .../asterisk/wrap/events/LinkEvent.java | 4 +- .../asterisk/wrap/events/ManagerEvent.java | 2 +- .../asterisk/wrap/events/MasqueradeEvent.java | 4 +- .../asterisk/wrap/events/MeetMeJoinEvent.java | 4 +- .../wrap/events/MeetMeLeaveEvent.java | 4 +- .../asterisk/wrap/events/NewChannelEvent.java | 4 +- .../asterisk/wrap/events/NewExtenEvent.java | 4 +- .../asterisk/wrap/events/NewStateEvent.java | 29 ++ .../wrap/events/OriginateResponseEvent.java | 7 +- .../asterisk/wrap/events/ParkedCallEvent.java | 4 +- .../asterisk/wrap/events/PeerEntryEvent.java | 4 +- .../asterisk/wrap/events/PeerStatusEvent.java | 2 +- .../wrap/events/PeerlistCompleteEvent.java | 2 +- .../wrap/events/QueueCallerLeaveEvent.java | 5 +- .../asterisk/wrap/events/RenameEvent.java | 4 +- .../asterisk/wrap/events/ResponseEvent.java | 2 +- .../asterisk/wrap/events/ResponseEvents.java | 2 +- .../wrap/events/StatusCompleteEvent.java | 2 +- .../asterisk/wrap/events/StatusEvent.java | 6 +- .../asterisk/wrap/events/UnlinkEvent.java | 4 +- .../wrap/events/UnparkedCallEvent.java | 4 +- .../asterisk/wrap/events/VarSetEvent.java | 4 +- .../wrap/response/CommandResponse.java | 2 +- .../asterisk/wrap/response/ManagerError.java | 2 +- .../wrap/response/ManagerResponse.java | 2 +- .../asterisk/wrap/userEvents/UserEvent.java | 6 +- .../activity}/ActivityHelper.java | 10 +- .../activity}/BlindTransferActivityImpl.java | 22 +- .../activity}/BridgeActivityImpl.java | 17 +- .../activity}/DialActivityImpl.java | 13 +- .../activity}/DialToAgiActivityImpl.java | 13 +- .../activity}/HoldActivityImpl.java | 9 +- .../activity}/JoinActivityImpl.java | 7 +- .../activity}/ParkActivityImpl.java | 17 +- .../activity}/SplitActivityImpl.java | 13 +- .../internal/asterisk/MeetmeRoomControl.java | 23 +- .../asterisk/wrap/events/NewStateEvent.java | 28 -- .../pbx/internal/core/AsteriskPBX.java | 54 +-- .../pbx/internal/core/CallTracker.java | 2 +- .../pbx/internal/core/ChannelImpl.java | 13 +- .../pbx/internal/core/ChannelProxy.java | 13 +- .../internal/core/CoherentEventFactory.java | 70 ++-- .../core/CoherentManagerConnection.java | 23 +- .../core/CoherentManagerEventListener.java | 2 +- .../core/CoherentManagerEventQueue.java | 2 +- .../internal/core/DialLocalToAgiActivity.java | 17 +- .../pbx/internal/core/EndPointImpl.java | 1 + .../core/FilteredManagerListener.java | 3 +- .../pbx/internal/core/LiveChannelManager.java | 11 +- .../asteriskjava/pbx/internal/core/Peer.java | 8 +- .../pbx/internal/core/PeerMonitor.java | 25 +- .../pbx/internal/core/PeerState.java | 2 +- .../pbx/internal/managerAPI/Connector.java | 2 +- .../pbx/internal/managerAPI/Dial.java | 14 +- .../pbx/internal/managerAPI/DialToAgi.java | 8 +- .../managerAPI/EventListenerBaseClass.java | 2 +- .../pbx/internal/managerAPI/HoldAtAgi.java | 2 +- .../pbx/internal/managerAPI/MonitorCall.java | 2 +- .../managerAPI/OriginateBaseClass.java | 22 +- .../managerAPI/OriginateToExtension.java | 4 +- .../pbx/internal/managerAPI/RedirectCall.java | 8 +- .../internal/managerAPI/RedirectToMeetMe.java | 2 +- .../{internal => }/agi/RateLimiterTest.java | 4 +- 127 files changed, 591 insertions(+), 574 deletions(-) rename src/main/java/org/asteriskjava/pbx/{internal/agi => }/AgiChannelActivityAction.java (78%) rename src/main/java/org/asteriskjava/pbx/{internal/asterisk => }/AsteriskSettings.java (98%) rename src/main/java/org/asteriskjava/pbx/{internal/core => }/DialPlanExtension.java (95%) rename src/main/java/org/asteriskjava/pbx/{internal/asterisk => }/InvalidChannelName.java (78%) rename src/main/java/org/asteriskjava/pbx/{internal/core => }/ListenerPriority.java (96%) rename src/main/java/org/asteriskjava/pbx/{internal/core => }/TechType.java (96%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/ActivityAgi.java (93%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/AgiChannelActivityBlindTransfer.java (92%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/AgiChannelActivityBridge.java (93%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/AgiChannelActivityDial.java (93%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/AgiChannelActivityHangup.java (91%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/AgiChannelActivityHold.java (94%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/AgiChannelActivityHoldForBridge.java (93%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/AgiChannelActivityMeetme.java (92%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/AgiChannelActivityQueue.java (91%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/AgiChannelActivityVoicemail.java (88%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/NJAgiScript.java (97%) rename src/main/java/org/asteriskjava/pbx/{internal => }/agi/RateLimiter.java (95%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/AbstractManagerAction.java (90%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/BridgeAction.java (89%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/CommandAction.java (86%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/ConfbridgeListAction.java (91%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/DbGetAction.java (88%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/EventGeneratingAction.java (68%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/GetVarAction.java (89%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/HangupAction.java (88%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/ListCommandsAction.java (90%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/ManagerAction.java (73%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/MonitorAction.java (90%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/OriginateAction.java (93%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/PingAction.java (89%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/PlayDtmfAction.java (89%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/RedirectAction.java (94%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/SetVarAction.java (91%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/SipPeersAction.java (87%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/SipShowPeerAction.java (87%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/StatusAction.java (92%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/actions/UserEventAction.java (76%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/AbstractChannelStateEvent.java (80%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/AbstractMeetMeEvent.java (78%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/AbstractParkedCallEvent.java (80%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/AgentCalledEvent.java (79%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/AgentConnectEvent.java (79%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/BridgeEvent.java (85%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/ChannelEvent.java (63%) rename src/main/java/org/asteriskjava/pbx/{internal/core => asterisk/wrap/events}/ChannelEventHelper.java (72%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/ChannelState.java (91%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/ConfbridgeListCompleteEvent.java (81%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/ConfbridgeListEvent.java (89%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/ConnectEvent.java (90%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/DbGetResponseEvent.java (92%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/DialEvent.java (79%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/DisconnectEvent.java (85%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/DndStateEvent.java (90%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/ExtensionStatusEvent.java (96%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/HangupEvent.java (91%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/LinkEvent.java (75%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/ManagerEvent.java (84%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/MasqueradeEvent.java (98%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/MeetMeJoinEvent.java (84%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/MeetMeLeaveEvent.java (87%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/NewChannelEvent.java (89%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/NewExtenEvent.java (92%) create mode 100644 src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/OriginateResponseEvent.java (90%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/ParkedCallEvent.java (91%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/PeerEntryEvent.java (85%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/PeerStatusEvent.java (92%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/PeerlistCompleteEvent.java (86%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/QueueCallerLeaveEvent.java (77%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/RenameEvent.java (93%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/ResponseEvent.java (91%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/ResponseEvents.java (88%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/StatusCompleteEvent.java (86%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/StatusEvent.java (94%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/UnlinkEvent.java (75%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/UnparkedCallEvent.java (87%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/events/VarSetEvent.java (90%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/response/CommandResponse.java (88%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/response/ManagerError.java (82%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/response/ManagerResponse.java (96%) rename src/main/java/org/asteriskjava/pbx/{internal => }/asterisk/wrap/userEvents/UserEvent.java (82%) rename src/main/java/org/asteriskjava/pbx/{activities => internal/activity}/ActivityHelper.java (91%) rename src/main/java/org/asteriskjava/pbx/{activities => internal/activity}/BlindTransferActivityImpl.java (91%) rename src/main/java/org/asteriskjava/pbx/{activities => internal/activity}/BridgeActivityImpl.java (87%) rename src/main/java/org/asteriskjava/pbx/{activities => internal/activity}/DialActivityImpl.java (92%) rename src/main/java/org/asteriskjava/pbx/{activities => internal/activity}/DialToAgiActivityImpl.java (91%) rename src/main/java/org/asteriskjava/pbx/{activities => internal/activity}/HoldActivityImpl.java (86%) rename src/main/java/org/asteriskjava/pbx/{activities => internal/activity}/JoinActivityImpl.java (94%) rename src/main/java/org/asteriskjava/pbx/{activities => internal/activity}/ParkActivityImpl.java (89%) rename src/main/java/org/asteriskjava/pbx/{activities => internal/activity}/SplitActivityImpl.java (92%) delete mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewStateEvent.java rename src/test/java/org/asteriskjava/pbx/{internal => }/agi/RateLimiterTest.java (85%) diff --git a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java index 8a735b519..8948437de 100644 --- a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java +++ b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java @@ -12,11 +12,11 @@ import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.TechType; import org.asteriskjava.pbx.Trunk; import org.asteriskjava.pbx.activities.BlindTransferActivity; import org.asteriskjava.pbx.activities.DialActivity; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.TechType; /** * dial somebody and then blind transfer the call to a third party. diff --git a/src/main/java/org/asteriskjava/examples/activities/Dial.java b/src/main/java/org/asteriskjava/examples/activities/Dial.java index 48a4028dc..db3c6e636 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Dial.java +++ b/src/main/java/org/asteriskjava/examples/activities/Dial.java @@ -8,9 +8,9 @@ import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.TechType; import org.asteriskjava.pbx.Trunk; import org.asteriskjava.pbx.activities.DialActivity; -import org.asteriskjava.pbx.internal.core.TechType; public class Dial { diff --git a/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java b/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java index 7114eda29..30c9d0b5f 100644 --- a/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java +++ b/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java @@ -1,6 +1,6 @@ package org.asteriskjava.examples.activities; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.AsteriskSettings; public class ExamplesAsteriskSettings implements AsteriskSettings { diff --git a/src/main/java/org/asteriskjava/examples/activities/Hold.java b/src/main/java/org/asteriskjava/examples/activities/Hold.java index dce9f2a46..bf37a9640 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Hold.java +++ b/src/main/java/org/asteriskjava/examples/activities/Hold.java @@ -8,9 +8,9 @@ import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.TechType; import org.asteriskjava.pbx.activities.DialActivity; import org.asteriskjava.pbx.activities.HoldActivity; -import org.asteriskjava.pbx.internal.core.TechType; /** * dial somebody and then put them on hold. diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityAction.java b/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java similarity index 78% rename from src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityAction.java rename to src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java index d4d936d00..90daddbaf 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityAction.java +++ b/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java @@ -1,8 +1,7 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx; import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; -import org.asteriskjava.pbx.Channel; public interface AgiChannelActivityAction { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/AsteriskSettings.java b/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java similarity index 98% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/AsteriskSettings.java rename to src/main/java/org/asteriskjava/pbx/AsteriskSettings.java index 983c538e6..f4944c213 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/AsteriskSettings.java +++ b/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk; +package org.asteriskjava.pbx; public interface AsteriskSettings { diff --git a/src/main/java/org/asteriskjava/pbx/Channel.java b/src/main/java/org/asteriskjava/pbx/Channel.java index 82ef417b7..7c018eb30 100644 --- a/src/main/java/org/asteriskjava/pbx/Channel.java +++ b/src/main/java/org/asteriskjava/pbx/Channel.java @@ -2,9 +2,6 @@ import java.util.concurrent.TimeUnit; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; - /** * Provides an abstraction for an channel object which is independant of the * underlying PBX. @@ -13,178 +10,179 @@ */ public interface Channel { - /** - * Compares if two channels are the same logical channel on the pbx. This - * comparison uses the full unique name of the channel not just the - * abbreviated peer name. e.g. SIP/100-00000100 - * - * @param rhs - * @return - */ - boolean isSame(Channel rhs); - - boolean isSame(String channelName, String uniqueID); - - /* - * This comparision uses just the peer name. e.g. SIP/100 - */ - boolean sameEndPoint(Channel rhs); - - /* - * This comparision uses just the peer name. e.g. SIP/100 - */ - boolean sameEndPoint(EndPoint extensionRoaming); - - /** - * Compares if this channel is the same as the named channel. - * - * @param channelName - * @return - */ - boolean sameExtenededChannelName(String channelName); - - /** - * This method does not actually change the state of the channel, rather it - * is intended to be used to record the fact that the state has changed. - * - * @see public iPBX.iParkCallActivity park(iChannel channel, Direction - * direction, boolean parkState) for a method which actually parks the - * channel. - */ - void setParked(boolean parked); - - /** - * This method does not actually change the state of the channel, rather it - * is intended to be used to record the fact that the state has changed. - * - * @see public iPBX.iMuteCallActivity mute(iChannel channel, Direction - * direction, boolean muteState) for a method which actually mutes the - * channel. - */ - void setMute(boolean muteState); - - /** - * Each channel is assigned a unique PBX independent id to help track the - * channels when logging. - * - * @return - */ - long getChannelId(); - - /** - * Returns true if the channel is alive. A channel is considered to be alive - * from the moment it is created until we get a notification that it has - * been hungup. - * - * @return - */ - boolean isLive(); - - /** - * Adds a listener to the channel. The channel will send a hungup - * notification to the listener when it hungup. A channel must be able to - * support multiple listeners. - * - * @param call - */ - void addHangupListener(ChannelHangupListener listener); - - void removeListener(ChannelHangupListener listener); - - /** - * Returns true if the given endpont is currently connected to this channel. - * - * @param extension - * @return - */ - boolean isConnectedTo(EndPoint endPoint); - - /** - * returns a fully qualifed channel name which includes the tech. e.g. - * SIP/100-00000342 - * - * @return - */ - String getChannelName(); - - EndPoint getEndPoint(); - - /** - * Checks if this channel is currently mute. A channel is mute if the party - * connected to this channel cannot hear any audio. - * - * @return - */ - boolean isMute(); - - /** - * In Asterisk speak, this method returns true if it is a LOCAL/ channel Not - * quite certain how this will map to other pbx's - * - * @return - */ - boolean isLocal(); - - /** - * @return true if the channel is currently parked. - */ - boolean isParked(); - - /** - * Returns true if the channel has been marked as in a zombie state. - * - * @return - */ - boolean isZombie(); - - /** - * @return true if the channel was originated from the console - * (Console/DSP). - */ - boolean isConsole(); - - /** - * Returns the current callerid for this channel. Note: on some systems this - * involves a round trip to the pbx. - * - * @return - */ - CallerID getCallerID(); - - /** - * Called to rename a channel - * - * @param newname - * the new name of the channel - * @throws InvalidChannelName - */ - void rename(String newName) throws InvalidChannelName; - - /** - * Returns a PBX specific version of the Channel name. - * - * @return - */ - String getExtendedChannelName(); - - void notifyHangupListeners(Integer cause, String causeText); - - boolean canDetectHangup(); - - boolean isQuiescent(); - - boolean hasCallerID(); - - AgiChannelActivityAction getCurrentActivityAction(); - - public void setCurrentActivityAction(AgiChannelActivityAction action); - - void setIsInAgi(boolean b); - - boolean isInAgi(); - - String getUniqueId(); - - boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException; + /** + * Compares if two channels are the same logical channel on the pbx. This + * comparison uses the full unique name of the channel not just the + * abbreviated peer name. e.g. SIP/100-00000100 + * + * @param rhs + * @return + */ + boolean isSame(Channel rhs); + + boolean isSame(String channelName, String uniqueID); + + /* + * This comparision uses just the peer name. e.g. SIP/100 + */ + boolean sameEndPoint(Channel rhs); + + /* + * This comparision uses just the peer name. e.g. SIP/100 + */ + boolean sameEndPoint(EndPoint extensionRoaming); + + /** + * Compares if this channel is the same as the named channel. + * + * @param channelName + * @return + */ + boolean sameExtenededChannelName(String channelName); + + /** + * This method does not actually change the state of the channel, rather it + * is intended to be used to record the fact that the state has changed. + * + * @see public iPBX.iParkCallActivity park(iChannel channel, Direction + * direction, boolean parkState) for a method which actually parks the + * channel. + */ + void setParked(boolean parked); + + /** + * This method does not actually change the state of the channel, rather it + * is intended to be used to record the fact that the state has changed. + * + * @see public iPBX.iMuteCallActivity mute(iChannel channel, Direction + * direction, boolean muteState) for a method which actually mutes the + * channel. + */ + void setMute(boolean muteState); + + /** + * Each channel is assigned a unique PBX independent id to help track the + * channels when logging. + * + * @return + */ + long getChannelId(); + + /** + * Returns true if the channel is alive. A channel is considered to be alive + * from the moment it is created until we get a notification that it has + * been hungup. + * + * @return + */ + boolean isLive(); + + /** + * Adds a listener to the channel. The channel will send a hungup + * notification to the listener when it hungup. A channel must be able to + * support multiple listeners. + * + * @param call + */ + void addHangupListener(ChannelHangupListener listener); + + void removeListener(ChannelHangupListener listener); + + /** + * Returns true if the given endpont is currently connected to this channel. + * + * @param extension + * @return + */ + boolean isConnectedTo(EndPoint endPoint); + + /** + * returns a fully qualifed channel name which includes the tech. e.g. + * SIP/100-00000342 + * + * @return + */ + String getChannelName(); + + EndPoint getEndPoint(); + + /** + * Checks if this channel is currently mute. A channel is mute if the party + * connected to this channel cannot hear any audio. + * + * @return + */ + boolean isMute(); + + /** + * In Asterisk speak, this method returns true if it is a LOCAL/ channel Not + * quite certain how this will map to other pbx's + * + * @return + */ + boolean isLocal(); + + /** + * @return true if the channel is currently parked. + */ + boolean isParked(); + + /** + * Returns true if the channel has been marked as in a zombie state. + * + * @return + */ + boolean isZombie(); + + /** + * @return true if the channel was originated from the console + * (Console/DSP). + */ + boolean isConsole(); + + /** + * Returns the current callerid for this channel. Note: on some systems this + * involves a round trip to the pbx. + * + * @return + */ + CallerID getCallerID(); + + /** + * Called to rename a channel + * + * @param newname the new name of the channel + * @throws InvalidChannelName + */ + void rename(String newName) throws InvalidChannelName; + + /** + * Returns a PBX specific version of the Channel name. + * + * @return + */ + String getExtendedChannelName(); + + void notifyHangupListeners(Integer cause, String causeText); + + boolean canDetectHangup(); + + boolean isQuiescent(); + + boolean hasCallerID(); + + AgiChannelActivityAction getCurrentActivityAction(); + + public void setCurrentActivityAction(AgiChannelActivityAction action); + + void setIsInAgi(boolean b); + + boolean isInAgi(); + + String getUniqueId(); + + boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException; + + void setCallerId(CallerID buildCallerID); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialPlanExtension.java b/src/main/java/org/asteriskjava/pbx/DialPlanExtension.java similarity index 95% rename from src/main/java/org/asteriskjava/pbx/internal/core/DialPlanExtension.java rename to src/main/java/org/asteriskjava/pbx/DialPlanExtension.java index 719a39292..9b4bc5fa3 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialPlanExtension.java +++ b/src/main/java/org/asteriskjava/pbx/DialPlanExtension.java @@ -1,7 +1,6 @@ -package org.asteriskjava.pbx.internal.core; +package org.asteriskjava.pbx; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.EndPoint; /** * Represents an asterisk dial plan extension such as: diff --git a/src/main/java/org/asteriskjava/pbx/EndPoint.java b/src/main/java/org/asteriskjava/pbx/EndPoint.java index f08e39e3f..c9d694d7f 100644 --- a/src/main/java/org/asteriskjava/pbx/EndPoint.java +++ b/src/main/java/org/asteriskjava/pbx/EndPoint.java @@ -1,7 +1,5 @@ package org.asteriskjava.pbx; -import org.asteriskjava.pbx.internal.core.TechType; - /** * Provides an abstract interface for entities which can be dialed. * diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/InvalidChannelName.java b/src/main/java/org/asteriskjava/pbx/InvalidChannelName.java similarity index 78% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/InvalidChannelName.java rename to src/main/java/org/asteriskjava/pbx/InvalidChannelName.java index 5af9695ae..b1cb6de54 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/InvalidChannelName.java +++ b/src/main/java/org/asteriskjava/pbx/InvalidChannelName.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk; +package org.asteriskjava.pbx; public class InvalidChannelName extends Exception { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerPriority.java b/src/main/java/org/asteriskjava/pbx/ListenerPriority.java similarity index 96% rename from src/main/java/org/asteriskjava/pbx/internal/core/ListenerPriority.java rename to src/main/java/org/asteriskjava/pbx/ListenerPriority.java index 853e39ab5..7c622ff43 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerPriority.java +++ b/src/main/java/org/asteriskjava/pbx/ListenerPriority.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.core; +package org.asteriskjava.pbx; public enum ListenerPriority { diff --git a/src/main/java/org/asteriskjava/pbx/PBX.java b/src/main/java/org/asteriskjava/pbx/PBX.java index 48198842a..d36a4a14c 100644 --- a/src/main/java/org/asteriskjava/pbx/PBX.java +++ b/src/main/java/org/asteriskjava/pbx/PBX.java @@ -9,7 +9,6 @@ import org.asteriskjava.pbx.activities.JoinActivity; import org.asteriskjava.pbx.activities.ParkActivity; import org.asteriskjava.pbx.activities.SplitActivity; -import org.asteriskjava.pbx.internal.core.TechType; /** * Provides an abstracted interface for communicating with a PBX. diff --git a/src/main/java/org/asteriskjava/pbx/PBXFactory.java b/src/main/java/org/asteriskjava/pbx/PBXFactory.java index 840f15cf3..b6fedfa2c 100644 --- a/src/main/java/org/asteriskjava/pbx/PBXFactory.java +++ b/src/main/java/org/asteriskjava/pbx/PBXFactory.java @@ -2,7 +2,6 @@ import java.util.concurrent.atomic.AtomicReference; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class PBXFactory diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/TechType.java b/src/main/java/org/asteriskjava/pbx/TechType.java similarity index 96% rename from src/main/java/org/asteriskjava/pbx/internal/core/TechType.java rename to src/main/java/org/asteriskjava/pbx/TechType.java index 2edf3031e..fd20efa1b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/TechType.java +++ b/src/main/java/org/asteriskjava/pbx/TechType.java @@ -1,7 +1,6 @@ -package org.asteriskjava.pbx.internal.core; +package org.asteriskjava.pbx; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.Tech; public enum TechType implements Tech { diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java similarity index 93% rename from src/main/java/org/asteriskjava/pbx/internal/agi/ActivityAgi.java rename to src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index 9e994a1d3..79064af7b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -1,13 +1,13 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ChannelHangupListener; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ChannelProxy; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -19,7 +19,7 @@ public class ActivityAgi extends NJAgiScript @Override public void service() throws AgiException { - ChannelProxy channelProxy = null; + Channel channelProxy = null; String channelName = channel.getName(); try diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBlindTransfer.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java similarity index 92% rename from src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBlindTransfer.java rename to src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java index 569f1d87e..2ec97797e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBlindTransfer.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java @@ -1,9 +1,10 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import java.util.concurrent.CountDownLatch; import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; public class AgiChannelActivityBlindTransfer implements AgiChannelActivityAction diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBridge.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java similarity index 93% rename from src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBridge.java rename to src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java index 934b97dfe..d07c1711e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityBridge.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java @@ -1,10 +1,11 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import java.util.concurrent.CountDownLatch; import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityDial.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java similarity index 93% rename from src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityDial.java rename to src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java index 846dcda4d..5f65bd3e0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityDial.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java @@ -1,9 +1,10 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import java.util.concurrent.CountDownLatch; import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; public class AgiChannelActivityDial implements AgiChannelActivityAction diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHangup.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java similarity index 91% rename from src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHangup.java rename to src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java index 4cc9b1aab..d6fd85bd7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHangup.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java @@ -1,10 +1,11 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import java.util.concurrent.CountDownLatch; import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHold.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java similarity index 94% rename from src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHold.java rename to src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java index a680f1430..efb5df319 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHold.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -6,6 +6,7 @@ import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHoldForBridge.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java similarity index 93% rename from src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHoldForBridge.java rename to src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java index 2f897ce17..d655c6ce5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityHoldForBridge.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java @@ -1,8 +1,9 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityMeetme.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java similarity index 92% rename from src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityMeetme.java rename to src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java index 56ca01f3b..fe7c02a70 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityMeetme.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import java.io.IOException; import java.util.concurrent.CountDownLatch; @@ -7,10 +7,11 @@ import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.manager.TimeoutException; +import org.asteriskjava.pbx.AgiChannelActivityAction; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityQueue.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java similarity index 91% rename from src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityQueue.java rename to src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java index f751e77a4..217eb60ac 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityQueue.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import java.io.IOException; import java.util.concurrent.CountDownLatch; @@ -7,10 +7,11 @@ import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; import org.asteriskjava.manager.TimeoutException; +import org.asteriskjava.pbx.AgiChannelActivityAction; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityVoicemail.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java similarity index 88% rename from src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityVoicemail.java rename to src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java index 13153ee12..0010ae3f6 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/AgiChannelActivityVoicemail.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java @@ -1,7 +1,8 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; public class AgiChannelActivityVoicemail implements AgiChannelActivityAction diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/NJAgiScript.java b/src/main/java/org/asteriskjava/pbx/agi/NJAgiScript.java similarity index 97% rename from src/main/java/org/asteriskjava/pbx/internal/agi/NJAgiScript.java rename to src/main/java/org/asteriskjava/pbx/agi/NJAgiScript.java index 2df64d949..39ba5e5ae 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/NJAgiScript.java +++ b/src/main/java/org/asteriskjava/pbx/agi/NJAgiScript.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import org.apache.log4j.Logger; import org.asteriskjava.fastagi.AgiChannel; diff --git a/src/main/java/org/asteriskjava/pbx/internal/agi/RateLimiter.java b/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java similarity index 95% rename from src/main/java/org/asteriskjava/pbx/internal/agi/RateLimiter.java rename to src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java index 97bdc6ee5..0efadab42 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/agi/RateLimiter.java +++ b/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import java.util.LinkedList; import java.util.List; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/AbstractManagerAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/AbstractManagerAction.java similarity index 90% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/AbstractManagerAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/AbstractManagerAction.java index 878f019e6..0b1f6e19d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/AbstractManagerAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/AbstractManagerAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; /** * Automatically generates a globally unique action id (based on the systems mac diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/BridgeAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/BridgeAction.java similarity index 89% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/BridgeAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/BridgeAction.java index 691773bb5..2961cf4bb 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/BridgeAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/BridgeAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.asteriskjava.pbx.Channel; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/CommandAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/CommandAction.java similarity index 86% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/CommandAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/CommandAction.java index 4cb0130f5..2c6b37988 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/CommandAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/CommandAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; public class CommandAction extends AbstractManagerAction { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ConfbridgeListAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeListAction.java similarity index 91% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ConfbridgeListAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeListAction.java index 0fc8d9c08..af3535b0e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ConfbridgeListAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeListAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.asteriskjava.manager.action.ManagerAction; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/DbGetAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/DbGetAction.java similarity index 88% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/DbGetAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/DbGetAction.java index 5c3f3809e..75ef3a8b5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/DbGetAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/DbGetAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.asteriskjava.manager.action.ManagerAction; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/EventGeneratingAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/EventGeneratingAction.java similarity index 68% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/EventGeneratingAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/EventGeneratingAction.java index 73047bd5a..2f554fca3 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/EventGeneratingAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/EventGeneratingAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; public interface EventGeneratingAction { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/GetVarAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/GetVarAction.java similarity index 89% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/GetVarAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/GetVarAction.java index fdbcc4f96..a222726be 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/GetVarAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/GetVarAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.asteriskjava.pbx.Channel; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/HangupAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/HangupAction.java similarity index 88% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/HangupAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/HangupAction.java index b5dd8423f..8bcf97441 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/HangupAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/HangupAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.asteriskjava.pbx.Channel; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ListCommandsAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ListCommandsAction.java similarity index 90% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ListCommandsAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ListCommandsAction.java index 46a010e98..12b9c8dc4 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ListCommandsAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ListCommandsAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.apache.log4j.Logger; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ManagerAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ManagerAction.java similarity index 73% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ManagerAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ManagerAction.java index 9198c9128..a573d7c0d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/ManagerAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ManagerAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; public interface ManagerAction { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/MonitorAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/MonitorAction.java similarity index 90% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/MonitorAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/MonitorAction.java index 7a01d95a0..7d7c1a6cf 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/MonitorAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/MonitorAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.asteriskjava.pbx.Channel; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/OriginateAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java similarity index 93% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/OriginateAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java index 5ccfd0c3d..50bcef2a8 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/OriginateAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import java.util.Map; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PingAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PingAction.java similarity index 89% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PingAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PingAction.java index d74bc0465..c44c97e6b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PingAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PingAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.apache.log4j.Logger; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PlayDtmfAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PlayDtmfAction.java similarity index 89% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PlayDtmfAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PlayDtmfAction.java index 6f96a8cec..59218af9e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/PlayDtmfAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PlayDtmfAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.asteriskjava.manager.action.ManagerAction; import org.asteriskjava.pbx.Channel; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/RedirectAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/RedirectAction.java similarity index 94% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/RedirectAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/RedirectAction.java index 0fdbda90a..32c067f57 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/RedirectAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/RedirectAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SetVarAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SetVarAction.java similarity index 91% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SetVarAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SetVarAction.java index 5862312b9..4f89aa5a4 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SetVarAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SetVarAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.asteriskjava.pbx.Channel; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipPeersAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipPeersAction.java similarity index 87% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipPeersAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipPeersAction.java index 71f0a2d3a..b24ee11be 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipPeersAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipPeersAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; public class SipPeersAction extends AbstractManagerAction implements EventGeneratingAction { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipShowPeerAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipShowPeerAction.java similarity index 87% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipShowPeerAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipShowPeerAction.java index fca71b3a0..f29bbfd1c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/SipShowPeerAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipShowPeerAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.asteriskjava.manager.action.ManagerAction; import org.asteriskjava.pbx.EndPoint; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/StatusAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/StatusAction.java similarity index 92% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/StatusAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/StatusAction.java index 26ec849a1..8a10e941c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/StatusAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/StatusAction.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.asteriskjava.AsteriskVersion; import org.asteriskjava.pbx.Channel; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/UserEventAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/UserEventAction.java similarity index 76% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/UserEventAction.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/UserEventAction.java index 525434854..92c791f62 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/actions/UserEventAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/UserEventAction.java @@ -1,7 +1,7 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.actions; +package org.asteriskjava.pbx.asterisk.wrap.actions; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.wrap.userEvents.UserEvent; +import org.asteriskjava.pbx.asterisk.wrap.userEvents.UserEvent; abstract public class UserEventAction extends AbstractManagerAction { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractChannelStateEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractChannelStateEvent.java similarity index 80% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractChannelStateEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractChannelStateEvent.java index 4d627ee37..afe1f2b1b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractChannelStateEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractChannelStateEvent.java @@ -1,8 +1,7 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.core.ChannelEventHelper; +import org.asteriskjava.pbx.InvalidChannelName; public abstract class AbstractChannelStateEvent extends ChannelEventHelper { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractMeetMeEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractMeetMeEvent.java similarity index 78% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractMeetMeEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractMeetMeEvent.java index 925357c9c..47fa9ad86 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractMeetMeEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractMeetMeEvent.java @@ -1,8 +1,7 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.core.ChannelEventHelper; +import org.asteriskjava.pbx.InvalidChannelName; public class AbstractMeetMeEvent extends ChannelEventHelper { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractParkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractParkedCallEvent.java similarity index 80% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractParkedCallEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractParkedCallEvent.java index f940dd4b3..14442c78c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AbstractParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractParkedCallEvent.java @@ -1,8 +1,7 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.core.ChannelEventHelper; +import org.asteriskjava.pbx.InvalidChannelName; public class AbstractParkedCallEvent extends ChannelEventHelper { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentCalledEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentCalledEvent.java similarity index 79% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentCalledEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentCalledEvent.java index e954d08a0..6c3fb7370 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentCalledEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentCalledEvent.java @@ -1,8 +1,7 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.core.ChannelEventHelper; +import org.asteriskjava.pbx.InvalidChannelName; public class AgentCalledEvent extends ChannelEventHelper { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentConnectEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentConnectEvent.java similarity index 79% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentConnectEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentConnectEvent.java index 12950efbc..da6362880 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/AgentConnectEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentConnectEvent.java @@ -1,8 +1,7 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.core.ChannelEventHelper; +import org.asteriskjava.pbx.InvalidChannelName; public class AgentConnectEvent extends ChannelEventHelper { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/BridgeEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BridgeEvent.java similarity index 85% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/BridgeEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BridgeEvent.java index bb803779b..ef5124235 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/BridgeEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BridgeEvent.java @@ -1,10 +1,10 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ChannelProxy; public class BridgeEvent extends ManagerEvent { @@ -19,8 +19,8 @@ enum BridgeState } private final BridgeState bridgeState; - private final ChannelProxy channel1; - private final ChannelProxy channel2; + private final Channel channel1; + private final Channel channel2; public BridgeEvent(final org.asteriskjava.manager.event.BridgeEvent event) throws InvalidChannelName { @@ -37,12 +37,12 @@ public BridgeState getBridgeState() return this.bridgeState; } - public ChannelProxy getChannel1() + public Channel getChannel1() { return this.channel1; } - public ChannelProxy getChannel2() + public Channel getChannel2() { return this.channel2; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEvent.java similarity index 63% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEvent.java index c7b15975b..f409cbd95 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.asteriskjava.pbx.Channel; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelEventHelper.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java similarity index 72% rename from src/main/java/org/asteriskjava/pbx/internal/core/ChannelEventHelper.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java index 8810965b4..a65bf8695 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelEventHelper.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java @@ -1,10 +1,10 @@ -package org.asteriskjava.pbx.internal.core; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ChannelEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; public abstract class ChannelEventHelper extends ManagerEvent implements ChannelEvent { @@ -16,7 +16,7 @@ public abstract class ChannelEventHelper extends ManagerEvent implements Channel /** * The name of the channel. */ - private final ChannelProxy channel; + private final Channel channel; protected ChannelEventHelper(final org.asteriskjava.manager.event.AbstractChannelEvent event) throws InvalidChannelName { @@ -41,18 +41,18 @@ public ChannelEventHelper(final String channel, final String uniqueId) throws In } @Override - public ChannelProxy getChannel() + public Channel getChannel() { return this.channel; } - public static ChannelProxy registerChannel(final String channelName, final String uniqueId, final String callerIdNum, + public static Channel registerChannel(final String channelName, final String uniqueId, final String callerIdNum, final String callerIdName) throws InvalidChannelName { final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - final ChannelProxy channel = pbx.internalRegisterChannel(channelName, uniqueId); - channel.getRealChannel().setCallerId(pbx.buildCallerID(callerIdNum, callerIdName)); + final Channel channel = pbx.internalRegisterChannel(channelName, uniqueId); + channel.setCallerId(pbx.buildCallerID(callerIdNum, callerIdName)); return channel; } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelState.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelState.java similarity index 91% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelState.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelState.java index 0fad8139b..57163d544 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ChannelState.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelState.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; /** * Holds the state of a channel as used by NewStateEvent and NewChannelEvent. diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListCompleteEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListCompleteEvent.java similarity index 81% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListCompleteEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListCompleteEvent.java index 8c844cc61..a01b32ca9 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListCompleteEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListCompleteEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; public class ConfbridgeListCompleteEvent extends ManagerEvent { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListEvent.java similarity index 89% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListEvent.java index 4d0f981d2..5073f111b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConfbridgeListEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; public class ConfbridgeListEvent extends ResponseEvent { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConnectEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConnectEvent.java similarity index 90% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConnectEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConnectEvent.java index 6e2947872..2edc4eae5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ConnectEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConnectEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DbGetResponseEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java similarity index 92% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DbGetResponseEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java index d320a540f..a64417197 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DbGetResponseEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DialEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEvent.java similarity index 79% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DialEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEvent.java index 4d7479a73..72018b01f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DialEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEvent.java @@ -1,11 +1,10 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ChannelEventHelper; -import org.asteriskjava.pbx.internal.core.ChannelProxy; public class DialEvent extends ChannelEventHelper { @@ -17,7 +16,7 @@ public class DialEvent extends ChannelEventHelper /** * The name of the destination channel. */ - private final ChannelProxy destination; + private final Channel destination; private final String dialString; private final String dialStatus; @@ -37,7 +36,7 @@ public DialEvent(final org.asteriskjava.manager.event.DialEvent event) throws In } - public ChannelProxy getDestination() + public Channel getDestination() { return this.destination; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DisconnectEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DisconnectEvent.java similarity index 85% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DisconnectEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DisconnectEvent.java index 3db4bac29..cdf67b4e0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DisconnectEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DisconnectEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DndStateEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DndStateEvent.java similarity index 90% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DndStateEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DndStateEvent.java index 24d6daf12..e8c0df1f7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/DndStateEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DndStateEvent.java @@ -1,9 +1,9 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelImpl; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ExtensionStatusEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ExtensionStatusEvent.java similarity index 96% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ExtensionStatusEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ExtensionStatusEvent.java index d6a4fdb20..a9e80c3fc 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ExtensionStatusEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ExtensionStatusEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/HangupEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/HangupEvent.java similarity index 91% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/HangupEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/HangupEvent.java index b84f24bd2..7a6369f27 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/HangupEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/HangupEvent.java @@ -1,9 +1,9 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class HangupEvent extends ManagerEvent implements ChannelEvent diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/LinkEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/LinkEvent.java similarity index 75% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/LinkEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/LinkEvent.java index 7f3d0a969..349d512a7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/LinkEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/LinkEvent.java @@ -1,7 +1,7 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.InvalidChannelName; public class LinkEvent extends BridgeEvent { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ManagerEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ManagerEvent.java similarity index 84% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ManagerEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ManagerEvent.java index e4b3c086a..fce61db8c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ManagerEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ManagerEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import java.util.EventObject; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MasqueradeEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MasqueradeEvent.java similarity index 98% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MasqueradeEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MasqueradeEvent.java index 7fc5e20ae..5b830b9ef 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MasqueradeEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MasqueradeEvent.java @@ -1,9 +1,9 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelImpl; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeJoinEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeJoinEvent.java similarity index 84% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeJoinEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeJoinEvent.java index a562d8d00..b49728adc 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeJoinEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeJoinEvent.java @@ -1,10 +1,10 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; public class MeetMeJoinEvent extends AbstractMeetMeEvent { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeLeaveEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeLeaveEvent.java similarity index 87% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeLeaveEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeLeaveEvent.java index 657d90fd6..bdcdaf3b7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/MeetMeLeaveEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeLeaveEvent.java @@ -1,10 +1,10 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; public class MeetMeLeaveEvent extends AbstractMeetMeEvent { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewChannelEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java similarity index 89% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewChannelEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java index 801f639ff..8147b2ee0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewChannelEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java @@ -1,7 +1,7 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.InvalidChannelName; public class NewChannelEvent extends AbstractChannelStateEvent { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewExtenEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewExtenEvent.java similarity index 92% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewExtenEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewExtenEvent.java index 174077423..b8a3b5c0a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewExtenEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewExtenEvent.java @@ -1,9 +1,9 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class NewExtenEvent extends ManagerEvent implements ChannelEvent diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java new file mode 100644 index 000000000..65e3dab5d --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java @@ -0,0 +1,29 @@ +package org.asteriskjava.pbx.asterisk.wrap.events; + +import org.apache.log4j.Logger; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.pbx.internal.core.ChannelProxy; + +public class NewStateEvent extends AbstractChannelStateEvent +{ + private static final long serialVersionUID = 1L; + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(NewStateEvent.class); + private ChannelProxy destChannel; + + public NewStateEvent(final org.asteriskjava.manager.event.NewStateEvent event) throws InvalidChannelName + { + super(event); + } + + public Channel getDestination() + { + return destChannel; + } + + public String toString() + { + return "NewStateEvent: channel:" + this.getChannel() + " channelState:" + this.getChannelState(); //$NON-NLS-1$//$NON-NLS-2$ + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/OriginateResponseEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/OriginateResponseEvent.java similarity index 90% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/OriginateResponseEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/OriginateResponseEvent.java index 2f720fef1..bc9b8f3e9 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/OriginateResponseEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/OriginateResponseEvent.java @@ -1,14 +1,13 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.core.ChannelEventHelper; +import org.asteriskjava.pbx.TechType; import org.asteriskjava.pbx.internal.core.ChannelImpl; -import org.asteriskjava.pbx.internal.core.TechType; public class OriginateResponseEvent extends ResponseEvent implements ChannelEvent { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ParkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ParkedCallEvent.java similarity index 91% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ParkedCallEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ParkedCallEvent.java index 5beb1e5cb..8669fcfba 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ParkedCallEvent.java @@ -1,9 +1,9 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelImpl; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerEntryEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerEntryEvent.java similarity index 85% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerEntryEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerEntryEvent.java index 250a710af..0525dd694 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerEntryEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerEntryEvent.java @@ -1,10 +1,10 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.core.TechType; +import org.asteriskjava.pbx.TechType; public class PeerEntryEvent extends ResponseEvent { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerStatusEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerStatusEvent.java similarity index 92% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerStatusEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerStatusEvent.java index e5367dd8e..108f159ca 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerStatusEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerStatusEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.EndPoint; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerlistCompleteEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerlistCompleteEvent.java similarity index 86% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerlistCompleteEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerlistCompleteEvent.java index 2f7534b95..4d06148be 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/PeerlistCompleteEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerlistCompleteEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/QueueCallerLeaveEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/QueueCallerLeaveEvent.java similarity index 77% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/QueueCallerLeaveEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/QueueCallerLeaveEvent.java index c2b0a1668..9a3138eef 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/QueueCallerLeaveEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/QueueCallerLeaveEvent.java @@ -1,8 +1,7 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.core.ChannelEventHelper; +import org.asteriskjava.pbx.InvalidChannelName; public class QueueCallerLeaveEvent extends ChannelEventHelper { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/RenameEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java similarity index 93% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/RenameEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java index 97f64072a..b5e15762c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/RenameEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java @@ -1,9 +1,9 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelProxy; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvent.java similarity index 91% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvent.java index 33da1f7e7..0bc9464f3 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvents.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvents.java similarity index 88% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvents.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvents.java index 07b965892..ba6c3dfcc 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/ResponseEvents.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvents.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import java.util.ArrayList; import java.util.Collection; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusCompleteEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusCompleteEvent.java similarity index 86% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusCompleteEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusCompleteEvent.java index 50a2c9311..5d81c3747 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusCompleteEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusCompleteEvent.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusEvent.java similarity index 94% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusEvent.java index 9a0b2bc36..3c621b250 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/StatusEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusEvent.java @@ -1,14 +1,14 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import java.util.Map; import org.apache.log4j.Logger; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.DialPlanExtension; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.DialPlanExtension; public class StatusEvent extends ResponseEvent implements ChannelEvent { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnlinkEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnlinkEvent.java similarity index 75% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnlinkEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnlinkEvent.java index 17c6a7c32..7b7efb890 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnlinkEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnlinkEvent.java @@ -1,7 +1,7 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.InvalidChannelName; public class UnlinkEvent extends BridgeEvent { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnparkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnparkedCallEvent.java similarity index 87% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnparkedCallEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnparkedCallEvent.java index ba66e85c9..2837ca2b0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/UnparkedCallEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnparkedCallEvent.java @@ -1,9 +1,9 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelImpl; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/VarSetEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/VarSetEvent.java similarity index 90% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/VarSetEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/VarSetEvent.java index 2fa547a66..c743d7dad 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/VarSetEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/VarSetEvent.java @@ -1,9 +1,9 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; +package org.asteriskjava.pbx.asterisk.wrap.events; import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class VarSetEvent extends ManagerEvent implements ChannelEvent diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/CommandResponse.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java similarity index 88% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/CommandResponse.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java index 00af9f3d1..dde7a33fd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/CommandResponse.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.response; +package org.asteriskjava.pbx.asterisk.wrap.response; import java.util.List; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerError.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java similarity index 82% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerError.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java index 9b22661c9..397b42c63 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerError.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.response; +package org.asteriskjava.pbx.asterisk.wrap.response; import org.apache.log4j.Logger; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerResponse.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java similarity index 96% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerResponse.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java index e99afa2c4..545f61b31 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/response/ManagerResponse.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.response; +package org.asteriskjava.pbx.asterisk.wrap.response; import java.util.Date; import java.util.Locale; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/userEvents/UserEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/userEvents/UserEvent.java similarity index 82% rename from src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/userEvents/UserEvent.java rename to src/main/java/org/asteriskjava/pbx/asterisk/wrap/userEvents/UserEvent.java index 58157b81d..2d67875af 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/userEvents/UserEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/userEvents/UserEvent.java @@ -1,10 +1,10 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.userEvents; +package org.asteriskjava.pbx.asterisk.wrap.userEvents; import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class UserEvent extends ManagerEvent diff --git a/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java similarity index 91% rename from src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java rename to src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java index 34003cd12..330cd7cdd 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/ActivityHelper.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.activities; +package org.asteriskjava.pbx.internal.activity; import java.util.HashSet; import java.util.Set; @@ -8,13 +8,13 @@ import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.ActivityStatusEnum; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SetVarAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.asterisk.wrap.actions.SetVarAction; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ListenerPriority; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; public abstract class ActivityHelper implements Runnable, Activity diff --git a/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java similarity index 91% rename from src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivityImpl.java rename to src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index 6be6cd56d..350d5ca3b 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.activities; +package org.asteriskjava.pbx.internal.activity; import java.util.HashSet; import java.util.concurrent.CountDownLatch; @@ -13,18 +13,18 @@ import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityBlindTransfer; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.BridgeEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.DialEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.LinkEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.activities.BlindTransferActivity; +import org.asteriskjava.pbx.agi.AgiChannelActivityBlindTransfer; +import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.DialEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ChannelProxy; -import org.asteriskjava.pbx.internal.core.ListenerPriority; /** * The BlindTransferActivity is used by the AsteriksPBX to transfer a live @@ -59,7 +59,7 @@ public class BlindTransferActivityImpl extends ActivityHelper implements BridgeActivity diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java similarity index 92% rename from src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java rename to src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java index 5b790aa35..ef1e46a51 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/DialActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java @@ -1,26 +1,27 @@ -package org.asteriskjava.pbx.activities; +package org.asteriskjava.pbx.internal.activity; import java.util.HashSet; import java.util.Map; import org.apache.log4j.Logger; import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.CallDirection; import org.asteriskjava.pbx.CallImpl; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.NewChannelListener; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SetVarAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.activities.DialActivity; +import org.asteriskjava.pbx.asterisk.wrap.actions.SetVarAction; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ListenerPriority; import org.asteriskjava.pbx.internal.managerAPI.Dial; import org.asteriskjava.pbx.internal.managerAPI.OriginateResult; diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java similarity index 91% rename from src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivityImpl.java rename to src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index 2b9748769..48ee786f9 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -1,23 +1,24 @@ -package org.asteriskjava.pbx.activities; +package org.asteriskjava.pbx.internal.activity; import java.util.HashSet; import java.util.Map; import org.apache.log4j.Logger; import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.NewChannelListener; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SetVarAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.activities.DialToAgiActivity; +import org.asteriskjava.pbx.asterisk.wrap.actions.SetVarAction; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ListenerPriority; import org.asteriskjava.pbx.internal.managerAPI.DialToAgi; import org.asteriskjava.pbx.internal.managerAPI.OriginateResult; diff --git a/src/main/java/org/asteriskjava/pbx/activities/HoldActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java similarity index 86% rename from src/main/java/org/asteriskjava/pbx/activities/HoldActivityImpl.java rename to src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java index 059aca09f..f56554bae 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/HoldActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java @@ -1,16 +1,17 @@ -package org.asteriskjava.pbx.activities; +package org.asteriskjava.pbx.internal.activity; import java.util.HashSet; import org.apache.log4j.Logger; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHold; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.activities.HoldActivity; +import org.asteriskjava.pbx.agi.AgiChannelActivityHold; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ListenerPriority; public class HoldActivityImpl extends ActivityHelper implements HoldActivity { diff --git a/src/main/java/org/asteriskjava/pbx/activities/JoinActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java similarity index 94% rename from src/main/java/org/asteriskjava/pbx/activities/JoinActivityImpl.java rename to src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java index 3f7f49d13..bd3d8e30d 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/JoinActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.activities; +package org.asteriskjava.pbx.internal.activity; import java.util.HashSet; import java.util.LinkedList; @@ -10,12 +10,13 @@ import org.asteriskjava.pbx.CallDirection; import org.asteriskjava.pbx.CallImpl; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.Call.OperandChannel; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.activities.JoinActivity; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ListenerPriority; /** * The JoinActivity is used by the AsteriksPBX implementation to Join two diff --git a/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java similarity index 89% rename from src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java rename to src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java index 5bc48071c..e1eea5412 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.activities; +package org.asteriskjava.pbx.internal.activity; import java.io.IOException; import java.util.HashSet; @@ -8,20 +8,21 @@ import org.apache.log4j.Logger; import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.CallDirection; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ParkedCallEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.TechType; +import org.asteriskjava.pbx.activities.ParkActivity; +import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ParkedCallEvent; +import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ListenerPriority; -import org.asteriskjava.pbx.internal.core.TechType; /** * The ParkActivity is used by the AsteriksPBX implementation to park a channel. diff --git a/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java similarity index 92% rename from src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java rename to src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index 765b9e599..876d223db 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -1,4 +1,4 @@ -package org.asteriskjava.pbx.activities; +package org.asteriskjava.pbx.internal.activity; import java.util.HashSet; import java.util.LinkedList; @@ -6,19 +6,20 @@ import org.apache.log4j.Logger; import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.CallImpl; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHold; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.activities.SplitActivity; +import org.asteriskjava.pbx.agi.AgiChannelActivityHold; +import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelProxy; -import org.asteriskjava.pbx.internal.core.ListenerPriority; /** * The SplitActivity is used by the AsteriksPBX to split a call and place the diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index f7337fd2a..37791328b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -10,23 +10,24 @@ import org.apache.log4j.Logger; import org.asteriskjava.AsteriskVersion; import org.asteriskjava.live.ManagerCommunicationException; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.CommandAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ConfbridgeListAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ConfbridgeListEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.MeetMeJoinEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.MeetMeLeaveEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ResponseEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ResponseEvents; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.CommandResponse; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.asterisk.wrap.actions.CommandAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.ConfbridgeListAction; +import org.asteriskjava.pbx.asterisk.wrap.events.ConfbridgeListEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.MeetMeJoinEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.MeetMeLeaveEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvents; +import org.asteriskjava.pbx.asterisk.wrap.response.CommandResponse; +import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.CoherentManagerEventListener; -import org.asteriskjava.pbx.internal.core.ListenerPriority; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; public class MeetmeRoomControl extends EventListenerBaseClass implements CoherentManagerEventListener diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewStateEvent.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewStateEvent.java deleted file mode 100644 index 349d54c88..000000000 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/wrap/events/NewStateEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.asteriskjava.pbx.internal.asterisk.wrap.events; - -import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.core.ChannelProxy; - -public class NewStateEvent extends AbstractChannelStateEvent -{ - private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(NewStateEvent.class); - private ChannelProxy destChannel; - - public NewStateEvent(final org.asteriskjava.manager.event.NewStateEvent event) throws InvalidChannelName - { - super(event); - } - - public ChannelProxy getDestination() - { - return destChannel; - } - - public String toString() - { - return "NewStateEvent: channel:" + this.getChannel() + " channelState:" + this.getChannelState(); //$NON-NLS-1$//$NON-NLS-2$ - } -} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index a351b7ce7..065bf38ea 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -16,6 +16,7 @@ import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.ActivityStatusEnum; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.Call.OperandChannel; import org.asteriskjava.pbx.CallDirection; @@ -24,44 +25,45 @@ import org.asteriskjava.pbx.ChannelHangupListener; import org.asteriskjava.pbx.CompletionAdaptor; import org.asteriskjava.pbx.DTMFTone; +import org.asteriskjava.pbx.DialPlanExtension; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.TechType; import org.asteriskjava.pbx.Trunk; import org.asteriskjava.pbx.activities.BlindTransferActivity; -import org.asteriskjava.pbx.activities.BlindTransferActivityImpl; import org.asteriskjava.pbx.activities.BridgeActivity; -import org.asteriskjava.pbx.activities.BridgeActivityImpl; import org.asteriskjava.pbx.activities.DialActivity; -import org.asteriskjava.pbx.activities.DialActivityImpl; import org.asteriskjava.pbx.activities.DialToAgiActivity; -import org.asteriskjava.pbx.activities.DialToAgiActivityImpl; import org.asteriskjava.pbx.activities.HoldActivity; -import org.asteriskjava.pbx.activities.HoldActivityImpl; import org.asteriskjava.pbx.activities.JoinActivity; -import org.asteriskjava.pbx.activities.JoinActivityImpl; import org.asteriskjava.pbx.activities.ParkActivity; -import org.asteriskjava.pbx.activities.ParkActivityImpl; import org.asteriskjava.pbx.activities.SplitActivity; -import org.asteriskjava.pbx.activities.SplitActivityImpl; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHangup; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHold; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.agi.AgiChannelActivityHangup; +import org.asteriskjava.pbx.agi.AgiChannelActivityHold; +import org.asteriskjava.pbx.asterisk.wrap.actions.CommandAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.EventGeneratingAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.HangupAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.ManagerAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.PlayDtmfAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvents; +import org.asteriskjava.pbx.asterisk.wrap.response.CommandResponse; +import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.internal.activity.BlindTransferActivityImpl; +import org.asteriskjava.pbx.internal.activity.BridgeActivityImpl; +import org.asteriskjava.pbx.internal.activity.DialActivityImpl; +import org.asteriskjava.pbx.internal.activity.DialToAgiActivityImpl; +import org.asteriskjava.pbx.internal.activity.HoldActivityImpl; +import org.asteriskjava.pbx.internal.activity.JoinActivityImpl; +import org.asteriskjava.pbx.internal.activity.ParkActivityImpl; +import org.asteriskjava.pbx.internal.activity.SplitActivityImpl; import org.asteriskjava.pbx.internal.asterisk.CallerIDImpl; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoomControl; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.CommandAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.EventGeneratingAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.HangupAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ManagerAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.PlayDtmfAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.RedirectAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ResponseEvents; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.CommandResponse; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.managerAPI.RedirectCall; public enum AsteriskPBX implements PBX, ChannelHangupListener @@ -397,7 +399,7 @@ public String getManagementContext() } @Override - public ChannelProxy getChannelByEndPoint(final EndPoint endPoint) + public Channel getChannelByEndPoint(final EndPoint endPoint) { return this.liveChannels.getChannelByEndPoint(endPoint); } @@ -509,9 +511,9 @@ public CallerID buildCallerID(final AbstractChannelEvent event) return this.buildCallerID(number, name); } - public ChannelProxy registerChannel(final String channelName, final String uniqueID) throws InvalidChannelName + public Channel registerChannel(final String channelName, final String uniqueID) throws InvalidChannelName { - ChannelProxy proxy = findChannel(cleanChannelName(channelName), null); + Channel proxy = findChannel(cleanChannelName(channelName), null); if (proxy == null) { logger.info("Couldn't find the channel " + channelName + ", creating it"); @@ -542,7 +544,7 @@ public ChannelProxy registerChannel(final String channelName, final String uniqu * @return * @throws InvalidChannelName */ - public ChannelProxy internalRegisterChannel(final String channelName, final String uniqueID) throws InvalidChannelName + public Channel internalRegisterChannel(final String channelName, final String uniqueID) throws InvalidChannelName { ChannelProxy proxy = null; synchronized (this.liveChannels) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java index 3b6e7df4b..325267218 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java @@ -7,7 +7,7 @@ import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ChannelHangupListener; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ChannelState; +import org.asteriskjava.pbx.asterisk.wrap.events.ChannelState; /** * This is a fairly simple class which is used by a Peer to track what calls are diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index 5f9b48735..f63e94bea 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -4,16 +4,17 @@ import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; +import org.asteriskjava.pbx.AgiChannelActivityAction; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ChannelFactory; import org.asteriskjava.pbx.ChannelHangupListener; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.TechType; /** * TODO set the channel unique id when registering against an existing channel @@ -191,7 +192,7 @@ public class ChannelImpl implements Channel * a complete clone just the key elements that we generally track on our * side rather than getting directly from asterisk. */ - void masquerade(Channel channel) + public void masquerade(Channel channel) { // If the channel doesn't have a caller id // preserve the existing one (as given this is a clone they should be @@ -427,7 +428,7 @@ boolean wasMarkedDuringSweep() return ret; } - void setCallerId(final CallerID callerId) + public void setCallerId(final CallerID callerId) { this._callerID = callerId; } @@ -563,7 +564,7 @@ public boolean sameExtenededChannelName(final String extendedChannelName) * @param uniqueID * @return */ - boolean sameUniqueID(String uniqueID) + public boolean sameUniqueID(String uniqueID) { boolean equals = false; if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index aac42341b..22ae2caf0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -8,13 +8,13 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.log4j.Logger; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ChannelHangupListener; import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityHold; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; +import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.pbx.agi.AgiChannelActivityHold; /** * The ChannelProxy exists to deal with the fact that Asterisk will often @@ -384,4 +384,11 @@ public int getIdentity() return _identity; } + @Override + public void setCallerId(CallerID callerId) + { + _channel.setCallerId(callerId); + + } + } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java index 6050bd66e..ef9c94bbd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java @@ -5,41 +5,41 @@ import java.util.Hashtable; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ManagerAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.AgentCalledEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.AgentConnectEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.BridgeEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ConfbridgeListCompleteEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ConfbridgeListEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ConnectEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.DialEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.DisconnectEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.DndStateEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ExtensionStatusEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.LinkEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.MasqueradeEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.MeetMeJoinEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.MeetMeLeaveEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewChannelEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewStateEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.OriginateResponseEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ParkedCallEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerEntryEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerStatusEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerlistCompleteEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.QueueCallerLeaveEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.RenameEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ResponseEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusCompleteEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.UnlinkEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.UnparkedCallEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.VarSetEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.CommandResponse; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerError; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.asterisk.wrap.actions.ManagerAction; +import org.asteriskjava.pbx.asterisk.wrap.events.AgentCalledEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.AgentConnectEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ConfbridgeListCompleteEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ConfbridgeListEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ConnectEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.DialEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.DisconnectEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.DndStateEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ExtensionStatusEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.MasqueradeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.MeetMeJoinEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.MeetMeLeaveEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.NewStateEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.OriginateResponseEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ParkedCallEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.PeerEntryEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.PeerStatusEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.PeerlistCompleteEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.QueueCallerLeaveEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.RenameEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.UnparkedCallEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.VarSetEvent; +import org.asteriskjava.pbx.asterisk.wrap.response.CommandResponse; +import org.asteriskjava.pbx.asterisk.wrap.response.ManagerError; +import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; /** * This class maps asterisk-java events to our internal events that use iChannel diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java index 019618f0b..bacc6d4b5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -17,21 +17,22 @@ import org.asteriskjava.manager.ManagerConnection; import org.asteriskjava.manager.ManagerConnectionState; import org.asteriskjava.manager.TimeoutException; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.EventGeneratingAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.GetVarAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ListCommandsAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.ManagerAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SetVarAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ConnectEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.DisconnectEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ResponseEvents; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.asterisk.wrap.actions.EventGeneratingAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.GetVarAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.ListCommandsAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.ManagerAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.SetVarAction; +import org.asteriskjava.pbx.asterisk.wrap.events.ConnectEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.DisconnectEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvents; +import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.managerAPI.Connector; /** diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java index 9e97aad94..c5aa4799d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java @@ -2,7 +2,7 @@ import java.util.EventListener; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; public interface CoherentManagerEventListener extends EventListener { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index f36542c76..b2507a650 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -10,7 +10,7 @@ import org.apache.log4j.Logger; import org.asteriskjava.manager.ManagerEventListener; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.eventQueue.EventLifeMonitor; import org.asteriskjava.pbx.util.LogTime; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java index 8eb02e8c4..498fc5c8b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -13,20 +13,21 @@ import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.ActivityStatusEnum; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.GetVarAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.OriginateAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewChannelEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.OriginateResponseEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.asterisk.wrap.actions.GetVarAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.OriginateAction; +import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.OriginateResponseEvent; +import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; import org.asteriskjava.pbx.internal.managerAPI.OriginateBaseClass; import org.asteriskjava.util.Log; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java index 172babbd7..2a3ee57f3 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java @@ -2,6 +2,7 @@ import org.apache.log4j.Logger; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.TechType; import org.asteriskjava.pbx.Trunk; public class EndPointImpl implements EndPoint diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java index 09afe9b5a..08c70e462 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java @@ -2,7 +2,8 @@ import java.util.Set; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.ListenerPriority; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; /** * Allows a object to receive Manager event notification which are pre-filtered. diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index a3a6c8be1..aac187c1e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -9,11 +9,12 @@ import org.apache.log4j.Priority; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.internal.asterisk.InvalidChannelName; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.MasqueradeEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.RenameEvent; +import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.pbx.ListenerPriority; +import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.MasqueradeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.RenameEvent; /** * The LiveChannelManager keeps a list of all of the live channels present on an diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java index f471ee5ba..870010c3d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java @@ -5,10 +5,10 @@ import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.MasqueradeEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewChannelEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewStateEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.MasqueradeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.NewStateEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; /* * this class tracks the status of a Peer on asterisk. T diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java index 6e7fed882..7c5c84c25 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java @@ -8,20 +8,21 @@ import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.NewExtensionListener; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.SipPeersAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.StatusAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.DndStateEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.MasqueradeEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewChannelEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewStateEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerEntryEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerStatusEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.PeerlistCompleteEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusCompleteEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.pbx.asterisk.wrap.actions.SipPeersAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.StatusAction; +import org.asteriskjava.pbx.asterisk.wrap.events.DndStateEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.MasqueradeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.NewStateEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.PeerEntryEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.PeerStatusEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.PeerlistCompleteEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; /* diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java index 666d4c9a2..c5887e700 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java @@ -1,7 +1,7 @@ package org.asteriskjava.pbx.internal.core; import org.apache.log4j.Logger; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ChannelState; +import org.asteriskjava.pbx.asterisk.wrap.events.ChannelState; public enum PeerState { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java index a0b74d8f3..3f07e1bf3 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java @@ -10,7 +10,7 @@ import org.asteriskjava.manager.ManagerConnection; import org.asteriskjava.manager.ManagerConnectionFactory; import org.asteriskjava.manager.TimeoutException; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.AsteriskSettings; /* * this class is a very thin wrapper around the manager connection class diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java index 5cbd4c42b..1996b6dbd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java @@ -9,18 +9,18 @@ import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.NewChannelListener; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityDial; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.BridgeEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.LinkEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.agi.AgiChannelActivityDial; +import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ListenerPriority; public class Dial extends EventListenerBaseClass { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index 37d6b12f2..b4213599f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -5,18 +5,18 @@ import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.NewChannelListener; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.core.ListenerPriority; public class DialToAgi extends EventListenerBaseClass { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java index 4d89e9380..89b04522f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java @@ -2,7 +2,7 @@ import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.FilteredManagerListener; diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java index 38b84224a..1483da224 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java @@ -1,7 +1,7 @@ package org.asteriskjava.pbx.internal.managerAPI; import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.internal.core.TechType; +import org.asteriskjava.pbx.TechType; public class HoldAtAgi implements EndPoint { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java index 18368850f..6cc7f2435 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java @@ -5,7 +5,7 @@ import org.apache.log4j.Logger; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.MonitorAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.MonitorAction; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class MonitorCall diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 87823e8c6..05e23530f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -7,6 +7,7 @@ import org.apache.log4j.Logger; import org.asteriskjava.live.ManagerCommunicationException; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; @@ -14,17 +15,16 @@ import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.GetVarAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.actions.OriginateAction; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.BridgeEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.LinkEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.NewChannelEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.OriginateResponseEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.events.UnlinkEvent; -import org.asteriskjava.pbx.internal.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.pbx.asterisk.wrap.actions.GetVarAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.OriginateAction; +import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.OriginateResponseEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public abstract class OriginateBaseClass extends EventListenerBaseClass diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java index cf0a5efb6..96262a2ab 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java @@ -3,12 +3,12 @@ import java.util.HashMap; import java.util.Map; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.NewChannelListener; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; -import org.asteriskjava.pbx.internal.core.ListenerPriority; public class OriginateToExtension extends OriginateBaseClass { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java index 9446789ea..0d5e3e5e5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java @@ -3,14 +3,14 @@ import java.util.HashMap; import org.apache.log4j.Logger; +import org.asteriskjava.pbx.AgiChannelActivityAction; +import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityAction; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityDial; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityVoicemail; -import org.asteriskjava.pbx.internal.asterisk.AsteriskSettings; +import org.asteriskjava.pbx.agi.AgiChannelActivityDial; +import org.asteriskjava.pbx.agi.AgiChannelActivityVoicemail; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class RedirectCall diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java index 5c615ab0b..2a439b5b2 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java @@ -4,7 +4,7 @@ import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.internal.agi.AgiChannelActivityMeetme; +import org.asteriskjava.pbx.agi.AgiChannelActivityMeetme; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class RedirectToMeetMe diff --git a/src/test/java/org/asteriskjava/pbx/internal/agi/RateLimiterTest.java b/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java similarity index 85% rename from src/test/java/org/asteriskjava/pbx/internal/agi/RateLimiterTest.java rename to src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java index 0ff84f2a9..bbd63098c 100644 --- a/src/test/java/org/asteriskjava/pbx/internal/agi/RateLimiterTest.java +++ b/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java @@ -1,8 +1,8 @@ -package org.asteriskjava.pbx.internal.agi; +package org.asteriskjava.pbx.agi; import static org.junit.Assert.assertTrue; -import org.asteriskjava.pbx.internal.agi.RateLimiter; +import org.asteriskjava.pbx.agi.RateLimiter; import org.junit.Test; public class RateLimiterTest From df81a38a363c36d441d374869ba331acac5729b5 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 26 Oct 2016 13:55:55 +1100 Subject: [PATCH 065/802] fix warning --- .../java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 065bf38ea..ec7b69bdd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -179,7 +179,7 @@ public void split(final Call callToSplit) throws PBXException { final CompletionAdaptor completion = new CompletionAdaptor<>(); - final SplitActivityImpl split = new SplitActivityImpl(callToSplit, completion); + new SplitActivityImpl(callToSplit, completion); completion.waitForCompletion(10, TimeUnit.SECONDS); From 6648349ac5ae1b7c1beabf28568a4ace6b885300 Mon Sep 17 00:00:00 2001 From: Thomas Weber Date: Mon, 7 Nov 2016 10:00:03 +0100 Subject: [PATCH 066/802] Only sign archives if we want to upload archives. --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 94e98f9a2..6af40b84c 100644 --- a/build.gradle +++ b/build.gradle @@ -47,6 +47,7 @@ artifacts { } signing { + required { gradle.taskGraph.hasTask("uploadArchives") } sign configurations.archives } From ebef5c3c0af201d2a7d893f03165cfaeefdf4d18 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 6 Feb 2017 10:23:48 +1100 Subject: [PATCH 067/802] reject back argument, with descriptive message --- .../java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index ec7b69bdd..2e4e67db1 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -513,6 +513,11 @@ public CallerID buildCallerID(final AbstractChannelEvent event) public Channel registerChannel(final String channelName, final String uniqueID) throws InvalidChannelName { + if (channelName == null || channelName.trim().length() == 0) + { + throw new IllegalArgumentException("Channel name must not be empty"); + } + Channel proxy = findChannel(cleanChannelName(channelName), null); if (proxy == null) { From 5ba29c78526d8b6ce394604ac6f060d9c5d71015 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Wed, 8 Feb 2017 07:29:21 -0500 Subject: [PATCH 068/802] Asterisk 14 version support --- src/main/java/org/asteriskjava/AsteriskVersion.java | 7 +++++++ .../manager/internal/ManagerConnectionImpl.java | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 474a1f16a..aea63e8f9 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -89,6 +89,13 @@ public class AsteriskVersion implements Comparable, Serializabl */ public static final AsteriskVersion ASTERISK_13 = new AsteriskVersion(1300, "Asterisk 13"); + /** + * Represents the Asterisk 14 series. + * + * @since 1.1.0 + */ + public static final AsteriskVersion ASTERISK_14 = new AsteriskVersion(1400, "Asterisk 14"); + /** * Serial version identifier. diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index ba40f031c..33a4dd236 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -96,6 +96,7 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher private static final Pattern VERSION_PATTERN_11 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?11[-. ].*"); private static final Pattern VERSION_PATTERN_12 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?12[-. ].*"); private static final Pattern VERSION_PATTERN_13 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?13[-. ].*"); + private static final Pattern VERSION_PATTERN_14 = Pattern.compile("^\\s*Asterisk (GIT-)?14[-. ].*"); private static final AtomicLong idCounter = new AtomicLong(0); @@ -710,6 +711,10 @@ else if (VERSION_PATTERN_13.matcher(coreLine).matches()) { return AsteriskVersion.ASTERISK_13; } + else if (VERSION_PATTERN_14.matcher(coreLine).matches()) + { + return AsteriskVersion.ASTERISK_14; + } } } From 986fa48826955db6baf8b31765c40f2fa12168ef Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Fri, 17 Feb 2017 18:00:14 -0300 Subject: [PATCH 069/802] new asterisk service level 2 this is included on asterisk master branch --- .../manager/event/QueueParamsEvent.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueParamsEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueParamsEvent.java index 6ff935b62..504dc3e83 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueParamsEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueParamsEvent.java @@ -41,6 +41,7 @@ public class QueueParamsEvent extends ResponseEvent private Integer abandoned; private Integer serviceLevel; private Double serviceLevelPerf; + private Double serviceLevelPerf2; private Integer weight; public QueueParamsEvent(Object source) @@ -48,6 +49,7 @@ public QueueParamsEvent(Object source) super(source); } + /** * Returns the name of the queue. * @@ -295,4 +297,15 @@ public void setWeight(Integer weight) { this.weight = weight; } + + public Double getServiceLevelPerf2() { + return serviceLevelPerf2; + } + + public void setServiceLevelPerf2(Double serviceLevelPerf2) { + this.serviceLevelPerf2 = serviceLevelPerf2; + } + + + } From c17a8cc90cb876e9530ecc1fc9ac0c5d03acc7a4 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Fri, 17 Feb 2017 18:05:31 -0300 Subject: [PATCH 070/802] fix issue #187 add output setter --- .../manager/response/ManagerResponse.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/response/ManagerResponse.java b/src/main/java/org/asteriskjava/manager/response/ManagerResponse.java index cd62c7bae..75fb7650f 100644 --- a/src/main/java/org/asteriskjava/manager/response/ManagerResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/ManagerResponse.java @@ -51,6 +51,7 @@ public class ManagerResponse implements Serializable private String uniqueId; private String events; private Map attributes; + private String output; public ManagerResponse() { @@ -91,7 +92,7 @@ public void setAttributes(Map attributes) * variable name. *

* Example: - * + * *

      * GetVarAction action = new GetVarAction();
      * action.setChannel("SIP/1310-22c3");
@@ -99,7 +100,7 @@ public void setAttributes(Map attributes)
      * ManagerResponse response = connection.sendAction(action);
      * String alertInfo = response.getAttribute("ALERT_INFO");
      * 
- * + * * As all attributes are internally stored in lower case the key is * automatically converted to lower case before lookup. * @@ -313,4 +314,12 @@ public void setEvents(String events) { this.events = events; } + + public String getOutput() { + return output; + } + + public void setOutput(String output) { + this.output = output; + } } From 060979e63e518319994a66160350bc68cb91914a Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Fri, 17 Feb 2017 18:06:49 -0300 Subject: [PATCH 071/802] fix issue #186 add missing properties --- .../manager/event/FullyBootedEvent.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/FullyBootedEvent.java b/src/main/java/org/asteriskjava/manager/event/FullyBootedEvent.java index 13e4b0d9a..84e220f45 100644 --- a/src/main/java/org/asteriskjava/manager/event/FullyBootedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/FullyBootedEvent.java @@ -18,6 +18,8 @@ public class FullyBootedEvent extends ManagerEvent { private static final long serialVersionUID = 0L; private String status; + private String lastreload; + private Integer uptime; public FullyBootedEvent(Object source) { @@ -43,4 +45,20 @@ public void setStatus(String status) { this.status = status; } + + public String getLastreload() { + return lastreload; + } + + public void setLastreload(String lastreload) { + this.lastreload = lastreload; + } + + public Integer getUptime() { + return uptime; + } + + public void setUptime(Integer uptime) { + this.uptime = uptime; + } } From ea8fa4cd4a862fa0b0d26f21ce4d47e968c451c7 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Fri, 17 Feb 2017 18:08:44 -0300 Subject: [PATCH 072/802] fix issue #184 add missing properties --- .../manager/event/StatusEvent.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/StatusEvent.java b/src/main/java/org/asteriskjava/manager/event/StatusEvent.java index d58135b5a..60471f7a2 100644 --- a/src/main/java/org/asteriskjava/manager/event/StatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/StatusEvent.java @@ -55,6 +55,8 @@ public class StatusEvent extends ResponseEvent private String writetrans; private String bridgeId; private String readtrans; + private String connectedlinename; + private String connectedlinenum; public StatusEvent(Object source) { @@ -508,4 +510,20 @@ public void setReadtrans(String readtrans) { this.readtrans = readtrans; } + + public String getConnectedlinename() { + return connectedlinename; + } + + public void setConnectedlinename(String connectedlinename) { + this.connectedlinename = connectedlinename; + } + + public String getConnectedlinenum() { + return connectedlinenum; + } + + public void setConnectedlinenum(String connectedlinenum) { + this.connectedlinenum = connectedlinenum; + } } From 6768b1f7bb818be359943675d9e098dc277e390a Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Fri, 17 Feb 2017 18:11:02 -0300 Subject: [PATCH 073/802] add new protocol version --- .../internal/ManagerConnectionImpl.java | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 33a4dd236..44dc3da49 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -75,7 +75,7 @@ /** * Internal implemention of the ManagerConnection interface. - * + * * @author srt * @version $Id$ * @see org.asteriskjava.manager.ManagerConnectionFactory @@ -167,7 +167,7 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher * Closes the connection (and reconnects) if no input has been read for the * given amount of milliseconds. A timeout of zero is interpreted as an * infinite timeout. - * + * * @see Socket#setSoTimeout(int) */ private int socketReadTimeout = 0; @@ -266,7 +266,7 @@ protected ManagerWriter createWriter() * Sets the hostname of the asterisk server to connect to. *

* Default is localhost. - * + * * @param hostname the hostname to connect to */ public void setHostname(String hostname) @@ -279,7 +279,7 @@ public void setHostname(String hostname) * specified in asterisk's manager.conf file. *

* Default is 5038. - * + * * @param port the port to connect to */ public void setPort(int port) @@ -297,7 +297,7 @@ public void setPort(int port) /** * Sets whether to use SSL.
* Default is false. - * + * * @param ssl true to use SSL for the connection, * false for a plain text connection. * @since 0.3 @@ -310,7 +310,7 @@ public void setSsl(boolean ssl) /** * Sets the username to use to connect to the asterisk server. This is the * username specified in asterisk's manager.conf file. - * + * * @param username the username to use for login */ public void setUsername(String username) @@ -321,7 +321,7 @@ public void setUsername(String username) /** * Sets the password to use to connect to the asterisk server. This is the * password specified in Asterisk's manager.conf file. - * + * * @param password the password to use for login */ public void setPassword(String password) @@ -340,7 +340,7 @@ public void setEncoding(Charset encoding) * {@link #sendAction(ManagerAction)} will wait for a response before * throwing a TimeoutException.
* Default is 2000. - * + * * @param defaultResponseTimeout default response timeout in milliseconds * @since 0.2 */ @@ -355,7 +355,7 @@ public void setDefaultResponseTimeout(long defaultResponseTimeout) * response and the last response event before throwing a TimeoutException. *
* Default is 5000. - * + * * @param defaultEventTimeout default event timeout in milliseconds * @since 0.2 */ @@ -368,7 +368,7 @@ public void setDefaultEventTimeout(long defaultEventTimeout) * Set to true to try reconnecting to ther asterisk serve even * if the reconnection attempt threw an AuthenticationFailedException.
* Default is true. - * + * * @param keepAliveAfterAuthenticationFailure true to try * reconnecting to ther asterisk serve even if the reconnection * attempt threw an AuthenticationFailedException, @@ -498,7 +498,7 @@ public synchronized void login(String eventMask) throws IOException, Authenticat * is sent using the calculated key (MD5 hash of the password appended to * the received challenge). * - * + * * @param timeout the maximum time to wait for the protocol identifier (in * ms) * @param eventMask the event mask. Set to "on" if all events should be @@ -1095,7 +1095,7 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas /** * Creates a new unique internal action id based on the hash code of this * connection and a sequence. - * + * * @return a new internal action id * @see ManagerUtil#addInternalActionId(String,String) * @see ManagerUtil#getInternalActionId(String) @@ -1152,7 +1152,7 @@ public ManagerConnectionState getState() * This method is called by the reader whenever a {@link ManagerResponse} is * received. The response is dispatched to the associated * {@link SendActionCallback}. - * + * * @param response the response received by the reader * @see ManagerReader */ @@ -1223,7 +1223,7 @@ public void dispatchResponse(ManagerResponse response) /** * This method is called by the reader whenever a ManagerEvent is received. * The event is dispatched to all registered ManagerEventHandlers. - * + * * @param event the event received by the reader * @see #addEventListener(ManagerEventListener) * @see #removeEventListener(ManagerEventListener) @@ -1353,7 +1353,7 @@ private void dispatchLegacyEventIfNeeded(ManagerEvent event) /** * Notifies all {@link ManagerEventListener}s registered by users. - * + * * @param event the event to propagate */ private void fireEvent(ManagerEvent event) @@ -1378,7 +1378,7 @@ private void fireEvent(ManagerEvent event) * This method is called when a {@link ProtocolIdentifierReceivedEvent} is * received from the reader. Having received a correct protocol identifier * is the precodition for logging in. - * + * * @param identifier the protocol version used by the Asterisk server. */ private void setProtocolIdentifier(final String identifier) @@ -1397,6 +1397,8 @@ private void setProtocolIdentifier(final String identifier) // 13.2 && !"Asterisk Call Manager/2.8.0".equals(identifier) // Asterisk > 13.5 + && !"Asterisk Call Manager/2.9.0".equals(identifier) // Asterisk > 13.13 + && !"OpenPBX Call Manager/1.0".equals(identifier) && !"CallWeaver Call Manager/1.0".equals(identifier) && !(identifier != null && identifier.startsWith("Asterisk Call Manager Proxy/"))) { @@ -1558,7 +1560,7 @@ private static class DefaultSendActionCallback implements SendActionCallback, Se /** * Creates a new instance. - * + * * @param result the result to store the response in */ public DefaultSendActionCallback(ResponseHandlerResult result) @@ -1587,7 +1589,7 @@ private static class ResponseEventHandler implements ManagerEventListener, SendA /** * Creates a new instance. - * + * * @param events the ResponseEventsImpl to store the events in * @param actionCompleteEventClass the type of event that indicates that * all events have been received From f31713c66acbd95213990ab5d4fd94a94179263f Mon Sep 17 00:00:00 2001 From: Prasad Mahendra Date: Tue, 21 Feb 2017 20:00:36 -0800 Subject: [PATCH 074/802] Fix build break. --- build.gradle | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index 5243989b6..6c6ce04b5 100644 --- a/build.gradle +++ b/build.gradle @@ -12,8 +12,15 @@ description = """Asterisk-Java""" sourceCompatibility = 1.6 targetCompatibility = 1.6 +if (JavaVersion.current().isJava8Compatible()) { + allprojects { + tasks.withType(Javadoc) { + options.addStringOption('Xdoclint:none', '-quiet') + } + } +} + repositories { - maven { url "http://repo.maven.apache.org/maven2" } } @@ -46,9 +53,9 @@ artifacts { archives javadocJar, sourcesJar } -signing { - sign configurations.archives -} +//signing { +// sign configurations.archives +//} def ossrhUsername = hasProperty('ossrhUsername') ? ossrhUsername : '' def ossrhPassword = hasProperty('ossrhPassword') ? ossrhPassword : '' @@ -56,14 +63,21 @@ def ossrhPassword = hasProperty('ossrhPassword') ? ossrhPassword : '' uploadArchives { repositories { mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + //beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } + //repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { + // authentication(userName: ossrhUsername, password: ossrhPassword) + //} + + //snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { + // authentication(userName: ossrhUsername, password: ossrhPassword) + //} - snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - authentication(userName: ossrhUsername, password: ossrhPassword) + ivy { + url "s3://truly-internal/releases" + layout "pattern", { + artifact "[artifact]-[revision].[ext]" + } } pom.project { @@ -152,4 +166,4 @@ uploadArchives { } } } -} \ No newline at end of file +} From fdd86e9b4479f2c44a99d0a144a389ea2de3a63c Mon Sep 17 00:00:00 2001 From: Prasad Mahendra Date: Tue, 21 Feb 2017 20:08:42 -0800 Subject: [PATCH 075/802] Revert "Fix build break." --- build.gradle | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/build.gradle b/build.gradle index 61a66b421..6af40b84c 100644 --- a/build.gradle +++ b/build.gradle @@ -12,15 +12,8 @@ description = """Asterisk-Java""" sourceCompatibility = 1.7 targetCompatibility = 1.7 -if (JavaVersion.current().isJava8Compatible()) { - allprojects { - tasks.withType(Javadoc) { - options.addStringOption('Xdoclint:none', '-quiet') - } - } -} - repositories { + maven { url "http://repo.maven.apache.org/maven2" } } @@ -53,10 +46,10 @@ artifacts { archives javadocJar, sourcesJar } -//signing { -// required { gradle.taskGraph.hasTask("uploadArchives") } -// sign configurations.archives -//} +signing { + required { gradle.taskGraph.hasTask("uploadArchives") } + sign configurations.archives +} def ossrhUsername = hasProperty('ossrhUsername') ? ossrhUsername : '' def ossrhPassword = hasProperty('ossrhPassword') ? ossrhPassword : '' @@ -64,21 +57,14 @@ def ossrhPassword = hasProperty('ossrhPassword') ? ossrhPassword : '' uploadArchives { repositories { mavenDeployer { - //beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - //repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - // authentication(userName: ossrhUsername, password: ossrhPassword) - //} - - //snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - // authentication(userName: ossrhUsername, password: ossrhPassword) - //} + repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { + authentication(userName: ossrhUsername, password: ossrhPassword) + } - ivy { - url "s3://truly-internal/releases" - layout "pattern", { - artifact "[artifact]-[revision].[ext]" - } + snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { + authentication(userName: ossrhUsername, password: ossrhPassword) } pom.project { @@ -167,4 +153,4 @@ uploadArchives { } } } -} +} \ No newline at end of file From d0e47610a401fcd43dc509eca4cefe74c2c26830 Mon Sep 17 00:00:00 2001 From: Sebastian Murray-Roberts Date: Wed, 5 Apr 2017 10:01:23 +0200 Subject: [PATCH 076/802] Added pattern matchers to match certified versions of Asterisk 11 and 13 --- .../manager/internal/ManagerConnectionImpl.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 44dc3da49..66a006401 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -94,8 +94,10 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher private static final Pattern VERSION_PATTERN_1_8 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?1\\.8[-. ].*"); private static final Pattern VERSION_PATTERN_10 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?10[-. ].*"); private static final Pattern VERSION_PATTERN_11 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?11[-. ].*"); + private static final Pattern VERSION_PATTERN_CERTIFIED_11 = Pattern.compile("^\\s*Asterisk certified/((SVN-branch|GIT)-)?11[-. ].*"); private static final Pattern VERSION_PATTERN_12 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?12[-. ].*"); private static final Pattern VERSION_PATTERN_13 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?13[-. ].*"); + private static final Pattern VERSION_PATTERN_CERTIFIED_13 = Pattern.compile("^\\s*Asterisk certified/((SVN-branch|GIT)-)?13[-. ].*"); private static final Pattern VERSION_PATTERN_14 = Pattern.compile("^\\s*Asterisk (GIT-)?14[-. ].*"); private static final AtomicLong idCounter = new AtomicLong(0); @@ -703,6 +705,10 @@ else if (VERSION_PATTERN_11.matcher(coreLine).matches()) { return AsteriskVersion.ASTERISK_11; } + else if (VERSION_PATTERN_CERTIFIED_11.matcher(coreLine).matches()) + { + return AsteriskVersion.ASTERISK_11; + } else if (VERSION_PATTERN_12.matcher(coreLine).matches()) { return AsteriskVersion.ASTERISK_12; @@ -711,6 +717,10 @@ else if (VERSION_PATTERN_13.matcher(coreLine).matches()) { return AsteriskVersion.ASTERISK_13; } + else if (VERSION_PATTERN_CERTIFIED_13.matcher(coreLine).matches()) + { + return AsteriskVersion.ASTERISK_13; + } else if (VERSION_PATTERN_14.matcher(coreLine).matches()) { return AsteriskVersion.ASTERISK_14; From e88d7eb72ae669893275220b311a33cb56739675 Mon Sep 17 00:00:00 2001 From: "Shonbir.singh" Date: Wed, 5 Apr 2017 16:18:05 +0530 Subject: [PATCH 077/802] Adding "output" response key handling for Asterisk 14.3.0 --- .../manager/internal/ResponseBuilderImpl.java | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java index 87f757f2d..1e2f740ab 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java @@ -44,8 +44,10 @@ class ResponseBuilderImpl extends AbstractBuilder implements ResponseBuilder private static final String RESPONSE_KEY = "response"; private static final String PROXY_RESPONSE_KEY = "proxyresponse"; private static final String RESPONSE_TYPE_ERROR = "error"; + private static final String OUTPUT_RESPONSE_KEY = "output"; //Asterisk 14.3.0 - public ManagerResponse buildResponse(Class responseClass, Map attributes) + @SuppressWarnings("unchecked") + public ManagerResponse buildResponse(Class responseClass, Map attributes) { final ManagerResponse response; final String responseType = (String) attributes.get(RESPONSE_KEY); @@ -77,13 +79,27 @@ else if (responseClass == null) { final CommandResponse commandResponse = (CommandResponse) response; final List result = new ArrayList<>(); - for (String resultLine : ((String) attributes.get(ManagerReader.COMMAND_RESULT_RESPONSE_KEY)).split("\n")) - { - // on error there is a leading space - if (!resultLine.equals("--END COMMAND--") && !resultLine.equals(" --END COMMAND--")) - { - result.add(resultLine); - } + //For Asterisk 14 + if(attributes.get(OUTPUT_RESPONSE_KEY) != null){ + if(attributes.get(OUTPUT_RESPONSE_KEY) instanceof List){ + for(String tmp : (List)attributes.get(OUTPUT_RESPONSE_KEY)){ + if(tmp != null && tmp.length() != 0){ + result.add(tmp.trim()); + } + } + }else{ + result.add((String)attributes.get(OUTPUT_RESPONSE_KEY)); + } + + }else{ + for (String resultLine : ((String) attributes.get(ManagerReader.COMMAND_RESULT_RESPONSE_KEY)).split("\n")) + { + // on error there is a leading space + if (!resultLine.equals("--END COMMAND--") && !resultLine.equals(" --END COMMAND--")) + { + result.add(resultLine); + } + } } commandResponse.setResult(result); } From f78e43a26ac225005aa0af7fbc264dc76b289fc2 Mon Sep 17 00:00:00 2001 From: "Shonbir.singh" Date: Wed, 5 Apr 2017 16:20:50 +0530 Subject: [PATCH 078/802] Corrected "output" setter when "output" response is list --- .../asteriskjava/manager/internal/AbstractBuilder.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index f77d08b50..8dd944a21 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -104,6 +104,15 @@ else if (dataType.isAssignableFrom(String.class)) value = null; } + if(value instanceof List){ + StringBuffer strBuff = new StringBuffer(); + for(String tmp : (List)value){ + if(tmp != null && tmp.length() != 0){ + strBuff.append(tmp + "\n"); + } + } + value = strBuff.toString(); + } } else if (dataType.isAssignableFrom(Map.class)) { From a438fa3584f77a6548fa71f8f95d2da0c51fd056 Mon Sep 17 00:00:00 2001 From: "Shonbir.singh" Date: Wed, 5 Apr 2017 16:23:03 +0530 Subject: [PATCH 079/802] Adding "Asterisk Call Manager/3.1.0" for Asterisk 14.3.0 --- .../asteriskjava/manager/internal/ManagerConnectionImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 44dc3da49..968d2ca4d 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1398,6 +1398,8 @@ private void setProtocolIdentifier(final String identifier) && !"Asterisk Call Manager/2.8.0".equals(identifier) // Asterisk > 13.5 && !"Asterisk Call Manager/2.9.0".equals(identifier) // Asterisk > 13.13 + + && !"Asterisk Call Manager/3.1.0".equals(identifier) //Asterisk =14.3.0 && !"OpenPBX Call Manager/1.0".equals(identifier) && !"CallWeaver Call Manager/1.0".equals(identifier) && !(identifier != null && identifier.startsWith("Asterisk Call Manager Proxy/"))) From a0a31c1b1e4aa17e5a2884ab5faa037761098d5f Mon Sep 17 00:00:00 2001 From: "Shonbir.singh" Date: Wed, 5 Apr 2017 16:26:17 +0530 Subject: [PATCH 080/802] Do not break, Check if the response contains "output" response key [Asterisk 14.3.0], and send the correct version command --- .../manager/internal/ManagerConnectionImpl.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 968d2ca4d..b35d28646 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -32,6 +32,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -644,7 +645,7 @@ protected AsteriskVersion determineVersion() throws IOException, TimeoutExceptio { final ManagerResponse showVersionFilesResponse; final List showVersionFilesResult; - + boolean Asterisk14outputPresent = false; // increase timeout as output is quite large showVersionFilesResponse = sendAction(new CommandAction("show version files pbx.c"), defaultResponseTimeout * 2); if (!(showVersionFilesResponse instanceof CommandResponse)) @@ -654,10 +655,18 @@ protected AsteriskVersion determineVersion() throws IOException, TimeoutExceptio // actionId='null'; message='Permission denied'; // response='Error'; // uniqueId='null'; systemHashcode=15231583 - break; + if(showVersionFilesResponse.getOutput() != null){ + Asterisk14outputPresent = true; + }else{ + break; + } + } + if(Asterisk14outputPresent){ + List outputList = Arrays.asList(showVersionFilesResponse.getOutput().split(SocketConnectionFacadeImpl.NL_PATTERN.pattern())); + showVersionFilesResult = outputList; + }else{ + showVersionFilesResult = ((CommandResponse) showVersionFilesResponse).getResult(); } - - showVersionFilesResult = ((CommandResponse) showVersionFilesResponse).getResult(); if (showVersionFilesResult != null && !showVersionFilesResult.isEmpty()) { final String line1 = showVersionFilesResult.get(0); From 8944112ce2d4fce60b65d1f9b431aabd140fcee9 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 30 May 2017 13:41:33 +1000 Subject: [PATCH 081/802] change separation of args to use pipe --- src/main/java/org/asteriskjava/fastagi/command/DialCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java index d00ccdd63..7c0885851 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java @@ -33,7 +33,7 @@ public String buildCommand() + escapeAndQuote("" + timeout); if (options != null && options.length() > 0) { - command += "," + escapeAndQuote(options); + command += "|" + escapeAndQuote(options); } logger.info(command); From 7073b93390822ec500c9911ec7af5cdb3716e7b8 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 9 Jun 2017 10:32:33 +1000 Subject: [PATCH 082/802] change assert condition --- .../pbx/asterisk/wrap/events/RenameEvent.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java index b5e15762c..925f94472 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java @@ -11,7 +11,6 @@ public class RenameEvent extends ManagerEvent implements ChannelEvent { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") private static final Logger logger = Logger.getLogger(RenameEvent.class); /** @@ -32,8 +31,11 @@ public RenameEvent(final org.asteriskjava.manager.event.RenameEvent event) throw this._channel = pbx.internalRegisterChannel(event.getChannel(), event.getUniqueId()); this._newName = event.getNewname(); - assert ((ChannelProxy) this._channel).getRealChannel().getUniqueId() - .compareToIgnoreCase(event.getUniqueId()) == 0 : "Rename registered against incorrect channel"; //$NON-NLS-1$ + String uniqueId = ((ChannelProxy) this._channel).getRealChannel().getUniqueId(); + logger.error("Renaming :" + uniqueId + " " + event.getUniqueId()); + + assert uniqueId.equalsIgnoreCase("-1") + || uniqueId.compareToIgnoreCase(event.getUniqueId()) == 0 : "Rename registered against incorrect channel"; //$NON-NLS-1$ } From 004357e5ff532facdd7eca42d2f008dc550f120d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 29 Jun 2017 16:10:33 +1000 Subject: [PATCH 083/802] Auto configuration of AgiScripts --- .../org/asteriskjava/pbx/agi/ActivityAgi.java | 3 +- .../pbx/agi/config/AgiConfiguration.java | 10 ++ .../pbx/agi/config/AgiMappingStragegy.java | 136 ++++++++++++++++++ .../pbx/agi/config/ConfiguableAGIServer.java | 56 ++++++++ .../agi/config/DuplicateScriptException.java | 14 ++ .../ServiceAgiScript.java} | 30 ++-- .../pbx/internal/core/AsteriskPBX.java | 5 +- 7 files changed, 241 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/agi/config/AgiConfiguration.java create mode 100644 src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java create mode 100644 src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java create mode 100644 src/main/java/org/asteriskjava/pbx/agi/config/DuplicateScriptException.java rename src/main/java/org/asteriskjava/pbx/agi/{NJAgiScript.java => config/ServiceAgiScript.java} (62%) diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index 79064af7b..5d9662054 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -7,11 +7,12 @@ import org.asteriskjava.pbx.ChannelHangupListener; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.agi.config.ServiceAgiScript; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class ActivityAgi extends NJAgiScript +public abstract class ActivityAgi extends ServiceAgiScript { private final Log logger = LogFactory.getLog(this.getClass()); diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/AgiConfiguration.java b/src/main/java/org/asteriskjava/pbx/agi/config/AgiConfiguration.java new file mode 100644 index 000000000..14bbd70e1 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/agi/config/AgiConfiguration.java @@ -0,0 +1,10 @@ +package org.asteriskjava.pbx.agi.config; + +import java.util.List; + +public interface AgiConfiguration +{ + + List> getAgiHandlers(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java b/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java new file mode 100644 index 000000000..b89d6c7cc --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java @@ -0,0 +1,136 @@ +/* + * Copyright 2004-2006 by S. Brett Sutton. Commercial support is provided by + * Asterisk I.T. http://www.asteriskit.com.au + * + * The contents of this file are subject to a modified GPL Version 2 License or + * later version at your discretion. + * + * The sole modification to the GPL is a limitation on use. + * + * The limitation is that AsterFax (and its source components) may only be used + * on a single Channel as defined in AsterFax.xml. The implications of the + * limitation is that the free verions of AsterFax may only be used to send or + * receive a single fax at a time. + * + * Any copied or modified versions of the AsterFax source must retain this + * limitation. + * + * If you wish to use multiple channels then you can purchase a commercial + * license by emailing sales@asteriskit.com.au + * + * Contributor(s): all the names of the contributors are added in the source + * code where applicable. + */ +package org.asteriskjava.pbx.agi.config; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiRequest; +import org.asteriskjava.fastagi.AgiScript; +import org.asteriskjava.fastagi.MappingStrategy; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class AgiMappingStragegy implements MappingStrategy +{ + + static private final Log logger = LogFactory.getLog(AgiMappingStragegy.class); + + private Map> handlers = new HashMap<>(); + + @Override + public AgiScript determineScript(AgiRequest request, AgiChannel channel) + { + AgiScript ret = null; + + String script = request.getScript(); + if (script.indexOf(".") != -1) + { + script = script.substring(0, script.indexOf(".")); + } + else + { + logger.warn("scripts should be called as scriptname.agi"); + } + if (script.startsWith("/")) + { + // this is specifically for the "FastAgiSimulator" + script = script.substring(1); + } + Iterator itr = request.getParameterMap().keySet().iterator(); + logger.info("*********************************"); + logger.info("script " + script); + while (itr.hasNext()) + { + String key = itr.next(); + String val = request.getParameter(key); + if (key.compareToIgnoreCase("cardNumber") == 0) + val = "suppressed"; + logger.info(key + ": " + val); + } + logger.info("******"); + + if (handlers.containsKey(script)) + { + try + { + ret = handlers.get(script).newInstance(); + } + catch (InstantiationException e) + { + // TODO Auto-generated catch block + logger.error(e, e); + } + catch (IllegalAccessException e) + { + // TODO Auto-generated catch block + logger.error(e, e); + } + } + + return ret; + } + + /** + * this will be a pluggable extension system for the agi core, it's still a + * work in progress and is not useable + * + * @param handler + * @throws DuplicateScriptException + * @throws IllegalAccessException + * @throws InstantiationException + */ + @SuppressWarnings("unchecked") + public void addNoojeeAgiHandler(Class< ? extends ServiceAgiScript> handler) + throws DuplicateScriptException, InstantiationException, IllegalAccessException + { + + logger.info("loading agi handler {}" + handler.getCanonicalName()); + ServiceAgiScript tmpHandler = handler.newInstance(); + if (handlers.containsKey(tmpHandler.getScriptName())) + { + throw new DuplicateScriptException("Script " + tmpHandler.getScriptName() + " already exists"); + } + String[] parameters = tmpHandler.getParameters(); + String sample = "Agi(agi://localhost/" + tmpHandler.getScriptName() + ".agi"; + logger.info("********************************************"); + logger.info("registered new agi script: " + tmpHandler.getScriptName()); + for (int i = 0; i < parameters.length; i++) + { + logger.info("parameter: " + parameters[i]); + if (i == 0) + sample += "?" + parameters[i] + "=testdata"; + else + sample += "&" + parameters[i] + "=testdata"; + } + + logger.info("sample usage..."); + logger.info(sample + ")"); + Class handler2 = (Class) handler; + handlers.put(tmpHandler.getScriptName(), handler2); + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java b/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java new file mode 100644 index 000000000..bb9c6ebb2 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java @@ -0,0 +1,56 @@ +/* + * Copyright 2004-2006 by S. Brett Sutton. + * Commercial support is provided by Asterisk I.T. http://www.asteriskit.com.au + * + * The contents of this file are subject to a modified GPL Version 2 License + * or later version at your discretion. + * + * The sole modification to the GPL is a limitation on use. + * + * The limitation is that AsterFax (and its source components) may only be used on a single Channel + * as defined in AsterFax.xml. + * The implications of the limitation is that the free verions of AsterFax may only be used to send + * or receive a single fax at a time. + * + * Any copied or modified versions of the AsterFax source must retain this limitation. + * + * If you wish to use multiple channels then you can purchase a commercial license + * by emailing sales@asteriskit.com.au + * + * Contributor(s): all the names of the contributors are added in the source code + * where applicable. + */ +package org.asteriskjava.pbx.agi.config; + +import java.util.List; + +import javax.naming.ConfigurationException; + +import org.asteriskjava.fastagi.DefaultAgiServer; + +public class ConfiguableAGIServer extends DefaultAgiServer implements Runnable +{ + + public ConfiguableAGIServer(AgiConfiguration configuration) + throws DuplicateScriptException, InstantiationException, IllegalAccessException, ConfigurationException + { + AgiMappingStragegy mappingStrategy = new AgiMappingStragegy(); + setMaximumPoolSize(500); + loadHandlers(mappingStrategy, configuration); + + this.setMappingStrategy(mappingStrategy); + new Thread(this, "AGIServer:" + this.getPort()).start(); + + } + + private void loadHandlers(AgiMappingStragegy mappingStrategy, AgiConfiguration configuration) + throws DuplicateScriptException, InstantiationException, IllegalAccessException + { + List> handlers = configuration.getAgiHandlers(); + for (Class< ? extends ServiceAgiScript> clazz : handlers) + { + mappingStrategy.addNoojeeAgiHandler(clazz); + } + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/DuplicateScriptException.java b/src/main/java/org/asteriskjava/pbx/agi/config/DuplicateScriptException.java new file mode 100644 index 000000000..9221273aa --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/agi/config/DuplicateScriptException.java @@ -0,0 +1,14 @@ +package org.asteriskjava.pbx.agi.config; + +public class DuplicateScriptException extends Exception +{ + public DuplicateScriptException(String string) + { + super(string); + } + + /** + * + */ + private static final long serialVersionUID = -3931649299622511878L; +} diff --git a/src/main/java/org/asteriskjava/pbx/agi/NJAgiScript.java b/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScript.java similarity index 62% rename from src/main/java/org/asteriskjava/pbx/agi/NJAgiScript.java rename to src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScript.java index 39ba5e5ae..be1a888e6 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/NJAgiScript.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScript.java @@ -1,14 +1,26 @@ -package org.asteriskjava.pbx.agi; +package org.asteriskjava.pbx.agi.config; -import org.apache.log4j.Logger; import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiRequest; import org.asteriskjava.fastagi.BaseAgiScript; - -abstract public class NJAgiScript extends BaseAgiScript +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +/** + * Allows for auto configuration of the AGI script.
+ *
+ * Provides a getParameter(..) method which verifies the existence of the + * parameter.
+ *
+ * Requires an implementing agi to provide it's name and parameter list via + * getScriptName() and getParameters. + * + * @author rsutton + */ +abstract public class ServiceAgiScript extends BaseAgiScript { - static transient Logger logger = Logger.getLogger(NJAgiScript.class); + static transient Log logger = LogFactory.getLog(ServiceAgiScript.class); protected AgiRequest request; protected AgiChannel channel; @@ -40,10 +52,8 @@ protected String getParameter(String name) throws AgiException return required(name, request.getParameter(name)); } - public void setVariable(String name, String value) throws AgiException - { - logger.debug("AGIVar set: " + name + "=(" + value + ")"); - super.setVariable(name, value); - } + public abstract String getScriptName(); + + public abstract String[] getParameters(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 2e4e67db1..55087d1b3 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -6,7 +6,6 @@ import java.util.Map; import java.util.concurrent.TimeUnit; -import org.apache.log4j.Logger; import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.AuthenticationFailedException; import org.asteriskjava.manager.EventTimeoutException; @@ -65,13 +64,15 @@ import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoomControl; import org.asteriskjava.pbx.internal.managerAPI.RedirectCall; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public enum AsteriskPBX implements PBX, ChannelHangupListener { SELF; - private final Logger logger = Logger.getLogger(AsteriskPBX.class); + private final Log logger = LogFactory.getLog(getClass()); private boolean muteSupported; private boolean bridgeSupport; From 56193933ebd09a5341561f3b4aeffc5451944da5 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 30 Jun 2017 16:09:24 +1000 Subject: [PATCH 084/802] remove unnecessary direct references to log4j --- pom.xml | 2 +- .../org/asteriskjava/fastagi/HangupTest.java | 2 +- .../java/org/asteriskjava/pbx/CallImpl.java | 5 +- .../asteriskjava/pbx/CallStateAnswered.java | 27 +- .../org/asteriskjava/pbx/CallStateData.java | 4 - .../pbx/CallStateDataNewInbound.java | 37 +- .../asteriskjava/pbx/CallStateDataParked.java | 14 +- .../pbx/CallStateDataTransfer.java | 81 +- .../org/asteriskjava/pbx/ChannelFactory.java | 15 +- .../asteriskjava/pbx/CompletionAdaptor.java | 5 +- .../asteriskjava/pbx/DialPlanExtension.java | 168 ++--- .../org/asteriskjava/pbx/PBXException.java | 30 +- .../java/org/asteriskjava/pbx/TechType.java | 169 ++--- .../wrap/actions/ListCommandsAction.java | 26 +- .../pbx/asterisk/wrap/actions/PingAction.java | 26 +- .../wrap/actions/UserEventAction.java | 29 +- .../events/AbstractChannelStateEvent.java | 42 +- .../wrap/events/AbstractMeetMeEvent.java | 51 +- .../wrap/events/AbstractParkedCallEvent.java | 42 +- .../wrap/events/AgentCalledEvent.java | 41 +- .../wrap/events/AgentConnectEvent.java | 41 +- .../pbx/asterisk/wrap/events/BridgeEvent.java | 5 +- .../wrap/events/ChannelEventHelper.java | 4 - .../asterisk/wrap/events/ConnectEvent.java | 33 +- .../wrap/events/DbGetResponseEvent.java | 61 +- .../pbx/asterisk/wrap/events/DialEvent.java | 4 - .../asterisk/wrap/events/DisconnectEvent.java | 14 +- .../asterisk/wrap/events/DndStateEvent.java | 4 - .../wrap/events/ExtensionStatusEvent.java | 174 +++-- .../pbx/asterisk/wrap/events/HangupEvent.java | 100 ++- .../pbx/asterisk/wrap/events/LinkEvent.java | 15 +- .../asterisk/wrap/events/ManagerEvent.java | 15 +- .../asterisk/wrap/events/MasqueradeEvent.java | 4 - .../asterisk/wrap/events/MeetMeJoinEvent.java | 28 +- .../wrap/events/MeetMeLeaveEvent.java | 40 +- .../asterisk/wrap/events/NewChannelEvent.java | 71 +- .../asterisk/wrap/events/NewExtenEvent.java | 4 - .../asterisk/wrap/events/NewStateEvent.java | 3 - .../wrap/events/OriginateResponseEvent.java | 166 ++--- .../asterisk/wrap/events/ParkedCallEvent.java | 4 - .../asterisk/wrap/events/PeerEntryEvent.java | 28 +- .../asterisk/wrap/events/PeerStatusEvent.java | 30 +- .../wrap/events/PeerlistCompleteEvent.java | 14 +- .../wrap/events/QueueCallerLeaveEvent.java | 4 - .../pbx/asterisk/wrap/events/RenameEvent.java | 5 +- .../asterisk/wrap/events/ResponseEvent.java | 47 +- .../wrap/events/StatusCompleteEvent.java | 14 +- .../pbx/asterisk/wrap/events/StatusEvent.java | 4 - .../pbx/asterisk/wrap/events/UnlinkEvent.java | 15 +- .../wrap/events/UnparkedCallEvent.java | 4 - .../pbx/asterisk/wrap/events/VarSetEvent.java | 4 - .../wrap/response/CommandResponse.java | 24 +- .../asterisk/wrap/response/ManagerError.java | 13 +- .../asterisk/wrap/userEvents/UserEvent.java | 4 - .../pbx/internal/activity/ActivityHelper.java | 5 +- .../activity/BlindTransferActivityImpl.java | 5 +- .../internal/activity/BridgeActivityImpl.java | 273 ++++--- .../internal/activity/DialActivityImpl.java | 5 +- .../activity/DialToAgiActivityImpl.java | 5 +- .../internal/activity/HoldActivityImpl.java | 139 ++-- .../internal/activity/JoinActivityImpl.java | 18 +- .../internal/activity/ParkActivityImpl.java | 5 +- .../internal/activity/SplitActivityImpl.java | 10 +- .../pbx/internal/asterisk/CallerIDImpl.java | 200 +++-- .../pbx/internal/asterisk/MeetmeRoom.java | 5 +- .../internal/asterisk/MeetmeRoomControl.java | 5 +- .../pbx/internal/core/CallTracker.java | 379 +++++----- .../pbx/internal/core/ChannelImpl.java | 5 +- .../pbx/internal/core/ChannelProxy.java | 5 +- .../internal/core/CoherentEventFactory.java | 5 +- .../core/CoherentManagerConnection.java | 9 +- .../core/CoherentManagerEventQueue.java | 591 ++++++++------- .../pbx/internal/core/EndPointImpl.java | 4 - .../pbx/internal/core/LiveChannelManager.java | 9 +- .../asteriskjava/pbx/internal/core/Peer.java | 613 ++++++++------- .../pbx/internal/core/PeerMonitor.java | 701 +++++++++--------- .../pbx/internal/core/PeerState.java | 208 +++--- .../internal/eventQueue/EventLifeMonitor.java | 49 +- .../eventQueue/ManagerEventQueue.java | 2 +- .../pbx/internal/managerAPI/Connector.java | 5 +- .../pbx/internal/managerAPI/Dial.java | 5 +- .../pbx/internal/managerAPI/DialToAgi.java | 5 +- .../pbx/internal/managerAPI/MonitorCall.java | 63 +- .../managerAPI/OriginateBaseClass.java | 5 +- .../internal/managerAPI/OriginateResult.java | 82 +- .../pbx/internal/managerAPI/RedirectCall.java | 5 +- .../internal/managerAPI/RedirectToMeetMe.java | 5 +- src/main/java/org/asteriskjava/util/Log.java | 2 + .../util/internal/JavaLoggingLog.java | 15 + .../asteriskjava/util/internal/NullLog.java | 6 + 90 files changed, 2561 insertions(+), 2708 deletions(-) diff --git a/pom.xml b/pom.xml index 22c84c72b..ca5da88f3 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 2.0.0.alpha-SNAPSHOT + 2.0.1.alpha-SNAPSHOT The free Java library for Asterisk PBX integration. 2004 diff --git a/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java b/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java index 5b1ec320d..cb0abe5ec 100644 --- a/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java +++ b/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java @@ -10,7 +10,7 @@ public class HangupTest extends BaseAgiScript { - private Logger logger = Logger.getLogger(HangupTest.class); + private Logger logger = LogFactory.getLog(getClass()); public void service(AgiRequest request, AgiChannel channel) throws AgiException { diff --git a/src/main/java/org/asteriskjava/pbx/CallImpl.java b/src/main/java/org/asteriskjava/pbx/CallImpl.java index 4f2ee7503..233aeb908 100644 --- a/src/main/java/org/asteriskjava/pbx/CallImpl.java +++ b/src/main/java/org/asteriskjava/pbx/CallImpl.java @@ -5,8 +5,9 @@ import java.util.LinkedList; import java.util.List; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.activities.BlindTransferActivity; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * Holds a call which may consist of 0, 1, 2 or 3 channels. When dialing out a @@ -25,7 +26,7 @@ public class CallImpl implements ChannelHangupListener, Call { - static Logger logger = Logger.getLogger(CallImpl.class); + private static final Log logger = LogFactory.getLog(CallImpl.class); /** * We give every call a unique call id to help track the calls when checking diff --git a/src/main/java/org/asteriskjava/pbx/CallStateAnswered.java b/src/main/java/org/asteriskjava/pbx/CallStateAnswered.java index f7a9e273b..30f8714b7 100644 --- a/src/main/java/org/asteriskjava/pbx/CallStateAnswered.java +++ b/src/main/java/org/asteriskjava/pbx/CallStateAnswered.java @@ -1,23 +1,24 @@ package org.asteriskjava.pbx; -import org.apache.log4j.Logger; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class CallStateAnswered extends CallStateData { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(CallStateAnswered.class); + @SuppressWarnings("unused") + private static final Log logger = LogFactory.getLog(CallStateAnswered.class); - // The channel that accepted the call. - private Channel _acceptingParty; + // The channel that accepted the call. + private Channel _acceptingParty; - public CallStateAnswered(Channel acceptingParty) - { - this._acceptingParty = acceptingParty; - } + public CallStateAnswered(Channel acceptingParty) + { + this._acceptingParty = acceptingParty; + } - public Channel getAcceptingParty() - { - return this._acceptingParty; - } + public Channel getAcceptingParty() + { + return this._acceptingParty; + } } diff --git a/src/main/java/org/asteriskjava/pbx/CallStateData.java b/src/main/java/org/asteriskjava/pbx/CallStateData.java index 3a58c0183..c840e29d3 100644 --- a/src/main/java/org/asteriskjava/pbx/CallStateData.java +++ b/src/main/java/org/asteriskjava/pbx/CallStateData.java @@ -1,9 +1,5 @@ package org.asteriskjava.pbx; -import org.apache.log4j.Logger; - public class CallStateData { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(CallStateData.class); } diff --git a/src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java b/src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java index 34942a24d..428030b63 100644 --- a/src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java +++ b/src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java @@ -1,29 +1,30 @@ package org.asteriskjava.pbx; -import org.apache.log4j.Logger; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class CallStateDataNewInbound extends CallStateData { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(CallStateDataNewInbound.class); + @SuppressWarnings("unused") + private static final Log logger = LogFactory.getLog(CallStateDataNewInbound.class); - CallerID _originatingPartyCallerID; + CallerID _originatingPartyCallerID; - private final String _fromDID; + private final String _fromDID; - public CallStateDataNewInbound(String fromDID, CallerID originatingPartyCallerID) - { - this._originatingPartyCallerID = originatingPartyCallerID; - this._fromDID = fromDID; - } + public CallStateDataNewInbound(String fromDID, CallerID originatingPartyCallerID) + { + this._originatingPartyCallerID = originatingPartyCallerID; + this._fromDID = fromDID; + } - public CallerID getOriginatingPartyCallerID() - { - return this._originatingPartyCallerID; - } + public CallerID getOriginatingPartyCallerID() + { + return this._originatingPartyCallerID; + } - public String getFromDID() - { - return this._fromDID; - } + public String getFromDID() + { + return this._fromDID; + } } diff --git a/src/main/java/org/asteriskjava/pbx/CallStateDataParked.java b/src/main/java/org/asteriskjava/pbx/CallStateDataParked.java index 579a9aaa1..0a52bcc4d 100644 --- a/src/main/java/org/asteriskjava/pbx/CallStateDataParked.java +++ b/src/main/java/org/asteriskjava/pbx/CallStateDataParked.java @@ -1,17 +1,13 @@ package org.asteriskjava.pbx; -import org.apache.log4j.Logger; - public class CallStateDataParked extends CallStateData { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(CallStateDataParked.class); - EndPoint _parkingLot; + EndPoint _parkingLot; - public CallStateDataParked(EndPoint parkingLot) - { - this._parkingLot = parkingLot; - } + public CallStateDataParked(EndPoint parkingLot) + { + this._parkingLot = parkingLot; + } } diff --git a/src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java b/src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java index cda21f04b..c0686ca5f 100644 --- a/src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java +++ b/src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java @@ -1,50 +1,47 @@ package org.asteriskjava.pbx; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.CallImpl.TransferType; import org.asteriskjava.pbx.activities.BlindTransferActivity; public class CallStateDataTransfer extends CallStateData { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(CallStateDataTransfer.class); - - private TransferType _transferType; - /** - * the end point we are attempting to transfer the call to. - */ - private EndPoint _transferTarget; - - private CallerID _transferTargetCallerID; - - private BlindTransferActivity _transferActivity; - - public CallStateDataTransfer(TransferType transferType, EndPoint transferTarget, CallerID transferTargetCallerID, - BlindTransferActivity transferActivity) - { - this._transferType = transferType; - this._transferTarget = transferTarget; - this._transferTargetCallerID = transferTargetCallerID; - this._transferActivity = transferActivity; - } - - public EndPoint getTransferTarget() - { - return this._transferTarget; - } - - public CallerID getTransferTargetCallerID() - { - return this._transferTargetCallerID; - } - - public TransferType getTransferType() - { - return this._transferType; - } - - public BlindTransferActivity getActivity() - { - return this._transferActivity; - } + + private TransferType _transferType; + /** + * the end point we are attempting to transfer the call to. + */ + private EndPoint _transferTarget; + + private CallerID _transferTargetCallerID; + + private BlindTransferActivity _transferActivity; + + public CallStateDataTransfer(TransferType transferType, EndPoint transferTarget, CallerID transferTargetCallerID, + BlindTransferActivity transferActivity) + { + this._transferType = transferType; + this._transferTarget = transferTarget; + this._transferTargetCallerID = transferTargetCallerID; + this._transferActivity = transferActivity; + } + + public EndPoint getTransferTarget() + { + return this._transferTarget; + } + + public CallerID getTransferTargetCallerID() + { + return this._transferTargetCallerID; + } + + public TransferType getTransferType() + { + return this._transferType; + } + + public BlindTransferActivity getActivity() + { + return this._transferActivity; + } } diff --git a/src/main/java/org/asteriskjava/pbx/ChannelFactory.java b/src/main/java/org/asteriskjava/pbx/ChannelFactory.java index 7d1d0f75a..0e5fd88f5 100644 --- a/src/main/java/org/asteriskjava/pbx/ChannelFactory.java +++ b/src/main/java/org/asteriskjava/pbx/ChannelFactory.java @@ -1,23 +1,18 @@ package org.asteriskjava.pbx; -import org.apache.log4j.Logger; - /** * Currently this factories only purposes is to serve up globally unique channel * id's which every new channel must be assigned. * * @author bsutton - * */ public class ChannelFactory { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(ChannelFactory.class); - private static long nextChannelId = 0; + private static long nextChannelId = 0; - public static synchronized long getNextChannelId() - { - return ++ChannelFactory.nextChannelId; - } + public static synchronized long getNextChannelId() + { + return ++ChannelFactory.nextChannelId; + } } diff --git a/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java b/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java index f17271d68..71f6b4d6d 100644 --- a/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java +++ b/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java @@ -3,7 +3,8 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.apache.log4j.Logger; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * This is a utility class designed to wait for an activity to complete. When @@ -16,7 +17,7 @@ */ public class CompletionAdaptor implements ActivityCallback { - private static final Logger logger = Logger.getLogger(CompletionAdaptor.class); + private static final Log logger = LogFactory.getLog(CompletionAdaptor.class); CountDownLatch _latch = new CountDownLatch(1); diff --git a/src/main/java/org/asteriskjava/pbx/DialPlanExtension.java b/src/main/java/org/asteriskjava/pbx/DialPlanExtension.java index 9b4bc5fa3..cbdf2e7c3 100644 --- a/src/main/java/org/asteriskjava/pbx/DialPlanExtension.java +++ b/src/main/java/org/asteriskjava/pbx/DialPlanExtension.java @@ -1,111 +1,101 @@ package org.asteriskjava.pbx; -import org.apache.log4j.Logger; - /** - * Represents an asterisk dial plan extension such as: - * - * [njr-operator] - * njr-inbound,1,xxxxx - * - * In the above example njr-inbound is the dialplan extension. - * - * This class primarily exists to stop common mistakes that can occur if we pass - * this around as a simple string. + * Represents an asterisk dial plan extension such as: [njr-operator] + * njr-inbound,1,xxxxx In the above example njr-inbound is the dialplan + * extension. This class primarily exists to stop common mistakes that can occur + * if we pass this around as a simple string. * * @author bsutton - * */ public class DialPlanExtension implements EndPoint { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(DialPlanExtension.class); - // the dial plan extension. - String _extension; - final boolean _empty; + // the dial plan extension. + String _extension; + final boolean _empty; - public DialPlanExtension(String extension) - { - if (extension == null || extension.trim().length() == 0) - { - this._empty = true; - this._extension = ""; - } - else - { - this._extension = extension.trim(); - this._empty = false; - } - } + public DialPlanExtension(String extension) + { + if (extension == null || extension.trim().length() == 0) + { + this._empty = true; + this._extension = ""; + } + else + { + this._extension = extension.trim(); + this._empty = false; + } + } - @Override - public int compareTo(EndPoint rhs) - { - return this._extension.compareTo(rhs.getSimpleName()); - } + @Override + public int compareTo(EndPoint rhs) + { + return this._extension.compareTo(rhs.getSimpleName()); + } - @Override - public boolean isSame(EndPoint rhs) - { - return this.compareTo(rhs) == 0; - } + @Override + public boolean isSame(EndPoint rhs) + { + return this.compareTo(rhs) == 0; + } - @Override - public boolean isLocal() - { - return false; - } + @Override + public boolean isLocal() + { + return false; + } - @Override - public boolean isSIP() - { - return false; - } + @Override + public boolean isSIP() + { + return false; + } - /** - * The same as getSimpleName as in this case the Tech is really just an - * identifier rather than a legitimate tech that the pbx understands. - */ - @Override - public String getFullyQualifiedName() - { - return this._extension; - } + /** + * The same as getSimpleName as in this case the Tech is really just an + * identifier rather than a legitimate tech that the pbx understands. + */ + @Override + public String getFullyQualifiedName() + { + return this._extension; + } - @Override - public String getSimpleName() - { - return this._extension; - } + @Override + public String getSimpleName() + { + return this._extension; + } - @Override - public String getSIPSimpleName() - { - throw new UnsupportedOperationException(); - } + @Override + public String getSIPSimpleName() + { + throw new UnsupportedOperationException(); + } - @Override - public boolean isUnknown() - { - // TODO Auto-generated method stub - return false; - } + @Override + public boolean isUnknown() + { + // TODO Auto-generated method stub + return false; + } - @Override - public TechType getTech() - { - return TechType.DIALPLAN; - } + @Override + public TechType getTech() + { + return TechType.DIALPLAN; + } - public String toString() - { - return this._extension; - } + public String toString() + { + return this._extension; + } - @Override - public boolean isEmpty() - { - return false; - } + @Override + public boolean isEmpty() + { + return false; + } } diff --git a/src/main/java/org/asteriskjava/pbx/PBXException.java b/src/main/java/org/asteriskjava/pbx/PBXException.java index fe754e0ca..6d12bf3fe 100644 --- a/src/main/java/org/asteriskjava/pbx/PBXException.java +++ b/src/main/java/org/asteriskjava/pbx/PBXException.java @@ -1,25 +1,21 @@ package org.asteriskjava.pbx; -import org.apache.log4j.Logger; - public class PBXException extends Exception { - private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(PBXException.class); + private static final long serialVersionUID = 1L; - public PBXException(String message, final Exception e) - { - super(message, e); - } + public PBXException(String message, final Exception e) + { + super(message, e); + } - public PBXException(final String message) - { - super(message); - } + public PBXException(final String message) + { + super(message); + } - public PBXException(Throwable e) - { - super(e); - } + public PBXException(Throwable e) + { + super(e); + } } diff --git a/src/main/java/org/asteriskjava/pbx/TechType.java b/src/main/java/org/asteriskjava/pbx/TechType.java index fd20efa1b..8ded5b1ed 100644 --- a/src/main/java/org/asteriskjava/pbx/TechType.java +++ b/src/main/java/org/asteriskjava/pbx/TechType.java @@ -1,90 +1,91 @@ package org.asteriskjava.pbx; -import org.apache.log4j.Logger; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public enum TechType implements Tech { - // - UNKNOWN, SIP, DAHDI, LOCAL, IAX, IAX2 - // The DIALPLAN tech is used to suppresses output of the tech - // when obtaining the fully qualified name of the endpoint. - // Basically if you want to call into an asterisk dialplan extension - // then the tech needs to be suppressed. - , DIALPLAN - // CONSOLE is sent when a call is made from the asterisk console. - // These type of channels are ignored. - , CONSOLE; - - private static final Logger logger = Logger.getLogger(TechType.class); - - /** - * Extracts the technology from a fully qualified endpoint string of the - * form: TECH/NNNN - * - * @param fullyQualifiedEndPoint - * @return - */ - public static TechType getTech(final String fullyQualifiedEndPoint) - { - if (!TechType.hasValidTech(fullyQualifiedEndPoint)) - { - throw new IllegalArgumentException("The provided end point '" //$NON-NLS-1$ - + fullyQualifiedEndPoint + "' must contain a tech prefix. e.g. SIP/100"); //$NON-NLS-1$ - } - - final String techName = fullyQualifiedEndPoint.substring(0, fullyQualifiedEndPoint.indexOf("/")); //$NON-NLS-1$ - return TechType.valueOf(techName.toUpperCase()); - } - - /** - * returns true if the endPoint name contains a valid tech descriptor. - * - * @param endPointName - * @return - */ - public static boolean hasValidTech(final String endPointName) - { - TechType tech = UNKNOWN; - final int index = endPointName.indexOf("/"); //$NON-NLS-1$ - - if (index >= 1) - { - final String techName = endPointName.substring(0, index); - try - { - tech = TechType.valueOf(techName.toUpperCase()); - } - catch (final IllegalArgumentException e) - { - TechType.logger.error("Invalid tech for endpoint:" + endPointName); //$NON-NLS-1$ - } - } - - return tech != UNKNOWN; - - } - - /** - * returns true if the endPoint name contains a tech descriptor even if it - * isn't a known descriptor. - * - * @param endPointName - * @return - */ - public static boolean hasTech(final String endPointName) - { - boolean hasTech = false; - - final int index = endPointName.indexOf("/"); //$NON-NLS-1$ - - if (index != -1) - { - hasTech = true; - } - - return hasTech; - - } - -} \ No newline at end of file + // + UNKNOWN, SIP, DAHDI, LOCAL, IAX, IAX2 + // The DIALPLAN tech is used to suppresses output of the tech + // when obtaining the fully qualified name of the endpoint. + // Basically if you want to call into an asterisk dialplan extension + // then the tech needs to be suppressed. + , DIALPLAN + // CONSOLE is sent when a call is made from the asterisk console. + // These type of channels are ignored. + , CONSOLE; + + private static final Log logger = LogFactory.getLog(TechType.class); + + /** + * Extracts the technology from a fully qualified endpoint string of the + * form: TECH/NNNN + * + * @param fullyQualifiedEndPoint + * @return + */ + public static TechType getTech(final String fullyQualifiedEndPoint) + { + if (!TechType.hasValidTech(fullyQualifiedEndPoint)) + { + throw new IllegalArgumentException("The provided end point '" //$NON-NLS-1$ + + fullyQualifiedEndPoint + "' must contain a tech prefix. e.g. SIP/100"); //$NON-NLS-1$ + } + + final String techName = fullyQualifiedEndPoint.substring(0, fullyQualifiedEndPoint.indexOf("/")); //$NON-NLS-1$ + return TechType.valueOf(techName.toUpperCase()); + } + + /** + * returns true if the endPoint name contains a valid tech descriptor. + * + * @param endPointName + * @return + */ + public static boolean hasValidTech(final String endPointName) + { + TechType tech = UNKNOWN; + final int index = endPointName.indexOf("/"); //$NON-NLS-1$ + + if (index >= 1) + { + final String techName = endPointName.substring(0, index); + try + { + tech = TechType.valueOf(techName.toUpperCase()); + } + catch (final IllegalArgumentException e) + { + TechType.logger.error("Invalid tech for endpoint:" + endPointName); //$NON-NLS-1$ + } + } + + return tech != UNKNOWN; + + } + + /** + * returns true if the endPoint name contains a tech descriptor even if it + * isn't a known descriptor. + * + * @param endPointName + * @return + */ + public static boolean hasTech(final String endPointName) + { + boolean hasTech = false; + + final int index = endPointName.indexOf("/"); //$NON-NLS-1$ + + if (index != -1) + { + hasTech = true; + } + + return hasTech; + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ListCommandsAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ListCommandsAction.java index 12b9c8dc4..cd2c77a1a 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ListCommandsAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ListCommandsAction.java @@ -1,24 +1,20 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; -import org.apache.log4j.Logger; - public class ListCommandsAction extends AbstractManagerAction { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(ListCommandsAction.class); - @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.ListCommandsAction action = new org.asteriskjava.manager.action.ListCommandsAction(); - action.setActionId(this.getActionId()); + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.ListCommandsAction action = new org.asteriskjava.manager.action.ListCommandsAction(); + action.setActionId(this.getActionId()); - return action; - } + return action; + } - public String toString() - { - return "ListCommandsAction"; //$NON-NLS-1$ - } + public String toString() + { + return "ListCommandsAction"; //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PingAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PingAction.java index c44c97e6b..320526670 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PingAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PingAction.java @@ -1,23 +1,19 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; -import org.apache.log4j.Logger; - public class PingAction extends AbstractManagerAction { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(PingAction.class); - @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.PingAction action = new org.asteriskjava.manager.action.PingAction(); - action.setActionId(this.getActionId()); - return action; - } + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.PingAction action = new org.asteriskjava.manager.action.PingAction(); + action.setActionId(this.getActionId()); + return action; + } - public String toString() - { - return "PingAction"; //$NON-NLS-1$ - } + public String toString() + { + return "PingAction"; //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/UserEventAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/UserEventAction.java index 92c791f62..ad8c045bb 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/UserEventAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/UserEventAction.java @@ -1,28 +1,25 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.asterisk.wrap.userEvents.UserEvent; abstract public class UserEventAction extends AbstractManagerAction { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(UserEventAction.class); - private String _actionId; + private String _actionId; - public UserEventAction(UserEvent event) - { - // NOOP - } + public UserEventAction(UserEvent event) + { + // NOOP + } - public void setActionId(String actionId) - { - this._actionId = actionId; - } + public void setActionId(String actionId) + { + this._actionId = actionId; + } - public String getActionId() - { - return this._actionId; - } + public String getActionId() + { + return this._actionId; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractChannelStateEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractChannelStateEvent.java index afe1f2b1b..8e192da87 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractChannelStateEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractChannelStateEvent.java @@ -1,35 +1,35 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public abstract class AbstractChannelStateEvent extends ChannelEventHelper { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(AbstractChannelStateEvent.class); + @SuppressWarnings("unused") + private static final Log logger = LogFactory.getLog(AbstractChannelStateEvent.class); - private final ChannelState channelState; - private final String channelStateDesc; + private final ChannelState channelState; + private final String channelStateDesc; - AbstractChannelStateEvent(final org.asteriskjava.manager.event.AbstractChannelStateEvent event) - throws InvalidChannelName - { - super(event); - this.channelState = ChannelState.valueOfDesc(event.getChannelStateDesc()); - this.channelStateDesc = event.getChannelStateDesc(); - } + AbstractChannelStateEvent(final org.asteriskjava.manager.event.AbstractChannelStateEvent event) throws InvalidChannelName + { + super(event); + this.channelState = ChannelState.valueOfDesc(event.getChannelStateDesc()); + this.channelStateDesc = event.getChannelStateDesc(); + } - public ChannelState getChannelState() - { - return this.channelState; - } + public ChannelState getChannelState() + { + return this.channelState; + } - public String getChannelStateDesc() - { - return this.channelStateDesc; - } + public String getChannelStateDesc() + { + return this.channelStateDesc; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractMeetMeEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractMeetMeEvent.java index 47fa9ad86..0984a2ab7 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractMeetMeEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractMeetMeEvent.java @@ -1,33 +1,34 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class AbstractMeetMeEvent extends ChannelEventHelper { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(AbstractMeetMeEvent.class); - - private final String meetMe; - private final Integer userNum; - - public AbstractMeetMeEvent(final org.asteriskjava.manager.event.AbstractMeetMeEvent event) throws InvalidChannelName - { - super(event.getChannel(), event.getUniqueId()); - this.meetMe = event.getMeetMe(); - this.userNum = event.getUser(); - } - - public String getMeetMe() - { - return this.meetMe; - } - - public Integer getUserNum() - { - return this.userNum; - } + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Log logger = LogFactory.getLog(AbstractMeetMeEvent.class); + + private final String meetMe; + private final Integer userNum; + + public AbstractMeetMeEvent(final org.asteriskjava.manager.event.AbstractMeetMeEvent event) throws InvalidChannelName + { + super(event.getChannel(), event.getUniqueId()); + this.meetMe = event.getMeetMe(); + this.userNum = event.getUser(); + } + + public String getMeetMe() + { + return this.meetMe; + } + + public Integer getUserNum() + { + return this.userNum; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractParkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractParkedCallEvent.java index 14442c78c..25902d984 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractParkedCallEvent.java @@ -1,33 +1,33 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class AbstractParkedCallEvent extends ChannelEventHelper { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(AbstractParkedCallEvent.class); + @SuppressWarnings("unused") + private static final Log logger = LogFactory.getLog(AbstractParkedCallEvent.class); - private final String exten; - private final String parkingLot; + private final String exten; + private final String parkingLot; - AbstractParkedCallEvent(final org.asteriskjava.manager.event.AbstractParkedCallEvent event) - throws InvalidChannelName - { - super(event.getParkeeChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); - this.exten = event.getExten(); - this.parkingLot = event.getParkingLot(); - } + AbstractParkedCallEvent(final org.asteriskjava.manager.event.AbstractParkedCallEvent event) throws InvalidChannelName + { + super(event.getParkeeChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + this.exten = event.getExten(); + this.parkingLot = event.getParkingLot(); + } - public String getExten() - { - return this.exten; - } + public String getExten() + { + return this.exten; + } - public String getParkingLot() - { - return this.parkingLot; - } + public String getParkingLot() + { + return this.parkingLot; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentCalledEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentCalledEvent.java index 6c3fb7370..1b03387a6 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentCalledEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentCalledEvent.java @@ -1,35 +1,36 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class AgentCalledEvent extends ChannelEventHelper { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(AgentCalledEvent.class); + @SuppressWarnings("unused") + private static final Log logger = LogFactory.getLog(AgentCalledEvent.class); - private String queue; + private String queue; - private String agentInterface; + private String agentInterface; - public AgentCalledEvent(final org.asteriskjava.manager.event.AgentCalledEvent event) throws InvalidChannelName - { - super(event.getChannelCalling(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + public AgentCalledEvent(final org.asteriskjava.manager.event.AgentCalledEvent event) throws InvalidChannelName + { + super(event.getChannelCalling(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); - agentInterface = event.getAgentCalled(); - queue = event.getQueue(); - } + agentInterface = event.getAgentCalled(); + queue = event.getQueue(); + } - public String getQueueName() - { - return queue; - } + public String getQueueName() + { + return queue; + } - public String getAgentInterface() - { - return agentInterface; - } + public String getAgentInterface() + { + return agentInterface; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentConnectEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentConnectEvent.java index da6362880..50fcf1f99 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentConnectEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentConnectEvent.java @@ -1,35 +1,36 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class AgentConnectEvent extends ChannelEventHelper { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(AgentConnectEvent.class); + @SuppressWarnings("unused") + private static final Log logger = LogFactory.getLog(AgentConnectEvent.class); - private String queue; + private String queue; - private String agentInterface; + private String agentInterface; - public AgentConnectEvent(final org.asteriskjava.manager.event.AgentConnectEvent event) throws InvalidChannelName - { - super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + public AgentConnectEvent(final org.asteriskjava.manager.event.AgentConnectEvent event) throws InvalidChannelName + { + super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); - agentInterface = event.getInterface(); - queue = event.getQueue(); - } + agentInterface = event.getInterface(); + queue = event.getQueue(); + } - public String getQueueName() - { - return queue; - } + public String getQueueName() + { + return queue; + } - public String getAgentInterface() - { - return agentInterface; - } + public String getAgentInterface() + { + return agentInterface; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BridgeEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BridgeEvent.java index ef5124235..7119db605 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BridgeEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BridgeEvent.java @@ -1,17 +1,18 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class BridgeEvent extends ManagerEvent { private static final long serialVersionUID = 1L; @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(BridgeEvent.class); + private static final Log logger = LogFactory.getLog(BridgeEvent.class); enum BridgeState { diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java index a65bf8695..85d9ae047 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; @@ -10,9 +9,6 @@ public abstract class ChannelEventHelper extends ManagerEvent implements Channel { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(ChannelEventHelper.class); - /** * The name of the channel. */ diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConnectEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConnectEvent.java index 2edc4eae5..a33a30204 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConnectEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConnectEvent.java @@ -1,28 +1,23 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; - public class ConnectEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(ConnectEvent.class); + private static final long serialVersionUID = 1L; - /** - * The version of the manager protocol. - */ - private final String protocolIdentifier; + /** + * The version of the manager protocol. + */ + private final String protocolIdentifier; - public ConnectEvent(final org.asteriskjava.manager.event.ConnectEvent event) - { - super(event); - this.protocolIdentifier = event.getProtocolIdentifier(); - } + public ConnectEvent(final org.asteriskjava.manager.event.ConnectEvent event) + { + super(event); + this.protocolIdentifier = event.getProtocolIdentifier(); + } - public String getProtocolIdentifier() - { - return this.protocolIdentifier; - } + public String getProtocolIdentifier() + { + return this.protocolIdentifier; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java index a64417197..dd7aba042 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java @@ -1,39 +1,34 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; - public class DbGetResponseEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(DbGetResponseEvent.class); - - private final String family; - private final String key; - private final String val; - - DbGetResponseEvent(final org.asteriskjava.manager.event.DbGetResponseEvent event) - { - super(event); - this.family = event.getFamily(); - this.key = event.getKey(); - this.val = event.getVal(); - } - - public String getVal() - { - return this.val; - } - - public String getFamily() - { - return this.family; - } - - public String getKey() - { - return this.key; - } + private static final long serialVersionUID = 1L; + + private final String family; + private final String key; + private final String val; + + DbGetResponseEvent(final org.asteriskjava.manager.event.DbGetResponseEvent event) + { + super(event); + this.family = event.getFamily(); + this.key = event.getKey(); + this.val = event.getVal(); + } + + public String getVal() + { + return this.val; + } + + public String getFamily() + { + return this.family; + } + + public String getKey() + { + return this.key; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEvent.java index 72018b01f..e8e1ba6e2 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; @@ -10,9 +9,6 @@ public class DialEvent extends ChannelEventHelper { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(DialEvent.class); - /** * The name of the destination channel. */ diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DisconnectEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DisconnectEvent.java index cdf67b4e0..f69fef8a6 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DisconnectEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DisconnectEvent.java @@ -1,15 +1,11 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; - public class DisconnectEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(DisconnectEvent.class); + private static final long serialVersionUID = 1L; - public DisconnectEvent(final org.asteriskjava.manager.event.DisconnectEvent event) - { - super(event); - } + public DisconnectEvent(final org.asteriskjava.manager.event.DisconnectEvent event) + { + super(event); + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DndStateEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DndStateEvent.java index e8c0df1f7..4e68e61a4 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DndStateEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DndStateEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; @@ -11,9 +10,6 @@ public class DndStateEvent extends ManagerEvent implements ChannelEvent { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(DndStateEvent.class); - /** * The name of the channel. */ diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ExtensionStatusEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ExtensionStatusEvent.java index a9e80c3fc..4c58223a8 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ExtensionStatusEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ExtensionStatusEvent.java @@ -1,95 +1,91 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; - public class ExtensionStatusEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(ExtensionStatusEvent.class); - - enum Status - { - - /** - * No device INUSE or BUSY. - */ - NOT_INUSE(org.asteriskjava.manager.event.ExtensionStatusEvent.NOT_INUSE), - - /** - * One or more devices INUSE. - */ - INUSE(org.asteriskjava.manager.event.ExtensionStatusEvent.INUSE), - - /** - * All devices BUSY. - */ - BUSY(org.asteriskjava.manager.event.ExtensionStatusEvent.BUSY), - - /** - * All devices UNAVAILABLE/UNREGISTERED. - */ - UNAVAILABLE(org.asteriskjava.manager.event.ExtensionStatusEvent.UNAVAILABLE), - - /** - * One or more devices RINGING. - */ - RINGING(org.asteriskjava.manager.event.ExtensionStatusEvent.RINGING); - - int _status; - - Status(int status) - { - this._status = status; - } - - static Status valueOf(Integer status) - { - Status theStatus = null; - for (Status aStatus : Status.values()) - { - if (aStatus._status == status) - { - theStatus = aStatus; - break; - } - } - return theStatus; - } - } - - private final String exten; - private final String context; - private final String hint; - private final Status status; - - public ExtensionStatusEvent(final org.asteriskjava.manager.event.ExtensionStatusEvent event) - { - super(event); - this.exten = event.getExten(); - this.context = event.getContext(); - this.hint = event.getHint(); - this.status = Status.valueOf(event.getStatus()); - } - - public String getExten() - { - return this.exten; - } - - public String getContext() - { - return this.context; - } - - public String getHint() - { - return this.hint; - } - - public Status getStatus() - { - return this.status; - } + private static final long serialVersionUID = 1L; + + enum Status + { + + /** + * No device INUSE or BUSY. + */ + NOT_INUSE(org.asteriskjava.manager.event.ExtensionStatusEvent.NOT_INUSE), + + /** + * One or more devices INUSE. + */ + INUSE(org.asteriskjava.manager.event.ExtensionStatusEvent.INUSE), + + /** + * All devices BUSY. + */ + BUSY(org.asteriskjava.manager.event.ExtensionStatusEvent.BUSY), + + /** + * All devices UNAVAILABLE/UNREGISTERED. + */ + UNAVAILABLE(org.asteriskjava.manager.event.ExtensionStatusEvent.UNAVAILABLE), + + /** + * One or more devices RINGING. + */ + RINGING(org.asteriskjava.manager.event.ExtensionStatusEvent.RINGING); + + int _status; + + Status(int status) + { + this._status = status; + } + + static Status valueOf(Integer status) + { + Status theStatus = null; + for (Status aStatus : Status.values()) + { + if (aStatus._status == status) + { + theStatus = aStatus; + break; + } + } + return theStatus; + } + } + + private final String exten; + private final String context; + private final String hint; + private final Status status; + + public ExtensionStatusEvent(final org.asteriskjava.manager.event.ExtensionStatusEvent event) + { + super(event); + this.exten = event.getExten(); + this.context = event.getContext(); + this.hint = event.getHint(); + this.status = Status.valueOf(event.getStatus()); + } + + public String getExten() + { + return this.exten; + } + + public String getContext() + { + return this.context; + } + + public String getHint() + { + return this.hint; + } + + public Status getStatus() + { + return this.status; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/HangupEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/HangupEvent.java index 7a6369f27..e18aef5c2 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/HangupEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/HangupEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; @@ -8,55 +7,52 @@ public class HangupEvent extends ManagerEvent implements ChannelEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(HangupEvent.class); - - /** - * The name of the channel. - */ - private final Channel channel; - - private final Integer cause; - private final String causeTxt; - private final String uniqueId; - - public HangupEvent(final org.asteriskjava.manager.event.HangupEvent event) throws InvalidChannelName - { - super(event); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - - this.channel = pbx.registerHangupChannel(event.getChannel(), event.getUniqueId()); - this.cause = event.getCause(); - this.causeTxt = event.getCauseTxt(); - this.uniqueId = event.getUniqueId(); - - } - - public Integer getCause() - { - return this.cause; - } - - public String getCauseTxt() - { - return this.causeTxt; - } - - @Override - public Channel getChannel() - { - return this.channel; - } - - public String getUniqueId() - { - return this.uniqueId; - } - - public String toString() - { - return "HangupEvent: channel:" + this.channel + " cause:" + this.causeTxt; //$NON-NLS-1$//$NON-NLS-2$ - } + private static final long serialVersionUID = 1L; + + /** + * The name of the channel. + */ + private final Channel channel; + + private final Integer cause; + private final String causeTxt; + private final String uniqueId; + + public HangupEvent(final org.asteriskjava.manager.event.HangupEvent event) throws InvalidChannelName + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this.channel = pbx.registerHangupChannel(event.getChannel(), event.getUniqueId()); + this.cause = event.getCause(); + this.causeTxt = event.getCauseTxt(); + this.uniqueId = event.getUniqueId(); + + } + + public Integer getCause() + { + return this.cause; + } + + public String getCauseTxt() + { + return this.causeTxt; + } + + @Override + public Channel getChannel() + { + return this.channel; + } + + public String getUniqueId() + { + return this.uniqueId; + } + + public String toString() + { + return "HangupEvent: channel:" + this.channel + " cause:" + this.causeTxt; //$NON-NLS-1$//$NON-NLS-2$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/LinkEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/LinkEvent.java index 349d512a7..5a1b48f7c 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/LinkEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/LinkEvent.java @@ -1,17 +1,14 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.InvalidChannelName; public class LinkEvent extends BridgeEvent { - private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(LinkEvent.class); + private static final long serialVersionUID = 1L; - @SuppressWarnings("deprecation") - public LinkEvent(final org.asteriskjava.manager.event.LinkEvent event) throws InvalidChannelName - { - super(event); - } + @SuppressWarnings("deprecation") + public LinkEvent(final org.asteriskjava.manager.event.LinkEvent event) throws InvalidChannelName + { + super(event); + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ManagerEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ManagerEvent.java index fce61db8c..9427c1514 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ManagerEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ManagerEvent.java @@ -2,18 +2,13 @@ import java.util.EventObject; -import org.apache.log4j.Logger; - public class ManagerEvent extends EventObject { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(ManagerEvent.class); + private static final long serialVersionUID = 1L; - public ManagerEvent(Object source) - { - super(source); - } + public ManagerEvent(Object source) + { + super(source); + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MasqueradeEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MasqueradeEvent.java index 5b830b9ef..4e8a43365 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MasqueradeEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MasqueradeEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; @@ -100,9 +99,6 @@ public class MasqueradeEvent extends ManagerEvent { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(MasqueradeEvent.class); - private final Channel _original; private final Channel _clone; diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeJoinEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeJoinEvent.java index b49728adc..d86b8b43e 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeJoinEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeJoinEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBX; @@ -8,25 +7,22 @@ public class MeetMeJoinEvent extends AbstractMeetMeEvent { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(MeetMeJoinEvent.class); + CallerID callerID; - CallerID callerID; + public MeetMeJoinEvent(final org.asteriskjava.manager.event.MeetMeJoinEvent event) throws InvalidChannelName + { + super(event); + final PBX pbx = PBXFactory.getActivePBX(); - public MeetMeJoinEvent(final org.asteriskjava.manager.event.MeetMeJoinEvent event) throws InvalidChannelName - { - super(event); - final PBX pbx = PBXFactory.getActivePBX(); + pbx.buildCallerID(event.getCallerIdNum(), event.getCallerIdName()); - pbx.buildCallerID(event.getCallerIdNum(), event.getCallerIdName()); + } - } - - public CallerID getCallerID() - { - return this.callerID; - } + public CallerID getCallerID() + { + return this.callerID; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeLeaveEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeLeaveEvent.java index bdcdaf3b7..b83049fcb 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeLeaveEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeLeaveEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBX; @@ -8,32 +7,29 @@ public class MeetMeLeaveEvent extends AbstractMeetMeEvent { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(MeetMeLeaveEvent.class); + private final CallerID callerID; + private final Long duration; - private final CallerID callerID; - private final Long duration; + public MeetMeLeaveEvent(final org.asteriskjava.manager.event.MeetMeLeaveEvent event) throws InvalidChannelName + { + super(event); - public MeetMeLeaveEvent(final org.asteriskjava.manager.event.MeetMeLeaveEvent event) throws InvalidChannelName - { - super(event); + final PBX pbx = PBXFactory.getActivePBX(); - final PBX pbx = PBXFactory.getActivePBX(); + this.callerID = pbx.buildCallerID(event.getCallerIdNum(), event.getCallerIdName()); + this.duration = event.getDuration(); + } - this.callerID = pbx.buildCallerID(event.getCallerIdNum(), event.getCallerIdName()); - this.duration = event.getDuration(); - } + public CallerID getCallerID() + { + return this.callerID; + } - public CallerID getCallerID() - { - return this.callerID; - } - - public Long getDuration() - { - return this.duration; - } + public Long getDuration() + { + return this.duration; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java index 8147b2ee0..02fa2c271 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java @@ -1,45 +1,42 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.InvalidChannelName; public class NewChannelEvent extends AbstractChannelStateEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(NewChannelEvent.class); - - private final String accountCode; - private final String context; - private final String exten; - - public NewChannelEvent(final org.asteriskjava.manager.event.NewChannelEvent event) throws InvalidChannelName - { - super(event); - this.accountCode = event.getAccountCode(); - this.context = event.getContext(); - this.exten = event.getExten(); - } - - public String getAccountCode() - { - return this.accountCode; - } - - public String getContext() - { - return this.context; - } - - public String getExten() - { - return this.exten; - } - - public String toString() - { - return "NewChannelEvent: channel: " + this.getChannel() + " context=" + this.context + " exten=" + this.exten + " state=" + this.getChannelStateDesc(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - } + private static final long serialVersionUID = 1L; + + private final String accountCode; + private final String context; + private final String exten; + + public NewChannelEvent(final org.asteriskjava.manager.event.NewChannelEvent event) throws InvalidChannelName + { + super(event); + this.accountCode = event.getAccountCode(); + this.context = event.getContext(); + this.exten = event.getExten(); + } + + public String getAccountCode() + { + return this.accountCode; + } + + public String getContext() + { + return this.context; + } + + public String getExten() + { + return this.exten; + } + + public String toString() + { + return "NewChannelEvent: channel: " + this.getChannel() + " context=" + this.context + " exten=" + this.exten //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + " state=" + this.getChannelStateDesc(); //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewExtenEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewExtenEvent.java index b8a3b5c0a..34a6594ac 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewExtenEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewExtenEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; @@ -10,9 +9,6 @@ public class NewExtenEvent extends ManagerEvent implements ChannelEvent { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(NewExtenEvent.class); - private final String context; private final String extension; private final String application; diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java index 65e3dab5d..e7138cfbb 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.internal.core.ChannelProxy; @@ -8,8 +7,6 @@ public class NewStateEvent extends AbstractChannelStateEvent { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(NewStateEvent.class); private ChannelProxy destChannel; public NewStateEvent(final org.asteriskjava.manager.event.NewStateEvent event) throws InvalidChannelName diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/OriginateResponseEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/OriginateResponseEvent.java index bc9b8f3e9..5ae4bd8e0 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/OriginateResponseEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/OriginateResponseEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.InvalidChannelName; @@ -12,89 +11,86 @@ public class OriginateResponseEvent extends ResponseEvent implements ChannelEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(OriginateResponseEvent.class); - - // reflects whether we have a iChannel or an iEndPoint. We can't have both. - private final boolean isChannel; - private final Channel channel; - private final EndPoint endPoint; - private final String response; - private final String context; - private final String exten; - private final Integer reason; - - public OriginateResponseEvent(final org.asteriskjava.manager.event.OriginateResponseEvent event) - throws InvalidChannelName - { - super(event); - - PBX pbx = PBXFactory.getActivePBX(); - - // The doco says this should be a channel but under 1.4 it comes up as - // an endpoint. - this.isChannel = pbx.isChannel(event.getChannel()); - if (this.isChannel) - { - this.channel = ChannelEventHelper.registerChannel(event.getChannel(), - (event.getUniqueId() == null ? ChannelImpl.UNKNOWN_UNIQUE_ID : event.getUniqueId()), - event.getCallerIdNum(), event.getCallerIdName()); - this.endPoint = null; - } - else - { - this.endPoint = pbx.buildEndPoint(TechType.SIP, event.getChannel()); - this.channel = null; - } - - this.response = event.getResponse(); - this.context = event.getContext(); - this.exten = event.getExten(); - this.reason = event.getReason(); - - } - - public String getResponse() - { - return this.response; - } - - public String getContext() - { - return this.context; - } - - public String getExten() - { - return this.exten; - } - - public Integer getReason() - { - return this.reason; - } - - public boolean isChannel() - { - return this.isChannel; - } - - @Override - public Channel getChannel() - { - return this.channel; - } - - public EndPoint getEndPoint() - { - return this.endPoint; - } - - public boolean isSuccess() - { - return "Success".equalsIgnoreCase(this.response); //$NON-NLS-1$ - } + private static final long serialVersionUID = 1L; + + // reflects whether we have a iChannel or an iEndPoint. We can't have both. + private final boolean isChannel; + private final Channel channel; + private final EndPoint endPoint; + private final String response; + private final String context; + private final String exten; + private final Integer reason; + + public OriginateResponseEvent(final org.asteriskjava.manager.event.OriginateResponseEvent event) + throws InvalidChannelName + { + super(event); + + PBX pbx = PBXFactory.getActivePBX(); + + // The doco says this should be a channel but under 1.4 it comes up as + // an endpoint. + this.isChannel = pbx.isChannel(event.getChannel()); + if (this.isChannel) + { + this.channel = ChannelEventHelper.registerChannel(event.getChannel(), + (event.getUniqueId() == null ? ChannelImpl.UNKNOWN_UNIQUE_ID : event.getUniqueId()), + event.getCallerIdNum(), event.getCallerIdName()); + this.endPoint = null; + } + else + { + this.endPoint = pbx.buildEndPoint(TechType.SIP, event.getChannel()); + this.channel = null; + } + + this.response = event.getResponse(); + this.context = event.getContext(); + this.exten = event.getExten(); + this.reason = event.getReason(); + + } + + public String getResponse() + { + return this.response; + } + + public String getContext() + { + return this.context; + } + + public String getExten() + { + return this.exten; + } + + public Integer getReason() + { + return this.reason; + } + + public boolean isChannel() + { + return this.isChannel; + } + + @Override + public Channel getChannel() + { + return this.channel; + } + + public EndPoint getEndPoint() + { + return this.endPoint; + } + + public boolean isSuccess() + { + return "Success".equalsIgnoreCase(this.response); //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ParkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ParkedCallEvent.java index 8669fcfba..5426bbd03 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ParkedCallEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; @@ -12,9 +11,6 @@ public class ParkedCallEvent extends ManagerEvent private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(ParkedCallEvent.class); - private final Channel fromChannel; private final Integer timeout; private String exten; diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerEntryEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerEntryEvent.java index 0525dd694..524dfbdd2 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerEntryEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerEntryEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; @@ -8,23 +7,20 @@ public class PeerEntryEvent extends ResponseEvent { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(PeerEntryEvent.class); + private final EndPoint peer; - private final EndPoint peer; + public PeerEntryEvent(final org.asteriskjava.manager.event.PeerEntryEvent event) + { + super(event); - public PeerEntryEvent(final org.asteriskjava.manager.event.PeerEntryEvent event) - { - super(event); + PBX pbx = PBXFactory.getActivePBX(); + this.peer = pbx.buildEndPoint(TechType.valueOf(event.getChannelType()), event.getObjectName()); + } - PBX pbx = PBXFactory.getActivePBX(); - this.peer = pbx.buildEndPoint(TechType.valueOf(event.getChannelType()), event.getObjectName()); - } - - public EndPoint getPeer() - { - return this.peer; - } + public EndPoint getPeer() + { + return this.peer; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerStatusEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerStatusEvent.java index 108f159ca..7fa0dc1e5 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerStatusEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerStatusEvent.java @@ -1,31 +1,27 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class PeerStatusEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(PeerStatusEvent.class); + private final EndPoint peer; - private final EndPoint peer; + public PeerStatusEvent(final org.asteriskjava.manager.event.PeerStatusEvent event) + { + super(event); + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - public PeerStatusEvent(final org.asteriskjava.manager.event.PeerStatusEvent event) - { - super(event); - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + this.peer = pbx.buildEndPoint(event.getPeer());// registerChannel(event.getPeer(), + // Channel.UNKNOWN_UNIQUE_ID); + } - this.peer = pbx.buildEndPoint(event.getPeer());// registerChannel(event.getPeer(), - // Channel.UNKNOWN_UNIQUE_ID); - } - - public EndPoint getPeer() - { - return this.peer; - } + public EndPoint getPeer() + { + return this.peer; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerlistCompleteEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerlistCompleteEvent.java index 4d06148be..3044f9468 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerlistCompleteEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerlistCompleteEvent.java @@ -1,15 +1,11 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; - public class PeerlistCompleteEvent extends ResponseEvent { - private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(PeerlistCompleteEvent.class); + private static final long serialVersionUID = 1L; - public PeerlistCompleteEvent(final org.asteriskjava.manager.event.PeerlistCompleteEvent event) - { - super(event); - } + public PeerlistCompleteEvent(final org.asteriskjava.manager.event.PeerlistCompleteEvent event) + { + super(event); + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/QueueCallerLeaveEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/QueueCallerLeaveEvent.java index 9a3138eef..8c51bf203 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/QueueCallerLeaveEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/QueueCallerLeaveEvent.java @@ -1,15 +1,11 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.InvalidChannelName; public class QueueCallerLeaveEvent extends ChannelEventHelper { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(QueueCallerLeaveEvent.class); - private String queue; public QueueCallerLeaveEvent(final org.asteriskjava.manager.event.QueueCallerLeaveEvent event) throws InvalidChannelName diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java index 925f94472..6a175ee3c 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java @@ -1,17 +1,18 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelProxy; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class RenameEvent extends ManagerEvent implements ChannelEvent { private static final long serialVersionUID = 1L; - private static final Logger logger = Logger.getLogger(RenameEvent.class); + private static final Log logger = LogFactory.getLog(RenameEvent.class); /** * The existing channel which is about to be renamed. diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvent.java index 0bc9464f3..444598af5 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvent.java @@ -1,32 +1,27 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; - public class ResponseEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(ResponseEvent.class); - - private final String actionId; - private final String internalActionId; - - public ResponseEvent(final org.asteriskjava.manager.event.ResponseEvent event) - { - super(event); - this.actionId = event.getActionId(); - this.internalActionId = event.getInternalActionId(); - } - - public String getActionId() - { - return this.actionId; - } - - public String getInternalActionId() - { - return this.internalActionId; - } + private static final long serialVersionUID = 1L; + + private final String actionId; + private final String internalActionId; + + public ResponseEvent(final org.asteriskjava.manager.event.ResponseEvent event) + { + super(event); + this.actionId = event.getActionId(); + this.internalActionId = event.getInternalActionId(); + } + + public String getActionId() + { + return this.actionId; + } + + public String getInternalActionId() + { + return this.internalActionId; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusCompleteEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusCompleteEvent.java index 5d81c3747..cb0d576e3 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusCompleteEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusCompleteEvent.java @@ -1,15 +1,11 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; - public class StatusCompleteEvent extends ResponseEvent { - private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(StatusCompleteEvent.class); + private static final long serialVersionUID = 1L; - public StatusCompleteEvent(final org.asteriskjava.manager.event.StatusCompleteEvent event) - { - super(event); - } + public StatusCompleteEvent(final org.asteriskjava.manager.event.StatusCompleteEvent event) + { + super(event); + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusEvent.java index 3c621b250..597956be9 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusEvent.java @@ -2,7 +2,6 @@ import java.util.Map; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.DialPlanExtension; @@ -14,9 +13,6 @@ public class StatusEvent extends ResponseEvent implements ChannelEvent { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(StatusEvent.class); - private final Channel channel; private final CallerID callerId; private final String accountCode; diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnlinkEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnlinkEvent.java index 7b7efb890..d537291e5 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnlinkEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnlinkEvent.java @@ -1,17 +1,14 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.InvalidChannelName; public class UnlinkEvent extends BridgeEvent { - private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(UnlinkEvent.class); + private static final long serialVersionUID = 1L; - @SuppressWarnings("deprecation") - public UnlinkEvent(final org.asteriskjava.manager.event.UnlinkEvent event) throws InvalidChannelName - { - super(event); - } + @SuppressWarnings("deprecation") + public UnlinkEvent(final org.asteriskjava.manager.event.UnlinkEvent event) throws InvalidChannelName + { + super(event); + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnparkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnparkedCallEvent.java index 2837ca2b0..fdd0bda97 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnparkedCallEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnparkedCallEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; @@ -11,9 +10,6 @@ public class UnparkedCallEvent extends AbstractParkedCallEvent { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(UnparkedCallEvent.class); - private final Channel fromChannel; public UnparkedCallEvent(final org.asteriskjava.manager.event.UnparkedCallEvent event) throws InvalidChannelName diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/VarSetEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/VarSetEvent.java index c743d7dad..d4d586dbd 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/VarSetEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/VarSetEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; @@ -10,9 +9,6 @@ public class VarSetEvent extends ManagerEvent implements ChannelEvent { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(VarSetEvent.class); - /** * The name of the channel. */ diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java index dde7a33fd..825c04fe2 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java @@ -2,24 +2,20 @@ import java.util.List; -import org.apache.log4j.Logger; - public class CommandResponse extends ManagerResponse { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(CommandResponse.class); - private List result; + private List result; - public CommandResponse(org.asteriskjava.manager.response.CommandResponse response) - { - super(response); - this.result = response.getResult(); + public CommandResponse(org.asteriskjava.manager.response.CommandResponse response) + { + super(response); + this.result = response.getResult(); - } + } - public List getResult() - { - return this.result; - } + public List getResult() + { + return this.result; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java index 397b42c63..36cc5a57c 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java @@ -1,16 +1,11 @@ package org.asteriskjava.pbx.asterisk.wrap.response; -import org.apache.log4j.Logger; - public class ManagerError extends ManagerResponse { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(ManagerError.class); - - public ManagerError(org.asteriskjava.manager.response.ManagerError error) - { - super(error); - } + public ManagerError(org.asteriskjava.manager.response.ManagerError error) + { + super(error); + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/userEvents/UserEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/userEvents/UserEvent.java index 2d67875af..24bfc3078 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/userEvents/UserEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/userEvents/UserEvent.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.userEvents; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; @@ -11,9 +10,6 @@ public class UserEvent extends ManagerEvent { private static final long serialVersionUID = 1L; - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(UserEvent.class); - private Channel channel; public UserEvent(org.asteriskjava.manager.event.UserEvent source, Channel channel) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java index 330cd7cdd..a61cc5d0c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java @@ -3,7 +3,6 @@ import java.util.HashSet; import java.util.Set; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.ActivityStatusEnum; @@ -16,10 +15,12 @@ import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public abstract class ActivityHelper implements Runnable, Activity { - static private Logger logger = Logger.getLogger(ActivityHelper.class); + private static final Log logger = LogFactory.getLog(ActivityHelper.class); /** * If the activity fails due to an exception then lastException will contain diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index 350d5ca3b..5a71bf575 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -4,7 +4,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.Call.OperandChannel; @@ -25,6 +24,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * The BlindTransferActivity is used by the AsteriksPBX to transfer a live @@ -34,7 +35,7 @@ */ public class BlindTransferActivityImpl extends ActivityHelper implements BlindTransferActivity { - static Logger logger = Logger.getLogger(BlindTransferActivityImpl.class); + private static final Log logger = LogFactory.getLog(BlindTransferActivityImpl.class); private Call _call; diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java index 6cde4e49d..197bb88b9 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java @@ -6,7 +6,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ListenerPriority; @@ -22,143 +21,143 @@ import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.managerAPI.RedirectToMeetMe; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class BridgeActivityImpl extends ActivityHelper implements BridgeActivity { - static Logger logger = Logger.getLogger(BridgeActivityImpl.class); - private final Channel _lhsChannel; - private final Channel _rhsChannel; - - private CountDownLatch _bridgeLatch; - - public BridgeActivityImpl(final Channel lhsChannel, final Channel rhsChannel, - final ActivityCallback callback) - { - super("Bridge", callback); //$NON-NLS-1$ - - this._lhsChannel = lhsChannel; - this._rhsChannel = rhsChannel; - this.startActivity(true); - } - - @Override - public boolean doActivity() throws PBXException - { - boolean success = false; - - BridgeActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ - BridgeActivityImpl.logger.info("*********** begin Bridge ****************"); //$NON-NLS-1$ - BridgeActivityImpl.logger.info("*********** lhs:" + this._lhsChannel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ - BridgeActivityImpl.logger.info("*********** rhs:" + this._rhsChannel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ - BridgeActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ - try - { - - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - - if (!pbx.moveChannelToAgi(_lhsChannel)) - { - throw new PBXException("Channel: " + _lhsChannel + " couldn't be moved to agi"); - } - if (!pbx.moveChannelToAgi(_rhsChannel)) - { - throw new PBXException("Channel: " + _rhsChannel + " couldn't be moved to agi"); - } - - List channels = new LinkedList<>(); - channels.add(this._lhsChannel); - channels.add(_rhsChannel); - if (!pbx.waitForChannelsToQuiescent(channels, 3000)) - throw new PBXException( - "Channel: " + this._lhsChannel + " cannot be held as it is still in transition."); - try - { - if (pbx.isBridgeSupported()) - { - - this._bridgeLatch = new CountDownLatch(1); - final AgiChannelActivityBridge action = new AgiChannelActivityBridge(_lhsChannel); - _lhsChannel.setCurrentActivityAction(new AgiChannelActivityHoldForBridge(action)); - _rhsChannel.setCurrentActivityAction(action); - - // now wait for the bridge event to arrive. - success = this._bridgeLatch.await(3, TimeUnit.SECONDS); - - } - else if (pbx.isMeetmeInstalled()) - { - // As bridge isn't supported we need to do the bridge using - // a - // meetme - // room - - final RedirectToMeetMe meetmeTransfer = new RedirectToMeetMe(); - // meetme room is empty - // find a new available room. - MeetmeRoom room = pbx.acquireMeetmeRoom(); - - // redirect the lhs to meetme - meetmeTransfer.redirectToMeetme(_lhsChannel, room.getRoomNumber(), true); - - // redirect destination this is not the marked call - // as we want this to be hung up if no other calls are left - // in - // this - // room - final boolean markedCall = !_rhsChannel.canDetectHangup(); - meetmeTransfer.redirectToMeetme(_rhsChannel, room.getRoomNumber(), markedCall); - - // TODO put some logic to check that the meetme actually - // completes. - success = true; - - } - else - throw new PBXException( - "Cannot bridge two calls as neither the BridgeAction nor Meetme is available"); //$NON-NLS-1$ - } - catch (IllegalArgumentException | IllegalStateException | InterruptedException e) - { - throw new PBXException(e); - } - - } - catch (IllegalArgumentException | IllegalStateException e) - { - BridgeActivityImpl.logger.error(e, e); - BridgeActivityImpl.logger.error(e, e); - throw new PBXException(e); - } - return success; - } - - @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); - required.add(StatusCompleteEvent.class); - required.add(StatusEvent.class); - required.add(BridgeEvent.class); - return required; - } - - @Override - public ListenerPriority getPriority() - { - return ListenerPriority.NORMAL; - } - - @Override - public void onManagerEvent(ManagerEvent event) - { - - if (event instanceof BridgeEvent) - { - BridgeEvent bridge = (BridgeEvent) event; - if (bridge.isLink() - && (bridge.getChannel1().isSame(this._lhsChannel) || bridge.getChannel1().isSame(this._rhsChannel)) - && (bridge.getChannel2().isSame(this._lhsChannel) || bridge.getChannel2().isSame(this._rhsChannel))) - this._bridgeLatch.countDown(); - } - } + private static final Log logger = LogFactory.getLog(BridgeActivityImpl.class); + private final Channel _lhsChannel; + private final Channel _rhsChannel; + + private CountDownLatch _bridgeLatch; + + public BridgeActivityImpl(final Channel lhsChannel, final Channel rhsChannel, + final ActivityCallback callback) + { + super("Bridge", callback); //$NON-NLS-1$ + + this._lhsChannel = lhsChannel; + this._rhsChannel = rhsChannel; + this.startActivity(true); + } + + @Override + public boolean doActivity() throws PBXException + { + boolean success = false; + + BridgeActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + BridgeActivityImpl.logger.info("*********** begin Bridge ****************"); //$NON-NLS-1$ + BridgeActivityImpl.logger.info("*********** lhs:" + this._lhsChannel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + BridgeActivityImpl.logger.info("*********** rhs:" + this._rhsChannel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + BridgeActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + try + { + + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + if (!pbx.moveChannelToAgi(_lhsChannel)) + { + throw new PBXException("Channel: " + _lhsChannel + " couldn't be moved to agi"); + } + if (!pbx.moveChannelToAgi(_rhsChannel)) + { + throw new PBXException("Channel: " + _rhsChannel + " couldn't be moved to agi"); + } + + List channels = new LinkedList<>(); + channels.add(this._lhsChannel); + channels.add(_rhsChannel); + if (!pbx.waitForChannelsToQuiescent(channels, 3000)) + throw new PBXException("Channel: " + this._lhsChannel + " cannot be held as it is still in transition."); + try + { + if (pbx.isBridgeSupported()) + { + + this._bridgeLatch = new CountDownLatch(1); + final AgiChannelActivityBridge action = new AgiChannelActivityBridge(_lhsChannel); + _lhsChannel.setCurrentActivityAction(new AgiChannelActivityHoldForBridge(action)); + _rhsChannel.setCurrentActivityAction(action); + + // now wait for the bridge event to arrive. + success = this._bridgeLatch.await(3, TimeUnit.SECONDS); + + } + else if (pbx.isMeetmeInstalled()) + { + // As bridge isn't supported we need to do the bridge using + // a + // meetme + // room + + final RedirectToMeetMe meetmeTransfer = new RedirectToMeetMe(); + // meetme room is empty + // find a new available room. + MeetmeRoom room = pbx.acquireMeetmeRoom(); + + // redirect the lhs to meetme + meetmeTransfer.redirectToMeetme(_lhsChannel, room.getRoomNumber(), true); + + // redirect destination this is not the marked call + // as we want this to be hung up if no other calls are left + // in + // this + // room + final boolean markedCall = !_rhsChannel.canDetectHangup(); + meetmeTransfer.redirectToMeetme(_rhsChannel, room.getRoomNumber(), markedCall); + + // TODO put some logic to check that the meetme actually + // completes. + success = true; + + } + else + throw new PBXException("Cannot bridge two calls as neither the BridgeAction nor Meetme is available"); //$NON-NLS-1$ + } + catch (IllegalArgumentException | IllegalStateException | InterruptedException e) + { + throw new PBXException(e); + } + + } + catch (IllegalArgumentException | IllegalStateException e) + { + BridgeActivityImpl.logger.error(e, e); + BridgeActivityImpl.logger.error(e, e); + throw new PBXException(e); + } + return success; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + required.add(StatusCompleteEvent.class); + required.add(StatusEvent.class); + required.add(BridgeEvent.class); + return required; + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + + if (event instanceof BridgeEvent) + { + BridgeEvent bridge = (BridgeEvent) event; + if (bridge.isLink() + && (bridge.getChannel1().isSame(this._lhsChannel) || bridge.getChannel1().isSame(this._rhsChannel)) + && (bridge.getChannel2().isSame(this._lhsChannel) || bridge.getChannel2().isSame(this._rhsChannel))) + this._bridgeLatch.countDown(); + } + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java index ef1e46a51..93055aab4 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java @@ -3,7 +3,6 @@ import java.util.HashSet; import java.util.Map; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Call; @@ -24,10 +23,12 @@ import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.managerAPI.Dial; import org.asteriskjava.pbx.internal.managerAPI.OriginateResult; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class DialActivityImpl extends ActivityHelper implements DialActivity, NewChannelListener { - static Logger logger = Logger.getLogger(DialActivityImpl.class); + private static final Log logger = LogFactory.getLog(DialActivityImpl.class); private final boolean hideToCallerId; diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index 48ee786f9..15831cd66 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -3,7 +3,6 @@ import java.util.HashSet; import java.util.Map; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.CallerID; @@ -21,10 +20,12 @@ import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.managerAPI.DialToAgi; import org.asteriskjava.pbx.internal.managerAPI.OriginateResult; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class DialToAgiActivityImpl extends ActivityHelper implements DialToAgiActivity, NewChannelListener { - static Logger logger = Logger.getLogger(DialToAgiActivityImpl.class); + private static final Log logger = LogFactory.getLog(DialToAgiActivityImpl.class); private final boolean hideToCallerId; diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java index f56554bae..983ab098d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java @@ -2,7 +2,6 @@ import java.util.HashSet; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ListenerPriority; @@ -12,76 +11,78 @@ import org.asteriskjava.pbx.agi.AgiChannelActivityHold; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class HoldActivityImpl extends ActivityHelper implements HoldActivity { - static Logger logger = Logger.getLogger(HoldActivityImpl.class); - private final Channel _channel; - - public HoldActivityImpl(final Channel channel, final ActivityCallback callback) - { - super("HoldCall", callback); //$NON-NLS-1$ - - this._channel = channel; - this.startActivity(false); - } - - @Override - public boolean doActivity() throws PBXException - { - boolean success = false; - - HoldActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ - HoldActivityImpl.logger.info("*********** begin Hold Audio ****************"); //$NON-NLS-1$ - HoldActivityImpl.logger.info("*********** " + this._channel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ - HoldActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ - try - { - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - - if (!pbx.moveChannelToAgi(_channel)) - { - throw new PBXException("Channel: " + _channel + " couldn't be moved to agi"); - } - - _channel.setCurrentActivityAction(new AgiChannelActivityHold()); - success = true; - - } - catch (IllegalArgumentException | IllegalStateException e) - { - HoldActivityImpl.logger.error(e, e); - HoldActivityImpl.logger.error(e, e); - throw new PBXException(e); - } - return success; - } - - public Channel getChannel() - { - return this._channel; - } - - @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); - // no events requried. - - return required; - } - - @Override - public ListenerPriority getPriority() - { - return ListenerPriority.NORMAL; - } - - @Override - public void onManagerEvent(ManagerEvent event) - { - // NOOP - - } + private static final Log logger = LogFactory.getLog(HoldActivityImpl.class); + private final Channel _channel; + + public HoldActivityImpl(final Channel channel, final ActivityCallback callback) + { + super("HoldCall", callback); //$NON-NLS-1$ + + this._channel = channel; + this.startActivity(false); + } + + @Override + public boolean doActivity() throws PBXException + { + boolean success = false; + + HoldActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + HoldActivityImpl.logger.info("*********** begin Hold Audio ****************"); //$NON-NLS-1$ + HoldActivityImpl.logger.info("*********** " + this._channel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + HoldActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + try + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + if (!pbx.moveChannelToAgi(_channel)) + { + throw new PBXException("Channel: " + _channel + " couldn't be moved to agi"); + } + + _channel.setCurrentActivityAction(new AgiChannelActivityHold()); + success = true; + + } + catch (IllegalArgumentException | IllegalStateException e) + { + HoldActivityImpl.logger.error(e, e); + HoldActivityImpl.logger.error(e, e); + throw new PBXException(e); + } + return success; + } + + public Channel getChannel() + { + return this._channel; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + // no events requried. + + return required; + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + // NOOP + + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java index bd3d8e30d..7f6c5922e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java @@ -4,19 +4,20 @@ import java.util.LinkedList; import java.util.List; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.Call.OperandChannel; import org.asteriskjava.pbx.CallDirection; import org.asteriskjava.pbx.CallImpl; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.Call.OperandChannel; import org.asteriskjava.pbx.activities.JoinActivity; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * The JoinActivity is used by the AsteriksPBX implementation to Join two @@ -30,7 +31,7 @@ public class JoinActivityImpl extends ActivityHelper implements JoinActivity { - static Logger logger = Logger.getLogger(JoinActivityImpl.class); + private static final Log logger = LogFactory.getLog(JoinActivityImpl.class); private final Call _lhsCall; private final OperandChannel _originatingOperand; @@ -90,7 +91,6 @@ public JoinActivityImpl(final Call lhsCall, OperandChannel originatingOperand, f throw new IllegalArgumentException("rhsOperand may not be null"); //$NON-NLS-1$ } - this.startActivity(true); } @@ -110,7 +110,7 @@ public boolean doActivity() throws PBXException { final Channel rhsChannel = this._rhsCall.getOperandChannel(this._acceptingOperand); final Channel lhsChannel = this._lhsCall.getOperandChannel(this._originatingOperand); - + if (!pbx.moveChannelToAgi(rhsChannel)) { throw new PBXException("Channel: " + rhsChannel + " couldn't be moved to agi"); @@ -126,18 +126,16 @@ public boolean doActivity() throws PBXException if (!pbx.waitForChannelsToQuiescent(channels, 3000)) { logger.error(callSite, callSite); - throw new PBXException("Channel: " + rhsChannel - + " cannot be joined as it is still in transition."); + throw new PBXException("Channel: " + rhsChannel + " cannot be joined as it is still in transition."); } // Now do the actual join on the pbx. - pbx.bridge(lhsChannel, - rhsChannel); + pbx.bridge(lhsChannel, rhsChannel); this._joined = ((CallImpl) this._lhsCall).join(this._originatingOperand, this._rhsCall, this._acceptingOperand, this._direction); success = true; } - catch (RuntimeException e) + catch (RuntimeException e) { logger.error(e, e); logger.error(callSite, callSite); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java index e1eea5412..3633b426b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java @@ -5,7 +5,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.apache.log4j.Logger; import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.AsteriskSettings; @@ -23,6 +22,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ParkedCallEvent; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * The ParkActivity is used by the AsteriksPBX implementation to park a channel. @@ -36,7 +37,7 @@ */ public class ParkActivityImpl extends ActivityHelper implements ParkActivity { - static Logger logger = Logger.getLogger(ParkActivityImpl.class); + private static final Log logger = LogFactory.getLog(ParkActivityImpl.class); /** * call - the call which is being packed. diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index 876d223db..dc2770409 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -4,7 +4,6 @@ import java.util.LinkedList; import java.util.List; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Call; @@ -20,6 +19,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelProxy; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * The SplitActivity is used by the AsteriksPBX to split a call and place the @@ -31,7 +32,7 @@ */ public class SplitActivityImpl extends ActivityHelper implements SplitActivity { - static Logger logger = Logger.getLogger(SplitActivityImpl.class); + private static final Log logger = LogFactory.getLog(SplitActivityImpl.class); private Call _callToSplit; @@ -45,9 +46,8 @@ public class SplitActivityImpl extends ActivityHelper implements /** * Splits a call by moving each of its two channels into the Activity agi. - * The channels will sit in the agi (with no audio) until something is done with them. - * As such you should leave them split for too long. - * + * The channels will sit in the agi (with no audio) until something is done + * with them. As such you should leave them split for too long. * * @param callToSplit The call to split * @param listener diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java index 8bb4ab35e..eac9d1df2 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java @@ -1,125 +1,115 @@ package org.asteriskjava.pbx.internal.asterisk; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.PBXFactory; public class CallerIDImpl implements CallerID { - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(CallerIDImpl.class); - private final String number; - private final String name; - private boolean hideCallerID = false; + private final String number; + private final String name; + private boolean hideCallerID = false; - /** - * Creates a caller ID. - * - * @param number - * - if null then we store an empty string. - * @param name - * - if null then we store an empty string. - */ - public CallerIDImpl(final String number, final String name) - { - this.number = (number == null ? "" : number.trim()); //$NON-NLS-1$ - this.name = (name == null ? "" : name.trim()); //$NON-NLS-1$ - } + /** + * Creates a caller ID. + * + * @param number - if null then we store an empty string. + * @param name - if null then we store an empty string. + */ + public CallerIDImpl(final String number, final String name) + { + this.number = (number == null ? "" : number.trim()); //$NON-NLS-1$ + this.name = (name == null ? "" : name.trim()); //$NON-NLS-1$ + } - @Override - public String getNumber() - { - return this.number; - } + @Override + public String getNumber() + { + return this.number; + } - @Override - public String getName() - { - return this.name; - } + @Override + public String getName() + { + return this.name; + } - /** - * This is a little helper class which will buid the name component of a - * clid from the first and lastnames. - * - * If both firstname and lastname are null then the name component will be - * an empty string. - * - * @param firstname - * the person's firstname, may be null. - * @param lastname - * the person's lastname, may be null - * @param number - * the phone number. - * @return - */ - public static CallerID buildFromComponents(final String firstname, final String lastname, final String number) - { - String name = ""; //$NON-NLS-1$ - if (firstname != null) - { - name += firstname.trim(); - } + /** + * This is a little helper class which will buid the name component of a + * clid from the first and lastnames. If both firstname and lastname are + * null then the name component will be an empty string. + * + * @param firstname the person's firstname, may be null. + * @param lastname the person's lastname, may be null + * @param number the phone number. + * @return + */ + public static CallerID buildFromComponents(final String firstname, final String lastname, final String number) + { + String name = ""; //$NON-NLS-1$ + if (firstname != null) + { + name += firstname.trim(); + } - if (lastname != null) - { - if (name.length() > 0) - { - name += " "; //$NON-NLS-1$ - } - name += lastname.trim(); - } + if (lastname != null) + { + if (name.length() > 0) + { + name += " "; //$NON-NLS-1$ + } + name += lastname.trim(); + } - return PBXFactory.getActivePBX().buildCallerID(number, name); - } + return PBXFactory.getActivePBX().buildCallerID(number, name); + } - /** - * Formats and returns the caller ID in an asterisk specific format suitable - * for passing to the likes of the originate action. The format is: name - * - * - * @return a formatted clid. - */ - public String formatted() - { - String callerID = ""; //$NON-NLS-1$ - if (this.name != null) - { - callerID += this.name; - } - if (this.number != null) - { - if (callerID.length() > 1) - { - callerID += " "; //$NON-NLS-1$ - } - callerID += "<" + this.number + ">"; //$NON-NLS-1$ //$NON-NLS-2$ - } - return callerID; - } + /** + * Formats and returns the caller ID in an asterisk specific format suitable + * for passing to the likes of the originate action. The format is: name + * + * + * @return a formatted clid. + */ + public String formatted() + { + String callerID = ""; //$NON-NLS-1$ + if (this.name != null) + { + callerID += this.name; + } + if (this.number != null) + { + if (callerID.length() > 1) + { + callerID += " "; //$NON-NLS-1$ + } + callerID += "<" + this.number + ">"; //$NON-NLS-1$ //$NON-NLS-2$ + } + return callerID; + } - @Override - public void setHideCallerID(final boolean hide) - { - this.hideCallerID = hide; + @Override + public void setHideCallerID(final boolean hide) + { + this.hideCallerID = hide; - } + } - @Override - public boolean isHideCallerID() - { - return this.hideCallerID; - } + @Override + public boolean isHideCallerID() + { + return this.hideCallerID; + } - @Override - public String toString() - { - return this.formatted(); - } + @Override + public String toString() + { + return this.formatted(); + } - @Override - public boolean isUnknown() - { - return (this.number.length() == 0) || (this.number.compareToIgnoreCase("unknown") == 0); //$NON-NLS-1$ - } + @Override + public boolean isUnknown() + { + return (this.number.length() == 0) || (this.number.compareToIgnoreCase("unknown") == 0); //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java index 7a7eaa377..86fb24264 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java @@ -3,8 +3,9 @@ import java.util.Date; import java.util.LinkedList; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /* * This class tracks the status, channel names and number of participants in @@ -20,7 +21,7 @@ public class MeetmeRoom */ private final int roomNumber; - static Logger logger = Logger.getLogger(MeetmeRoom.class); + private static final Log logger = LogFactory.getLog(MeetmeRoom.class); LinkedList channels = new LinkedList<>(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index 37791328b..bc743d960 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -7,7 +7,6 @@ import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicReference; -import org.apache.log4j.Logger; import org.asteriskjava.AsteriskVersion; import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.pbx.AsteriskSettings; @@ -29,6 +28,8 @@ import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.CoherentManagerEventListener; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class MeetmeRoomControl extends EventListenerBaseClass implements CoherentManagerEventListener { @@ -39,7 +40,7 @@ public class MeetmeRoomControl extends EventListenerBaseClass implements Coheren * default.Also manages the available room list. */ - static Logger logger = Logger.getLogger(MeetmeRoomControl.class); + private static final Log logger = LogFactory.getLog(MeetmeRoomControl.class); private Integer meetmeBaseAddress; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java index 325267218..b593079bd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java @@ -4,207 +4,204 @@ import java.util.LinkedList; import java.util.List; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ChannelHangupListener; import org.asteriskjava.pbx.asterisk.wrap.events.ChannelState; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * This is a fairly simple class which is used by a Peer to track what calls are - * live for the given Peer. - * - * It should be noted that the Peer must keep track of all calls regardless of - * whether they are associated with NJR. The reason for this is that a Peer - * needs to track the status of the associated endpoint so that it can show if a - * handset is on a call. In this way the operator can tell if a person is busy - * even before they call them. - * - * Essentially all this calls does is track the set of channels associated with - * a call. + * live for the given Peer. It should be noted that the Peer must keep track of + * all calls regardless of whether they are associated with NJR. The reason for + * this is that a Peer needs to track the status of the associated endpoint so + * that it can show if a handset is on a call. In this way the operator can tell + * if a person is busy even before they call them. Essentially all this calls + * does is track the set of channels associated with a call. * * @author bsutton - * */ public class CallTracker implements ChannelHangupListener { - private static final Logger logger = Logger.getLogger(CallTracker.class); - - /** - * The list of channels associated with this call. - */ - ArrayList _associatedChannels = new ArrayList<>(); - - /** - * The state of this call. - */ - PeerState _state; - - private CallEndedListener listener; - - CallTracker(Peer peer, Channel initialChannel) - { - this._associatedChannels.add(initialChannel); - initialChannel.addHangupListener(this); - this.listener = peer; - - } - - /** - * Used to merge two calls into a single call. This is required as during a - * masquerade a new channel is created an initially we will create a - * CallTracker for it. When the masquerade event finally turns up we will - * realise it belongs to an existing CallTracker and as such we need to - * merge the two CallTrackers. - * - * @param rhs - */ - void mergeCalls(CallTracker rhs) - { - synchronized (this._associatedChannels) - { - for (Channel channel : rhs._associatedChannels) - this._associatedChannels.add(channel); - // not certain this is necessary but lets just tidy up a bit. - rhs._associatedChannels.clear(); - } - } - - public PeerState getState() - { - return this._state; - } - - /** - * @param s - */ - public void setState(final ChannelState channelState) - { - this._state = PeerState.valueByChannelState(channelState); - } - - public int findChannel(Channel newChannel) - { - int index = -1; - synchronized (this._associatedChannels) - { - - for (int i = 0; i < this._associatedChannels.size(); i++) - { - Channel channel = this._associatedChannels.get(i); - if (channel.isSame(newChannel)) - { - index = i; - break; - } - } - } - - return index; - } - - /** - * Remove a channel from the call. - * - * @param channel - */ - public void remove(Channel channel) - { - synchronized (this._associatedChannels) - { - int index = findChannel(channel); - if (index != -1) - { - if (logger.isDebugEnabled()) - logger.debug("CallTracker removing channel: " + this.toString() + " " + channel.getExtendedChannelName()); //$NON-NLS-1$ //$NON-NLS-2$ - - this._associatedChannels.remove(index); - } - } - - } - - public void startSweep() - { - synchronized (this._associatedChannels) - { - for (final Channel channel : this._associatedChannels) - { - ((ChannelProxy) channel).getRealChannel().startSweep(); - } - } - } - - public void endSweep() - { - final List toremove = new LinkedList<>(); - synchronized (this._associatedChannels) - { - for (final Channel channel : this._associatedChannels) - { - if (!((ChannelProxy) channel).getRealChannel().wasMarkedDuringSweep()) - { - toremove.add(channel); - logger.warn("removing channel " + this.hashCode() + " " + channel.getChannelName());//$NON-NLS-1$ //$NON-NLS-2$ - } - } - - this._associatedChannels.removeAll(toremove); - } - - // Now tell each of the channels it has been hungup - for (final Channel channel : toremove) - { - ((ChannelProxy) channel).getRealChannel().notifyHangupListeners(-1, - "Lingering channel probably due to missed hangup event"); - } - - } - - void dumpChannelList() - { - if (logger.isDebugEnabled()) - { - logger.debug("CallTracker: dump channellist:" + this); //$NON-NLS-1$ - synchronized (this._associatedChannels) - { - for (final Channel channel : this._associatedChannels) - { - logger.debug("--> " + channel.toString()); //$NON-NLS-1$ - } - } - } - } - - public boolean hasEnded() - { - synchronized (this._associatedChannels) - { - return this._associatedChannels.size() == 0; - } - } - - @Override - public void channelHangup(Channel channel, Integer cause, String causeText) - { - remove(channel); - synchronized (this._associatedChannels) - { - if (this._associatedChannels.size() == 0) - { - this._state = PeerState.NOTSET; - notifyCallEndedListener(); - } - } - } - - private void notifyCallEndedListener() - { - this.listener.callEnded(this); - } - - public String toString() - { - return this.listener + " : " + this._state; //$NON-NLS-1$ - } + private static final Log logger = LogFactory.getLog(CallTracker.class); + + /** + * The list of channels associated with this call. + */ + ArrayList _associatedChannels = new ArrayList<>(); + + /** + * The state of this call. + */ + PeerState _state; + + private CallEndedListener listener; + + CallTracker(Peer peer, Channel initialChannel) + { + this._associatedChannels.add(initialChannel); + initialChannel.addHangupListener(this); + this.listener = peer; + + } + + /** + * Used to merge two calls into a single call. This is required as during a + * masquerade a new channel is created an initially we will create a + * CallTracker for it. When the masquerade event finally turns up we will + * realise it belongs to an existing CallTracker and as such we need to + * merge the two CallTrackers. + * + * @param rhs + */ + void mergeCalls(CallTracker rhs) + { + synchronized (this._associatedChannels) + { + for (Channel channel : rhs._associatedChannels) + this._associatedChannels.add(channel); + // not certain this is necessary but lets just tidy up a bit. + rhs._associatedChannels.clear(); + } + } + + public PeerState getState() + { + return this._state; + } + + /** + * @param s + */ + public void setState(final ChannelState channelState) + { + this._state = PeerState.valueByChannelState(channelState); + } + + public int findChannel(Channel newChannel) + { + int index = -1; + synchronized (this._associatedChannels) + { + + for (int i = 0; i < this._associatedChannels.size(); i++) + { + Channel channel = this._associatedChannels.get(i); + if (channel.isSame(newChannel)) + { + index = i; + break; + } + } + } + + return index; + } + + /** + * Remove a channel from the call. + * + * @param channel + */ + public void remove(Channel channel) + { + synchronized (this._associatedChannels) + { + int index = findChannel(channel); + if (index != -1) + { + if (logger.isDebugEnabled()) + logger.debug( + "CallTracker removing channel: " + this.toString() + " " + channel.getExtendedChannelName()); //$NON-NLS-1$ //$NON-NLS-2$ + + this._associatedChannels.remove(index); + } + } + + } + + public void startSweep() + { + synchronized (this._associatedChannels) + { + for (final Channel channel : this._associatedChannels) + { + ((ChannelProxy) channel).getRealChannel().startSweep(); + } + } + } + + public void endSweep() + { + final List toremove = new LinkedList<>(); + synchronized (this._associatedChannels) + { + for (final Channel channel : this._associatedChannels) + { + if (!((ChannelProxy) channel).getRealChannel().wasMarkedDuringSweep()) + { + toremove.add(channel); + logger.warn("removing channel " + this.hashCode() + " " + channel.getChannelName());//$NON-NLS-1$ //$NON-NLS-2$ + } + } + + this._associatedChannels.removeAll(toremove); + } + + // Now tell each of the channels it has been hungup + for (final Channel channel : toremove) + { + ((ChannelProxy) channel).getRealChannel().notifyHangupListeners(-1, + "Lingering channel probably due to missed hangup event"); + } + + } + + void dumpChannelList() + { + if (logger.isDebugEnabled()) + { + logger.debug("CallTracker: dump channellist:" + this); //$NON-NLS-1$ + synchronized (this._associatedChannels) + { + for (final Channel channel : this._associatedChannels) + { + logger.debug("--> " + channel.toString()); //$NON-NLS-1$ + } + } + } + } + + public boolean hasEnded() + { + synchronized (this._associatedChannels) + { + return this._associatedChannels.size() == 0; + } + } + + @Override + public void channelHangup(Channel channel, Integer cause, String causeText) + { + remove(channel); + synchronized (this._associatedChannels) + { + if (this._associatedChannels.size() == 0) + { + this._state = PeerState.NOTSET; + notifyCallEndedListener(); + } + } + } + + private void notifyCallEndedListener() + { + this.listener.callEnded(this); + } + + public String toString() + { + return this.listener + " : " + this._state; //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index f63e94bea..c391cabe9 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -3,7 +3,6 @@ import java.util.Date; import java.util.concurrent.TimeUnit; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.CallerID; @@ -15,6 +14,8 @@ import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.TechType; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * TODO set the channel unique id when registering against an existing channel @@ -43,7 +44,7 @@ public class ChannelImpl implements Channel public static final String UNKNOWN_UNIQUE_ID = "-1"; //$NON-NLS-1$ - private static Logger logger = Logger.getLogger(ChannelImpl.class); + private static final Log logger = LogFactory.getLog(ChannelImpl.class); private static int logCounter = 100; /** diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index 22ae2caf0..9a0be3a8e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -7,7 +7,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; @@ -15,6 +14,8 @@ import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.agi.AgiChannelActivityHold; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * The ChannelProxy exists to deal with the fact that Asterisk will often @@ -29,7 +30,7 @@ public class ChannelProxy implements Channel, ChannelHangupListener { - private static final Logger logger = Logger.getLogger(ChannelProxy.class); + private static final Log logger = LogFactory.getLog(ChannelProxy.class); /** * We give each proxy a unique identity to help track them when debugging. diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java index ef9c94bbd..808ffa801 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java @@ -4,7 +4,6 @@ import java.lang.reflect.InvocationTargetException; import java.util.Hashtable; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.asterisk.wrap.actions.ManagerAction; import org.asteriskjava.pbx.asterisk.wrap.events.AgentCalledEvent; import org.asteriskjava.pbx.asterisk.wrap.events.AgentConnectEvent; @@ -40,6 +39,8 @@ import org.asteriskjava.pbx.asterisk.wrap.response.CommandResponse; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerError; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * This class maps asterisk-java events to our internal events that use iChannel @@ -50,7 +51,7 @@ @SuppressWarnings("deprecation") public class CoherentEventFactory { - private static final Logger logger = Logger.getLogger(CoherentEventFactory.class); + private static final Log logger = LogFactory.getLog(CoherentEventFactory.class); // Events static Hashtable, Class< ? extends ManagerEvent>> mapEvents = new Hashtable<>(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java index bacc6d4b5..52ee84daf 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -10,7 +10,6 @@ import javax.naming.OperationNotSupportedException; -import org.apache.log4j.Logger; import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.AuthenticationFailedException; import org.asteriskjava.manager.EventTimeoutException; @@ -34,6 +33,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvents; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.managerAPI.Connector; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * This is a wrapper class for the asterisk manager.
@@ -53,8 +54,8 @@ * This means that we are always responsive to asterisk when receiving events, * if we are not responsive then asterisk will drop the connection.
*
- * It should be noted that as all events are dispatch from a single thread and as such - * a single tardy listener can block all other listeners.
+ * It should be noted that as all events are dispatch from a single thread and + * as such a single tardy listener can block all other listeners.
*
* If your listener is likely to be slow in handling events then you should wrap * the listener in its own ManagerEventQueue.
@@ -71,7 +72,7 @@ class CoherentManagerConnection implements FilteredManagerListener { - static private Logger logger = Logger.getLogger(CoherentManagerConnection.class); + static private Log logger = LogFactory.getLog(CoherentManagerConnection.class); static Map eventStatistics = new HashMap<>(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index b2507a650..fa8d06741 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -8,315 +8,308 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.apache.log4j.Logger; import org.asteriskjava.manager.ManagerEventListener; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.eventQueue.EventLifeMonitor; import org.asteriskjava.pbx.util.LogTime; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * This class provides a method of accepting, queueing and delivering manager - * events. - * - * Asterisk is very sensitive to delays in receiving events. This class ensures - * that events are received and queued rapidly. A separate thread dequeues them - * and delivers them to the manager listener. - * - * Used this queue as follows: - * - * manager.addEventListener(new CoherentManagerEventQueue(originalListener)); - * - * This affectively daisy changes the originalListener via our queue. + * events. Asterisk is very sensitive to delays in receiving events. This class + * ensures that events are received and queued rapidly. A separate thread + * dequeues them and delivers them to the manager listener. Used this queue as + * follows: manager.addEventListener(new + * CoherentManagerEventQueue(originalListener)); This affectively daisy changes + * the originalListener via our queue. * * @author bsutton - * */ class CoherentManagerEventQueue implements ManagerEventListener, Runnable { - static Logger logger = Logger.getLogger(CoherentManagerEventQueue.class); - - private class Listener - { - FilteredManagerListener _listener; - Set> requiredEvents; - - public Listener(FilteredManagerListener listener) - { - this._listener = listener; - this.requiredEvents = listener.requiredEvents(); - } - - @Override - public String toString() - { - return this._listener.getName(); - } - - } - - private final TreeSet listeners = new TreeSet<>(new ListenerPriorityComparator()); - - private boolean _stop = false; - private final Thread _th; - private final BlockingQueue> _eventQueue = new LinkedBlockingQueue<>(); - - private int _queueMaxSize; - - private long _queueSum; - - private long _queueCount; - - private HashSet> globalEvents = new HashSet<>(); - - public CoherentManagerEventQueue(String name) - { - CoherentManagerConnection.managerConnection.addEventListener(this); - - this._th = new Thread(this); - this._th.setName("EventQueue: " + name);//$NON-NLS-1$ - this._th.setDaemon(true); - this._th.start(); - } - - /** - * handles manager events passed to us in our role as a listener. - * - * We queue the event so that it can be read, by the run method of this - * class, and subsequently passed on to the original listener. - */ - @Override - public void onManagerEvent(final org.asteriskjava.manager.event.ManagerEvent event) - { - - // logger.error(event); - boolean wanted = false; - /** - * Dump any events we arn't interested in ASAP to minimise the - * processing overhead of these events. - */ - // Only enqueue the events that are of interest to one of our listeners. - synchronized (this.globalEvents) - { - Class shadowEvent = CoherentEventFactory.getShadowEvent(event); - if (this.globalEvents.contains(shadowEvent)) - { - wanted = true; - } - } - - if (wanted) - { - - // We don't support all events. - this._eventQueue.add(new EventLifeMonitor<>(event)); - final int queueSize = this._eventQueue.size(); - if (this._queueMaxSize < queueSize) - { - this._queueMaxSize = queueSize; - } - this._queueSum += queueSize; - this._queueCount++; - - if (CoherentManagerEventQueue.logger.isDebugEnabled()) - { - if (this._eventQueue.size() > ((this._queueMaxSize + (this._queueSum / this._queueCount)) / 2)) - { - CoherentManagerEventQueue.logger.debug("queue gtr max avg: size=" + queueSize + " max:" //$NON-NLS-1$ //$NON-NLS-2$ - + this._queueMaxSize + " avg:" + (this._queueSum / this._queueCount)); //$NON-NLS-1$ - } - } - } - } - - @Override - public void run() - { - - while (this._stop == false) - { - try - { - final EventLifeMonitor elm = this._eventQueue.poll(2, - TimeUnit.SECONDS); - if (elm != null) - { - // A poison queue event means its time to shutdown. - if (elm.getEvent().getClass() == PoisonQueueEvent.class) - break; - - final ManagerEvent iEvent = CoherentEventFactory.build(elm.getEvent()); - if (iEvent != null) - { - dispatchEvent(iEvent); - elm.assessAge(); - } - } - } - catch (final Exception e) - { - /** - * If an exception is thrown whilst we are shutting down then we - * don't care. If it is thrown when we aren't shutting down then - * we have a problem and we need to log it. - */ - if (this._stop == false) - { - CoherentManagerEventQueue.logger.error(e, e); - } - } - - } - - } - - class PoisonQueueEvent extends org.asteriskjava.manager.event.ManagerEvent - { - private static final long serialVersionUID = 1L; - - public PoisonQueueEvent() - { - super("PoisonQueueEvent"); //$NON-NLS-1$ - } - - } - - public void stop() - { - this._stop = true; - try - { - this._eventQueue - .put(new EventLifeMonitor(new PoisonQueueEvent())); - } - catch (InterruptedException e) - { - logger.error(e, e); - - } - } - - /** - * Events are sent here from the CoherentManagerEventQueue after being - * converted from a ManagerEvent to an ManagerEvent. This method is called - * from a dedicated thread attached to the event queue which it uses for - * dispatching events. - */ - public void dispatchEvent(final ManagerEvent event) - { - if (logger.isDebugEnabled()) - { - logger.debug("dispatch=" + event.toString()); //$NON-NLS-1$ - } - - // take a copy of the listeners so they can be modified whilst we - // iterate over them - // The iteration may call some long running processes. - final TreeSet listenerCopy = new TreeSet<>(new ListenerPriorityComparator()); - synchronized (this.listeners) - { - listenerCopy.addAll(this.listeners); - } - - for (final Listener filter : listenerCopy) - { - if (filter.requiredEvents.contains(event.getClass())) - { - final LogTime time = new LogTime(); - - filter._listener.onManagerEvent(event); - if (time.timeTaken() > 500) - { - logger.warn("ManagerListener :" + filter._listener.getName() //$NON-NLS-1$ - + " is taken too long to process events " + " time taken: " + time.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - } - } - - /** - * Adds a listener which will be sent all events that its filterEvent - * handler will accept. All events are dispatch by way of a shared queue - * which is read via a thread which is shared by all listeners. Whilst poor - * performance of you listener can affect other listeners you can't affect - * the read thread which takes events from asterisk and enqueues them. - * - * @param listener - */ - public void addListener(final FilteredManagerListener listener) - { - synchronized (this.listeners) - { - this.listeners.add(new Listener(listener)); - synchronized (this.globalEvents) - { - this.globalEvents.addAll(listener.requiredEvents()); - } - } - logger.debug("listener added"); //$NON-NLS-1$ - } - - public void removeListener(final FilteredManagerListener melf) - { - synchronized (this.listeners) - { - if (melf != null) - { - for (Listener container : this.listeners) - { - if (container._listener == melf) - { - this.listeners.remove(container); - - // When we remove a listener we must unfortunately - // completely - // recalculate the set of required events. - synchronized (this.globalEvents) - { - this.globalEvents.clear(); - for (Listener readdContainer : this.listeners) - { - this.globalEvents.addAll(readdContainer._listener.requiredEvents()); - } - } - break; - } - } - } - } - } - - final class ListenerPriorityComparator implements Comparator - { - @Override - public int compare(Listener lhs, Listener rhs) - { - - int result = lhs._listener.getPriority().compare(rhs._listener.getPriority()); - - if (result == 0) - result = (lhs._listener.equals(rhs._listener) ? 0 : 1); - - return result; - } - } - - /** - * transfers the listeners from one queue to another. - * - * @param eventQueue - */ - public void transferListeners(CoherentManagerEventQueue eventQueue) - { - synchronized (this.listeners) - { - synchronized (eventQueue.listeners) - { - for (Listener listener : eventQueue.listeners) - { - this.addListener(listener._listener); - } - eventQueue.listeners.clear(); - } - } - } + private static final Log logger = LogFactory.getLog(CoherentManagerEventQueue.class); + + private class Listener + { + FilteredManagerListener _listener; + Set> requiredEvents; + + public Listener(FilteredManagerListener listener) + { + this._listener = listener; + this.requiredEvents = listener.requiredEvents(); + } + + @Override + public String toString() + { + return this._listener.getName(); + } + + } + + private final TreeSet listeners = new TreeSet<>(new ListenerPriorityComparator()); + + private boolean _stop = false; + private final Thread _th; + private final BlockingQueue> _eventQueue = new LinkedBlockingQueue<>(); + + private int _queueMaxSize; + + private long _queueSum; + + private long _queueCount; + + private HashSet> globalEvents = new HashSet<>(); + + public CoherentManagerEventQueue(String name) + { + CoherentManagerConnection.managerConnection.addEventListener(this); + + this._th = new Thread(this); + this._th.setName("EventQueue: " + name);//$NON-NLS-1$ + this._th.setDaemon(true); + this._th.start(); + } + + /** + * handles manager events passed to us in our role as a listener. We queue + * the event so that it can be read, by the run method of this class, and + * subsequently passed on to the original listener. + */ + @Override + public void onManagerEvent(final org.asteriskjava.manager.event.ManagerEvent event) + { + + // logger.error(event); + boolean wanted = false; + /** + * Dump any events we arn't interested in ASAP to minimise the + * processing overhead of these events. + */ + // Only enqueue the events that are of interest to one of our listeners. + synchronized (this.globalEvents) + { + Class< ? extends ManagerEvent> shadowEvent = CoherentEventFactory.getShadowEvent(event); + if (this.globalEvents.contains(shadowEvent)) + { + wanted = true; + } + } + + if (wanted) + { + + // We don't support all events. + this._eventQueue.add(new EventLifeMonitor<>(event)); + final int queueSize = this._eventQueue.size(); + if (this._queueMaxSize < queueSize) + { + this._queueMaxSize = queueSize; + } + this._queueSum += queueSize; + this._queueCount++; + + if (CoherentManagerEventQueue.logger.isDebugEnabled()) + { + if (this._eventQueue.size() > ((this._queueMaxSize + (this._queueSum / this._queueCount)) / 2)) + { + CoherentManagerEventQueue.logger.debug("queue gtr max avg: size=" + queueSize + " max:" //$NON-NLS-1$ //$NON-NLS-2$ + + this._queueMaxSize + " avg:" + (this._queueSum / this._queueCount)); //$NON-NLS-1$ + } + } + } + } + + @Override + public void run() + { + + while (this._stop == false) + { + try + { + final EventLifeMonitor elm = this._eventQueue.poll(2, + TimeUnit.SECONDS); + if (elm != null) + { + // A poison queue event means its time to shutdown. + if (elm.getEvent().getClass() == PoisonQueueEvent.class) + break; + + final ManagerEvent iEvent = CoherentEventFactory.build(elm.getEvent()); + if (iEvent != null) + { + dispatchEvent(iEvent); + elm.assessAge(); + } + } + } + catch (final Exception e) + { + /** + * If an exception is thrown whilst we are shutting down then we + * don't care. If it is thrown when we aren't shutting down then + * we have a problem and we need to log it. + */ + if (this._stop == false) + { + CoherentManagerEventQueue.logger.error(e, e); + } + } + + } + + } + + class PoisonQueueEvent extends org.asteriskjava.manager.event.ManagerEvent + { + private static final long serialVersionUID = 1L; + + public PoisonQueueEvent() + { + super("PoisonQueueEvent"); //$NON-NLS-1$ + } + + } + + public void stop() + { + this._stop = true; + try + { + this._eventQueue.put(new EventLifeMonitor(new PoisonQueueEvent())); + } + catch (InterruptedException e) + { + logger.error(e, e); + + } + } + + /** + * Events are sent here from the CoherentManagerEventQueue after being + * converted from a ManagerEvent to an ManagerEvent. This method is called + * from a dedicated thread attached to the event queue which it uses for + * dispatching events. + */ + public void dispatchEvent(final ManagerEvent event) + { + if (logger.isDebugEnabled()) + { + logger.debug("dispatch=" + event.toString()); //$NON-NLS-1$ + } + + // take a copy of the listeners so they can be modified whilst we + // iterate over them + // The iteration may call some long running processes. + final TreeSet listenerCopy = new TreeSet<>(new ListenerPriorityComparator()); + synchronized (this.listeners) + { + listenerCopy.addAll(this.listeners); + } + + for (final Listener filter : listenerCopy) + { + if (filter.requiredEvents.contains(event.getClass())) + { + final LogTime time = new LogTime(); + + filter._listener.onManagerEvent(event); + if (time.timeTaken() > 500) + { + logger.warn("ManagerListener :" + filter._listener.getName() //$NON-NLS-1$ + + " is taken too long to process events " + " time taken: " + time.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + } + } + + /** + * Adds a listener which will be sent all events that its filterEvent + * handler will accept. All events are dispatch by way of a shared queue + * which is read via a thread which is shared by all listeners. Whilst poor + * performance of you listener can affect other listeners you can't affect + * the read thread which takes events from asterisk and enqueues them. + * + * @param listener + */ + public void addListener(final FilteredManagerListener listener) + { + synchronized (this.listeners) + { + this.listeners.add(new Listener(listener)); + synchronized (this.globalEvents) + { + this.globalEvents.addAll(listener.requiredEvents()); + } + } + logger.debug("listener added"); //$NON-NLS-1$ + } + + public void removeListener(final FilteredManagerListener melf) + { + synchronized (this.listeners) + { + if (melf != null) + { + for (Listener container : this.listeners) + { + if (container._listener == melf) + { + this.listeners.remove(container); + + // When we remove a listener we must unfortunately + // completely + // recalculate the set of required events. + synchronized (this.globalEvents) + { + this.globalEvents.clear(); + for (Listener readdContainer : this.listeners) + { + this.globalEvents.addAll(readdContainer._listener.requiredEvents()); + } + } + break; + } + } + } + } + } + + final class ListenerPriorityComparator implements Comparator + { + @Override + public int compare(Listener lhs, Listener rhs) + { + + int result = lhs._listener.getPriority().compare(rhs._listener.getPriority()); + + if (result == 0) + result = (lhs._listener.equals(rhs._listener) ? 0 : 1); + + return result; + } + } + + /** + * transfers the listeners from one queue to another. + * + * @param eventQueue + */ + public void transferListeners(CoherentManagerEventQueue eventQueue) + { + synchronized (this.listeners) + { + synchronized (eventQueue.listeners) + { + for (Listener listener : eventQueue.listeners) + { + this.addListener(listener._listener); + } + eventQueue.listeners.clear(); + } + } + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java index 2a3ee57f3..b8914123d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.internal.core; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.TechType; import org.asteriskjava.pbx.Trunk; @@ -9,9 +8,6 @@ public class EndPointImpl implements EndPoint { private static final String DELIMITER = "/"; //$NON-NLS-1$ - @SuppressWarnings("unused") - private static final Logger logger = Logger.getLogger(EndPointImpl.class); - final private TechType _tech; final private String _endPointName; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index aac187c1e..1add25e1d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -5,8 +5,6 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; -import org.apache.log4j.Logger; -import org.apache.log4j.Priority; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.InvalidChannelName; @@ -15,6 +13,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.MasqueradeEvent; import org.asteriskjava.pbx.asterisk.wrap.events.RenameEvent; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * The LiveChannelManager keeps a list of all of the live channels present on an @@ -51,7 +51,7 @@ */ public class LiveChannelManager implements FilteredManagerListener { - private static final Logger logger = Logger.getLogger(LiveChannelManager.class); + private static final Log logger = LogFactory.getLog(LiveChannelManager.class); /** * A collection of all of the live proxies in the system. We monitor the @@ -333,11 +333,10 @@ public ListenerPriority getPriority() return ListenerPriority.CRITICAL; } - @SuppressWarnings("deprecation") public void sanityCheck() { - if (logger.isEnabledFor(Priority.INFO)) + if (logger.isDebugEnabled()) { logger.error("Performing Sanity Check"); Set channels = new HashSet<>(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java index 870010c3d..0718943bf 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java @@ -2,13 +2,14 @@ import java.util.LinkedList; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.asterisk.wrap.events.MasqueradeEvent; import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; import org.asteriskjava.pbx.asterisk.wrap.events.NewStateEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /* * this class tracks the status of a Peer on asterisk. T @@ -20,309 +21,307 @@ public class Peer implements CallEndedListener { - static private Logger logger = Logger.getLogger(Peer.class); - - private final EndPoint peerEndPoint; - - /** - * Used to track the list of channels associated with this peer. - * - * I think there would normally only be a single channel unless we are in - * the middle of a transfer or the phone has two calls up. - */ - private final LinkedList callList = new LinkedList<>(); - - private PeerState _state = PeerState.NOTSET; - private boolean dnd = false; - - public Peer(final EndPoint endPoint) - { - this.peerEndPoint = endPoint; - } - - public boolean isSame(final Peer rhs) - { - return this.peerEndPoint.isSame(rhs.getEndPoint()); - } - - private CallTracker registerChannel(final Channel newChannel) - { - CallTracker associatedCall = null; - boolean found = false; - synchronized (this.callList) - { - for (final CallTracker call : this.callList) - { - if (call.findChannel(newChannel) != -1) - { - found = true; - associatedCall = call; - break; - } - } - if (!found) - { - if (logger.isDebugEnabled()) - logger.debug("Peer adding Call: " + this.toString() + " " + newChannel.getExtendedChannelName()); //$NON-NLS-1$ //$NON-NLS-2$ - associatedCall = createCallTracker(newChannel); - this.dumpCallList(); - } - } - return associatedCall; - } - - private CallTracker createCallTracker(final Channel newChannel) - { - CallTracker newCall; - synchronized (this.callList) - { - newCall = new CallTracker(this, newChannel); - this.callList.add(newCall); - } - return newCall; - } - - public boolean getDND() - { - return this.dnd; - } - - // public String getFullChannelName() - // { - // String channelName = null; - // synchronized (this.callList) - // { - // if (this.callList.size() > 0) - // { - // channelName = this.callList.get(0).getChannelName(); - // } - // } - // - // return channelName; - // } - - public PeerState getState() - { - return this._state; - } - - /** - * Determines if the given channel is connected to this peer. - * - * @param channel - * @return - */ - private boolean isConnectedToSelf(final Channel channel) - { - return this.getEndPoint().isSame(channel.getEndPoint()); - } - - /** - * We handle the masqurade event is it contains channel state information. - * During a masquerade we will have two channels for the one peer, the - * original and the clone. As the clone is taking over from the original - * peer we now need to use that as true indicator of state. - * - * @param b - * @throws Exception - */ - public void handleEvent(final MasqueradeEvent b) - { - if (this.isConnectedToSelf(b.getClone())) - { - // At this point we will actually have two CallTrackers - // which we now need to merge into a single CallTracker. - CallTracker original = findCall(b.getOriginal()); - CallTracker clone = findCall(b.getClone()); - if (original != null && clone != null) - { - clone.mergeCalls(original); - clone.setState(b.getCloneState()); - this.evaluateState(); - } - else - logger.warn("When processing masquradeEvent we could not find the expected calls. event=" //$NON-NLS-1$ - + b.toString() + " original=" + original + " clone=" + clone); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - - /** - * When a new channel comes up associated it with the peer. - * - * Be warned a peer can have multiple calls associated with it. - * - * @param b - * @throws Exception - */ - public void handleEvent(final NewChannelEvent b) - { - // Very occasionally we get a null channel which we can't do anything - // with so just throw the event away. - // If we get a Console/dsp channel name it means that someone has - // dialled from the asterisk - // console. We just ignore these. - if ((b.getChannel() == null) || (b.getChannel().isConsole())) - { - return; - } - - if (this.isConnectedToSelf(b.getChannel())) - { - CallTracker call = this.registerChannel(b.getChannel()); - if (call != null) - { - call.setState(b.getChannelState()); - this.evaluateState(); - } - } - } - - public void handleEvent(final NewStateEvent b) - { - if (this.isConnectedToSelf(b.getChannel())) - { - CallTracker call = this.registerChannel(b.getChannel()); - if (call != null) - { - call.setState(b.getChannelState()); - this.evaluateState(); - } - } - } - - public void handleEvent(final StatusEvent b) - { - final Channel channel = b.getChannel(); - if (this.isConnectedToSelf(channel)) - { - ((ChannelProxy) channel).getRealChannel().markChannel(); - - CallTracker call = findCall(channel); - if (call != null) - { - call.setState(b.getState()); - this.evaluateState(); - } - } - } - - private CallTracker findCall(Channel channel) - { - CallTracker result = null; - synchronized (this.callList) - { - for (CallTracker call : this.callList) - { - if (call.findChannel(channel) != -1) - { - result = call; - break; - } - } - - } - return result; - } - - public void setDND(final boolean on) - { - this.dnd = on; - } - - public void startSweep() - { - Peer.logger.debug("Starting sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ - synchronized (this.callList) - { - for (final CallTracker call : this.callList) - { - call.startSweep(); - } - } - } - - public void endSweep() - { - Peer.logger.debug("Ending sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ - synchronized (this.callList) - { - for (final CallTracker call : this.callList) - { - call.endSweep(); - } - } - this.evaluateState(); - } - - /** - * Called each time the state of a call changes to determine the Peers - * overall state. - */ - private void evaluateState() - { - synchronized (this.callList) - { - // Get the highest prioirty state from the set of calls. - PeerState newState = PeerState.NOTSET; - for (CallTracker call : this.callList) - { - if (call.getState().getPriority() > newState.getPriority()) - newState = call.getState(); - } - - this._state = newState; - } - } - - public EndPoint getEndPoint() - { - return this.peerEndPoint; - } - - @Override - public String toString() - { - return this.getEndPoint().toString(); - } - - private void dumpCallList() - { - if (logger.isDebugEnabled()) - { - Peer.logger.debug("Peer: dump CallList:" + this); //$NON-NLS-1$ - for (final CallTracker call : this.callList) - { - call.dumpChannelList(); - } - } - } - - @Override - public void callEnded(CallTracker call) - { - boolean found = false; - synchronized (this.callList) - { - for (final CallTracker aCall : this.callList) - { - if (call == aCall) - { - found = true; - if (logger.isDebugEnabled()) - logger.debug("peer Removing call " + call); //$NON-NLS-1$ - this.callList.remove(call); - this.evaluateState(); - this.dumpCallList(); - break; - } - } - if (!found) - { - logger.error("Error call not found removing call from peer: call=" + call + " peer=" + this); //$NON-NLS-1$ //$NON-NLS-2$ - this.dumpCallList(); - } - } - - } - -} \ No newline at end of file + private static final Log logger = LogFactory.getLog(Peer.class); + + private final EndPoint peerEndPoint; + + /** + * Used to track the list of channels associated with this peer. I think + * there would normally only be a single channel unless we are in the middle + * of a transfer or the phone has two calls up. + */ + private final LinkedList callList = new LinkedList<>(); + + private PeerState _state = PeerState.NOTSET; + private boolean dnd = false; + + public Peer(final EndPoint endPoint) + { + this.peerEndPoint = endPoint; + } + + public boolean isSame(final Peer rhs) + { + return this.peerEndPoint.isSame(rhs.getEndPoint()); + } + + private CallTracker registerChannel(final Channel newChannel) + { + CallTracker associatedCall = null; + boolean found = false; + synchronized (this.callList) + { + for (final CallTracker call : this.callList) + { + if (call.findChannel(newChannel) != -1) + { + found = true; + associatedCall = call; + break; + } + } + if (!found) + { + if (logger.isDebugEnabled()) + logger.debug("Peer adding Call: " + this.toString() + " " + newChannel.getExtendedChannelName()); //$NON-NLS-1$ //$NON-NLS-2$ + associatedCall = createCallTracker(newChannel); + this.dumpCallList(); + } + } + return associatedCall; + } + + private CallTracker createCallTracker(final Channel newChannel) + { + CallTracker newCall; + synchronized (this.callList) + { + newCall = new CallTracker(this, newChannel); + this.callList.add(newCall); + } + return newCall; + } + + public boolean getDND() + { + return this.dnd; + } + + // public String getFullChannelName() + // { + // String channelName = null; + // synchronized (this.callList) + // { + // if (this.callList.size() > 0) + // { + // channelName = this.callList.get(0).getChannelName(); + // } + // } + // + // return channelName; + // } + + public PeerState getState() + { + return this._state; + } + + /** + * Determines if the given channel is connected to this peer. + * + * @param channel + * @return + */ + private boolean isConnectedToSelf(final Channel channel) + { + return this.getEndPoint().isSame(channel.getEndPoint()); + } + + /** + * We handle the masqurade event is it contains channel state information. + * During a masquerade we will have two channels for the one peer, the + * original and the clone. As the clone is taking over from the original + * peer we now need to use that as true indicator of state. + * + * @param b + * @throws Exception + */ + public void handleEvent(final MasqueradeEvent b) + { + if (this.isConnectedToSelf(b.getClone())) + { + // At this point we will actually have two CallTrackers + // which we now need to merge into a single CallTracker. + CallTracker original = findCall(b.getOriginal()); + CallTracker clone = findCall(b.getClone()); + if (original != null && clone != null) + { + clone.mergeCalls(original); + clone.setState(b.getCloneState()); + this.evaluateState(); + } + else + logger.warn("When processing masquradeEvent we could not find the expected calls. event=" //$NON-NLS-1$ + + b.toString() + " original=" + original + " clone=" + clone); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + /** + * When a new channel comes up associated it with the peer. Be warned a peer + * can have multiple calls associated with it. + * + * @param b + * @throws Exception + */ + public void handleEvent(final NewChannelEvent b) + { + // Very occasionally we get a null channel which we can't do anything + // with so just throw the event away. + // If we get a Console/dsp channel name it means that someone has + // dialled from the asterisk + // console. We just ignore these. + if ((b.getChannel() == null) || (b.getChannel().isConsole())) + { + return; + } + + if (this.isConnectedToSelf(b.getChannel())) + { + CallTracker call = this.registerChannel(b.getChannel()); + if (call != null) + { + call.setState(b.getChannelState()); + this.evaluateState(); + } + } + } + + public void handleEvent(final NewStateEvent b) + { + if (this.isConnectedToSelf(b.getChannel())) + { + CallTracker call = this.registerChannel(b.getChannel()); + if (call != null) + { + call.setState(b.getChannelState()); + this.evaluateState(); + } + } + } + + public void handleEvent(final StatusEvent b) + { + final Channel channel = b.getChannel(); + if (this.isConnectedToSelf(channel)) + { + ((ChannelProxy) channel).getRealChannel().markChannel(); + + CallTracker call = findCall(channel); + if (call != null) + { + call.setState(b.getState()); + this.evaluateState(); + } + } + } + + private CallTracker findCall(Channel channel) + { + CallTracker result = null; + synchronized (this.callList) + { + for (CallTracker call : this.callList) + { + if (call.findChannel(channel) != -1) + { + result = call; + break; + } + } + + } + return result; + } + + public void setDND(final boolean on) + { + this.dnd = on; + } + + public void startSweep() + { + Peer.logger.debug("Starting sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ + synchronized (this.callList) + { + for (final CallTracker call : this.callList) + { + call.startSweep(); + } + } + } + + public void endSweep() + { + Peer.logger.debug("Ending sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ + synchronized (this.callList) + { + for (final CallTracker call : this.callList) + { + call.endSweep(); + } + } + this.evaluateState(); + } + + /** + * Called each time the state of a call changes to determine the Peers + * overall state. + */ + private void evaluateState() + { + synchronized (this.callList) + { + // Get the highest prioirty state from the set of calls. + PeerState newState = PeerState.NOTSET; + for (CallTracker call : this.callList) + { + if (call.getState().getPriority() > newState.getPriority()) + newState = call.getState(); + } + + this._state = newState; + } + } + + public EndPoint getEndPoint() + { + return this.peerEndPoint; + } + + @Override + public String toString() + { + return this.getEndPoint().toString(); + } + + private void dumpCallList() + { + if (logger.isDebugEnabled()) + { + Peer.logger.debug("Peer: dump CallList:" + this); //$NON-NLS-1$ + for (final CallTracker call : this.callList) + { + call.dumpChannelList(); + } + } + } + + @Override + public void callEnded(CallTracker call) + { + boolean found = false; + synchronized (this.callList) + { + for (final CallTracker aCall : this.callList) + { + if (call == aCall) + { + found = true; + if (logger.isDebugEnabled()) + logger.debug("peer Removing call " + call); //$NON-NLS-1$ + this.callList.remove(call); + this.evaluateState(); + this.dumpCallList(); + break; + } + } + if (!found) + { + logger.error("Error call not found removing call from peer: call=" + call + " peer=" + this); //$NON-NLS-1$ //$NON-NLS-2$ + this.dumpCallList(); + } + } + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java index 7c5c84c25..675490360 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java @@ -5,7 +5,6 @@ import java.util.LinkedList; import java.util.List; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.ListenerPriority; @@ -24,6 +23,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /* * this class tracks the status of all peers on asterisk. @@ -31,356 +32,352 @@ public class PeerMonitor extends EventListenerBaseClass implements Runnable { - static Logger logger = Logger.getLogger(PeerMonitor.class); - - LinkedList peerList = new LinkedList<>(); - - boolean initSip = false; - - private final Thread markAndSweepThread; - - private static PeerMonitor self; - - private static NewExtensionListener listener; - - /** - * needs to notify PhoneBookDisplayController.getInstance().addExtensions(); - * - * @param _listener - */ - public synchronized static void init(final NewExtensionListener _listener) - { - PeerMonitor.listener = _listener; - - if (PeerMonitor.self == null) - { - PeerMonitor.self = new PeerMonitor(); - } - else if (_listener != null) - { - logger.error("Call to PeerMonitor.init, but it's already initialized. Listener will not be set"); - } - } - - public static synchronized PeerMonitor getInstance() - { - if (PeerMonitor.self == null) - { - throw new IllegalStateException("You must call PeerMonitor.init()"); //$NON-NLS-1$ - } - return PeerMonitor.self; - } - - private PeerMonitor() - { - super("PeerMonitor"); //$NON-NLS-1$ - this.peerList = new LinkedList<>(); - this.startListener(PBXFactory.getActivePBX()); - this.addSipsToMonitor(); - try - { - if (PeerMonitor.listener != null) - { - PeerMonitor.listener.newExtension(); - } - else - { - logger.warn("Peer monitor listener is null"); - } - } - catch (final Exception e) - { - PeerMonitor.logger.error(e, e); - } - - this.markAndSweepThread = new Thread(this); - this.markAndSweepThread.setName("PeerMonitor-MarkAndSweep"); //$NON-NLS-1$ - this.markAndSweepThread.setDaemon(true); - this.markAndSweepThread.start(); - - } - - public void addSipsToMonitor() - { - /* - * request asterisk to send a list of sip peers. The monitor will - * dynamically add the peers to its list - */ - this.initSip = false; - - final StatusAction sa = new StatusAction(); - final SipPeersAction t = new SipPeersAction(); - try - { - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - pbx.sendAction(t, 5000); - pbx.sendAction(sa, 5000); - } - catch (final Exception e) - { - PeerMonitor.logger.error(e, e); - } - - } - - synchronized public Peer registerPeer(final Channel newChannel) - { - final Peer peer = this.registerPeer(newChannel.getEndPoint()); - return peer; - } - - synchronized public Peer registerPeer(final EndPoint endPoint) - { - if (endPoint.isLocal()) - { - return null; - } - - Peer peer = this.findPeer(endPoint); - if (peer == null) - { - peer = new Peer(endPoint); - this.peerList.add(peer); - } - - return peer; - } - - synchronized public Peer findPeer(final EndPoint peerEndPoint) - { - Peer found = null; - - for (final Peer peer : this.peerList) - { - if (peer.getEndPoint().isSame(peerEndPoint)) - { - found = peer; - break; - } - } - return found; - } - - @SuppressWarnings("unchecked") - public Iterator getIterator() - { - final List clone = (LinkedList) this.peerList.clone(); - final List tmpList = clone; - return tmpList.iterator(); - - } - - @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); - - required.add(NewChannelEvent.class); - required.add(PeerStatusEvent.class); - required.add(PeerEntryEvent.class); - required.add(PeerlistCompleteEvent.class); - required.add(NewStateEvent.class); - required.add(StatusEvent.class); - required.add(StatusCompleteEvent.class); - required.add(DndStateEvent.class); - - return required; - } - - @Override - synchronized public void onManagerEvent(final ManagerEvent event) - { - /* - * This function is called from the base class. Here we process events - * we are interested in. - */ - - if (event instanceof PeerStatusEvent) - { - this.handleEvent((PeerStatusEvent) event); - } - else if (event instanceof PeerlistCompleteEvent) - { - this.handleEvent((PeerlistCompleteEvent) event); - } - else if (event instanceof PeerEntryEvent) - { - this.handleEvent((PeerEntryEvent) event); - } - else if (event instanceof NewChannelEvent) - { - this.handleEvent((NewChannelEvent) event); - } - else if (event instanceof MasqueradeEvent) - { - this.handleEvent((MasqueradeEvent) event); - } - else if (event instanceof StatusEvent) - { - this.handleEvent((StatusEvent) event); - } - else if (event instanceof StatusCompleteEvent) - { - this.handleEvent((StatusCompleteEvent) event); - } - else if (event instanceof NewStateEvent) - { - this.handleEvent((NewStateEvent) event); - } - } - - private void handleEvent(NewStateEvent event) - { - for (Peer peer : this.peerList) - { - peer.handleEvent(event); - } - } - - private void handleEvent(final NewChannelEvent event) - { - for (Peer peer : this.peerList) - { - peer.handleEvent(event); - } - } - - private void handleEvent(final MasqueradeEvent event) - { - for (Peer peer : this.peerList) - { - peer.handleEvent(event); - } - } - - private void handleEvent(final StatusEvent event) - { - for (Peer peer : this.peerList) - { - peer.handleEvent(event); - } - } - - private void handleEvent(final PeerEntryEvent event) - { - final EndPoint endPoint = event.getPeer(); - this.registerPeer(endPoint); - } - - private void handleEvent(final PeerlistCompleteEvent b) - { - this.initSip = true; - } - - /** - * @param event - */ - private void handleEvent(final PeerStatusEvent event) - { - this.registerPeer(event.getPeer()); - } - - /** - * We receive the StatusComplete event once the Mark and Sweep channel - * operation has completed. We now call endSweep which will remove any - * channels that were not marked during the operation. - * - * @param event - */ - private synchronized void handleEvent(final StatusCompleteEvent event) - { - - for (final Peer peer : this.peerList) - { - peer.endSweep(); - } - PeerMonitor.logger.debug("Channel Mark and Sweep complete"); //$NON-NLS-1$ - } - - boolean isInitialized() - { - return this.initSip; - } - - public void stop() - { - this.close(); - - } - - /************************************************************************************** - * - * Mark and Sweep logic follows - * - **************************************************************************************/ - - /** - * Runs the mark and sweep operation every 120 seconds on all channels to - * clean up any channels that have died and for which (for some reason) we - * missed the hangup event. - * - */ - @Override - public void run() - { - while (true) - { - try - { - Thread.sleep(120000); - PeerMonitor.getInstance().startSweep(); - } - catch (final InterruptedException e) - { - PeerMonitor.logger.error(e, e); - - } - } - - } - - /** - * Check every channel to make certain they are still active. We do this in - * case we missed a hangup event along the way somewhere. This allows us to - * cleanup any old channels. We start by clearing the mark on all channels - * and then generates a Asterisk status message for every active channel. At - * the end of the process any channels which haven't been marked are then - * discarded. - */ - public void startSweep() - { - PeerMonitor.logger.debug("Starting channel mark and sweep"); //$NON-NLS-1$ - - // Mark every channel as 'clearing' - synchronized (PeerMonitor.class) - { - for (final Peer peer : this.peerList) - { - peer.startSweep(); - } - } - - /** - * Request Asterisk to send us a status update for every channel. - * - */ - final StatusAction sa = new StatusAction(); - try - { - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - pbx.sendAction(sa, 5000); - } - catch (final Exception e) - { - PeerMonitor.logger.error(e, e); - } - - } - - @Override - public ListenerPriority getPriority() - { - return ListenerPriority.HIGH; - } + private static final Log logger = LogFactory.getLog(PeerMonitor.class); + + LinkedList peerList = new LinkedList<>(); + + boolean initSip = false; + + private final Thread markAndSweepThread; + + private static PeerMonitor self; + + private static NewExtensionListener listener; + + /** + * needs to notify PhoneBookDisplayController.getInstance().addExtensions(); + * + * @param _listener + */ + public synchronized static void init(final NewExtensionListener _listener) + { + PeerMonitor.listener = _listener; + + if (PeerMonitor.self == null) + { + PeerMonitor.self = new PeerMonitor(); + } + else if (_listener != null) + { + logger.error("Call to PeerMonitor.init, but it's already initialized. Listener will not be set"); + } + } + + public static synchronized PeerMonitor getInstance() + { + if (PeerMonitor.self == null) + { + throw new IllegalStateException("You must call PeerMonitor.init()"); //$NON-NLS-1$ + } + return PeerMonitor.self; + } + + private PeerMonitor() + { + super("PeerMonitor"); //$NON-NLS-1$ + this.peerList = new LinkedList<>(); + this.startListener(PBXFactory.getActivePBX()); + this.addSipsToMonitor(); + try + { + if (PeerMonitor.listener != null) + { + PeerMonitor.listener.newExtension(); + } + else + { + logger.warn("Peer monitor listener is null"); + } + } + catch (final Exception e) + { + PeerMonitor.logger.error(e, e); + } + + this.markAndSweepThread = new Thread(this); + this.markAndSweepThread.setName("PeerMonitor-MarkAndSweep"); //$NON-NLS-1$ + this.markAndSweepThread.setDaemon(true); + this.markAndSweepThread.start(); + + } + + public void addSipsToMonitor() + { + /* + * request asterisk to send a list of sip peers. The monitor will + * dynamically add the peers to its list + */ + this.initSip = false; + + final StatusAction sa = new StatusAction(); + final SipPeersAction t = new SipPeersAction(); + try + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + pbx.sendAction(t, 5000); + pbx.sendAction(sa, 5000); + } + catch (final Exception e) + { + PeerMonitor.logger.error(e, e); + } + + } + + synchronized public Peer registerPeer(final Channel newChannel) + { + final Peer peer = this.registerPeer(newChannel.getEndPoint()); + return peer; + } + + synchronized public Peer registerPeer(final EndPoint endPoint) + { + if (endPoint.isLocal()) + { + return null; + } + + Peer peer = this.findPeer(endPoint); + if (peer == null) + { + peer = new Peer(endPoint); + this.peerList.add(peer); + } + + return peer; + } + + synchronized public Peer findPeer(final EndPoint peerEndPoint) + { + Peer found = null; + + for (final Peer peer : this.peerList) + { + if (peer.getEndPoint().isSame(peerEndPoint)) + { + found = peer; + break; + } + } + return found; + } + + @SuppressWarnings("unchecked") + public Iterator getIterator() + { + final List clone = (LinkedList) this.peerList.clone(); + final List tmpList = clone; + return tmpList.iterator(); + + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + required.add(NewChannelEvent.class); + required.add(PeerStatusEvent.class); + required.add(PeerEntryEvent.class); + required.add(PeerlistCompleteEvent.class); + required.add(NewStateEvent.class); + required.add(StatusEvent.class); + required.add(StatusCompleteEvent.class); + required.add(DndStateEvent.class); + + return required; + } + + @Override + synchronized public void onManagerEvent(final ManagerEvent event) + { + /* + * This function is called from the base class. Here we process events + * we are interested in. + */ + + if (event instanceof PeerStatusEvent) + { + this.handleEvent((PeerStatusEvent) event); + } + else if (event instanceof PeerlistCompleteEvent) + { + this.handleEvent((PeerlistCompleteEvent) event); + } + else if (event instanceof PeerEntryEvent) + { + this.handleEvent((PeerEntryEvent) event); + } + else if (event instanceof NewChannelEvent) + { + this.handleEvent((NewChannelEvent) event); + } + else if (event instanceof MasqueradeEvent) + { + this.handleEvent((MasqueradeEvent) event); + } + else if (event instanceof StatusEvent) + { + this.handleEvent((StatusEvent) event); + } + else if (event instanceof StatusCompleteEvent) + { + this.handleEvent((StatusCompleteEvent) event); + } + else if (event instanceof NewStateEvent) + { + this.handleEvent((NewStateEvent) event); + } + } + + private void handleEvent(NewStateEvent event) + { + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } + } + + private void handleEvent(final NewChannelEvent event) + { + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } + } + + private void handleEvent(final MasqueradeEvent event) + { + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } + } + + private void handleEvent(final StatusEvent event) + { + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } + } + + private void handleEvent(final PeerEntryEvent event) + { + final EndPoint endPoint = event.getPeer(); + this.registerPeer(endPoint); + } + + private void handleEvent(final PeerlistCompleteEvent b) + { + this.initSip = true; + } + + /** + * @param event + */ + private void handleEvent(final PeerStatusEvent event) + { + this.registerPeer(event.getPeer()); + } + + /** + * We receive the StatusComplete event once the Mark and Sweep channel + * operation has completed. We now call endSweep which will remove any + * channels that were not marked during the operation. + * + * @param event + */ + private synchronized void handleEvent(final StatusCompleteEvent event) + { + + for (final Peer peer : this.peerList) + { + peer.endSweep(); + } + PeerMonitor.logger.debug("Channel Mark and Sweep complete"); //$NON-NLS-1$ + } + + boolean isInitialized() + { + return this.initSip; + } + + public void stop() + { + this.close(); + + } + + /************************************************************************************** + * Mark and Sweep logic follows + **************************************************************************************/ + + /** + * Runs the mark and sweep operation every 120 seconds on all channels to + * clean up any channels that have died and for which (for some reason) we + * missed the hangup event. + */ + @Override + public void run() + { + while (true) + { + try + { + Thread.sleep(120000); + PeerMonitor.getInstance().startSweep(); + } + catch (final InterruptedException e) + { + PeerMonitor.logger.error(e, e); + + } + } + + } + + /** + * Check every channel to make certain they are still active. We do this in + * case we missed a hangup event along the way somewhere. This allows us to + * cleanup any old channels. We start by clearing the mark on all channels + * and then generates a Asterisk status message for every active channel. At + * the end of the process any channels which haven't been marked are then + * discarded. + */ + public void startSweep() + { + PeerMonitor.logger.debug("Starting channel mark and sweep"); //$NON-NLS-1$ + + // Mark every channel as 'clearing' + synchronized (PeerMonitor.class) + { + for (final Peer peer : this.peerList) + { + peer.startSweep(); + } + } + + /** + * Request Asterisk to send us a status update for every channel. + */ + final StatusAction sa = new StatusAction(); + try + { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + pbx.sendAction(sa, 5000); + } + catch (final Exception e) + { + PeerMonitor.logger.error(e, e); + } + + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.HIGH; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java index c5887e700..06a3ab2e9 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java @@ -1,111 +1,111 @@ package org.asteriskjava.pbx.internal.core; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.asterisk.wrap.events.ChannelState; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public enum PeerState { - DOWN(1,"Down", "OnHook", false), //$NON-NLS-1$ //$NON-NLS-2$ - UP(2,"Up", "OnPhone", true), //$NON-NLS-1$ //$NON-NLS-2$ - UNKNOWN(0,"Unknown", "Unknown", false), //$NON-NLS-1$ //$NON-NLS-2$ - NOTSET(0, "Not Set", "", false), //$NON-NLS-1$ //$NON-NLS-2$ - UNMONITORED(0, "Unmonitored", "Unmonitored", true), //$NON-NLS-1$ //$NON-NLS-2$ - DND(3,"DND", "DND", true), //$NON-NLS-1$ //$NON-NLS-2$ - RINGING(4,"Ringing", "Ringing", true), //$NON-NLS-1$ //$NON-NLS-2$ - OFF_LINE(1,"Off line", "Offline", true), //$NON-NLS-1$ //$NON-NLS-2$ - UNREGISTERED(0,"Unregistered", "Unregistered", true), //$NON-NLS-1$ //$NON-NLS-2$ - REGISTERED(0,"Registered", "Registered", false), //$NON-NLS-1$ //$NON-NLS-2$ - BUSY(2,"Busy", "Busy", true), //$NON-NLS-1$//$NON-NLS-2$ - RING(4,"Ring", "Dialing", true), //$NON-NLS-1$ //$NON-NLS-2$ - EXTERNAL(0,"External", "External", false);//$NON-NLS-1$ //$NON-NLS-2$ - - static private final Logger logger = Logger.getLogger(PeerState.class); - - final String _asteriskStateName; - - final String label; - - /** - * Controls whether the state should be displayed to the end user or just - * hidden. - * - */ - private boolean _visible; - - /** - * The priority ranks the PeerStates relative to each other. When a Peer has - * multiple active calls we need to display the call state from the call - * with the highest priority. e.g. If one call is UP and another is RINGING - * then we need to display the RINGING state as this is more interesting. - */ - private int _priority; - - public static PeerState valueByName(final String value) - { - PeerState status = NOTSET; - - for (PeerState aState : PeerState.values()) - { - - if (aState.getAsteriskStateName().compareToIgnoreCase(value) == 0) - { - status = aState; - break; - } - } - return status; - } - - private String getAsteriskStateName() - { - return this._asteriskStateName; - } - - public static PeerState valueByChannelState(final ChannelState state) - { - PeerState status = NOTSET; - - for (PeerState aState : PeerState.values()) - { - - if (aState.getAsteriskStateName().compareToIgnoreCase(state.name()) == 0) - { - status = aState; - break; - } - } - - if (status == NOTSET) - logger.warn("Unknown channelState: " + state + " recieved", new Throwable("Unknown channelState")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - return status; - } - - PeerState(int priority, final String asteriskStateName, final String label, boolean visible) - { - this._asteriskStateName = asteriskStateName; - this.label = label; - this._visible = visible; - this._priority = priority; - } - - public String getLabel() - { - return this.label; - } - - @Override - public String toString() - { - return this.label; - } - - public boolean isVisible() - { - return this._visible; - } - - public int getPriority() - { - return this._priority; - } + DOWN(1, "Down", "OnHook", false), //$NON-NLS-1$ //$NON-NLS-2$ + UP(2, "Up", "OnPhone", true), //$NON-NLS-1$ //$NON-NLS-2$ + UNKNOWN(0, "Unknown", "Unknown", false), //$NON-NLS-1$ //$NON-NLS-2$ + NOTSET(0, "Not Set", "", false), //$NON-NLS-1$ //$NON-NLS-2$ + UNMONITORED(0, "Unmonitored", "Unmonitored", true), //$NON-NLS-1$ //$NON-NLS-2$ + DND(3, "DND", "DND", true), //$NON-NLS-1$ //$NON-NLS-2$ + RINGING(4, "Ringing", "Ringing", true), //$NON-NLS-1$ //$NON-NLS-2$ + OFF_LINE(1, "Off line", "Offline", true), //$NON-NLS-1$ //$NON-NLS-2$ + UNREGISTERED(0, "Unregistered", "Unregistered", true), //$NON-NLS-1$ //$NON-NLS-2$ + REGISTERED(0, "Registered", "Registered", false), //$NON-NLS-1$ //$NON-NLS-2$ + BUSY(2, "Busy", "Busy", true), //$NON-NLS-1$//$NON-NLS-2$ + RING(4, "Ring", "Dialing", true), //$NON-NLS-1$ //$NON-NLS-2$ + EXTERNAL(0, "External", "External", false);//$NON-NLS-1$ //$NON-NLS-2$ + + private static final Log logger = LogFactory.getLog(PeerState.class); + + final String _asteriskStateName; + + final String label; + + /** + * Controls whether the state should be displayed to the end user or just + * hidden. + */ + private boolean _visible; + + /** + * The priority ranks the PeerStates relative to each other. When a Peer has + * multiple active calls we need to display the call state from the call + * with the highest priority. e.g. If one call is UP and another is RINGING + * then we need to display the RINGING state as this is more interesting. + */ + private int _priority; + + public static PeerState valueByName(final String value) + { + PeerState status = NOTSET; + + for (PeerState aState : PeerState.values()) + { + + if (aState.getAsteriskStateName().compareToIgnoreCase(value) == 0) + { + status = aState; + break; + } + } + return status; + } + + private String getAsteriskStateName() + { + return this._asteriskStateName; + } + + public static PeerState valueByChannelState(final ChannelState state) + { + PeerState status = NOTSET; + + for (PeerState aState : PeerState.values()) + { + + if (aState.getAsteriskStateName().compareToIgnoreCase(state.name()) == 0) + { + status = aState; + break; + } + } + + if (status == NOTSET) + logger.warn("Unknown channelState: " + state + " recieved", new Throwable("Unknown channelState")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + return status; + } + + PeerState(int priority, final String asteriskStateName, final String label, boolean visible) + { + this._asteriskStateName = asteriskStateName; + this.label = label; + this._visible = visible; + this._priority = priority; + } + + public String getLabel() + { + return this.label; + } + + @Override + public String toString() + { + return this.label; + } + + public boolean isVisible() + { + return this._visible; + } + + public int getPriority() + { + return this._priority; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java b/src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java index a49dc43b8..1d7e5ba5f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java +++ b/src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java @@ -1,38 +1,39 @@ package org.asteriskjava.pbx.internal.eventQueue; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.util.LogTime; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class EventLifeMonitor { - static Logger logger = Logger.getLogger(EventLifeMonitor.class); + private static final Log logger = LogFactory.getLog(EventLifeMonitor.class); - /* - * this class is used to hold an event while its in the queue and calculate - * how long it spent in the que before being processed. - */ + /* + * this class is used to hold an event while its in the queue and calculate + * how long it spent in the que before being processed. + */ - private final T theEvent; + private final T theEvent; - private final LogTime age; + private final LogTime age; - public EventLifeMonitor(final T event) - { - this.theEvent = event; - this.age = new LogTime(); - } + public EventLifeMonitor(final T event) + { + this.theEvent = event; + this.age = new LogTime(); + } - public void assessAge() - { - if (this.age.timeTaken() > 2000) - { - EventLifeMonitor.logger.warn("event age : " + this.age.timeTaken()); //$NON-NLS-1$ - } + public void assessAge() + { + if (this.age.timeTaken() > 2000) + { + EventLifeMonitor.logger.warn("event age : " + this.age.timeTaken()); //$NON-NLS-1$ + } - } + } - public T getEvent() - { - return this.theEvent; - } + public T getEvent() + { + return this.theEvent; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java index 3339e9ce1..f5a012f58 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java @@ -19,7 +19,7 @@ */ public class ManagerEventQueue // implements ManagerEventListener, Runnable { - // static Logger logger = Logger.getLogger(ManagerEventQueue.class); + // static Logger logger = LogFactory.getLog(getClass()); // // private final ManagerEventListener listener; // private boolean stop = false; diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java index 3f07e1bf3..57b1d0e4a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java @@ -5,12 +5,13 @@ import java.net.Socket; import java.net.UnknownHostException; -import org.apache.log4j.Logger; import org.asteriskjava.manager.AuthenticationFailedException; import org.asteriskjava.manager.ManagerConnection; import org.asteriskjava.manager.ManagerConnectionFactory; import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.AsteriskSettings; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /* * this class is a very thin wrapper around the manager connection class @@ -18,7 +19,7 @@ public class Connector { private ManagerConnection managerConnection; - static Logger logger = Logger.getLogger(Connector.class); + private static final Log logger = LogFactory.getLog(Connector.class); /** * Establishes a Asterisk ManagerConnection as well as performing the diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java index 1996b6dbd..342e4d11a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java @@ -5,7 +5,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; @@ -21,10 +20,12 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class Dial extends EventListenerBaseClass { - private final static Logger logger = Logger.getLogger(Dial.class); + private static final Log logger = LogFactory.getLog(Dial.class); private final OriginateResult result[] = new OriginateResult[2]; diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index b4213599f..855ddd6c9 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -4,7 +4,6 @@ import java.util.Map; import java.util.concurrent.TimeUnit; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; @@ -17,10 +16,12 @@ import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class DialToAgi extends EventListenerBaseClass { - private final static Logger logger = Logger.getLogger(DialToAgi.class); + private static final Log logger = LogFactory.getLog(DialToAgi.class); private final OriginateResult result[] = new OriginateResult[2]; diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java index 6cc7f2435..b0b23c0f4 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java @@ -2,54 +2,55 @@ import java.util.Date; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.asterisk.wrap.actions.MonitorAction; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class MonitorCall { - static Logger logger = Logger.getLogger(MonitorCall.class); + private static final Log logger = LogFactory.getLog(MonitorCall.class); - static long id = 1; + static long id = 1; - private String file = null; + private String file = null; - public MonitorCall(final Call call) - { - super(); + public MonitorCall(final Call call) + { + super(); - try - { - this.setFile(); - final MonitorAction monitorAction = new MonitorAction(call.getRemoteParty(), this.file, "gsm", true); //$NON-NLS-1$ + try + { + this.setFile(); + final MonitorAction monitorAction = new MonitorAction(call.getRemoteParty(), this.file, "gsm", true); //$NON-NLS-1$ - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - pbx.sendAction(monitorAction, 1000); + pbx.sendAction(monitorAction, 1000); - } - catch (final Exception e) - { - MonitorCall.logger.error(e, e); - } - } + } + catch (final Exception e) + { + MonitorCall.logger.error(e, e); + } + } - public String getFilename() - { - return this.file + ".gsm"; //$NON-NLS-1$ - } + public String getFilename() + { + return this.file + ".gsm"; //$NON-NLS-1$ + } - private synchronized void setFile() - { - long no = (new Date()).getTime(); - no = no / 1000; - final String unq = Long.toHexString(no); + private synchronized void setFile() + { + long no = (new Date()).getTime(); + no = no / 1000; + final String unq = Long.toHexString(no); - this.file = "njr" + unq + "-" + MonitorCall.id; //$NON-NLS-1$ //$NON-NLS-2$ - MonitorCall.id++; + this.file = "njr" + unq + "-" + MonitorCall.id; //$NON-NLS-1$ //$NON-NLS-2$ + MonitorCall.id++; - } + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 05e23530f..8e20f976f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -5,7 +5,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.apache.log4j.Logger; import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.CallerID; @@ -26,6 +25,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public abstract class OriginateBaseClass extends EventListenerBaseClass { @@ -36,7 +37,7 @@ public abstract class OriginateBaseClass extends EventListenerBaseClass * this class generates and issues ActionEvents to asterisk through the * manager. This is the asterisk coal face. */ - static Logger logger = Logger.getLogger(OriginateBaseClass.class); + protected static final Log logger = LogFactory.getLog(OriginateBaseClass.class); private volatile String originateID; diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java index 880ccb07b..9b3ef4e81 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java @@ -1,65 +1,63 @@ package org.asteriskjava.pbx.internal.managerAPI; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; public class OriginateResult { - static Logger logger = Logger.getLogger(OriginateResult.class); - private boolean channelHungup = false; + private boolean channelHungup = false; - private boolean success = false; + private boolean success = false; - private Channel newChannel = null; + private Channel newChannel = null; - private String abortReason; + private String abortReason; - OriginateResult() - { - // not used - } + OriginateResult() + { + // not used + } - public String getAbortReason() - { - return this.abortReason; - } + public String getAbortReason() + { + return this.abortReason; + } - void setAbortReason(final String reason) - { - this.abortReason = reason; + void setAbortReason(final String reason) + { + this.abortReason = reason; - } + } - public void setChannelData(final Channel channel) - { - this.newChannel = channel; - } + public void setChannelData(final Channel channel) + { + this.newChannel = channel; + } - public Channel getChannel() - { + public Channel getChannel() + { - return this.newChannel; - } + return this.newChannel; + } - public boolean isSuccess() - { - return this.success; - } + public boolean isSuccess() + { + return this.success; + } - public void setSuccess(boolean success) - { - this.success = success; - } + public void setSuccess(boolean success) + { + this.success = success; + } - public boolean isChannelHungup() - { - return this.channelHungup; - } + public boolean isChannelHungup() + { + return this.channelHungup; + } - public void setChannelHungup(boolean channel1Hungup) - { - this.channelHungup = channel1Hungup; - } + public void setChannelHungup(boolean channel1Hungup) + { + this.channelHungup = channel1Hungup; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java index 0d5e3e5e5..f10db39c5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java @@ -2,7 +2,6 @@ import java.util.HashMap; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Channel; @@ -12,6 +11,8 @@ import org.asteriskjava.pbx.agi.AgiChannelActivityDial; import org.asteriskjava.pbx.agi.AgiChannelActivityVoicemail; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class RedirectCall { @@ -19,7 +20,7 @@ public class RedirectCall * this class generates and issues ActionEvents to asterisk through the * manager. This is the asterisk coal face. */ - static Logger logger = Logger.getLogger(RedirectCall.class); + private static final Log logger = LogFactory.getLog(RedirectCall.class); static public void setAutoAnswer(final HashMap myVars, final AsteriskSettings settings) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java index 2a439b5b2..992683d89 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java @@ -1,15 +1,16 @@ package org.asteriskjava.pbx.internal.managerAPI; -import org.apache.log4j.Logger; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.agi.AgiChannelActivityMeetme; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class RedirectToMeetMe { - static Logger logger = Logger.getLogger(RedirectToMeetMe.class); + private static final Log logger = LogFactory.getLog(RedirectToMeetMe.class); public RedirectToMeetMe() { diff --git a/src/main/java/org/asteriskjava/util/Log.java b/src/main/java/org/asteriskjava/util/Log.java index 4c9ca4389..ea794260f 100644 --- a/src/main/java/org/asteriskjava/util/Log.java +++ b/src/main/java/org/asteriskjava/util/Log.java @@ -40,4 +40,6 @@ public interface Log void error(Object obj, Throwable exception); public boolean isDebugEnabled(); + + void debug(Object e, Throwable e2); } diff --git a/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java b/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java index c1967132e..61b1f3448 100644 --- a/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java +++ b/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java @@ -150,4 +150,19 @@ public boolean isDebugEnabled() return log.isLoggable(Level.FINE); } + @Override + public void debug(Object e, Throwable e2) + { + StackTraceElement ste = getInvokerSTE(); + + if (ste != null) + { + log.logp(Level.FINE, ste.getClassName(), ste.getMethodName(), e.toString(), e2); + } + else + { + log.log(Level.FINE, e.toString(), e2); + } + } + } diff --git a/src/main/java/org/asteriskjava/util/internal/NullLog.java b/src/main/java/org/asteriskjava/util/internal/NullLog.java index bf4d8f43c..ca6e1bff5 100644 --- a/src/main/java/org/asteriskjava/util/internal/NullLog.java +++ b/src/main/java/org/asteriskjava/util/internal/NullLog.java @@ -65,4 +65,10 @@ public boolean isDebugEnabled() { return false; } + + @Override + public void debug(Object e, Throwable e2) + { + + } } From 42a4e5b9991906fe8fb2ef1ec5ed169416c1ce5d Mon Sep 17 00:00:00 2001 From: SeeMirra Date: Mon, 3 Jul 2017 14:14:54 -0500 Subject: [PATCH 085/802] Update README.md Typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f207080af..34dcb3144 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The Asterisk-Java package consists of a set of Java classes that allow you to ea FastAGI ------- -FastAGI lets you create a service that manages a call in a similar way to what a webserver handles a http request. FastAGI can be (and should be) used to replace dialplan. FastAGI is thousands of times faster than dialplan, easier to debug and lets you do call control in a language that you are fimilar with. +FastAGI lets you create a service that manages a call in a similar way to what a webserver handles a http request. FastAGI can be (and should be) used to replace dialplan. FastAGI is thousands of times faster than dialplan, easier to debug and lets you do call control in a language that you are familiar with. The FastAGI implementation supports all commands currently available from Asterisk. From 954baf7dc13f54f0b70d0837b1611431d1c2462d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 19 Jul 2017 16:12:12 +1000 Subject: [PATCH 086/802] add configuration of agi host --- .../activities/ExamplesAsteriskSettings.java | 7 ++ .../asteriskjava/pbx/AsteriskSettings.java | 97 ++++++++++--------- .../pbx/internal/core/AsteriskPBX.java | 3 +- 3 files changed, 62 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java b/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java index 30c9d0b5f..b4abcced2 100644 --- a/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java +++ b/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java @@ -89,4 +89,11 @@ public boolean getCanDetectHangup() return false; } + @Override + public String getAgiHost() + { + // TODO Auto-generated method stub + return "127.0.0.1"; + } + } diff --git a/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java b/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java index f4944c213..e4f880577 100644 --- a/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java +++ b/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java @@ -3,97 +3,106 @@ public interface AsteriskSettings { - /** - * The port no. that the asterisk manager api listens on. - * This should be 5060 unless you have re-configured the manager api. - * @return the port no. - */ + /** + * The port no. that the asterisk manager api listens on. This should be + * 5060 unless you have re-configured the manager api. + * + * @return the port no. + */ int getManagerPortNo(); - /** - * This password MUST match the password (secret=) in manager.conf - * @return - */ + /** + * This password MUST match the password (secret=) in manager.conf + * + * @return + */ String getManagerPassword(); /** - * This MUST match the section header (e.g. '[myconnection]') in manager.conf + * This MUST match the section header (e.g. '[myconnection]') in + * manager.conf + * * @return */ String getManagerUsername(); /** * The IP address of FQND of the Asterisk PBX + * * @return IP address or FQDN. */ String getAsteriskIP(); - /** - * Asterisk-Java uses conference rooms for a variety of purposes. - * Just make certain that the base address doesn't overlap any conference - * rooms you are currently running on your pbx. - * You should probably allow 200 conference rooms here e.g. (3000-3200) - * Actions like transfers (and conference calls) use a conference room. + * Asterisk-Java uses conference rooms for a variety of purposes. Just make + * certain that the base address doesn't overlap any conference rooms you + * are currently running on your pbx. You should probably allow 200 + * conference rooms here e.g. (3000-3200) Actions like transfers (and + * conference calls) use a conference room. + * * @return meetme base address */ Integer getMeetmeBaseAddress(); - /** * Return true if you Asterisk version doesn't support bridging channels. - * All version after 1.8 support bridging so normally you should returm false; + * All version after 1.8 support bridging so normally you should returm + * false; * * @return false if you asterisk version supports bridging channels. */ boolean getDisableBridge(); - - - /** - * This is an asterisk dialplan context. - * Simply pick a context which doesn't already exist - * and use AsteriskPBX.createAgiEntryPoint() - * to inject the necessary dialplan used by asterisk-java - * @return an unused asterisk dialplan context. e.g. "asteriskjava" - */ + + /** + * This is an asterisk dialplan context. Simply pick a context which doesn't + * already exist and use AsteriskPBX.createAgiEntryPoint() to inject the + * necessary dialplan used by asterisk-java + * + * @return an unused asterisk dialplan context. e.g. "asteriskjava" + */ String getManagementContext(); /** - * Return an asterisk dialplan extension (within the above Management Context) - * that will be used to park calls. - * Just ensure that its a unique asterisk dialplan extension name. - */ + * Return an asterisk dialplan extension (within the above Management + * Context) that will be used to park calls. Just ensure that its a unique + * asterisk dialplan extension name. + */ String getExtensionPark(); /** - * The time (in seconds) to wait for a dial attempt to be answered before giving up. - * Recommend a value of 30. + * The time (in seconds) to wait for a dial attempt to be answered before + * giving up. Recommend a value of 30. + * * @return */ int getDialTimeout(); /** - * Return the SIP header to be used to force a handset to auto-answer when dialed. - * e.g. For Yealink/Snom use return "Call-Info:\; answer-after=0"; + * Return the SIP header to be used to force a handset to auto-answer when + * dialed. e.g. For Yealink/Snom use return "Call-Info:\; answer-after=0"; + * * @return */ String getAutoAnswer(); /** - * * Return an asterisk dialplan extension (within the Management Context) - * that will be used to inject the agi dialplan entry point used by Activites.. - * Just ensure that its a unique asterisk dialplan extension name. + * that will be used to inject the agi dialplan entry point used by + * Activites.. Just ensure that its a unique asterisk dialplan extension + * name. + * * @return "asterisk-java-agi" */ String getAgiExtension(); - - /** - * Return true if the telephony tech you are dialing from can reliably detect - * hangups. (for SIP set to true, POTS set false). - * @return - */ + /** + * Return true if the telephony tech you are dialing from can reliably + * detect hangups. (for SIP set to true, POTS set false). + * + * @return + */ boolean getCanDetectHangup(); + String getAgiHost(); + } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 55087d1b3..7ed6efacd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -885,8 +885,9 @@ public String createAgiEntryPoint() throws IOException, AuthenticationFailedExce AsteriskSettings profile = PBXFactory.getActiveProfile(); + String host = profile.getAgiHost(); String agi = profile.getAgiExtension(); - pbx.addAsteriskExtension(agi, 1, "AGI(agi://127.0.0.1/activityAgi), into " + profile.getManagementContext()); + pbx.addAsteriskExtension(agi, 1, "AGI(agi://" + host + "/activityAgi), into " + profile.getManagementContext()); pbx.addAsteriskExtension(agi, 2, "wait(0.5), into " + profile.getManagementContext()); pbx.addAsteriskExtension(agi, 3, "goto(" + agi + ",1), into " + profile.getManagementContext()); From dccf23344b0baa7fcefc2b18cc52803d129c9104 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 24 Jul 2017 15:18:02 +1000 Subject: [PATCH 087/802] fix for bridge activity --- .../internal/activity/BridgeActivityImpl.java | 2 ++ .../pbx/internal/core/AsteriskPBX.java | 17 +++++++++++---- .../core/CoherentManagerEventQueue.java | 21 +++++++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java index 197bb88b9..6d0b4ac0e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java @@ -15,6 +15,7 @@ import org.asteriskjava.pbx.agi.AgiChannelActivityBridge; import org.asteriskjava.pbx.agi.AgiChannelActivityHoldForBridge; import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; @@ -138,6 +139,7 @@ else if (pbx.isMeetmeInstalled()) required.add(StatusCompleteEvent.class); required.add(StatusEvent.class); required.add(BridgeEvent.class); + required.add(LinkEvent.class); return required; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 7ed6efacd..4c3d92447 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -733,8 +733,8 @@ static public String getSIPADDHeader(final boolean inherit, final boolean target @Override public boolean waitForChannelsToQuiescent(List channels, long timeout) { - - while (timeout > 0 && !channelsAreQuiesent(channels)) + long elapsed = 0; + while (elapsed < timeout && !channelsAreQuiesent(channels)) { try { @@ -744,10 +744,19 @@ public boolean waitForChannelsToQuiescent(List channels, long timeout) { logger.error(e, e); } - timeout -= 200; + logger.info("Waiting for channesl to Quiescent"); + elapsed += 200; } - return timeout > 0; + if (elapsed > timeout / 2) + { + logger.warn("Took " + elapsed + "ms for channels to Quiescent"); + } + if (elapsed >= timeout) + { + logger.error("Channels didn't Quiescent"); + } + return timeout > elapsed; } private boolean channelsAreQuiesent(List channels) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index fa8d06741..ee0cfc0f5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -9,7 +9,10 @@ import java.util.concurrent.TimeUnit; import org.asteriskjava.manager.ManagerEventListener; +import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.internal.eventQueue.EventLifeMonitor; import org.asteriskjava.pbx.util.LogTime; import org.asteriskjava.util.Log; @@ -39,6 +42,24 @@ public Listener(FilteredManagerListener listener) { this._listener = listener; this.requiredEvents = listener.requiredEvents(); + + for (Class< ? extends ManagerEvent> event : requiredEvents) + { + if (event == BridgeEvent.class) + { + // add LinkEvent and UnlinkEvent, as BridgeEvent only will + // miss some events + requiredEvents.add(LinkEvent.class); + requiredEvents.add(UnlinkEvent.class); + } + + if (!CoherentEventFactory.mapEvents.values().contains(event) + && !CoherentEventFactory.mapResponses.values().contains(event)) + { + throw new RuntimeException( + "The requested event type of " + event + "+isn't known by " + CoherentEventFactory.class); + } + } } @Override From 52dac90e8386e3ace2be35d2c70b7d65c7c88c9b Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 25 Jul 2017 16:35:36 +1000 Subject: [PATCH 088/802] bug fix for co-mod and adjust logging level --- .../pbx/asterisk/wrap/events/RenameEvent.java | 2 +- .../internal/core/CoherentManagerEventQueue.java | 16 ++++++++-------- .../pbx/internal/core/LiveChannelManager.java | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java index 6a175ee3c..3f122000d 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java @@ -33,7 +33,7 @@ public RenameEvent(final org.asteriskjava.manager.event.RenameEvent event) throw this._newName = event.getNewname(); String uniqueId = ((ChannelProxy) this._channel).getRealChannel().getUniqueId(); - logger.error("Renaming :" + uniqueId + " " + event.getUniqueId()); + logger.debug("Renaming :" + uniqueId + " " + event.getUniqueId()); assert uniqueId.equalsIgnoreCase("-1") || uniqueId.compareToIgnoreCase(event.getUniqueId()) == 0 : "Rename registered against incorrect channel"; //$NON-NLS-1$ diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index ee0cfc0f5..5ac5ef7f0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -43,16 +43,16 @@ public Listener(FilteredManagerListener listener) this._listener = listener; this.requiredEvents = listener.requiredEvents(); - for (Class< ? extends ManagerEvent> event : requiredEvents) + if (requiredEvents.contains(BridgeEvent.class)) { - if (event == BridgeEvent.class) - { - // add LinkEvent and UnlinkEvent, as BridgeEvent only will - // miss some events - requiredEvents.add(LinkEvent.class); - requiredEvents.add(UnlinkEvent.class); - } + // add LinkEvent and UnlinkEvent, as BridgeEvent only will + // miss some events + requiredEvents.add(LinkEvent.class); + requiredEvents.add(UnlinkEvent.class); + } + for (Class< ? extends ManagerEvent> event : requiredEvents) + { if (!CoherentEventFactory.mapEvents.values().contains(event) && !CoherentEventFactory.mapResponses.values().contains(event)) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index 1add25e1d..03e79b963 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -164,10 +164,10 @@ public ChannelProxy findChannel(String extendedChannelName, String uniqueID) if (proxy == null) { - logger.info("Failed to match channel to any of..."); + logger.debug("Failed to match channel to any of..."); for (ChannelProxy aChannel : _liveChannels) { - logger.info(aChannel); + logger.debug(aChannel); } } From 2f4acfd8219c317593ffaaed5b69d8542c0bef2b Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 28 Jul 2017 17:12:55 +1000 Subject: [PATCH 089/802] protect channely proxy from duplicate listeners --- .../org/asteriskjava/pbx/internal/core/ChannelProxy.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index 9a0be3a8e..1c5621061 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -125,13 +125,17 @@ public boolean isLive() @Override public void addHangupListener(ChannelHangupListener listener) { - this.listeners.add(listener); + if (!listeners.contains(listener)) + { + this.listeners.add(listener); + } } @Override public void removeListener(ChannelHangupListener listener) { + this.listeners.remove(listener); } From cbb8f8f92ac5ab742b04cf82bc650c295229b123 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 31 Jul 2017 13:48:22 +1000 Subject: [PATCH 090/802] fix checks for missing dialplan --- .../pbx/internal/core/AsteriskPBX.java | 47 +++++++++++++++---- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 4c3d92447..3818793bb 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -72,6 +72,7 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener SELF; + public static final String ACTIVITY_AGI = "activityAgi"; private final Log logger = LogFactory.getLog(getClass()); private boolean muteSupported; private boolean bridgeSupport; @@ -878,36 +879,62 @@ public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, Agi * * @param profile * @param dialContext - * @return + * @return success or failure * @throws IllegalStateException * @throws IOException * @throws AuthenticationFailedException * @throws TimeoutException */ - public String createAgiEntryPoint() throws IOException, AuthenticationFailedException, TimeoutException + public boolean createAgiEntryPoint() throws IOException, AuthenticationFailedException, TimeoutException { try { AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - AsteriskSettings profile = PBXFactory.getActiveProfile(); + if (!checkDialplanExists(profile)) - String host = profile.getAgiHost(); - String agi = profile.getAgiExtension(); - pbx.addAsteriskExtension(agi, 1, "AGI(agi://" + host + "/activityAgi), into " + profile.getManagementContext()); - pbx.addAsteriskExtension(agi, 2, "wait(0.5), into " + profile.getManagementContext()); - pbx.addAsteriskExtension(agi, 3, "goto(" + agi + ",1), into " + profile.getManagementContext()); + { + String host = profile.getAgiHost(); + String agi = profile.getAgiExtension(); + pbx.addAsteriskExtension(agi, 1, + "AGI(agi://" + host + "/" + ACTIVITY_AGI + "), into " + profile.getManagementContext()); + pbx.addAsteriskExtension(agi, 2, "wait(0.5), into " + profile.getManagementContext()); + pbx.addAsteriskExtension(agi, 3, "goto(" + agi + ",1), into " + profile.getManagementContext()); + + return checkDialplanExists(profile); + } + return true; } catch (Exception e) { logger.error(e); - return e.getLocalizedMessage(); + return false; + } + + } + + public boolean checkDialplanExists(AsteriskSettings profile) + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException + { + String ext = "show dialplan " + profile.getManagementContext(); + + CommandAction action = new CommandAction(ext); + CommandResponse response = (CommandResponse) sendAction(action, 30000); + + boolean exists = false; + for (String line : response.getResult()) + { + if (line.contains(ACTIVITY_AGI)) + { + exists = true; + break; + } } - return null; + return exists; } From f9ab4f1c8432ed18df4d8aa9cfce56bff084c965 Mon Sep 17 00:00:00 2001 From: karsten Date: Mon, 31 Jul 2017 10:41:06 +0200 Subject: [PATCH 091/802] added import changed from log4j-logger to asterisk.util.Log --- .../org/asteriskjava/fastagi/HangupTest.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java b/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java index cb0abe5ec..c5ab9f865 100644 --- a/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java +++ b/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java @@ -1,16 +1,17 @@ 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; +import org.asteriskjava.live.DefaultAsteriskServer; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + public class HangupTest extends BaseAgiScript { - private Logger logger = LogFactory.getLog(getClass()); + private Log logger = LogFactory.getLog(getClass()); public void service(AgiRequest request, AgiChannel channel) throws AgiException { @@ -27,7 +28,7 @@ public void service(AgiRequest request, AgiChannel channel) throws AgiException } catch (Exception e) { - logger.info("Exception caught: " + e.getMessage(), e); + logger.error("Exception caught: " + e.getMessage(), e); } } From 83b65cd2670d1febae35e5aeeca05fd8ae5ee959 Mon Sep 17 00:00:00 2001 From: karsten Date: Mon, 31 Jul 2017 10:45:31 +0200 Subject: [PATCH 092/802] RtcpReceivedEvent: flag report0iaJitter changed from Integer to Long --- .../org/asteriskjava/manager/event/RtcpReceivedEvent.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java b/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java index 1c50c2a98..7baf0f440 100644 --- a/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java @@ -66,7 +66,7 @@ public class RtcpReceivedEvent extends AbstractRtcpEvent private Integer reportCount; private Integer report0CumulativeLost; private Integer report0FractionLost; - private Integer report0iaJitter; + private Long report0iaJitter; private Integer report0HighestSequence; private InetAddress toAddress; private Integer toPort; @@ -364,12 +364,12 @@ public void setReport0FractionLost(Integer report0FractionLost) this.report0FractionLost = report0FractionLost; } - public Integer getReport0iaJitter() + public Long getReport0iaJitter() { return report0iaJitter; } - public void setReport0iaJitter(Integer report0iaJitter) + public void setReport0iaJitter(Long report0iaJitter) { this.report0iaJitter = report0iaJitter; } From aa00dfc2fc702600a990af9e548d0907cf069bf4 Mon Sep 17 00:00:00 2001 From: karsten Date: Mon, 31 Jul 2017 11:02:04 +0200 Subject: [PATCH 093/802] Revert "added import changed from log4j-logger to asterisk.util.Log" This reverts commit f9ab4f1c8432ed18df4d8aa9cfce56bff084c965. --- .../org/asteriskjava/fastagi/HangupTest.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java b/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java index c5ab9f865..cb0abe5ec 100644 --- a/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java +++ b/src/integrationtest/org/asteriskjava/fastagi/HangupTest.java @@ -1,17 +1,16 @@ 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; -import org.asteriskjava.live.DefaultAsteriskServer; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; - public class HangupTest extends BaseAgiScript { - private Log logger = LogFactory.getLog(getClass()); + private Logger logger = LogFactory.getLog(getClass()); public void service(AgiRequest request, AgiChannel channel) throws AgiException { @@ -28,7 +27,7 @@ public void service(AgiRequest request, AgiChannel channel) throws AgiException } catch (Exception e) { - logger.error("Exception caught: " + e.getMessage(), e); + logger.info("Exception caught: " + e.getMessage(), e); } } From fe4bf28b4541f3bf54c9a16fa779ef8a70166f3f Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 2 Aug 2017 10:23:35 +1000 Subject: [PATCH 094/802] add redirectToActivity action to pbx --- src/main/java/org/asteriskjava/pbx/PBX.java | 7 +- .../pbx/activities/RedirectToActivity.java | 19 ++ .../activity/RedirectToActivityImpl.java | 202 ++++++++++++++++++ .../pbx/internal/core/AsteriskPBX.java | 9 + 4 files changed, 235 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/activities/RedirectToActivity.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java diff --git a/src/main/java/org/asteriskjava/pbx/PBX.java b/src/main/java/org/asteriskjava/pbx/PBX.java index d36a4a14c..0258b1985 100644 --- a/src/main/java/org/asteriskjava/pbx/PBX.java +++ b/src/main/java/org/asteriskjava/pbx/PBX.java @@ -8,6 +8,7 @@ import org.asteriskjava.pbx.activities.HoldActivity; import org.asteriskjava.pbx.activities.JoinActivity; import org.asteriskjava.pbx.activities.ParkActivity; +import org.asteriskjava.pbx.activities.RedirectToActivity; import org.asteriskjava.pbx.activities.SplitActivity; /** @@ -131,9 +132,10 @@ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID /** * Hangup the given call, not returning until the call is hungup. + * * @param call */ - public void hangup(Call call) throws PBXException; + public void hangup(Call call) throws PBXException; /** * Put the given channel on hold. @@ -207,6 +209,8 @@ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID public SplitActivity split(final Call callToSplit, final ActivityCallback listener) throws PBXException; + public RedirectToActivity redirectToActivity(final Channel channel, final ActivityCallback listener); + public void split(final Call callToSplit) throws PBXException; /** @@ -276,5 +280,4 @@ public void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandC public Trunk buildTrunk(String string); - } diff --git a/src/main/java/org/asteriskjava/pbx/activities/RedirectToActivity.java b/src/main/java/org/asteriskjava/pbx/activities/RedirectToActivity.java new file mode 100644 index 000000000..ff2342b46 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/activities/RedirectToActivity.java @@ -0,0 +1,19 @@ +package org.asteriskjava.pbx.activities; + +import org.asteriskjava.pbx.Activity; +import org.asteriskjava.pbx.Call; + +public interface RedirectToActivity extends Activity +{ + + /** + * After a call has been split we get a new calls. The call created as a + * result of the lhsOperandChannel being split can be retrieved by calling + * this method. + * + * @return the call which holds the call associated with the + * lhsOperandChannel + */ + Call getCall(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java new file mode 100644 index 000000000..2986ebdba --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java @@ -0,0 +1,202 @@ +package org.asteriskjava.pbx.internal.activity; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.AsteriskSettings; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.CallDirection; +import org.asteriskjava.pbx.CallImpl; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.activities.RedirectToActivity; +import org.asteriskjava.pbx.agi.AgiChannelActivityHold; +import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.pbx.internal.core.ChannelProxy; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +/** + * The SplitActivity is used by the AsteriksPBX to split a call and place the + * component channels into the specialist Activity fastagi. The SplitActivity + * can only split a call with two channels. The (obvious?) limitation is that we + * can't split something in a conference call as it has more than two channels. + * + * @author bsutton + */ +public class RedirectToActivityImpl extends ActivityHelper implements RedirectToActivity +{ + private static final Log logger = LogFactory.getLog(RedirectToActivityImpl.class); + + private Channel channel1; + + private Call _lhsCall; + + /** + * Splits a call by moving each of its two channels into the Activity agi. + * The channels will sit in the agi (with no audio) until something is done + * with them. As such you should leave them split for too long. + * + * @param callToSplit The call to split + * @param listener + */ + public RedirectToActivityImpl(final Channel channel1, final ActivityCallback listener) + { + super("SplitActivity", listener); //$NON-NLS-1$ + + this.channel1 = channel1; + + this.startActivity(true); + } + + @Override + public boolean doActivity() throws PBXException + { + + RedirectToActivityImpl.logger + .info("*******************************************************************************"); //$NON-NLS-1$ + RedirectToActivityImpl.logger + .info("*********** begin redirect to activity ****************"); //$NON-NLS-1$ + RedirectToActivityImpl.logger.info("*********** " + this.channel1 + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ + RedirectToActivityImpl.logger + .info("*******************************************************************************"); //$NON-NLS-1$ + + // Splits the originating and secondary channels by moving each of them + // into the associated + // target. + boolean success = false; + + if (this.channel1 != null) + { + success = splitTwo(); + + // Now update the call to reflect the split + if (success) + { + this._lhsCall = new CallImpl(channel1, CallDirection.OUTBOUND); + } + } + return success; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + // No events required. + return required; + } + + @Override + synchronized public void onManagerEvent(final ManagerEvent event) + { + // NOOP + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + /** + * After a call has been split we get two new calls. One will hold the + * original remote party and the other will hold the original local party. + * + * @return the call which holds the original remote party. + */ + @Override + public Call getCall() + { + return this._lhsCall; + } + + /** + * After a call has been split we get two new calls. One will hold the + * original remote party and the other will hold the original local party. + * + * @return the call which holds the original local party. + */ + + /** + * Splits two channels moving them to defined endpoints. + * + * @param lhs + * @param lhsTarget + * @param lhsTargetContext + * @param rhs + * @param rhsTarget + * @param rhsTargetContext + * @return + * @throws PBXException + */ + private boolean splitTwo() throws PBXException + { + final AsteriskSettings profile = PBXFactory.getActiveProfile(); + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + List channels = new LinkedList<>(); + channels.add(channel1); + if (!pbx.waitForChannelsToQuiescent(channels, 3000)) + { + logger.error(callSite, callSite); + throw new PBXException("Channel: " + channel1 + " cannot be split as they are still in transition."); + } + + /* + * redirects the specified channels to the specified endpoints. Returns + * true or false reflecting success. + */ + + AgiChannelActivityHold agi1 = new AgiChannelActivityHold(); + + pbx.setVariable(channel1, "proxyId", "" + ((ChannelProxy) channel1).getIdentity()); + + channel1.setCurrentActivityAction(agi1); + + final String agiExten = profile.getAgiExtension(); + final String agiContext = profile.getManagementContext(); + logger.debug("redirect channel lhs:" + channel1 + " to " + agiExten + " in context " + agiContext); + + final EndPoint extensionAgi = pbx.getExtensionAgi(); + final RedirectAction redirect = new RedirectAction(channel1, agiContext, extensionAgi, 1); + // logger.error(redirect); + + boolean ret = false; + { + try + { + + // final ManagerResponse response = + pbx.sendAction(redirect, 1000); + double ctr = 0; + while (!agi1.hasCallReachedAgi() && ctr < 10) + { + Thread.sleep(100); + ctr += 100.0 / 1000.0; + if (!agi1.hasCallReachedAgi()) + { + logger.error("Waiting on (agi1) " + channel1); + } + + } + ret = agi1.hasCallReachedAgi(); + + } + catch (final Exception e) + { + logger.error(e, e); + } + } + return ret; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 3818793bb..e9e1acb11 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -39,6 +39,7 @@ import org.asteriskjava.pbx.activities.HoldActivity; import org.asteriskjava.pbx.activities.JoinActivity; import org.asteriskjava.pbx.activities.ParkActivity; +import org.asteriskjava.pbx.activities.RedirectToActivity; import org.asteriskjava.pbx.activities.SplitActivity; import org.asteriskjava.pbx.agi.AgiChannelActivityHangup; import org.asteriskjava.pbx.agi.AgiChannelActivityHold; @@ -59,6 +60,7 @@ import org.asteriskjava.pbx.internal.activity.HoldActivityImpl; import org.asteriskjava.pbx.internal.activity.JoinActivityImpl; import org.asteriskjava.pbx.internal.activity.ParkActivityImpl; +import org.asteriskjava.pbx.internal.activity.RedirectToActivityImpl; import org.asteriskjava.pbx.internal.activity.SplitActivityImpl; import org.asteriskjava.pbx.internal.asterisk.CallerIDImpl; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; @@ -194,6 +196,13 @@ public SplitActivity split(final Call callToSplit, final ActivityCallback listener) + { + + return new RedirectToActivityImpl(channel, listener); + } + /** * Joins two calls not returning until the join completes. The join will * complete almost immediately as it is a simple bridging of two active From a0493071ea1076c4918b6a1f682880697c3f156e Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 4 Aug 2017 11:47:13 +1000 Subject: [PATCH 095/802] reduce logging --- .../java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index e9e1acb11..9d4d34ed4 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -539,7 +539,7 @@ public Channel registerChannel(final String channelName, final String uniqueID) { if (uniqueID != null && !uniqueID.equals(proxy.getUniqueId())) { - logger.warn( + logger.info( "Found the channel(" + proxy.getUniqueId() + "), but with a different uniqueId (" + uniqueID + ")"); } From e6d1fafc0e1d40b159036c8a3bbaae8498857a62 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 7 Aug 2017 13:27:44 +1000 Subject: [PATCH 096/802] fix for issue setting up CoherentManagerConnection --- .../java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java | 4 +--- .../pbx/internal/core/CoherentManagerConnection.java | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 9d4d34ed4..934cabb41 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -81,7 +81,7 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener private static final int MAX_MEETME_ROOMS = 50; - private LiveChannelManager liveChannels; + private final LiveChannelManager liveChannels = new LiveChannelManager(); AsteriskPBX() { @@ -101,8 +101,6 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener logger.error(e, e); } - this.liveChannels = new LiveChannelManager(); - } catch (IllegalStateException | IOException | AuthenticationFailedException | TimeoutException e1) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java index 52ee84daf..1c7d5f63b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -122,6 +122,7 @@ public static synchronized void init() else { self = new CoherentManagerConnection(); + self.checkConnection(); self.checkFeatures(); } From 52a039cc2056ef0502dd38d443e28a33801e238c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 7 Aug 2017 14:01:33 +1000 Subject: [PATCH 097/802] correct initialization order --- .../java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 934cabb41..2543f4053 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -81,7 +81,7 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener private static final int MAX_MEETME_ROOMS = 50; - private final LiveChannelManager liveChannels = new LiveChannelManager(); + private LiveChannelManager liveChannels; AsteriskPBX() { @@ -91,7 +91,7 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener this.muteSupported = CoherentManagerConnection.getInstance().isMuteAudioSupported(); this.bridgeSupport = CoherentManagerConnection.getInstance().isBridgeSupported(); - + liveChannels = new LiveChannelManager(); try { MeetmeRoomControl.init(this, AsteriskPBX.MAX_MEETME_ROOMS); From 0ac04332681b247ee5a17d0babaf2438a9cbe870 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 8 Aug 2017 14:31:46 +1000 Subject: [PATCH 098/802] fix to correctly set the callerId on BlindTransferActivity --- .../pbx/agi/AgiChannelActivityBlindTransfer.java | 5 ++++- .../pbx/internal/activity/BlindTransferActivityImpl.java | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java index 2ec97797e..350184a6c 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java @@ -14,11 +14,13 @@ public class AgiChannelActivityBlindTransfer implements AgiChannelActivityAction private String target; private String sipHeader; int timeout = 30; + private String callerId; - public AgiChannelActivityBlindTransfer(String fullyQualifiedName, String sipHeader) + public AgiChannelActivityBlindTransfer(String fullyQualifiedName, String sipHeader, String callerId) { this.target = fullyQualifiedName; this.sipHeader = sipHeader; + this.callerId = callerId; if (sipHeader == null) { this.sipHeader = ""; @@ -30,6 +32,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I { channel.setVariable("__SIPADDHEADER", sipHeader); + channel.setCallerId(callerId); ichannel.setCurrentActivityAction(new AgiChannelActivityHold()); channel.dial(target, timeout, ""); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index 5a71bf575..930452697 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -150,8 +150,8 @@ public boolean doActivity() throws PBXException { sipHeader = PBXFactory.getActiveProfile().getAutoAnswer(); } - actualChannelToTransfer.setCurrentActivityAction( - new AgiChannelActivityBlindTransfer(this._transferTarget.getFullyQualifiedName(), sipHeader)); + actualChannelToTransfer.setCurrentActivityAction(new AgiChannelActivityBlindTransfer( + this._transferTarget.getFullyQualifiedName(), sipHeader, _toCallerID.getNumber())); // TODO: At one point we were adding the /n option to the end of the // channel to get around From da072bd735bebbc6e5fd756f1e0d16fc8e46402f Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 8 Aug 2017 17:12:14 +1000 Subject: [PATCH 099/802] add clean up for old local channels --- .../asteriskjava/pbx/agi/AgiChannelActivityHold.java | 11 +++++++++++ .../pbx/internal/core/LiveChannelManager.java | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java index efb5df319..3da0ba121 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java @@ -17,6 +17,7 @@ public class AgiChannelActivityHold implements AgiChannelActivityAction CountDownLatch latch = new CountDownLatch(1); volatile boolean callReachedAgi = false; + long timer = System.currentTimeMillis(); @Override public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException @@ -38,6 +39,16 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I logger.warn(e); } } + else + { + long secondsOnHold = Math.abs(System.currentTimeMillis() - timer) / 1000; + if (channel.getName().startsWith("Local") && secondsOnHold > 3600) + { + // cleanup Local channels older than 1 hour + logger.error("Hanging up local channel that has been on hold for 1 hour " + channel.getName()); + channel.hangup(); + } + } } catch (AgiHangupException e) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index 03e79b963..0f148b8a9 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -123,7 +123,7 @@ public void remove(ChannelProxy proxy) public ChannelProxy findChannel(String extendedChannelName, String uniqueID) { ChannelProxy proxy = null; - logger.info("Trying to find channel " + extendedChannelName + " " + uniqueID); + logger.debug("Trying to find channel " + extendedChannelName + " " + uniqueID); String localUniqueId = uniqueID; if (localUniqueId == null) @@ -308,7 +308,7 @@ else if (event instanceof HangupEvent) if (proxy != null) { this._liveChannels.remove(proxy); - logger.info("Removing liveChannel " + proxy); + logger.debug("Removing liveChannel " + proxy); proxy.getChannel().notifyHangupListeners(hangup.getCause(), hangup.getCauseTxt()); dumpProxies(proxy, "HangupEvent"); //$NON-NLS-1$ } From 6f0b24084b4c8f84309afccb92cb6ff85a06d84e Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 9 Aug 2017 10:45:37 +1000 Subject: [PATCH 100/802] cleanup pbx/agi/config --- .../org/asteriskjava/pbx/agi/ActivityAgi.java | 8 +-- .../pbx/agi/config/AgiMappingStragegy.java | 12 ++-- .../pbx/agi/config/ConfiguableAGIServer.java | 2 +- .../pbx/agi/config/ServiceAgiScript.java | 55 ++--------------- .../pbx/agi/config/ServiceAgiScriptImpl.java | 59 +++++++++++++++++++ .../asterisk/wrap/actions/RedirectAction.java | 4 +- .../pbx/internal/core/AsteriskPBX.java | 2 +- .../pbx/internal/core/ChannelImpl.java | 6 +- .../pbx/internal/core/ChannelProxy.java | 6 +- .../pbx/internal/core/LiveChannelManager.java | 2 +- 10 files changed, 83 insertions(+), 73 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScriptImpl.java diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index 5d9662054..acab6d8b4 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -7,12 +7,12 @@ import org.asteriskjava.pbx.ChannelHangupListener; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.agi.config.ServiceAgiScript; +import org.asteriskjava.pbx.agi.config.ServiceAgiScriptImpl; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public abstract class ActivityAgi extends ServiceAgiScript +public abstract class ActivityAgi extends ServiceAgiScriptImpl { private final Log logger = LogFactory.getLog(this.getClass()); @@ -71,7 +71,7 @@ public void channelHangup(Channel channel, Integer cause, String causeText) action.execute(this.channel, channelProxy); action = channelProxy.getCurrentActivityAction(); - logger.info("Action for proxy " + channelProxy + " is " + action.getClass().getSimpleName()); + logger.debug("Action for proxy " + channelProxy + " is " + action.getClass().getSimpleName()); isAlive = checkChannelIsStillUp(); rateLimiter.acquire(); } @@ -86,7 +86,7 @@ public void channelHangup(Channel channel, Integer cause, String causeText) logger.error(e, e); } - logger.info("Channel leaving agi " + channelName); + logger.debug("Channel leaving agi " + channelName); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java b/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java index b89d6c7cc..94a6f63e6 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java @@ -61,17 +61,17 @@ public AgiScript determineScript(AgiRequest request, AgiChannel channel) script = script.substring(1); } Iterator itr = request.getParameterMap().keySet().iterator(); - logger.info("*********************************"); - logger.info("script " + script); + logger.debug("*********************************"); + logger.debug("script " + script); while (itr.hasNext()) { String key = itr.next(); String val = request.getParameter(key); if (key.compareToIgnoreCase("cardNumber") == 0) val = "suppressed"; - logger.info(key + ": " + val); + logger.debug(key + ": " + val); } - logger.info("******"); + logger.debug("******"); if (handlers.containsKey(script)) { @@ -81,12 +81,10 @@ public AgiScript determineScript(AgiRequest request, AgiChannel channel) } catch (InstantiationException e) { - // TODO Auto-generated catch block logger.error(e, e); } catch (IllegalAccessException e) { - // TODO Auto-generated catch block logger.error(e, e); } } @@ -104,7 +102,7 @@ public AgiScript determineScript(AgiRequest request, AgiChannel channel) * @throws InstantiationException */ @SuppressWarnings("unchecked") - public void addNoojeeAgiHandler(Class< ? extends ServiceAgiScript> handler) + public void addServiceAgiScript(Class< ? extends ServiceAgiScript> handler) throws DuplicateScriptException, InstantiationException, IllegalAccessException { diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java b/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java index bb9c6ebb2..f981a5ed4 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java @@ -49,7 +49,7 @@ private void loadHandlers(AgiMappingStragegy mappingStrategy, AgiConfiguration c List> handlers = configuration.getAgiHandlers(); for (Class< ? extends ServiceAgiScript> clazz : handlers) { - mappingStrategy.addNoojeeAgiHandler(clazz); + mappingStrategy.addServiceAgiScript(clazz); } } diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScript.java b/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScript.java index be1a888e6..23f29de2d 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScript.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScript.java @@ -1,59 +1,12 @@ package org.asteriskjava.pbx.agi.config; -import org.asteriskjava.fastagi.AgiChannel; -import org.asteriskjava.fastagi.AgiException; -import org.asteriskjava.fastagi.AgiRequest; -import org.asteriskjava.fastagi.BaseAgiScript; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; +import org.asteriskjava.fastagi.AgiScript; -/** - * Allows for auto configuration of the AGI script.
- *
- * Provides a getParameter(..) method which verifies the existence of the - * parameter.
- *
- * Requires an implementing agi to provide it's name and parameter list via - * getScriptName() and getParameters. - * - * @author rsutton - */ -abstract public class ServiceAgiScript extends BaseAgiScript +public interface ServiceAgiScript extends AgiScript { - static transient Log logger = LogFactory.getLog(ServiceAgiScript.class); - protected AgiRequest request; - protected AgiChannel channel; - public synchronized void service(AgiRequest request, AgiChannel channel) throws AgiException - { - this.request = request; - this.channel = channel; - service(); - } + String getScriptName(); - /** - * field variables request and channel will be set prior to calling - * service() AgiRequest request AgiChannel channel - * - * @throws AgiException - */ - - public abstract void service() throws AgiException; - - protected String required(String name, String parameter) throws AgiException - { - if (parameter == null || parameter.length() == 0) - throw new AgiException("Required parameter " + name + " missing."); - return parameter; - } - - protected String getParameter(String name) throws AgiException - { - return required(name, request.getParameter(name)); - } - - public abstract String getScriptName(); - - public abstract String[] getParameters(); + String[] getParameters(); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScriptImpl.java b/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScriptImpl.java new file mode 100644 index 000000000..286114f7e --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScriptImpl.java @@ -0,0 +1,59 @@ +package org.asteriskjava.pbx.agi.config; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiRequest; +import org.asteriskjava.fastagi.BaseAgiScript; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +/** + * Allows for auto configuration of the AGI script.
+ *
+ * Provides a getParameter(..) method which verifies the existence of the + * parameter.
+ *
+ * Requires an implementing agi to provide it's name and parameter list via + * getScriptName() and getParameters. + * + * @author rsutton + */ +abstract public class ServiceAgiScriptImpl extends BaseAgiScript implements ServiceAgiScript +{ + static transient Log logger = LogFactory.getLog(ServiceAgiScriptImpl.class); + protected AgiRequest request; + protected AgiChannel channel; + + public synchronized void service(AgiRequest request, AgiChannel channel) throws AgiException + { + this.request = request; + this.channel = channel; + service(); + } + + /** + * field variables request and channel will be set prior to calling + * service() AgiRequest request AgiChannel channel + * + * @throws AgiException + */ + + public abstract void service() throws AgiException; + + protected String required(String name, String parameter) throws AgiException + { + if (parameter == null || parameter.length() == 0) + throw new AgiException("Required parameter " + name + " missing."); + return parameter; + } + + protected String getParameter(String name) throws AgiException + { + return required(name, request.getParameter(name)); + } + + public abstract String getScriptName(); + + public abstract String[] getParameters(); + +} diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/RedirectAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/RedirectAction.java index 32c067f57..52805adfa 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/RedirectAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/RedirectAction.java @@ -51,12 +51,12 @@ public org.asteriskjava.manager.action.ManagerAction getAJAction() { final org.asteriskjava.manager.action.RedirectAction action = new org.asteriskjava.manager.action.RedirectAction(); action.setActionId(this.getActionId()); - action.setChannel(this._channel.getChannelName()); + action.setChannel(this._channel.getChannelName().toLowerCase()); action.setContext(this._context); action.setExten(this._exten.getFullyQualifiedName()); action.setPriority(this._priority); if (this._extraChannel != null) - action.setExtraChannel(this._extraChannel.getChannelName()); + action.setExtraChannel(this._extraChannel.getChannelName().toLowerCase()); action.setExtraContext(this._extraContext); if (this._extraExten != null) action.setExtraExten(this._extraExten.getFullyQualifiedName()); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 2543f4053..c77c94393 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -569,7 +569,7 @@ public Channel internalRegisterChannel(final String channelName, final String un if (proxy == null) { proxy = new ChannelProxy(new ChannelImpl(channelName, localUniqueID)); - logger.info("Creating new Channel Proxy " + proxy); + logger.debug("Creating new Channel Proxy " + proxy); this.liveChannels.add(proxy); proxy.addHangupListener(this); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index c391cabe9..68da48cf1 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -178,7 +178,7 @@ public class ChannelImpl implements Channel if (uniqueID.compareToIgnoreCase("-1") == 0) { - logger.info("uniqueID is -1"); + logger.debug("uniqueID is -1"); } this._uniqueID = uniqueID; @@ -228,7 +228,7 @@ else if (this._callerID != null && ((ChannelImpl) channel)._callerID != null) private void setChannelName(final String channelName) throws InvalidChannelName { - logger.info("Renamed channel from " + this._channelName + " to " + channelName); + logger.debug("Renamed channel from " + this._channelName + " to " + channelName); this._channelName = this.cleanChannelName(channelName); this.validateChannelName(this._channelName); @@ -355,7 +355,7 @@ private String cleanChannelName(final String name) } if (wasInAction != this._isInAction) { - logger.info("Channel " + this + " : inaction status changed from " + wasInAction + " to " + this._isInAction); + logger.debug("Channel " + this + " : inaction status changed from " + wasInAction + " to " + this._isInAction); } // Channels can be marked as in a zombie state diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index 1c5621061..e266844ac 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -226,7 +226,7 @@ public void masquerade(ChannelProxy cloneProxy) throws InvalidChannelName this._channel.addHangupListener(this); cloneProxy._channel.addHangupListener(cloneProxy); - logger.info(originalChannel + " Channel proxy now points to " + this._channel); + logger.debug(originalChannel + " Channel proxy now points to " + this._channel); } public ChannelImpl getRealChannel() @@ -338,7 +338,7 @@ public void setCurrentActivityAction(AgiChannelActivityAction action) { AgiChannelActivityAction previousAction = currentActivityAction.get(); - logger.info("Setting action to " + action.getClass().getSimpleName() + " for " + this); + logger.debug("Setting action to " + action.getClass().getSimpleName() + " for " + this); // Exception e = new Exception("Setting action to " + // action.getClass().getSimpleName() + " for " + this); @@ -360,7 +360,7 @@ public void setIsInAgi(boolean b) hasReachedAgi.countDown(); } isInAgi = b; - logger.info("Setting is in agi to " + b + " for channel " + this); + logger.debug("Setting is in agi to " + b + " for channel " + this); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index 0f148b8a9..afa508330 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -88,7 +88,7 @@ public void add(ChannelProxy proxy) if (index == null) this._liveChannels.add(proxy); } - logger.info("Adding liveChannel " + proxy); + logger.debug("Adding liveChannel " + proxy); dumpProxies(proxy, "Add"); //$NON-NLS-1$ sanityCheck(); From 558d117b10e3b5e6d2d951c9c903779905deecd1 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 10 Aug 2017 10:38:36 +1000 Subject: [PATCH 101/802] reduce logging levels --- .../internal/AgiConnectionHandler.java | 43 +++++++++++-------- .../pbx/agi/AgiChannelActivityHold.java | 7 ++- .../pbx/agi/config/AgiMappingStragegy.java | 5 +-- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java index 3d20b8626..5d5a0e6aa 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java @@ -16,16 +16,16 @@ */ package org.asteriskjava.fastagi.internal; -import org.asteriskjava.fastagi.AgiWriter; -import org.asteriskjava.fastagi.AgiReader; -import org.asteriskjava.fastagi.AgiChannelFactory; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiChannelFactory; import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiReader; import org.asteriskjava.fastagi.AgiRequest; import org.asteriskjava.fastagi.AgiScript; +import org.asteriskjava.fastagi.AgiWriter; import org.asteriskjava.fastagi.MappingStrategy; import org.asteriskjava.fastagi.NamedAgiScript; import org.asteriskjava.fastagi.command.VerboseCommand; @@ -34,8 +34,7 @@ /** * An AgiConnectionHandler is created and run by the AgiServer whenever a new - * AGI connection from an Asterisk Server is received. - *
+ * AGI connection from an Asterisk Server is received.
* It reads the request using an AgiReader and runs the AgiScript configured to * handle this type of request. Finally it closes the AGI connection. * @@ -54,9 +53,8 @@ public abstract class AgiConnectionHandler implements Runnable private AgiScript script = null; private AgiChannelFactory agiChannelFactory; - - public static final ConcurrentMap AGI_CONNECTION_HANDLERS = - new ConcurrentHashMap<>(32); + public static final ConcurrentMap AGI_CONNECTION_HANDLERS = new ConcurrentHashMap<>( + 32); /** * The strategy to use to determine which script to run. @@ -66,8 +64,10 @@ public abstract class AgiConnectionHandler implements Runnable /** * Creates a new AGIConnectionHandler to handle the given socket connection. * - * @param mappingStrategy the strategy to use to determine which script to run. - * @param agiChannelFactory the AgiFactory, that is used to create new AgiChannel objects. + * @param mappingStrategy the strategy to use to determine which script to + * run. + * @param agiChannelFactory the AgiFactory, that is used to create new + * AgiChannel objects. */ protected AgiConnectionHandler(MappingStrategy mappingStrategy, AgiChannelFactory agiChannelFactory) { @@ -108,7 +108,9 @@ protected AgiScript getScript() */ public abstract void release(); - @Override public void run() { + @Override + public void run() + { AgiChannel channel = null; try @@ -134,14 +136,16 @@ protected AgiScript getScript() { final String errorMessage; - errorMessage = "No script configured for URL '" + request.getRequestURL() + "' (script '" + request.getScript() + "')"; + errorMessage = "No script configured for URL '" + request.getRequestURL() + "' (script '" + + request.getScript() + "')"; logger.error(errorMessage); setStatusVariable(channel, AJ_AGISTATUS_NOT_FOUND); logToAsterisk(channel, errorMessage); } - else if (script != null) { - AGI_CONNECTION_HANDLERS.put(this, channel); + else if (script != null) + { + AGI_CONNECTION_HANDLERS.put(this, channel); runScript(script, request, channel); } } @@ -155,19 +159,20 @@ else if (script != null) { setStatusVariable(channel, AJ_AGISTATUS_FAILED); logger.error("Unexpected Exception while handling request", e); } - finally { - AGI_CONNECTION_HANDLERS.remove(this); + finally + { + AGI_CONNECTION_HANDLERS.remove(this); AgiConnectionHandler.channel.set(null); release(); } - }//run + }// run private void runScript(AgiScript script, AgiRequest request, AgiChannel channel) { String threadName; threadName = Thread.currentThread().getName(); - logger.info("Begin AgiScript " + getScriptName(script) + " on " + threadName); + logger.debug("Begin AgiScript " + getScriptName(script) + " on " + threadName); try { script.service(request, channel); @@ -183,7 +188,7 @@ private void runScript(AgiScript script, AgiRequest request, AgiChannel channel) logger.error("Exception running AgiScript " + getScriptName(script) + " on " + threadName, e); setStatusVariable(channel, AJ_AGISTATUS_FAILED); } - logger.info("End AgiScript " + getScriptName(script) + " on " + threadName); + logger.debug("End AgiScript " + getScriptName(script) + " on " + threadName); } protected String getScriptName(AgiScript script) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java index 3da0ba121..bedfd35fe 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java @@ -27,7 +27,11 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I callReachedAgi = true; channel.answer(); channel.playMusicOnHold(); - logger.info(ichannel + " is still on hold"); + long secondsOnHold = Math.abs(System.currentTimeMillis() - timer) / 1000; + if (secondsOnHold > 600) + { + logger.info(ichannel + " is still on hold after " + secondsOnHold + " seconds"); + } if (latch.await(10, TimeUnit.SECONDS)) { try @@ -41,7 +45,6 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } else { - long secondsOnHold = Math.abs(System.currentTimeMillis() - timer) / 1000; if (channel.getName().startsWith("Local") && secondsOnHold > 3600) { // cleanup Local channels older than 1 hour diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java b/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java index 94a6f63e6..6ae110963 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java @@ -51,10 +51,7 @@ public AgiScript determineScript(AgiRequest request, AgiChannel channel) { script = script.substring(0, script.indexOf(".")); } - else - { - logger.warn("scripts should be called as scriptname.agi"); - } + if (script.startsWith("/")) { // this is specifically for the "FastAgiSimulator" From 69e66dd98a571d9eb6316b7f6d8dc2fb0ff4a769 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 10 Aug 2017 10:53:48 +1000 Subject: [PATCH 102/802] reduce logging levels and some tidy up --- .../examples/activities/Hold.java | 2 ++ .../pbx/internal/activity/ActivityHelper.java | 6 ++-- .../activity/BlindTransferActivityImpl.java | 20 ++++++------- .../internal/activity/BridgeActivityImpl.java | 14 ++++----- .../internal/activity/DialActivityImpl.java | 29 +++++++++---------- .../activity/DialToAgiActivityImpl.java | 17 +++++------ .../internal/activity/HoldActivityImpl.java | 10 +++---- .../internal/activity/JoinActivityImpl.java | 20 ++++++------- .../internal/activity/ParkActivityImpl.java | 24 +++++++-------- .../activity/RedirectToActivityImpl.java | 13 ++++----- .../internal/activity/SplitActivityImpl.java | 12 ++++---- 11 files changed, 81 insertions(+), 86 deletions(-) diff --git a/src/main/java/org/asteriskjava/examples/activities/Hold.java b/src/main/java/org/asteriskjava/examples/activities/Hold.java index bf37a9640..af792962e 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Hold.java +++ b/src/main/java/org/asteriskjava/examples/activities/Hold.java @@ -58,6 +58,8 @@ public void progress(DialActivity activity, ActivityStatusEnum status, String me HoldActivity hold = pbx.hold(call.getRemoteParty()); Channel heldChannel = hold.getChannel(); + + System.out.println("Held channel is " + heldChannel); } if (status == ActivityStatusEnum.FAILURE) System.out.println("Oops something bad happened when we dialed."); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java index a61cc5d0c..8a2a96362 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java @@ -154,7 +154,7 @@ public boolean validateChannel(final Channel channel) { boolean ret = false; - final SetVarAction var = new SetVarAction(channel, "testState", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + final SetVarAction var = new SetVarAction(channel, "testState", "1"); ManagerResponse response = null; try @@ -165,9 +165,9 @@ public boolean validateChannel(final Channel channel) catch (final Exception e) { ActivityHelper.logger.debug(e, e); - ActivityHelper.logger.error("getVariable: " + e); //$NON-NLS-1$ + ActivityHelper.logger.error("getVariable: " + e); } - if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) //$NON-NLS-1$ //$NON-NLS-2$ + if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) { ret = true; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index 930452697..9735d228f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -79,7 +79,7 @@ public BlindTransferActivityImpl(Call call, final Call.OperandChannel channelToT final CallerID toCallerID, boolean autoAnswer, long timeout, final ActivityCallback listener) { - super("BlindTransferActivity", listener); //$NON-NLS-1$ + super("BlindTransferActivity", listener); this._call = call; this._channelToTransfer = channelToTransfer; @@ -96,7 +96,7 @@ public BlindTransferActivityImpl(Call call, final Call.OperandChannel channelToT public BlindTransferActivityImpl(Channel agentChannel, EndPoint transferTarget, CallerID toCallerID, boolean autoAnswer, int timeout, ActivityCallback iCallback) throws PBXException { - super("BlindTransferActivity", iCallback); //$NON-NLS-1$ + super("BlindTransferActivity", iCallback); this._transferTarget = transferTarget; this._toCallerID = toCallerID; @@ -123,14 +123,12 @@ public boolean doActivity() throws PBXException try { - logger.info("*******************************************************************************"); //$NON-NLS-1$ - logger.info("*********** begin blind transfer ****************"); //$NON-NLS-1$ - logger.info("*********** " + this._channelToTransfer //$NON-NLS-1$ - + " ****************"); //$NON-NLS-1$ - logger.info("*********** " + this._transferTarget //$NON-NLS-1$ - + " ****************"); //$NON-NLS-1$ - logger.info("*********** " + this._toCallerID + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ - logger.info("*******************************************************************************"); //$NON-NLS-1$ + logger.debug("*******************************************************************************"); + logger.info("*********** begin blind transfer ****************"); + logger.debug("*********** " + this._channelToTransfer + " ****************"); + logger.debug("*********** " + this._transferTarget + " ****************"); + logger.debug("*********** " + this._toCallerID + " ****************"); + logger.debug("*******************************************************************************"); if (!pbx.moveChannelToAgi(actualChannelToTransfer)) { @@ -187,7 +185,7 @@ else if (_completionCause == CompletionCause.CANCELLED) } catch (final Exception e) { - logger.error("error occurred in blindtransfer", e); //$NON-NLS-1$ + logger.error("error occurred in blindtransfer", e); this.setLastException(new PBXException(e)); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java index 6d0b4ac0e..5cc8171ea 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java @@ -36,7 +36,7 @@ public class BridgeActivityImpl extends ActivityHelper implement public BridgeActivityImpl(final Channel lhsChannel, final Channel rhsChannel, final ActivityCallback callback) { - super("Bridge", callback); //$NON-NLS-1$ + super("Bridge", callback); this._lhsChannel = lhsChannel; this._rhsChannel = rhsChannel; @@ -48,11 +48,11 @@ public boolean doActivity() throws PBXException { boolean success = false; - BridgeActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ - BridgeActivityImpl.logger.info("*********** begin Bridge ****************"); //$NON-NLS-1$ - BridgeActivityImpl.logger.info("*********** lhs:" + this._lhsChannel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ - BridgeActivityImpl.logger.info("*********** rhs:" + this._rhsChannel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ - BridgeActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + BridgeActivityImpl.logger.debug("*******************************************************************************"); + BridgeActivityImpl.logger.info("*********** begin Bridge ****************"); + BridgeActivityImpl.logger.debug("*********** lhs:" + this._lhsChannel + " ****************"); + BridgeActivityImpl.logger.debug("*********** rhs:" + this._rhsChannel + " ****************"); + BridgeActivityImpl.logger.debug("*******************************************************************************"); try { @@ -115,7 +115,7 @@ else if (pbx.isMeetmeInstalled()) } else - throw new PBXException("Cannot bridge two calls as neither the BridgeAction nor Meetme is available"); //$NON-NLS-1$ + throw new PBXException("Cannot bridge two calls as neither the BridgeAction nor Meetme is available"); } catch (IllegalArgumentException | IllegalStateException | InterruptedException e) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java index 93055aab4..d06b94779 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java @@ -58,7 +58,7 @@ public DialActivityImpl(final EndPoint originating, final EndPoint accepting, fi final boolean hideToCallerID, final ActivityCallback listener, Map channelVarsToSet) { - super("Dial", listener); //$NON-NLS-1$ + super("Dial", listener); this._originating = originating; this._accepting = accepting; this.toCallerID = toCallerID; @@ -76,11 +76,10 @@ public boolean doActivity() throws PBXException try (Dial nr = new Dial(this.toCallerID.toString())) { - DialActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ - DialActivityImpl.logger.info("*********** begin dial out ****************"); //$NON-NLS-1$ - DialActivityImpl.logger.info("*********** " + this._accepting //$NON-NLS-1$ - + " ****************"); //$NON-NLS-1$ - DialActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + DialActivityImpl.logger.debug("*******************************************************************************"); + DialActivityImpl.logger.info("*********** begin dial out ****************"); + DialActivityImpl.logger.debug("*********** " + this._accepting + " ****************"); + DialActivityImpl.logger.debug("*******************************************************************************"); final AsteriskSettings profile = PBXFactory.getActiveProfile(); @@ -95,8 +94,8 @@ public boolean doActivity() throws PBXException // Unless the operated cancelled the call if (!this.cancelledByOperator) { - this.setLastException(new PBXException(("OperatorEndedCall")));//$NON-NLS-1$ - DialActivityImpl.logger.error("dialout to " + this._accepting.getFullyQualifiedName() + " failed."); //$NON-NLS-1$ //$NON-NLS-2$ + this.setLastException(new PBXException(("OperatorEndedCall"))); + DialActivityImpl.logger.error("dialout to " + this._accepting.getFullyQualifiedName() + " failed."); } } else @@ -109,12 +108,12 @@ public boolean doActivity() throws PBXException newCall = new CallImpl(originatingChannel, acceptingChannel, CallDirection.OUTBOUND); - DialActivityImpl.logger.debug("dialout succeeded: dest channel is :" + this.acceptingChannel); //$NON-NLS-1$ + DialActivityImpl.logger.debug("dialout succeeded: dest channel is :" + this.acceptingChannel); if (this.validateChannel(this.acceptingChannel) == false) { - this.setLastException(new PBXException(("dialed extension hungup unexpectedly")));//$NON-NLS-1$ - DialActivityImpl.logger.error("dialed extension hungup unexpectedly"); //$NON-NLS-1$ + this.setLastException(new PBXException(("dialed extension hungup unexpectedly"))); + DialActivityImpl.logger.error("dialed extension hungup unexpectedly"); } else { @@ -199,7 +198,7 @@ public void channelUpdate(final Channel channel) this.originatingChannel = channel; } - super.progess(this, "Channel for " + channel.getEndPoint().getSIPSimpleName() + " is now up."); //$NON-NLS-1$ //$NON-NLS-2$ + super.progess(this, "Channel for " + channel.getEndPoint().getSIPSimpleName() + " is now up."); } @@ -212,7 +211,7 @@ public boolean validateChannel(final Channel channel) { boolean ret = false; - final SetVarAction var = new SetVarAction(channel, "testState", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + final SetVarAction var = new SetVarAction(channel, "testState", "1"); ManagerResponse response = null; try @@ -223,9 +222,9 @@ public boolean validateChannel(final Channel channel) catch (final Exception e) { DialActivityImpl.logger.debug(e, e); - DialActivityImpl.logger.error("getVariable: " + e); //$NON-NLS-1$ + DialActivityImpl.logger.error("getVariable: " + e); } - if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) //$NON-NLS-1$ //$NON-NLS-2$ + if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) { ret = true; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index 15831cd66..0990e7090 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -48,7 +48,7 @@ public DialToAgiActivityImpl(final EndPoint originating, final CallerID toCaller final ActivityCallback listener, Map channelVarsToSet, AgiChannelActivityAction action) { - super("Dial", listener); //$NON-NLS-1$ + super("Dial", listener); this.action = action; this._originating = originating; @@ -67,10 +67,9 @@ public boolean doActivity() throws PBXException try (DialToAgi nr = new DialToAgi(this.toCallerID.toString())) { - DialToAgiActivityImpl.logger.info("**************************************************************************"); - DialToAgiActivityImpl.logger.info("*********** begin dial out ***********"); - DialToAgiActivityImpl.logger.info("*********** to agi ***********"); - DialToAgiActivityImpl.logger.info("**************************************************************************"); + DialToAgiActivityImpl.logger.debug("**************************************************************************"); + DialToAgiActivityImpl.logger.info("*********** begin dial out to agi ***********"); + DialToAgiActivityImpl.logger.debug("**************************************************************************"); final OriginateResult[] resultChannels = nr.dial(this, this._originating, this.action, this.toCallerID, this.hideToCallerId, channelVarsToSet); @@ -163,7 +162,7 @@ public void channelUpdate(final Channel channel) this.originatingChannel = channel; } - super.progess(this, "Channel for " + channel.getEndPoint().getSIPSimpleName() + " is now up."); //$NON-NLS-1$ //$NON-NLS-2$ + super.progess(this, "Channel for " + channel.getEndPoint().getSIPSimpleName() + " is now up."); } @@ -176,7 +175,7 @@ public boolean validateChannel(final Channel channel) { boolean ret = false; - final SetVarAction var = new SetVarAction(channel, "testState", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + final SetVarAction var = new SetVarAction(channel, "testState", "1"); ManagerResponse response = null; try @@ -187,9 +186,9 @@ public boolean validateChannel(final Channel channel) catch (final Exception e) { DialToAgiActivityImpl.logger.debug(e, e); - DialToAgiActivityImpl.logger.error("getVariable: " + e); //$NON-NLS-1$ + DialToAgiActivityImpl.logger.error("getVariable: " + e); } - if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) //$NON-NLS-1$ //$NON-NLS-2$ + if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) { ret = true; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java index 983ab098d..2aa9f1711 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java @@ -21,7 +21,7 @@ public class HoldActivityImpl extends ActivityHelper implements Ho public HoldActivityImpl(final Channel channel, final ActivityCallback callback) { - super("HoldCall", callback); //$NON-NLS-1$ + super("HoldCall", callback); this._channel = channel; this.startActivity(false); @@ -32,10 +32,10 @@ public boolean doActivity() throws PBXException { boolean success = false; - HoldActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ - HoldActivityImpl.logger.info("*********** begin Hold Audio ****************"); //$NON-NLS-1$ - HoldActivityImpl.logger.info("*********** " + this._channel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ - HoldActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + HoldActivityImpl.logger.debug("*******************************************************************************"); + HoldActivityImpl.logger.info("*********** begin Hold Audio ****************"); + HoldActivityImpl.logger.debug("*********** " + this._channel + " ****************"); + HoldActivityImpl.logger.debug("*******************************************************************************"); try { AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java index 7f6c5922e..9f2b629c5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java @@ -61,7 +61,7 @@ public class JoinActivityImpl extends ActivityHelper implements Jo public JoinActivityImpl(final Call lhsCall, OperandChannel originatingOperand, final Call rhsCall, OperandChannel acceptingOperand, CallDirection direction, final ActivityCallback listener) { - super("JoinActivity", listener); //$NON-NLS-1$ + super("JoinActivity", listener); callSite = new Exception("Call site"); @@ -73,22 +73,22 @@ public JoinActivityImpl(final Call lhsCall, OperandChannel originatingOperand, f if (this._lhsCall == null) { - throw new IllegalArgumentException("lhsCall may not be null"); //$NON-NLS-1$ + throw new IllegalArgumentException("lhsCall may not be null"); } if (this._originatingOperand == null) { - throw new IllegalArgumentException("lhsOperand may not be null"); //$NON-NLS-1$ + throw new IllegalArgumentException("lhsOperand may not be null"); } if (this._rhsCall == null) { - throw new IllegalArgumentException("rhsCall may not be null"); //$NON-NLS-1$ + throw new IllegalArgumentException("rhsCall may not be null"); } if (this._acceptingOperand == null) { - throw new IllegalArgumentException("rhsOperand may not be null"); //$NON-NLS-1$ + throw new IllegalArgumentException("rhsOperand may not be null"); } this.startActivity(true); @@ -100,11 +100,11 @@ public boolean doActivity() throws PBXException boolean success = false; final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - JoinActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ - JoinActivityImpl.logger.info("*********** begin join ****************"); //$NON-NLS-1$ - JoinActivityImpl.logger.info("*********** " + this._lhsCall + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ - JoinActivityImpl.logger.info("*********** " + this._rhsCall + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ - JoinActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + JoinActivityImpl.logger.debug("*******************************************************************************"); + JoinActivityImpl.logger.info("*********** begin join ****************"); + JoinActivityImpl.logger.debug("*********** " + this._lhsCall + " ****************"); + JoinActivityImpl.logger.debug("*********** " + this._rhsCall + " ****************"); + JoinActivityImpl.logger.debug("*******************************************************************************"); try { diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java index 3633b426b..74cff5896 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java @@ -61,21 +61,21 @@ public class ParkActivityImpl extends ActivityHelper implements Pa */ public ParkActivityImpl(final Call call, final Channel parkChannel, final ActivityCallback listener) { - super("ParkActivity", listener); //$NON-NLS-1$ + super("ParkActivity", listener); if (call == null) { - throw new IllegalArgumentException("call may not be null"); //$NON-NLS-1$ + throw new IllegalArgumentException("call may not be null"); } if (parkChannel == null) { - throw new IllegalArgumentException("parkChannel may not be null"); //$NON-NLS-1$ + throw new IllegalArgumentException("parkChannel may not be null"); } this._parkChannel = parkChannel; this._call = call; if (!this._call.contains(parkChannel)) - throw new IllegalArgumentException("The parkChannel must be from the call."); //$NON-NLS-1$ + throw new IllegalArgumentException("The parkChannel must be from the call."); this.startActivity(true); } @@ -86,10 +86,10 @@ public boolean doActivity() throws PBXException boolean success = false; final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - ParkActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ - ParkActivityImpl.logger.info("*********** begin park ****************"); //$NON-NLS-1$ - ParkActivityImpl.logger.info("*********** " + this._parkChannel + " ****************"); //$NON-NLS-1$ //$NON-NLS-2$ - ParkActivityImpl.logger.info("*******************************************************************************"); //$NON-NLS-1$ + ParkActivityImpl.logger.debug("*******************************************************************************"); + ParkActivityImpl.logger.info("*********** begin park ****************"); + ParkActivityImpl.logger.debug("*********** " + this._parkChannel + " ****************"); + ParkActivityImpl.logger.debug("*******************************************************************************"); try { @@ -104,7 +104,7 @@ public boolean doActivity() throws PBXException pbx.getExtensionPark(), 1); final ManagerResponse response = pbx.sendAction(redirect, 1000); - if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0))//$NON-NLS-1$ + if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0)) { // Hangup the call as we have parked the other side of // the call. @@ -136,8 +136,8 @@ public boolean doActivity() throws PBXException if (this._parkingLot == null) { success = false; - ParkActivityImpl.logger.warn("ParkCallEvent not recieved within 2 seconds of parking call."); //$NON-NLS-1$ - this.setLastException(new PBXException("ParkCallEvent not recieved within 2 seconds of parking call.")); //$NON-NLS-1$ + ParkActivityImpl.logger.warn("ParkCallEvent not recieved within 2 seconds of parking call."); + this.setLastException(new PBXException("ParkCallEvent not recieved within 2 seconds of parking call.")); } } catch (final InterruptedException e) @@ -169,7 +169,7 @@ public EndPoint getParkingLot() @Override synchronized public void onManagerEvent(final ManagerEvent event) { - assert event instanceof ParkedCallEvent : "Unexpected event"; //$NON-NLS-1$ + assert event instanceof ParkedCallEvent : "Unexpected event"; final ParkedCallEvent parkedEvent = (ParkedCallEvent) event; final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java index 2986ebdba..ad7387c02 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java @@ -49,7 +49,7 @@ public class RedirectToActivityImpl extends ActivityHelper i */ public RedirectToActivityImpl(final Channel channel1, final ActivityCallback listener) { - super("SplitActivity", listener); //$NON-NLS-1$ + super("SplitActivity", listener); this.channel1 = channel1; @@ -60,13 +60,10 @@ public RedirectToActivityImpl(final Channel channel1, final ActivityCallback implements */ public SplitActivityImpl(final Call callToSplit, final ActivityCallback listener) { - super("SplitActivity", listener); //$NON-NLS-1$ + super("SplitActivity", listener); this._callToSplit = callToSplit; @@ -70,11 +70,11 @@ public SplitActivityImpl(final Call callToSplit, final ActivityCallback Date: Thu, 10 Aug 2017 11:20:47 +1000 Subject: [PATCH 103/802] further cleanup and adjust logging levels --- .../org/asteriskjava/live/OriginateCauseTest.java | 3 +-- .../org/asteriskjava/live/OriginateTest.java | 1 - .../internal/activity/BlindTransferActivityImpl.java | 2 +- .../pbx/internal/activity/BridgeActivityImpl.java | 2 +- .../pbx/internal/activity/DialActivityImpl.java | 2 +- .../pbx/internal/activity/DialToAgiActivityImpl.java | 3 +-- .../pbx/internal/activity/HoldActivityImpl.java | 2 +- .../pbx/internal/activity/JoinActivityImpl.java | 2 +- .../pbx/internal/activity/ParkActivityImpl.java | 2 +- .../internal/activity/RedirectToActivityImpl.java | 2 +- .../pbx/internal/activity/SplitActivityImpl.java | 2 +- .../pbx/internal/core/DialLocalToAgiActivity.java | 12 ++++-------- 12 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/integrationtest/org/asteriskjava/live/OriginateCauseTest.java b/src/integrationtest/org/asteriskjava/live/OriginateCauseTest.java index e8c696353..313b32911 100644 --- a/src/integrationtest/org/asteriskjava/live/OriginateCauseTest.java +++ b/src/integrationtest/org/asteriskjava/live/OriginateCauseTest.java @@ -84,8 +84,7 @@ public void run() } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); + e.printStackTrace(); } } }, 10, TimeUnit.SECONDS); diff --git a/src/integrationtest/org/asteriskjava/live/OriginateTest.java b/src/integrationtest/org/asteriskjava/live/OriginateTest.java index 33bdf8247..31c135efe 100644 --- a/src/integrationtest/org/asteriskjava/live/OriginateTest.java +++ b/src/integrationtest/org/asteriskjava/live/OriginateTest.java @@ -73,7 +73,6 @@ public void run() } catch (Exception e) { - // TODO Auto-generated catch block e.printStackTrace(); } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index 9735d228f..bd77aa89a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -125,7 +125,7 @@ public boolean doActivity() throws PBXException logger.debug("*******************************************************************************"); logger.info("*********** begin blind transfer ****************"); - logger.debug("*********** " + this._channelToTransfer + " ****************"); + logger.info("*********** " + this._channelToTransfer + " ****************"); logger.debug("*********** " + this._transferTarget + " ****************"); logger.debug("*********** " + this._toCallerID + " ****************"); logger.debug("*******************************************************************************"); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java index 5cc8171ea..4a89ac0b7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java @@ -50,7 +50,7 @@ public boolean doActivity() throws PBXException BridgeActivityImpl.logger.debug("*******************************************************************************"); BridgeActivityImpl.logger.info("*********** begin Bridge ****************"); - BridgeActivityImpl.logger.debug("*********** lhs:" + this._lhsChannel + " ****************"); + BridgeActivityImpl.logger.info("*********** lhs:" + this._lhsChannel + " ****************"); BridgeActivityImpl.logger.debug("*********** rhs:" + this._rhsChannel + " ****************"); BridgeActivityImpl.logger.debug("*******************************************************************************"); try diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java index d06b94779..e24989771 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java @@ -78,7 +78,7 @@ public boolean doActivity() throws PBXException { DialActivityImpl.logger.debug("*******************************************************************************"); DialActivityImpl.logger.info("*********** begin dial out ****************"); - DialActivityImpl.logger.debug("*********** " + this._accepting + " ****************"); + DialActivityImpl.logger.info("*********** " + this._accepting + " ****************"); DialActivityImpl.logger.debug("*******************************************************************************"); final AsteriskSettings profile = PBXFactory.getActiveProfile(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index 0990e7090..c21f1caa5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -101,8 +101,7 @@ public boolean doActivity() throws PBXException } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + logger.error(e); } finally { diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java index 2aa9f1711..f8fd68287 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java @@ -34,7 +34,7 @@ public boolean doActivity() throws PBXException HoldActivityImpl.logger.debug("*******************************************************************************"); HoldActivityImpl.logger.info("*********** begin Hold Audio ****************"); - HoldActivityImpl.logger.debug("*********** " + this._channel + " ****************"); + HoldActivityImpl.logger.info("*********** " + this._channel + " ****************"); HoldActivityImpl.logger.debug("*******************************************************************************"); try { diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java index 9f2b629c5..7538d1d97 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java @@ -102,7 +102,7 @@ public boolean doActivity() throws PBXException JoinActivityImpl.logger.debug("*******************************************************************************"); JoinActivityImpl.logger.info("*********** begin join ****************"); - JoinActivityImpl.logger.debug("*********** " + this._lhsCall + " ****************"); + JoinActivityImpl.logger.info("*********** " + this._lhsCall + " ****************"); JoinActivityImpl.logger.debug("*********** " + this._rhsCall + " ****************"); JoinActivityImpl.logger.debug("*******************************************************************************"); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java index 74cff5896..346aafe81 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java @@ -88,7 +88,7 @@ public boolean doActivity() throws PBXException ParkActivityImpl.logger.debug("*******************************************************************************"); ParkActivityImpl.logger.info("*********** begin park ****************"); - ParkActivityImpl.logger.debug("*********** " + this._parkChannel + " ****************"); + ParkActivityImpl.logger.info("*********** " + this._parkChannel + " ****************"); ParkActivityImpl.logger.debug("*******************************************************************************"); try diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java index ad7387c02..b9b913bf5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java @@ -62,7 +62,7 @@ public boolean doActivity() throws PBXException RedirectToActivityImpl.logger.debug("***************************************************************************"); RedirectToActivityImpl.logger.info("*********** begin redirect to activity ****************"); - RedirectToActivityImpl.logger.debug("*********** " + this.channel1 + " ****************"); + RedirectToActivityImpl.logger.info("*********** " + this.channel1 + " ****************"); RedirectToActivityImpl.logger.debug("***************************************************************************"); // Splits the originating and secondary channels by moving each of them diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index a972e6b40..a0b2b7918 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -72,7 +72,7 @@ public boolean doActivity() throws PBXException SplitActivityImpl.logger.debug("*******************************************************************************"); SplitActivityImpl.logger.info("*********** begin split ****************"); - SplitActivityImpl.logger.debug("*********** " + this.channel1 + " ****************"); + SplitActivityImpl.logger.info("*********** " + this.channel1 + " ****************"); SplitActivityImpl.logger.debug("*********** " + this.channel2 + " ****************"); SplitActivityImpl.logger.debug("*******************************************************************************"); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java index 498fc5c8b..1951a44de 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -65,10 +65,10 @@ public DialLocalToAgiActivity(EndPoint from, CallerID fromCallerID, ActivityCall @Override public void run() { - logger.info("*******************************************************************************"); + logger.debug("*******************************************************************************"); logger.info("*********** begin dial local to AGI ****************"); - logger.info("*********** " + " ****************"); - logger.info("*******************************************************************************"); + logger.debug("*********** ****************"); + logger.debug("*******************************************************************************"); final AsteriskSettings settings = PBXFactory.getActiveProfile(); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -101,12 +101,10 @@ public void run() } catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) { - // TODO Auto-generated catch block logger.error(e, e); } catch (InterruptedException e) { - // TODO Auto-generated catch block logger.error(e, e); } @@ -114,7 +112,7 @@ public void run() public void abort(final String reason) { - logger.debug("Aborting originate ");//$NON-NLS-1$ + logger.debug("Aborting originate "); this.close(); for (Channel channel : channels) @@ -186,12 +184,10 @@ else if (channelsOriginateId == null || channelsOriginateId.length() == 0) } catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) { - // TODO Auto-generated catch block logger.error(e, e); } catch (InterruptedException e) { - // TODO Auto-generated catch block logger.error(e, e); } From b172e20a3f4d66c10eb771615601941ebb64dec2 Mon Sep 17 00:00:00 2001 From: "YAMASHIRO, Jun" Date: Mon, 21 Aug 2017 18:33:28 +0900 Subject: [PATCH 104/802] Fix order of Channel1/Channel2/UniqueId1/UniqueId2/CallerId1/CallerId2 In sometimes, swap order of BridgeEvent's Channel/UniqueId/CallerId argument with Asterisk 13. It makes lack of compatibility. Fix order of channels using BridgeEnterEvent#getBridgeNumChannels(). --- .../bridge/BridgeState.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index a16171c6a..92262b936 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -104,13 +104,27 @@ private BridgeEvent buildBridgeEvent(String bridgeState, List { BridgeEvent bridgeEvent = new BridgeEvent(this); - bridgeEvent.setCallerId1(members.get(0).getCallerIdNum()); - bridgeEvent.setUniqueId1(members.get(0).getUniqueId()); - bridgeEvent.setChannel1(members.get(0).getChannel()); - bridgeEvent.setCallerId2(members.get(1).getCallerIdNum()); - bridgeEvent.setUniqueId2(members.get(1).getUniqueId()); - bridgeEvent.setChannel2(members.get(1).getChannel()); + if (new Integer(2).equals(members.get(0).getBridgeNumChannels())) + { + bridgeEvent.setCallerId1(members.get(0).getCallerIdNum()); + bridgeEvent.setUniqueId1(members.get(0).getUniqueId()); + bridgeEvent.setChannel1(members.get(0).getChannel()); + + bridgeEvent.setCallerId2(members.get(1).getCallerIdNum()); + bridgeEvent.setUniqueId2(members.get(1).getUniqueId()); + bridgeEvent.setChannel2(members.get(1).getChannel()); + } + else + { + bridgeEvent.setCallerId1(members.get(1).getCallerIdNum()); + bridgeEvent.setUniqueId1(members.get(1).getUniqueId()); + bridgeEvent.setChannel1(members.get(1).getChannel()); + + bridgeEvent.setCallerId2(members.get(0).getCallerIdNum()); + bridgeEvent.setUniqueId2(members.get(0).getUniqueId()); + bridgeEvent.setChannel2(members.get(0).getChannel()); + } bridgeEvent.setBridgeState(bridgeState); bridgeEvent.setDateReceived(new Date()); From 3f580bbbfc933f9761ffceb4a2876fe13bc9a01b Mon Sep 17 00:00:00 2001 From: "YAMASHIRO, Jun" Date: Tue, 22 Aug 2017 11:52:22 +0900 Subject: [PATCH 105/802] Whitespace: s/\t/ / --- .../backwardsCompatibility/bridge/BridgeState.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 92262b936..3a49fe14c 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -111,9 +111,9 @@ private BridgeEvent buildBridgeEvent(String bridgeState, List bridgeEvent.setUniqueId1(members.get(0).getUniqueId()); bridgeEvent.setChannel1(members.get(0).getChannel()); - bridgeEvent.setCallerId2(members.get(1).getCallerIdNum()); - bridgeEvent.setUniqueId2(members.get(1).getUniqueId()); - bridgeEvent.setChannel2(members.get(1).getChannel()); + bridgeEvent.setCallerId2(members.get(1).getCallerIdNum()); + bridgeEvent.setUniqueId2(members.get(1).getUniqueId()); + bridgeEvent.setChannel2(members.get(1).getChannel()); } else { @@ -121,9 +121,9 @@ private BridgeEvent buildBridgeEvent(String bridgeState, List bridgeEvent.setUniqueId1(members.get(1).getUniqueId()); bridgeEvent.setChannel1(members.get(1).getChannel()); - bridgeEvent.setCallerId2(members.get(0).getCallerIdNum()); - bridgeEvent.setUniqueId2(members.get(0).getUniqueId()); - bridgeEvent.setChannel2(members.get(0).getChannel()); + bridgeEvent.setCallerId2(members.get(0).getCallerIdNum()); + bridgeEvent.setUniqueId2(members.get(0).getUniqueId()); + bridgeEvent.setChannel2(members.get(0).getChannel()); } bridgeEvent.setBridgeState(bridgeState); From 006211383376d19e9b2b76d2a81e2f00cec2e882 Mon Sep 17 00:00:00 2001 From: "YAMASHIRO, Jun" Date: Tue, 22 Aug 2017 11:53:32 +0900 Subject: [PATCH 106/802] Change sort rule for legacy support code(BridgeEvent). Sort rule using "BridgeNumChannels: 2" in last commit is not better. (In future, if change behavior of Asterisk make new bug) New rule: BridgeEnterEvent has an older unique ID set to UniqueId1 in BridgeEvent. --- .../bridge/BridgeState.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 3a49fe14c..8bd08be1b 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -5,6 +5,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.asteriskjava.manager.event.BridgeEnterEvent; import org.asteriskjava.manager.event.BridgeEvent; @@ -105,7 +107,8 @@ private BridgeEvent buildBridgeEvent(String bridgeState, List BridgeEvent bridgeEvent = new BridgeEvent(this); - if (new Integer(2).equals(members.get(0).getBridgeNumChannels())) + if (this.compareUniqueId(members.get(0).getUniqueId(), + members.get(1).getUniqueId()) < 0) { bridgeEvent.setCallerId1(members.get(0).getCallerIdNum()); bridgeEvent.setUniqueId1(members.get(0).getUniqueId()); @@ -131,4 +134,44 @@ private BridgeEvent buildBridgeEvent(String bridgeState, List return bridgeEvent; } + + /** + * Compares two Asteirsk Unique ID. + * + * @param id1 1st Asterisk Unique ID, for example "1099015093.165". + * @param id2 2nd Asterisk Unique ID, for example "1099015093.166". + * @return Return 0 if s1 == s2. + * Return less then 0 if s1 < s2. + * Return greater then 0 if s1 > s2. + */ + private int compareUniqueId(String id1, String id2) { + Pattern uniqueIdPattern = Pattern.compile("^([0-9]+)\\.([0-9]+)$"); + Matcher uniqueId1Matcher = uniqueIdPattern.matcher(id1); + Matcher uniqueId2Matcher = uniqueIdPattern.matcher(id2); + + boolean find1 = uniqueId1Matcher.find(); + boolean find2 = uniqueId2Matcher.find(); + + if (find1 && find2) { + // 1501234567.890 -> epochtime: 1501234567 | serial: 890 + int epochtime1 = Integer.valueOf(uniqueId1Matcher.group(1)); + int epochtime2 = Integer.valueOf(uniqueId2Matcher.group(1)); + int serial1 = Integer.valueOf(uniqueId1Matcher.group(2)); + int serial2 = Integer.valueOf(uniqueId2Matcher.group(2)); + + if (epochtime1 == epochtime2) { + return Integer.compare(serial1, serial2); + } + + return Integer.compare(epochtime1, epochtime2); + + } else if (!find1 && find2) { + // id1 < id2 + return -1; + } else if (find1 && !find2) { + // id1 > id2 + return 1; + } + return 0; + } } From 6fc364003ce0c56f890eba77f462408b1b8c3acb Mon Sep 17 00:00:00 2001 From: "YAMASHIRO, Jun" Date: Tue, 22 Aug 2017 14:15:04 +0900 Subject: [PATCH 107/802] Fix comment. --- .../internal/backwardsCompatibility/bridge/BridgeState.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 8bd08be1b..a011263e9 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -140,9 +140,9 @@ private BridgeEvent buildBridgeEvent(String bridgeState, List * * @param id1 1st Asterisk Unique ID, for example "1099015093.165". * @param id2 2nd Asterisk Unique ID, for example "1099015093.166". - * @return Return 0 if s1 == s2. - * Return less then 0 if s1 < s2. - * Return greater then 0 if s1 > s2. + * @return Return 0 if id1 == id2. + * Return less then 0 if id1 < id2. + * Return greater then 0 if id1 > id2. */ private int compareUniqueId(String id1, String id2) { Pattern uniqueIdPattern = Pattern.compile("^([0-9]+)\\.([0-9]+)$"); From 77b62449e354c310f59bb3520f3384382c5e87b4 Mon Sep 17 00:00:00 2001 From: "YAMASHIRO, Jun" Date: Mon, 28 Aug 2017 10:18:10 +0900 Subject: [PATCH 108/802] Refactoring: Change coding style to open-braces for asterisk-java standard. see also: https://github.com/asterisk-java/asterisk-java/pull/210 --- .../bridge/BridgeState.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index a011263e9..8c6cfaa09 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -144,7 +144,8 @@ private BridgeEvent buildBridgeEvent(String bridgeState, List * Return less then 0 if id1 < id2. * Return greater then 0 if id1 > id2. */ - private int compareUniqueId(String id1, String id2) { + private int compareUniqueId(String id1, String id2) + { Pattern uniqueIdPattern = Pattern.compile("^([0-9]+)\\.([0-9]+)$"); Matcher uniqueId1Matcher = uniqueIdPattern.matcher(id1); Matcher uniqueId2Matcher = uniqueIdPattern.matcher(id2); @@ -152,26 +153,33 @@ private int compareUniqueId(String id1, String id2) { boolean find1 = uniqueId1Matcher.find(); boolean find2 = uniqueId2Matcher.find(); - if (find1 && find2) { + if (find1 && find2) + { // 1501234567.890 -> epochtime: 1501234567 | serial: 890 int epochtime1 = Integer.valueOf(uniqueId1Matcher.group(1)); int epochtime2 = Integer.valueOf(uniqueId2Matcher.group(1)); int serial1 = Integer.valueOf(uniqueId1Matcher.group(2)); int serial2 = Integer.valueOf(uniqueId2Matcher.group(2)); - if (epochtime1 == epochtime2) { + if (epochtime1 == epochtime2) + { return Integer.compare(serial1, serial2); } return Integer.compare(epochtime1, epochtime2); - } else if (!find1 && find2) { + } + else if (!find1 && find2) + { // id1 < id2 return -1; - } else if (find1 && !find2) { + } + else if (find1 && !find2) + { // id1 > id2 return 1; } + // Both of inputs are invalid value: id1 == id2 return 0; } } From c82d0d9cbb2fc969f29db5f80d30e094f6a13b74 Mon Sep 17 00:00:00 2001 From: "YAMASHIRO, Jun" Date: Mon, 28 Aug 2017 11:08:55 +0900 Subject: [PATCH 109/802] Refactoring: Reduce getter/setter code. see also: https://github.com/asterisk-java/asterisk-java/pull/210 --- .../bridge/BridgeState.java | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 8c6cfaa09..cfbede993 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -105,29 +105,26 @@ ManagerEvent removeMember(BridgeLeaveEvent event) private BridgeEvent buildBridgeEvent(String bridgeState, List members) { BridgeEvent bridgeEvent = new BridgeEvent(this); - + int index1, index2; if (this.compareUniqueId(members.get(0).getUniqueId(), members.get(1).getUniqueId()) < 0) { - bridgeEvent.setCallerId1(members.get(0).getCallerIdNum()); - bridgeEvent.setUniqueId1(members.get(0).getUniqueId()); - bridgeEvent.setChannel1(members.get(0).getChannel()); - - bridgeEvent.setCallerId2(members.get(1).getCallerIdNum()); - bridgeEvent.setUniqueId2(members.get(1).getUniqueId()); - bridgeEvent.setChannel2(members.get(1).getChannel()); + index1 = 0; + index2 = 1; } else { - bridgeEvent.setCallerId1(members.get(1).getCallerIdNum()); - bridgeEvent.setUniqueId1(members.get(1).getUniqueId()); - bridgeEvent.setChannel1(members.get(1).getChannel()); - - bridgeEvent.setCallerId2(members.get(0).getCallerIdNum()); - bridgeEvent.setUniqueId2(members.get(0).getUniqueId()); - bridgeEvent.setChannel2(members.get(0).getChannel()); + index1 = 1; + index2 = 0; } + bridgeEvent.setCallerId1(members.get(index1).getCallerIdNum()); + bridgeEvent.setUniqueId1(members.get(index1).getUniqueId()); + bridgeEvent.setChannel1(members.get(index1).getChannel()); + + bridgeEvent.setCallerId2(members.get(index2).getCallerIdNum()); + bridgeEvent.setUniqueId2(members.get(index2).getUniqueId()); + bridgeEvent.setChannel2(members.get(index2).getChannel()); bridgeEvent.setBridgeState(bridgeState); bridgeEvent.setDateReceived(new Date()); From e4f37eb21d14e1e69393535566cfd5e74c0f6e0e Mon Sep 17 00:00:00 2001 From: "YAMASHIRO, Jun" Date: Mon, 28 Aug 2017 11:16:01 +0900 Subject: [PATCH 110/802] Refactoring: s/\t/ / --- .../internal/backwardsCompatibility/bridge/BridgeState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index cfbede993..c2bda7e30 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -176,7 +176,7 @@ else if (find1 && !find2) // id1 > id2 return 1; } - // Both of inputs are invalid value: id1 == id2 + // Both of inputs are invalid value: id1 == id2 return 0; } } From e64a4b51a0cd9820141d501f8df0f615ab138407 Mon Sep 17 00:00:00 2001 From: "YAMASHIRO, Jun" Date: Tue, 29 Aug 2017 17:26:27 +0900 Subject: [PATCH 111/802] Fix year 2038 problem at BridgeState#compareUniqueId(). I added compareUniqueId() in last pull-request(#210). This method will overflow after January 2038. Because, it used int/Integer for epoch time. --- .../internal/backwardsCompatibility/bridge/BridgeState.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index c2bda7e30..b055aa590 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -153,8 +153,8 @@ private int compareUniqueId(String id1, String id2) if (find1 && find2) { // 1501234567.890 -> epochtime: 1501234567 | serial: 890 - int epochtime1 = Integer.valueOf(uniqueId1Matcher.group(1)); - int epochtime2 = Integer.valueOf(uniqueId2Matcher.group(1)); + long epochtime1 = Long.valueOf(uniqueId1Matcher.group(1)); + long epochtime2 = Long.valueOf(uniqueId2Matcher.group(1)); int serial1 = Integer.valueOf(uniqueId1Matcher.group(2)); int serial2 = Integer.valueOf(uniqueId2Matcher.group(2)); @@ -163,7 +163,7 @@ private int compareUniqueId(String id1, String id2) return Integer.compare(serial1, serial2); } - return Integer.compare(epochtime1, epochtime2); + return Long.compare(epochtime1, epochtime2); } else if (!find1 && find2) From 836acbc2e569b35a1705e8b6258bbe2d2902db64 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 1 Sep 2017 17:22:47 +1000 Subject: [PATCH 112/802] fix for failed initialization of CoherentManagerConnection --- .../pbx/internal/core/AsteriskPBX.java | 5 ++-- .../core/CoherentManagerConnection.java | 27 ++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index c77c94393..6371f6702 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -102,7 +102,8 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener } } - catch (IllegalStateException | IOException | AuthenticationFailedException | TimeoutException e1) + catch (IllegalStateException | IOException | AuthenticationFailedException | TimeoutException + | InterruptedException e1) { logger.error(e1, e1); } @@ -296,7 +297,7 @@ public void hangup(final Channel channel) throws PBXException { if (channel.isLive()) { - logger.debug("Sending hangup action for channel: " + channel); //$NON-NLS-1$ + logger.warn("Sending hangup action for channel: " + channel); //$NON-NLS-1$ PBX pbx = PBXFactory.getActivePBX(); if (!pbx.waitForChannelToQuiescent(channel, 3000)) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java index 1c7d5f63b..f22c91da2 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -115,15 +115,36 @@ class CoherentManagerConnection implements FilteredManagerListener private CountDownLatch _reconnectLatch = new CountDownLatch(0); public static synchronized void init() - throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException + throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException, InterruptedException { if (self != null) logger.warn("The CoherentManagerConnection has already been initialised"); //$NON-NLS-1$ else { self = new CoherentManagerConnection(); - self.checkConnection(); - self.checkFeatures(); + boolean done = false; + while (!done) + { + try + { + + self.checkConnection(); + self.checkFeatures(); + done = true; + } + catch (Exception e) + { + logger.error(e, e); + try + { + TimeUnit.MILLISECONDS.sleep(500); + } + catch (InterruptedException e1) + { + throw e1; + } + } + } } self.checkConnection(); From a9e5b0a7c6fda63906470d482888aebf8d09ec91 Mon Sep 17 00:00:00 2001 From: sere Date: Fri, 1 Sep 2017 10:24:38 +0200 Subject: [PATCH 113/802] Fixed race conditions during (dis-)connecting - synchronized state changes - synchronized crucial state checks --- .../internal/ManagerConnectionImpl.java | 196 +++++++++--------- 1 file changed, 102 insertions(+), 94 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index ba40f031c..2fb00179d 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -23,22 +23,6 @@ import static org.asteriskjava.manager.ManagerConnectionState.INITIAL; import static org.asteriskjava.manager.ManagerConnectionState.RECONNECTING; -import java.io.IOException; -import java.io.Serializable; -import java.net.InetAddress; -import java.net.Socket; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.AuthenticationFailedException; import org.asteriskjava.manager.EventTimeoutException; @@ -73,9 +57,25 @@ import org.asteriskjava.util.SocketConnectionFacade; import org.asteriskjava.util.internal.SocketConnectionFacadeImpl; +import java.io.IOException; +import java.io.Serializable; +import java.net.InetAddress; +import java.net.Socket; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * Internal implemention of the ManagerConnection interface. - * + * * @author srt * @version $Id$ * @see org.asteriskjava.manager.ManagerConnectionFactory @@ -166,7 +166,7 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher * Closes the connection (and reconnects) if no input has been read for the * given amount of milliseconds. A timeout of zero is interpreted as an * infinite timeout. - * + * * @see Socket#setSoTimeout(int) */ private int socketReadTimeout = 0; @@ -265,7 +265,7 @@ protected ManagerWriter createWriter() * Sets the hostname of the asterisk server to connect to. *

* Default is localhost. - * + * * @param hostname the hostname to connect to */ public void setHostname(String hostname) @@ -278,7 +278,7 @@ public void setHostname(String hostname) * specified in asterisk's manager.conf file. *

* Default is 5038. - * + * * @param port the port to connect to */ public void setPort(int port) @@ -296,7 +296,7 @@ public void setPort(int port) /** * Sets whether to use SSL.
* Default is false. - * + * * @param ssl true to use SSL for the connection, * false for a plain text connection. * @since 0.3 @@ -309,7 +309,7 @@ public void setSsl(boolean ssl) /** * Sets the username to use to connect to the asterisk server. This is the * username specified in asterisk's manager.conf file. - * + * * @param username the username to use for login */ public void setUsername(String username) @@ -320,7 +320,7 @@ public void setUsername(String username) /** * Sets the password to use to connect to the asterisk server. This is the * password specified in Asterisk's manager.conf file. - * + * * @param password the password to use for login */ public void setPassword(String password) @@ -339,7 +339,7 @@ public void setEncoding(Charset encoding) * {@link #sendAction(ManagerAction)} will wait for a response before * throwing a TimeoutException.
* Default is 2000. - * + * * @param defaultResponseTimeout default response timeout in milliseconds * @since 0.2 */ @@ -354,7 +354,7 @@ public void setDefaultResponseTimeout(long defaultResponseTimeout) * response and the last response event before throwing a TimeoutException. *
* Default is 5000. - * + * * @param defaultEventTimeout default event timeout in milliseconds * @since 0.2 */ @@ -367,7 +367,7 @@ public void setDefaultEventTimeout(long defaultEventTimeout) * Set to true to try reconnecting to ther asterisk serve even * if the reconnection attempt threw an AuthenticationFailedException.
* Default is true. - * + * * @param keepAliveAfterAuthenticationFailure true to try * reconnecting to ther asterisk serve even if the reconnection * attempt threw an AuthenticationFailedException, @@ -497,7 +497,7 @@ public synchronized void login(String eventMask) throws IOException, Authenticat * is sent using the calculated key (MD5 hash of the password appended to * the received challenge). * - * + * * @param timeout the maximum time to wait for the protocol identifier (in * ms) * @param eventMask the event mask. Set to "on" if all events should be @@ -1090,7 +1090,7 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas /** * Creates a new unique internal action id based on the hash code of this * connection and a sequence. - * + * * @return a new internal action id * @see ManagerUtil#addInternalActionId(String,String) * @see ManagerUtil#getInternalActionId(String) @@ -1147,7 +1147,7 @@ public ManagerConnectionState getState() * This method is called by the reader whenever a {@link ManagerResponse} is * received. The response is dispatched to the associated * {@link SendActionCallback}. - * + * * @param response the response received by the reader * @see ManagerReader */ @@ -1218,7 +1218,7 @@ public void dispatchResponse(ManagerResponse response) /** * This method is called by the reader whenever a ManagerEvent is received. * The event is dispatched to all registered ManagerEventHandlers. - * + * * @param event the event received by the reader * @see #addEventListener(ManagerEventListener) * @see #removeEventListener(ManagerEventListener) @@ -1286,37 +1286,39 @@ public void dispatchEvent(ManagerEvent event) { // When we receive get disconnected while we are connected start // a new reconnect thread and set the state to RECONNECTING. - if (state == CONNECTED) - { - state = RECONNECTING; - // close socket if still open and remove reference to - // readerThread - // After sending the DisconnectThread that thread will die - // anyway. - cleanup(); - Thread reconnectThread = new Thread(new Runnable() - { - public void run() - { - reconnect(); - } - }); - reconnectThread.setName( - "Asterisk-Java ManagerConnection-" + id + "-Reconnect-" + reconnectThreadCounter.getAndIncrement()); - reconnectThread.setDaemon(true); - reconnectThread.start(); - // now the DisconnectEvent is dispatched to registered - // eventListeners - // (clients) and after that the ManagerReaderThread is gone. - // So effectively we replaced the reader thread by a - // ReconnectThread. - } - else - { - // when we receive a DisconnectEvent while not connected we - // ignore it and do not send it to clients - return; - } + synchronized (this) + { + if (state == CONNECTED) + { + state = RECONNECTING; + // close socket if still open and remove reference to + // readerThread + // After sending the DisconnectThread that thread will die + // anyway. + cleanup(); + Thread reconnectThread = new Thread(new Runnable() { + + public void run() { + reconnect(); + } + }); + reconnectThread.setName( + "Asterisk-Java ManagerConnection-" + id + "-Reconnect-" + reconnectThreadCounter.getAndIncrement()); + reconnectThread.setDaemon(true); + reconnectThread.start(); + // now the DisconnectEvent is dispatched to registered + // eventListeners + // (clients) and after that the ManagerReaderThread is gone. + // So effectively we replaced the reader thread by a + // ReconnectThread. + } + else + { + // when we receive a DisconnectEvent while not connected we + // ignore it and do not send it to clients + return; + } + } } if (event instanceof ProtocolIdentifierReceivedEvent) { @@ -1348,7 +1350,7 @@ private void dispatchLegacyEventIfNeeded(ManagerEvent event) /** * Notifies all {@link ManagerEventListener}s registered by users. - * + * * @param event the event to propagate */ private void fireEvent(ManagerEvent event) @@ -1373,7 +1375,7 @@ private void fireEvent(ManagerEvent event) * This method is called when a {@link ProtocolIdentifierReceivedEvent} is * received from the reader. Having received a correct protocol identifier * is the precodition for logging in. - * + * * @param identifier the protocol version used by the Asterisk server. */ private void setProtocolIdentifier(final String identifier) @@ -1422,7 +1424,7 @@ private void reconnect() // try to reconnect numTries = 0; - while (state == RECONNECTING) + while (true) { try { @@ -1446,34 +1448,40 @@ private void reconnect() try { - connect(); - - try - { - doLogin(defaultResponseTimeout, eventMask); - logger.info("Successfully reconnected."); - // everything is ok again, so we leave - // when successful doLogin set the state to CONNECTED so no - // need to adjust it - break; - } - catch (AuthenticationFailedException e1) - { - if (keepAliveAfterAuthenticationFailure) - { - logger.error("Unable to log in after reconnect: " + e1.getMessage()); - } - else - { - logger.error("Unable to log in after reconnect: " + e1.getMessage() + ". Giving up."); - state = DISCONNECTED; - } - } - catch (TimeoutException e1) - { - // shouldn't happen - but happens! - logger.error("TimeoutException while trying to log in " + "after reconnect."); - } + synchronized (this) + { + if (state != RECONNECTING) { + break; + } + connect(); + + try + { + doLogin(defaultResponseTimeout, eventMask); + logger.info("Successfully reconnected."); + // everything is ok again, so we leave + // when successful doLogin set the state to CONNECTED so no + // need to adjust it + break; + } + catch (AuthenticationFailedException e1) + { + if (keepAliveAfterAuthenticationFailure) + { + logger.error("Unable to log in after reconnect: " + e1.getMessage()); + } + else + { + logger.error("Unable to log in after reconnect: " + e1.getMessage() + ". Giving up."); + state = DISCONNECTED; + } + } + catch (TimeoutException e1) + { + // shouldn't happen - but happens! + logger.error("TimeoutException while trying to log in " + "after reconnect."); + } + } } catch (IOException e) { @@ -1553,7 +1561,7 @@ private static class DefaultSendActionCallback implements SendActionCallback, Se /** * Creates a new instance. - * + * * @param result the result to store the response in */ public DefaultSendActionCallback(ResponseHandlerResult result) @@ -1582,7 +1590,7 @@ private static class ResponseEventHandler implements ManagerEventListener, SendA /** * Creates a new instance. - * + * * @param events the ResponseEventsImpl to store the events in * @param actionCompleteEventClass the type of event that indicates that * all events have been received From 8eb6cffc9e3ea1db24423134478439fa4d673c0c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 7 Sep 2017 16:11:46 +1000 Subject: [PATCH 114/802] Add ownership to MeetmeRoomControl --- .../internal/activity/BridgeActivityImpl.java | 3 +- .../internal/asterisk/DurationRoomOwner.java | 27 +++++++ .../pbx/internal/asterisk/MeetmeRoom.java | 27 ++++++- .../internal/asterisk/MeetmeRoomControl.java | 70 +++++++++++-------- .../pbx/internal/asterisk/RoomOwner.java | 21 ++++++ .../pbx/internal/core/AsteriskPBX.java | 5 +- 6 files changed, 116 insertions(+), 37 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/DurationRoomOwner.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/asterisk/RoomOwner.java diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java index 4a89ac0b7..8fc8b22fe 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java @@ -19,6 +19,7 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.pbx.internal.asterisk.DurationRoomOwner; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.managerAPI.RedirectToMeetMe; @@ -96,7 +97,7 @@ else if (pbx.isMeetmeInstalled()) final RedirectToMeetMe meetmeTransfer = new RedirectToMeetMe(); // meetme room is empty // find a new available room. - MeetmeRoom room = pbx.acquireMeetmeRoom(); + MeetmeRoom room = pbx.acquireMeetmeRoom(new DurationRoomOwner(30, TimeUnit.SECONDS)); // redirect the lhs to meetme meetmeTransfer.redirectToMeetme(_lhsChannel, room.getRoomNumber(), true); diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/DurationRoomOwner.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/DurationRoomOwner.java new file mode 100644 index 000000000..0cd4e830b --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/DurationRoomOwner.java @@ -0,0 +1,27 @@ +package org.asteriskjava.pbx.internal.asterisk; + +import java.util.concurrent.TimeUnit; + +public class DurationRoomOwner implements RoomOwner +{ + + long end = System.currentTimeMillis(); + + public DurationRoomOwner(long duration, TimeUnit units) + { + end = System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(duration, units); + } + + @Override + public boolean isRoomStillRequired() + { + return System.currentTimeMillis() < end; + } + + @Override + public void setRoom(MeetmeRoom meetmeRoom) + { + + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java index 86fb24264..cfd3ab204 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java @@ -33,6 +33,8 @@ public class MeetmeRoom private Date lastUpdated = null; + private RoomOwner owner = null; + public MeetmeRoom(final int number) { this.roomNumber = number; @@ -93,7 +95,7 @@ public String getRoomNumber() * * @return */ - public boolean getStatus() + public boolean isActive() { return this.active; } @@ -177,9 +179,28 @@ public void resetChannelCount(final int resetChannelCount) } - public boolean isActive() + public RoomOwner getOwner() { - return this.active; + return owner; + } + + public void setOwner(RoomOwner newOwner) + { + owner = newOwner; + owner.setRoom(this); + setActive(); + } + + public void removeOwner(RoomOwner toRemove) + { + if (owner == toRemove) + { + owner = null; + } + else + { + logger.error("Tring to remove the owner, but it's not the current owner"); + } } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index bc743d960..8bdd9c2ad 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -103,55 +103,62 @@ private MeetmeRoomControl(PBX pbx, final int roomCount) throws NoMeetmeException * returns the next available meetme room, or null if no rooms are * available. */ - public synchronized MeetmeRoom findAvailableRoom() + public synchronized MeetmeRoom findAvailableRoom(RoomOwner newOwner) { int count = 0; for (final MeetmeRoom room : this.rooms) { if (MeetmeRoomControl.logger.isDebugEnabled()) { - MeetmeRoomControl.logger.debug("room " + room.getRoomNumber() + " count " + count); //$NON-NLS-1$ //$NON-NLS-2$ + MeetmeRoomControl.logger.debug("room " + room.getRoomNumber() + " count " + count); } - /* - * new code to attempt to recover uncleared meetme rooms safely - */ - try + if (room.getOwner() == null || !room.getOwner().isRoomStillRequired()) { - final Date lastUpdated = room.getLastUpdated(); - final long now = new Date().getTime(); - if (lastUpdated != null) + /* + * new code to attempt to recover uncleared meetme rooms safely + */ + try { - final long elapsedTime = now - lastUpdated.getTime(); - MeetmeRoomControl.logger.debug("room: " + room.getRoomNumber() + " count: " + count + " elapsed: " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - + elapsedTime); - if ((elapsedTime > 7200000) && (room.getChannelCount() == 1)) + final Date lastUpdated = room.getLastUpdated(); + final long now = new Date().getTime(); + if (lastUpdated != null) { - MeetmeRoomControl.logger.debug("clearing room"); //$NON-NLS-1$ - room.setInactive(); + final long elapsedTime = now - lastUpdated.getTime(); + MeetmeRoomControl.logger + .debug("room: " + room.getRoomNumber() + " count: " + count + " elapsed: " + elapsedTime); + if ((elapsedTime > 7200000) && (room.getChannelCount() == 1)) + { + MeetmeRoomControl.logger.debug("clearing room"); //$NON-NLS-1$ + room.setInactive(); + } } } - } - catch (final Exception e) - { - /* - * attempt to make this new change safe - */ - MeetmeRoomControl.logger.error(e, e); - } + catch (final Exception e) + { + /* + * attempt to make this new change safe + */ + MeetmeRoomControl.logger.error(e, e); + } + + if (room.getChannelCount() == 0) + { + room.setInactive(); + room.setOwner(newOwner); + MeetmeRoomControl.logger.warn("Returning available room " + room.getRoomNumber()); + return room; + } - if (room.getChannelCount() == 0) - { - room.setInactive(); } - if (room.getStatus() == false) + else { - MeetmeRoomControl.logger.debug("Returning available room base+" + room.getRoomNumber()); //$NON-NLS-1$ - return room; + logger.warn("Meetme " + room.getRoomNumber() + " is still in use by " + room.getOwner()); } count++; } - MeetmeRoomControl.logger.error("no more available rooms"); //$NON-NLS-1$ + MeetmeRoomControl.logger.error("no more available rooms"); return null; + } /** @@ -234,7 +241,7 @@ public void hangupChannels(final MeetmeRoom room) { final Channel Channels[] = room.getChannels(); - if (room.getStatus() == true) + if (room.isActive() == true) { PBX pbx = PBXFactory.getActivePBX(); @@ -244,6 +251,7 @@ public void hangupChannels(final MeetmeRoom room) try { + logger.warn("Hanging up"); pbx.hangup(channel); } catch (IllegalArgumentException | IllegalStateException | PBXException e) diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/RoomOwner.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/RoomOwner.java new file mode 100644 index 000000000..3bb04c3de --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/RoomOwner.java @@ -0,0 +1,21 @@ +package org.asteriskjava.pbx.internal.asterisk; + +public interface RoomOwner +{ + /** + * implementations of this method should NOT take locks and should return + * quickly. This is used as an indication that the room (even though empty) + * is still required by the owner + * + * @return true if the meetme room is still required + */ + boolean isRoomStillRequired(); + + /** + * this can be usefull to null the reference to the Owner when the room is + * nolong owned + * + * @param meetmeRoom + */ + void setRoom(MeetmeRoom meetmeRoom); +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 6371f6702..8d915ddc2 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -65,6 +65,7 @@ import org.asteriskjava.pbx.internal.asterisk.CallerIDImpl; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoomControl; +import org.asteriskjava.pbx.internal.asterisk.RoomOwner; import org.asteriskjava.pbx.internal.managerAPI.RedirectCall; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -618,9 +619,9 @@ public ChannelProxy findChannel(final String channelName, final String uniqueID) return this.liveChannels.findChannel(channelName, uniqueID); } - public MeetmeRoom acquireMeetmeRoom() + public MeetmeRoom acquireMeetmeRoom(RoomOwner owner) { - return MeetmeRoomControl.getInstance().findAvailableRoom(); + return MeetmeRoomControl.getInstance().findAvailableRoom(owner); } public void addListener(FilteredManagerListener listener) From 4f415260963bcfa9cbbbc6d4bd20c660cfd902a6 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 12 Sep 2017 11:35:55 +1000 Subject: [PATCH 115/802] set meetme control limit to 500 fix logger statement in CallImpl --- src/main/java/org/asteriskjava/pbx/CallImpl.java | 2 +- .../java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/CallImpl.java b/src/main/java/org/asteriskjava/pbx/CallImpl.java index 233aeb908..96f7b1782 100644 --- a/src/main/java/org/asteriskjava/pbx/CallImpl.java +++ b/src/main/java/org/asteriskjava/pbx/CallImpl.java @@ -868,7 +868,7 @@ public Channel getOperandChannel(OperandChannel operand) } if (channel == null) { - Exception e = new Exception("failed to get channel for {}" + operand); + Exception e = new Exception("failed to get channel for " + operand); logger.warn(e, e); } return channel; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 8d915ddc2..668e78f2f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -80,7 +80,7 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener private boolean muteSupported; private boolean bridgeSupport; - private static final int MAX_MEETME_ROOMS = 50; + private static final int MAX_MEETME_ROOMS = 500; private LiveChannelManager liveChannels; From 6a7d2e626cc98d417b3eaaad708103d94e19d28d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 18 Sep 2017 15:31:36 +1000 Subject: [PATCH 116/802] fix for possible unnecessary timeout --- .../internal/ManagerConnectionImpl.java | 240 +++++++++--------- .../internal/ProtocolIdentifierWrapper.java | 37 +++ .../manager/internal/ResponseEventsImpl.java | 18 +- 3 files changed, 176 insertions(+), 119 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 0e3bb2c48..9f9eaf308 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -36,6 +36,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -95,10 +97,12 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher private static final Pattern VERSION_PATTERN_1_8 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?1\\.8[-. ].*"); private static final Pattern VERSION_PATTERN_10 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?10[-. ].*"); private static final Pattern VERSION_PATTERN_11 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?11[-. ].*"); - private static final Pattern VERSION_PATTERN_CERTIFIED_11 = Pattern.compile("^\\s*Asterisk certified/((SVN-branch|GIT)-)?11[-. ].*"); + private static final Pattern VERSION_PATTERN_CERTIFIED_11 = Pattern + .compile("^\\s*Asterisk certified/((SVN-branch|GIT)-)?11[-. ].*"); private static final Pattern VERSION_PATTERN_12 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?12[-. ].*"); private static final Pattern VERSION_PATTERN_13 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?13[-. ].*"); - private static final Pattern VERSION_PATTERN_CERTIFIED_13 = Pattern.compile("^\\s*Asterisk certified/((SVN-branch|GIT)-)?13[-. ].*"); + private static final Pattern VERSION_PATTERN_CERTIFIED_13 = Pattern + .compile("^\\s*Asterisk certified/((SVN-branch|GIT)-)?13[-. ].*"); private static final Pattern VERSION_PATTERN_14 = Pattern.compile("^\\s*Asterisk (GIT-)?14[-. ].*"); private static final AtomicLong idCounter = new AtomicLong(0); @@ -531,29 +535,26 @@ protected synchronized void doLogin(long timeout, String eventMask) connect(); } - synchronized (protocolIdentifier) + if (protocolIdentifier.getValue() == null) { - if (protocolIdentifier.value == null) + try { - try - { - protocolIdentifier.wait(timeout); - } - catch (InterruptedException e) // NOPMD - { - Thread.currentThread().interrupt(); - } + protocolIdentifier.await(timeout); } + catch (InterruptedException e) // NOPMD + { + Thread.currentThread().interrupt(); + } + } - if (protocolIdentifier.value == null) + if (protocolIdentifier.getValue() == null) + { + disconnect(); + if (reader != null && reader.getTerminationException() != null) { - disconnect(); - if (reader != null && reader.getTerminationException() != null) - { - throw reader.getTerminationException(); - } - throw new TimeoutException("Timeout waiting for protocol identifier"); + throw reader.getTerminationException(); } + throw new TimeoutException("Timeout waiting for protocol identifier"); } challengeAction = new ChallengeAction("MD5"); @@ -657,17 +658,24 @@ protected AsteriskVersion determineVersion() throws IOException, TimeoutExceptio // actionId='null'; message='Permission denied'; // response='Error'; // uniqueId='null'; systemHashcode=15231583 - if(showVersionFilesResponse.getOutput() != null){ - Asterisk14outputPresent = true; - }else{ - break; - } + if (showVersionFilesResponse.getOutput() != null) + { + Asterisk14outputPresent = true; + } + else + { + break; + } } - if(Asterisk14outputPresent){ - List outputList = Arrays.asList(showVersionFilesResponse.getOutput().split(SocketConnectionFacadeImpl.NL_PATTERN.pattern())); - showVersionFilesResult = outputList; - }else{ - showVersionFilesResult = ((CommandResponse) showVersionFilesResponse).getResult(); + if (Asterisk14outputPresent) + { + List outputList = Arrays + .asList(showVersionFilesResponse.getOutput().split(SocketConnectionFacadeImpl.NL_PATTERN.pattern())); + showVersionFilesResult = outputList; + } + else + { + showVersionFilesResult = ((CommandResponse) showVersionFilesResponse).getResult(); } if (showVersionFilesResult != null && !showVersionFilesResult.isEmpty()) { @@ -714,7 +722,7 @@ else if (VERSION_PATTERN_11.matcher(coreLine).matches()) { return AsteriskVersion.ASTERISK_11; } - else if (VERSION_PATTERN_CERTIFIED_11.matcher(coreLine).matches()) + else if (VERSION_PATTERN_CERTIFIED_11.matcher(coreLine).matches()) { return AsteriskVersion.ASTERISK_11; } @@ -726,7 +734,7 @@ else if (VERSION_PATTERN_13.matcher(coreLine).matches()) { return AsteriskVersion.ASTERISK_13; } - else if (VERSION_PATTERN_CERTIFIED_13.matcher(coreLine).matches()) + else if (VERSION_PATTERN_CERTIFIED_13.matcher(coreLine).matches()) { return AsteriskVersion.ASTERISK_13; } @@ -874,7 +882,7 @@ protected synchronized void disconnect() } socket = null; } - protocolIdentifier.value = null; + protocolIdentifier.reset(); } public ManagerResponse sendAction(ManagerAction action) @@ -883,41 +891,37 @@ public ManagerResponse sendAction(ManagerAction action) return sendAction(action, defaultResponseTimeout); } - /* + /** * Implements synchronous sending of "simple" actions. + * + * @param timeout - in milliseconds */ public ManagerResponse sendAction(ManagerAction action, long timeout) throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException { - ResponseHandlerResult result; - SendActionCallback callbackHandler; + ResponseHandlerResult result = new ResponseHandlerResult(); + SendActionCallback callbackHandler = new DefaultSendActionCallback(result); - result = new ResponseHandlerResult(); - callbackHandler = new DefaultSendActionCallback(result); + sendAction(action, callbackHandler); - synchronized (result) + // definitely return null for the response of user events + if (action instanceof UserEventAction) { - sendAction(action, callbackHandler); + return null; + } - // definitely return null for the response of user events - if (action instanceof UserEventAction) + // only wait if we did not yet receive the response. + // Responses may be returned really fast. + if (result.getResponse() == null) + { + try { - return null; + result.await(timeout); } - - // only wait if we did not yet receive the response. - // Responses may be returned really fast. - if (result.getResponse() == null) + catch (InterruptedException ex) { - try - { - result.wait(timeout); - } - catch (InterruptedException ex) - { - logger.warn("Interrupted while waiting for result"); - Thread.currentThread().interrupt(); - } + logger.warn("Interrupted while waiting for result"); + Thread.currentThread().interrupt(); } } @@ -1062,21 +1066,18 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas this.responseEventListeners.put(internalActionId, responseEventHandler); } - synchronized (responseEvents) + writer.sendAction(action, internalActionId); + // only wait if response has not yet arrived. + if (responseEvents.getResponse() == null || !responseEvents.isComplete()) { - writer.sendAction(action, internalActionId); - // only wait if response has not yet arrived. - if (responseEvents.getResponse() == null || !responseEvents.isComplete()) + try { - try - { - responseEvents.wait(timeout); - } - catch (InterruptedException e) - { - logger.warn("Interrupted while waiting for response events."); - Thread.currentThread().interrupt(); - } + responseEvents.await(timeout); + } + catch (InterruptedException e) + { + logger.warn("Interrupted while waiting for response events."); + Thread.currentThread().interrupt(); } } @@ -1157,7 +1158,7 @@ public void removeEventListener(final ManagerEventListener listener) public String getProtocolIdentifier() { - return protocolIdentifier.value; + return protocolIdentifier.getValue(); } public ManagerConnectionState getState() @@ -1414,11 +1415,14 @@ private void setProtocolIdentifier(final String identifier) // 13 && !"Asterisk Call Manager/2.7.0".equals(identifier) // Asterisk // 13.2 - && !"Asterisk Call Manager/2.8.0".equals(identifier) // Asterisk > 13.5 + && !"Asterisk Call Manager/2.8.0".equals(identifier) // Asterisk + // > 13.5 + + && !"Asterisk Call Manager/2.9.0".equals(identifier) // Asterisk + // > 13.13 - && !"Asterisk Call Manager/2.9.0".equals(identifier) // Asterisk > 13.13 - - && !"Asterisk Call Manager/3.1.0".equals(identifier) //Asterisk =14.3.0 + && !"Asterisk Call Manager/3.1.0".equals(identifier) // Asterisk + // =14.3.0 && !"OpenPBX Call Manager/1.0".equals(identifier) && !"CallWeaver Call Manager/1.0".equals(identifier) && !(identifier != null && identifier.startsWith("Asterisk Call Manager Proxy/"))) @@ -1426,11 +1430,9 @@ private void setProtocolIdentifier(final String identifier) logger.warn("Unsupported protocol version '" + identifier + "'. Use at your own risk."); } - synchronized (protocolIdentifier) - { - protocolIdentifier.value = identifier; - protocolIdentifier.notifyAll(); - } + protocolIdentifier.setValue(identifier); + protocolIdentifier.countDown(); + } /** @@ -1551,6 +1553,7 @@ private static class ResponseHandlerResult implements Serializable */ private static final long serialVersionUID = 7831097958568769220L; private ManagerResponse response; + private final CountDownLatch latch = new CountDownLatch(1); public ResponseHandlerResult() { @@ -1565,6 +1568,21 @@ public void setResponse(ManagerResponse response) { this.response = response; } + + private void countDown() + { + latch.countDown(); + } + + /** + * @param millis - milliseconds to wait + * @throws InterruptedException + */ + private void await(long millis) throws InterruptedException + { + latch.await(millis, TimeUnit.MILLISECONDS); + } + } /** @@ -1591,11 +1609,8 @@ public DefaultSendActionCallback(ResponseHandlerResult result) public void onResponse(ManagerResponse response) { - synchronized (result) - { - result.setResponse(response); - result.notifyAll(); - } + result.setResponse(response); + result.countDown(); } } @@ -1623,57 +1638,46 @@ public ResponseEventHandler(ResponseEventsImpl events, Class< ? > actionComplete public void onManagerEvent(ManagerEvent event) { - synchronized (events) + // should always be a ResponseEvent, anyway... + if (event instanceof ResponseEvent) { - // should always be a ResponseEvent, anyway... - if (event instanceof ResponseEvent) - { - ResponseEvent responseEvent; + ResponseEvent responseEvent; - responseEvent = (ResponseEvent) event; - events.addEvent(responseEvent); - } + responseEvent = (ResponseEvent) event; + events.addEvent(responseEvent); + } - // finished? - if (actionCompleteEventClass.isAssignableFrom(event.getClass())) + // finished? + if (actionCompleteEventClass.isAssignableFrom(event.getClass())) + { + events.setComplete(true); + // notify if action complete event and response have been + // received + if (events.getResponse() != null) { - events.setComplete(true); - // notify if action complete event and response have been - // received - if (events.getResponse() != null) - { - events.notifyAll(); - } + events.countDown(); } } } public void onResponse(ManagerResponse response) { - synchronized (events) + events.setRepsonse(response); + if (response instanceof ManagerError) { - events.setRepsonse(response); - if (response instanceof ManagerError) - { - events.setComplete(true); - } + events.setComplete(true); + } - // finished? - // notify if action complete event and response have been - // received - if (events.isComplete()) - { - events.notifyAll(); - } + // finished? + // notify if action complete event and response have been + // received + if (events.isComplete()) + { + events.countDown(); } } } - private static class ProtocolIdentifierWrapper - { - String value; - } - @Override public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) { diff --git a/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java b/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java new file mode 100644 index 000000000..74c1d6d9d --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java @@ -0,0 +1,37 @@ +package org.asteriskjava.manager.internal; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +class ProtocolIdentifierWrapper +{ + private CountDownLatch latch = new CountDownLatch(1); + private String value; + + void reset() + { + value = null; + latch = new CountDownLatch(1); + } + + void await(long timeout) throws InterruptedException + { + latch.await(timeout, TimeUnit.MILLISECONDS); + } + + String getValue() + { + return value; + } + + void countDown() + { + latch.countDown(); + } + + public void setValue(String identifier) + { + value = identifier; + + } +} diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java index f94013923..8d056cc2c 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java @@ -18,12 +18,13 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.manager.response.ManagerResponse; - /** * Implementation of the ResponseEvents interface. * @@ -36,6 +37,7 @@ public class ResponseEventsImpl implements ResponseEvents private ManagerResponse response; private final Collection events; private boolean complete; + private final CountDownLatch latch = new CountDownLatch(1); /** * Creates a new instance. @@ -98,4 +100,18 @@ public void setComplete(boolean complete) { this.complete = complete; } + + /** + * @param timeout - milliseconds + * @throws InterruptedException + */ + public void await(long timeout) throws InterruptedException + { + latch.await(timeout, TimeUnit.MILLISECONDS); + } + + public void countDown() + { + latch.countDown(); + } } From 30c148050b11319c09ebd467d725ad0d37acf00b Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 18 Sep 2017 15:31:54 +1000 Subject: [PATCH 117/802] fix for possible NPE --- .../pbx/internal/activity/SplitActivityImpl.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index a0b2b7918..f10e9a825 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -58,12 +58,14 @@ public SplitActivityImpl(final Call callToSplit, final ActivityCallback tmp = callToSplit.getChannels(); + if (tmp.size() > 1) + { + channel1 = tmp.get(0); + channel2 = tmp.get(1); + } this.startActivity(true); + } @Override From 92208d4508b61519749d38b404fc83999acd0645 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 19 Sep 2017 15:36:42 +1000 Subject: [PATCH 118/802] new PlayMessage activity --- .../agi/AgiChannelActivityPlayMessage.java | 54 +++++++++++++++++++ .../pbx/internal/core/AsteriskPBX.java | 3 +- .../core/CoherentManagerEventQueue.java | 2 +- 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java new file mode 100644 index 000000000..b9f0083e8 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java @@ -0,0 +1,54 @@ +package org.asteriskjava.pbx.agi; + +import java.util.concurrent.TimeUnit; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.pbx.AgiChannelActivityAction; +import org.asteriskjava.pbx.Channel; + +public class AgiChannelActivityPlayMessage implements AgiChannelActivityAction +{ + + private String file; + private boolean hangup = false; + + public AgiChannelActivityPlayMessage(String file) + { + this.file = file; + } + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + if (ichannel == null) + { + throw new NullPointerException("ichannel cannot be null"); + } + String tmp = file; + if (file.indexOf(".") > 0) + { + tmp = file.substring(0, file.indexOf(".")); + } + channel.exec("Playtones", "beep"); + TimeUnit.MILLISECONDS.sleep(100); + channel.streamFile(tmp); + channel.exec("Playtones", "beep"); + TimeUnit.MILLISECONDS.sleep(100); + channel.hangup(); + hangup = true; + + } + + @Override + public boolean isDisconnect() + { + return hangup; + } + + @Override + public void cancel(Channel channel) + { + hangup = true; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 668e78f2f..1a9c1ffff 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -15,6 +15,7 @@ import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.ActivityStatusEnum; +import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.Call.OperandChannel; @@ -856,7 +857,7 @@ public ChannelProxy getProxyById(String id) return liveChannels.findProxyById(id); } - public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, AgiChannelActivityHold action, + public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, AgiChannelActivityAction action, ActivityCallback iCallback) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index 5ac5ef7f0..65f435076 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -241,7 +241,7 @@ public void dispatchEvent(final ManagerEvent event) if (time.timeTaken() > 500) { logger.warn("ManagerListener :" + filter._listener.getName() //$NON-NLS-1$ - + " is taken too long to process events " + " time taken: " + time.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$ + + " is taken too long to process event " + event + " time taken: " + time.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$ } } } From c0524a6dda05f893ec6334936021e7c7c512783f Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 19 Sep 2017 15:47:09 +1000 Subject: [PATCH 119/802] increase logging around hangup actions --- .../org/asteriskjava/examples/activities/Dial.java | 14 +++++++++++--- .../activity/BlindTransferActivityImpl.java | 1 + .../pbx/internal/activity/DialActivityImpl.java | 2 ++ .../internal/activity/DialToAgiActivityImpl.java | 1 + .../pbx/internal/activity/ParkActivityImpl.java | 6 ++++++ .../pbx/internal/core/DialLocalToAgiActivity.java | 2 +- .../internal/managerAPI/OriginateBaseClass.java | 4 +++- 7 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/examples/activities/Dial.java b/src/main/java/org/asteriskjava/examples/activities/Dial.java index db3c6e636..3cbdae526 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Dial.java +++ b/src/main/java/org/asteriskjava/examples/activities/Dial.java @@ -11,9 +11,13 @@ import org.asteriskjava.pbx.TechType; import org.asteriskjava.pbx.Trunk; import org.asteriskjava.pbx.activities.DialActivity; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; public class Dial { + static private Log logger = LogFactory.getLog(Dial.class); + static public void main(String[] args) { syncDial(); @@ -32,8 +36,10 @@ static private void syncDial() { PBX pbx = PBXFactory.getActivePBX(); - // The trunk MUST match the section header (e.g. [default]) that appears - // in your /etc/asterisk/sip.d file (assuming you are using a SIP trunk). + // The trunk MUST match the section header (e.g. [default]) that + // appears + // in your /etc/asterisk/sip.d file (assuming you are using a SIP + // trunk). // The trunk is used to select which SIP trunk to dial through. Trunk trunk = pbx.buildTrunk("default"); @@ -53,9 +59,10 @@ static private void syncDial() DialActivity dial = pbx.dial(from, fromCallerID, to, toCallerID); Call call = dial.getNewCall(); - + Thread.sleep(20000); + logger.warn("Hanging up"); pbx.hangup(call); } catch (PBXException | InterruptedException e) @@ -94,6 +101,7 @@ public void progress(DialActivity activity, ActivityStatusEnum status, String me // Call is up Call call = activity.getNewCall(); // So lets just hangup the call + logger.warn("Hanging up"); PBXFactory.getActivePBX().hangup(call.getOriginatingParty()); } catch (PBXException e) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index bd77aa89a..bf2535db4 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -165,6 +165,7 @@ public boolean doActivity() throws PBXException } else if (_completionCause == CompletionCause.CANCELLED) { + logger.warn("Cancelled, hanging up dialed channel"); pbx.hangup(dialedChannel); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java index e24989771..115967350 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java @@ -138,10 +138,12 @@ private void hangup() final PBX pbx = PBXFactory.getActivePBX(); if (this.acceptingChannel != null) { + logger.warn("Hanging up"); pbx.hangup(this.acceptingChannel); } if (this.originatingChannel != null) { + logger.warn("Hanging up"); pbx.hangup(this.originatingChannel); } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index c21f1caa5..1180506f2 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -121,6 +121,7 @@ private void hangup() if (this.originatingChannel != null) { + logger.warn("Hanging up"); pbx.hangup(this.originatingChannel); } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java index 346aafe81..5d4343a72 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java @@ -109,9 +109,15 @@ public boolean doActivity() throws PBXException // Hangup the call as we have parked the other side of // the call. if (this._call.getDirection() == CallDirection.INBOUND) + { + logger.warn("Hanging up"); pbx.hangup(this._call.getAcceptingParty()); + } else + { + logger.warn("Hanging up"); pbx.hangup(this._call.getOriginatingParty()); + } success = true; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java index 1951a44de..856285670 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -112,7 +112,7 @@ public void run() public void abort(final String reason) { - logger.debug("Aborting originate "); + logger.warn("Aborting originate "); this.close(); for (Channel channel : channels) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 8e20f976f..17f1fc41f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -221,6 +221,7 @@ protected OriginateResult originate(final EndPoint local, final EndPoint target, { try { + logger.warn("Hanging up"); pbx.hangup(this.newChannel); } catch (IllegalArgumentException | IllegalStateException | PBXException e) @@ -242,7 +243,7 @@ void abort(final String reason) this.hungup = true; if (this.newChannel != null) { - OriginateBaseClass.logger.debug("Aborted, Hangup up on the way out");//$NON-NLS-1$ + OriginateBaseClass.logger.warn("Aborted, Hangup up on the way out");//$NON-NLS-1$ this.result.setChannelHungup(true); PBX pbx = PBXFactory.getActivePBX(); @@ -308,6 +309,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) PBX pbx = PBXFactory.getActivePBX(); try { + logger.warn("Hanging up"); pbx.hangup(this.newChannel); } catch (IllegalArgumentException | IllegalStateException | PBXException e) From 9bb571aec4a09d8dbb5eda87a73e5b8db665ae53 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 28 Sep 2017 15:00:24 +1000 Subject: [PATCH 120/802] reduced severity of logging --- src/main/java/org/asteriskjava/pbx/CallImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/CallImpl.java b/src/main/java/org/asteriskjava/pbx/CallImpl.java index 96f7b1782..a72805160 100644 --- a/src/main/java/org/asteriskjava/pbx/CallImpl.java +++ b/src/main/java/org/asteriskjava/pbx/CallImpl.java @@ -868,8 +868,7 @@ public Channel getOperandChannel(OperandChannel operand) } if (channel == null) { - Exception e = new Exception("failed to get channel for " + operand); - logger.warn(e, e); + logger.warn("failed to get channel for " + operand); } return channel; } From 646ac15555fb9eb45cbfc78ca95cf061e59b1d53 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 2 Oct 2017 15:28:45 +1100 Subject: [PATCH 121/802] NA-5273 #Committed play controls for message play back --- .../pbx/agi/AgiChannelActivityPlayMessage.java | 6 +++++- .../pbx/internal/activity/BridgeActivityImpl.java | 4 ++-- .../pbx/internal/managerAPI/RedirectToMeetMe.java | 11 ++++++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java index b9f0083e8..0ab78b529 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java @@ -32,7 +32,11 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } channel.exec("Playtones", "beep"); TimeUnit.MILLISECONDS.sleep(100); - channel.streamFile(tmp); + // file, escape, offset, forward, rewind, pause + + // # to exit, 6 forward, 4 back, 5 pause + channel.controlStreamFile(tmp, "#", 5000, "6", "4", "5"); + channel.exec("Playtones", "beep"); TimeUnit.MILLISECONDS.sleep(100); channel.hangup(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java index 8fc8b22fe..2c9d83eed 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java @@ -100,7 +100,7 @@ else if (pbx.isMeetmeInstalled()) MeetmeRoom room = pbx.acquireMeetmeRoom(new DurationRoomOwner(30, TimeUnit.SECONDS)); // redirect the lhs to meetme - meetmeTransfer.redirectToMeetme(_lhsChannel, room.getRoomNumber(), true); + meetmeTransfer.redirectToMeetme(_lhsChannel, room.getRoomNumber(), true, false); // redirect destination this is not the marked call // as we want this to be hung up if no other calls are left @@ -108,7 +108,7 @@ else if (pbx.isMeetmeInstalled()) // this // room final boolean markedCall = !_rhsChannel.canDetectHangup(); - meetmeTransfer.redirectToMeetme(_rhsChannel, room.getRoomNumber(), markedCall); + meetmeTransfer.redirectToMeetme(_rhsChannel, room.getRoomNumber(), markedCall, false); // TODO put some logic to check that the meetme actually // completes. diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java index 992683d89..f5f2ce284 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java @@ -17,7 +17,8 @@ public RedirectToMeetMe() super(); } - public boolean redirectToMeetme(final Channel channel, final String room, final boolean markedUser) throws PBXException + public boolean redirectToMeetme(final Channel channel, final String room, final boolean markedUser, + final boolean passDTMF) throws PBXException { final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); /* @@ -33,11 +34,15 @@ public boolean redirectToMeetme(final Channel channel, final String room, final String options = new String(); if (markedUser == true) { - options = "qdxAF"; //$NON-NLS-1$ + options = "qdxA"; //$NON-NLS-1$ } else { - options = "qdxF"; //$NON-NLS-1$ + options = "qdx"; //$NON-NLS-1$ + } + if (passDTMF) + { + options += "F"; } if (!pbx.moveChannelToAgi(channel)) From 5499eceeeb6726955983994ef27f60087256e249 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 10 Oct 2017 14:26:16 +1100 Subject: [PATCH 122/802] change the jump back duration to 30 seconds --- .../org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java index 0ab78b529..e77d8039d 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java @@ -35,7 +35,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I // file, escape, offset, forward, rewind, pause // # to exit, 6 forward, 4 back, 5 pause - channel.controlStreamFile(tmp, "#", 5000, "6", "4", "5"); + channel.controlStreamFile(tmp, "#", 30000, "", "4", "5"); channel.exec("Playtones", "beep"); TimeUnit.MILLISECONDS.sleep(100); From 9c442e4d42da2a1c86ed72d30c075b1e00e516c4 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 10 Oct 2017 16:21:23 +1100 Subject: [PATCH 123/802] change duration and key --- .../org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java index e77d8039d..346a8e92e 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java @@ -35,7 +35,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I // file, escape, offset, forward, rewind, pause // # to exit, 6 forward, 4 back, 5 pause - channel.controlStreamFile(tmp, "#", 30000, "", "4", "5"); + channel.controlStreamFile(tmp, "#", 15000, "6", "4", "5"); channel.exec("Playtones", "beep"); TimeUnit.MILLISECONDS.sleep(100); From f1226e84728dc3ab24196d4e5139b7fd8e3e1157 Mon Sep 17 00:00:00 2001 From: Stephanie Miller Date: Wed, 11 Oct 2017 15:50:22 -0400 Subject: [PATCH 124/802] Asterisk 13 changes rtt to a float in manager Changed secStringToDouble to have a check for a period in the number and if so try to convert it as a float and then downcast. --- .../org/asteriskjava/manager/event/AbstractRtcpEvent.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java index 5b52b74da..2e85118a0 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java @@ -92,6 +92,11 @@ protected Long secStringToLong(String s) { return null; } + + //things like RTT can be float/double in the event message in newer asterisk versions + if(s.contains(".")) { + return secStringToDouble(s).longValue(); + } if (s.endsWith("(sec)")) { From 36e4634093e00609d0380fa124e65ecda2eeaa06 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 16 Oct 2017 10:49:30 +1100 Subject: [PATCH 125/802] throw exception on bad controlStream request --- .../pbx/agi/AgiChannelActivityPlayMessage.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java index 346a8e92e..5d3a06960 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java @@ -35,7 +35,15 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I // file, escape, offset, forward, rewind, pause // # to exit, 6 forward, 4 back, 5 pause - channel.controlStreamFile(tmp, "#", 15000, "6", "4", "5"); + try + { + channel.controlStreamFile(tmp, "#", 15000, "6", "4", "5"); + } + catch (Exception e) + { + TimeUnit.MILLISECONDS.sleep(100); + throw e; + } channel.exec("Playtones", "beep"); TimeUnit.MILLISECONDS.sleep(100); From 314ef7dbaee0e7a51fb5be3f41ccc3593bfbc6f3 Mon Sep 17 00:00:00 2001 From: Almazzzs Date: Tue, 17 Oct 2017 12:59:04 +0500 Subject: [PATCH 126/802] Remove unnessecary fields, setters, getters from descedant events --- .../manager/event/AbstractChannelEvent.java | 2 +- .../manager/event/HangupEvent.java | 12 --------- .../manager/event/NewChannelEvent.java | 26 ------------------- 3 files changed, 1 insertion(+), 39 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java index 46b2517ac..f31bfc45e 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java @@ -29,7 +29,7 @@ public abstract class AbstractChannelEvent extends ManagerEvent */ static final long serialVersionUID = 5906599407896179295L; - private String accountCode; + protected String accountCode; /** * The name of the channel. diff --git a/src/main/java/org/asteriskjava/manager/event/HangupEvent.java b/src/main/java/org/asteriskjava/manager/event/HangupEvent.java index 9d842526d..fa54fab92 100644 --- a/src/main/java/org/asteriskjava/manager/event/HangupEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/HangupEvent.java @@ -35,8 +35,6 @@ public class HangupEvent extends AbstractChannelStateEvent private String language; private String linkedId; private String connectedlinenum; - - private String accountCode; public HangupEvent(Object source) { @@ -96,16 +94,6 @@ public void setCauseTxt(String causeTxt) this.causeTxt = causeTxt; } - public String getAccountCode() - { - return accountCode; - } - - public void setAccountCode(String accountCode) - { - this.accountCode = accountCode; - } - public String getLinkedId() { return linkedId; diff --git a/src/main/java/org/asteriskjava/manager/event/NewChannelEvent.java b/src/main/java/org/asteriskjava/manager/event/NewChannelEvent.java index f7983206b..e731dbdaf 100644 --- a/src/main/java/org/asteriskjava/manager/event/NewChannelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/NewChannelEvent.java @@ -30,8 +30,6 @@ public class NewChannelEvent extends AbstractChannelStateEvent * Serializable version identifier. */ static final long serialVersionUID = 1L; - - private String accountCode; private String language; private String linkedid; @@ -50,30 +48,6 @@ public void setLanguage(String language) this.language = language; } - /** - * Returns the account code of the new channel. - *

- * This property is available since Asterisk 1.6. - * - * @return the account code of the new channel. - * @since 1.0.0 - */ - public String getAccountCode() - { - return accountCode; - } - - /** - * Sets the account code of the new channel. - * - * @param accountCode the account code of the new channel. - * @since 1.0.0 - */ - public void setAccountCode(String accountCode) - { - this.accountCode = accountCode; - } - public String getLinkedid() { return linkedid; From 84ba68d930cb2a42362dd12d3a6b3d5b55fdc2a0 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 31 Oct 2017 11:48:05 +1100 Subject: [PATCH 127/802] fixes for AsteriskPBX and ChannelImpl around rename event --- .../java/org/asteriskjava/pbx/Channel.java | 17 ++++---- .../pbx/asterisk/wrap/events/RenameEvent.java | 9 +++++ .../pbx/internal/core/AsteriskPBX.java | 14 ++++++- .../pbx/internal/core/ChannelImpl.java | 39 +++++++++++++------ .../pbx/internal/core/ChannelProxy.java | 4 +- .../pbx/internal/core/LiveChannelManager.java | 25 ++++++------ 6 files changed, 75 insertions(+), 33 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/Channel.java b/src/main/java/org/asteriskjava/pbx/Channel.java index 7c018eb30..cc0552231 100644 --- a/src/main/java/org/asteriskjava/pbx/Channel.java +++ b/src/main/java/org/asteriskjava/pbx/Channel.java @@ -148,14 +148,6 @@ public interface Channel */ CallerID getCallerID(); - /** - * Called to rename a channel - * - * @param newname the new name of the channel - * @throws InvalidChannelName - */ - void rename(String newName) throws InvalidChannelName; - /** * Returns a PBX specific version of the Channel name. * @@ -185,4 +177,13 @@ public interface Channel void setCallerId(CallerID buildCallerID); + /** + * Called to rename a channel + * + * @param newname the new name of the channel + * @throws InvalidChannelName + */ + + void rename(String newName, String uniqueId) throws InvalidChannelName; + } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java index 3f122000d..9a4d88456 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java @@ -24,6 +24,8 @@ public class RenameEvent extends ManagerEvent implements ChannelEvent */ private final String _newName; + private String uniqueId; + public RenameEvent(final org.asteriskjava.manager.event.RenameEvent event) throws InvalidChannelName { super(event); @@ -35,6 +37,8 @@ public RenameEvent(final org.asteriskjava.manager.event.RenameEvent event) throw String uniqueId = ((ChannelProxy) this._channel).getRealChannel().getUniqueId(); logger.debug("Renaming :" + uniqueId + " " + event.getUniqueId()); + this.uniqueId = event.getUniqueId(); + assert uniqueId.equalsIgnoreCase("-1") || uniqueId.compareToIgnoreCase(event.getUniqueId()) == 0 : "Rename registered against incorrect channel"; //$NON-NLS-1$ @@ -51,6 +55,11 @@ public final String getNewName() return this._newName; } + public final String getUniqueId() + { + return uniqueId; + } + @Override public String toString() { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 1a9c1ffff..1dcad6642 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -523,8 +523,15 @@ public CallerID buildCallerID(final AbstractChannelEvent event) return this.buildCallerID(number, name); } - public Channel registerChannel(final String channelName, final String uniqueID) throws InvalidChannelName + public Channel registerChannel(final String channelName, final String uniqueIdParam) throws InvalidChannelName { + String uniqueID = uniqueIdParam; + if (uniqueIdParam == null || uniqueIdParam.length() == 0) + { + uniqueID = ChannelImpl.UNKNOWN_UNIQUE_ID; + } + + logger.error("Registering channel " + channelName + " " + uniqueID); if (channelName == null || channelName.trim().length() == 0) { throw new IllegalArgumentException("Channel name must not be empty"); @@ -766,6 +773,11 @@ public boolean waitForChannelsToQuiescent(List channels, long timeout) if (elapsed >= timeout) { logger.error("Channels didn't Quiescent"); + for (Channel channel : channels) + { + logger.error(channel); + } + } return timeout > elapsed; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index 68da48cf1..a4a39d3a5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -59,7 +59,7 @@ public class ChannelImpl implements Channel * a channel can be 're-created' on the fly. In this case the channels name * will be the same but the unique id will change. */ - final private String _uniqueID; + private String _uniqueID; /** * This is an abbreviated form of the channel name obtained by removing * everything after the '-' in the channel name. @@ -82,7 +82,7 @@ public class ChannelImpl implements Channel private boolean _parked = false; - private boolean _isZombie = false; + private volatile boolean _isZombie = false; /** * A channel is live if it has not been hungup. @@ -94,14 +94,14 @@ public class ChannelImpl implements Channel * Masqueraded channels have an extra suffix after the sequence * number e.g. SIP/100-000009823 */ - private boolean _isMasqueraded = false; + private volatile boolean _isMasqueraded = false; /** * Indicates that the channel is undergoing an action such as being parked. * Action channels have an extra prefix before the tech e.g. * Parked/SIP/100-000009823 */ - private boolean _isInAction = false; + private volatile boolean _isInAction = false; /** * Indicates that the channel has been originated directly from the Asterisk @@ -257,13 +257,6 @@ else if (ChannelImpl.logCounter == 0) } } - @Override - public void rename(final String newName) throws InvalidChannelName - { - this.setChannelName(newName); - - } - /** * validates the channel name. Validate is to be called after the channel * has been cleaned. @@ -385,6 +378,30 @@ private String cleanChannelName(final String name) return cleanedName; } + @Override + public void rename(final String newName, String uniqueId) throws InvalidChannelName + { + + String oldChannelName = getChannelName(); + logger.warn("Changing " + oldChannelName + " to " + newName + " on " + oldChannelName + " " + _uniqueID); + this.setChannelName(newName); + + if (_uniqueID.equalsIgnoreCase("-1")) + { + logger.warn("Changing " + _uniqueID + " to " + uniqueId + " on " + oldChannelName + " " + _uniqueID); + _uniqueID = uniqueId; + } + + // the new replacement channel will go through a rename (without + // MASQ) and is ready to use. + + // the old channel will go through a rename (MASQ), then anther + // rename (ZOMBIE) and finally a hangup + + _isInAction = false; + + } + @Override public String getChannelName() { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index e266844ac..4ef87cc0a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -189,9 +189,9 @@ public CallerID getCallerID() } @Override - public void rename(String newName) throws InvalidChannelName + public void rename(String newName, String uniqueId) throws InvalidChannelName { - this._channel.rename(newName); + this._channel.rename(newName, uniqueId); } @Override diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index afa508330..e41a31df0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -90,7 +90,7 @@ public void add(ChannelProxy proxy) } logger.debug("Adding liveChannel " + proxy); - dumpProxies(proxy, "Add"); //$NON-NLS-1$ + dumpProxies(proxy, "Add"); sanityCheck(); } @@ -99,10 +99,10 @@ private void dumpProxies(ChannelProxy proxy, String cause) { if (logger.isDebugEnabled()) { - logger.debug("Dump of LiveChannels, cause:" + cause + ": " + proxy); //$NON-NLS-1$ //$NON-NLS-2$ + logger.debug("Dump of LiveChannels, cause:" + cause + ": " + proxy); //$NON-NLS-2$ for (ChannelProxy aProxy : _liveChannels) { - logger.debug("ChannelProxy: " + aProxy); //$NON-NLS-1$ + logger.debug("ChannelProxy: " + aProxy); } } } @@ -116,7 +116,7 @@ public void remove(ChannelProxy proxy) logger.info("Removing liveChannel " + proxy); this._liveChannels.remove(index); } - dumpProxies(proxy, "Removing"); //$NON-NLS-1$ + dumpProxies(proxy, "Removing"); } @@ -250,7 +250,7 @@ public void onManagerEvent(ManagerEvent event) // now the active channel // and everyone will be happy. originalProxy.masquerade(cloneProxy); - dumpProxies(cloneProxy, "Masquerade"); //$NON-NLS-1$ + dumpProxies(cloneProxy, "Masquerade"); sanityCheck(); } catch (InvalidChannelName e) @@ -261,8 +261,8 @@ public void onManagerEvent(ManagerEvent event) } else - logger.error("Either the clone or original channelProxy was missing during a masquerade: cloneIndex=" //$NON-NLS-1$ - + cloneIndex + " originalIndex=" + originalIndex); //$NON-NLS-1$ + logger.error("Either the clone or original channelProxy was missing during a masquerade: cloneIndex=" + + cloneIndex + " originalIndex=" + originalIndex); } if (event instanceof RenameEvent) @@ -274,8 +274,9 @@ public void onManagerEvent(ManagerEvent event) { try { - oldChannel.rename(rename.getNewName()); - dumpProxies(oldChannel, "RenameEvent"); //$NON-NLS-1$ + oldChannel.rename(rename.getNewName(), rename.getUniqueId()); + + dumpProxies(oldChannel, "RenameEvent"); sanityCheck(); } catch (InvalidChannelName e) @@ -307,10 +308,12 @@ else if (event instanceof HangupEvent) ChannelProxy proxy = findProxy(hangup.getChannel()); if (proxy != null) { + logger.debug("Removing proxy " + proxy); + this._liveChannels.remove(proxy); logger.debug("Removing liveChannel " + proxy); proxy.getChannel().notifyHangupListeners(hangup.getCause(), hangup.getCauseTxt()); - dumpProxies(proxy, "HangupEvent"); //$NON-NLS-1$ + dumpProxies(proxy, "HangupEvent"); } } @@ -324,7 +327,7 @@ else if (event instanceof HangupEvent) @Override public String getName() { - return "LiveChannelManager"; //$NON-NLS-1$ + return "LiveChannelManager"; } @Override From 59ebc8bf7c1618556135057054ef663f58d547f9 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 31 Oct 2017 12:15:58 +1100 Subject: [PATCH 128/802] lower logging levels --- .../java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java | 1 - .../java/org/asteriskjava/pbx/internal/core/ChannelImpl.java | 4 ++-- .../asteriskjava/pbx/internal/core/LiveChannelManager.java | 4 +++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 1dcad6642..6b5393938 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -531,7 +531,6 @@ public Channel registerChannel(final String channelName, final String uniqueIdPa uniqueID = ChannelImpl.UNKNOWN_UNIQUE_ID; } - logger.error("Registering channel " + channelName + " " + uniqueID); if (channelName == null || channelName.trim().length() == 0) { throw new IllegalArgumentException("Channel name must not be empty"); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index a4a39d3a5..ec85a7704 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -383,12 +383,12 @@ public void rename(final String newName, String uniqueId) throws InvalidChannelN { String oldChannelName = getChannelName(); - logger.warn("Changing " + oldChannelName + " to " + newName + " on " + oldChannelName + " " + _uniqueID); + logger.info("Changing " + oldChannelName + " to " + newName + " on " + oldChannelName + " " + _uniqueID); this.setChannelName(newName); if (_uniqueID.equalsIgnoreCase("-1")) { - logger.warn("Changing " + _uniqueID + " to " + uniqueId + " on " + oldChannelName + " " + _uniqueID); + logger.info("Changing " + _uniqueID + " to " + uniqueId + " on " + oldChannelName + " " + _uniqueID); _uniqueID = uniqueId; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index e41a31df0..49cccbfec 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -286,7 +286,9 @@ public void onManagerEvent(ManagerEvent event) } else { - logger.warn("Unable to rename channel -> Failed to find channel " + rename.getChannel()); + String message = "Unable to rename channel -> Failed to find channel " + rename.getChannel(); + logger.warn(message); + dumpProxies(null, message); } } else if (event instanceof HangupEvent) From e1c8decd5ef31775b345913bc39c91ed770f50bb Mon Sep 17 00:00:00 2001 From: Yuri Orlov Date: Tue, 31 Oct 2017 22:00:43 +0300 Subject: [PATCH 129/802] remove redundant instanceof check --- src/main/java/org/asteriskjava/util/AstUtil.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/AstUtil.java b/src/main/java/org/asteriskjava/util/AstUtil.java index a6a875bd6..1aa348dc7 100644 --- a/src/main/java/org/asteriskjava/util/AstUtil.java +++ b/src/main/java/org/asteriskjava/util/AstUtil.java @@ -92,16 +92,7 @@ public static boolean isTrue(Object o) return (Boolean) o; } - final String s; - if (o instanceof String) - { - s = (String) o; - } - else - { - s = o.toString(); - } - return TRUE_LITERALS.contains(s.toLowerCase(Locale.US)); + return TRUE_LITERALS.contains(o.toString().toLowerCase(Locale.US)); } /** From f3a7167424267894f198a76327d8ddf54be2bd48 Mon Sep 17 00:00:00 2001 From: Stephanie Miller Date: Thu, 2 Nov 2017 13:52:57 -0400 Subject: [PATCH 130/802] Match code style. --- .../java/org/asteriskjava/manager/event/AbstractRtcpEvent.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java index 2e85118a0..482e209f5 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java @@ -94,7 +94,8 @@ protected Long secStringToLong(String s) } //things like RTT can be float/double in the event message in newer asterisk versions - if(s.contains(".")) { + if(s.contains(".")) + { return secStringToDouble(s).longValue(); } From 81f8197982f126f6e841b41f73526a4e942169db Mon Sep 17 00:00:00 2001 From: Brett Sutton Date: Wed, 8 Nov 2017 09:42:16 +1100 Subject: [PATCH 131/802] Added a default class for the asterisk settings. --- .gitignore | 1 + .../activities/ExamplesAsteriskSettings.java | 121 +++++------------- .../asteriskjava/pbx/AsteriskSettings.java | 6 + .../pbx/DefaultAsteriskSettings.java | 106 +++++++++++++++ 4 files changed, 142 insertions(+), 92 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java diff --git a/.gitignore b/.gitignore index ebf99b0ef..647fe6c60 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ classes /bin build/ /.settings/ +/.metadata/ diff --git a/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java b/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java index b4abcced2..f7a5d0629 100644 --- a/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java +++ b/src/main/java/org/asteriskjava/examples/activities/ExamplesAsteriskSettings.java @@ -1,99 +1,36 @@ package org.asteriskjava.examples.activities; -import org.asteriskjava.pbx.AsteriskSettings; +import org.asteriskjava.pbx.DefaultAsteriskSettings; -public class ExamplesAsteriskSettings implements AsteriskSettings +public class ExamplesAsteriskSettings extends DefaultAsteriskSettings { - @Override - public int getManagerPortNo() - { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getManagerPassword() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getManagerUsername() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getAsteriskIP() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public Integer getMeetmeBaseAddress() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean getDisableBridge() - { - // TODO Auto-generated method stub - return false; - } - - @Override - public String getManagementContext() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getExtensionPark() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getDialTimeout() - { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getAutoAnswer() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getAgiExtension() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean getCanDetectHangup() - { - // TODO Auto-generated method stub - return false; - } - - @Override - public String getAgiHost() - { - // TODO Auto-generated method stub - return "127.0.0.1"; - } + @Override + public String getManagerPassword() + { + // this password MUST match the password (secret=) in manager.conf + return "a good password"; + } + + @Override + public String getManagerUsername() + { + // this MUST match the section header '[myconnection]' in manager.conf + return "myconnection"; + } + + @Override + public String getAsteriskIP() + { + // The IP address or FQDN of your Asterisk server. + return "2.2.2.2"; + } + + @Override + public String getAgiHost() + { + // The IP Address of FQDN of you asterisk-java application. + return "1.1.1.1"; + } } diff --git a/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java b/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java index e4f880577..9ae400bd0 100644 --- a/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java +++ b/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java @@ -103,6 +103,12 @@ public interface AsteriskSettings */ boolean getCanDetectHangup(); + /** + * The IP address of FQDN of the asterisk-java application. + * Currenly only used if you are doing 'activities' but its + * safer to just set this. + * @return + */ String getAgiHost(); } diff --git a/src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java b/src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java new file mode 100644 index 000000000..50008aaf1 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java @@ -0,0 +1,106 @@ +package org.asteriskjava.pbx; + +/** + * A convenience class that provides a set of defaults that will work + * for most people. + * + * You can over-ride any specific methods for settings that you need to change. + * + * Key thing to watch out for is that we user a meetme range of 3000-3200. + * If you are already using this range for other meetme rooms then you need + * to over-ride the getMeetMeBaseAddress. + * + * If you are using handsets other than yealink or snom you should also over-ride + * the getAutoAnswer settings. + * + * @author bsutton + * + */ +public abstract class DefaultAsteriskSettings implements AsteriskSettings +{ + + @Override + public int getManagerPortNo() + { + return 5060; + } + + @Override + public Integer getMeetmeBaseAddress() + { + // We use conference rooms. Just make certain that the base address + // doesn't overlap any conference rooms you are currently running on your pbx. + // You should probably allow 200 conference rooms here e.g. (3000-3200) + // Actions like transfers (and conference calls) use a conference room. + return new Integer(3000); + } + + @Override + public boolean getDisableBridge() + { + // Return false if you version of asterisk supports bridging channels. + // All version after 1.8 support bridging. + return false; + } + + @Override + public String getManagementContext() + { + // This is an asterisk dialplan context. + // Simply pick a context which doesn't already exist + // and use AsteriskPBX.createAgiEntryPoint() + // to inject the necessary dialplan used by asterisk-java + return "asteriskjava"; + } + + @Override + public String getExtensionPark() + { + // Return an asterisk dialplan extension (within the Management Context) + // that will be used to park calls. + // Just ensure that its a unique asterisk dialplan extension name. + return "asterisk-java-park"; + } + + @Override + public int getDialTimeout() + { + // Return the amount of time to wait (in seconds) when dialing before we give up + // when the call isn't answered + return 30; + } + + /* + * If you are using handsets other than yealink or snom you should over-ride + * these method to return the correct auto-answer string for you handset type. + * + * If you neve use the auto answer feature in the dial command you can + * ignore this setting. + */ + @Override + public String getAutoAnswer() + { + // Return the auto-answer heading used by your organisations handsets + // to force them to auto-answer when we ring the handset. + // Bad luck if you have incompatible handsets. + return "Call-Info:\\; answer-after=0"; + } + + @Override + public String getAgiExtension() + { + // Return an asterisk dialplan extension (within the Management Context) + // that will be used to inject the agi dialplan entry point used by Activites.. + // Just ensure that its a unique asterisk dialplan extension name. + return "asterisk-java-agi"; + } + + @Override + public boolean getCanDetectHangup() + { + // Return try if the telephony tech you are dialing from can reliabily + // detect hangups. + return true; + } + +} From bf2da02ce5ff91217b396da58fda3271ae32eb64 Mon Sep 17 00:00:00 2001 From: Brett Sutton Date: Wed, 8 Nov 2017 09:54:56 +1100 Subject: [PATCH 132/802] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 34dcb3144..7144eb0a7 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,14 @@ Activities are new to asterisk-java 2.0. The aim of Activities is to provide a h Activities provide a simple and consistent method of interaction with Asterisk without having to worry about issues such as connection management and without having to understand the intricacies of Asterisk Manager Actions and Events. +[Getting Started](https://github.com/asterisk-java/asterisk-java/wiki/Getting-Started) +[Tutorial](https://github.com/asterisk-java/asterisk-java/wiki/Tutorial) + +[Activities](https://github.com/asterisk-java/asterisk-java/wiki/Activities) + +[Examples](https://github.com/asterisk-java/asterisk-java/wiki/Examples) -See docs/tutorial.html for examples. GETTING ASTERISK-JAVA --------------------- From daf44873cc2e832754738cb0e1285ddcc4d4d6c9 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 9 Nov 2017 11:48:38 +1100 Subject: [PATCH 133/802] Allow LiveChannelManager to track calls created before initialization and all new calls in the system --- src/main/java/org/asteriskjava/pbx/PBX.java | 2 + .../java/org/asteriskjava/pbx/PBXFactory.java | 1 + .../asterisk/wrap/events/NewChannelEvent.java | 7 +++ .../internal/activity/SplitActivityImpl.java | 4 +- .../pbx/internal/core/AsteriskPBX.java | 11 +++++ .../pbx/internal/core/LiveChannelManager.java | 49 +++++++++++++++++++ 6 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/PBX.java b/src/main/java/org/asteriskjava/pbx/PBX.java index 0258b1985..08c7ff4ac 100644 --- a/src/main/java/org/asteriskjava/pbx/PBX.java +++ b/src/main/java/org/asteriskjava/pbx/PBX.java @@ -280,4 +280,6 @@ public void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandC public Trunk buildTrunk(String string); + public void performPostCreationTasks(); + } diff --git a/src/main/java/org/asteriskjava/pbx/PBXFactory.java b/src/main/java/org/asteriskjava/pbx/PBXFactory.java index b6fedfa2c..7a64e7e40 100644 --- a/src/main/java/org/asteriskjava/pbx/PBXFactory.java +++ b/src/main/java/org/asteriskjava/pbx/PBXFactory.java @@ -18,6 +18,7 @@ public static PBX getActivePBX() public static void init(AsteriskSettings newProfile) { profile.set(newProfile); + getActivePBX().performPostCreationTasks(); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java index 02fa2c271..eaf939e81 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java @@ -1,6 +1,8 @@ package org.asteriskjava.pbx.asterisk.wrap.events; import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; public class NewChannelEvent extends AbstractChannelStateEvent { @@ -16,6 +18,11 @@ public NewChannelEvent(final org.asteriskjava.manager.event.NewChannelEvent even this.accountCode = event.getAccountCode(); this.context = event.getContext(); this.exten = event.getExten(); + + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + pbx.internalRegisterChannel(event.getChannel(), event.getUniqueId()); + } public String getAccountCode() diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index f10e9a825..9d43b906a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -216,11 +216,11 @@ private boolean splitTwo() throws PBXException ctr += 100.0 / 1000.0; if (!agi1.hasCallReachedAgi()) { - logger.error("Waiting on (agi1) " + channel1); + logger.info("Waiting on (agi1) " + channel1); } if (!agi2.hasCallReachedAgi()) { - logger.error("Waiting on (agi2) " + channel2); + logger.info("Waiting on (agi2) " + channel2); } } ret = agi1.hasCallReachedAgi() && agi2.hasCallReachedAgi(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 6b5393938..0029db1f5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -112,6 +112,12 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener } + @Override + public void performPostCreationTasks() + { + liveChannels.performPostCreationTasks(); + } + /** * Call this method when shutting down the PBX interface to allow it to * cleanup. @@ -990,4 +996,9 @@ public String getTrunkAsString() }; } + public List getChannelList() + { + return liveChannels.getChannelList(); + } + } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index 49cccbfec..85d1fe98f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -1,18 +1,26 @@ package org.asteriskjava.pbx.internal.core; +import java.io.IOException; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; +import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.ListenerPriority; +import org.asteriskjava.pbx.asterisk.wrap.actions.StatusAction; import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.MasqueradeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; import org.asteriskjava.pbx.asterisk.wrap.events.RenameEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvents; +import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -63,6 +71,36 @@ public class LiveChannelManager implements FilteredManagerListener public LiveChannelManager() { CoherentManagerConnection.getInstance().addListener(this); + + } + + /** + * Find all the channels that came into existence before startup. This can't + * be done during the Constructor call, because it requires calls back to + * AsteriskPBX which isn't finished constructing until after the Constructor + * returns. + */ + void performPostCreationTasks() + { + StatusAction statusAction = new StatusAction(); + try + { + ResponseEvents events = CoherentManagerConnection.sendEventGeneratingAction(statusAction, 1000); + for (ResponseEvent event : events.getEvents()) + { + if (event instanceof StatusEvent) + { + // do nothing. Creating the events will register the + // channels, which is after all what we are trying to do. + } + } + + } + catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) + { + logger.error(e, e); + } + } public ChannelProxy getChannelByEndPoint(EndPoint endPoint) @@ -196,6 +234,10 @@ private ChannelProxy findProxy(Channel original) required.add(RenameEvent.class); required.add(HangupEvent.class); + // add NewChannelEvent so all channels are added to the + // LiveChannelManager + required.add(NewChannelEvent.class); + return required; } @@ -367,4 +409,11 @@ public void sanityCheck() } } + public List getChannelList() + { + List channels = new LinkedList<>(); + channels.addAll(_liveChannels); + return channels; + } + } From 57e4b81e496170caeaff44df09299c9a22352361 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 15 Dec 2017 09:31:16 +1100 Subject: [PATCH 134/802] reduce logging severity --- .../java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java | 4 ++++ .../pbx/internal/activity/RedirectToActivityImpl.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java index bedfd35fe..09461fdb8 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java @@ -38,6 +38,10 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I { channel.stopMusicOnHold(); } + catch (AgiHangupException e) + { + logger.info("Channel hungup " + channel.getName()); + } catch (Exception e) { logger.warn(e); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java index b9b913bf5..1ab3fa7aa 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java @@ -181,7 +181,7 @@ private boolean splitTwo() throws PBXException ctr += 100.0 / 1000.0; if (!agi1.hasCallReachedAgi()) { - logger.error("Waiting on (agi1) " + channel1); + logger.warn("Waiting on (agi1) " + channel1); } } From 72b36d2e4f7c39c92c690aa0beb6c30f14d1c245 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 15 Dec 2017 10:16:57 +1100 Subject: [PATCH 135/802] 2.0.2 release build --- pom.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ca5da88f3..0d38de8c2 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 2.0.1.alpha-SNAPSHOT + 2.0.2 The free Java library for Asterisk PBX integration. 2004 @@ -251,12 +251,17 @@ org.apache.maven.plugins maven-gpg-plugin 1.5 + + EA919AF2 + sign-artifacts verify + sign + From bbf8044719a67f573185370ff5a27bd743f26124 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 15 Dec 2017 10:21:12 +1100 Subject: [PATCH 136/802] new version number 2.0.3-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0d38de8c2..cddf121a6 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 2.0.2 + 2.0.3-SNAPSHOT The free Java library for Asterisk PBX integration. 2004 From bb514d10e8cd7bed90e97f06b80e5ef8593da067 Mon Sep 17 00:00:00 2001 From: Marcin Turek Date: Thu, 18 Jan 2018 14:03:21 +0100 Subject: [PATCH 137/802] Fixing BridgeEnterEvents order comparision (uniqueId can be prefixed) --- .../bridge/BridgeEnterEventComparator.java | 38 +++ .../bridge/BridgeState.java | 102 ++------ .../BridgeEnterEventComparatorTest.java | 237 ++++++++++++++++++ 3 files changed, 297 insertions(+), 80 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java create mode 100644 src/test/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparatorTest.java diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java new file mode 100644 index 000000000..8e3112169 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java @@ -0,0 +1,38 @@ +package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; + +import org.asteriskjava.manager.event.BridgeEnterEvent; + +import java.util.Comparator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class BridgeEnterEventComparator implements Comparator { + + private static final String UNIQUE_ID_PATTERN = "([0-9]+)\\.([0-9]+)$"; + + @Override + public int compare(BridgeEnterEvent o1, BridgeEnterEvent o2) { + Pattern uniqueIdPattern = Pattern.compile(UNIQUE_ID_PATTERN); + Matcher uniqueId1Matcher = uniqueIdPattern.matcher(o1.getUniqueId()); + Matcher uniqueId2Matcher = uniqueIdPattern.matcher(o2.getUniqueId()); + + boolean find1 = uniqueId1Matcher.find(); + boolean find2 = uniqueId2Matcher.find(); + + if (find1 && find2) { + // 1501234567.890 -> epochtime: 1501234567 | serial: 890 + long epochtime1 = Long.valueOf(uniqueId1Matcher.group(1)); + long epochtime2 = Long.valueOf(uniqueId2Matcher.group(1)); + int serial1 = Integer.valueOf(uniqueId1Matcher.group(2)); + int serial2 = Integer.valueOf(uniqueId2Matcher.group(2)); + + return epochtime1 == epochtime2 ? Integer.compare(serial1, serial2) : Long.compare(epochtime1, epochtime2); + } else if (!find1 && !find2) { + // Both of inputs are invalid value: id1 == id2 + return 0; + } else { + // id1 is valid ==> 1 + return find1 ? 1 : -1; + } + } +} diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index b055aa590..19dc393e7 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -1,12 +1,11 @@ package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.asteriskjava.manager.event.BridgeEnterEvent; import org.asteriskjava.manager.event.BridgeEvent; @@ -18,15 +17,17 @@ /** * Track the current members of a bridge, emmitting BridgeEvents when 2 members * join or breakup - * + * * @author rsutton */ class BridgeState { - final Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); + + private static final BridgeEnterEventComparator BRIDGE_ENTER_EVENT_COMPARATOR = new BridgeEnterEventComparator(); private final Map members = new HashMap<>(); - + ManagerEvent destroy() { synchronized (members) { @@ -37,7 +38,7 @@ ManagerEvent destroy() /** * if there are exactly 2 members in the bridge, return a BridgeEvent - * + * * @param event * @return */ @@ -72,7 +73,7 @@ ManagerEvent addMember(BridgeEnterEvent event) /** * If there are exactly 2 members in the bridge, return a BridgeEvent - * + * * @param event * @return */ @@ -80,7 +81,7 @@ ManagerEvent addMember(BridgeEnterEvent event) ManagerEvent removeMember(BridgeLeaveEvent event) { List remaining = null; - + synchronized (members) { if (members.remove(event.getChannel()) != null @@ -101,82 +102,23 @@ ManagerEvent removeMember(BridgeLeaveEvent event) BridgeEvent.BRIDGE_STATE_UNLINK, remaining); } - - private BridgeEvent buildBridgeEvent(String bridgeState, List members) - { - BridgeEvent bridgeEvent = new BridgeEvent(this); - int index1, index2; - if (this.compareUniqueId(members.get(0).getUniqueId(), - members.get(1).getUniqueId()) < 0) - { - index1 = 0; - index2 = 1; - } - else - { - index1 = 1; - index2 = 0; - } - bridgeEvent.setCallerId1(members.get(index1).getCallerIdNum()); - bridgeEvent.setUniqueId1(members.get(index1).getUniqueId()); - bridgeEvent.setChannel1(members.get(index1).getChannel()); + private BridgeEvent buildBridgeEvent(String bridgeState, List members) { + Collections.sort(members, BRIDGE_ENTER_EVENT_COMPARATOR); - bridgeEvent.setCallerId2(members.get(index2).getCallerIdNum()); - bridgeEvent.setUniqueId2(members.get(index2).getUniqueId()); - bridgeEvent.setChannel2(members.get(index2).getChannel()); + BridgeEvent bridgeEvent = new BridgeEvent(this); - bridgeEvent.setBridgeState(bridgeState); - bridgeEvent.setDateReceived(new Date()); + bridgeEvent.setCallerId1(members.get(0).getCallerIdNum()); + bridgeEvent.setUniqueId1(members.get(0).getUniqueId()); + bridgeEvent.setChannel1(members.get(0).getChannel()); - return bridgeEvent; - } + bridgeEvent.setCallerId2(members.get(1).getCallerIdNum()); + bridgeEvent.setUniqueId2(members.get(1).getUniqueId()); + bridgeEvent.setChannel2(members.get(1).getChannel()); - /** - * Compares two Asteirsk Unique ID. - * - * @param id1 1st Asterisk Unique ID, for example "1099015093.165". - * @param id2 2nd Asterisk Unique ID, for example "1099015093.166". - * @return Return 0 if id1 == id2. - * Return less then 0 if id1 < id2. - * Return greater then 0 if id1 > id2. - */ - private int compareUniqueId(String id1, String id2) - { - Pattern uniqueIdPattern = Pattern.compile("^([0-9]+)\\.([0-9]+)$"); - Matcher uniqueId1Matcher = uniqueIdPattern.matcher(id1); - Matcher uniqueId2Matcher = uniqueIdPattern.matcher(id2); - - boolean find1 = uniqueId1Matcher.find(); - boolean find2 = uniqueId2Matcher.find(); - - if (find1 && find2) - { - // 1501234567.890 -> epochtime: 1501234567 | serial: 890 - long epochtime1 = Long.valueOf(uniqueId1Matcher.group(1)); - long epochtime2 = Long.valueOf(uniqueId2Matcher.group(1)); - int serial1 = Integer.valueOf(uniqueId1Matcher.group(2)); - int serial2 = Integer.valueOf(uniqueId2Matcher.group(2)); - - if (epochtime1 == epochtime2) - { - return Integer.compare(serial1, serial2); - } + bridgeEvent.setBridgeState(bridgeState); + bridgeEvent.setDateReceived(new Date()); - return Long.compare(epochtime1, epochtime2); - - } - else if (!find1 && find2) - { - // id1 < id2 - return -1; - } - else if (find1 && !find2) - { - // id1 > id2 - return 1; - } - // Both of inputs are invalid value: id1 == id2 - return 0; - } + return bridgeEvent; + } } diff --git a/src/test/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparatorTest.java b/src/test/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparatorTest.java new file mode 100644 index 000000000..f0dab2bde --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparatorTest.java @@ -0,0 +1,237 @@ +package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; + +import org.asteriskjava.manager.event.BridgeEnterEvent; +import org.junit.Assert; +import org.junit.Test; + +public class BridgeEnterEventComparatorTest { + + private BridgeEnterEventComparator bridgeEnterEventComparator = new BridgeEnterEventComparator(); + + @Test + public void withoutPrefix_shouldId2BeGreater() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590350.29"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withoutPrefix_shouldId1BeGreater() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590350.29"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withoutPrefix_shouldId2BeGreaterForSameSerials() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590350.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withoutPrefix_shouldId1BeGreaterForSameSerials() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590350.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withoutPrefix_shouldId2BeGreaterForSameEpoch() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.29"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withoutPrefix_shouldId1BeGreaterForSameEpoch() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.29"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withoutPrefix_shouldIdsBeEqual() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(0, compareResult); + } + + @Test + public void withPrefix_shouldId2BeGreater() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.29"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withPrefix_shouldId1BeGreater() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.29"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withPrefix_shouldId2BeGreaterForSameSerials() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withPrefix_shouldId1BeGreaterForSameSerials() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withPrefix_shouldId2BeGreaterForSameEpoch() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.29"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withPrefix_shouldId1BeGreaterForSameEpoch() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.29"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withPrefix_shouldIdsBeEqual() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(0, compareResult); + } + + @Test + public void shouldBothIdsDoesNotMatchPattern() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_id_1"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_id_2"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(0, compareResult); + } + + @Test + public void shouldId1DoesNotMatchPattern() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_id_1"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void shouldId2DoesNotMatchPattern() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_id_2"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + private static BridgeEnterEvent createBridgeEnterEvent(String uniqueId) { + BridgeEnterEvent bridgeEnterEvent = new BridgeEnterEvent(new Object()); + bridgeEnterEvent.setUniqueId(uniqueId); + return bridgeEnterEvent; + } +} \ No newline at end of file From 5ba82d7711e0a636e2398a7431c69cbf871754f3 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 19 Jan 2018 10:02:29 +1100 Subject: [PATCH 138/802] minor logging change --- .../pbx/internal/core/DialLocalToAgiActivity.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java index 856285670..286f9a086 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -99,11 +99,7 @@ public void run() callback.progress(this, ActivityStatusEnum.SUCCESS, ActivityStatusEnum.SUCCESS.getDefaultMessage()); } - catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) - { - logger.error(e, e); - } - catch (InterruptedException e) + catch (Exception e) { logger.error(e, e); } From e4d1c2b06afc3b61eaf31625ebdc5cd565049519 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 29 Jan 2018 17:34:02 -0500 Subject: [PATCH 139/802] Add MixMonitor and StopMixMonitor AMI actions. These have been available since Asterisk 11 so I am not sure why they haven't made it into the project yet. Signed-off-by: Sean Bright --- .../manager/action/MixMonitorAction.java | 203 ++++++++++++++++++ .../manager/action/StopMixMonitorAction.java | 116 ++++++++++ .../manager/response/MixMonitorResponse.java | 51 +++++ 3 files changed, 370 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/action/MixMonitorAction.java create mode 100644 src/main/java/org/asteriskjava/manager/action/StopMixMonitorAction.java create mode 100644 src/main/java/org/asteriskjava/manager/response/MixMonitorResponse.java diff --git a/src/main/java/org/asteriskjava/manager/action/MixMonitorAction.java b/src/main/java/org/asteriskjava/manager/action/MixMonitorAction.java new file mode 100644 index 000000000..a66023ff2 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/MixMonitorAction.java @@ -0,0 +1,203 @@ +/* + * Copyright 2018 CallShaper, LLC + * + * 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.manager.action; + +import org.asteriskjava.manager.ExpectedResponse; +import org.asteriskjava.manager.response.MixMonitorResponse; + +/** + * Start a MixMonitor on the specified channel. + * + * Available since Asterisk 11 + * + * @see org.asteriskjava.manager.response.MixMonitorResponse + * @see StopMixMonitorAction + * @see PauseMixMonitorAction + * @see MixMonitorMuteAction + */ +@ExpectedResponse(MixMonitorResponse.class) +public class MixMonitorAction extends AbstractManagerAction +{ + private static final long serialVersionUID = 1L; + private String channel; + private String file; + private String options; + private String command; + + /** + * Creates a new empty MixMonitorAction + */ + public MixMonitorAction() + { + super(); + } + + /** + * Creates a new MixMonitorAction that starts monitoring the given channel + * using a default filename. + * + * @param channel the name of the channel to monitor + */ + public MixMonitorAction(String channel) + { + this(channel, null, null, null); + } + + /** + * Creates a new MixMonitorAction that starts monitoring the given channel + * with the specified filename. + * + * @param channel the name of the channel to monitor + * @param filename the filename to use for the recording + */ + public MixMonitorAction(String channel, String filename) + { + this(channel, filename, null, null); + } + + /** + * Creates a new MixMonitorAction with options that starts monitoring the + * given channel with the specified filename. + * + * @param channel the name of the channel to monitor + * @param filename the filename to use for the recording + * @param options the MixMonitor options to use when starting the recording + */ + public MixMonitorAction(String channel, String filename, String options) + { + this(channel, filename, options, null); + } + + /** + * Creates a new MixMonitorAction with options that starts monitoring the + * given channel with the specified filename. Also takes a command to + * execute when the recording has ended. + * + * The {@code command} option has been available since Asterisk 12 + * + * @param channel the name of the channel to monitor + * @param filename the filename to use for the recording + * @param options the MixMonitor options to use when starting the recording + * @param command the command to execute when the recording is complete + */ + public MixMonitorAction(String channel, String filename, String options, String command) + { + this.channel = channel; + this.file = filename; + this.options = options; + this.command = command; + } + + /** + * Returns the name of this action, i.e. "MixMonitor" + * + * @return the name of the AMI action that this class implements + */ + @Override + public String getAction() + { + return "MixMonitor"; + } + + /** + * Returns the name of the Asterisk channel to monitor. + * + * @return the Asterisk channel name + */ + public String getChannel() + { + return channel; + } + + /** + * Sets the name of the Asterisk channel to the given value. + * + * @param channel the Asterisk channel name + */ + public void setChannel(String channel) + { + this.channel = channel; + } + + /** + * Returns the filename that Asterisk will use when saving the recording. + * + * @return the recording filename + */ + public String getFile() + { + return file; + } + + /** + * Sets the filename that Asterisk will use when saving the recording. + * + * @param filename the recording filename + */ + public void setFile(String filename) + { + this.file = filename; + } + + /** + * Gets the options that are passed to MixMonitor. + * + * @return the MixMonitor options + */ + public String getOptions() + { + return options; + } + + /** + * Sets the options that are passed to MixMonitor. These should be + * specified in the same format you would use if you were invoking + * the MixMonitor dialplan application. + * + * @param options the MixMonitor options + */ + public void setOptions(String options) + { + this.options = options; + } + + /** + * Get the command to be executed when the MixMonitor recording has + * ended. + * + * Available since Asterisk 12 + * + * @return the command to execute + */ + public String getCommand() + { + return command; + } + + /** + * Sets the command to be executed when the MixMonitor recording has + * ended. + * + * Available since Asterisk 12 + * + * @param command the command to execute + */ + public void setCommand(String command) + { + this.command = command; + } +} diff --git a/src/main/java/org/asteriskjava/manager/action/StopMixMonitorAction.java b/src/main/java/org/asteriskjava/manager/action/StopMixMonitorAction.java new file mode 100644 index 000000000..79d172279 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/StopMixMonitorAction.java @@ -0,0 +1,116 @@ +/* + * Copyright 2018 CallShaper, LLC + * + * 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.manager.action; + +/** + * Stop the specified MixMonitor on the specified channel. + * + * Available since Asterisk 11 + * + * @see MixMonitorAction + * @see PauseMixMonitorAction + * @see MixMonitorMuteAction + */ +public class StopMixMonitorAction extends AbstractManagerAction +{ + private static final long serialVersionUID = 1L; + private String channel; + private String mixMonitorId; + + /** + * Creates a new empty StopMixMonitorAction + */ + public StopMixMonitorAction() + { + super(); + } + + /** + * Creates a StopMixMonitorAction that stops all MixMonitors on the + * specified channel. + * + * @param channel the name of the channel + */ + public StopMixMonitorAction(String channel) + { + this(channel, null); + } + + /** + * Creates a StopMixMonitorAction that stops the specified MixMonitor on + * the specified channel. + * + * @param channel the name of the channel + * @param mixMonitorId the ID of the MixMonitor to stop + */ + public StopMixMonitorAction(String channel, String mixMonitorId) + { + this.channel = channel; + this.mixMonitorId = mixMonitorId; + } + + /** + * Returns the name of this action, i.e. "StopMixMonitor" + * + * @return the name of the AMI action that this class implements + */ + @Override + public String getAction() + { + return "StopMixMonitor"; + } + + /** + * Returns the name of the Asterisk channel to monitor. + * + * @return the Asterisk channel name + */ + public String getChannel() + { + return channel; + } + + /** + * Sets the name of the Asterisk channel to the given value. + * + * @param channel the Asterisk channel name + */ + public void setChannel(String channel) + { + this.channel = channel; + } + + /** + * Returns the ID of the MixMonitor to stop. + * + * @return the MixMonitor ID + */ + public String getMixMonitorId() + { + return mixMonitorId; + } + + /** + * Sets the ID of the MixMonitor so stop. + * + * @param mixMonitorId the MixMonitor ID + */ + public void setMixMonitorId(String mixMonitorId) + { + this.mixMonitorId = mixMonitorId; + } +} \ No newline at end of file diff --git a/src/main/java/org/asteriskjava/manager/response/MixMonitorResponse.java b/src/main/java/org/asteriskjava/manager/response/MixMonitorResponse.java new file mode 100644 index 000000000..77609965f --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/response/MixMonitorResponse.java @@ -0,0 +1,51 @@ +/* + * Copyright 2018 CallShaper, LLC + * + * 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.manager.response; + +/** + * A MixMonitorResponse is sent in response to a MixMonitorAction and provides + * the ID of the MixMonitor that was started on the referenced channel. + * + * Available since Asterisk 11 + * + * @see org.asteriskjava.manager.action.MixMonitorAction; + */ +public class MixMonitorResponse extends ManagerResponse +{ + private static final long serialVersionUID = 1L; + private String mixMonitorId; + + /** + * Returns the ID of the MixMonitor + * + * @return the MixMonitor ID + */ + public String getMixMonitorId() + { + return mixMonitorId; + } + + /** + * Sets the ID of the MixMonitor + * + * @param mixMonitorId the MixMonitor ID + */ + public void setMixMonitorId(String mixMonitorId) + { + this.mixMonitorId = mixMonitorId; + } +} From 8690bd05aaf3c572c72ffb2bb3cd223ecf3c64d3 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 29 Jan 2018 18:43:10 -0500 Subject: [PATCH 140/802] Use 'dialplan show' for Asterisk 1.6.0+ Fixes #224 Signed-off-by: Sean Bright --- .../asteriskjava/pbx/internal/core/AsteriskPBX.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 0029db1f5..37d4a6117 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -947,9 +947,16 @@ public boolean createAgiEntryPoint() throws IOException, AuthenticationFailedExc public boolean checkDialplanExists(AsteriskSettings profile) throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException { - String ext = "show dialplan " + profile.getManagementContext(); + String command; - CommandAction action = new CommandAction(ext); + if (getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) { + // TODO: Use ShowDialplanAction instead of CommandAction? + command = "dialplan show " + profile.getManagementContext(); + } else { + command = "show dialplan " + profile.getManagementContext(); + } + + CommandAction action = new CommandAction(command); CommandResponse response = (CommandResponse) sendAction(action, 30000); boolean exists = false; From 83596ad6fbc83da8aa50edfc83afc698e148a8ac Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 30 Jan 2018 06:15:38 -0500 Subject: [PATCH 141/802] Fix some formatting in README.md --- README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7144eb0a7..d6d6e171b 100644 --- a/README.md +++ b/README.md @@ -40,19 +40,20 @@ Asterisk-Java is available from [here](https://github.com/asterisk-java/asterisk Maven Dependency ---------------- -Asterisk 1.0 +Asterisk-Java 2.0 - org.asteriskjava - asterisk-java - 1.0.0-final + org.asteriskjava + asterisk-java + 2.0.2 -Asterisk 2.0 +Asterisk-Java 1.0 + - org.asteriskjava - asterisk-java - 2.0.0-final + org.asteriskjava + asterisk-java + 1.0.0-final INSTALLATION FROM SOURCE From 96fd344b65b4c5aaad6bae5b459b4f1fef8f4723 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 30 Jan 2018 06:29:01 -0500 Subject: [PATCH 142/802] Add Asterisk 15 as a version option Signed-off-by: Sean Bright --- src/main/java/org/asteriskjava/AsteriskVersion.java | 6 ++++++ .../manager/internal/ManagerConnectionImpl.java | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index aea63e8f9..fc8fd9ecf 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -96,6 +96,12 @@ public class AsteriskVersion implements Comparable, Serializabl */ public static final AsteriskVersion ASTERISK_14 = new AsteriskVersion(1400, "Asterisk 14"); + /** + * Represents the Asterisk 15 series. + * + * @since 2.0.3 + */ + public static final AsteriskVersion ASTERISK_15 = new AsteriskVersion(1500, "Asterisk 15"); /** * Serial version identifier. diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 82511c256..875500214 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -104,6 +104,7 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher private static final Pattern VERSION_PATTERN_CERTIFIED_13 = Pattern .compile("^\\s*Asterisk certified/((SVN-branch|GIT)-)?13[-. ].*"); private static final Pattern VERSION_PATTERN_14 = Pattern.compile("^\\s*Asterisk (GIT-)?14[-. ].*"); + private static final Pattern VERSION_PATTERN_15 = Pattern.compile("^\\s*Asterisk (GIT-)?15[-. ].*"); private static final AtomicLong idCounter = new AtomicLong(0); @@ -742,6 +743,10 @@ else if (VERSION_PATTERN_14.matcher(coreLine).matches()) { return AsteriskVersion.ASTERISK_14; } + else if (VERSION_PATTERN_15.matcher(coreLine).matches()) + { + return AsteriskVersion.ASTERISK_15; + } } } From bdf476a33383077f7f6f24c94d7a2c8620bd9f56 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 30 Jan 2018 07:11:58 -0500 Subject: [PATCH 143/802] semver: The next release should be 2.1.0, not 2.0.3 Signed-off-by: Sean Bright --- src/main/java/org/asteriskjava/AsteriskVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index fc8fd9ecf..418dc0540 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -99,7 +99,7 @@ public class AsteriskVersion implements Comparable, Serializabl /** * Represents the Asterisk 15 series. * - * @since 2.0.3 + * @since 2.1.0 */ public static final AsteriskVersion ASTERISK_15 = new AsteriskVersion(1500, "Asterisk 15"); From 2d238f1b74b807148a5a9a1c72c5d568c3f965f4 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 30 Jan 2018 09:53:49 -0500 Subject: [PATCH 144/802] Various cleanups (no functional changes) - Tabs -> Spaces - Formatted code to align with other source files - Added Marcin as copyright holder and include license header Signed-off-by: Sean Bright --- .../bridge/BridgeEnterEventComparator.java | 80 +-- .../bridge/BridgeState.java | 30 +- .../BridgeEnterEventComparatorTest.java | 493 ++++++++++-------- 3 files changed, 329 insertions(+), 274 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java index 8e3112169..7aab5e319 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java @@ -1,3 +1,19 @@ +/* + * Copyright 2018 Marcin Turek + * + * 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.manager.internal.backwardsCompatibility.bridge; import org.asteriskjava.manager.event.BridgeEnterEvent; @@ -6,33 +22,39 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class BridgeEnterEventComparator implements Comparator { - - private static final String UNIQUE_ID_PATTERN = "([0-9]+)\\.([0-9]+)$"; - - @Override - public int compare(BridgeEnterEvent o1, BridgeEnterEvent o2) { - Pattern uniqueIdPattern = Pattern.compile(UNIQUE_ID_PATTERN); - Matcher uniqueId1Matcher = uniqueIdPattern.matcher(o1.getUniqueId()); - Matcher uniqueId2Matcher = uniqueIdPattern.matcher(o2.getUniqueId()); - - boolean find1 = uniqueId1Matcher.find(); - boolean find2 = uniqueId2Matcher.find(); - - if (find1 && find2) { - // 1501234567.890 -> epochtime: 1501234567 | serial: 890 - long epochtime1 = Long.valueOf(uniqueId1Matcher.group(1)); - long epochtime2 = Long.valueOf(uniqueId2Matcher.group(1)); - int serial1 = Integer.valueOf(uniqueId1Matcher.group(2)); - int serial2 = Integer.valueOf(uniqueId2Matcher.group(2)); - - return epochtime1 == epochtime2 ? Integer.compare(serial1, serial2) : Long.compare(epochtime1, epochtime2); - } else if (!find1 && !find2) { - // Both of inputs are invalid value: id1 == id2 - return 0; - } else { - // id1 is valid ==> 1 - return find1 ? 1 : -1; - } - } +public class BridgeEnterEventComparator implements Comparator +{ + private static final String UNIQUE_ID_PATTERN = "([0-9]+)\\.([0-9]+)$"; + + @Override + public int compare(BridgeEnterEvent o1, BridgeEnterEvent o2) + { + Pattern uniqueIdPattern = Pattern.compile(UNIQUE_ID_PATTERN); + Matcher uniqueId1Matcher = uniqueIdPattern.matcher(o1.getUniqueId()); + Matcher uniqueId2Matcher = uniqueIdPattern.matcher(o2.getUniqueId()); + + boolean find1 = uniqueId1Matcher.find(); + boolean find2 = uniqueId2Matcher.find(); + + if (find1 && find2) + { + // 1501234567.890 -> epochtime: 1501234567 | serial: 890 + long epochtime1 = Long.valueOf(uniqueId1Matcher.group(1)); + long epochtime2 = Long.valueOf(uniqueId2Matcher.group(1)); + int serial1 = Integer.valueOf(uniqueId1Matcher.group(2)); + int serial2 = Integer.valueOf(uniqueId2Matcher.group(2)); + + return epochtime1 == epochtime2 ? Integer.compare(serial1, serial2) : Long.compare(epochtime1, epochtime2); + } + else if (!find1 && !find2) + { + // Both of inputs are invalid value: id1 == id2 + return 0; + } + else + { + // id1 is valid ==> 1 + return find1 ? 1 : -1; + } + } } diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 19dc393e7..98a7295d1 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -22,9 +22,9 @@ */ class BridgeState { - private final Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); - private static final BridgeEnterEventComparator BRIDGE_ENTER_EVENT_COMPARATOR = new BridgeEnterEventComparator(); + private static final BridgeEnterEventComparator BRIDGE_ENTER_EVENT_COMPARATOR = new BridgeEnterEventComparator(); private final Map members = new HashMap<>(); @@ -103,22 +103,22 @@ ManagerEvent removeMember(BridgeLeaveEvent event) remaining); } - private BridgeEvent buildBridgeEvent(String bridgeState, List members) { - Collections.sort(members, BRIDGE_ENTER_EVENT_COMPARATOR); + private BridgeEvent buildBridgeEvent(String bridgeState, List members) { + Collections.sort(members, BRIDGE_ENTER_EVENT_COMPARATOR); - BridgeEvent bridgeEvent = new BridgeEvent(this); + BridgeEvent bridgeEvent = new BridgeEvent(this); - bridgeEvent.setCallerId1(members.get(0).getCallerIdNum()); - bridgeEvent.setUniqueId1(members.get(0).getUniqueId()); - bridgeEvent.setChannel1(members.get(0).getChannel()); + bridgeEvent.setCallerId1(members.get(0).getCallerIdNum()); + bridgeEvent.setUniqueId1(members.get(0).getUniqueId()); + bridgeEvent.setChannel1(members.get(0).getChannel()); - bridgeEvent.setCallerId2(members.get(1).getCallerIdNum()); - bridgeEvent.setUniqueId2(members.get(1).getUniqueId()); - bridgeEvent.setChannel2(members.get(1).getChannel()); + bridgeEvent.setCallerId2(members.get(1).getCallerIdNum()); + bridgeEvent.setUniqueId2(members.get(1).getUniqueId()); + bridgeEvent.setChannel2(members.get(1).getChannel()); - bridgeEvent.setBridgeState(bridgeState); - bridgeEvent.setDateReceived(new Date()); + bridgeEvent.setBridgeState(bridgeState); + bridgeEvent.setDateReceived(new Date()); - return bridgeEvent; - } + return bridgeEvent; + } } diff --git a/src/test/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparatorTest.java b/src/test/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparatorTest.java index f0dab2bde..da6261875 100644 --- a/src/test/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparatorTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparatorTest.java @@ -1,237 +1,270 @@ +/* + * Copyright 2018 Marcin Turek + * + * 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.manager.internal.backwardsCompatibility.bridge; import org.asteriskjava.manager.event.BridgeEnterEvent; import org.junit.Assert; import org.junit.Test; -public class BridgeEnterEventComparatorTest { - - private BridgeEnterEventComparator bridgeEnterEventComparator = new BridgeEnterEventComparator(); - - @Test - public void withoutPrefix_shouldId2BeGreater() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590350.29"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(-1, compareResult); - } - - @Test - public void withoutPrefix_shouldId1BeGreater() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590350.29"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(1, compareResult); - } - - @Test - public void withoutPrefix_shouldId2BeGreaterForSameSerials() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590350.30"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(-1, compareResult); - } - - @Test - public void withoutPrefix_shouldId1BeGreaterForSameSerials() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590350.30"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(1, compareResult); - } - - @Test - public void withoutPrefix_shouldId2BeGreaterForSameEpoch() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.29"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(-1, compareResult); - } - - @Test - public void withoutPrefix_shouldId1BeGreaterForSameEpoch() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.29"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(1, compareResult); - } - - @Test - public void withoutPrefix_shouldIdsBeEqual() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(0, compareResult); - } - - @Test - public void withPrefix_shouldId2BeGreater() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.29"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(-1, compareResult); - } - - @Test - public void withPrefix_shouldId1BeGreater() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.29"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(1, compareResult); - } - - @Test - public void withPrefix_shouldId2BeGreaterForSameSerials() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.30"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(-1, compareResult); - } - - @Test - public void withPrefix_shouldId1BeGreaterForSameSerials() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.30"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(1, compareResult); - } - - @Test - public void withPrefix_shouldId2BeGreaterForSameEpoch() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.29"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.30"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(-1, compareResult); - } - - @Test - public void withPrefix_shouldId1BeGreaterForSameEpoch() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.30"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.29"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(1, compareResult); - } - - @Test - public void withPrefix_shouldIdsBeEqual() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(0, compareResult); - } - - @Test - public void shouldBothIdsDoesNotMatchPattern() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_id_1"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_id_2"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(0, compareResult); - } - - @Test - public void shouldId1DoesNotMatchPattern() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_id_1"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(-1, compareResult); - } - - @Test - public void shouldId2DoesNotMatchPattern() { - // given - BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); - BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_id_2"); - - // when - int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); - - // then - Assert.assertEquals(1, compareResult); - } - - private static BridgeEnterEvent createBridgeEnterEvent(String uniqueId) { - BridgeEnterEvent bridgeEnterEvent = new BridgeEnterEvent(new Object()); - bridgeEnterEvent.setUniqueId(uniqueId); - return bridgeEnterEvent; - } +public class BridgeEnterEventComparatorTest +{ + private BridgeEnterEventComparator bridgeEnterEventComparator = new BridgeEnterEventComparator(); + + @Test + public void withoutPrefix_shouldId2BeGreater() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590350.29"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withoutPrefix_shouldId1BeGreater() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590350.29"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withoutPrefix_shouldId2BeGreaterForSameSerials() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590350.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withoutPrefix_shouldId1BeGreaterForSameSerials() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590350.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withoutPrefix_shouldId2BeGreaterForSameEpoch() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.29"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withoutPrefix_shouldId1BeGreaterForSameEpoch() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.29"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withoutPrefix_shouldIdsBeEqual() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(0, compareResult); + } + + @Test + public void withPrefix_shouldId2BeGreater() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.29"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withPrefix_shouldId1BeGreater() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.29"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withPrefix_shouldId2BeGreaterForSameSerials() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withPrefix_shouldId1BeGreaterForSameSerials() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withPrefix_shouldId2BeGreaterForSameEpoch() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.29"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void withPrefix_shouldId1BeGreaterForSameEpoch() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590350.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590350.29"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + @Test + public void withPrefix_shouldIdsBeEqual() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(0, compareResult); + } + + @Test + public void shouldBothIdsDoesNotMatchPattern() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_id_1"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_id_2"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(0, compareResult); + } + + @Test + public void shouldId1DoesNotMatchPattern() + { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_id_1"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_prefix-1515590353.30"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(-1, compareResult); + } + + @Test + public void shouldId2DoesNotMatchPattern() { + // given + BridgeEnterEvent bridgeEnterEvent1 = createBridgeEnterEvent("some_prefix-1515590353.30"); + BridgeEnterEvent bridgeEnterEvent2 = createBridgeEnterEvent("some_id_2"); + + // when + int compareResult = bridgeEnterEventComparator.compare(bridgeEnterEvent1, bridgeEnterEvent2); + + // then + Assert.assertEquals(1, compareResult); + } + + private static BridgeEnterEvent createBridgeEnterEvent(String uniqueId) + { + BridgeEnterEvent bridgeEnterEvent = new BridgeEnterEvent(new Object()); + bridgeEnterEvent.setUniqueId(uniqueId); + return bridgeEnterEvent; + } } \ No newline at end of file From 0ec4baffe3da50139caf754df16723a78432c6f9 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 30 Jan 2018 09:55:35 -0500 Subject: [PATCH 145/802] Only compile the UNIQUE_ID_PATTERN regex once. Signed-off-by: Sean Bright --- .../bridge/BridgeEnterEventComparator.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java index 7aab5e319..b104e2344 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java @@ -24,14 +24,13 @@ public class BridgeEnterEventComparator implements Comparator { - private static final String UNIQUE_ID_PATTERN = "([0-9]+)\\.([0-9]+)$"; + private static final Pattern UNIQUE_ID_PATTERN = Pattern.compile("([0-9]+)\\.([0-9]+)$"); @Override public int compare(BridgeEnterEvent o1, BridgeEnterEvent o2) { - Pattern uniqueIdPattern = Pattern.compile(UNIQUE_ID_PATTERN); - Matcher uniqueId1Matcher = uniqueIdPattern.matcher(o1.getUniqueId()); - Matcher uniqueId2Matcher = uniqueIdPattern.matcher(o2.getUniqueId()); + Matcher uniqueId1Matcher = UNIQUE_ID_PATTERN.matcher(o1.getUniqueId()); + Matcher uniqueId2Matcher = UNIQUE_ID_PATTERN.matcher(o2.getUniqueId()); boolean find1 = uniqueId1Matcher.find(); boolean find2 = uniqueId2Matcher.find(); From 3460e371926182816e3ba4a241c09ca44011927e Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 1 Feb 2018 10:32:01 +1100 Subject: [PATCH 146/802] change default max agi pool size to 500 --- src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java b/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java index 76bedea20..f6782de25 100644 --- a/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java @@ -27,7 +27,7 @@ public abstract class AbstractAgiServer /** * The default thread pool size. */ - private static final int DEFAULT_MAXIMUM_POOL_SIZE = 100; + private static final int DEFAULT_MAXIMUM_POOL_SIZE = 500; /** * The minimum number of worker threads in the thread pool. From 123155c713e7376776e043031155dce428eeaab7 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 1 Feb 2018 12:58:54 -0500 Subject: [PATCH 147/802] Add LocalOptimizationBegin and LocalOptimizationEnd events. Signed-off-by: Sean Bright --- .../event/LocalOptimizationBeginEvent.java | 488 ++++++++++++++++++ .../event/LocalOptimizationEndEvent.java | 344 ++++++++++++ .../manager/internal/EventBuilderImpl.java | 2 + 3 files changed, 834 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java diff --git a/src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java new file mode 100644 index 000000000..5b8948789 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java @@ -0,0 +1,488 @@ +/* + * Copyright 2018 Sean Bright + * + * 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.manager.event; + +/** + * Raised when two halves of a Local Channel begin to optimize themselves out + * of the media path. + * + * Available since Asterisk 12 + */ +public class LocalOptimizationBeginEvent extends ManagerEvent +{ + private static final long serialVersionUID = 0L; + + private Integer id; + private String destUniqueId; + + private String localOneChannel; + private String localOneChannelState; + private String localOneChannelStateDesc; + private String localOneCallerIDNum; + private String localOneCallerIDName; + private String localOneConnectedLineNum; + private String localOneConnectedLineName; + private String localOneAccountCode; + private String localOneContext; + private String localOneExten; + private Integer localOnePriority; + private String localOneUniqueid; + private String localOneLinkedid; + + private String localTwoChannel; + private String localTwoChannelState; + private String localTwoChannelStateDesc; + private String localTwoCallerIDNum; + private String localTwoCallerIDName; + private String localTwoConnectedLineNum; + private String localTwoConnectedLineName; + private String localTwoAccountCode; + private String localTwoContext; + private String localTwoExten; + private Integer localTwoPriority; + private String localTwoUniqueid; + private String localTwoLinkedid; + + private String sourceChannel; + private String sourceChannelState; + private String sourceChannelStateDesc; + private String sourceCallerIDNum; + private String sourceCallerIDName; + private String sourceConnectedLineNum; + private String sourceConnectedLineName; + private String sourceAccountCode; + private String sourceContext; + private String sourceExten; + private Integer sourcePriority; + private String sourceUniqueid; + private String sourceLinkedid; + + public LocalOptimizationBeginEvent(Object source) + { + super(source); + } + + public Integer getId() + { + return this.id; + } + + public void setId(Integer value) + { + this.id = value; + } + + public String getDestUniqueId() + { + return this.destUniqueId; + } + + public void setDestUniqueId(String value) + { + this.destUniqueId = value; + } + + public String getLocalOneChannel() + { + return this.localOneChannel; + } + + public void setLocalOneChannel(String value) + { + this.localOneChannel = value; + } + + public String getLocalOneChannelState() + { + return this.localOneChannelState; + } + + public void setLocalOneChannelState(String value) + { + this.localOneChannelState = value; + } + + public String getLocalOneChannelStateDesc() + { + return this.localOneChannelStateDesc; + } + + public void setLocalOneChannelStateDesc(String value) + { + this.localOneChannelStateDesc = value; + } + + public String getLocalOneCallerIDNum() + { + return this.localOneCallerIDNum; + } + + public void setLocalOneCallerIDNum(String value) + { + this.localOneCallerIDNum = value; + } + + public String getLocalOneCallerIDName() + { + return this.localOneCallerIDName; + } + + public void setLocalOneCallerIDName(String value) + { + this.localOneCallerIDName = value; + } + + public String getLocalOneConnectedLineNum() + { + return this.localOneConnectedLineNum; + } + + public void setLocalOneConnectedLineNum(String value) + { + this.localOneConnectedLineNum = value; + } + + public String getLocalOneConnectedLineName() + { + return this.localOneConnectedLineName; + } + + public void setLocalOneConnectedLineName(String value) + { + this.localOneConnectedLineName = value; + } + + public String getLocalOneAccountCode() + { + return this.localOneAccountCode; + } + + public void setLocalOneAccountCode(String value) + { + this.localOneAccountCode = value; + } + + public String getLocalOneContext() + { + return this.localOneContext; + } + + public void setLocalOneContext(String value) + { + this.localOneContext = value; + } + + public String getLocalOneExten() + { + return this.localOneExten; + } + + public void setLocalOneExten(String value) + { + this.localOneExten = value; + } + + public Integer getLocalOnePriority() + { + return this.localOnePriority; + } + + public void setLocalOnePriority(Integer value) + { + this.localOnePriority = value; + } + + public String getLocalOneUniqueid() + { + return this.localOneUniqueid; + } + + public void setLocalOneUniqueid(String value) + { + this.localOneUniqueid = value; + } + + public String getLocalOneLinkedid() + { + return this.localOneLinkedid; + } + + public void setLocalOneLinkedid(String value) + { + this.localOneLinkedid = value; + } + + public String getLocalTwoChannel() + { + return this.localTwoChannel; + } + + public void setLocalTwoChannel(String value) + { + this.localTwoChannel = value; + } + + public String getLocalTwoChannelState() + { + return this.localTwoChannelState; + } + + public void setLocalTwoChannelState(String value) + { + this.localTwoChannelState = value; + } + + public String getLocalTwoChannelStateDesc() + { + return this.localTwoChannelStateDesc; + } + + public void setLocalTwoChannelStateDesc(String value) + { + this.localTwoChannelStateDesc = value; + } + + public String getLocalTwoCallerIDNum() + { + return this.localTwoCallerIDNum; + } + + public void setLocalTwoCallerIDNum(String value) + { + this.localTwoCallerIDNum = value; + } + + public String getLocalTwoCallerIDName() + { + return this.localTwoCallerIDName; + } + + public void setLocalTwoCallerIDName(String value) + { + this.localTwoCallerIDName = value; + } + + public String getLocalTwoConnectedLineNum() + { + return this.localTwoConnectedLineNum; + } + + public void setLocalTwoConnectedLineNum(String value) + { + this.localTwoConnectedLineNum = value; + } + + public String getLocalTwoConnectedLineName() + { + return this.localTwoConnectedLineName; + } + + public void setLocalTwoConnectedLineName(String value) + { + this.localTwoConnectedLineName = value; + } + + public String getLocalTwoAccountCode() + { + return this.localTwoAccountCode; + } + + public void setLocalTwoAccountCode(String value) + { + this.localTwoAccountCode = value; + } + + public String getLocalTwoContext() + { + return this.localTwoContext; + } + + public void setLocalTwoContext(String value) + { + this.localTwoContext = value; + } + + public String getLocalTwoExten() + { + return this.localTwoExten; + } + + public void setLocalTwoExten(String value) + { + this.localTwoExten = value; + } + + public Integer getLocalTwoPriority() + { + return this.localTwoPriority; + } + + public void setLocalTwoPriority(Integer value) + { + this.localTwoPriority = value; + } + + public String getLocalTwoUniqueid() + { + return this.localTwoUniqueid; + } + + public void setLocalTwoUniqueid(String value) + { + this.localTwoUniqueid = value; + } + + public String getLocalTwoLinkedid() + { + return this.localTwoLinkedid; + } + + public void setLocalTwoLinkedid(String value) + { + this.localTwoLinkedid = value; + } + + public String getSourceChannel() + { + return this.sourceChannel; + } + + public void setSourceChannel(String value) + { + this.sourceChannel = value; + } + + public String getSourceChannelState() + { + return this.sourceChannelState; + } + + public void setSourceChannelState(String value) + { + this.sourceChannelState = value; + } + + public String getSourceChannelStateDesc() + { + return this.sourceChannelStateDesc; + } + + public void setSourceChannelStateDesc(String value) + { + this.sourceChannelStateDesc = value; + } + + public String getSourceCallerIDNum() + { + return this.sourceCallerIDNum; + } + + public void setSourceCallerIDNum(String value) + { + this.sourceCallerIDNum = value; + } + + public String getSourceCallerIDName() + { + return this.sourceCallerIDName; + } + + public void setSourceCallerIDName(String value) + { + this.sourceCallerIDName = value; + } + + public String getSourceConnectedLineNum() + { + return this.sourceConnectedLineNum; + } + + public void setSourceConnectedLineNum(String value) + { + this.sourceConnectedLineNum = value; + } + + public String getSourceConnectedLineName() + { + return this.sourceConnectedLineName; + } + + public void setSourceConnectedLineName(String value) + { + this.sourceConnectedLineName = value; + } + + public String getSourceAccountCode() + { + return this.sourceAccountCode; + } + + public void setSourceAccountCode(String value) + { + this.sourceAccountCode = value; + } + + public String getSourceContext() + { + return this.sourceContext; + } + + public void setSourceContext(String value) + { + this.sourceContext = value; + } + + public String getSourceExten() + { + return this.sourceExten; + } + + public void setSourceExten(String value) + { + this.sourceExten = value; + } + + public Integer getSourcePriority() + { + return this.sourcePriority; + } + + public void setSourcePriority(Integer value) + { + this.sourcePriority = value; + } + + public String getSourceUniqueid() + { + return this.sourceUniqueid; + } + + public void setSourceUniqueid(String value) + { + this.sourceUniqueid = value; + } + + public String getSourceLinkedid() + { + return this.sourceLinkedid; + } + + public void setSourceLinkedid(String value) + { + this.sourceLinkedid = value; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java new file mode 100644 index 000000000..61e27e10a --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java @@ -0,0 +1,344 @@ +/* + * Copyright 2018 Sean Bright + * + * 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.manager.event; + +/** + * Raised when two halves of a Local Channel have finished optimizing + * themselves out of the media path. + * + * Available since Asterisk 12 + */ +public class LocalOptimizationEndEvent extends ManagerEvent +{ + private static final long serialVersionUID = 0L; + + private Integer id; + private Boolean success; + + private String localOneChannel; + private String localOneChannelState; + private String localOneChannelStateDesc; + private String localOneCallerIDNum; + private String localOneCallerIDName; + private String localOneConnectedLineNum; + private String localOneConnectedLineName; + private String localOneAccountCode; + private String localOneContext; + private String localOneExten; + private Integer localOnePriority; + private String localOneUniqueid; + private String localOneLinkedid; + + private String localTwoChannel; + private String localTwoChannelState; + private String localTwoChannelStateDesc; + private String localTwoCallerIDNum; + private String localTwoCallerIDName; + private String localTwoConnectedLineNum; + private String localTwoConnectedLineName; + private String localTwoAccountCode; + private String localTwoContext; + private String localTwoExten; + private Integer localTwoPriority; + private String localTwoUniqueid; + private String localTwoLinkedid; + + public LocalOptimizationEndEvent(Object source) + { + super(source); + } + + public Integer getId() + { + return this.id; + } + + public void setId(Integer value) + { + this.id = value; + } + + public Boolean getSuccess() + { + return this.success; + } + + public void setSuccess(Boolean success) + { + this.success = success; + } + + public String getLocalOneChannel() + { + return this.localOneChannel; + } + + public void setLocalOneChannel(String value) + { + this.localOneChannel = value; + } + + public String getLocalOneChannelState() + { + return this.localOneChannelState; + } + + public void setLocalOneChannelState(String value) + { + this.localOneChannelState = value; + } + + public String getLocalOneChannelStateDesc() + { + return this.localOneChannelStateDesc; + } + + public void setLocalOneChannelStateDesc(String value) + { + this.localOneChannelStateDesc = value; + } + + public String getLocalOneCallerIDNum() + { + return this.localOneCallerIDNum; + } + + public void setLocalOneCallerIDNum(String value) + { + this.localOneCallerIDNum = value; + } + + public String getLocalOneCallerIDName() + { + return this.localOneCallerIDName; + } + + public void setLocalOneCallerIDName(String value) + { + this.localOneCallerIDName = value; + } + + public String getLocalOneConnectedLineNum() + { + return this.localOneConnectedLineNum; + } + + public void setLocalOneConnectedLineNum(String value) + { + this.localOneConnectedLineNum = value; + } + + public String getLocalOneConnectedLineName() + { + return this.localOneConnectedLineName; + } + + public void setLocalOneConnectedLineName(String value) + { + this.localOneConnectedLineName = value; + } + + public String getLocalOneAccountCode() + { + return this.localOneAccountCode; + } + + public void setLocalOneAccountCode(String value) + { + this.localOneAccountCode = value; + } + + public String getLocalOneContext() + { + return this.localOneContext; + } + + public void setLocalOneContext(String value) + { + this.localOneContext = value; + } + + public String getLocalOneExten() + { + return this.localOneExten; + } + + public void setLocalOneExten(String value) + { + this.localOneExten = value; + } + + public Integer getLocalOnePriority() + { + return this.localOnePriority; + } + + public void setLocalOnePriority(Integer value) + { + this.localOnePriority = value; + } + + public String getLocalOneUniqueid() + { + return this.localOneUniqueid; + } + + public void setLocalOneUniqueid(String value) + { + this.localOneUniqueid = value; + } + + public String getLocalOneLinkedid() + { + return this.localOneLinkedid; + } + + public void setLocalOneLinkedid(String value) + { + this.localOneLinkedid = value; + } + + public String getLocalTwoChannel() + { + return this.localTwoChannel; + } + + public void setLocalTwoChannel(String value) + { + this.localTwoChannel = value; + } + + public String getLocalTwoChannelState() + { + return this.localTwoChannelState; + } + + public void setLocalTwoChannelState(String value) + { + this.localTwoChannelState = value; + } + + public String getLocalTwoChannelStateDesc() + { + return this.localTwoChannelStateDesc; + } + + public void setLocalTwoChannelStateDesc(String value) + { + this.localTwoChannelStateDesc = value; + } + + public String getLocalTwoCallerIDNum() + { + return this.localTwoCallerIDNum; + } + + public void setLocalTwoCallerIDNum(String value) + { + this.localTwoCallerIDNum = value; + } + + public String getLocalTwoCallerIDName() + { + return this.localTwoCallerIDName; + } + + public void setLocalTwoCallerIDName(String value) + { + this.localTwoCallerIDName = value; + } + + public String getLocalTwoConnectedLineNum() + { + return this.localTwoConnectedLineNum; + } + + public void setLocalTwoConnectedLineNum(String value) + { + this.localTwoConnectedLineNum = value; + } + + public String getLocalTwoConnectedLineName() + { + return this.localTwoConnectedLineName; + } + + public void setLocalTwoConnectedLineName(String value) + { + this.localTwoConnectedLineName = value; + } + + public String getLocalTwoAccountCode() + { + return this.localTwoAccountCode; + } + + public void setLocalTwoAccountCode(String value) + { + this.localTwoAccountCode = value; + } + + public String getLocalTwoContext() + { + return this.localTwoContext; + } + + public void setLocalTwoContext(String value) + { + this.localTwoContext = value; + } + + public String getLocalTwoExten() + { + return this.localTwoExten; + } + + public void setLocalTwoExten(String value) + { + this.localTwoExten = value; + } + + public Integer getLocalTwoPriority() + { + return this.localTwoPriority; + } + + public void setLocalTwoPriority(Integer value) + { + this.localTwoPriority = value; + } + + public String getLocalTwoUniqueid() + { + return this.localTwoUniqueid; + } + + public void setLocalTwoUniqueid(String value) + { + this.localTwoUniqueid = value; + } + + public String getLocalTwoLinkedid() + { + return this.localTwoLinkedid; + } + + public void setLocalTwoLinkedid(String value) + { + this.localTwoLinkedid = value; + } +} diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index 51561966d..83207e2fa 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -137,6 +137,8 @@ private void registerBuiltinEventClasses() registerEventClass(LinkEvent.class); registerEventClass(ListDialplanEvent.class); registerEventClass(LocalBridgeEvent.class); + registerEventClass(LocalOptimizationBeginEvent.class); + registerEventClass(LocalOptimizationEndEvent.class); registerEventClass(LogChannelEvent.class); registerEventClass(NewConnectedLineEvent.class); registerEventClass(MasqueradeEvent.class); From c9308927228a9e1ca990fd6733d0d12d1b50bd46 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 1 Feb 2018 13:20:15 -0500 Subject: [PATCH 148/802] Add ContactStatus event Signed-off-by: Sean Bright --- .../manager/event/ContactStatusEvent.java | 139 ++++++++++++++++++ .../manager/internal/EventBuilderImpl.java | 1 + 2 files changed, 140 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/event/ContactStatusEvent.java diff --git a/src/main/java/org/asteriskjava/manager/event/ContactStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/ContactStatusEvent.java new file mode 100644 index 000000000..a2ef9ca1a --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/ContactStatusEvent.java @@ -0,0 +1,139 @@ +/* + * Copyright 2018 Sean Bright + * + * 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.manager.event; + +/** + * Raised when the state of a contact changes. + * + * Available since Asterisk 13 + */ +public class ContactStatusEvent extends ManagerEvent +{ + private static final long serialVersionUID = 0L; + + public static final String STATUS_CREATED = "Created"; + public static final String STATUS_REACHABLE = "Reachable"; + public static final String STATUS_REMOVED = "Removed"; + public static final String STATUS_UNKNOWN = "Unknown"; + public static final String STATUS_UNREACHABLE = "Unreachable"; + public static final String STATUS_UPDATED = "Updated"; + + private String uri; + private String contactStatus; + private String aor; + private String endpointName; + private String roundtripUsec; + private String userAgent; + private String regExpire; + private String viaAddress; + private String callID; + + public ContactStatusEvent(Object source) + { + super(source); + } + + public String getUri() + { + return uri; + } + + public void setUri(String value) + { + this.uri = value; + } + + public String getContactStatus() + { + return contactStatus; + } + + public void setContactStatus(String value) + { + this.contactStatus = value; + } + + public String getAor() + { + return aor; + } + + public void setAor(String value) + { + this.aor = value; + } + + public String getEndpointName() + { + return endpointName; + } + + public void setEndpointName(String value) + { + this.endpointName = value; + } + + public String getRoundtripUsec() + { + return roundtripUsec; + } + + public void setRoundtripUsec(String value) + { + this.roundtripUsec = value; + } + + public String getUserAgent() + { + return userAgent; + } + + public void setUserAgent(String value) + { + this.userAgent = value; + } + + public String getRegExpire() + { + return regExpire; + } + + public void setRegExpire(String value) + { + this.regExpire = value; + } + + public String getViaAddress() + { + return viaAddress; + } + + public void setViaAddress(String value) + { + this.viaAddress = value; + } + + public String getCallID() + { + return callID; + } + + public void setCallID(String callID) + { + this.callID = callID; + } +} diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index 83207e2fa..a22e98057 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -98,6 +98,7 @@ private void registerBuiltinEventClasses() registerEventClass(ConfbridgeListRoomsCompleteEvent.class); registerEventClass(ConfbridgeStartEvent.class); registerEventClass(ConfbridgeTalkingEvent.class); + registerEventClass(ContactStatusEvent.class); registerEventClass(CoreShowChannelEvent.class); registerEventClass(CoreShowChannelsCompleteEvent.class); registerEventClass(DAHDIChannelEvent.class); From 5b600cfd62e0ab8a55fb424c6014092ebcc42d27 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 1 Feb 2018 16:08:39 -0500 Subject: [PATCH 149/802] AbstractBuilder: Prefer StringBuilder to StringBuffer Signed-off-by: Sean Bright --- .../manager/internal/AbstractBuilder.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index 8dd944a21..58e1f2cb5 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -104,14 +104,14 @@ else if (dataType.isAssignableFrom(String.class)) value = null; } - if(value instanceof List){ - StringBuffer strBuff = new StringBuffer(); - for(String tmp : (List)value){ - if(tmp != null && tmp.length() != 0){ - strBuff.append(tmp + "\n"); - } - } - value = strBuff.toString(); + if (value instanceof List) { + StringBuilder strBuff = new StringBuilder(); + for (String tmp : (List) value) { + if (tmp != null && tmp.length() != 0) { + strBuff.append(tmp).append('\n'); + } + } + value = strBuff.toString(); } } else if (dataType.isAssignableFrom(Map.class)) From eb3782159c565012d17a09883e5f133c1f3da27d Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 1 Feb 2018 16:14:59 -0500 Subject: [PATCH 150/802] Enum constructors are always private. Signed-off-by: Sean Bright --- src/main/java/org/asteriskjava/live/HangupCause.java | 4 ++-- src/main/java/org/asteriskjava/pbx/CallDirection.java | 2 +- src/main/java/org/asteriskjava/util/MixMonitorDirection.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/live/HangupCause.java b/src/main/java/org/asteriskjava/live/HangupCause.java index fcbe9ff6e..ae08cccef 100644 --- a/src/main/java/org/asteriskjava/live/HangupCause.java +++ b/src/main/java/org/asteriskjava/live/HangupCause.java @@ -88,12 +88,12 @@ public enum HangupCause AST_CAUSE_NOTDEFINED(0), AST_CAUSE_NOSUCHDRIVER(AST_CAUSE_CHAN_NOT_IMPLEMENTED); - private HangupCause(int code) + HangupCause(int code) { this.code = code; } - private HangupCause(HangupCause cause) + HangupCause(HangupCause cause) { this.code = cause.code; } diff --git a/src/main/java/org/asteriskjava/pbx/CallDirection.java b/src/main/java/org/asteriskjava/pbx/CallDirection.java index 80baa9fc8..ac3f8a717 100644 --- a/src/main/java/org/asteriskjava/pbx/CallDirection.java +++ b/src/main/java/org/asteriskjava/pbx/CallDirection.java @@ -33,7 +33,7 @@ public enum CallDirection private final int dbValue; - private CallDirection(final int dbValue) + CallDirection(final int dbValue) { this.dbValue = dbValue; } diff --git a/src/main/java/org/asteriskjava/util/MixMonitorDirection.java b/src/main/java/org/asteriskjava/util/MixMonitorDirection.java index 69892378b..58a520155 100644 --- a/src/main/java/org/asteriskjava/util/MixMonitorDirection.java +++ b/src/main/java/org/asteriskjava/util/MixMonitorDirection.java @@ -13,7 +13,7 @@ public enum MixMonitorDirection String stateName; - private MixMonitorDirection(String name) + MixMonitorDirection(String name) { this.stateName = name; } From 2c053b4b7ef3ba09b3a527ceb892fac159eec9b6 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 1 Feb 2018 16:27:30 -0500 Subject: [PATCH 151/802] Interface members are public by definition. Signed-off-by: Sean Bright --- .../org/asteriskjava/fastagi/AgiChannel.java | 6 +++--- .../org/asteriskjava/live/AsteriskAgent.java | 7 +++---- .../org/asteriskjava/live/AsteriskQueue.java | 12 +++++------ .../live/AsteriskQueueMember.java | 10 +++++----- .../org/asteriskjava/live/AsteriskServer.java | 16 +++++++-------- .../asteriskjava/manager/AsteriskMapping.java | 2 +- .../manager/ManagerConnection.java | 2 +- .../manager/internal/ManagerWriter.java | 2 +- src/main/java/org/asteriskjava/pbx/Call.java | 4 ++-- .../java/org/asteriskjava/pbx/Channel.java | 2 +- .../java/org/asteriskjava/pbx/EndPoint.java | 18 ++++++++--------- src/main/java/org/asteriskjava/pbx/PBX.java | 20 +++++++++---------- .../pbx/activities/HoldActivity.java | 2 +- .../asterisk/wrap/events/ChannelEvent.java | 3 +-- .../pbx/internal/core/CallEndedListener.java | 3 +-- .../core/FilteredManagerListener.java | 9 ++++----- src/main/java/org/asteriskjava/util/Log.java | 2 +- 17 files changed, 58 insertions(+), 62 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/AgiChannel.java b/src/main/java/org/asteriskjava/fastagi/AgiChannel.java index f9082c703..279e7b4a6 100644 --- a/src/main/java/org/asteriskjava/fastagi/AgiChannel.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiChannel.java @@ -840,7 +840,7 @@ char controlStreamFile(String file, String escapeDigits, int offset, String forw * @param priority the priority of the called extension. * @since 1.0.0 */ - public void gosub(String context, String extension, String priority) throws AgiException; + void gosub(String context, String extension, String priority) throws AgiException; /** * Calls a subroutine in the dialplan @@ -856,7 +856,7 @@ char controlStreamFile(String file, String escapeDigits, int offset, String forw * of ${ARG1}, ${ARG2}, etc in the subroutine body. * @since 1.0.0 */ - public void gosub(String context, String extension, String priority, String... arguments) throws AgiException; + void gosub(String context, String extension, String priority, String... arguments) throws AgiException; /** * invoke the dial command @@ -866,7 +866,7 @@ char controlStreamFile(String file, String escapeDigits, int offset, String forw * @param options * @throws AgiException */ - public void dial(String target, int timeout, String options) throws AgiException; + void dial(String target, int timeout, String options) throws AgiException; /** * invoke the bridge command diff --git a/src/main/java/org/asteriskjava/live/AsteriskAgent.java b/src/main/java/org/asteriskjava/live/AsteriskAgent.java index f112c3912..96e61019f 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskAgent.java +++ b/src/main/java/org/asteriskjava/live/AsteriskAgent.java @@ -35,18 +35,17 @@ public interface AsteriskAgent extends LiveObject /** * @return the name */ - public String getName(); + String getName(); /** * @return the agentId */ - public String getAgentId(); + String getAgentId(); /** * Returns the state of this agent. * * @return the state the state of this agent. */ - public AgentState getState(); - + AgentState getState(); } diff --git a/src/main/java/org/asteriskjava/live/AsteriskQueue.java b/src/main/java/org/asteriskjava/live/AsteriskQueue.java index fe95a560b..23a4f4a41 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskQueue.java +++ b/src/main/java/org/asteriskjava/live/AsteriskQueue.java @@ -150,28 +150,28 @@ public interface AsteriskQueue * @return the ratio of calls answered within the specified service level per total completed * calls (in percent). */ - public Double getServiceLevelPerf(); + Double getServiceLevelPerf(); /** * Returns the number of completed calls. * @author itaqua * @return the number of completed calls. */ - public Integer getCompleted(); + Integer getCompleted(); /** * Returns the current average talk time for this queue based on an exponential average. * * @return the current average talk time for this queue. */ - public Integer getTalkTime(); + Integer getTalkTime(); /** * Returns the current average holdtime for this queue (in seconds). * @author itaqua * @return the current average holdtime for this queue (in seconds). */ - public Integer getHoldTime(); + Integer getHoldTime(); /** * Returns the number of calls currently waiting in the queue. @@ -180,7 +180,7 @@ public interface AsteriskQueue * @see getWaiting() * @return the number of calls currently waiting in the queue. */ - public Integer getCalls(); + Integer getCalls(); /** * Returns the number of calls currently waiting in the queue. @@ -188,7 +188,7 @@ public interface AsteriskQueue * @author itaqua * @return the number of calls currently waiting in the queue. */ - public Integer getWaiting(); + Integer getWaiting(); /** * timestamp (miliseconds) of last update of this object diff --git a/src/main/java/org/asteriskjava/live/AsteriskQueueMember.java b/src/main/java/org/asteriskjava/live/AsteriskQueueMember.java index f3a4a3ceb..e8951b6ea 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskQueueMember.java +++ b/src/main/java/org/asteriskjava/live/AsteriskQueueMember.java @@ -105,7 +105,7 @@ public interface AsteriskQueueMember extends LiveObject * if the added member is a static queue member. * @since 1.0.0 */ - public String getMembership(); + String getMembership(); /** * Convenience method that checks whether this member has been statically @@ -115,7 +115,7 @@ public interface AsteriskQueueMember extends LiveObject * queues.conf, false otherwise. * @since 1.0.0 */ - public boolean isStatic(); + boolean isStatic(); /** * Convenience method that checks whether this member has been dynamically @@ -125,7 +125,7 @@ public interface AsteriskQueueMember extends LiveObject * the QueueAdd command, false otherwise. * @since 1.0.0 */ - public boolean isDynamic(); + boolean isDynamic(); /** * Returns the penalty of this member. @@ -152,12 +152,12 @@ public interface AsteriskQueueMember extends LiveObject * @author itaqua * @return */ - public abstract Long getLastCall(); + Long getLastCall(); /** * total calls taken * @author itaqua * @return */ - public abstract Integer getCallsTaken(); + Integer getCallsTaken(); } diff --git a/src/main/java/org/asteriskjava/live/AsteriskServer.java b/src/main/java/org/asteriskjava/live/AsteriskServer.java index 64716bfb5..da543db02 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskServer.java +++ b/src/main/java/org/asteriskjava/live/AsteriskServer.java @@ -69,7 +69,7 @@ public interface AsteriskServer * @throws ManagerCommunicationException if the originate action cannot be * sent to Asterisk */ - public AsteriskChannel originate(OriginateAction originateAction) + AsteriskChannel originate(OriginateAction originateAction) throws ManagerCommunicationException, NoSuchChannelException; /** @@ -81,7 +81,7 @@ public AsteriskChannel originate(OriginateAction originateAction) * @throws ManagerCommunicationException if the originate action cannot be * sent to Asterisk */ - public void originateAsync(OriginateAction originateAction, OriginateCallback cb) throws ManagerCommunicationException; + void originateAsync(OriginateAction originateAction, OriginateCallback cb) throws ManagerCommunicationException; /** * Generates an outgoing channel to a dialplan entry (extension, context, @@ -513,14 +513,14 @@ void originateToApplicationAsync(String channel, String application, String data * these cases it can be critical that you have the same name otherwise your * state information will be out of date. */ - public void addChainListener(ManagerEventListener chainListener); + void addChainListener(ManagerEventListener chainListener); /** * remove the chain listener. * * @param chainListener */ - public void removeChainListener(ManagerEventListener chainListener); + void removeChainListener(ManagerEventListener chainListener); /** * Closes the connection to this server. @@ -541,7 +541,7 @@ void originateToApplicationAsync(String channel, String application, String data * @param queueName Name of the queue to retrieve * @return */ - public AsteriskQueue getQueueByName(String queueName); + AsteriskQueue getQueueByName(String queueName); /** * List of Queues Objects updated after certain date @@ -550,7 +550,7 @@ void originateToApplicationAsync(String channel, String application, String data * @param date * @return */ - public List getQueuesUpdatedAfter(Date date); + List getQueuesUpdatedAfter(Date date); /** * every time we get an event of a queue we reload the information about it @@ -558,7 +558,7 @@ void originateToApplicationAsync(String channel, String application, String data * * @author itaqua */ - public void forceQueuesMonitor(boolean force); + void forceQueuesMonitor(boolean force); /** * Check if the Queue Information is forced @@ -566,5 +566,5 @@ void originateToApplicationAsync(String channel, String application, String data * @author itaqua * @return */ - public boolean isQueuesMonitorForced(); + boolean isQueuesMonitorForced(); } diff --git a/src/main/java/org/asteriskjava/manager/AsteriskMapping.java b/src/main/java/org/asteriskjava/manager/AsteriskMapping.java index 25ed99913..55d2e1ce9 100644 --- a/src/main/java/org/asteriskjava/manager/AsteriskMapping.java +++ b/src/main/java/org/asteriskjava/manager/AsteriskMapping.java @@ -19,5 +19,5 @@ @Retention(RUNTIME) public @interface AsteriskMapping { - public abstract String value(); + String value(); } \ No newline at end of file diff --git a/src/main/java/org/asteriskjava/manager/ManagerConnection.java b/src/main/java/org/asteriskjava/manager/ManagerConnection.java index 8c6e613ce..442f9a2e2 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/ManagerConnection.java @@ -187,7 +187,7 @@ public interface ManagerConnection * @see java.net.Socket#connect(java.net.SocketAddress, int) * @since 0.2 */ - public void setSocketTimeout(int socketTimeout); + void setSocketTimeout(int socketTimeout); /** * Connection is dropped (and restarted) if it stales on read longer than diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerWriter.java b/src/main/java/org/asteriskjava/manager/internal/ManagerWriter.java index 987c23f30..8e0a0bc28 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerWriter.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerWriter.java @@ -41,7 +41,7 @@ public interface ManagerWriter * @param targetVersion the version of the target Asterisk server. * @since 0.2 */ - public void setTargetVersion(AsteriskVersion targetVersion); + void setTargetVersion(AsteriskVersion targetVersion); /** * Sets the socket to use for writing to Asterisk. diff --git a/src/main/java/org/asteriskjava/pbx/Call.java b/src/main/java/org/asteriskjava/pbx/Call.java index 31813a5b8..71a7d678f 100644 --- a/src/main/java/org/asteriskjava/pbx/Call.java +++ b/src/main/java/org/asteriskjava/pbx/Call.java @@ -16,7 +16,7 @@ public interface Call * @author bsutton */ - public enum OperandChannel + enum OperandChannel { /** * this party received (did not originate) the call @@ -87,7 +87,7 @@ public enum OperandChannel * * @return */ - public Channel getLocalParty(); + Channel getLocalParty(); /** * Returns true of the Call can be split into two (or more) separate calls. diff --git a/src/main/java/org/asteriskjava/pbx/Channel.java b/src/main/java/org/asteriskjava/pbx/Channel.java index cc0552231..2299cfbf0 100644 --- a/src/main/java/org/asteriskjava/pbx/Channel.java +++ b/src/main/java/org/asteriskjava/pbx/Channel.java @@ -165,7 +165,7 @@ public interface Channel AgiChannelActivityAction getCurrentActivityAction(); - public void setCurrentActivityAction(AgiChannelActivityAction action); + void setCurrentActivityAction(AgiChannelActivityAction action); void setIsInAgi(boolean b); diff --git a/src/main/java/org/asteriskjava/pbx/EndPoint.java b/src/main/java/org/asteriskjava/pbx/EndPoint.java index c9d694d7f..731e49a26 100644 --- a/src/main/java/org/asteriskjava/pbx/EndPoint.java +++ b/src/main/java/org/asteriskjava/pbx/EndPoint.java @@ -11,11 +11,11 @@ */ public interface EndPoint extends Comparable { - public boolean isSame(EndPoint rhs); + boolean isSame(EndPoint rhs); - public boolean isLocal(); + boolean isLocal(); - public boolean isSIP(); + boolean isSIP(); /** * Returns the fully qualified name of the EndPoint including the tech. e.g. @@ -23,7 +23,7 @@ public interface EndPoint extends Comparable * * @return */ - public String getFullyQualifiedName(); + String getFullyQualifiedName(); /** * Returns the simple name of the EndPoint sans the tech. e.g. SIP/100 would @@ -31,7 +31,7 @@ public interface EndPoint extends Comparable * * @return */ - public String getSimpleName(); + String getSimpleName(); /** * Returns the simple name of a SIP EndPoint sans the tech. e.g. SIP/100 @@ -41,23 +41,23 @@ public interface EndPoint extends Comparable * * @return */ - public String getSIPSimpleName(); + String getSIPSimpleName(); /** * Returns true if the tech is not know for this end point. * * @return */ - public boolean isUnknown(); + boolean isUnknown(); /** * Returns the Tech that is used to reach this endpoint. * * @return */ - public TechType getTech(); + TechType getTech(); - public boolean isEmpty(); + boolean isEmpty(); /** * Sets the tech on the end point to the specified tech. diff --git a/src/main/java/org/asteriskjava/pbx/PBX.java b/src/main/java/org/asteriskjava/pbx/PBX.java index 08c7ff4ac..d46a275cc 100644 --- a/src/main/java/org/asteriskjava/pbx/PBX.java +++ b/src/main/java/org/asteriskjava/pbx/PBX.java @@ -23,7 +23,7 @@ public interface PBX * Call this method when shutting down the PBX interface to allow it to * cleanup. */ - public void shutdown(); + void shutdown(); /** * Returns true if the bridge function is supported. @@ -135,7 +135,7 @@ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID * * @param call */ - public void hangup(Call call) throws PBXException; + void hangup(Call call) throws PBXException; /** * Put the given channel on hold. @@ -207,20 +207,20 @@ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID * has completed. */ - public SplitActivity split(final Call callToSplit, final ActivityCallback listener) throws PBXException; + SplitActivity split(final Call callToSplit, final ActivityCallback listener) throws PBXException; - public RedirectToActivity redirectToActivity(final Channel channel, final ActivityCallback listener); + RedirectToActivity redirectToActivity(final Channel channel, final ActivityCallback listener); - public void split(final Call callToSplit) throws PBXException; + void split(final Call callToSplit) throws PBXException; /** * Joins two calls not returning until the join completes. Each call must * only have one active channel */ - public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, + JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, CallDirection direction); - public void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, + void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, CallDirection direction, ActivityCallback listener); /** @@ -276,10 +276,10 @@ public void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandC EndPoint getExtensionAgi(); - public boolean waitForChannelToQuiescent(Channel channel, int timeout); + boolean waitForChannelToQuiescent(Channel channel, int timeout); - public Trunk buildTrunk(String string); + Trunk buildTrunk(String string); - public void performPostCreationTasks(); + void performPostCreationTasks(); } diff --git a/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java b/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java index 812c927be..e932204e6 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java @@ -6,5 +6,5 @@ public interface HoldActivity extends Activity { // Returns the Channel that is on hold - public Channel getChannel(); + Channel getChannel(); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEvent.java index f409cbd95..489076680 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEvent.java @@ -4,6 +4,5 @@ public interface ChannelEvent { - public Channel getChannel(); - + Channel getChannel(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java index 3071596cf..fe42b1ce6 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java @@ -10,6 +10,5 @@ */ public interface CallEndedListener { - public void callEnded(CallTracker listener); - + void callEnded(CallTracker listener); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java index 08c70e462..ebf7afbbb 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java @@ -18,7 +18,7 @@ public interface FilteredManagerListener * * @return a unique name for the listener. */ - abstract String getName(); + String getName(); /** * Called whenever the listener is first added and any time any listener is @@ -26,7 +26,7 @@ public interface FilteredManagerListener * * @return list of required events. */ - abstract public Set> requiredEvents(); + Set> requiredEvents(); /** * Called for each manager event that the connection receives for which the @@ -34,7 +34,7 @@ public interface FilteredManagerListener * * @param event */ - abstract void onManagerEvent(T event); + void onManagerEvent(T event); /** * Set the listeners priority. Higher priority listeners have events @@ -42,6 +42,5 @@ public interface FilteredManagerListener * * @return */ - abstract ListenerPriority getPriority(); - + ListenerPriority getPriority(); } diff --git a/src/main/java/org/asteriskjava/util/Log.java b/src/main/java/org/asteriskjava/util/Log.java index ea794260f..8084e60c0 100644 --- a/src/main/java/org/asteriskjava/util/Log.java +++ b/src/main/java/org/asteriskjava/util/Log.java @@ -39,7 +39,7 @@ public interface Log void error(Object obj, Throwable exception); - public boolean isDebugEnabled(); + boolean isDebugEnabled(); void debug(Object e, Throwable e2); } From 37ebb2dbea61098b40c5e6c9aaa14bd81367ffc0 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 1 Feb 2018 16:30:45 -0500 Subject: [PATCH 152/802] Remove unnecessary semicolons Signed-off-by: Sean Bright --- src/main/java/org/asteriskjava/pbx/CallImpl.java | 2 +- .../org/asteriskjava/pbx/internal/managerAPI/Connector.java | 2 +- .../java/org/asteriskjava/pbx/internal/managerAPI/Dial.java | 2 +- .../org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/CallImpl.java b/src/main/java/org/asteriskjava/pbx/CallImpl.java index a72805160..ca8cb5fa4 100644 --- a/src/main/java/org/asteriskjava/pbx/CallImpl.java +++ b/src/main/java/org/asteriskjava/pbx/CallImpl.java @@ -44,7 +44,7 @@ public class CallImpl implements ChannelHangupListener, Call */ public enum TransferType { - NONE, ASSISTED, BLIND; + NONE, ASSISTED, BLIND } /** diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java index 57b1d0e4a..a8c47406e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java @@ -55,7 +55,7 @@ public ManagerConnection connect(final AsteriskSettings asteriskSettings) */ private void checkIfAsteriskRunning(AsteriskSettings asteriskSettings) throws UnknownHostException, IOException { - try (Socket socket = new Socket();) + try (Socket socket = new Socket()) { socket.setSoTimeout(2000); diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java index 342e4d11a..46300e69b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java @@ -60,7 +60,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint { final PBX pbx = PBXFactory.getActivePBX(); - try (final OriginateToExtension originate = new OriginateToExtension(listener);) + try (final OriginateToExtension originate = new OriginateToExtension(listener)) { // First bring the operator's handset up and connect it to the diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index 855ddd6c9..e2930264b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -56,7 +56,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint { final PBX pbx = PBXFactory.getActivePBX(); - try (final OriginateToExtension originate = new OriginateToExtension(listener);) + try (final OriginateToExtension originate = new OriginateToExtension(listener)) { // First bring the operator's handset up and connect it to the From 858a519720c11a4096707b6b9afa5b2d108e9332 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 1 Feb 2018 16:32:41 -0500 Subject: [PATCH 153/802] Use diamond operator where possible Signed-off-by: Sean Bright --- src/main/java/org/asteriskjava/config/ConfigFileReader.java | 2 +- .../org/asteriskjava/manager/internal/ResponseBuilderImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/config/ConfigFileReader.java b/src/main/java/org/asteriskjava/config/ConfigFileReader.java index ef0d912dc..b4f08f035 100644 --- a/src/main/java/org/asteriskjava/config/ConfigFileReader.java +++ b/src/main/java/org/asteriskjava/config/ConfigFileReader.java @@ -67,7 +67,7 @@ public ConfigFile readFile(String configfile) // ignored } - result = new ConfigFileImpl(configfile, new TreeMap(categories)); + result = new ConfigFileImpl(configfile, new TreeMap<>(categories)); return result; } diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java index 1e2f740ab..bdeb91964 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java @@ -111,7 +111,7 @@ else if (responseClass == null) // make the map of all attributes available to the response // but clone it as it is reused by the ManagerReader - response.setAttributes(new HashMap(attributes)); + response.setAttributes(new HashMap<>(attributes)); return response; } From 5e81391dec9e103fce8ff63084d064d4a21e3a15 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 1 Feb 2018 16:35:17 -0500 Subject: [PATCH 154/802] Use Collections.addAll() where possible Signed-off-by: Sean Bright --- .../org/asteriskjava/live/internal/AsteriskQueueImpl.java | 5 +---- .../java/org/asteriskjava/pbx/internal/core/CallTracker.java | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java index 227739802..989f72531 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java @@ -579,10 +579,7 @@ public Collection getMembers() List listOfMembers = new ArrayList<>(members.size()); synchronized (members) { - for (AsteriskQueueMemberImpl asteriskQueueMember : members.values()) - { - listOfMembers.add(asteriskQueueMember); - } + listOfMembers.addAll(members.values()); } return listOfMembers; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java index b593079bd..4dc529478 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java @@ -58,8 +58,7 @@ void mergeCalls(CallTracker rhs) { synchronized (this._associatedChannels) { - for (Channel channel : rhs._associatedChannels) - this._associatedChannels.add(channel); + this._associatedChannels.addAll(rhs._associatedChannels); // not certain this is necessary but lets just tidy up a bit. rhs._associatedChannels.clear(); } From c3989b272872687aa0f345ed6a54f879148c3a5f Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 1 Feb 2018 16:37:24 -0500 Subject: [PATCH 155/802] Use varags instead of new'ing arrays Signed-off-by: Sean Bright --- .../org/asteriskjava/manager/internal/AbstractBuilder.java | 2 +- .../org/asteriskjava/manager/internal/EventBuilderImpl.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index 58e1f2cb5..cd2ca82de 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -134,7 +134,7 @@ else if (entry.getValue() instanceof String) { try { - Constructor< ? > constructor = dataType.getConstructor(new Class[]{String.class}); + Constructor< ? > constructor = dataType.getConstructor(String.class); value = constructor.newInstance(entry.getValue()); } catch (Exception e) diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index 51561966d..1c9b400cb 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -273,7 +273,7 @@ public final void registerEventClass(String eventType, Class< ? extends ManagerE try { - defaultConstructor = clazz.getConstructor(new Class[]{Object.class}); + defaultConstructor = clazz.getConstructor(Object.class); } catch (NoSuchMethodException ex) { @@ -390,7 +390,7 @@ else if (value instanceof String && !"listitems".equals(key)) try { - constructor = eventClass.getConstructor(new Class[]{Object.class}); + constructor = eventClass.getConstructor(Object.class); } catch (NoSuchMethodException ex) { From 98a618848cebd04ae3bf0e79c9fa25c3e7cde58f Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 1 Feb 2018 17:00:32 -0500 Subject: [PATCH 156/802] Remove dead code from AbstractBuilder.setAttributes() The lines above this already change 'class' -> 'clazz' so this block can never be executed. Signed-off-by: Sean Bright --- .../asteriskjava/manager/internal/AbstractBuilder.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index 58e1f2cb5..6cdcacb5c 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -54,15 +54,6 @@ else if ("class".equals(setterName)) setterName = "clazz"; } - /* - * The class property needs to be renamed. It is used in - * MusicOnHoldEvent. - */ - if ("class".equals(setterName)) - { - setterName = "classname"; - } - setter = setters.get(setterName); if (setter == null && !setterName.endsWith("s")) // no exact match From 15b9bd66792893f9412651ad661f05deb7d55288 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 7 Feb 2018 16:48:21 +1100 Subject: [PATCH 157/802] fix for CoherentManagerEventQueue to monitor Bridge Events for asterisk 1.4 --- .../core/CoherentManagerEventQueue.java | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index 65f435076..7dd9dc904 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -1,5 +1,6 @@ package org.asteriskjava.pbx.internal.core; +import java.util.Collection; import java.util.Comparator; import java.util.HashSet; import java.util.Set; @@ -263,10 +264,35 @@ public void addListener(final FilteredManagerListener listener) this.listeners.add(new Listener(listener)); synchronized (this.globalEvents) { - this.globalEvents.addAll(listener.requiredEvents()); + Collection> expandEvents = expandEvents(listener.requiredEvents()); + this.globalEvents.addAll(expandEvents); } } - logger.debug("listener added"); //$NON-NLS-1$ + logger.debug("listener added " + listener); + } + + /** + * in order to get Bridge Events, we must subscribe to Link and Unlink + * events for asterisk 1.4, so we automatically add them if the Bridge Event + * is required + * + * @param events + * @return + */ + Collection> expandEvents(Collection> events) + { + Collection> requiredEvents = new HashSet<>(); + for (Class< ? extends ManagerEvent> event : events) + { + requiredEvents.add(event); + if (event.equals(BridgeEvent.class)) + { + requiredEvents.add(UnlinkEvent.class); + requiredEvents.add(LinkEvent.class); + } + } + + return requiredEvents; } public void removeListener(final FilteredManagerListener melf) @@ -289,7 +315,7 @@ public void removeListener(final FilteredManagerListener melf) this.globalEvents.clear(); for (Listener readdContainer : this.listeners) { - this.globalEvents.addAll(readdContainer._listener.requiredEvents()); + this.globalEvents.addAll(expandEvents(readdContainer._listener.requiredEvents())); } } break; From 30e0f9b91071570a3f32f8b61eedb40f823883b9 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 7 Feb 2018 16:49:22 +1100 Subject: [PATCH 158/802] fix for SplitActivityImpl to ensure that the channels finish transitioning before returning --- .../internal/activity/SplitActivityImpl.java | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index 9d43b906a..2c5798ac7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -3,6 +3,8 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.AsteriskSettings; @@ -16,6 +18,7 @@ import org.asteriskjava.pbx.activities.SplitActivity; import org.asteriskjava.pbx.agi.AgiChannelActivityHold; import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelProxy; @@ -102,14 +105,27 @@ public boolean doActivity() throws PBXException { HashSet> required = new HashSet<>(); - // No events required. + required.add(BridgeEvent.class); return required; } + final CountDownLatch unlinkRecieved = new CountDownLatch(1); + @Override synchronized public void onManagerEvent(final ManagerEvent event) { - // NOOP + + if (event instanceof BridgeEvent) + { + BridgeEvent link = (BridgeEvent) event; + if (link.isUnlink()) + { + if (link.getChannel1().isSame(channel1) || link.getChannel1().isSame(channel2)) + { + unlinkRecieved.countDown(); + } + } + } } @Override @@ -209,6 +225,28 @@ private boolean splitTwo() throws PBXException // final ManagerResponse response = pbx.sendAction(redirect, 1000); + + // wait for channels to unbridge + if (!unlinkRecieved.await(5000, TimeUnit.MILLISECONDS)) + { + logger.error("There was no unlink event"); + } + else + { + logger.warn("Channels are unlinked, now waiting for Quiescent"); + } + + channels.clear(); + + channels.add(channel1); + channels.add(channel2); + if (!pbx.waitForChannelsToQuiescent(channels, 3000)) + { + logger.error(callSite, callSite); + throw new PBXException("Channel: " + channel1 + " or " + channel2 + + " cannot be split as they are still in transition."); + } + double ctr = 0; while ((!agi1.hasCallReachedAgi() || !agi2.hasCallReachedAgi()) && ctr < 10) { From b2bd620c8d68bef0ff2e4a6edd26e32f98372491 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 8 Feb 2018 11:04:10 +1100 Subject: [PATCH 159/802] wait for rename event received after redirect --- .../internal/activity/SplitActivityImpl.java | 31 ++--- .../eventQueue/ManagerEventQueue.java | 131 ------------------ 2 files changed, 15 insertions(+), 147 deletions(-) delete mode 100644 src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index 2c5798ac7..a3c5f6903 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.AsteriskSettings; @@ -18,8 +19,8 @@ import org.asteriskjava.pbx.activities.SplitActivity; import org.asteriskjava.pbx.agi.AgiChannelActivityHold; import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; -import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.RenameEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelProxy; import org.asteriskjava.util.Log; @@ -59,6 +60,7 @@ public SplitActivityImpl(final Call callToSplit, final ActivityCallback tmp = callToSplit.getChannels(); @@ -105,25 +107,21 @@ public boolean doActivity() throws PBXException { HashSet> required = new HashSet<>(); - required.add(BridgeEvent.class); + required.add(RenameEvent.class); return required; } - final CountDownLatch unlinkRecieved = new CountDownLatch(1); + final AtomicReference renameEventReceived = new AtomicReference<>(); @Override synchronized public void onManagerEvent(final ManagerEvent event) { - - if (event instanceof BridgeEvent) + if (event instanceof RenameEvent) { - BridgeEvent link = (BridgeEvent) event; - if (link.isUnlink()) + RenameEvent rename = (RenameEvent) event; + if (rename.getChannel().isSame(channel1) || rename.getChannel().isSame(channel2)) { - if (link.getChannel1().isSame(channel1) || link.getChannel1().isSame(channel2)) - { - unlinkRecieved.countDown(); - } + renameEventReceived.get().countDown(); } } } @@ -177,8 +175,7 @@ private boolean splitTwo() throws PBXException if (channel1 == channel2) { - throw new NullPointerException( - "channel1 is the same as channel2. if I let this happen, asterisk will core dump :)"); + throw new PBXException("channel1 is the same as channel2. if I let this happen, asterisk will core dump :)"); } List channels = new LinkedList<>(); @@ -223,17 +220,19 @@ private boolean splitTwo() throws PBXException try { + renameEventReceived.set(new CountDownLatch(1)); + // final ManagerResponse response = pbx.sendAction(redirect, 1000); // wait for channels to unbridge - if (!unlinkRecieved.await(5000, TimeUnit.MILLISECONDS)) + if (!renameEventReceived.get().await(2000, TimeUnit.MILLISECONDS)) { - logger.error("There was no unlink event"); + logger.error("There was no rename event"); } else { - logger.warn("Channels are unlinked, now waiting for Quiescent"); + logger.warn("Channels are renaming, now waiting for Quiescent"); } channels.clear(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java deleted file mode 100644 index f5a012f58..000000000 --- a/src/main/java/org/asteriskjava/pbx/internal/eventQueue/ManagerEventQueue.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.asteriskjava.pbx.internal.eventQueue; - -/** - * This class provides a method of accepting, queueing and delivering manager - * events. - * - * Asterisk is very sensitive to delays in receiving events. This class ensures - * that events are received and queued rapidly. A separate thread dequeues them - * and delivers them to the manager listener. - * - * Used this queue as follows: - * - * manager.addEventListener(new ManagerEventQueue(originalListener)); - * - * This affectively daisy changes the originalListener via our queue. - * - * @author bsutton - * @deprecated use CoherentManagerEventQueue - */ -public class ManagerEventQueue // implements ManagerEventListener, Runnable -{ - // static Logger logger = LogFactory.getLog(getClass()); - // - // private final ManagerEventListener listener; - // private boolean stop = false; - // private final Thread th; - // private final BlockingQueue> eventQueue = - // new LinkedBlockingQueue<>(); - // - // private int queueMaxSize; - // - // private long queueSum; - // - // private long queueCount; - // - // public ManagerEventQueue(final ManagerEventListener listener) - // { - // this.listener = listener; - // this.th = new Thread(this); - // this.th.setName("EventQueue: " + listener.getClass().getSimpleName());//$NON-NLS-1$ - // this.th.setDaemon(true); - // this.th.start(); - // } - // - // /** - // * handles manager events passed to us in our role as a listener. - // * - // * We queue the event so that it can be read, by the run method of this - // * class, and subsequently passed on to the original listener. - // */ - // @Override - // public void onManagerEvent(final ManagerEvent event) - // { - // // if ((event instanceof DisconnectEvent) || (event instanceof - // // ConnectEvent) || (event instanceof HangupEvent) - // // || (event instanceof NewExtenEvent)) - // // { - // - // if (event instanceof NewExtenEvent) - // return; - // - // this.eventQueue.add(new EventLifeMonitor<>(event)); - // final int queueSize = this.eventQueue.size(); - // if (this.queueMaxSize < queueSize) - // { - // this.queueMaxSize = queueSize; - // } - // this.queueSum += queueSize; - // this.queueCount++; - // - // if (ManagerEventQueue.logger.isDebugEnabled()) - // { - // if (this.eventQueue.size() > ((this.queueMaxSize + (this.queueSum / - // this.queueCount)) / 2)) - // { - // ManagerEventQueue.logger.debug("queue size max avg"); //$NON-NLS-1$ - // ManagerEventQueue.logger - // .debug(" " + queueSize + " " + this.queueMaxSize + " " + (this.queueSum / this.queueCount)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - // } - // - // ManagerEventQueue.logger.debug("queue size " + this.eventQueue.size());//$NON-NLS-1$ - // } - // // } - // - // } - // - // @Override - // public void run() - // { - // - // while (this.stop == false) - // { - // try - // { - // final EventLifeMonitor elm = this.eventQueue.poll(2, - // TimeUnit.SECONDS); - // if (elm != null) - // { - // // Re-add the following line if you want to log every event. - // // logger.error(elm.getEvent()); - // this.listener.onManagerEvent(elm.getEvent()); - // elm.assessAge(); - // } - // } - // catch (final Exception e) - // { - // /** - // * If an exception is thrown whilst we are shutting down then we - // * don't care. If it is thrown when we aren't shutting down then - // * we have a problem and we need to log it. - // */ - // if (this.stop == false) - // { - // ManagerEventQueue.logger.error(e, e); - // } - // } - // - // } - // - // } - // - // public void stop() - // { - // this.stop = true; - // synchronized (this.eventQueue) - // { - // this.eventQueue.notify(); - // } - // } - -} From f596b9eb902cd2cc40f7b069b7eef9991f56ae01 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 13 Feb 2018 11:20:56 +1100 Subject: [PATCH 160/802] remove reconnect logic from CoherentManagerConnection --- .../core/CoherentManagerConnection.java | 129 +----------------- 1 file changed, 7 insertions(+), 122 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java index f22c91da2..9f0d86861 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -1,7 +1,6 @@ package org.asteriskjava.pbx.internal.core; import java.io.IOException; -import java.net.InetAddress; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -446,120 +445,6 @@ private void checkFeatures() throws IOException, TimeoutException } } - // @SuppressWarnings("unused") - // private boolean ping(final int timeout) - // { - // boolean result = false; - // - // try - // { - // // logger.debug("ping"); - // final PingAction pa = new PingAction(); - // result = true; - // } - // catch (final Exception e) - // { - // // logger.warn("ping failed asterisk connection may have been lost"); - // - // } - // return result; - // - // } - - // // TODO consider putting the ping logic back in. - // // Having said that the ping command doesn't appear to have been working - // for - // // some time - // // as it was always returning true. - // public void run() - // { - // // Establish the initial connection. - // this.connector = new Connector(); - // try - // { - // this.managerListener = this.con.connect(this.profile); - // this.queue = new ManagerEventQueue(this); - // - // this.managerListener.addEventListener(this.queue); - // - // this.managerWriter = this.con.connect(this.profile); - // - // } - // catch (final Exception e) - // { - // logger.error(e, e); - // } - // - // // Monitor the connection by doing an asterisk ping. - // while (this.stop == false) - // { - // if (!this.ping(200)) - // { - // if (!this.ping(90)) - // { - // if (!this.ping(90)) - // { - // logger.error("Asterisk connection lost, attempting reconnect"); - // //$NON-NLS-1$ - // // The ping has failed so we need to force a reconnect. - // this.reconnect(); - // } - // } - // } - // try - // { - // Thread.sleep(500); - // } - // catch (final InterruptedException e) - // { - // CallMarker.logger.error(e, e); - // } - // - // } - // - // } - - private void reconnect() - { - final ManagerConnection oldConnection = CoherentManagerConnection.managerConnection; - try - { - try - { - final InetAddress address = InetAddress.getByName(CoherentManagerConnection.managerConnection.getHostname()); - int counter = 0; - while (!address.isReachable(100)) - { - if (counter % 10 == 0) - CoherentManagerConnection.logger.debug("Testing for host " //$NON-NLS-1$ - + CoherentManagerConnection.managerConnection.getHostname()); - counter++; - } - } - catch (final Exception e2) - { - CoherentManagerConnection.logger.error(e2, e2); - } - try - { - CoherentManagerConnection.logger.debug("reconnecting to asterisk"); //$NON-NLS-1$ - - connector = new Connector(); - this.configureConnection(); - CoherentManagerConnection.logger.debug("asterisk reconnection complete"); //$NON-NLS-1$ - } - catch (final Exception e1) - { - - CoherentManagerConnection.logger.error(e1, e1); - } - } - finally - { - oldConnection.logoff(); - } - } - public void shutDown() { CoherentManagerConnection.managerConnection.removeEventListener(this.eventQueue); @@ -640,13 +525,13 @@ public void onManagerEvent(ManagerEvent event) else if (event instanceof DisconnectEvent) { logger.warn("****************** Asterisk manager connection lost **************************"); //$NON-NLS-1$ - new Thread(new Runnable() - { - public void run() - { - reconnect(); - } - }); + // new Thread(new Runnable() + // { + // public void run() + // { + // reconnect(); + // } + // }); } } From c82b7ed73280a250cf743451ea0fbe9fcea8b506 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 13 Feb 2018 11:21:35 +1100 Subject: [PATCH 161/802] add ability to concurrently process the same event for multiple listeners in CoherentManagerEventQueue --- .../core/CoherentManagerEventQueue.java | 72 ++++++++++++++++--- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index 7dd9dc904..da6d10826 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -6,6 +6,9 @@ import java.util.Set; import java.util.TreeSet; import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -210,6 +213,9 @@ public void stop() } } + // TODO: make this multi threaded + private final ExecutorService executors = Executors.newFixedThreadPool(1); + /** * Events are sent here from the CoherentManagerEventQueue after being * converted from a ManagerEvent to an ManagerEvent. This method is called @@ -232,22 +238,72 @@ public void dispatchEvent(final ManagerEvent event) listenerCopy.addAll(this.listeners); } - for (final Listener filter : listenerCopy) + try { - if (filter.requiredEvents.contains(event.getClass())) - { - final LogTime time = new LogTime(); + final LogTime totalTime = new LogTime(); + + CountDownLatch latch = new CountDownLatch(listenerCopy.size()); - filter._listener.onManagerEvent(event); - if (time.timeTaken() > 500) + for (final Listener filter : listenerCopy) + { + if (filter.requiredEvents.contains(event.getClass())) + { + dispatchEventOnThread(event, filter, latch); + } + else { - logger.warn("ManagerListener :" + filter._listener.getName() //$NON-NLS-1$ - + " is taken too long to process event " + event + " time taken: " + time.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$ + // this listener didn't want the event, so just decrease the + // countdown + latch.countDown(); } } + + latch.await(); + + if (totalTime.timeTaken() > 500) + { + logger.warn("Too long to process event " + event + " time taken: " + totalTime.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + catch (InterruptedException e) + { + Thread.interrupted(); } } + private void dispatchEventOnThread(final ManagerEvent event, final Listener filter, final CountDownLatch latch) + { + Runnable runner = new Runnable() + { + @Override + public void run() + { + try + { + final LogTime time = new LogTime(); + + filter._listener.onManagerEvent(event); + if (time.timeTaken() > 500) + { + logger.warn("ManagerListener :" + filter._listener.getName() //$NON-NLS-1$ + + " is taken too long to process event " + event + " time taken: " + time.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + catch (Exception e) + { + logger.error(e, e); + } + finally + { + latch.countDown(); + } + } + }; + + executors.execute(runner); + + } + /** * Adds a listener which will be sent all events that its filterEvent * handler will accept. All events are dispatch by way of a shared queue From 0b8c50b739c561f3d842a5c481cd9ccd250d27ee Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 13 Feb 2018 11:22:05 +1100 Subject: [PATCH 162/802] remove listener when done --- .../org/asteriskjava/pbx/internal/managerAPI/Dial.java | 7 ++++++- .../asteriskjava/pbx/internal/managerAPI/DialToAgi.java | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java index 46300e69b..165fef092 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java @@ -34,7 +34,6 @@ public class Dial extends EventListenerBaseClass public Dial(final String descriptiveName) { super(descriptiveName); - this.startListener(PBXFactory.getActivePBX()); } /** @@ -63,6 +62,8 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint try (final OriginateToExtension originate = new OriginateToExtension(listener)) { + this.startListener(PBXFactory.getActivePBX()); + // First bring the operator's handset up and connect it to the // 'njr-dial' extension where they can // wait whilst we complete the second leg @@ -111,6 +112,10 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint return this.result; } + finally + { + this.close(); + } } @Override diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index e2930264b..3bbb3ef25 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -30,7 +30,6 @@ public class DialToAgi extends EventListenerBaseClass public DialToAgi(final String descriptiveName) { super(descriptiveName); - this.startListener(PBXFactory.getActivePBX()); } /** @@ -58,6 +57,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint try (final OriginateToExtension originate = new OriginateToExtension(listener)) { + this.startListener(PBXFactory.getActivePBX()); // First bring the operator's handset up and connect it to the // 'njr-dial' extension where they can @@ -88,6 +88,10 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint return this.result; } + finally + { + this.close(); + } } @Override From 529ef290231ddb0278159e91234cd1802a7c551d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 13 Feb 2018 11:22:37 +1100 Subject: [PATCH 163/802] remove listener when done, and remove check for random HangupEvent --- .../pbx/internal/core/DialLocalToAgiActivity.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java index 286f9a086..20d3322cf 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -56,7 +56,6 @@ public DialLocalToAgiActivity(EndPoint from, CallerID fromCallerID, ActivityCall this.callback = callback; this.channelVarsToSet = channelVarsToSet; - this.startListener(PBXFactory.getActivePBX()); thread = new Thread(this, "Dial " + from + " to AGI"); thread.start(); } @@ -94,6 +93,8 @@ public void run() try { + this.startListener(PBXFactory.getActivePBX()); + pbx.sendAction(originate, 30000); latch.await(30, TimeUnit.SECONDS); callback.progress(this, ActivityStatusEnum.SUCCESS, ActivityStatusEnum.SUCCESS.getDefaultMessage()); @@ -103,6 +104,10 @@ public void run() { logger.error(e, e); } + finally + { + this.close(); + } } @@ -131,10 +136,6 @@ public void abort(final String reason) @Override synchronized public void onManagerEvent(final ManagerEvent event) { - if (event instanceof HangupEvent) - { - this.close(); - } if (event instanceof NewChannelEvent) { final NewChannelEvent newState = (NewChannelEvent) event; From 46d59cdf9f694fff7a76586db6c9a1f6d8f3cf01 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 13 Feb 2018 12:12:29 +1100 Subject: [PATCH 164/802] release listener when done and process events faster --- .../managerAPI/OriginateBaseClass.java | 202 +++++++----------- 1 file changed, 75 insertions(+), 127 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 17f1fc41f..8afe460d0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -79,9 +79,6 @@ protected OriginateBaseClass(final NewChannelListener listener, final Channel mo this.monitorChannel2 = monitor2; this.result = new OriginateResult(); - // Just add us as an asterisk event listener. - this.startListener(PBXFactory.getActivePBX()); - } /** @@ -93,7 +90,7 @@ protected OriginateBaseClass(final NewChannelListener listener, final Channel mo * @param context * @return */ - protected OriginateResult originate(final EndPoint local, final EndPoint target, final HashMap myVars, + OriginateResult originate(final EndPoint local, final EndPoint target, final HashMap myVars, final CallerID callerID, final Integer timeout, final boolean hideCallerId, final String context) { OriginateBaseClass.logger.debug("originate called"); //$NON-NLS-1$ @@ -104,7 +101,6 @@ protected OriginateResult originate(final EndPoint local, final EndPoint target, { // the monitored channel already hungup so just return false and // shutdown - this.close(); return null; } @@ -176,6 +172,9 @@ protected OriginateResult originate(final EndPoint local, final EndPoint target, try { + // Just add us as an asterisk event listener. + this.startListener(pbx); + response = pbx.sendAction(originate, localTimeout); OriginateBaseClass.logger.debug("Originate.sendAction completed"); //$NON-NLS-1$ if (response.getResponse().compareToIgnoreCase("Success") != 0)//$NON-NLS-1$ @@ -395,7 +394,6 @@ synchronized public void onManagerEvent(final ManagerEvent event) { final NewChannelEvent newState = (NewChannelEvent) event; final Channel channel = newState.getChannel(); - final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); OriginateBaseClass.logger.debug("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-1$//$NON-NLS-2$ + " state =" + newState.getChannelStateDesc() + " state =" + newState.getChannelState()); //$NON-NLS-1$ //$NON-NLS-2$ @@ -409,73 +407,8 @@ synchronized public void onManagerEvent(final ManagerEvent event) // We need to try several times as it can take some time to // appear // within asterisk. - int ctr = 0; - String __originateID = null; - while ((ctr < 5) && (__originateID == null)) - { - try - { - ctr++; - /* - * wait 100ms to allow asterisk time to make the channel - * variables available. If you request the channel variables - * too soon asterisk responds with channel not found. - */ - Thread.sleep(100); - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - final ManagerResponse response = pbx.sendAction(var, 500); - __originateID = response.getAttribute("value"); //$NON-NLS-1$ - - if ((__originateID != null)) - { - // Check if the event is for our channel by checking - // the - // originateIDs match. - if (__originateID.compareToIgnoreCase(this.originateID) == 0) - { - if ((this.newChannel == null) && !channel.isLocal()) - { - this.newChannel = channel; - this.channelSeen = true; - - OriginateBaseClass.logger.debug("new channel name " + channel); //$NON-NLS-1$ } - if (this.listener != null) - { - /* - * sometimes it's not actually the NJR phone - * we're originating. Otherwise update the - * NJR phone channel to allow the call to be - * cancelled before it's answered. - */ - this.listener.channelUpdate(channel); - } - - if (this.originateSeen == true) - { - OriginateBaseClass.logger.debug("notifying success 362");//$NON-NLS-1$ - originateLatch.countDown(); - } - } - } - else - { - // So we got an originate but it wasn't for us which - // means this channel isn't ours. - // so we can ignore the event. - OriginateBaseClass.logger.debug("originateID " + __originateID); //$NON-NLS-1$ - } - } - } - catch (final Exception e) - { - // We only care about error if we are on the last - // attempt. - if ((this.originateSuccess == false) && (ctr == 4)) - { - OriginateBaseClass.logger.error(e, e); - } - } - } + + checkBridge(5, channel); } // Look for the channel events that tell us that both sides of the @@ -493,9 +426,8 @@ synchronized public void onManagerEvent(final ManagerEvent event) { channel = bridgeEvent.getChannel2(); } - final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); - OriginateBaseClass.logger.debug("new channel event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-1$//$NON-NLS-2$ + OriginateBaseClass.logger.debug("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-1$//$NON-NLS-2$ + " channel2 =" + bridgeEvent.getChannel2()); //$NON-NLS-1$ // Now try to get the NJR_ORIGINATE_ID's value to see if this is @@ -507,75 +439,91 @@ synchronized public void onManagerEvent(final ManagerEvent event) // We need to try several times as it can take some time to // appear // within asterisk. - int ctr = 0; - String __originateID = null; - while ((ctr < 5) && (__originateID == null)) + + checkBridge(5, channel); + + } + + } + + private void checkBridge(int ctr, Channel channel) + { + while (ctr > 0) + { + logger.error("Check " + ctr); + try { - try + ctr--; + /* + * wait 100ms to allow asterisk time to make the channel + * variables available. If you request the channel variables too + * soon asterisk responds with channel not found. + */ + + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); + + final ManagerResponse response = pbx.sendAction(var, 500); + String __originateID = response.getAttribute("value"); //$NON-NLS-1$ + + if ((__originateID != null)) { - ctr++; - /* - * wait 100ms to allow asterisk time to make the channel - * variables available. If you request the channel variables - * too soon asterisk responds with channel not found. - */ - Thread.sleep(100); - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - final ManagerResponse response = pbx.sendAction(var, 500); - __originateID = response.getAttribute("value"); //$NON-NLS-1$ - - if ((__originateID != null)) + // Check if the event is for our channel by checking + // the + // originateIDs match. + if ((this.originateID != null) && (__originateID.compareToIgnoreCase(this.originateID) == 0)) { - // Check if the event is for our channel by checking - // the - // originateIDs match. - if ((this.originateID != null) && (__originateID.compareToIgnoreCase(this.originateID) == 0)) + if ((this.newChannel == null) && !channel.isLocal()) { - if ((this.newChannel == null) && !channel.isLocal()) + this.newChannel = channel; + this.channelSeen = true; + + OriginateBaseClass.logger.debug("new channel name " + channel); //$NON-NLS-1$ } + if (this.listener != null) + { + /* + * sometimes it's not actually the NJR phone + * we're originating. Otherwise update the NJR + * phone channel to allow the call to be + * cancelled before it's answered. + */ + this.listener.channelUpdate(channel); + } + + if (this.originateSeen == true) { - this.newChannel = channel; - this.channelSeen = true; - - OriginateBaseClass.logger.debug("new channel name " + channel); //$NON-NLS-1$ } - if (this.listener != null) - { - /* - * sometimes it's not actually the NJR phone - * we're originating. Otherwise update the - * NJR phone channel to allow the call to be - * cancelled before it's answered. - */ - this.listener.channelUpdate(channel); - } - - if (this.originateSeen == true) - { - OriginateBaseClass.logger.debug("notifying success 362");//$NON-NLS-1$ - originateLatch.countDown(); - } + OriginateBaseClass.logger.debug("notifying success 362");//$NON-NLS-1$ + originateLatch.countDown(); } + break; } } - else - { - // So we got an originate but it wasn't for us which - // means this channel isn't ours. - // so we can ignore the event. - OriginateBaseClass.logger.debug("originateID " + __originateID); //$NON-NLS-1$ - } } - catch (final Exception e) + Thread.sleep(100); + } + catch (final Exception e) + { + if (ctr == 0 && this.originateSuccess == false) { // We only care about error if we are on the last // attempt. - if ((this.originateSuccess == false) && (ctr == 4)) + OriginateBaseClass.logger.error(e, e); + } + else + { + try + { + Thread.sleep(100); + } + catch (InterruptedException e1) { - OriginateBaseClass.logger.error(e, e); + logger.error(e1); } } + } - } + } } } From a630a1253dfd42acaf329e857e3b51c81ecb1d99 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 15 Feb 2018 14:06:54 +1100 Subject: [PATCH 165/802] add pathways to allow aborting an unanswered originate --- .../activity/DialToAgiActivityImpl.java | 13 +++++ .../pbx/internal/core/AsteriskPBX.java | 20 +++++++- .../core/DialToAgiWithAbortCallback.java | 51 +++++++++++++++++++ .../pbx/internal/managerAPI/DialToAgi.java | 8 +++ 4 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index 1180506f2..3e7c0b2fa 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -44,6 +44,8 @@ public class DialToAgiActivityImpl extends ActivityHelper imp private AgiChannelActivityAction action; + private DialToAgi originator; + public DialToAgiActivityImpl(final EndPoint originating, final CallerID toCallerID, final boolean hideToCallerID, final ActivityCallback listener, Map channelVarsToSet, AgiChannelActivityAction action) @@ -57,6 +59,10 @@ public DialToAgiActivityImpl(final EndPoint originating, final CallerID toCaller this.cancelledByOperator = false; this.channelVarsToSet = channelVarsToSet; + } + + public void dial() + { this.startActivity(false); } @@ -71,6 +77,8 @@ public boolean doActivity() throws PBXException DialToAgiActivityImpl.logger.info("*********** begin dial out to agi ***********"); DialToAgiActivityImpl.logger.debug("**************************************************************************"); + originator = nr; + final OriginateResult[] resultChannels = nr.dial(this, this._originating, this.action, this.toCallerID, this.hideToCallerId, channelVarsToSet); @@ -223,4 +231,9 @@ public void onManagerEvent(ManagerEvent event) // NOOP } + public void abort() + { + originator.abort(); + } + } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 37d4a6117..37ad013d5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -882,6 +882,8 @@ public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, Agi final DialToAgiActivityImpl dialer = new DialToAgiActivityImpl(endPoint, callerID, false, completion, null, action); + dialer.startActivity(false); + completion.waitForCompletion(3, TimeUnit.MINUTES); final ActivityStatusEnum status; @@ -900,6 +902,17 @@ public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, Agi return dialer; } + public DialToAgiWithAbortCallback dialToAgiWithAbort(EndPoint endPoint, CallerID callerID, + AgiChannelActivityAction action, ActivityCallback iCallback) + { + + final CompletionAdaptor completion = new CompletionAdaptor<>(); + + final DialToAgiActivityImpl dialer = new DialToAgiActivityImpl(endPoint, callerID, false, completion, null, action); + + return new DialToAgiWithAbortCallback(dialer, completion, iCallback); + } + /** * Creates the set of extensions required to test NJR during the * installation. The context must already exist in the dialplan. @@ -949,10 +962,13 @@ public boolean checkDialplanExists(AsteriskSettings profile) { String command; - if (getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) { + if (getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) + { // TODO: Use ShowDialplanAction instead of CommandAction? command = "dialplan show " + profile.getManagementContext(); - } else { + } + else + { command = "show dialplan " + profile.getManagementContext(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java new file mode 100644 index 000000000..2b26c5bb8 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java @@ -0,0 +1,51 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.concurrent.TimeUnit; + +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.ActivityStatusEnum; +import org.asteriskjava.pbx.CompletionAdaptor; +import org.asteriskjava.pbx.activities.DialToAgiActivity; +import org.asteriskjava.pbx.internal.activity.DialToAgiActivityImpl; + +public class DialToAgiWithAbortCallback +{ + private DialToAgiActivityImpl dialer; + private CompletionAdaptor completion; + private ActivityCallback iCallback; + + public DialToAgiWithAbortCallback(DialToAgiActivityImpl dialer, CompletionAdaptor completion, + ActivityCallback iCallback) + { + this.dialer = dialer; + this.completion = completion; + this.iCallback = iCallback; + } + + public DialToAgiActivityImpl start() + { + dialer.startActivity(false); + + completion.waitForCompletion(3, TimeUnit.MINUTES); + + final ActivityStatusEnum status; + + if (dialer.isSuccess()) + { + status = ActivityStatusEnum.SUCCESS; + } + else + { + status = ActivityStatusEnum.FAILURE; + } + + iCallback.progress(dialer, status, status.getDefaultMessage()); + + return dialer; + } + + public void abort() + { + dialer.abort(); + } +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index 3bbb3ef25..b6a0e3d81 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -27,6 +27,8 @@ public class DialToAgi extends EventListenerBaseClass private volatile boolean hangupDetected = false; + private OriginateToExtension originator; + public DialToAgi(final String descriptiveName) { super(descriptiveName); @@ -58,6 +60,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint try (final OriginateToExtension originate = new OriginateToExtension(listener)) { this.startListener(PBXFactory.getActivePBX()); + originator = originate; // First bring the operator's handset up and connect it to the // 'njr-dial' extension where they can @@ -130,4 +133,9 @@ public ListenerPriority getPriority() return ListenerPriority.NORMAL; } + public void abort() + { + originator.abort("user abort"); + } + } From 2225b892973bd4bbaf6707616218a852bb7073d6 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 20 Feb 2018 13:23:46 +1100 Subject: [PATCH 166/802] Fix CoherentManagerEventQueue failure to remove listeners. Improve OriginateBaseClass handling of manager events. --- .../pbx/internal/activity/ActivityHelper.java | 4 +- .../internal/asterisk/MeetmeRoomControl.java | 6 +- .../core/CoherentManagerConnection.java | 6 +- .../core/CoherentManagerEventQueue.java | 113 +++++------------- .../internal/core/DialLocalToAgiActivity.java | 5 +- .../core/DialToAgiWithAbortCallback.java | 39 +++--- .../core/FilteredManagerListenerWrapper.java | 49 ++++++++ .../pbx/internal/core/ListenerManager.java | 84 +++++++++++++ .../pbx/internal/core/PeerMonitor.java | 4 +- .../pbx/internal/managerAPI/Dial.java | 4 +- .../pbx/internal/managerAPI/DialToAgi.java | 4 +- .../managerAPI/EventListenerBaseClass.java | 14 +-- .../managerAPI/OriginateBaseClass.java | 18 +-- .../internal/core/ListenerManagerTest.java | 77 ++++++++++++ 14 files changed, 302 insertions(+), 125 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListenerWrapper.java create mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java create mode 100644 src/test/java/org/asteriskjava/pbx/internal/core/ListenerManagerTest.java diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java index 8a2a96362..b12d012e1 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java @@ -62,7 +62,7 @@ public void close() throws Exception } }; } - EventListenerBaseClass listener = new EventListenerBaseClass(activityName) + EventListenerBaseClass listener = new EventListenerBaseClass(activityName, PBXFactory.getActivePBX()) { @Override @@ -84,7 +84,7 @@ public ListenerPriority getPriority() return ActivityHelper.this.getPriority(); } }; - listener.startListener(PBXFactory.getActivePBX()); + listener.startListener(); return listener; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index 8bdd9c2ad..c9da7d9ad 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -69,7 +69,7 @@ public static MeetmeRoomControl getInstance() if (MeetmeRoomControl.self.get() == null) { throw new IllegalStateException( - "Thee MeetmeRoomControl has not been initialised. Please call MeetmeRoomControl.init()."); //$NON-NLS-1$ + "The MeetmeRoomControl has not been initialised. Please call MeetmeRoomControl.init()."); //$NON-NLS-1$ } return MeetmeRoomControl.self.get(); @@ -78,14 +78,14 @@ public static MeetmeRoomControl getInstance() private MeetmeRoomControl(PBX pbx, final int roomCount) throws NoMeetmeException { - super("MeetmeRoomControl"); //$NON-NLS-1$ + super("MeetmeRoomControl", pbx); //$NON-NLS-1$ this.roomCount = roomCount; final AsteriskSettings settings = PBXFactory.getActiveProfile(); this.meetmeBaseAddress = settings.getMeetmeBaseAddress(); this.rooms = new MeetmeRoom[roomCount]; this.configure((AsteriskPBX) pbx); - this.startListener(pbx); + this.startListener(); } @Override diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java index 9f0d86861..4735f1e22 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -396,7 +396,8 @@ private void configureConnection() // that it hasn't already) // and should have no duplicate events. Once drained the queue will be // garbage collected. - CoherentManagerEventQueue newRealtime = new CoherentManagerEventQueue("Realtime"); //$NON-NLS-1$ + CoherentManagerEventQueue newRealtime = new CoherentManagerEventQueue("Realtime", //$NON-NLS-1$ + CoherentManagerConnection.managerConnection); if (this.realtimeEventQueue != null) { this.realtimeEventQueue.stop(); @@ -404,7 +405,8 @@ private void configureConnection() } this.realtimeEventQueue = newRealtime; - CoherentManagerEventQueue newStandard = new CoherentManagerEventQueue("Standard"); //$NON-NLS-1$ + CoherentManagerEventQueue newStandard = new CoherentManagerEventQueue("Standard", //$NON-NLS-1$ + CoherentManagerConnection.managerConnection); if (this.eventQueue != null) { this.eventQueue.stop(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index da6d10826..7dc40fe70 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -1,10 +1,9 @@ package org.asteriskjava.pbx.internal.core; import java.util.Collection; -import java.util.Comparator; import java.util.HashSet; -import java.util.Set; -import java.util.TreeSet; +import java.util.Iterator; +import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -12,6 +11,7 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import org.asteriskjava.manager.ManagerConnection; import org.asteriskjava.manager.ManagerEventListener; import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; @@ -37,44 +37,7 @@ class CoherentManagerEventQueue implements ManagerEventListener, Runnable { private static final Log logger = LogFactory.getLog(CoherentManagerEventQueue.class); - private class Listener - { - FilteredManagerListener _listener; - Set> requiredEvents; - - public Listener(FilteredManagerListener listener) - { - this._listener = listener; - this.requiredEvents = listener.requiredEvents(); - - if (requiredEvents.contains(BridgeEvent.class)) - { - // add LinkEvent and UnlinkEvent, as BridgeEvent only will - // miss some events - requiredEvents.add(LinkEvent.class); - requiredEvents.add(UnlinkEvent.class); - } - - for (Class< ? extends ManagerEvent> event : requiredEvents) - { - if (!CoherentEventFactory.mapEvents.values().contains(event) - && !CoherentEventFactory.mapResponses.values().contains(event)) - { - throw new RuntimeException( - "The requested event type of " + event + "+isn't known by " + CoherentEventFactory.class); - } - } - } - - @Override - public String toString() - { - return this._listener.getName(); - } - - } - - private final TreeSet listeners = new TreeSet<>(new ListenerPriorityComparator()); + private final ListenerManager listeners = new ListenerManager(); private boolean _stop = false; private final Thread _th; @@ -88,9 +51,10 @@ public String toString() private HashSet> globalEvents = new HashSet<>(); - public CoherentManagerEventQueue(String name) + public CoherentManagerEventQueue(String name, ManagerConnection connection) { - CoherentManagerConnection.managerConnection.addEventListener(this); + + connection.addEventListener(this); this._th = new Thread(this); this._th.setName("EventQueue: " + name);//$NON-NLS-1$ @@ -232,10 +196,10 @@ public void dispatchEvent(final ManagerEvent event) // take a copy of the listeners so they can be modified whilst we // iterate over them // The iteration may call some long running processes. - final TreeSet listenerCopy = new TreeSet<>(new ListenerPriorityComparator()); + final List listenerCopy; synchronized (this.listeners) { - listenerCopy.addAll(this.listeners); + listenerCopy = this.listeners.getCopyAsList(); } try @@ -244,7 +208,7 @@ public void dispatchEvent(final ManagerEvent event) CountDownLatch latch = new CountDownLatch(listenerCopy.size()); - for (final Listener filter : listenerCopy) + for (final FilteredManagerListenerWrapper filter : listenerCopy) { if (filter.requiredEvents.contains(event.getClass())) { @@ -271,7 +235,8 @@ public void dispatchEvent(final ManagerEvent event) } } - private void dispatchEventOnThread(final ManagerEvent event, final Listener filter, final CountDownLatch latch) + private void dispatchEventOnThread(final ManagerEvent event, final FilteredManagerListenerWrapper filter, + final CountDownLatch latch) { Runnable runner = new Runnable() { @@ -317,7 +282,7 @@ public void addListener(final FilteredManagerListener listener) { synchronized (this.listeners) { - this.listeners.add(new Listener(listener)); + this.listeners.addListener(listener); synchronized (this.globalEvents) { Collection> expandEvents = expandEvents(listener.requiredEvents()); @@ -353,47 +318,30 @@ public void addListener(final FilteredManagerListener listener) public void removeListener(final FilteredManagerListener melf) { - synchronized (this.listeners) + if (melf != null) { - if (melf != null) + synchronized (this.listeners) { - for (Listener container : this.listeners) + this.listeners.removeListener(melf); + + // When we remove a listener we must unfortunately + // completely + // recalculate the set of required events. + synchronized (this.globalEvents) { - if (container._listener == melf) + this.globalEvents.clear(); + Iterator itr = this.listeners.iterator(); + while (itr.hasNext()) { - this.listeners.remove(container); - - // When we remove a listener we must unfortunately - // completely - // recalculate the set of required events. - synchronized (this.globalEvents) - { - this.globalEvents.clear(); - for (Listener readdContainer : this.listeners) - { - this.globalEvents.addAll(expandEvents(readdContainer._listener.requiredEvents())); - } - } - break; + FilteredManagerListenerWrapper readdContainer = itr.next(); + this.globalEvents.addAll(expandEvents(readdContainer._listener.requiredEvents())); } } - } - } - } - - final class ListenerPriorityComparator implements Comparator - { - @Override - public int compare(Listener lhs, Listener rhs) - { - int result = lhs._listener.getPriority().compare(rhs._listener.getPriority()); - - if (result == 0) - result = (lhs._listener.equals(rhs._listener) ? 0 : 1); + } - return result; } + } /** @@ -407,8 +355,11 @@ public void transferListeners(CoherentManagerEventQueue eventQueue) { synchronized (eventQueue.listeners) { - for (Listener listener : eventQueue.listeners) + Iterator itr = eventQueue.listeners.iterator(); + while (itr.hasNext()) { + FilteredManagerListenerWrapper listener = itr.next(); + this.addListener(listener._listener); } eventQueue.listeners.clear(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java index 20d3322cf..f91ca550e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -50,7 +50,7 @@ public class DialLocalToAgiActivity extends EventListenerBaseClass implements Ru public DialLocalToAgiActivity(EndPoint from, CallerID fromCallerID, ActivityCallback callback, Map channelVarsToSet) { - super("Dial " + from + " to AGI"); + super("Dial " + from + " to AGI", PBXFactory.getActivePBX()); this.from = from; this.fromCallerID = fromCallerID; this.callback = callback; @@ -93,7 +93,7 @@ public void run() try { - this.startListener(PBXFactory.getActivePBX()); + this.startListener(); pbx.sendAction(originate, 30000); latch.await(30, TimeUnit.SECONDS); @@ -114,7 +114,6 @@ public void run() public void abort(final String reason) { logger.warn("Aborting originate "); - this.close(); for (Channel channel : channels) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java index 2b26c5bb8..a768a7f7f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java @@ -22,26 +22,37 @@ public DialToAgiWithAbortCallback(DialToAgiActivityImpl dialer, CompletionAdapto this.iCallback = iCallback; } - public DialToAgiActivityImpl start() + public void asyncStartDial() { - dialer.startActivity(false); - completion.waitForCompletion(3, TimeUnit.MINUTES); + Runnable runner = new Runnable() + { - final ActivityStatusEnum status; + @Override + public void run() + { + dialer.startActivity(false); - if (dialer.isSuccess()) - { - status = ActivityStatusEnum.SUCCESS; - } - else - { - status = ActivityStatusEnum.FAILURE; - } + completion.waitForCompletion(3, TimeUnit.MINUTES); + + final ActivityStatusEnum status; + + if (dialer.isSuccess()) + { + status = ActivityStatusEnum.SUCCESS; + } + else + { + status = ActivityStatusEnum.FAILURE; + } + + iCallback.progress(dialer, status, status.getDefaultMessage()); + + } + }; - iCallback.progress(dialer, status, status.getDefaultMessage()); + new Thread(runner).start(); - return dialer; } public void abort() diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListenerWrapper.java b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListenerWrapper.java new file mode 100644 index 000000000..ae73a9f22 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListenerWrapper.java @@ -0,0 +1,49 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; + +public class FilteredManagerListenerWrapper +{ + FilteredManagerListener _listener; + Set> requiredEvents; + + private final static AtomicInteger seed = new AtomicInteger(); + Integer equalityBuster = seed.incrementAndGet(); + + public FilteredManagerListenerWrapper(FilteredManagerListener listener) + { + this._listener = listener; + this.requiredEvents = listener.requiredEvents(); + + if (requiredEvents.contains(BridgeEvent.class)) + { + // add LinkEvent and UnlinkEvent, as BridgeEvent only will + // miss some events + requiredEvents.add(LinkEvent.class); + requiredEvents.add(UnlinkEvent.class); + } + + for (Class< ? extends ManagerEvent> event : requiredEvents) + { + if (!CoherentEventFactory.mapEvents.values().contains(event) + && !CoherentEventFactory.mapResponses.values().contains(event)) + { + throw new RuntimeException( + "The requested event type of " + event + "+isn't known by " + CoherentEventFactory.class); + } + } + } + + @Override + public String toString() + { + return this._listener.getName(); + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java new file mode 100644 index 000000000..da3e3ef4d --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java @@ -0,0 +1,84 @@ +package org.asteriskjava.pbx.internal.core; + +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.TreeSet; + +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class ListenerManager +{ + private final TreeSet listeners = new TreeSet<>(new ListenerPriorityComparator()); + + Log logger = LogFactory.getLog(ListenerManager.class); + + final class ListenerPriorityComparator implements Comparator + { + @Override + public int compare(FilteredManagerListenerWrapper lhs, FilteredManagerListenerWrapper rhs) + { + + int result = lhs._listener.getPriority().compare(rhs._listener.getPriority()); + + if (result == 0) + result = lhs.equalityBuster.compareTo(rhs.equalityBuster); + + return result; + } + } + + public void clear() + { + listeners.clear(); + } + + public int size() + { + return listeners.size(); + } + + public Iterator iterator() + { + return listeners.iterator(); + } + + public void addListener(FilteredManagerListener listener) + { + listeners.add(new FilteredManagerListenerWrapper(listener)); + } + + List getCopyAsList() + { + List list = new LinkedList<>(); + for (FilteredManagerListenerWrapper listener : listeners) + { + list.add(listener); + } + + return list; + } + + boolean removeListener(FilteredManagerListener toRemove) + { + boolean removed = false; + Iterator itr = listeners.iterator(); + while (itr.hasNext()) + { + FilteredManagerListenerWrapper container = itr.next(); + // logger.error("Checking " + container._listener + " " + toRemove); + if (container._listener == toRemove) + { + logger.error("Removing listener " + toRemove); + itr.remove(); + removed = true; + break; + } + } + return removed; + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java index 675490360..387b1b3ee 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java @@ -74,9 +74,9 @@ public static synchronized PeerMonitor getInstance() private PeerMonitor() { - super("PeerMonitor"); //$NON-NLS-1$ + super("PeerMonitor", PBXFactory.getActivePBX()); //$NON-NLS-1$ this.peerList = new LinkedList<>(); - this.startListener(PBXFactory.getActivePBX()); + this.startListener(); this.addSipsToMonitor(); try { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java index 165fef092..6fe8f0a02 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java @@ -33,7 +33,7 @@ public class Dial extends EventListenerBaseClass public Dial(final String descriptiveName) { - super(descriptiveName); + super(descriptiveName, PBXFactory.getActivePBX()); } /** @@ -62,7 +62,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint try (final OriginateToExtension originate = new OriginateToExtension(listener)) { - this.startListener(PBXFactory.getActivePBX()); + this.startListener(); // First bring the operator's handset up and connect it to the // 'njr-dial' extension where they can diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index b6a0e3d81..382e0415b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -31,7 +31,7 @@ public class DialToAgi extends EventListenerBaseClass public DialToAgi(final String descriptiveName) { - super(descriptiveName); + super(descriptiveName, PBXFactory.getActivePBX()); } /** @@ -59,7 +59,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint try (final OriginateToExtension originate = new OriginateToExtension(listener)) { - this.startListener(PBXFactory.getActivePBX()); + this.startListener(); originator = originate; // First bring the operator's handset up and connect it to the diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java index 89b04522f..d294e9cf7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java @@ -1,7 +1,6 @@ package org.asteriskjava.pbx.internal.managerAPI; import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.FilteredManagerListener; @@ -14,10 +13,12 @@ public abstract class EventListenerBaseClass implements FilteredManagerListener< { private final String name; + private final PBX pbx; - protected EventListenerBaseClass(final String descriptiveName) + protected EventListenerBaseClass(final String descriptiveName, PBX iPBX) { this.name = descriptiveName; + this.pbx = iPBX; } @Override @@ -32,10 +33,10 @@ public String getName() * the pbx at that point event though it is initialised. */ - public void startListener(PBX iPBX) + public void startListener() { - ((AsteriskPBX) iPBX).addListener(this); + ((AsteriskPBX) pbx).addListener(this); } /** @@ -44,8 +45,7 @@ public void startListener(PBX iPBX) @Override public void close() { - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - pbx.removeListener(this); + ((AsteriskPBX) pbx).removeListener(this); } /** @@ -75,7 +75,7 @@ public AutoClose(final EventListenerBaseClass listener, final boolean sendEvents this.listener = listener; if (sendEvents) { - listener.startListener(PBXFactory.getActivePBX()); + listener.startListener(); } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 8afe460d0..f57328a52 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -53,6 +53,8 @@ public abstract class OriginateBaseClass extends EventListenerBaseClass private final OriginateResult result; + Exception ex = new Exception("Created here"); + /** * The following two variables together are used to determine if the * originated channel has come up. This is to overcome the problem that the @@ -71,9 +73,12 @@ public abstract class OriginateBaseClass extends EventListenerBaseClass private final CountDownLatch originateLatch = new CountDownLatch(1); + private final AsteriskPBX pbx; + protected OriginateBaseClass(final NewChannelListener listener, final Channel monitor, final Channel monitor2) { - super("NewOrginateClass"); //$NON-NLS-1$ + super("NewOrginateClass", PBXFactory.getActivePBX()); + pbx = (AsteriskPBX) PBXFactory.getActivePBX(); this.listener = listener; this.monitorChannel1 = monitor; this.monitorChannel2 = monitor2; @@ -168,12 +173,10 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has originate.setAsync(true); originate.setTimeout(localTimeout); - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - try { // Just add us as an asterisk event listener. - this.startListener(pbx); + this.startListener(); response = pbx.sendAction(originate, localTimeout); OriginateBaseClass.logger.debug("Originate.sendAction completed"); //$NON-NLS-1$ @@ -236,7 +239,6 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has void abort(final String reason) { OriginateBaseClass.logger.debug("Aborting originate ");//$NON-NLS-1$ - this.close(); this.originateSuccess = false; this.result.setAbortReason(reason); this.hungup = true; @@ -285,6 +287,7 @@ void abort(final String reason) @Override synchronized public void onManagerEvent(final ManagerEvent event) { + if (event instanceof HangupEvent) { final HangupEvent hangupEvt = (HangupEvent) event; @@ -450,7 +453,7 @@ private void checkBridge(int ctr, Channel channel) { while (ctr > 0) { - logger.error("Check " + ctr); + logger.debug("Check " + ctr); try { ctr--; @@ -495,9 +498,10 @@ private void checkBridge(int ctr, Channel channel) OriginateBaseClass.logger.debug("notifying success 362");//$NON-NLS-1$ originateLatch.countDown(); } - break; } } + logger.info("Id is " + __originateID); + break; } Thread.sleep(100); } diff --git a/src/test/java/org/asteriskjava/pbx/internal/core/ListenerManagerTest.java b/src/test/java/org/asteriskjava/pbx/internal/core/ListenerManagerTest.java new file mode 100644 index 000000000..658077c59 --- /dev/null +++ b/src/test/java/org/asteriskjava/pbx/internal/core/ListenerManagerTest.java @@ -0,0 +1,77 @@ +package org.asteriskjava.pbx.internal.core; + +import static org.junit.Assert.assertTrue; + +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.asteriskjava.pbx.ListenerPriority; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.VarSetEvent; +import org.junit.Test; + +public class ListenerManagerTest +{ + + volatile boolean managereventRecevied = false; + + @Test + public void listenerTest() throws InterruptedException + { + List> listeners = new LinkedList<>(); + + ListenerManager queue = new ListenerManager(); + + for (int i = 0; i < 1000; i++) + { + FilteredManagerListener listener = getListener(); + listeners.add(listener); + queue.addListener(listener); + } + Collections.shuffle(listeners); + for (FilteredManagerListener listener : listeners) + { + assertTrue(queue.removeListener(listener)); + } + + assertTrue(queue.size() == 0); + + } + + private FilteredManagerListener getListener() + { + return new FilteredManagerListener() + { + + @Override + public Set> requiredEvents() + { + Set> events = new HashSet<>(); + events.add(VarSetEvent.class); + return events; + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + managereventRecevied = true; + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + @Override + public String getName() + { + return "test"; + } + }; + } + +} From ff060e2370c1834b00a7490d9f302e129f286f55 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 21 Feb 2018 14:19:16 +1100 Subject: [PATCH 167/802] add timeout arg to dial commands --- .../internal/activity/DialToAgiActivityImpl.java | 14 ++++++++------ .../pbx/internal/core/AsteriskPBX.java | 8 +++++--- .../pbx/internal/core/ListenerManager.java | 2 +- .../asteriskjava/pbx/internal/managerAPI/Dial.java | 2 +- .../pbx/internal/managerAPI/DialToAgi.java | 6 +++--- .../internal/managerAPI/OriginateBaseClass.java | 2 +- .../internal/managerAPI/OriginateToExtension.java | 5 +++-- 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index 3e7c0b2fa..911115448 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -46,12 +46,14 @@ public class DialToAgiActivityImpl extends ActivityHelper imp private DialToAgi originator; - public DialToAgiActivityImpl(final EndPoint originating, final CallerID toCallerID, final boolean hideToCallerID, - final ActivityCallback listener, Map channelVarsToSet, - AgiChannelActivityAction action) + private Integer timeout; + + public DialToAgiActivityImpl(final EndPoint originating, final CallerID toCallerID, Integer timeout, + final boolean hideToCallerID, final ActivityCallback listener, + Map channelVarsToSet, AgiChannelActivityAction action) { super("Dial", listener); - + this.timeout = timeout; this.action = action; this._originating = originating; this.toCallerID = toCallerID; @@ -80,7 +82,7 @@ public boolean doActivity() throws PBXException originator = nr; final OriginateResult[] resultChannels = nr.dial(this, this._originating, this.action, this.toCallerID, - this.hideToCallerId, channelVarsToSet); + this.timeout, this.hideToCallerId, channelVarsToSet); if (resultChannels[0] == null || !resultChannels[0].isSuccess()) { @@ -91,7 +93,7 @@ public boolean doActivity() throws PBXException if (!this.cancelledByOperator) { this.setLastException(new PBXException(("OperatorEndedCall"))); - logger.error("dialout to failed."); + logger.warn("dialout to failed."); } } else diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 37ad013d5..f1bee9477 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -880,7 +880,8 @@ public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, Agi final CompletionAdaptor completion = new CompletionAdaptor<>(); - final DialToAgiActivityImpl dialer = new DialToAgiActivityImpl(endPoint, callerID, false, completion, null, action); + final DialToAgiActivityImpl dialer = new DialToAgiActivityImpl(endPoint, callerID, null, false, completion, null, + action); dialer.startActivity(false); @@ -902,13 +903,14 @@ public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, Agi return dialer; } - public DialToAgiWithAbortCallback dialToAgiWithAbort(EndPoint endPoint, CallerID callerID, + public DialToAgiWithAbortCallback dialToAgiWithAbort(EndPoint endPoint, CallerID callerID, int timeout, AgiChannelActivityAction action, ActivityCallback iCallback) { final CompletionAdaptor completion = new CompletionAdaptor<>(); - final DialToAgiActivityImpl dialer = new DialToAgiActivityImpl(endPoint, callerID, false, completion, null, action); + final DialToAgiActivityImpl dialer = new DialToAgiActivityImpl(endPoint, callerID, timeout, false, completion, null, + action); return new DialToAgiWithAbortCallback(dialer, completion, iCallback); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java index da3e3ef4d..0bec0d1c0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java @@ -72,7 +72,7 @@ boolean removeListener(FilteredManagerListener toRemove) // logger.error("Checking " + container._listener + " " + toRemove); if (container._listener == toRemove) { - logger.error("Removing listener " + toRemove); + logger.debug("Removing listener " + toRemove); itr.remove(); removed = true; break; diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java index 6fe8f0a02..961e653c7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java @@ -68,7 +68,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint // 'njr-dial' extension where they can // wait whilst we complete the second leg final OriginateResult trcResult = originate.originate(localHandset, pbx.getExtensionAgi(), true, - ((AsteriskPBX) pbx).getManagementContext(), callerID, hideCallerId, channelVarsToSet); + ((AsteriskPBX) pbx).getManagementContext(), callerID, null, hideCallerId, channelVarsToSet); this.result[0] = trcResult; if (trcResult.isSuccess() == true) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index 382e0415b..22652479e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -52,7 +52,7 @@ public DialToAgi(final String descriptiveName) * @throws PBXException */ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint localHandset, - final AgiChannelActivityAction action, final CallerID callerID, final boolean hideCallerId, + final AgiChannelActivityAction action, final CallerID callerID, int timeout, final boolean hideCallerId, Map channelVarsToSet) throws PBXException, InterruptedException { final PBX pbx = PBXFactory.getActivePBX(); @@ -66,7 +66,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint // 'njr-dial' extension where they can // wait whilst we complete the second leg final OriginateResult trcResult = originate.originate(localHandset, pbx.getExtensionAgi(), true, - ((AsteriskPBX) pbx).getManagementContext(), callerID, hideCallerId, channelVarsToSet); + ((AsteriskPBX) pbx).getManagementContext(), callerID, timeout, hideCallerId, channelVarsToSet); this.result[0] = trcResult; if (trcResult.isSuccess() == true) @@ -85,7 +85,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint } else { - logger.error("Originate failed: " + trcResult.getAbortReason()); + logger.warn("Originate failed: " + trcResult.getAbortReason()); } logger.info("Hangup status is " + hangupDetected); diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index f57328a52..62d613312 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -217,7 +217,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has } else { - OriginateBaseClass.logger.error("originate failed connecting endPoint: " + local + " to ext " + target); //$NON-NLS-1$//$NON-NLS-2$ + OriginateBaseClass.logger.warn("originate failed connecting endPoint: " + local + " to ext " + target); //$NON-NLS-1$//$NON-NLS-2$ if (this.newChannel != null) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java index 96262a2ab..640038158 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java @@ -45,7 +45,8 @@ public OriginateResult originate(final EndPoint localHandset, final EndPoint tar } public OriginateResult originate(final EndPoint localHandset, final EndPoint targetExtension, final boolean autoAnswer, - final String context, final CallerID callerID, final boolean hideCallerId, Map channelVarsToSet) + final String context, final CallerID callerID, Integer timeout, final boolean hideCallerId, + Map channelVarsToSet) { /* * A new call is originated on the nominated channel to the specified @@ -65,7 +66,7 @@ public OriginateResult originate(final EndPoint localHandset, final EndPoint tar myVars.putAll(channelVarsToSet); } - return this.originate(localHandset, targetExtension, myVars, callerID, null, hideCallerId, context); + return this.originate(localHandset, targetExtension, myVars, callerID, timeout, hideCallerId, context); } @Override From 95f68070669f6914dafaf73700a32f5cba97fdba Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 2 Mar 2018 15:57:04 +1100 Subject: [PATCH 168/802] change arg type to allow null as default --- .../org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index 22652479e..a81e6d188 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -52,7 +52,7 @@ public DialToAgi(final String descriptiveName) * @throws PBXException */ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint localHandset, - final AgiChannelActivityAction action, final CallerID callerID, int timeout, final boolean hideCallerId, + final AgiChannelActivityAction action, final CallerID callerID, Integer timeout, final boolean hideCallerId, Map channelVarsToSet) throws PBXException, InterruptedException { final PBX pbx = PBXFactory.getActivePBX(); From a3ed70bfdc2d2cf5ead44c393e99f89c400516a1 Mon Sep 17 00:00:00 2001 From: Nathan Bruning Date: Thu, 17 Aug 2017 18:33:32 +0200 Subject: [PATCH 169/802] Refactor version detection support. Adds proper support for Asterisk 15 up to 15.2. Removes support for < 1.6 versions, using the 'show file version' method. --- .../internal/ManagerConnectionImpl.java | 270 ++++++++---------- 1 file changed, 117 insertions(+), 153 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 875500214..8b22814d8 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -32,14 +32,12 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -import java.util.regex.Matcher; import java.util.regex.Pattern; import org.asteriskjava.AsteriskVersion; @@ -52,13 +50,7 @@ import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.SendActionCallback; import org.asteriskjava.manager.TimeoutException; -import org.asteriskjava.manager.action.ChallengeAction; -import org.asteriskjava.manager.action.CommandAction; -import org.asteriskjava.manager.action.EventGeneratingAction; -import org.asteriskjava.manager.action.LoginAction; -import org.asteriskjava.manager.action.LogoffAction; -import org.asteriskjava.manager.action.ManagerAction; -import org.asteriskjava.manager.action.UserEventAction; +import org.asteriskjava.manager.action.*; import org.asteriskjava.manager.event.ConnectEvent; import org.asteriskjava.manager.event.DialBeginEvent; import org.asteriskjava.manager.event.DialEvent; @@ -66,10 +58,7 @@ import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.event.ProtocolIdentifierReceivedEvent; import org.asteriskjava.manager.event.ResponseEvent; -import org.asteriskjava.manager.response.ChallengeResponse; -import org.asteriskjava.manager.response.CommandResponse; -import org.asteriskjava.manager.response.ManagerError; -import org.asteriskjava.manager.response.ManagerResponse; +import org.asteriskjava.manager.response.*; import org.asteriskjava.util.DateUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -91,7 +80,7 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher private static final int DEFAULT_PORT = 5038; private static final int RECONNECTION_VERSION_INTERVAL = 500; private static final int MAX_VERSION_ATTEMPTS = 4; - private static final Pattern SHOW_VERSION_PATTERN = Pattern.compile("^(core )?show version.*"); + private static final String CMD_SHOW_VERSION = "core show version"; private static final Pattern VERSION_PATTERN_1_6 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?1\\.6[-. ].*"); private static final Pattern VERSION_PATTERN_1_8 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?1\\.8[-. ].*"); @@ -108,6 +97,9 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher private static final AtomicLong idCounter = new AtomicLong(0); + // current debian stable version, as of 03/07/2018 + private static final AsteriskVersion DEFAULT_ASTERISK_VERSION = AsteriskVersion.ASTERISK_13; + /** * Instance logger. */ @@ -640,166 +632,129 @@ protected AsteriskVersion determineVersion() throws IOException, TimeoutExceptio { int attempts = 0; - // if ("Asterisk Call Manager/1.1".equals(protocolIdentifier.value)) - // { - // return AsteriskVersion.ASTERISK_1_6; - // } + logger.info("Got asterisk protocol identifier version " + protocolIdentifier.getValue()); while (attempts++ < MAX_VERSION_ATTEMPTS) { - final ManagerResponse showVersionFilesResponse; - final List showVersionFilesResult; - boolean Asterisk14outputPresent = false; - // increase timeout as output is quite large - showVersionFilesResponse = sendAction(new CommandAction("show version files pbx.c"), defaultResponseTimeout * 2); - if (!(showVersionFilesResponse instanceof CommandResponse)) - { - // return early in case of permission problems - // org.asteriskjava.manager.response.ManagerError: - // actionId='null'; message='Permission denied'; - // response='Error'; - // uniqueId='null'; systemHashcode=15231583 - if (showVersionFilesResponse.getOutput() != null) - { - Asterisk14outputPresent = true; - } - else - { - break; - } + try { + AsteriskVersion version = determineVersionByCoreSettings(); + if (version != null) return version; + } catch (Exception e) { } - if (Asterisk14outputPresent) - { - List outputList = Arrays - .asList(showVersionFilesResponse.getOutput().split(SocketConnectionFacadeImpl.NL_PATTERN.pattern())); - showVersionFilesResult = outputList; + + try { + AsteriskVersion version = determineVersionByCoreShowVersion(); + if (version != null) return version; + } catch (Exception e) { } - else + + try { - showVersionFilesResult = ((CommandResponse) showVersionFilesResponse).getResult(); + Thread.sleep(RECONNECTION_VERSION_INTERVAL); } - if (showVersionFilesResult != null && !showVersionFilesResult.isEmpty()) + catch (Exception ex) { - final String line1 = showVersionFilesResult.get(0); + // ignore + } // NOPMD + } - if (line1 != null && line1.startsWith("File")) - { - final String rawVersion; + logger.error("Unable to determine asterisk version, assuming " + DEFAULT_ASTERISK_VERSION + "... you should expect problems to follow."); + return DEFAULT_ASTERISK_VERSION; + } - rawVersion = getRawVersion(); - if (rawVersion != null && rawVersion.startsWith("Asterisk 1.4")) - { - return AsteriskVersion.ASTERISK_1_4; - } - return AsteriskVersion.ASTERISK_1_2; - } - else if (line1 != null && line1.contains("No such command")) - { + /** + * Get asterisk version by 'core settings' actions. + * This is supported from Asterisk 1.6 onwards. + * + * @return + * @throws Exception + */ + protected AsteriskVersion determineVersionByCoreSettings() throws Exception { - final ManagerResponse coreShowVersionResponse = sendAction(new CommandAction("core show version"), - defaultResponseTimeout * 2); + ManagerResponse response = sendAction(new CoreSettingsAction()); + if (!(response instanceof CoreSettingsResponse)) { + // NOTE: you need system or reporting permissions + logger.info("Could not get core settings, do we have the necessary permissions?"); + return null; + } - if (coreShowVersionResponse != null && coreShowVersionResponse instanceof CommandResponse) - { - final List coreShowVersionResult = ((CommandResponse) coreShowVersionResponse).getResult(); + String ver = ((CoreSettingsResponse)response).getAsteriskVersion(); + return parseVersionString("Asterisk " + ver); + } - if (coreShowVersionResult != null && !coreShowVersionResult.isEmpty()) - { - final String coreLine = coreShowVersionResult.get(0); - - if (VERSION_PATTERN_1_6.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_1_6; - } - else if (VERSION_PATTERN_1_8.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_1_8; - } - else if (VERSION_PATTERN_10.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_10; - } - else if (VERSION_PATTERN_11.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_11; - } - else if (VERSION_PATTERN_CERTIFIED_11.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_11; - } - else if (VERSION_PATTERN_12.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_12; - } - else if (VERSION_PATTERN_13.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_13; - } - else if (VERSION_PATTERN_CERTIFIED_13.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_13; - } - else if (VERSION_PATTERN_14.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_14; - } - else if (VERSION_PATTERN_15.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_15; - } - } - } + /** + * Determine version by the 'core show version' command. + * This needs 'command' permissions. + * + * @return + * @throws Exception + */ + protected AsteriskVersion determineVersionByCoreShowVersion() throws Exception { + final ManagerResponse coreShowVersionResponse = sendAction(new CommandAction(CMD_SHOW_VERSION)); - try - { - Thread.sleep(RECONNECTION_VERSION_INTERVAL); - } - catch (Exception ex) - { - // ingnore - } // NOPMD - } - else - { - // if it isn't the "no such command", break and return the - // lowest version immediately - break; - } - } + if (coreShowVersionResponse == null || !(coreShowVersionResponse instanceof CommandResponse)) { + // this needs 'command' permissions + logger.info("Could not get response for 'core show version'"); + return null; } - // TODO: add retry logic; in a reconnect scenario the version fails to - // be identified leading to errors + final List coreShowVersionResult = ((CommandResponse) coreShowVersionResponse).getResult(); + if (coreShowVersionResult == null || coreShowVersionResult.isEmpty()) { + logger.warn("Got empty response for 'core show version'"); + return null; + } - // as a fallback assume 1.6 - logger.error("Unable to determine asterisk version, assuming 1.6... you should expect problems to follow."); - return AsteriskVersion.ASTERISK_1_6; + final String coreLine = coreShowVersionResult.get(0); + return parseVersionString(coreLine); } - protected String getRawVersion() - { - final ManagerResponse showVersionResponse; + /** + * Parse a version identifier coming from ast_get_version. + * @param versionString + * @return + */ + protected AsteriskVersion parseVersionString(String versionString) { - try + if (VERSION_PATTERN_1_6.matcher(versionString).matches()) { - showVersionResponse = sendAction(new CommandAction("show version"), defaultResponseTimeout * 2); + return AsteriskVersion.ASTERISK_1_6; } - catch (Exception e) + else if (VERSION_PATTERN_1_8.matcher(versionString).matches()) { - return null; + return AsteriskVersion.ASTERISK_1_8; } - - if (showVersionResponse instanceof CommandResponse) + else if (VERSION_PATTERN_10.matcher(versionString).matches()) { - final List showVersionResult; - - showVersionResult = ((CommandResponse) showVersionResponse).getResult(); - if (showVersionResult != null && !showVersionResult.isEmpty()) - { - return showVersionResult.get(0); - } + return AsteriskVersion.ASTERISK_10; + } + else if (VERSION_PATTERN_11.matcher(versionString).matches()) + { + return AsteriskVersion.ASTERISK_11; + } + else if (VERSION_PATTERN_CERTIFIED_11.matcher(versionString).matches()) + { + return AsteriskVersion.ASTERISK_11; + } + else if (VERSION_PATTERN_12.matcher(versionString).matches()) + { + return AsteriskVersion.ASTERISK_12; + } + else if (VERSION_PATTERN_13.matcher(versionString).matches()) + { + return AsteriskVersion.ASTERISK_13; + } + else if (VERSION_PATTERN_CERTIFIED_13.matcher(versionString).matches()) + { + return AsteriskVersion.ASTERISK_13; + } + else if (VERSION_PATTERN_14.matcher(versionString).matches()) + { + return AsteriskVersion.ASTERISK_14; + } + else if (VERSION_PATTERN_15.matcher(versionString).matches()) + { + return AsteriskVersion.ASTERISK_15; } - return null; } @@ -995,12 +950,15 @@ else if (state != CONNECTED) boolean isShowVersionCommandAction(ManagerAction action) { - if (!(action instanceof CommandAction)) - { - return false; + if (action instanceof CoreSettingsAction) + return true; + + if (action instanceof CommandAction) { + String cmd = ((CommandAction) action).getCommand(); + return CMD_SHOW_VERSION.equals(cmd); } - final Matcher showVersionMatcher = SHOW_VERSION_PATTERN.matcher(((CommandAction) action).getCommand()); - return showVersionMatcher.matches(); + + return false; } private Class< ? extends ManagerResponse> getExpectedResponseClass(Class< ? extends ManagerAction> actionClass) @@ -1431,6 +1389,12 @@ private void setProtocolIdentifier(final String identifier) && !"Asterisk Call Manager/3.1.0".equals(identifier) // Asterisk // =14.3.0 + && !"Asterisk Call Manager/3.2.0".equals(identifier) // since Asterisk 14.4.0 + + && !"Asterisk Call Manager/4.0.0".equals(identifier) // since Asterisk 15 + && !"Asterisk Call Manager/4.0.1".equals(identifier) // since Asterisk 15.1 + && !"Asterisk Call Manager/4.0.2".equals(identifier) // since Asterisk 15.2 + && !"OpenPBX Call Manager/1.0".equals(identifier) && !"CallWeaver Call Manager/1.0".equals(identifier) && !(identifier != null && identifier.startsWith("Asterisk Call Manager Proxy/"))) { From dc6a19e6a45e18c71e1a33870d0bf4c46434dc2a Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 23 Mar 2018 12:04:11 +1100 Subject: [PATCH 170/802] add handling for tech types used by call parking --- src/main/java/org/asteriskjava/pbx/TechType.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/TechType.java b/src/main/java/org/asteriskjava/pbx/TechType.java index 8ded5b1ed..834d5f2f8 100644 --- a/src/main/java/org/asteriskjava/pbx/TechType.java +++ b/src/main/java/org/asteriskjava/pbx/TechType.java @@ -15,7 +15,10 @@ public enum TechType implements Tech , DIALPLAN // CONSOLE is sent when a call is made from the asterisk console. // These type of channels are ignored. - , CONSOLE; + , CONSOLE + + // PARKING & SIPPEER are used during call parking + , PARKING, SIPPEER; private static final Log logger = LogFactory.getLog(TechType.class); From d9c11bd450e47d3942128d6105086d260d17309b Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 27 Mar 2018 11:08:17 +1100 Subject: [PATCH 171/802] reduce logging levels --- .../org/asteriskjava/manager/internal/EventBuilderImpl.java | 2 +- .../java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index 1c9b400cb..13fdde216 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -467,7 +467,7 @@ public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) } if (toRemove.isEmpty()) { - logger.error("Couldn't remove event type " + eventClass); + logger.warn("Couldn't remove event type " + eventClass); } else { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index f1bee9477..23764b364 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -305,7 +305,7 @@ public void hangup(final Channel channel) throws PBXException { if (channel.isLive()) { - logger.warn("Sending hangup action for channel: " + channel); //$NON-NLS-1$ + logger.info("Sending hangup action for channel: " + channel); //$NON-NLS-1$ PBX pbx = PBXFactory.getActivePBX(); if (!pbx.waitForChannelToQuiescent(channel, 3000)) From 19c21fec2b7fb91a98b87490263d628d7062ebf0 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 29 Mar 2018 16:34:07 +1100 Subject: [PATCH 172/802] fix for possible NPE --- .../pbx/internal/managerAPI/DialToAgi.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index a81e6d188..e014684e1 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -71,17 +71,22 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint this.result[0] = trcResult; if (trcResult.isSuccess() == true) { - - trcResult.getChannel().setCurrentActivityAction(action); - if (trcResult.getChannel().waitForChannelToReachAgi(30, TimeUnit.SECONDS)) + if (trcResult.getChannel() != null) { - logger.info("Call reached AGI"); + trcResult.getChannel().setCurrentActivityAction(action); + if (trcResult.getChannel().waitForChannelToReachAgi(30, TimeUnit.SECONDS)) + { + logger.info("Call reached AGI"); + } + else + { + logger.error("Call never reached agi"); + } } else { logger.error("Call never reached agi"); } - } else { From 292f8cbe535374cf59108526a8ec276a1caf3350 Mon Sep 17 00:00:00 2001 From: Michael Krog Date: Mon, 23 Apr 2018 16:39:49 +0200 Subject: [PATCH 173/802] Fixes #243 Removes log4j dependency. --- pom.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pom.xml b/pom.xml index cddf121a6..6dd0406a3 100644 --- a/pom.xml +++ b/pom.xml @@ -180,12 +180,6 @@ 4.12 test - - log4j - log4j - 1.2.17 - compile - org.slf4j slf4j-api From 33dc053223c9520ec6c219c0d6480bdefc8d425d Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Fri, 4 May 2018 17:15:20 -0300 Subject: [PATCH 174/802] missing properties and datatype --- .../manager/event/AbstractParkedCallEvent.java | 6 +++--- .../manager/event/BridgeCreateEvent.java | 17 ++++++++++++++++- .../manager/event/ParkedCallEvent.java | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java index 5d27c2748..502e53eb6 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java @@ -35,7 +35,7 @@ public abstract class AbstractParkedCallEvent extends ManagerEvent private String parkeeCallerIDNum; // Previously CallerIDName private String parkeeCallerIDName; - private Integer parkeeConnectedLineNum; + private String parkeeConnectedLineNum; private String parkeeConnectedLineName; private String parkeeLanguage; private String parkeeAccountCode; @@ -187,12 +187,12 @@ public void setParkeeCallerIDName(String parkeeCallerIDName) this.parkeeCallerIDName = parkeeCallerIDName; } - public Integer getParkeeConnectedLineNum() + public String getParkeeConnectedLineNum() { return parkeeConnectedLineNum; } - public void setParkeeConnectedLineNum(Integer parkeeConnectedLineNum) + public void setParkeeConnectedLineNum(String parkeeConnectedLineNum) { this.parkeeConnectedLineNum = parkeeConnectedLineNum; } diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeCreateEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeCreateEvent.java index 876c785b9..89ad67840 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeCreateEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeCreateEvent.java @@ -5,13 +5,28 @@ */ public class BridgeCreateEvent extends AbstractBridgeEvent { + private String bridgevideosourcemode; + + /** + * @param bridgevideosourcemode the bridgevideosourcemode to set + */ + public void setBridgevideosourcemode(String bridgevideosourcemode) { + this.bridgevideosourcemode = bridgevideosourcemode; + } + /** - * + * @return the bridgevideosourcemode */ + public String getBridgevideosourcemode() { + return bridgevideosourcemode; + } + private static final long serialVersionUID = 1L; public BridgeCreateEvent(Object source) { super(source); } + + } diff --git a/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java b/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java index 9c6311988..3420473c0 100644 --- a/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java @@ -36,6 +36,7 @@ public class ParkedCallEvent extends AbstractParkedCallEvent private Integer timeout; private String connectedlinenum; private String connectedlinename; + private String parkeelinkedid; /** * @param source @@ -96,5 +97,19 @@ public void setConnectedLinename(String connectedlinename) this.connectedlinename = connectedlinename; } + /** + * @param parkeelinkedid the parkeelinkedid to set + */ + public void setParkeelinkedid(String parkeelinkedid) { + this.parkeelinkedid = parkeelinkedid; + } + + /** + * @return the parkeelinkedid + */ + public String getParkeelinkedid() { + return parkeelinkedid; + } + } From 6ecf48df55c04ccc6e66fea4fcaf33e934ed04ba Mon Sep 17 00:00:00 2001 From: Brett Sutton Date: Mon, 7 May 2018 13:23:47 +1000 Subject: [PATCH 175/802] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index d6d6e171b..98c564643 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,9 @@ 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](http://asterisk.org). Asterisk-Java supports both interfaces that Asterisk provides for this scenario: The [FastAGI](https://wiki.asterisk.org/wiki/display/AST/Application_AGI) protocol and the [Manager API](https://wiki.asterisk.org/wiki/display/AST/The+Asterisk+Manager+TCP+IP+API). +You can find the Java docs for the lastest version here: +[JavaDoc](https://javadoc.io/doc/org.asteriskjava/asterisk-java/2.0.2) + FastAGI ------- FastAGI lets you create a service that manages a call in a similar way to what a webserver handles a http request. FastAGI can be (and should be) used to replace dialplan. FastAGI is thousands of times faster than dialplan, easier to debug and lets you do call control in a language that you are familiar with. From 50eb964ed0c3cceedce4c5f81616fc08b1be03f4 Mon Sep 17 00:00:00 2001 From: Michael Krog Date: Sat, 12 May 2018 18:34:49 +0200 Subject: [PATCH 176/802] Readds log4j with provied scope instead of compile --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index 6dd0406a3..835f8de02 100644 --- a/pom.xml +++ b/pom.xml @@ -186,6 +186,12 @@ 1.7.9 compile + + log4j + log4j + 1.2.17 + provided + ch.qos.logback logback-classic From 3aea47befbf3aadf55eb51ab3d9de4d1f99b8397 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 15 May 2018 11:08:34 +1000 Subject: [PATCH 177/802] do not hangup when the activity is cancelled --- .../pbx/agi/AgiChannelActivityHoldForBridge.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java index d655c6ce5..41bd846cf 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java @@ -12,6 +12,7 @@ public class AgiChannelActivityHoldForBridge implements AgiChannelActivityAction { private final Log logger = LogFactory.getLog(this.getClass()); private AgiChannelActivityBridge bridgeActivity; + private boolean hangup = true; public AgiChannelActivityHoldForBridge(AgiChannelActivityBridge bridgeActivity) { @@ -26,7 +27,10 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I channel.playMusicOnHold(); bridgeActivity.sleepWhileBridged(); - channel.hangup(); + if (hangup) + { + channel.hangup(); + } } catch (AgiHangupException e) { @@ -44,7 +48,7 @@ public boolean isDisconnect() @Override public void cancel(Channel channel) { - // TODO Auto-generated method stub + hangup = false; } // Logger logger = LogManager.getLogger(); From 7ef4d04c634a924e5d3bdab37f4effdf18e3baf6 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 15 May 2018 15:32:33 +1000 Subject: [PATCH 178/802] fix for race condition in SplitActivity and ChannelActivitites --- .../agi/AgiChannelActivityHoldForBridge.java | 4 ++-- .../internal/activity/SplitActivityImpl.java | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java index 41bd846cf..5e87928b9 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java @@ -12,7 +12,7 @@ public class AgiChannelActivityHoldForBridge implements AgiChannelActivityAction { private final Log logger = LogFactory.getLog(this.getClass()); private AgiChannelActivityBridge bridgeActivity; - private boolean hangup = true; + private volatile boolean hangup = true; public AgiChannelActivityHoldForBridge(AgiChannelActivityBridge bridgeActivity) { @@ -48,7 +48,7 @@ public boolean isDisconnect() @Override public void cancel(Channel channel) { - hangup = false; + hangup = false; } // Logger logger = LogManager.getLogger(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index a3c5f6903..b42493a91 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -17,6 +17,7 @@ import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.activities.SplitActivity; +import org.asteriskjava.pbx.agi.AgiChannelActivityBridge; import org.asteriskjava.pbx.agi.AgiChannelActivityHold; import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; @@ -199,8 +200,22 @@ private boolean splitTwo() throws PBXException pbx.setVariable(channel1, "proxyId", "" + ((ChannelProxy) channel1).getIdentity()); pbx.setVariable(channel2, "proxyId", "" + ((ChannelProxy) channel2).getIdentity()); - channel1.setCurrentActivityAction(agi1); - channel2.setCurrentActivityAction(agi2); + // AgiChannelAcitivyBridge has a latch which other activities may be + // sleeping on, so it's important + // to change the other channels activity first to avoid it waking and + // taking an undesired action + // when the AgiChannelActivityBridge channel has it's acitvity + // cancelled. + if (channel2.getCurrentActivityAction() instanceof AgiChannelActivityBridge) + { + channel1.setCurrentActivityAction(agi1); + channel2.setCurrentActivityAction(agi2); + } + else + { + channel2.setCurrentActivityAction(agi2); + channel1.setCurrentActivityAction(agi1); + } final String agiExten = profile.getAgiExtension(); final String agiContext = profile.getManagementContext(); From ef18f8f7ae23e7b2be7ba10c7a8e90658e803d8c Mon Sep 17 00:00:00 2001 From: Nathan Bruning Date: Fri, 25 May 2018 16:19:14 +0200 Subject: [PATCH 179/802] Add PJSIPNotify action (new in Asterisk 15.4) --- .../manager/action/PJSIPNotifyAction.java | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java diff --git a/src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java b/src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java new file mode 100644 index 000000000..12e0ab610 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java @@ -0,0 +1,136 @@ +/* + * Copyright 2018 IPerity BV + * + * 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.manager.action; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Send a NOTIFY to either an endpoint or an arbitrary URI. + *

+ * Either a URI, a channel or an endpoint can be specified. + *

+ *

+ * See: https://wiki.asterisk.org/wiki/display/AST/Asterisk+15+ManagerAction_PJSIPNotify + */ +public class PJSIPNotifyAction extends AbstractManagerAction implements ManagerAction { + static final long serialVersionUID = 8198467461743334704L; + + private String channel; + private String endpoint; + private String uri; + private Map variables; + + public PJSIPNotifyAction() { + super(); + } + + @Override + public String getAction() { + return "PJSIPNotify"; + } + + /** + * Get the PJSIP channel to send the NOTIFY on. + * + * @return + */ + public String getChannel() { + return this.channel; + } + + /** + * Get the PJSIP endpoint to which to send the NOTIFY. + * + * @return + */ + public String getEndpoint() { + return this.endpoint; + } + + /** + * Get the URI to which to send the NOTIFY. + * + * @return + */ + public String getUri() { + return this.uri; + } + + /** + * Set the PJSIP channel name to send the NOTIFY on. This must be a PJSIP channel, + * ie. start with "PJSIP/". + * + * @param channel + */ + public void setChannel(String channel) { + this.channel = channel; + } + + /** + * Set the PJSIP endpoint to send to NOTIFY to. + * + * @param endpoint + */ + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + /** + * Set an abritrary URI to send the NOTIFY to. + * + * @param uri + */ + public void setUri(String uri) { + this.uri = uri; + } + + /** + * Add a variable. + *

+ * Use the 'content' variable to specify the NOTIFY body. + * + * @param name + * @param value + */ + public void setVariable(String name, String value) { + if (this.variables == null) { + this.variables = new LinkedHashMap<>(); + } + + this.variables.put(name, value); + } + + /** + * Set all variables. See {@link #setVariable(String, String)}. + * + * @param variables + */ + public void setVariables(Map variables) { + this.variables = variables; + } + + /** + * Get the variables. + * + * @return + */ + public Map getVariables() { + return this.variables; + } + +} From 032106dbea69e7db8fcf02a8251da756285a298d Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Thu, 31 May 2018 15:42:57 -0500 Subject: [PATCH 180/802] add early media to originate --- .../manager/action/OriginateAction.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java index fe5b510fe..3cad53230 100644 --- a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java +++ b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java @@ -73,6 +73,7 @@ public class OriginateAction extends AbstractManagerAction implements EventGener private String data; private Boolean async; private String codecs; + private Boolean earlyMedia; /** * Returns the name of this action, i.e. "Originate". @@ -467,6 +468,20 @@ public void setAsync(Boolean async) this.async = async; } + /** + * @param earlyMedia the earlyMedia to set + */ + public void setEarlyMedia(Boolean earlyMedia) { + this.earlyMedia = earlyMedia; + } + + /** + * @return the earlyMedia + */ + public Boolean getEarlyMedia() { + return earlyMedia; + } + /** * Returns the codecs to use for the call. * From 8f4f9a5a2e8da5fcfcf1c951903bd9babb1fe492 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 12 Jun 2018 15:16:08 -0400 Subject: [PATCH 181/802] Handle case when command is 'meetme list' --- .../asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index c9da7d9ad..8426910e2 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -354,7 +354,7 @@ private synchronized void parseMeetme(final String line) throws NoMeetmeExceptio && (line.toLowerCase().startsWith("conf num") == false) //$NON-NLS-1$ && (line.toLowerCase().startsWith("* total number") == false) //$NON-NLS-1$ && (line.toLowerCase().startsWith("no such conference") == false) //$NON-NLS-1$ - && (line.toLowerCase().startsWith("no such command 'meetme'") == false) //$NON-NLS-1$ + && (line.toLowerCase().startsWith("no such command 'meetme") == false) //$NON-NLS-1$ ) { // Update the stats on each meetme From 193cfeec6214067ce7c244d35117d3d11a72b0f8 Mon Sep 17 00:00:00 2001 From: Nathan Bruning Date: Wed, 20 Jun 2018 17:01:39 +0200 Subject: [PATCH 182/802] PJSIPNotifyAction: fix code formatting --- .../manager/action/PJSIPNotifyAction.java | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java b/src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java index 12e0ab610..6c261dcb8 100644 --- a/src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java @@ -27,20 +27,22 @@ *

* See: https://wiki.asterisk.org/wiki/display/AST/Asterisk+15+ManagerAction_PJSIPNotify */ -public class PJSIPNotifyAction extends AbstractManagerAction implements ManagerAction { - static final long serialVersionUID = 8198467461743334704L; - +public class PJSIPNotifyAction extends AbstractManagerAction implements ManagerAction +{ + private static final long serialVersionUID = 8198467461743334704L; private String channel; private String endpoint; private String uri; private Map variables; - public PJSIPNotifyAction() { + public PJSIPNotifyAction() + { super(); } @Override - public String getAction() { + public String getAction() + { return "PJSIPNotify"; } @@ -49,7 +51,8 @@ public String getAction() { * * @return */ - public String getChannel() { + public String getChannel() + { return this.channel; } @@ -58,7 +61,8 @@ public String getChannel() { * * @return */ - public String getEndpoint() { + public String getEndpoint() + { return this.endpoint; } @@ -67,7 +71,8 @@ public String getEndpoint() { * * @return */ - public String getUri() { + public String getUri() + { return this.uri; } @@ -77,7 +82,8 @@ public String getUri() { * * @param channel */ - public void setChannel(String channel) { + public void setChannel(String channel) + { this.channel = channel; } @@ -86,7 +92,8 @@ public void setChannel(String channel) { * * @param endpoint */ - public void setEndpoint(String endpoint) { + public void setEndpoint(String endpoint) + { this.endpoint = endpoint; } @@ -95,7 +102,8 @@ public void setEndpoint(String endpoint) { * * @param uri */ - public void setUri(String uri) { + public void setUri(String uri) + { this.uri = uri; } @@ -107,8 +115,10 @@ public void setUri(String uri) { * @param name * @param value */ - public void setVariable(String name, String value) { - if (this.variables == null) { + public void setVariable(String name, String value) + { + if (this.variables == null) + { this.variables = new LinkedHashMap<>(); } @@ -120,7 +130,8 @@ public void setVariable(String name, String value) { * * @param variables */ - public void setVariables(Map variables) { + public void setVariables(Map variables) + { this.variables = variables; } @@ -129,7 +140,8 @@ public void setVariables(Map variables) { * * @return */ - public Map getVariables() { + public Map getVariables() + { return this.variables; } From 0934f93ef0f44fb9c79965e0eb196e848d25d7cf Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 25 Jun 2018 14:47:45 +1000 Subject: [PATCH 183/802] Fixed some concurrency issues --- .../java/org/asteriskjava/pbx/CallImpl.java | 23 ++++---------- .../org/asteriskjava/pbx/ChannelFactory.java | 8 +++-- .../wrap/actions/AbstractManagerAction.java | 31 +++++-------------- .../pbx/internal/managerAPI/MonitorCall.java | 15 +++++---- 4 files changed, 26 insertions(+), 51 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/CallImpl.java b/src/main/java/org/asteriskjava/pbx/CallImpl.java index ca8cb5fa4..9596b11f6 100644 --- a/src/main/java/org/asteriskjava/pbx/CallImpl.java +++ b/src/main/java/org/asteriskjava/pbx/CallImpl.java @@ -4,6 +4,7 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import org.asteriskjava.pbx.activities.BlindTransferActivity; import org.asteriskjava.util.Log; @@ -32,12 +33,12 @@ public class CallImpl implements ChannelHangupListener, Call * We give every call a unique call id to help track the calls when checking * logs */ - private static int global_call_identifier_index = 0; + private static final AtomicInteger global_call_identifier_index = new AtomicInteger(); /** * A id that uniquely identifies this call. */ - private int _uniquecallID; + private final int _uniquecallID; /* * transfer types @@ -129,9 +130,9 @@ public CallImpl(Channel originatingChannel, CallDirection direction) throws PBXE { logger.debug("Created call=" + originatingChannel + " direction=" + direction); //$NON-NLS-1$ //$NON-NLS-2$ this._owner = OWNER.SELF; + this._uniquecallID = CallImpl.global_call_identifier_index.incrementAndGet(); this._direction = direction; this._callStarted = new Date(); - this.setUID(); this.setOriginatingParty(originatingChannel); } @@ -140,9 +141,9 @@ public CallImpl(Channel originatingChannel, Channel acceptingChannel, CallDirect { logger.debug("Created call=" + originatingChannel + " direction=" + direction); //$NON-NLS-1$ //$NON-NLS-2$ this._owner = OWNER.SELF; + this._uniquecallID = CallImpl.global_call_identifier_index.incrementAndGet(); this._direction = direction; this._callStarted = new Date(); - this.setUID(); this.setOriginatingParty(originatingChannel); this.setAcceptingParty(acceptingChannel); @@ -151,9 +152,9 @@ public CallImpl(Channel originatingChannel, Channel acceptingChannel, CallDirect public CallImpl(Channel agent, Channel callee) throws PBXException { this._owner = OWNER.SELF; + this._uniquecallID = CallImpl.global_call_identifier_index.incrementAndGet(); this._direction = CallDirection.OUTBOUND; this._callStarted = new Date(); - this.setUID(); this.setOriginatingParty(agent); this.setAcceptingParty(callee); @@ -671,18 +672,6 @@ public void setContactId(final Integer _contactId) // this.transferType = tType; // } - /** - * - */ - private synchronized void setUID() - { - this._uniquecallID = CallImpl.global_call_identifier_index++; - if (CallImpl.global_call_identifier_index > 99) - { - CallImpl.global_call_identifier_index = 0; - } - } - @Override public CallDirection getDirection() { diff --git a/src/main/java/org/asteriskjava/pbx/ChannelFactory.java b/src/main/java/org/asteriskjava/pbx/ChannelFactory.java index 0e5fd88f5..1da871dd6 100644 --- a/src/main/java/org/asteriskjava/pbx/ChannelFactory.java +++ b/src/main/java/org/asteriskjava/pbx/ChannelFactory.java @@ -1,5 +1,7 @@ package org.asteriskjava.pbx; +import java.util.concurrent.atomic.AtomicLong; + /** * Currently this factories only purposes is to serve up globally unique channel * id's which every new channel must be assigned. @@ -9,10 +11,10 @@ public class ChannelFactory { - private static long nextChannelId = 0; + private final static AtomicLong nextChannelId = new AtomicLong(); - public static synchronized long getNextChannelId() + public static long getNextChannelId() { - return ++ChannelFactory.nextChannelId; + return nextChannelId.incrementAndGet(); } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/AbstractManagerAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/AbstractManagerAction.java index 0b1f6e19d..04c33680a 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/AbstractManagerAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/AbstractManagerAction.java @@ -1,38 +1,23 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; +import java.util.concurrent.atomic.AtomicLong; + /** * Automatically generates a globally unique action id (based on the systems mac * address * * @author bsutton - * */ abstract public class AbstractManagerAction implements ManagerAction { - private static long _nextActionId = 1; - - private String _actionId; - - AbstractManagerAction() - { - this._actionId = generateActionId(); - } - - public String getActionId() - { - return this._actionId; - } - - synchronized public String generateActionId() - { + private final static AtomicLong _nextActionId = new AtomicLong(); - return "" + _nextActionId++; - } + private final String _actionId = "" + _nextActionId.incrementAndGet(); - protected void setActionId(String actionId) - { - this._actionId = actionId; - } + public String getActionId() + { + return this._actionId; + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java index b0b23c0f4..278fee9ca 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java @@ -1,6 +1,6 @@ package org.asteriskjava.pbx.internal.managerAPI; -import java.util.Date; +import java.util.concurrent.atomic.AtomicLong; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.PBXFactory; @@ -13,7 +13,7 @@ public class MonitorCall { private static final Log logger = LogFactory.getLog(MonitorCall.class); - static long id = 1; + private static final AtomicLong id = new AtomicLong(); private String file = null; @@ -24,7 +24,7 @@ public MonitorCall(final Call call) try { this.setFile(); - final MonitorAction monitorAction = new MonitorAction(call.getRemoteParty(), this.file, "gsm", true); //$NON-NLS-1$ + final MonitorAction monitorAction = new MonitorAction(call.getRemoteParty(), this.file, "gsm", true); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -39,17 +39,16 @@ public MonitorCall(final Call call) public String getFilename() { - return this.file + ".gsm"; //$NON-NLS-1$ + return this.file + ".gsm"; } - private synchronized void setFile() + private void setFile() { - long no = (new Date()).getTime(); + long no = System.currentTimeMillis(); no = no / 1000; final String unq = Long.toHexString(no); - this.file = "njr" + unq + "-" + MonitorCall.id; //$NON-NLS-1$ //$NON-NLS-2$ - MonitorCall.id++; + this.file = "njr" + unq + "-" + MonitorCall.id.incrementAndGet(); } From 939ec08d693370b23a9891d51565f9ef40289ece Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 26 Jun 2018 11:58:21 +1000 Subject: [PATCH 184/802] add convenience method for adding sip headers to originate action. also fix for possibly accidentally replacing set variables --- .../manager/action/OriginateAction.java | 33 ++++++++++++++++++- .../manager/action/VariableInheritance.java | 18 ++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/asteriskjava/manager/action/VariableInheritance.java diff --git a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java index fe5b510fe..130f0a0e7 100644 --- a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java +++ b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java @@ -16,10 +16,12 @@ */ package org.asteriskjava.manager.action; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.StringTokenizer; import org.asteriskjava.manager.event.OriginateResponseEvent; @@ -74,6 +76,10 @@ public class OriginateAction extends AbstractManagerAction implements EventGener private Boolean async; private String codecs; + // starting at ten saves on a formatter. + private int headerCounter = 10; + private Set preventDuplicateSipHeaders = new HashSet<>(); + /** * Returns the name of this action, i.e. "Originate". * @@ -447,7 +453,14 @@ public Map getVariables() */ public void setVariables(Map variables) { - this.variables = variables; + if (this.variables != null) + { + this.variables.putAll(variables); + } + else + { + this.variables = variables; + } } /** @@ -520,4 +533,22 @@ public void setCodecs(List codecs) { return OriginateResponseEvent.class; } + + public void addSipHeader(VariableInheritance inheritance, String header) + { + if (!preventDuplicateSipHeaders.contains(header)) + { + setVariable(inheritance.getPrefix() + "SIPADDHEADER" + (headerCounter++), header); + preventDuplicateSipHeaders.add(header); + if (headerCounter > 50) + { + logger.warn("I think only 50 headers are allowed by asterisk?"); + } + } + else + { + logger.error("Already added the sip header " + header); + } + } + } diff --git a/src/main/java/org/asteriskjava/manager/action/VariableInheritance.java b/src/main/java/org/asteriskjava/manager/action/VariableInheritance.java new file mode 100644 index 000000000..369f439e1 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/VariableInheritance.java @@ -0,0 +1,18 @@ +package org.asteriskjava.manager.action; + +public enum VariableInheritance +{ + NONE(""), SINGLE("_"), DOUBLE("__"); + + private String prefix; + + VariableInheritance(String prefix) + { + this.prefix = prefix; + } + + String getPrefix() + { + return prefix; + } +} From cd8e68a1ec3ee1c41de949343a29582b4e72e8f6 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 4 Jul 2018 14:11:24 +1000 Subject: [PATCH 185/802] remove unneeded method argument add convience method to AgiChannelActivityHoldForBridge --- .../asteriskjava/pbx/AgiChannelActivityAction.java | 2 +- .../java/org/asteriskjava/pbx/agi/ActivityAgi.java | 2 +- .../pbx/agi/AgiChannelActivityBlindTransfer.java | 2 +- .../pbx/agi/AgiChannelActivityBridge.java | 2 +- .../pbx/agi/AgiChannelActivityDial.java | 2 +- .../pbx/agi/AgiChannelActivityHangup.java | 2 +- .../pbx/agi/AgiChannelActivityHold.java | 2 +- .../pbx/agi/AgiChannelActivityHoldForBridge.java | 13 +++++++++++-- .../pbx/agi/AgiChannelActivityMeetme.java | 13 +++++-------- .../pbx/agi/AgiChannelActivityPlayMessage.java | 2 +- .../pbx/agi/AgiChannelActivityQueue.java | 12 ++++++------ .../pbx/agi/AgiChannelActivityVoicemail.java | 2 +- .../pbx/internal/core/ChannelProxy.java | 2 +- 13 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java b/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java index 90daddbaf..8e150d008 100644 --- a/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java +++ b/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java @@ -10,6 +10,6 @@ public interface AgiChannelActivityAction boolean isDisconnect(); - void cancel(Channel channel); + void cancel(); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index acab6d8b4..f773a4e5d 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -51,7 +51,7 @@ public void channelHangup(Channel channel, Integer cause, String causeText) final AgiChannelActivityAction currentActivityAction = channel.getCurrentActivityAction(); if (currentActivityAction != null) { - currentActivityAction.cancel(channel); + currentActivityAction.cancel(); } } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java index 350184a6c..156433cd2 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java @@ -45,7 +45,7 @@ public boolean isDisconnect() } @Override - public void cancel(Channel channel) + public void cancel() { latch.countDown(); diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java index d07c1711e..ba5141771 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java @@ -49,7 +49,7 @@ public boolean isDisconnect() } @Override - public void cancel(Channel channel) + public void cancel() { latch.countDown(); diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java index 5f65bd3e0..e33a76c1b 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java @@ -50,7 +50,7 @@ public boolean isDisconnect() } @Override - public void cancel(Channel channel) + public void cancel() { latch.countDown(); diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java index d6fd85bd7..dbc2bc240 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java @@ -39,7 +39,7 @@ public boolean isDisconnect() } @Override - public void cancel(Channel channel) + public void cancel() { latch.countDown(); diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java index 09461fdb8..308a224f3 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java @@ -71,7 +71,7 @@ public boolean isDisconnect() } @Override - public void cancel(Channel channel) + public void cancel() { latch.countDown(); diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java index 5e87928b9..1be5c4506 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java @@ -46,10 +46,19 @@ public boolean isDisconnect() } @Override - public void cancel(Channel channel) + public void cancel() { + // this seems a bit strange, but the logic here is that if you cancel + // this action you want to invoke a new action. We can't end the bridge + // from here, but not hanging up when it does collapse is + // important. hangup = false; } - // Logger logger = LogManager.getLogger(); + + public void hangupAfterBridge(boolean b) + { + hangup = b; + } + } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java index fe7c02a70..1194386ee 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java @@ -27,6 +27,8 @@ public class AgiChannelActivityMeetme implements AgiChannelActivityAction private String options; + private Channel ichannel; + public AgiChannelActivityMeetme(String room, String options) { this.room = room; @@ -40,6 +42,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I { throw new NullPointerException("ichannel cannot be null"); } + this.ichannel = ichannel; AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) { @@ -71,19 +74,13 @@ public boolean isDisconnect() } @Override - public void cancel(Channel channel) + public void cancel() { - - if (channel == null) - { - throw new NullPointerException("channel cannot be null"); - } - hangup = false; final AsteriskSettings profile = PBXFactory.getActiveProfile(); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - final RedirectAction redirect = new RedirectAction(channel, profile.getManagementContext(), pbx.getExtensionAgi(), + final RedirectAction redirect = new RedirectAction(ichannel, profile.getManagementContext(), pbx.getExtensionAgi(), 1); try { diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java index 5d3a06960..7aa2932d9 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java @@ -59,7 +59,7 @@ public boolean isDisconnect() } @Override - public void cancel(Channel channel) + public void cancel() { hangup = true; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java index 217eb60ac..327c68314 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java @@ -27,6 +27,8 @@ public class AgiChannelActivityQueue implements AgiChannelActivityAction private volatile boolean hangup = true; // volatile private iChannel ichannel; + private Channel ichannel; + public AgiChannelActivityQueue(String queue) { this.queue = queue; @@ -35,6 +37,8 @@ public AgiChannelActivityQueue(String queue) @Override public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { + this.ichannel = ichannel; + channel.queue(queue); if (hangup) { @@ -62,18 +66,14 @@ public boolean isDisconnect() } @Override - public void cancel(Channel channel) + public void cancel() { - if (channel == null) - { - throw new NullPointerException("channel cannot be null"); - } hangup = false; final AsteriskSettings profile = PBXFactory.getActiveProfile(); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - final RedirectAction redirect = new RedirectAction(channel, profile.getManagementContext(), pbx.getExtensionAgi(), + final RedirectAction redirect = new RedirectAction(ichannel, profile.getManagementContext(), pbx.getExtensionAgi(), 1); try { diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java index 0010ae3f6..560b35c48 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java @@ -28,7 +28,7 @@ public boolean isDisconnect() } @Override - public void cancel(Channel channel) + public void cancel() { // TODO Auto-generated method stub diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index 4ef87cc0a..c5b470db0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -348,7 +348,7 @@ public void setCurrentActivityAction(AgiChannelActivityAction action) if (previousAction != null) { // when we cancel the previous action, the new one will be invoked - previousAction.cancel(this); + previousAction.cancel(); } } From 7d5bc1012814303432b74e34b5368553aebca767 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 4 Jul 2018 16:57:49 +1000 Subject: [PATCH 186/802] Fast Scanner Impl --- NlStreamReaderFast273316816601633219txt | 31 +++ .../internal/SocketConnectionFacadeImpl.java | 23 +- .../internal/streamreader/FastScanner.java | 10 + .../streamreader/FastScannerCrNl.java | 72 +++++++ .../streamreader/FastScannerFactory.java | 72 +++++++ .../internal/streamreader/FastScannerNl.java | 199 ++++++++++++++++++ .../FastScannerDeterministicTest.java | 98 +++++++++ .../streamreader/FastScannerRandomTest.java | 143 +++++++++++++ .../streamreader/FastScannerSpeedTest.java | 105 +++++++++ .../FastScannerSpeedTestOnSocket.java | 127 +++++++++++ .../FastScannerTestSocketSource.java | 34 +++ 11 files changed, 899 insertions(+), 15 deletions(-) create mode 100644 NlStreamReaderFast273316816601633219txt create mode 100644 src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java create mode 100644 src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerCrNl.java create mode 100644 src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerFactory.java create mode 100644 src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java create mode 100644 src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerDeterministicTest.java create mode 100644 src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerRandomTest.java create mode 100644 src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTest.java create mode 100644 src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTestOnSocket.java create mode 100644 src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerTestSocketSource.java diff --git a/NlStreamReaderFast273316816601633219txt b/NlStreamReaderFast273316816601633219txt new file mode 100644 index 000000000..91b41b092 --- /dev/null +++ b/NlStreamReaderFast273316816601633219txt @@ -0,0 +1,31 @@ +agi_network: yes +agi_network_script: route?targ=7601&ctx=Pre-Handset +agi_request: agi://10.10.0.41/route?targ=7601&ctx=Pre-Handset +agi_channel: Local/7610@default-2df1,1 +agi_language: en +agi_type: Local +agi_uniqueid: 1530169476.16133 +agi_callerid: unknown +agi_calleridname: unknown +agi_callingpres: 0 +agi_callingani2: 0 +agi_callington: 0 +agi_callingtns: 0 +agi_dnid: unknown +agi_rdnis: unknown +agi_context: routesv2-handset +agi_extension: 7601 +agi_priority: 1 +agi_enhanced: 0.0 +agi_accountcode: + +200 result=0 +200 result=1 () +200 result=0 +200 result=1 +200 result=0 +200 result=0 +200 result=0 +200 result=0 +200 result=1 () +200 result=1 diff --git a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java index a08ba44f1..9b823bf44 100644 --- a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java +++ b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java @@ -16,7 +16,6 @@ */ package org.asteriskjava.util.internal; -import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; @@ -29,13 +28,14 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.NoSuchElementException; -import java.util.Scanner; import java.util.regex.Pattern; import javax.net.SocketFactory; import javax.net.ssl.SSLSocketFactory; import org.asteriskjava.util.SocketConnectionFacade; +import org.asteriskjava.util.internal.streamreader.FastScanner; +import org.asteriskjava.util.internal.streamreader.FastScannerFactory; /** * Default implementation of the SocketConnectionFacade interface using java.io. @@ -48,7 +48,7 @@ public class SocketConnectionFacadeImpl implements SocketConnectionFacade public static final Pattern CRNL_PATTERN = Pattern.compile("\r\n"); public static final Pattern NL_PATTERN = Pattern.compile("\n"); private Socket socket; - private Scanner scanner; + private FastScanner scanner; private BufferedWriter writer; private Trace trace; @@ -168,36 +168,29 @@ private void initialize(Socket socket, Charset encoding, Pattern pattern) throws InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, encoding)); + InputStreamReader reader = new InputStreamReader(inputStream, encoding); - this.scanner = new Scanner(reader); - this.scanner.useDelimiter(pattern); + this.scanner = FastScannerFactory.getReader(reader, pattern); + // this.scanner.useDelimiter(pattern); this.writer = new BufferedWriter(new OutputStreamWriter(outputStream, encoding)); } @Override public String readLine() throws IOException { - String line; + String line = null; try { line = scanner.next(); + } catch (IllegalStateException e) { - if (scanner.ioException() != null) - { - throw scanner.ioException(); - } // throw new IOException("No more lines available", e); // JDK6 throw new IOException("No more lines available: " + e.getMessage()); } catch (NoSuchElementException e) { - if (scanner.ioException() != null) - { - throw scanner.ioException(); - } // throw new IOException("No more lines available", e); // JDK6 throw new IOException("No more lines available: " + e.getMessage()); } diff --git a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java new file mode 100644 index 000000000..d3e92c1e1 --- /dev/null +++ b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java @@ -0,0 +1,10 @@ +package org.asteriskjava.util.internal.streamreader; + +import java.io.Closeable; +import java.io.IOException; + +public interface FastScanner extends Closeable +{ + public String next() throws IOException; + +} diff --git a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerCrNl.java b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerCrNl.java new file mode 100644 index 000000000..c6d48e826 --- /dev/null +++ b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerCrNl.java @@ -0,0 +1,72 @@ +package org.asteriskjava.util.internal.streamreader; + +public class FastScannerCrNl extends FastScannerNl +{ + + private char crChar = '\r'; + private boolean seenReturn = false; + + public FastScannerCrNl(Readable reader) + { + super(reader); + + } + + protected String getLine(boolean endOfLine) + { + // iterate the builder looking for the delimiter chars + for (int i = start; i < end; i++) + { + if (cbuf.get(i) == crChar) + { + // flag that we've encountered the first of the two delimiter + // characters + seenReturn = true; + } + else if (seenReturn && cbuf.get(i) == nlChar) + { + // we've seen both of the delimiter characters, package up the + // data and return it... + if (i == start) + { + // back track to remove a /r in the last packet + result.setLength(result.length() - 1); + } + if (i > start) + { + // append the data to the StringBuilder + result.append(cbuf.subSequence(start, start + (i - start) - 1)); + } + // skip the delimiter character + start = i + 1; + + // get the resulting line + String tmp = result.toString(); + + // clear the StringBuilder + result.setLength(0); + + // clear the delimiter seen flag + seenReturn = false; + + return tmp; + } + else + { + // clear the delimiter seen flag + seenReturn = false; + } + } + if (end >= start) + { + // we've hit the end of the buffer, add the data to the + // StringBuilder and return null so as to get + // the next part of the line + result.append(cbuf.subSequence(start, start + (end - start))).toString(); + start = 0; + end = 0; + } + return null; + } + +} diff --git a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerFactory.java b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerFactory.java new file mode 100644 index 000000000..130a2baec --- /dev/null +++ b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerFactory.java @@ -0,0 +1,72 @@ +package org.asteriskjava.util.internal.streamreader; + +import java.io.IOException; +import java.util.NoSuchElementException; +import java.util.Scanner; +import java.util.regex.Pattern; + +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class FastScannerFactory +{ + private static final Log logger = LogFactory.getLog(FastScannerFactory.class); + + private static volatile boolean useLegacyScanner = false; + + public static FastScanner getReader(Readable reader, Pattern pattern) + { + if (!useLegacyScanner) + { + if (pattern.pattern().equals("\r\n")) + { + return new FastScannerCrNl(reader); + } + if (pattern.pattern().equals("\n")) + { + return new FastScannerNl(reader); + } + } + + // fall back to legacy Scanner + + logger.warn("Using legacy scanner"); + Scanner scanner = new Scanner(reader); + scanner.useDelimiter(pattern); + + return getWrappedScanner(scanner); + + } + + public static void useLegacyScanner(boolean b) + { + useLegacyScanner = b; + } + + private static FastScanner getWrappedScanner(final Scanner scanner) + { + return new FastScanner() + { + + @Override + public String next() throws IOException + { + try + { + return scanner.next(); + } + catch (NoSuchElementException e) + { + return null; + } + } + + @Override + public void close() + { + scanner.close(); + } + + }; + } +} diff --git a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java new file mode 100644 index 000000000..fab787e00 --- /dev/null +++ b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java @@ -0,0 +1,199 @@ + +package org.asteriskjava.util.internal.streamreader; + +import java.io.BufferedWriter; +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; +import java.util.concurrent.atomic.AtomicReference; + +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class FastScannerNl implements FastScanner +{ + private static final Log logger = LogFactory.getLog(FastScannerNl.class); + + private static final int BUFFER_SIZE = 8192; + + private AtomicReference readableReference = new AtomicReference<>(); + protected char nlChar = '\n'; + protected StringBuilder result = new StringBuilder(80); + protected CharBuffer cbuf = CharBuffer.allocate(BUFFER_SIZE); + protected int end = 0; + protected int start = 0; + private boolean closed = false; + protected final Object sync = new Object(); + + private boolean isFirst = true; + + File logfile; + + private BufferedWriter writer; + + public FastScannerNl(Readable reader) + { + this.readableReference.set(reader); + + // createFileWriter(); + + } + + public String next() throws IOException + { + int bytes = 0; + + // check for a line in the buffer + String line = getLine(false); + if (line == null) + { + // doing this instead of a synchronized block to avoid a possible + // deadlock between calling readable.read() and a call to close() on + // another thread, which it appears that Asterisk-Java permits + // and/or does + Readable readable = readableReference.get(); + + // read from the stream to the buffer + while (readable != null && (bytes = readable.read(cbuf)) > -1) + { + // writeToFile(bytes); + + // set buffer position to 0 + cbuf.position(0); + + end = bytes; + + // try to get a line from the buffer + line = getLine(bytes >= 0); + + if (line != null) + { + if (isFirst && line.length() == 0) + { + // if the first character of the stream is the line + // terminator, try again + line = getLine(bytes >= 0); + } + break; + } + } + + } + // clear the first line flag + isFirst = false; + if (line == null) + + { + // the line is empty, get the contents from the StringBuilder if any + String tmp = result.toString(); + result.setLength(0); + + // if the reader is closed and there is no output + if (readableReference.get() == null && tmp.length() == 0) + { + return null; + } + + // if at the end of the inputStream and there is no output + if (bytes == -1 && tmp.length() == 0) + { + return null; + } + return tmp; + } + return line; + + } + + protected String getLine(boolean endOfLine) + { + // iterate the buffer, looking for the end character + for (int i = start; i < end; i++) + { + if (cbuf.get(i) == nlChar) + { + if (i > start) + { + // add the buffer contents up to i to the output buffer + result.append(cbuf.subSequence(start, start + (i - start))); + } + // skip the delimiter + start = i + 1; + + // get the output + String tmp = result.toString(); + + // reset the StringBuilder to 0 to avoid re-allocating memory + result.setLength(0); + return tmp; + + } + } + if (end >= start) + { + // we've hit the end of the buffer, copy the contents to the + // StringBuilder, then return null so we'll loop again and get the + // next part + result.append(cbuf.subSequence(start, start + (end - start))).toString(); + start = 0; + end = 0; + } + return null; + } + + public void close() + { + synchronized (sync) + { + if (closed) + return; + if (readableReference.get() instanceof Closeable) + { + try + { + ((Closeable) readableReference.get()).close(); + // closeFileWriter(); + } + catch (IOException ioe) + { + logger.error(ioe, ioe); + } + } + readableReference.set(null); + closed = true; + } + } + + @SuppressWarnings("unused") + private void createFileWriter() + { + try + { + logfile = File.createTempFile(this.getClass().getSimpleName(), "txt"); + writer = Files.newBufferedWriter(logfile.toPath(), Charset.defaultCharset(), StandardOpenOption.APPEND); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + @SuppressWarnings("unused") + private void writeToFile(int bytes) throws IOException + { + String lines = new StringBuffer().append(cbuf, 0, bytes).toString(); + writer.append(lines, 0, bytes); + } + + @SuppressWarnings("unused") + private void closeFileWriter() throws IOException + { + writer.flush(); + writer.close(); + } + +} diff --git a/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerDeterministicTest.java b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerDeterministicTest.java new file mode 100644 index 000000000..664c3df56 --- /dev/null +++ b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerDeterministicTest.java @@ -0,0 +1,98 @@ +package org.asteriskjava.util.internal.streamreader; + +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.NoSuchElementException; +import java.util.regex.Pattern; + +import org.asteriskjava.util.internal.SocketConnectionFacadeImpl; +import org.junit.Test; + +public class FastScannerDeterministicTest +{ + + @Test + public void testCrNlScanner() throws Exception + { + testScanner(10000, SocketConnectionFacadeImpl.NL_PATTERN); + } + + @Test + public void testNlScanner() throws Exception + { + testScanner(10000, SocketConnectionFacadeImpl.CRNL_PATTERN); + } + + private void testScanner(int testLines, Pattern pattern) throws Exception + { + + final byte[] bytes = buildTestData(testLines, pattern).getBytes(); + + InputStream inputStream = new ByteArrayInputStream(bytes); + + InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); + + // factory will return the correct reader for the pattern + try (FastScanner scanner = FastScannerFactory.getReader(reader, pattern)) + { + System.out.println("\nTesting scanner class: " + scanner.getClass()); + int ctr = 0; + @SuppressWarnings("unused") + String t; + while ((t = scanner.next()) != null) + { + // System.out.println("L: " + t + " " + t.length()); + ctr++; + } + assertTrue("Counter expected : " + (testLines) + " got " + ctr, (testLines) == ctr); + + } + catch (NoSuchElementException e) + { + } + + System.out.println("Done\n"); + } + + @Test + public void testBR2Accuraccy3() throws Exception + { + + final byte[] bytes = Files.readAllBytes(new File("NlStreamReaderFast273316816601633219txt").toPath()); + + InputStream inputStream = new ByteArrayInputStream(bytes); + + InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); + + try (FastScannerNl scanner = new FastScannerNl(reader);) + { + String t; + while ((t = scanner.next()) != null) + { + System.out.println("L: " + t + " " + t.length()); + } + + } + catch (NoSuchElementException e) + { + } + } + + String buildTestData(int lines, Pattern terminator) + { + StringBuilder builder = new StringBuilder(lines * 30); + int ctr = 0; + while (ctr < lines) + { + ctr++; + builder.append("Hallo hello: one line with text! " + ctr + terminator.pattern()); + } + return builder.toString(); + } +} diff --git a/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerRandomTest.java b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerRandomTest.java new file mode 100644 index 000000000..6ef155c8e --- /dev/null +++ b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerRandomTest.java @@ -0,0 +1,143 @@ +package org.asteriskjava.util.internal.streamreader; + +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.regex.Pattern; + +import org.asteriskjava.util.internal.SocketConnectionFacadeImpl; +import org.junit.Test; + +import ch.qos.logback.core.encoder.ByteArrayUtil; + +public class FastScannerRandomTest +{ + @Test + public void compareOutputOfNlFastScannerToScanner() throws Exception + { + setupTest(SocketConnectionFacadeImpl.NL_PATTERN, "NL"); + + } + + @Test + public void compareOutputOfCrNlFastScannerToScanner() throws Exception + { + setupTest(SocketConnectionFacadeImpl.CRNL_PATTERN, "CR NL"); + + } + + void setupTest(final Pattern pattern, String caption) throws InterruptedException + { + + final AtomicInteger ctr = new AtomicInteger(); + + int tests = 50; + + for (int i = 0; i < tests; i++) + { + + try + { + String testData = generateTestData(1_000_000); + compare(testData, pattern); + System.out.println(caption + " Completed " + (ctr.incrementAndGet()) * 1 + "MB"); + } + catch (Exception e) + { + e.printStackTrace(); + fail(); + } + + } + + } + + boolean compare(String testData, Pattern pattern) throws IOException + { + + InputStream inputStream1 = new ByteArrayInputStream(testData.getBytes()); + InputStreamReader reader1 = new InputStreamReader(inputStream1, StandardCharsets.UTF_8); + + InputStream inputStream2 = new ByteArrayInputStream(testData.getBytes()); + InputStreamReader reader2 = new InputStreamReader(inputStream2, StandardCharsets.UTF_8); + + FastScanner fast = FastScannerFactory.getReader(reader2, pattern); + + String scannerResult = ""; + String fastResult = ""; + + int ctr = 0; + Scanner scanner = new Scanner(reader1); + + scanner.useDelimiter(pattern); + + try + { + while ((scannerResult = scanner.next()) != null) + { + ctr++; + fastResult = fast.next(); + + if (!fastResult.equals(scannerResult)) + { + + System.out.println("Expected " + ByteArrayUtil.toHexString(scannerResult.getBytes())); + System.out.println("Got " + ByteArrayUtil.toHexString(fastResult.getBytes())); + System.out.println("Error " + ctr); + System.out.println(""); + + throw new RuntimeException("Mismatched output"); + } + } + } + catch (NoSuchElementException e) + { + if (fast.next() != null) + { + throw new RuntimeException("Expected null, not something else"); + } + // Scanner normally throws this exception at the end of the stream + } + finally + { + scanner.close(); + fast.close(); + } + return false; + } + + public static String generateTestData(int byteSize) + { + Random rand = new Random(); + String bodyData = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(),.<>[] {};':\""; + bodyData += bodyData.toUpperCase(); + + String[] terminators = new String[]{"\n", "\r", "\r\n", "\n\r"}; + + StringBuilder builder = new StringBuilder(byteSize * 2); + for (int i = 0; i < byteSize; i++) + { + if (Math.random() * 100 > 98) + { + // 2 % chance of a line ending + builder.append(terminators[rand.nextInt(terminators.length)]); + } + else + { + int position = rand.nextInt(bodyData.length()); + builder.append(bodyData.substring(position, position + 1)); + } + } + + return builder.toString(); + + } +} diff --git a/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTest.java b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTest.java new file mode 100644 index 000000000..598ca064b --- /dev/null +++ b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTest.java @@ -0,0 +1,105 @@ +package org.asteriskjava.util.internal.streamreader; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.NoSuchElementException; +import java.util.Scanner; +import java.util.regex.Pattern; + +import org.asteriskjava.util.internal.SocketConnectionFacadeImpl; +import org.junit.Test; + +public class FastScannerSpeedTest +{ + @Test + public void testScannerSpeed() throws Exception + { + final byte[] bytes = FastScannerRandomTest.generateTestData(10_000_000).getBytes(); + + for (int i = 10; i-- > 0;) + { + System.out.print("Scanner " + i + ":\t"); + + InputStream inputStream = new ByteArrayInputStream(bytes); + + InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); + + long start = System.currentTimeMillis(); + int ctr = 0; + try (Scanner scanner = new Scanner(reader);) + { + + scanner.useDelimiter(Pattern.compile("\r\n")); + + @SuppressWarnings("unused") + String t; + while ((t = scanner.next()) != null) + { + // System.out.println(t); + ctr++; + } + System.out.print(ctr + "\t"); + } + catch (NoSuchElementException e) + { + System.out.print(ctr + "\t"); + } + System.out.println((System.currentTimeMillis() - start) + " ms"); + } + } + + @Test + public void test1() throws Exception + { + System.out.println("\nTesting fast CrNlStream"); + fastScannerSpeedTest(SocketConnectionFacadeImpl.CRNL_PATTERN); + } + + @Test + public void test2() throws Exception + { + /* + * the random test data generates quite a lot of /n which means we will + * get a LOT more lines when checking for /n + */ + System.out.println("\nTesting fast NlStream"); + fastScannerSpeedTest(SocketConnectionFacadeImpl.NL_PATTERN); + } + + private void fastScannerSpeedTest(Pattern pattern) throws Exception + { + final byte[] bytes = FastScannerRandomTest.generateTestData(10_000_000).getBytes(); + + for (int i = 10; i-- > 0;) + { + System.out.print("Fast " + i + ":\t"); + + InputStream inputStream = new ByteArrayInputStream(bytes); + + InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); + FastScanner scanner = FastScannerFactory.getReader(reader, pattern); + + long start = System.currentTimeMillis(); + try + { + int ctr = 0; + @SuppressWarnings("unused") + String t; + while ((t = scanner.next()) != null) + { + // System.out.println(t); + ctr++; + } + System.out.print(ctr + "\t"); + + } + catch (NoSuchElementException e) + { + } + System.out.println((System.currentTimeMillis() - start) + " ms"); + } + } + +} diff --git a/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTestOnSocket.java b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTestOnSocket.java new file mode 100644 index 000000000..d4844921e --- /dev/null +++ b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTestOnSocket.java @@ -0,0 +1,127 @@ +package org.asteriskjava.util.internal.streamreader; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.Socket; +import java.net.UnknownHostException; +import java.nio.charset.StandardCharsets; +import java.util.NoSuchElementException; +import java.util.Scanner; +import java.util.regex.Pattern; + +import org.asteriskjava.util.internal.SocketConnectionFacadeImpl; +import org.junit.Test; + +public class FastScannerSpeedTestOnSocket +{ + + @Test + public void testScannerSpeed() throws Exception + { + try + { + for (int i = 10; i-- > 0;) + { + + InputStreamReader reader = getReader(); + System.out.print("Scanner " + i + ":\t"); + + long start = System.currentTimeMillis(); + int ctr = 0; + try (Scanner scanner = new Scanner(reader);) + { + + scanner.useDelimiter(Pattern.compile("\r\n")); + + @SuppressWarnings("unused") + String t; + while ((t = scanner.next()) != null) + { + // System.out.println(t); + ctr++; + } + System.out.print(ctr + "\t"); + } + catch (NoSuchElementException e) + { + System.out.print(ctr + "\t"); + } + System.out.println((System.currentTimeMillis() - start) + " ms"); + } + } + catch (Exception e) + { + System.out.println( + "If you want to run FastScannerSpeedTestOnSocket, you'll need to run FastScannerTestSocketSource first"); + } + } + + private InputStreamReader getReader() throws UnknownHostException, IOException, InterruptedException + { + + Socket echoSocket = new Socket("127.0.0.1", FastScannerTestSocketSource.portNumber); + + InputStream inputStream = echoSocket.getInputStream(); + + InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); + return reader; + } + + @Test + public void test1() throws Exception + { + System.out.println("\nTesting fast CrNlStream"); + fastScannerSpeedTest(SocketConnectionFacadeImpl.CRNL_PATTERN); + } + + @Test + public void test2() throws Exception + { + /* + * the random test data generates quite a lot of /n which means we will + * get a LOT more lines when checking for /n + */ + System.out.println("\nTesting fast NlStream"); + fastScannerSpeedTest(SocketConnectionFacadeImpl.NL_PATTERN); + } + + private void fastScannerSpeedTest(Pattern pattern) throws Exception + { + try + { + for (int i = 10; i-- > 0;) + { + + InputStreamReader reader = getReader(); + System.out.print("Fast " + i + ":\t"); + FastScanner scanner = FastScannerFactory.getReader(reader, pattern); + + long start = System.currentTimeMillis(); + try + { + int ctr = 0; + @SuppressWarnings("unused") + String t; + while ((t = scanner.next()) != null) + { + // System.out.println(t); + ctr++; + } + System.out.print(ctr + "\t"); + + } + catch (NoSuchElementException e) + { + } + System.out.println((System.currentTimeMillis() - start) + " ms"); + } + } + catch (Exception e) + { + System.out.println( + "If you want to run FastScannerSpeedTestOnSocket, you'll need to run FastScannerTestSocketSource first"); + } + } + +} diff --git a/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerTestSocketSource.java b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerTestSocketSource.java new file mode 100644 index 000000000..f14a9e055 --- /dev/null +++ b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerTestSocketSource.java @@ -0,0 +1,34 @@ +package org.asteriskjava.util.internal.streamreader; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + +public class FastScannerTestSocketSource +{ + + final static byte[] bytes = FastScannerRandomTest.generateTestData(100_000_000).getBytes(); + public static int portNumber = 2048; + + public static void main(String[] args) throws IOException + { + + while (true) + { + + listen(); + } + + } + + static void listen() throws IOException + { + System.out.println("Waiting for connect on " + portNumber); + + try (ServerSocket serverSocket = new ServerSocket(portNumber); Socket clientSocket = serverSocket.accept();) + { + clientSocket.getOutputStream().write(bytes); + } + } + +} From 0286714e933d1dc47d8357e4e8486270a80be496 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 4 Jul 2018 16:58:49 +1000 Subject: [PATCH 187/802] reduce logging levels --- .../java/org/asteriskjava/pbx/agi/ActivityAgi.java | 2 +- .../pbx/internal/activity/DialToAgiActivityImpl.java | 11 +++++++++-- .../pbx/internal/managerAPI/OriginateBaseClass.java | 6 +++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index acab6d8b4..1b614905b 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -33,7 +33,7 @@ public void service() throws AgiException } if (channelProxy == null) { - logger.warn("'proxyId' var not set or proxy doesn't exist anymore, trying to match the channel name... " + logger.info("'proxyId' var not set or proxy doesn't exist anymore, trying to match the channel name... " + channelName); channelProxy = pbx.internalRegisterChannel(channel.getName(), channel.getUniqueId()); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index 911115448..77084901b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -131,7 +131,7 @@ private void hangup() if (this.originatingChannel != null) { - logger.warn("Hanging up"); + logger.info("Hanging up"); pbx.hangup(this.originatingChannel); } } @@ -235,7 +235,14 @@ public void onManagerEvent(ManagerEvent event) public void abort() { - originator.abort(); + if (originator != null) + { + originator.abort(); + } + else + { + logger.error("Call to abort, but it doesn't look like the Dial had started yet"); + } } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 62d613312..dd93a6299 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -223,7 +223,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has { try { - logger.warn("Hanging up"); + logger.info("Hanging up"); pbx.hangup(this.newChannel); } catch (IllegalArgumentException | IllegalStateException | PBXException e) @@ -296,7 +296,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) if ((this.newChannel != null) && (hangupChannel.isSame(this.newChannel))) { this.originateSuccess = false; - OriginateBaseClass.logger.error("Dest channel " + this.newChannel + " hungup after answer"); //$NON-NLS-1$//$NON-NLS-2$ + OriginateBaseClass.logger.warn("Dest channel " + this.newChannel + " hungup after answer"); //$NON-NLS-1$//$NON-NLS-2$ originateLatch.countDown(); } if ((this.monitorChannel1 != null) && (hangupChannel.isSame(this.monitorChannel1))) @@ -499,8 +499,8 @@ private void checkBridge(int ctr, Channel channel) originateLatch.countDown(); } } + logger.debug("Id is " + __originateID); } - logger.info("Id is " + __originateID); break; } Thread.sleep(100); From dc4749d846f9c59cad1fb145120407e8b94fe03a Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 9 Jul 2018 11:29:51 +1000 Subject: [PATCH 188/802] Stop DialLocalToAgiActivity from blocking the event queue --- .../org/asteriskjava/pbx/agi/ActivityAgi.java | 49 ++++- .../pbx/agi/ActivityArrivalListener.java | 10 + .../wrap/actions/OriginateAction.java | 201 +++++++++--------- .../internal/core/DialLocalToAgiActivity.java | 133 +++--------- .../org/asteriskjava/util/AstUtilTest.java | 11 + 5 files changed, 206 insertions(+), 198 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/agi/ActivityArrivalListener.java diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index f9a960d11..c2ddf7198 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -1,5 +1,10 @@ package org.asteriskjava.pbx.agi; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; import org.asteriskjava.pbx.AgiChannelActivityAction; @@ -8,6 +13,7 @@ import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.agi.config.ServiceAgiScriptImpl; +import org.asteriskjava.pbx.asterisk.wrap.actions.OriginateAction; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -15,7 +21,38 @@ public abstract class ActivityAgi extends ServiceAgiScriptImpl { - private final Log logger = LogFactory.getLog(this.getClass()); + public static final String ARRIVAL_KEY = "ActivityAgiArrivalKey"; + + private final static Log logger = LogFactory.getLog(ActivityAgi.class); + + private static final Map arrivalListeners = new ConcurrentHashMap<>(); + + public static AutoCloseable addArrivalListener(OriginateAction originate, ActivityArrivalListener listener) + { + + final String key = UUID.randomUUID().toString(); + arrivalListeners.put(key, listener); + if (arrivalListeners.size() > 100) + { + // pick one at random to remove + ActivityArrivalListener leaked = arrivalListeners.remove(arrivalListeners.keySet().iterator().next()); + logger.error("Arrival Listeners are leaking" + leaked.getClass().getCanonicalName()); + } + + Map vars = new HashMap<>(); + vars.put("_" + ARRIVAL_KEY, key); + originate.setVariables(vars); + return new AutoCloseable() + { + + @Override + public void close() throws Exception + { + arrivalListeners.remove(key); + + } + }; + } @Override public void service() throws AgiException @@ -63,6 +100,16 @@ public void channelHangup(Channel channel, Integer cause, String causeText) action = new AgiChannelActivityHold(); } + String arrivalKey = channel.getVariable(ARRIVAL_KEY); + if (arrivalKey != null && arrivalKey.length() > 0) + { + ActivityArrivalListener listener = arrivalListeners.get(arrivalKey); + if (listener != null) + { + listener.channelArrived(channelProxy); + } + } + boolean isAlive = true; RateLimiter rateLimiter = new RateLimiter(2); while (!action.isDisconnect() && isAlive) diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityArrivalListener.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityArrivalListener.java new file mode 100644 index 000000000..d475f0e41 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityArrivalListener.java @@ -0,0 +1,10 @@ +package org.asteriskjava.pbx.agi; + +import org.asteriskjava.pbx.Channel; + +public interface ActivityArrivalListener +{ + + void channelArrived(Channel channel); + +} diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java index 50bcef2a8..4f54b84a0 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java @@ -10,133 +10,138 @@ public class OriginateAction extends AbstractManagerAction { - /** - * Asterisk uses the term channel but it actually appears to be an endpoint - * or a channel. Hence we support both. - * - * Either of the following may be set but NOT BOTH. - */ - private EndPoint _endPoint; - private Channel _channel; + /** + * Asterisk uses the term channel but it actually appears to be an endpoint + * or a channel. Hence we support both. Either of the following may be set + * but NOT BOTH. + */ + private EndPoint _endPoint; + private Channel _channel; - private String _option; + private String _option; - private String _context; + private String _context; - private EndPoint _extension; + private EndPoint _extension; - private int _priority; + private int _priority; - private int _callingPres; + private int _callingPres; - private CallerID _callerID; + private CallerID _callerID; - private Map _variables; + private Map _variables; - private Boolean _async; + private Boolean _async; - private long _timeout; + private long _timeout; - public OriginateAction() - { - } + public OriginateAction() + { + } - public String toString() - { - return "OriginateAction: endPoint/Channel=" + (this._endPoint == null ? this._channel : this._endPoint) + " context=" + this._context //$NON-NLS-1$ //$NON-NLS-2$ - + " extension=" + this._extension + " callerId=" + this._callerID; //$NON-NLS-1$ //$NON-NLS-2$ - } + public String toString() + { + return "OriginateAction: endPoint/Channel=" + (this._endPoint == null ? this._channel : this._endPoint) + " context=" //$NON-NLS-1$ //$NON-NLS-2$ + + this._context + " extension=" + this._extension + " callerId=" + this._callerID; //$NON-NLS-1$ //$NON-NLS-2$ + } - @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.OriginateAction action = new org.asteriskjava.manager.action.OriginateAction(); - action.setActionId(getActionId()); + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.OriginateAction action = new org.asteriskjava.manager.action.OriginateAction(); + action.setActionId(getActionId()); - // Was the channel or an end point passed. - String channel = (this._channel != null ? this._channel.getChannelName() : this._endPoint - .getFullyQualifiedName()); - if (this._option != null) - { - channel += this._option; - } - action.setChannel((channel)); - action.setContext(this._context); - action.setExten(this._extension.getFullyQualifiedName()); - action.setPriority(this._priority); - action.setCallingPres(this._callingPres); - action.setCallerId(((CallerIDImpl) this._callerID).formatted()); - action.setVariables(this._variables); - action.setAsync(this._async); - action.setTimeout(this._timeout); + // Was the channel or an end point passed. + String channel = (this._channel != null ? this._channel.getChannelName() : this._endPoint.getFullyQualifiedName()); + if (this._option != null) + { + channel += this._option; + } + action.setChannel((channel)); + action.setContext(this._context); + action.setExten(this._extension.getFullyQualifiedName()); + action.setPriority(this._priority); + action.setCallingPres(this._callingPres); + action.setCallerId(((CallerIDImpl) this._callerID).formatted()); + action.setVariables(this._variables); + action.setAsync(this._async); + action.setTimeout(this._timeout); - return action; - } + return action; + } - public void setEndPoint(final EndPoint endPoint) - { - this._endPoint = endPoint; - this._channel = null; - } + public void setEndPoint(final EndPoint endPoint) + { + this._endPoint = endPoint; + this._channel = null; + } - public void setChannel(Channel channel) - { - this._channel = channel; - this._endPoint = null; + public void setChannel(Channel channel) + { + this._channel = channel; + this._endPoint = null; - } + } - public void setOption(final String option) - { - this._option = option; + public void setOption(final String option) + { + this._option = option; - } + } - public void setContext(final String context) - { - this._context = context; + public void setContext(final String context) + { + this._context = context; - } + } - public void setExten(final EndPoint extension) - { - this._extension = extension; + public void setExten(final EndPoint extension) + { + this._extension = extension; - } + } - public void setPriority(final int priority) - { - this._priority = priority; + public void setPriority(final int priority) + { + this._priority = priority; - } + } - public void setCallingPres(final int callingPres) - { - this._callingPres = callingPres; + public void setCallingPres(final int callingPres) + { + this._callingPres = callingPres; - } + } - public void setCallerId(final CallerID callerID) - { - this._callerID = callerID; + public void setCallerId(final CallerID callerID) + { + this._callerID = callerID; - } + } - public void setVariables(final Map variables) - { - this._variables = variables; + public void setVariables(final Map variables) + { + if (_variables == null) + { + this._variables = variables; + } + else + { + this._variables.putAll(variables); + } - } - - public void setAsync(final boolean async) - { - this._async = async; - - } - - public void setTimeout(final long timeout) - { - this._timeout = timeout; - - } + } + + public void setAsync(final boolean async) + { + this._async = async; + + } + + public void setTimeout(final long timeout) + { + this._timeout = timeout; + + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java index f91ca550e..5787084d7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -1,15 +1,12 @@ package org.asteriskjava.pbx.internal.core; -import java.io.IOException; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.ActivityStatusEnum; @@ -17,23 +14,18 @@ import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.asterisk.wrap.actions.GetVarAction; +import org.asteriskjava.pbx.agi.ActivityAgi; +import org.asteriskjava.pbx.agi.ActivityArrivalListener; import org.asteriskjava.pbx.asterisk.wrap.actions.OriginateAction; -import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.OriginateResponseEvent; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; -import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; import org.asteriskjava.pbx.internal.managerAPI.OriginateBaseClass; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class DialLocalToAgiActivity extends EventListenerBaseClass implements Runnable, Activity +public class DialLocalToAgiActivity implements Runnable, Activity { private EndPoint from; @@ -50,7 +42,6 @@ public class DialLocalToAgiActivity extends EventListenerBaseClass implements Ru public DialLocalToAgiActivity(EndPoint from, CallerID fromCallerID, ActivityCallback callback, Map channelVarsToSet) { - super("Dial " + from + " to AGI", PBXFactory.getActivePBX()); this.from = from; this.fromCallerID = fromCallerID; this.callback = callback; @@ -91,22 +82,44 @@ public void run() originate.setVariables(myVars); - try + ActivityArrivalListener listener = new ActivityArrivalListener() { - this.startListener(); - pbx.sendAction(originate, 30000); - latch.await(30, TimeUnit.SECONDS); - callback.progress(this, ActivityStatusEnum.SUCCESS, ActivityStatusEnum.SUCCESS.getDefaultMessage()); + @Override + public void channelArrived(Channel channel) + { + channels.add(channel); + if (isSuccess()) + { + latch.countDown(); + } + } + }; + try (AutoCloseable closeable = ActivityAgi.addArrivalListener(originate, listener);) + { + ManagerResponse response = pbx.sendAction(originate, 5000); + if (response.getResponse().compareToIgnoreCase("Success") != 0) + { + callback.progress(this, ActivityStatusEnum.FAILURE, ActivityStatusEnum.FAILURE.getDefaultMessage()); + } + else + { + if (latch.await(5, TimeUnit.SECONDS)) + { + callback.progress(this, ActivityStatusEnum.SUCCESS, ActivityStatusEnum.SUCCESS.getDefaultMessage()); + } + else + { + callback.progress(this, ActivityStatusEnum.FAILURE, ActivityStatusEnum.FAILURE.getDefaultMessage()); + } + } } catch (Exception e) { logger.error(e, e); - } - finally - { - this.close(); + callback.progress(this, ActivityStatusEnum.FAILURE, ActivityStatusEnum.FAILURE.getDefaultMessage()); + } } @@ -132,93 +145,15 @@ public void abort(final String reason) } - @Override - synchronized public void onManagerEvent(final ManagerEvent event) - { - if (event instanceof NewChannelEvent) - { - final NewChannelEvent newState = (NewChannelEvent) event; - final Channel channel = newState.getChannel(); - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); - - ManagerResponse response; - try - { - if (channel.isLocal()) - { - int wait = 5; - while (wait > 0) - { - wait--; - response = pbx.sendAction(var, 500); - String channelsOriginateId = response.getAttribute("value"); - if (originateId.equalsIgnoreCase(channelsOriginateId)) - { - logger.info("Found the local channel " + channel); - channels.add(channel); - wait = 0; - if (channels.size() == 2) - { - latch.countDown(); - } - } - else if (channelsOriginateId == null || channelsOriginateId.length() == 0) - - { - Thread.sleep(100); - logger.error("Waiting for variables on " + channel); - } - else - { - logger.error("Didn't match " + channel + " " + channelsOriginateId + "!=" + originateId); - - wait = 0; - } - } - } - } - catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) - { - logger.error(e, e); - } - catch (InterruptedException e) - { - logger.error(e, e); - } - - } - } - - @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); - - required.add(OriginateResponseEvent.class); - required.add(HangupEvent.class); - required.add(NewChannelEvent.class); - - return required; - } - - @Override - public ListenerPriority getPriority() - { - return ListenerPriority.NORMAL; - } - @Override public Throwable getLastException() { - // TODO Auto-generated method stub return null; } @Override public boolean isSuccess() { - // TODO Auto-generated method stub return channels.size() == 2; } diff --git a/src/test/java/org/asteriskjava/util/AstUtilTest.java b/src/test/java/org/asteriskjava/util/AstUtilTest.java index 381ae54f4..569a748f0 100644 --- a/src/test/java/org/asteriskjava/util/AstUtilTest.java +++ b/src/test/java/org/asteriskjava/util/AstUtilTest.java @@ -77,4 +77,15 @@ public void testIsNullForIpAddressInPeerEntryEvent() { assertTrue("\"-none-\" must be considered null", AstUtil.isNull("-none-")); } + + @Test + public void testIsEqual() + { + assertTrue(AstUtil.isEqual(null, null)); + assertTrue(AstUtil.isEqual("", "")); + assertFalse(AstUtil.isEqual(null, "")); + assertFalse(AstUtil.isEqual("", null)); + assertFalse(AstUtil.isEqual("", "1")); + + } } From 012b6772cd492bebdabca4197b5b26dd6dd1307e Mon Sep 17 00:00:00 2001 From: "Jonathan R. Rose" Date: Mon, 9 Jul 2018 14:23:29 -0500 Subject: [PATCH 189/802] Use ParkingSpace to set parkedAt on channel Use ParkingSpace to set parkedAt on channel instead of 'Exten'. Falls back to Exten if ParkingSpace is null for some reason (most likely because we are on an older version of Asterisk). Also, changes setParkedAt to include a parkinglot name. This can be retrieved from the Asterisk channel with getParkingLot(). Between getParkedAt() and getParkingLot() you can get all the arguments needed to use the ParkedCall dialplan application on any parked call. --- .../org/asteriskjava/live/AsteriskChannel.java | 9 +++++++++ .../live/internal/AsteriskChannelImpl.java | 15 ++++++++++++++- .../live/internal/ChannelManager.java | 16 +++++++--------- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/asteriskjava/live/AsteriskChannel.java b/src/main/java/org/asteriskjava/live/AsteriskChannel.java index a7fee808a..124017e8a 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskChannel.java +++ b/src/main/java/org/asteriskjava/live/AsteriskChannel.java @@ -40,6 +40,7 @@ *

  • meetMeUser *
  • queueEntry *
  • parkedAt + *
  • parkingLot *
  • dtmfReceived *
  • dtmfSent * @@ -61,6 +62,7 @@ public interface AsteriskChannel extends LiveObject String PROPERTY_MEET_ME_USER = "meetMeUser"; String PROPERTY_QUEUE_ENTRY = "queueEntry"; String PROPERTY_PARKED_AT = "parkedAt"; + String PROPERTY_PARKING_LOT = "parkingLot"; String PROPERTY_DTMF_RECEIVED = "dtmfReceived"; String PROPERTY_DTMF_SENT = "dtmfSent"; String PROPERTY_MONITORED = "monitored"; @@ -287,6 +289,13 @@ public interface AsteriskChannel extends LiveObject */ Extension getParkedAt(); + /** + * Return the name of the parkinglot where the channel is currently parked. + * + * @return the name of the parkinglot used to park, null if not currently parked. + */ + String getParkingLot(); + /** * Returns the channel variables as received by * {@link org.asteriskjava.manager.event.VarSetEvent VarSetEvents}.

    diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java index 375d30d91..770d4001a 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java @@ -127,6 +127,11 @@ class AsteriskChannelImpl extends AbstractLiveObject implements AsteriskChannel * otherwise. */ private Extension parkedAt; + /** + * Parkinglot where the call is parked if it is parked, null + * otherwise. + */ + private String parkingLot; /** * Last dtmf digit recieved on this channel if any, null * otherwise. @@ -917,12 +922,20 @@ public Extension getParkedAt() return parkedAt; } - void setParkedAt(Extension parkedAt) + public String getParkingLot() + { + return this.parkingLot; + } + + void setParkedAt(Extension parkedAt, String parkingLot) { final Extension oldParkedAt = this.parkedAt; + final String oldParkingLot = this.parkingLot; this.parkedAt = parkedAt; + this.parkingLot = parkingLot; firePropertyChange(PROPERTY_PARKED_AT, oldParkedAt, parkedAt); + firePropertyChange(PROPERTY_PARKING_LOT, oldParkingLot, parkingLot); } void updateVariable(String name, String value) diff --git a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java index 9ee0c2136..709263f1e 100644 --- a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java +++ b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java @@ -821,6 +821,7 @@ private String getTraceId(AsteriskChannel channel) void handleParkedCallEvent(ParkedCallEvent event) { + logger.info("Trace - ChannelManager.java - handleParkedCallEvent: " + event); // Only bristuffed versions: AsteriskChannelImpl channel = // getChannelImplById(event.getUniqueId()); AsteriskChannelImpl channel = getChannelImplByNameAndActive(event.getParkeeChannel()); @@ -833,12 +834,9 @@ void handleParkedCallEvent(ParkedCallEvent event) synchronized (channel) { - // todo The context should be "parkedcalls" or whatever has been - // configured in features.conf - // unfortunately we don't get the context in the ParkedCallEvent so - // for now we'll set it to null. - Extension ext = new Extension(null, event.getExten(), 1); - channel.setParkedAt(ext); + Extension ext = new Extension(null, (event.getParkingSpace() != null) ? event.getParkingSpace() : event.getExten(), 1); + String parkinglot = event.getParkingLot(); + channel.setParkedAt(ext, parkinglot); logger.info("Channel " + channel.getName() + " is parked at " + channel.getParkedAt().getExtension()); } } @@ -865,7 +863,7 @@ void handleParkedCallGiveUpEvent(ParkedCallGiveUpEvent event) synchronized (channel) { - channel.setParkedAt(null); + channel.setParkedAt(null, null); } logger.info("Channel " + channel.getName() + " is unparked (GiveUp) from " + wasParkedAt.getExtension()); } @@ -892,7 +890,7 @@ void handleParkedCallTimeOutEvent(ParkedCallTimeOutEvent event) synchronized (channel) { - channel.setParkedAt(null); + channel.setParkedAt(null, null); } logger.info("Channel " + channel.getName() + " is unparked (Timeout) from " + wasParkedAt.getExtension()); } @@ -919,7 +917,7 @@ void handleUnparkedCallEvent(UnparkedCallEvent event) synchronized (channel) { - channel.setParkedAt(null); + channel.setParkedAt(null, null); } logger.info("Channel " + channel.getName() + " is unparked (moved away) from " + wasParkedAt.getExtension()); } From bb695de250b67cdcda98f5eb737f836db7b29062 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 12 Jul 2018 11:01:21 +1000 Subject: [PATCH 190/802] release 2.0.3 --- README.md | 22 ++++++++++++++++++++++ pom.xml | 35 +++-------------------------------- 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 98c564643..b048bbf07 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,28 @@ Asterisk-Java is available from [here](https://github.com/asterisk-java/asterisk Maven Dependency ---------------- +Asterisk-Java 2.0.3 + + + + asterisk-java-mvn-repo + https://raw.githubusercontent.com/asterisk-java/asterisk-java/mvn-repo + + true + + + true + + + + + + org.asteriskjava + asterisk-java + 2.0.3 + + + Asterisk-Java 2.0 diff --git a/pom.xml b/pom.xml index 835f8de02..6431933b6 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 2.0.3-SNAPSHOT + 2.0.3 The free Java library for Asterisk PBX integration. 2004 @@ -70,33 +70,15 @@ https://github.com/asterisk-java/asterisk-java - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2 + internal + file://${project.build.directory}/mvn-repo GitHub https://github.com/asterisk-java/asterisk-java/issues - - - Asterisk-Java User List - http://lists.sourceforge.net/mailman/listinfo/asterisk-java-users - http://lists.sourceforge.net/mailman/listinfo/asterisk-java-users - http://sourceforge.net/mailarchive/forum.php?forum=asterisk-java-users - - - Asterisk-Java Developer List - http://lists.sourceforge.net/mailman/listinfo/asterisk-java-devel - http://lists.sourceforge.net/mailman/listinfo/asterisk-java-devel - http://sourceforge.net/mailarchive/forum.php?forum=asterisk-java-devel - - UTF-8 @@ -266,17 +248,6 @@ - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.5 - true - - ossrh - https://oss.sonatype.org/ - false - - From 87e268aa76c06fe041c7c15e12d9f0d3a6c92361 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 12 Jul 2018 11:07:05 +1000 Subject: [PATCH 191/802] new version number 2.0.4-SNAP-SHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6431933b6..dd224e463 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 2.0.3 + 2.0.4-SNAP-SHOT The free Java library for Asterisk PBX integration. 2004 From 81cc71ce3600dd1a7dc18d1abb9198bbd3a162ca Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 24 Jul 2018 14:09:26 +1000 Subject: [PATCH 192/802] Refactor Asterisk Version determination --- .../org/asteriskjava/AsteriskVersion.java | 80 ++++++-- .../internal/ManagerConnectionImpl.java | 192 +++++++----------- .../org/asteriskjava/AsteriskVersionTest.java | 67 ++++++ .../fastagi/SimpleAgiRequest.java | 26 ++- 4 files changed, 221 insertions(+), 144 deletions(-) create mode 100644 src/test/java/org/asteriskjava/AsteriskVersionTest.java diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 418dc0540..2f36006d2 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -17,6 +17,7 @@ package org.asteriskjava; import java.io.Serializable; +import java.util.regex.Pattern; /** * Represents the version of an Asterisk server. @@ -27,100 +28,129 @@ */ public class AsteriskVersion implements Comparable, Serializable { + private static final String VERSION_PATTERN_15 = "^\\s*Asterisk (GIT-)?15[-. ].*"; + private static final String VERSION_PATTERN_14 = "^\\s*Asterisk (GIT-)?14[-. ].*"; + private static final String VERSION_PATTERN_13 = "^\\s*Asterisk ((SVN-branch|GIT)-)?13[-. ].*"; + private static final String VERSION_PATTERN_12 = "^\\s*Asterisk ((SVN-branch|GIT)-)?12[-. ].*"; + private static final String VERSION_PATTERN_11 = "^\\s*Asterisk ((SVN-branch|GIT)-)?11[-. ].*"; + private static final String VERSION_PATTERN_10 = "^\\s*Asterisk ((SVN-branch|GIT)-)?10[-. ].*"; + private static final String VERSION_PATTERN_1_8 = "^\\s*Asterisk ((SVN-branch|GIT)-)?1\\.8[-. ].*"; + private static final String VERSION_PATTERN_1_6 = "^\\s*Asterisk ((SVN-branch|GIT)-)?1\\.6[-. ].*"; private final int version; private final String versionString; + private final Pattern patterns[]; + + private static final String VERSION_PATTERN_CERTIFIED_13 = "^\\s*Asterisk certified/((SVN-branch|GIT)-)?13[-. ].*"; + private static final String VERSION_PATTERN_CERTIFIED_11 = "^\\s*Asterisk certified/((SVN-branch|GIT)-)?11[-. ].*"; /** * Represents the Asterisk 1.0 series. */ - public static final AsteriskVersion ASTERISK_1_0 = new AsteriskVersion(100, "Asterisk 1.0"); + public static final AsteriskVersion ASTERISK_1_0 = new AsteriskVersion(100, "Asterisk 1.0", new String[]{}); /** * Represents the Asterisk 1.2 series. */ - public static final AsteriskVersion ASTERISK_1_2 = new AsteriskVersion(120, "Asterisk 1.2"); + public static final AsteriskVersion ASTERISK_1_2 = new AsteriskVersion(120, "Asterisk 1.2", new String[]{}); /** * Represents the Asterisk 1.4 series. * * @since 0.3 */ - public static final AsteriskVersion ASTERISK_1_4 = new AsteriskVersion(140, "Asterisk 1.4"); + public static final AsteriskVersion ASTERISK_1_4 = new AsteriskVersion(140, "Asterisk 1.4", new String[]{}); /** * Represents the Asterisk 1.6 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_1_6 = new AsteriskVersion(160, "Asterisk 1.6"); + public static final AsteriskVersion ASTERISK_1_6 = new AsteriskVersion(160, "Asterisk 1.6", VERSION_PATTERN_1_6); /** * Represents the Asterisk 1.8 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_1_8 = new AsteriskVersion(180, "Asterisk 1.8"); + public static final AsteriskVersion ASTERISK_1_8 = new AsteriskVersion(180, "Asterisk 1.8", VERSION_PATTERN_1_8); /** * Represents the Asterisk 10 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_10 = new AsteriskVersion(1000, "Asterisk 10"); + public static final AsteriskVersion ASTERISK_10 = new AsteriskVersion(1000, "Asterisk 10", VERSION_PATTERN_10); /** * Represents the Asterisk 11 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_11 = new AsteriskVersion(1100, "Asterisk 11"); + public static final AsteriskVersion ASTERISK_11 = new AsteriskVersion(1100, "Asterisk 11", + new String[]{VERSION_PATTERN_11, VERSION_PATTERN_CERTIFIED_11}); /** * Represents the Asterisk 12 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_12 = new AsteriskVersion(1200, "Asterisk 12"); + public static final AsteriskVersion ASTERISK_12 = new AsteriskVersion(1200, "Asterisk 12", VERSION_PATTERN_12); /** * Represents the Asterisk 13 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_13 = new AsteriskVersion(1300, "Asterisk 13"); + public static final AsteriskVersion ASTERISK_13 = new AsteriskVersion(1300, "Asterisk 13", + new String[]{VERSION_PATTERN_13, VERSION_PATTERN_CERTIFIED_13}); /** * Represents the Asterisk 14 series. * * @since 1.1.0 */ - public static final AsteriskVersion ASTERISK_14 = new AsteriskVersion(1400, "Asterisk 14"); + public static final AsteriskVersion ASTERISK_14 = new AsteriskVersion(1400, "Asterisk 14", VERSION_PATTERN_14); /** * Represents the Asterisk 15 series. * * @since 2.1.0 */ - public static final AsteriskVersion ASTERISK_15 = new AsteriskVersion(1500, "Asterisk 15"); + public static final AsteriskVersion ASTERISK_15 = new AsteriskVersion(1500, "Asterisk 15", VERSION_PATTERN_15); + + private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ASTERISK_15, ASTERISK_14, ASTERISK_13, + ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6}; /** * Serial version identifier. */ private static final long serialVersionUID = 1L; - private AsteriskVersion(int version, String versionString) + private AsteriskVersion(int version, String versionString, String pattern) + { + this(version, versionString, new String[]{pattern}); + } + + private AsteriskVersion(int version, String versionString, String patterns[]) { this.version = version; this.versionString = versionString; + + this.patterns = new Pattern[patterns.length]; + int i = 0; + for (String pattern : patterns) + { + this.patterns[i++] = Pattern.compile(pattern); + } } /** - * Returns true if this version is equal to or higher than - * the given version. + * Returns true if this version is equal to or higher than the + * given version. * * @param o the version to compare to - * @return true if this version is equal to or higher than - * the given version, false otherwise. + * @return true if this version is equal to or higher than the + * given version, false otherwise. */ public boolean isAtLeast(AsteriskVersion o) { @@ -160,4 +190,22 @@ public String toString() { return versionString; } + + public static AsteriskVersion getDetermineVersionFromString(String coreLine) + { + for (AsteriskVersion version : knownVersions) + { + for (Pattern pattern : version.patterns) + { + if (pattern.matcher(coreLine).matches()) + { + return version; + } + } + } + + // we just default to 1.4 - to further understand why, see + // ManagerConnectionImpl.determineVersion + return AsteriskVersion.ASTERISK_1_4; + } } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 875500214..c196f3a39 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -93,19 +93,6 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher private static final int MAX_VERSION_ATTEMPTS = 4; private static final Pattern SHOW_VERSION_PATTERN = Pattern.compile("^(core )?show version.*"); - private static final Pattern VERSION_PATTERN_1_6 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?1\\.6[-. ].*"); - private static final Pattern VERSION_PATTERN_1_8 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?1\\.8[-. ].*"); - private static final Pattern VERSION_PATTERN_10 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?10[-. ].*"); - private static final Pattern VERSION_PATTERN_11 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?11[-. ].*"); - private static final Pattern VERSION_PATTERN_CERTIFIED_11 = Pattern - .compile("^\\s*Asterisk certified/((SVN-branch|GIT)-)?11[-. ].*"); - private static final Pattern VERSION_PATTERN_12 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?12[-. ].*"); - private static final Pattern VERSION_PATTERN_13 = Pattern.compile("^\\s*Asterisk ((SVN-branch|GIT)-)?13[-. ].*"); - private static final Pattern VERSION_PATTERN_CERTIFIED_13 = Pattern - .compile("^\\s*Asterisk certified/((SVN-branch|GIT)-)?13[-. ].*"); - private static final Pattern VERSION_PATTERN_14 = Pattern.compile("^\\s*Asterisk (GIT-)?14[-. ].*"); - private static final Pattern VERSION_PATTERN_15 = Pattern.compile("^\\s*Asterisk (GIT-)?15[-. ].*"); - private static final AtomicLong idCounter = new AtomicLong(0); /** @@ -707,46 +694,7 @@ else if (line1 != null && line1.contains("No such command")) { final String coreLine = coreShowVersionResult.get(0); - if (VERSION_PATTERN_1_6.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_1_6; - } - else if (VERSION_PATTERN_1_8.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_1_8; - } - else if (VERSION_PATTERN_10.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_10; - } - else if (VERSION_PATTERN_11.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_11; - } - else if (VERSION_PATTERN_CERTIFIED_11.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_11; - } - else if (VERSION_PATTERN_12.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_12; - } - else if (VERSION_PATTERN_13.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_13; - } - else if (VERSION_PATTERN_CERTIFIED_13.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_13; - } - else if (VERSION_PATTERN_14.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_14; - } - else if (VERSION_PATTERN_15.matcher(coreLine).matches()) - { - return AsteriskVersion.ASTERISK_15; - } + return AsteriskVersion.getDetermineVersionFromString(coreLine); } } @@ -1316,39 +1264,41 @@ public void dispatchEvent(ManagerEvent event) { // When we receive get disconnected while we are connected start // a new reconnect thread and set the state to RECONNECTING. - synchronized (this) - { - if (state == CONNECTED) - { - state = RECONNECTING; - // close socket if still open and remove reference to - // readerThread - // After sending the DisconnectThread that thread will die - // anyway. - cleanup(); - Thread reconnectThread = new Thread(new Runnable() { - - public void run() { - reconnect(); - } - }); - reconnectThread.setName( - "Asterisk-Java ManagerConnection-" + id + "-Reconnect-" + reconnectThreadCounter.getAndIncrement()); - reconnectThread.setDaemon(true); - reconnectThread.start(); - // now the DisconnectEvent is dispatched to registered - // eventListeners - // (clients) and after that the ManagerReaderThread is gone. - // So effectively we replaced the reader thread by a - // ReconnectThread. - } - else - { - // when we receive a DisconnectEvent while not connected we - // ignore it and do not send it to clients - return; - } - } + synchronized (this) + { + if (state == CONNECTED) + { + state = RECONNECTING; + // close socket if still open and remove reference to + // readerThread + // After sending the DisconnectThread that thread will die + // anyway. + cleanup(); + Thread reconnectThread = new Thread(new Runnable() + { + + public void run() + { + reconnect(); + } + }); + reconnectThread.setName("Asterisk-Java ManagerConnection-" + id + "-Reconnect-" + + reconnectThreadCounter.getAndIncrement()); + reconnectThread.setDaemon(true); + reconnectThread.start(); + // now the DisconnectEvent is dispatched to registered + // eventListeners + // (clients) and after that the ManagerReaderThread is gone. + // So effectively we replaced the reader thread by a + // ReconnectThread. + } + else + { + // when we receive a DisconnectEvent while not connected we + // ignore it and do not send it to clients + return; + } + } } if (event instanceof ProtocolIdentifierReceivedEvent) { @@ -1483,40 +1433,42 @@ private void reconnect() try { - synchronized (this) - { - if (state != RECONNECTING) { - break; - } - connect(); - - try - { - doLogin(defaultResponseTimeout, eventMask); - logger.info("Successfully reconnected."); - // everything is ok again, so we leave - // when successful doLogin set the state to CONNECTED so no - // need to adjust it - break; - } - catch (AuthenticationFailedException e1) - { - if (keepAliveAfterAuthenticationFailure) - { - logger.error("Unable to log in after reconnect: " + e1.getMessage()); - } - else - { - logger.error("Unable to log in after reconnect: " + e1.getMessage() + ". Giving up."); - state = DISCONNECTED; - } - } - catch (TimeoutException e1) - { - // shouldn't happen - but happens! - logger.error("TimeoutException while trying to log in " + "after reconnect."); - } - } + synchronized (this) + { + if (state != RECONNECTING) + { + break; + } + connect(); + + try + { + doLogin(defaultResponseTimeout, eventMask); + logger.info("Successfully reconnected."); + // everything is ok again, so we leave + // when successful doLogin set the state to CONNECTED so + // no + // need to adjust it + break; + } + catch (AuthenticationFailedException e1) + { + if (keepAliveAfterAuthenticationFailure) + { + logger.error("Unable to log in after reconnect: " + e1.getMessage()); + } + else + { + logger.error("Unable to log in after reconnect: " + e1.getMessage() + ". Giving up."); + state = DISCONNECTED; + } + } + catch (TimeoutException e1) + { + // shouldn't happen - but happens! + logger.error("TimeoutException while trying to log in " + "after reconnect."); + } + } } catch (IOException e) { diff --git a/src/test/java/org/asteriskjava/AsteriskVersionTest.java b/src/test/java/org/asteriskjava/AsteriskVersionTest.java new file mode 100644 index 000000000..1c83f8c45 --- /dev/null +++ b/src/test/java/org/asteriskjava/AsteriskVersionTest.java @@ -0,0 +1,67 @@ +package org.asteriskjava; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class AsteriskVersionTest +{ + + @Test + public void test1_4() + { + // we just default to 1.4 - to further understand why, see + // ManagerConnectionImpl.determineVersion + assertTrue(AsteriskVersion.getDetermineVersionFromString("").equals(AsteriskVersion.ASTERISK_1_4)); + } + + @Test + public void test1_6() + { + assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 1.6.0").equals(AsteriskVersion.ASTERISK_1_6)); + } + + @Test + public void test1_8() + { + assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 1.8.0").equals(AsteriskVersion.ASTERISK_1_8)); + } + + @Test + public void test10() + { + assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 10.1.0").equals(AsteriskVersion.ASTERISK_10)); + } + + @Test + public void test11() + { + assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 11.1.0").equals(AsteriskVersion.ASTERISK_11)); + } + + @Test + public void test12() + { + assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 12.1.0").equals(AsteriskVersion.ASTERISK_12)); + } + + @Test + public void test13() + { + assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 13.1.0~dfsg-1.1ubuntu4.1") + .equals(AsteriskVersion.ASTERISK_13)); + } + + @Test + public void test14() + { + assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 14.1.0").equals(AsteriskVersion.ASTERISK_14)); + } + + @Test + public void test15() + { + assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 15.1.0").equals(AsteriskVersion.ASTERISK_15)); + } + +} diff --git a/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java b/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java index 2667479a6..fdf132eef 100644 --- a/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java +++ b/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java @@ -19,6 +19,8 @@ import java.net.InetAddress; import java.util.Map; +import org.asteriskjava.AsteriskVersion; + public class SimpleAgiRequest implements AgiRequest { InetAddress localAddress; @@ -26,17 +28,18 @@ public class SimpleAgiRequest implements AgiRequest InetAddress remoteAddress; int remotePort; private String script; + private AsteriskVersion asteriskVersion; public SimpleAgiRequest() { this.script = "hello.agi"; } - + public SimpleAgiRequest(String script) { this.script = script; } - + public Map getRequest() { throw new UnsupportedOperationException(); @@ -73,12 +76,13 @@ public String getLanguage() } /** - * Returns the Caller*ID number, for example "1234".

    - * Note: even with Asterisk 1.0 is contains only the numerical part - * of the Caller ID. + * Returns the Caller*ID number, for example "1234". + *

    + * 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" null is returned. + * @return the Caller*ID number, for example "1234", if no Caller*ID is set + * or it is "unknown" null is returned. * @deprecated as of 0.3, use {@link #getCallerIdNumber()} instead. */ public String getCallerId() @@ -210,4 +214,10 @@ public void setRemotePort(int remotePort) { this.remotePort = remotePort; } -} \ No newline at end of file + + @Override + public AsteriskVersion getAsteriskVersion() + { + return asteriskVersion; + } +} From 0aa4e691bda6bd6d93c06c0bc9e153afc2e22af2 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 24 Jul 2018 14:13:47 +1000 Subject: [PATCH 193/802] Make Asterisk Version available to AGI scripts --- src/main/java/org/asteriskjava/fastagi/AgiChannel.java | 3 +++ .../java/org/asteriskjava/fastagi/AgiOperations.java | 7 +++++++ src/main/java/org/asteriskjava/fastagi/AgiRequest.java | 4 ++++ .../asteriskjava/fastagi/command/AbstractAgiCommand.java | 8 ++++++++ .../org/asteriskjava/fastagi/command/AgiCommand.java | 4 ++++ .../asteriskjava/fastagi/internal/AgiChannelImpl.java | 9 +++++++++ .../asteriskjava/fastagi/internal/AgiRequestImpl.java | 9 ++++++++- .../fastagi/internal/AgiRequestImplTest.java | 3 +++ 8 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/fastagi/AgiChannel.java b/src/main/java/org/asteriskjava/fastagi/AgiChannel.java index 279e7b4a6..023dbdba3 100644 --- a/src/main/java/org/asteriskjava/fastagi/AgiChannel.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiChannel.java @@ -16,6 +16,7 @@ */ package org.asteriskjava.fastagi; +import org.asteriskjava.AsteriskVersion; import org.asteriskjava.fastagi.command.AgiCommand; import org.asteriskjava.fastagi.reply.AgiReply; @@ -879,4 +880,6 @@ char controlStreamFile(String file, String escapeDigits, int offset, String forw void queue(String queue) throws AgiException; + AsteriskVersion getAsteriskVersion(); + } diff --git a/src/main/java/org/asteriskjava/fastagi/AgiOperations.java b/src/main/java/org/asteriskjava/fastagi/AgiOperations.java index ea3846a11..25b450c63 100644 --- a/src/main/java/org/asteriskjava/fastagi/AgiOperations.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiOperations.java @@ -16,6 +16,7 @@ */ package org.asteriskjava.fastagi; +import org.asteriskjava.AsteriskVersion; import org.asteriskjava.fastagi.command.AgiCommand; import org.asteriskjava.fastagi.internal.AgiConnectionHandler; import org.asteriskjava.fastagi.reply.AgiReply; @@ -460,4 +461,10 @@ public void queue(String queue) throws AgiException getChannel().queue(queue); } + + @Override + public AsteriskVersion getAsteriskVersion() + { + return channel.getAsteriskVersion(); + } } diff --git a/src/main/java/org/asteriskjava/fastagi/AgiRequest.java b/src/main/java/org/asteriskjava/fastagi/AgiRequest.java index 45086a621..64115a54c 100644 --- a/src/main/java/org/asteriskjava/fastagi/AgiRequest.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiRequest.java @@ -19,6 +19,8 @@ import java.net.InetAddress; import java.util.Map; +import org.asteriskjava.AsteriskVersion; + /** * Provides client request information to an {@link org.asteriskjava.fastagi.AgiScript}.

    * This includes information about the channel the script is invoked on and @@ -294,4 +296,6 @@ public interface AgiRequest * @since 0.2 */ int getRemotePort(); + + AsteriskVersion getAsteriskVersion(); } diff --git a/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java b/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java index 949277a05..1f2324d49 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java @@ -18,6 +18,8 @@ import java.io.Serializable; +import org.asteriskjava.AsteriskVersion; + /** * Abstract base class that provides some convenience methods for * implementing AgiCommand classes. @@ -31,6 +33,7 @@ public abstract class AbstractAgiCommand implements Serializable, AgiCommand * Serial version identifier. */ private static final long serialVersionUID = 3257849874518456633L; + protected AsteriskVersion asteriskVersion; public abstract String buildCommand(); @@ -88,4 +91,9 @@ public String toString() return sb.toString(); } + + public void setAsteriskVersion(AsteriskVersion asteriskVersion) + { + this.asteriskVersion = asteriskVersion; + } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/AgiCommand.java b/src/main/java/org/asteriskjava/fastagi/command/AgiCommand.java index 4d77554af..556942fe6 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/AgiCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/AgiCommand.java @@ -16,6 +16,8 @@ */ package org.asteriskjava.fastagi.command; +import org.asteriskjava.AsteriskVersion; + /** * AgiCommand that can be sent to Asterisk via the Asterisk Gateway Interface.

    * This interface contains only one method that transforms the command to a @@ -33,4 +35,6 @@ public interface AgiCommand * @return a string suitable to be sent to asterisk. */ String buildCommand(); + + void setAsteriskVersion(AsteriskVersion asteriskVersion); } diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java index ba0171f83..053ad4520 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java @@ -16,6 +16,7 @@ */ package org.asteriskjava.fastagi.internal; +import org.asteriskjava.AsteriskVersion; import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; @@ -113,6 +114,9 @@ public AgiReply getLastReply() public synchronized AgiReply sendCommand(AgiCommand command) throws AgiException { + // make the Asterisk Version available to the AgiCommand, with out + // causing a major refactor + command.setAsteriskVersion(getAsteriskVersion()); agiWriter.sendCommand(command); lastReply = agiReader.readReply(); @@ -132,6 +136,11 @@ public synchronized AgiReply sendCommand(AgiCommand command) throws AgiException return lastReply; } + public AsteriskVersion getAsteriskVersion() + { + return request.getAsteriskVersion(); + } + public void answer() throws AgiException { sendCommand(new AnswerCommand()); diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java index 219ba70fc..be8e42730 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java @@ -29,6 +29,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.asteriskjava.AsteriskVersion; import org.asteriskjava.fastagi.AgiRequest; import org.asteriskjava.util.AstUtil; import org.asteriskjava.util.Log; @@ -187,6 +188,12 @@ public String getRequestURL() return request.get("request"); } + @Override + public AsteriskVersion getAsteriskVersion() + { + return AsteriskVersion.getDetermineVersionFromString("Asterisk " + request.get("version")); + } + /** * Returns the name of the channel. * @@ -627,7 +634,7 @@ void setRemotePort(int remotePort) @Override public String toString() { - StringBuilder sb; + StringBuilder sb; sb = new StringBuilder("AgiRequest["); sb.append("script='").append(getScript()).append("',"); diff --git a/src/test/java/org/asteriskjava/fastagi/internal/AgiRequestImplTest.java b/src/test/java/org/asteriskjava/fastagi/internal/AgiRequestImplTest.java index 4d62c8a7e..4c49d8e49 100644 --- a/src/test/java/org/asteriskjava/fastagi/internal/AgiRequestImplTest.java +++ b/src/test/java/org/asteriskjava/fastagi/internal/AgiRequestImplTest.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; +import org.asteriskjava.AsteriskVersion; import org.asteriskjava.fastagi.AgiRequest; import org.junit.Test; @@ -53,6 +54,7 @@ public void testBuildRequest() lines.add("agi_priority: 1"); lines.add("agi_enhanced: 0.0"); lines.add("agi_accountcode: "); + lines.add("agi_version: 13.1.0~dfsg-1.1ubuntu4.1"); request = new AgiRequestImpl(lines); @@ -72,6 +74,7 @@ public void testBuildRequest() assertEquals("incorrect priority", new Integer(1), request.getPriority()); assertEquals("incorrect enhanced", Boolean.FALSE, request.getEnhanced()); assertNull("incorrect accountCode must not be set", request.getAccountCode()); + assertEquals("incorret Asterisk Version Number", AsteriskVersion.ASTERISK_13, request.getAsteriskVersion()); } @Test From eab1f672d9645abf631c9dfaaf5f6c1f11f19106 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 24 Jul 2018 14:15:28 +1000 Subject: [PATCH 194/802] allow AGI bridge command to change it's syntax based on the Asterisk Version --- .../asteriskjava/fastagi/command/BridgeCommand.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java index 390b66db1..1083a828d 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java @@ -1,5 +1,7 @@ package org.asteriskjava.fastagi.command; +import org.asteriskjava.AsteriskVersion; + public class BridgeCommand extends AbstractAgiCommand { /** @@ -25,7 +27,14 @@ public String buildCommand() String command = "EXEC " + escapeAndQuote("bridge") + " " + escapeAndQuote(channel); if (options != null && options.length() > 0) { - command += " " + escapeAndQuote(options); + if (asteriskVersion.isAtLeast(AsteriskVersion.ASTERISK_13)) + { + command += "," + escapeAndQuote(options); + } + else + { + command += " " + escapeAndQuote(options); + } } return command; From 269040a334a089b19e053be66551c83ed178455f Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 24 Jul 2018 14:19:01 +1000 Subject: [PATCH 195/802] protect against possible NPE --- .../fastagi/command/AbstractAgiCommand.java | 20 ++++++++++++++++--- .../fastagi/command/BridgeCommand.java | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java b/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java index 1f2324d49..232ba2a5f 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java @@ -19,10 +19,12 @@ import java.io.Serializable; import org.asteriskjava.AsteriskVersion; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** - * Abstract base class that provides some convenience methods for - * implementing AgiCommand classes. + * Abstract base class that provides some convenience methods for implementing + * AgiCommand classes. * * @author srt * @version $Id$ @@ -33,7 +35,9 @@ public abstract class AbstractAgiCommand implements Serializable, AgiCommand * Serial version identifier. */ private static final long serialVersionUID = 3257849874518456633L; - protected AsteriskVersion asteriskVersion; + private AsteriskVersion asteriskVersion; + + private static final Log logger = LogFactory.getLog(AbstractAgiCommand.class); public abstract String buildCommand(); @@ -96,4 +100,14 @@ public void setAsteriskVersion(AsteriskVersion asteriskVersion) { this.asteriskVersion = asteriskVersion; } + + AsteriskVersion getAsteriskVersion() + { + if (asteriskVersion == null) + { + logger.warn("Asterisk Version isn't known, returning 1.4"); + return AsteriskVersion.ASTERISK_1_4; + } + return asteriskVersion; + } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java index 1083a828d..5bccbd731 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java @@ -27,7 +27,7 @@ public String buildCommand() String command = "EXEC " + escapeAndQuote("bridge") + " " + escapeAndQuote(channel); if (options != null && options.length() > 0) { - if (asteriskVersion.isAtLeast(AsteriskVersion.ASTERISK_13)) + if (getAsteriskVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) { command += "," + escapeAndQuote(options); } From f1ad840e57206c27b260c8200fd9d65c9123b453 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 24 Jul 2018 14:35:45 +1000 Subject: [PATCH 196/802] Add null check for state in UnitTest --- .../asteriskjava/fastagi/internal/AgiChannelImpl.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java index 053ad4520..3d0500f6a 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java @@ -74,6 +74,8 @@ import org.asteriskjava.fastagi.command.VerboseCommand; import org.asteriskjava.fastagi.command.WaitForDigitCommand; import org.asteriskjava.fastagi.reply.AgiReply; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * Default implementation of the AgiChannel interface. @@ -87,6 +89,8 @@ public class AgiChannelImpl implements AgiChannel private final AgiWriter agiWriter; private final AgiReader agiReader; + private static Log logger = LogFactory.getLog(AgiChannelImpl.class); + private AgiReply lastReply; protected AgiChannelImpl(AgiRequest request, AgiWriter agiWriter, AgiReader agiReader) @@ -138,6 +142,11 @@ public synchronized AgiReply sendCommand(AgiCommand command) throws AgiException public AsteriskVersion getAsteriskVersion() { + if (request == null) + { + logger.warn("Request is null, I assume you're testing... returning AsteriskVersion 1.4"); + return AsteriskVersion.ASTERISK_1_4; + } return request.getAsteriskVersion(); } From 045e91878f1a788a8dced9e885e349ce1e68f5c4 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 24 Jul 2018 16:18:27 +1000 Subject: [PATCH 197/802] add alternate separater for bridge option --- .../java/org/asteriskjava/fastagi/command/BridgeCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java index 5bccbd731..a9f79e75e 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java @@ -33,7 +33,7 @@ public String buildCommand() } else { - command += " " + escapeAndQuote(options); + command += "|" + escapeAndQuote(options); } } From 70489d7f0c1a61dc320317e50898463f1ba7f262 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 25 Jul 2018 14:27:17 +1000 Subject: [PATCH 198/802] eliminate repeated resolving of AsteriskVersion --- .../org/asteriskjava/fastagi/internal/AgiChannelImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java index 3d0500f6a..5be7f8826 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java @@ -88,6 +88,7 @@ public class AgiChannelImpl implements AgiChannel private final AgiRequest request; private final AgiWriter agiWriter; private final AgiReader agiReader; + private AsteriskVersion asteriskVersion; private static Log logger = LogFactory.getLog(AgiChannelImpl.class); @@ -147,7 +148,11 @@ public AsteriskVersion getAsteriskVersion() logger.warn("Request is null, I assume you're testing... returning AsteriskVersion 1.4"); return AsteriskVersion.ASTERISK_1_4; } - return request.getAsteriskVersion(); + if (asteriskVersion == null) + { + asteriskVersion = request.getAsteriskVersion(); + } + return asteriskVersion; } public void answer() throws AgiException From a3b01f488abeefc6bd0eb126f6f80a90553bb2d7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 1 Aug 2018 17:38:38 +1000 Subject: [PATCH 199/802] fix for getting asterisk version in agi --- src/main/java/org/asteriskjava/fastagi/AgiOperations.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/fastagi/AgiOperations.java b/src/main/java/org/asteriskjava/fastagi/AgiOperations.java index 25b450c63..0a61a1810 100644 --- a/src/main/java/org/asteriskjava/fastagi/AgiOperations.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiOperations.java @@ -465,6 +465,6 @@ public void queue(String queue) throws AgiException @Override public AsteriskVersion getAsteriskVersion() { - return channel.getAsteriskVersion(); + return getChannel().getAsteriskVersion(); } } From e36c655f53eb7f17a48cc6c73c5c8071ed2913c3 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 6 Aug 2018 15:58:46 +1000 Subject: [PATCH 200/802] new version 3.0.0-snap-shot, java version 1.8 --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index dd224e463..e345440a1 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 2.0.4-SNAP-SHOT + 3.0.0-SNAP-SHOT The free Java library for Asterisk PBX integration. 2004 @@ -120,8 +120,8 @@ maven-compiler-plugin 3.2 - 1.7 - 1.7 + 1.8 + 1.8 From a7e9d55d915902330a29a7c6ee48f416bc01fbe1 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 17 Aug 2018 16:18:28 +1000 Subject: [PATCH 201/802] fix bug where only one manager connection will see a BridgeEvent --- .../backwardsCompatibility/bridge/BridgesActive.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java index 7ebe13854..55e675c42 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java @@ -26,10 +26,7 @@ public class BridgesActive { private final Log logger = LogFactory.getLog(BridgesActive.class); - // This map is shared (static) so that connections to asterisk that attach - // late can benefit from the known bridge information of older connections - private final static ConcurrentMap activeBridges = - new ConcurrentHashMap<>(); + private final ConcurrentMap activeBridges = new ConcurrentHashMap<>(); public ManagerEvent handleEvent(ManagerEvent event) { From 0c2d7aaf6775f2f8929fba5c7b9088d35bd67c21 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 17 Aug 2018 16:18:51 +1000 Subject: [PATCH 202/802] agi dial compatibility with later versions of asterisk --- .../org/asteriskjava/fastagi/command/DialCommand.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java index 7c0885851..ba1acead0 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java @@ -1,5 +1,6 @@ package org.asteriskjava.fastagi.command; +import org.asteriskjava.AsteriskVersion; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -29,11 +30,17 @@ public DialCommand(String target, int timeout, String options) public String buildCommand() { - String command = "EXEC " + escapeAndQuote("dial") + " " + escapeAndQuote(target) + "|" + String separator = "|"; + if (getAsteriskVersion().isAtLeast(AsteriskVersion.ASTERISK_10)) + { + separator = ","; + } + + String command = "EXEC " + escapeAndQuote("dial") + " " + escapeAndQuote(target) + separator + escapeAndQuote("" + timeout); if (options != null && options.length() > 0) { - command += "|" + escapeAndQuote(options); + command += separator + escapeAndQuote(options); } logger.info(command); From d0ead4b8a70561e2b88e7ed9535e640cb7f075df Mon Sep 17 00:00:00 2001 From: Nathan Bruning Date: Sun, 19 Aug 2018 22:52:33 +0200 Subject: [PATCH 203/802] Remove Asterisk version detection for <13 versions. Update protocol identifiers to Asterisk 15.3 - 15.5. --- .../org/asteriskjava/AsteriskVersion.java | 39 ++++++++----------- .../fastagi/internal/AgiChannelImpl.java | 4 +- .../fastagi/internal/AgiRequestImpl.java | 22 +++++------ .../internal/ManagerConnectionImpl.java | 20 ++++------ .../org/asteriskjava/AsteriskVersionTest.java | 32 +-------------- .../internal/ManagerConnectionImplTest.java | 2 +- 6 files changed, 39 insertions(+), 80 deletions(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 49d92250a..55d51d8a0 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -31,17 +31,11 @@ public class AsteriskVersion implements Comparable, Serializabl private static final String VERSION_PATTERN_15 = "^\\s*Asterisk (GIT-)?15[-. ].*"; private static final String VERSION_PATTERN_14 = "^\\s*Asterisk (GIT-)?14[-. ].*"; private static final String VERSION_PATTERN_13 = "^\\s*Asterisk ((SVN-branch|GIT)-)?13[-. ].*"; - private static final String VERSION_PATTERN_12 = "^\\s*Asterisk ((SVN-branch|GIT)-)?12[-. ].*"; - private static final String VERSION_PATTERN_11 = "^\\s*Asterisk ((SVN-branch|GIT)-)?11[-. ].*"; - private static final String VERSION_PATTERN_10 = "^\\s*Asterisk ((SVN-branch|GIT)-)?10[-. ].*"; - private static final String VERSION_PATTERN_1_8 = "^\\s*Asterisk ((SVN-branch|GIT)-)?1\\.8[-. ].*"; - private static final String VERSION_PATTERN_1_6 = "^\\s*Asterisk ((SVN-branch|GIT)-)?1\\.6[-. ].*"; private final int version; private final String versionString; private final Pattern patterns[]; private static final String VERSION_PATTERN_CERTIFIED_13 = "^\\s*Asterisk certified/((SVN-branch|GIT)-)?13[-. ].*"; - private static final String VERSION_PATTERN_CERTIFIED_11 = "^\\s*Asterisk certified/((SVN-branch|GIT)-)?11[-. ].*"; /** * Represents the Asterisk 1.0 series. @@ -65,36 +59,35 @@ public class AsteriskVersion implements Comparable, Serializabl * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_1_6 = new AsteriskVersion(160, "Asterisk 1.6", VERSION_PATTERN_1_6); + public static final AsteriskVersion ASTERISK_1_6 = new AsteriskVersion(160, "Asterisk 1.6", new String[]{}); /** * Represents the Asterisk 1.8 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_1_8 = new AsteriskVersion(180, "Asterisk 1.8", VERSION_PATTERN_1_8); + public static final AsteriskVersion ASTERISK_1_8 = new AsteriskVersion(180, "Asterisk 1.8", new String[]{}); /** * Represents the Asterisk 10 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_10 = new AsteriskVersion(1000, "Asterisk 10", VERSION_PATTERN_10); + public static final AsteriskVersion ASTERISK_10 = new AsteriskVersion(1000, "Asterisk 10", new String[]{}); /** * Represents the Asterisk 11 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_11 = new AsteriskVersion(1100, "Asterisk 11", - new String[]{VERSION_PATTERN_11, VERSION_PATTERN_CERTIFIED_11}); + public static final AsteriskVersion ASTERISK_11 = new AsteriskVersion(1100, "Asterisk 11", new String[]{}); /** * Represents the Asterisk 12 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_12 = new AsteriskVersion(1200, "Asterisk 12", VERSION_PATTERN_12); + public static final AsteriskVersion ASTERISK_12 = new AsteriskVersion(1200, "Asterisk 12", new String[]{}); /** * Represents the Asterisk 13 series. @@ -118,8 +111,10 @@ public class AsteriskVersion implements Comparable, Serializabl */ public static final AsteriskVersion ASTERISK_15 = new AsteriskVersion(1500, "Asterisk 15", VERSION_PATTERN_15); - private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ASTERISK_15, ASTERISK_14, ASTERISK_13, - ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6}; + private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ASTERISK_15, ASTERISK_14, ASTERISK_13}; + + // current debian stable version, as of 03/07/2018 + public static final AsteriskVersion DEFAULT_VERSION = ASTERISK_13; /** * Serial version identifier. @@ -191,14 +186,14 @@ public String toString() return versionString; } - /** - * Determine the Asterisk version from the string returned by Asterisk. - * The string should contain "Asterisk " followed by a version number. - * - * @param coreLine - * @return the detected version, or null if unknown - */ - public static AsteriskVersion getDetermineVersionFromString(String coreLine) + /** + * Determine the Asterisk version from the string returned by Asterisk. + * The string should contain "Asterisk " followed by a version number. + * + * @param coreLine + * @return the detected version, or null if unknown + */ + public static AsteriskVersion getDetermineVersionFromString(String coreLine) { for (AsteriskVersion version : knownVersions) { diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java index 5be7f8826..541f3c011 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java @@ -145,8 +145,8 @@ public AsteriskVersion getAsteriskVersion() { if (request == null) { - logger.warn("Request is null, I assume you're testing... returning AsteriskVersion 1.4"); - return AsteriskVersion.ASTERISK_1_4; + logger.warn("Request is null, I assume you're testing..."); + return AsteriskVersion.DEFAULT_VERSION; } if (asteriskVersion == null) { diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java index 4b853035c..0db6f7a69 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java @@ -38,7 +38,7 @@ /** * Default implementation of the AGIRequest interface. - * + * * @author srt * @version $Id$ */ @@ -107,7 +107,7 @@ private AgiRequestImpl(final Map request) * prefix stripped) and the corresponding values. *

    * Syntactically invalid and empty variables are skipped. - * + * * @param lines the environment to transform. * @return a map with the variables set corresponding to the given * environment. @@ -169,7 +169,7 @@ public Map getRequest() /** * Returns the name of the script to execute. - * + * * @return the name of the script to execute. */ public synchronized String getScript() @@ -180,7 +180,7 @@ public synchronized String getScript() /** * Returns the full URL of the request in the form * agi://host[:port][/script]. - * + * * @return the full URL of the request in the form * agi://host[:port][/script]. */ @@ -192,13 +192,13 @@ public String getRequestURL() @Override public AsteriskVersion getAsteriskVersion() { - AsteriskVersion detected = AsteriskVersion.getDetermineVersionFromString("Asterisk " + request.get("version")); - return detected != null ? detected : ManagerConnectionImpl.DEFAULT_ASTERISK_VERSION; + AsteriskVersion detected = AsteriskVersion.getDetermineVersionFromString("Asterisk " + request.get("version")); + return detected != null ? detected : AsteriskVersion.DEFAULT_VERSION; } /** * Returns the name of the channel. - * + * * @return the name of the channel. */ public String getChannel() @@ -208,7 +208,7 @@ public String getChannel() /** * Returns the unqiue id of the channel. - * + * * @return the unqiue id of the channel. */ public String getUniqueId() @@ -274,7 +274,7 @@ public String getCallerIdName() /** * Returns the Caller*ID number using Asterisk 1.0 logic. - * + * * @return the Caller*ID number */ private synchronized String getCallerId10() @@ -297,7 +297,7 @@ private synchronized String getCallerId10() /** * Returns the Caller*ID name using Asterisk 1.0 logic. - * + * * @return the Caller*ID name */ private synchronized String getCallerIdName10() @@ -480,7 +480,7 @@ public synchronized Map getParameterMap() /** * Parses the given parameter string and caches the result. - * + * * @param s the parameter string to parse * @return a Map made up of parameter names their values */ diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index d40da83ba..8d2a64834 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -83,9 +83,6 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher private static final AtomicLong idCounter = new AtomicLong(0); - // current debian stable version, as of 03/07/2018 - public static final AsteriskVersion DEFAULT_ASTERISK_VERSION = AsteriskVersion.ASTERISK_13; - /** * Instance logger. */ @@ -644,8 +641,8 @@ protected AsteriskVersion determineVersion() throws IOException, TimeoutExceptio } // NOPMD } - logger.error("Unable to determine asterisk version, assuming " + DEFAULT_ASTERISK_VERSION + "... you should expect problems to follow."); - return DEFAULT_ASTERISK_VERSION; + logger.error("Unable to determine asterisk version, assuming " + AsteriskVersion.DEFAULT_VERSION + "... you should expect problems to follow."); + return AsteriskVersion.DEFAULT_VERSION; } /** @@ -789,7 +786,7 @@ public ManagerResponse sendAction(ManagerAction action) /** * Implements synchronous sending of "simple" actions. - * + * * @param timeout - in milliseconds */ public ManagerResponse sendAction(ManagerAction action, long timeout) @@ -1308,13 +1305,9 @@ private void setProtocolIdentifier(final String identifier) { logger.info("Connected via " + identifier); - if (!"Asterisk Call Manager/1.0".equals(identifier) && !"Asterisk Call Manager/1.1".equals(identifier) // Asterisk - // 1.6 - && !"Asterisk Call Manager/1.2".equals(identifier) // bri - // stuffed - && !"Asterisk Call Manager/1.3".equals(identifier) // Asterisk - // 11 - && !"Asterisk Call Manager/2.6.0".equals(identifier) // Asterisk + // NOTE: value is AMI_VERSION, defined in include/asterisk/manager.h + + if (!"Asterisk Call Manager/2.6.0".equals(identifier) // Asterisk // 13 && !"Asterisk Call Manager/2.7.0".equals(identifier) // Asterisk // 13.2 @@ -1332,6 +1325,7 @@ private void setProtocolIdentifier(final String identifier) && !"Asterisk Call Manager/4.0.0".equals(identifier) // since Asterisk 15 && !"Asterisk Call Manager/4.0.1".equals(identifier) // since Asterisk 15.1 && !"Asterisk Call Manager/4.0.2".equals(identifier) // since Asterisk 15.2 + && !"Asterisk Call Manager/4.0.3".equals(identifier) // since Asterisk 15.3 && !"OpenPBX Call Manager/1.0".equals(identifier) && !"CallWeaver Call Manager/1.0".equals(identifier) && !(identifier != null && identifier.startsWith("Asterisk Call Manager Proxy/"))) diff --git a/src/test/java/org/asteriskjava/AsteriskVersionTest.java b/src/test/java/org/asteriskjava/AsteriskVersionTest.java index e97cc8fc8..8942533c5 100644 --- a/src/test/java/org/asteriskjava/AsteriskVersionTest.java +++ b/src/test/java/org/asteriskjava/AsteriskVersionTest.java @@ -13,37 +13,7 @@ public void testNullIfNoMatch() { assertNull(AsteriskVersion.getDetermineVersionFromString("")); } - - @Test - public void test1_6() - { - assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 1.6.0").equals(AsteriskVersion.ASTERISK_1_6)); - } - - @Test - public void test1_8() - { - assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 1.8.0").equals(AsteriskVersion.ASTERISK_1_8)); - } - - @Test - public void test10() - { - assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 10.1.0").equals(AsteriskVersion.ASTERISK_10)); - } - - @Test - public void test11() - { - assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 11.1.0").equals(AsteriskVersion.ASTERISK_11)); - } - - @Test - public void test12() - { - assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 12.1.0").equals(AsteriskVersion.ASTERISK_12)); - } - + @Test public void test13() { diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerConnectionImplTest.java b/src/test/java/org/asteriskjava/manager/internal/ManagerConnectionImplTest.java index d468fb30c..a7dbf7a60 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerConnectionImplTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerConnectionImplTest.java @@ -616,7 +616,7 @@ public void onManagerEvent(ManagerEvent event) public void testIsShowVersionCommandAction() { assertTrue(mc.isShowVersionCommandAction(new CoreSettingsAction())); - assertTrue(mc.isShowVersionCommandAction(new CommandAction("core show version"))); + assertTrue(mc.isShowVersionCommandAction(new CommandAction("core show version"))); assertFalse(mc.isShowVersionCommandAction(new PingAction())); } From a42fc80ab343f3574ecd25b48bad799aa0544bdb Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 20 Aug 2018 14:16:08 +1000 Subject: [PATCH 204/802] improve support for asterisk 13+ --- .../internal/activity/SplitActivityImpl.java | 20 ++++++++++--------- .../pbx/internal/core/AsteriskPBX.java | 7 +++++++ .../core/CoherentManagerConnection.java | 13 +++++++++++- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index b42493a91..0396db628 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -236,18 +236,20 @@ private boolean splitTwo() throws PBXException { renameEventReceived.set(new CountDownLatch(1)); - // final ManagerResponse response = pbx.sendAction(redirect, 1000); - - // wait for channels to unbridge - if (!renameEventReceived.get().await(2000, TimeUnit.MILLISECONDS)) + if (pbx.expectRenameEvents()) { - logger.error("There was no rename event"); - } - else - { - logger.warn("Channels are renaming, now waiting for Quiescent"); + + // wait for channels to unbridge + if (!renameEventReceived.get().await(2000, TimeUnit.MILLISECONDS)) + { + logger.error("There was no rename event"); + } + else + { + logger.warn("Channels are renaming, now waiting for Quiescent"); + } } channels.clear(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 23764b364..2a8543126 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -80,6 +80,7 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener private final Log logger = LogFactory.getLog(getClass()); private boolean muteSupported; private boolean bridgeSupport; + private boolean expectRenameEvents; private static final int MAX_MEETME_ROOMS = 500; @@ -93,6 +94,7 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener this.muteSupported = CoherentManagerConnection.getInstance().isMuteAudioSupported(); this.bridgeSupport = CoherentManagerConnection.getInstance().isBridgeSupported(); + expectRenameEvents = CoherentManagerConnection.getInstance().expectRenameEvents(); liveChannels = new LiveChannelManager(); try { @@ -1026,4 +1028,9 @@ public List getChannelList() return liveChannels.getChannelList(); } + public boolean expectRenameEvents() + { + return expectRenameEvents; + } + } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java index 4735f1e22..1a6393363 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -113,6 +113,8 @@ class CoherentManagerConnection implements FilteredManagerListener // ready to wait for one. private CountDownLatch _reconnectLatch = new CountDownLatch(0); + private boolean expectRenameEvents = true; + public static synchronized void init() throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException, InterruptedException { @@ -434,7 +436,11 @@ private void checkFeatures() throws IOException, TimeoutException { muteAudioFound = true; } - + } + if (CoherentManagerConnection.managerConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) + { + // we are really checking for the use of PJ SIP + expectRenameEvents = false; } this.canMuteAudio = muteAudioFound; if (profile.getDisableBridge()) @@ -538,4 +544,9 @@ else if (event instanceof DisconnectEvent) } + public boolean expectRenameEvents() + { + return expectRenameEvents; + } + } From 8013b84bbc16a8f1f2c8ae60099e3dfea4ee9ea7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 5 Sep 2018 10:47:00 +1000 Subject: [PATCH 205/802] fix for getting channel name in OriginateBaseClass --- .../managerAPI/OriginateBaseClass.java | 105 +++++++++--------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index dd93a6299..c693bd65e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -31,7 +31,7 @@ public abstract class OriginateBaseClass extends EventListenerBaseClass { // Used to set a - public static final String NJR_ORIGINATE_ID = "njrOriginateID"; //$NON-NLS-1$ + public static final String NJR_ORIGINATE_ID = "njrOriginateID"; /* * this class generates and issues ActionEvents to asterisk through the @@ -98,7 +98,7 @@ protected OriginateBaseClass(final NewChannelListener listener, final Channel mo OriginateResult originate(final EndPoint local, final EndPoint target, final HashMap myVars, final CallerID callerID, final Integer timeout, final boolean hideCallerId, final String context) { - OriginateBaseClass.logger.debug("originate called"); //$NON-NLS-1$ + OriginateBaseClass.logger.debug("originate called"); this.originateSeen = false; this.channelSeen = false; @@ -109,8 +109,8 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has return null; } - OriginateBaseClass.logger.debug("originate connection endPoint \n" + local + " to endPoint " + target //$NON-NLS-1$ //$NON-NLS-2$ - + " vars " + myVars); //$NON-NLS-1$ + OriginateBaseClass.logger.debug("originate connection endPoint \n" + local + " to endPoint " + target //$NON-NLS-2$ + + " vars " + myVars); ManagerResponse response = null; final AsteriskSettings settings = PBXFactory.getActiveProfile(); @@ -120,7 +120,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has // the double under score "__" is to cause the variable to propagate // forward to the new channel when using local/ - myVars.put("__" + OriginateBaseClass.NJR_ORIGINATE_ID, this.originateID); //$NON-NLS-1$ + myVars.put("__" + OriginateBaseClass.NJR_ORIGINATE_ID, this.originateID); Integer localTimeout = timeout; @@ -133,7 +133,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has } catch (final Exception e) { - OriginateBaseClass.logger.error("Invalid dial timeout value"); //$NON-NLS-1$ + OriginateBaseClass.logger.error("Invalid dial timeout value"); } } @@ -147,7 +147,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has if (local.isLocal()) { originate.setEndPoint(local); - originate.setOption("/n"); //$NON-NLS-1$ + originate.setOption("/n"); } else { @@ -179,22 +179,17 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has this.startListener(); response = pbx.sendAction(originate, localTimeout); - OriginateBaseClass.logger.debug("Originate.sendAction completed"); //$NON-NLS-1$ - if (response.getResponse().compareToIgnoreCase("Success") != 0)//$NON-NLS-1$ + OriginateBaseClass.logger.debug("Originate.sendAction completed"); + if (response.getResponse().compareToIgnoreCase("Success") != 0) { OriginateBaseClass.logger - .error("Error Originating call" + originate.toString() + " : " + response.getMessage());//$NON-NLS-1$//$NON-NLS-2$ + .error("Error Originating call" + originate.toString() + " : " + response.getMessage());//$NON-NLS-2$ throw new ManagerCommunicationException(response.getMessage(), null); } - originateLatch.await(localTimeout + 1000, TimeUnit.MILLISECONDS); // wait - // the - // set - // timeout - // +1 - // second to - // allow for + // wait the set timeout +1 second to allow for // asterisk to start the originate + originateLatch.await(localTimeout + 1000, TimeUnit.MILLISECONDS); } catch (final InterruptedException e) { @@ -213,11 +208,11 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has { this.result.setSuccess(true); this.result.setChannelData(this.newChannel); - OriginateBaseClass.logger.debug("new channel ok: " + this.newChannel); //$NON-NLS-1$ + OriginateBaseClass.logger.debug("new channel ok: " + this.newChannel); } else { - OriginateBaseClass.logger.warn("originate failed connecting endPoint: " + local + " to ext " + target); //$NON-NLS-1$//$NON-NLS-2$ + OriginateBaseClass.logger.warn("originate failed connecting endPoint: " + local + " to ext " + target); //$NON-NLS-2$ if (this.newChannel != null) { @@ -238,13 +233,13 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has void abort(final String reason) { - OriginateBaseClass.logger.debug("Aborting originate ");//$NON-NLS-1$ + OriginateBaseClass.logger.debug("Aborting originate "); this.originateSuccess = false; this.result.setAbortReason(reason); this.hungup = true; if (this.newChannel != null) { - OriginateBaseClass.logger.warn("Aborted, Hangup up on the way out");//$NON-NLS-1$ + OriginateBaseClass.logger.warn("Aborted, Hangup up on the way out"); this.result.setChannelHungup(true); PBX pbx = PBXFactory.getActivePBX(); @@ -296,7 +291,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) if ((this.newChannel != null) && (hangupChannel.isSame(this.newChannel))) { this.originateSuccess = false; - OriginateBaseClass.logger.warn("Dest channel " + this.newChannel + " hungup after answer"); //$NON-NLS-1$//$NON-NLS-2$ + OriginateBaseClass.logger.warn("Dest channel " + this.newChannel + " hungup after answer"); //$NON-NLS-2$ originateLatch.countDown(); } if ((this.monitorChannel1 != null) && (hangupChannel.isSame(this.monitorChannel1))) @@ -305,7 +300,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) this.hungup = true; if (this.newChannel != null) { - OriginateBaseClass.logger.debug("hanging up " + this.newChannel);//$NON-NLS-1$ + OriginateBaseClass.logger.debug("hanging up " + this.newChannel); this.result.setChannelHungup(true); PBX pbx = PBXFactory.getActivePBX(); @@ -320,7 +315,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) } } - OriginateBaseClass.logger.debug("notify channel 1 hungup");//$NON-NLS-1$ + OriginateBaseClass.logger.debug("notify channel 1 hungup"); originateLatch.countDown(); } if ((this.monitorChannel2 != null) && (hangupChannel.isSame(this.monitorChannel2))) @@ -329,7 +324,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) this.hungup = true; if (this.newChannel != null) { - OriginateBaseClass.logger.debug("Hanging up channel " + this.newChannel);//$NON-NLS-1$ + OriginateBaseClass.logger.debug("Hanging up channel " + this.newChannel); this.result.setChannelHungup(true); PBX pbx = PBXFactory.getActivePBX(); @@ -343,46 +338,56 @@ synchronized public void onManagerEvent(final ManagerEvent event) } } - OriginateBaseClass.logger.debug("Notify channel 2 (" + this.monitorChannel2 + ") hungup");//$NON-NLS-1$//$NON-NLS-2$ + OriginateBaseClass.logger.debug("Notify channel 2 (" + this.monitorChannel2 + ") hungup");//$NON-NLS-2$ originateLatch.countDown(); } } if (event instanceof OriginateResponseEvent) { - OriginateBaseClass.logger.debug("response : " + this.newChannel); //$NON-NLS-1$ + OriginateBaseClass.logger.debug("response : " + this.newChannel); final OriginateResponseEvent response = (OriginateResponseEvent) event; - OriginateBaseClass.logger.debug("OriginateResponseEvent: channel=" //$NON-NLS-1$ - + (response.isChannel() ? response.getChannel() : response.getEndPoint()) + " originateID:" //$NON-NLS-1$ + OriginateBaseClass.logger.debug("OriginateResponseEvent: channel=" + + (response.isChannel() ? response.getChannel() : response.getEndPoint()) + " originateID:" + this.originateID); - OriginateBaseClass.logger.debug("{" + response.getReason() + ":" + response.getResponse() + "}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + OriginateBaseClass.logger.debug("{" + response.getReason() + ":" + response.getResponse() + "}"); //$NON-NLS-2$ //$NON-NLS-3$ if (this.originateID != null) { if (this.originateID.compareToIgnoreCase(response.getActionId()) == 0) { this.originateSuccess = response.isSuccess(); - OriginateBaseClass.logger.debug("OriginateResponse: matched actionId, success=" + this.originateSuccess //$NON-NLS-1$ - + " channelSeen=" + this.channelSeen); //$NON-NLS-1$ + OriginateBaseClass.logger.debug("OriginateResponse: matched actionId, success=" + this.originateSuccess + + " channelSeen=" + this.channelSeen); this.originateSeen = true; - // if we have also seen the channel then we can notify - // the - // originate() method - // that the call is up. Otherwise we will rely on the - // NewChannelEvent doing the - // notify. - if (this.channelSeen == true) + if (originateSuccess) { - OriginateBaseClass.logger.debug("notify originate response event 305 " + this.originateSuccess);//$NON-NLS-1$ - originateLatch.countDown(); + this.newChannel = response.getChannel(); + channelSeen = newChannel != null; + + // if we have also seen the channel then we can notify + // the + // originate() method + // that the call is up. Otherwise we will rely on the + // NewChannelEvent doing the + // notify. + if (this.channelSeen == true) + { + OriginateBaseClass.logger.debug("notify originate response event 305 " + this.originateSuccess); + originateLatch.countDown(); + } + else + { + logger.error("Originate Response didn't contain the channel"); + } } } } else { - OriginateBaseClass.logger.warn("actionid is null");//$NON-NLS-1$ + OriginateBaseClass.logger.warn("actionid is null"); } } @@ -398,8 +403,8 @@ synchronized public void onManagerEvent(final ManagerEvent event) final NewChannelEvent newState = (NewChannelEvent) event; final Channel channel = newState.getChannel(); - OriginateBaseClass.logger.debug("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-1$//$NON-NLS-2$ - + " state =" + newState.getChannelStateDesc() + " state =" + newState.getChannelState()); //$NON-NLS-1$ //$NON-NLS-2$ + OriginateBaseClass.logger.debug("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-2$ + + " state =" + newState.getChannelStateDesc() + " state =" + newState.getChannelState()); //$NON-NLS-2$ // Now try to get the NJR_ORIGINATE_ID's value to see if this is // an @@ -430,8 +435,8 @@ synchronized public void onManagerEvent(final ManagerEvent event) channel = bridgeEvent.getChannel2(); } - OriginateBaseClass.logger.debug("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-1$//$NON-NLS-2$ - + " channel2 =" + bridgeEvent.getChannel2()); //$NON-NLS-1$ + OriginateBaseClass.logger.debug("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ + + " channel2 =" + bridgeEvent.getChannel2()); // Now try to get the NJR_ORIGINATE_ID's value to see if this is // an @@ -467,7 +472,7 @@ private void checkBridge(int ctr, Channel channel) final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); final ManagerResponse response = pbx.sendAction(var, 500); - String __originateID = response.getAttribute("value"); //$NON-NLS-1$ + String __originateID = response.getAttribute("value"); if ((__originateID != null)) { @@ -481,7 +486,7 @@ private void checkBridge(int ctr, Channel channel) this.newChannel = channel; this.channelSeen = true; - OriginateBaseClass.logger.debug("new channel name " + channel); //$NON-NLS-1$ } + OriginateBaseClass.logger.debug("new channel name " + channel); if (this.listener != null) { /* @@ -495,7 +500,7 @@ private void checkBridge(int ctr, Channel channel) if (this.originateSeen == true) { - OriginateBaseClass.logger.debug("notifying success 362");//$NON-NLS-1$ + OriginateBaseClass.logger.debug("notifying success 362"); originateLatch.countDown(); } } @@ -528,6 +533,6 @@ private void checkBridge(int ctr, Channel channel) } } - } +} } From f307c68cb71e167f153d6c7b0b907dff0bfdfcf7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 13 Sep 2018 10:31:37 +1000 Subject: [PATCH 206/802] use reflection to discover ManagerEvent classes in the package org.asteriskjava.manager.event --- .../manager/internal/EventBuilderImpl.java | 227 ++++-------------- 1 file changed, 45 insertions(+), 182 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index 34f0aa549..c9c2a3b48 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -22,13 +22,19 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import org.asteriskjava.manager.event.*; +import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.PeerEntryEvent; +import org.asteriskjava.manager.event.PeersEvent; +import org.asteriskjava.manager.event.ResponseEvent; +import org.asteriskjava.manager.event.UserEvent; +import org.reflections.Reflections; /** * Default implementation of the EventBuilder interface. @@ -42,191 +48,49 @@ class EventBuilderImpl extends AbstractBuilder implements EventBuilder private static final Set ignoredAttributes = new HashSet<>(Arrays.asList("event")); private Map> registeredEventClasses; + private final static Set> knownManagerEventClasses = loadEventClasses(); + EventBuilderImpl() { this.registeredEventClasses = new HashMap<>(); registerBuiltinEventClasses(); } - @SuppressWarnings({"deprecation"}) + /** + * find and all manager event classes in the package + * org.asteriskjava.manager.event + */ + private static Set> loadEventClasses() + { + Reflections reflections = new Reflections("org.asteriskjava.manager.event"); + + Set> managerEventClasses = reflections.getSubTypesOf(ManagerEvent.class); + + Iterator> itr = managerEventClasses.iterator(); + while (itr.hasNext()) + { + Class< ? extends ManagerEvent> clazz = itr.next(); + if (Modifier.isAbstract(clazz.getModifiers())) + { + itr.remove(); + } + } + return managerEventClasses; + } + + /** + * register the known ManagerEventClasses for this builder + */ private void registerBuiltinEventClasses() { - // please add new event classes alphabetically - registerEventClass(AgentCallbackLoginEvent.class); - registerEventClass(AgentCallbackLogoffEvent.class); - registerEventClass(AgentCalledEvent.class); - registerEventClass(AgentConnectEvent.class); - registerEventClass(AgentCompleteEvent.class); - registerEventClass(AgentDumpEvent.class); - registerEventClass(AgentLoginEvent.class); - registerEventClass(AgentLogoffEvent.class); - registerEventClass(AgentRingNoAnswerEvent.class); - registerEventClass(AgentsEvent.class); - registerEventClass(AgentsCompleteEvent.class); - registerEventClass(AgiExecEndEvent.class); - registerEventClass(AgiExecEvent.class); - registerEventClass(AgiExecStartEvent.class); - registerEventClass(AntennaLevelEvent.class); - registerEventClass(AsyncAgiEvent.class); - registerEventClass(AsyncAgiEndEvent.class); - registerEventClass(AsyncAgiExecEvent.class); - registerEventClass(AsyncAgiStartEvent.class); - registerEventClass(AlarmEvent.class); - registerEventClass(AlarmClearEvent.class); - registerEventClass(BridgeCreateEvent.class); - registerEventClass(BridgeDestroyEvent.class); - registerEventClass(BridgeEnterEvent.class); - registerEventClass(BridgeEvent.class); - registerEventClass(BridgeExecEvent.class); - registerEventClass(BridgeLeaveEvent.class); - registerEventClass(BridgeMergeEvent.class); - registerEventClass(BlindTransferEvent.class); - registerEventClass(AttendedTransferEvent.class); - registerEventClass(CdrEvent.class); - registerEventClass(CelEvent.class); - registerEventClass(ChallengeSentEvent.class); - registerEventClass(ChannelReloadEvent.class); - registerEventClass(ChannelUpdateEvent.class); - registerEventClass(ChanSpyStartEvent.class); - registerEventClass(ChanSpyStopEvent.class); - registerEventClass(ConfbridgeEndEvent.class); - registerEventClass(ConfbridgeJoinEvent.class); - registerEventClass(ConfbridgeLeaveEvent.class); - registerEventClass(ConfbridgeListEvent.class); - registerEventClass(ConfbridgeListCompleteEvent.class); - registerEventClass(ConfbridgeListRoomsEvent.class); - registerEventClass(ConfbridgeListRoomsCompleteEvent.class); - registerEventClass(ConfbridgeStartEvent.class); - registerEventClass(ConfbridgeTalkingEvent.class); - registerEventClass(ContactStatusEvent.class); - registerEventClass(CoreShowChannelEvent.class); - registerEventClass(CoreShowChannelsCompleteEvent.class); - registerEventClass(DAHDIChannelEvent.class); - registerEventClass(DahdiShowChannelsEvent.class); - registerEventClass(DahdiShowChannelsCompleteEvent.class); - registerEventClass(DbGetResponseEvent.class); - registerEventClass(DeviceStateChangeEvent.class); - registerEventClass(DialBeginEvent.class); - registerEventClass(DialEndEvent.class); - registerEventClass(DialEvent.class); - registerEventClass(DndStateEvent.class); - registerEventClass(DongleNewSMSBase64Event.class); - registerEventClass(DongleCENDEvent.class); - registerEventClass(DongleCallStateChangeEvent.class); - registerEventClass(DongleNewSMSEvent.class); - registerEventClass(DongleNewCMGREvent.class); - registerEventClass(DongleStatusEvent.class); - registerEventClass(DongleDeviceEntryEvent.class); - registerEventClass(DongleShowDevicesCompleteEvent.class); - registerEventClass(DtmfBeginEvent.class); - registerEventClass(DtmfEndEvent.class); - registerEventClass(DtmfEvent.class); - registerEventClass(ExtensionStatusEvent.class); - registerEventClass(FaxDocumentStatusEvent.class); - registerEventClass(FaxReceivedEvent.class); - registerEventClass(FaxStatusEvent.class); - registerEventClass(FullyBootedEvent.class); - registerEventClass(HangupEvent.class); - registerEventClass(HangupRequestEvent.class); - registerEventClass(HoldedCallEvent.class); - registerEventClass(HoldEvent.class); - registerEventClass(InvalidPasswordEvent.class); - registerEventClass(JabberEventEvent.class); - registerEventClass(JitterBufStatsEvent.class); - registerEventClass(JoinEvent.class); - registerEventClass(LeaveEvent.class); - registerEventClass(LinkEvent.class); - registerEventClass(ListDialplanEvent.class); - registerEventClass(LocalBridgeEvent.class); - registerEventClass(LocalOptimizationBeginEvent.class); - registerEventClass(LocalOptimizationEndEvent.class); - registerEventClass(LogChannelEvent.class); - registerEventClass(NewConnectedLineEvent.class); - registerEventClass(MasqueradeEvent.class); - registerEventClass(MeetMeEndEvent.class); - registerEventClass(MeetMeJoinEvent.class); - registerEventClass(MeetMeLeaveEvent.class); - registerEventClass(MeetMeMuteEvent.class); - registerEventClass(MeetMeTalkingEvent.class); - registerEventClass(MeetMeTalkingRequestEvent.class); - registerEventClass(MeetMeStopTalkingEvent.class); - registerEventClass(MessageWaitingEvent.class); - registerEventClass(ModuleLoadReportEvent.class); - registerEventClass(MonitorStartEvent.class); - registerEventClass(MonitorStopEvent.class); - registerEventClass(MusicOnHoldEvent.class); - registerEventClass(MusicOnHoldStartEvent.class); - registerEventClass(MusicOnHoldStopEvent.class); - registerEventClass(NewAccountCodeEvent.class); - registerEventClass(NewCallerIdEvent.class); - registerEventClass(NewChannelEvent.class); - registerEventClass(NewExtenEvent.class); - registerEventClass(NewStateEvent.class); - registerEventClass(OriginateFailureEvent.class); - registerEventClass(OriginateSuccessEvent.class); - registerEventClass(OriginateResponseEvent.class); - registerEventClass(ParkedCallGiveUpEvent.class); - registerEventClass(ParkedCallEvent.class); - registerEventClass(ParkedCallTimeOutEvent.class); - registerEventClass(ParkedCallsCompleteEvent.class); - registerEventClass(PausedEvent.class); - registerEventClass(PeerEntryEvent.class); - registerEventClass(PeerlistCompleteEvent.class); - registerEventClass(PeersEvent.class); - registerEventClass(PeerStatusEvent.class); - registerEventClass(PickupEvent.class); - registerEventClass(PriEventEvent.class); - registerEventClass(QueueCallerAbandonEvent.class); - registerEventClass(QueueCallerJoinEvent.class); - registerEventClass(QueueCallerLeaveEvent.class); - registerEventClass(QueueEntryEvent.class); - registerEventClass(QueueMemberAddedEvent.class); - registerEventClass(QueueMemberEvent.class); - registerEventClass(QueueMemberPausedEvent.class); - registerEventClass(QueueMemberPauseEvent.class); - registerEventClass(QueueMemberPenaltyEvent.class); - registerEventClass(QueueMemberRemovedEvent.class); - registerEventClass(QueueMemberStatusEvent.class); - registerEventClass(QueueParamsEvent.class); - registerEventClass(QueueStatusCompleteEvent.class); - registerEventClass(QueueSummaryCompleteEvent.class); - registerEventClass(QueueSummaryEvent.class); - registerEventClass(ReceiveFaxEvent.class); - registerEventClass(RegistrationsCompleteEvent.class); - registerEventClass(RegistryEntryEvent.class); - registerEventClass(RegistryEvent.class); - registerEventClass(ReloadEvent.class); - registerEventClass(RenameEvent.class); - registerEventClass(RtcpReceivedEvent.class); - registerEventClass(RtcpSentEvent.class); - registerEventClass(RtpReceiverStatEvent.class); - registerEventClass(RtpSenderStatEvent.class); - registerEventClass(SendFaxStatusEvent.class); - registerEventClass(SendFaxEvent.class); - registerEventClass(SkypeAccountStatusEvent.class); - registerEventClass(SkypeBuddyEntryEvent.class); - registerEventClass(SkypeBuddyListCompleteEvent.class); - registerEventClass(SkypeBuddyStatusEvent.class); - registerEventClass(SkypeChatMessageEvent.class); - registerEventClass(SkypeLicenseEvent.class); - registerEventClass(SkypeLicenseListCompleteEvent.class); - registerEventClass(ShowDialplanCompleteEvent.class); - registerEventClass(ShutdownEvent.class); - registerEventClass(SoftHangupRequestEvent.class); - registerEventClass(StatusEvent.class); - registerEventClass(StatusCompleteEvent.class); - registerEventClass(SuccessfulAuthEvent.class); - registerEventClass(T38FaxStatusEvent.class); - registerEventClass(TransferEvent.class); - registerEventClass(UnholdEvent.class); - registerEventClass(UnpausedEvent.class); - registerEventClass(UnlinkEvent.class); - registerEventClass(UnparkedCallEvent.class); - registerEventClass(VarSetEvent.class); - registerEventClass(VoicemailUserEntryCompleteEvent.class); - registerEventClass(VoicemailUserEntryEvent.class); - registerEventClass(ZapShowChannelsEvent.class); - registerEventClass(ZapShowChannelsCompleteEvent.class); + + for (Class< ? extends ManagerEvent> managerEventClass : knownManagerEventClasses) + { + + registerEventClass(managerEventClass); + + } + } public final void registerEventClass(Class< ? extends ManagerEvent> clazz) throws IllegalArgumentException @@ -253,10 +117,9 @@ public final void registerEventClass(Class< ? extends ManagerEvent> clazz) throw /** * Registers a new event class for the event given by eventType. * - * @param eventType the name of the event to register the class for. For - * example "Join". - * @param clazz the event class to register, must extend - * {@link ManagerEvent}. + * @param eventType the name of the event to register the class for. For example + * "Join". + * @param clazz the event class to register, must extend {@link ManagerEvent}. * @throws IllegalArgumentException if clazz is not a valid event class. */ public final void registerEventClass(String eventType, Class< ? extends ManagerEvent> clazz) From 9a04eaebc2c8d09adb9ca754c82ef2253a3199c5 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 13 Sep 2018 10:34:01 +1000 Subject: [PATCH 207/802] replace if block with reflection --- .../manager/AbstractManagerEventListener.java | 371 +++--------------- 1 file changed, 45 insertions(+), 326 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 1e507ef13..7b4c4ab07 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -1,5 +1,7 @@ package org.asteriskjava.manager; +import java.lang.reflect.Method; + import org.asteriskjava.manager.event.AgentCallbackLoginEvent; import org.asteriskjava.manager.event.AgentCallbackLogoffEvent; import org.asteriskjava.manager.event.AgentCalledEvent; @@ -83,11 +85,14 @@ import org.asteriskjava.manager.event.UserEvent; import org.asteriskjava.manager.event.ZapShowChannelsCompleteEvent; import org.asteriskjava.manager.event.ZapShowChannelsEvent; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** - * Utility class that provides a protected handler method for each concrete manager event. - * Makes life easier by removing the need to code endless if-then-else constructs with instanceof - * checking for the events you are interested in. + * Utility class that provides a protected handler method for each concrete + * manager event. Makes life easier by removing the need to code endless + * if-then-else constructs with instanceof checking for the events you are + * interested in. *

    * Kindly donated by Steve Prior. *

    @@ -141,6 +146,8 @@ */ public abstract class AbstractManagerEventListener implements ManagerEventListener { + Log logger = LogFactory.getLog(AbstractManagerEventListener.class); + protected void handleEvent(AgentCallbackLoginEvent event) { } @@ -176,7 +183,7 @@ protected void handleEvent(CdrEvent event) protected void handleEvent(ChanSpyStartEvent event) { } - + protected void handleEvent(ChanSpyStopEvent event) { } @@ -184,20 +191,23 @@ protected void handleEvent(ChanSpyStopEvent event) protected void handleEvent(ConnectEvent event) { } - protected void handleEvent(DAHDIChannelEvent event) + + protected void handleEvent(DAHDIChannelEvent event) { } - protected void handleEvent(SoftHangupRequestEvent event) + + protected void handleEvent(SoftHangupRequestEvent event) { } protected void handleEvent(DialEvent event) { } - + protected void handleEvent(HangupRequestEvent event) - { - } + { + } + protected void handleEvent(DisconnectEvent event) { } @@ -349,27 +359,35 @@ protected void handleEvent(AgentsEvent event) protected void handleEvent(DbGetResponseEvent event) { } + protected void handleEvent(DongleNewSMSBase64Event event) { } + protected void handleEvent(DongleStatusEvent event) { } + protected void handleEvent(DongleCENDEvent event) { } + protected void handleEvent(DongleCallStateChangeEvent event) { } + protected void handleEvent(DongleNewSMSEvent event) { } + protected void handleEvent(DongleNewCMGREvent event) { } + protected void handleEvent(DongleDeviceEntryEvent event) { } + protected void handleEvent(JoinEvent event) { } @@ -405,7 +423,7 @@ protected void handleEvent(PeerlistCompleteEvent event) protected void handleEvent(QueueEntryEvent event) { } - + protected void handleEvent(QueueMemberEvent event) { } @@ -441,6 +459,7 @@ protected void handleEvent(ZapShowChannelsCompleteEvent event) protected void handleEvent(DahdiShowChannelsCompleteEvent event) { } + protected void handleEvent(ZapShowChannelsEvent event) { } @@ -465,325 +484,25 @@ protected void handleEvent(CoreShowChannelsCompleteEvent event) @Override public void onManagerEvent(ManagerEvent event) { - if (event instanceof AgentCallbackLoginEvent) - { - handleEvent((AgentCallbackLoginEvent) event); - } - else if (event instanceof AgentCallbackLogoffEvent) - { - handleEvent((AgentCallbackLogoffEvent) event); - } - else if (event instanceof AgentCalledEvent) - { - handleEvent((AgentCalledEvent) event); - } - else if (event instanceof AgentLoginEvent) - { - handleEvent((AgentLoginEvent) event); - } - else if (event instanceof AgentLogoffEvent) - { - handleEvent((AgentLogoffEvent) event); - } - else if (event instanceof AlarmClearEvent) - { - handleEvent((AlarmClearEvent) event); - } - else if (event instanceof AlarmEvent) - { - handleEvent((AlarmEvent) event); - } - else if (event instanceof CdrEvent) - { - handleEvent((CdrEvent) event); - } - else if (event instanceof ConnectEvent) - { - handleEvent((ConnectEvent) event); - } - else if (event instanceof DAHDIChannelEvent) - { - handleEvent((DAHDIChannelEvent) event); - } - else if (event instanceof SoftHangupRequestEvent) - { - handleEvent((SoftHangupRequestEvent) event); - } - else if (event instanceof DialEvent) - { - handleEvent((DialEvent) event); - } - else if (event instanceof HangupRequestEvent) - { - handleEvent((HangupRequestEvent) event); - } - else if (event instanceof DisconnectEvent) - { - handleEvent((DisconnectEvent) event); - } - else if (event instanceof DndStateEvent) - { - handleEvent((DndStateEvent) event); - } - else if (event instanceof ExtensionStatusEvent) - { - handleEvent((ExtensionStatusEvent) event); - } - else if (event instanceof HoldedCallEvent) - { - handleEvent((HoldedCallEvent) event); - } - else if (event instanceof HoldEvent) - { - handleEvent((HoldEvent) event); - } - else if (event instanceof LogChannelEvent) - { - handleEvent((LogChannelEvent) event); - } - else if (event instanceof MessageWaitingEvent) - { - handleEvent((MessageWaitingEvent) event); - } - else if (event instanceof NewExtenEvent) - { - handleEvent((NewExtenEvent) event); - } - else if (event instanceof PeerStatusEvent) - { - handleEvent((PeerStatusEvent) event); - } - else if (event instanceof ProtocolIdentifierReceivedEvent) - { - handleEvent((ProtocolIdentifierReceivedEvent) event); - } - else if (event instanceof JoinEvent) - { - handleEvent((JoinEvent) event); - } - else if (event instanceof LeaveEvent) - { - handleEvent((LeaveEvent) event); - } - else if (event instanceof QueueEvent) - { - handleEvent((QueueEvent) event); - } - else if (event instanceof RegistrationsCompleteEvent) - { - handleEvent((RegistrationsCompleteEvent) event); - } - else if (event instanceof RegistryEntryEvent) - { - handleEvent((RegistryEntryEvent) event); - } - else if (event instanceof RegistryEvent) - { - handleEvent((RegistryEvent) event); - } - else if (event instanceof ReloadEvent) - { - handleEvent((ReloadEvent) event); - } - else if (event instanceof RenameEvent) - { - handleEvent((RenameEvent) event); - } - else if (event instanceof ShutdownEvent) - { - handleEvent((ShutdownEvent) event); - } - else if (event instanceof UserEvent) - { - handleEvent((UserEvent) event); - } - else if (event instanceof AgentCompleteEvent) - { - handleEvent((AgentCompleteEvent) event); - } - else if (event instanceof AgentConnectEvent) - { - handleEvent((AgentConnectEvent) event); - } - else if (event instanceof AgentDumpEvent) - { - handleEvent((AgentDumpEvent) event); - } - else if (event instanceof FaxReceivedEvent) - { - handleEvent((FaxReceivedEvent) event); - } - else if (event instanceof NewCallerIdEvent) - { - handleEvent((NewCallerIdEvent) event); - } - else if (event instanceof HangupEvent) - { - handleEvent((HangupEvent) event); - } - else if (event instanceof NewChannelEvent) - { - handleEvent((NewChannelEvent) event); - } - else if (event instanceof NewStateEvent) - { - handleEvent((NewStateEvent) event); - } - else if (event instanceof MeetMeJoinEvent) - { - handleEvent((MeetMeJoinEvent) event); - } - else if (event instanceof DongleNewSMSBase64Event) - { - handleEvent((DongleNewSMSBase64Event) event); - } - else if (event instanceof DongleCENDEvent) - { - handleEvent((DongleCENDEvent) event); - } - else if (event instanceof DongleCallStateChangeEvent) - { - handleEvent((DongleCallStateChangeEvent) event); - } - else if (event instanceof DongleNewSMSEvent) - { - handleEvent((DongleNewSMSEvent) event); - } - else if (event instanceof DongleNewCMGREvent) - { - handleEvent((DongleNewCMGREvent) event); - } - else if (event instanceof DongleStatusEvent) - { - handleEvent((DongleStatusEvent) event); - } - else if (event instanceof DongleDeviceEntryEvent) - { - handleEvent((DongleDeviceEntryEvent) event); - } - else if (event instanceof MeetMeLeaveEvent) - { - handleEvent((MeetMeLeaveEvent) event); - } - else if (event instanceof MeetMeMuteEvent) - { - handleEvent((MeetMeMuteEvent) event); - } - else if (event instanceof MeetMeTalkingEvent) - { - handleEvent((MeetMeTalkingEvent) event); - } - else if (event instanceof ParkedCallGiveUpEvent) - { - handleEvent((ParkedCallGiveUpEvent) event); - } - else if (event instanceof ParkedCallTimeOutEvent) - { - handleEvent((ParkedCallTimeOutEvent) event); - } - else if (event instanceof UnparkedCallEvent) - { - handleEvent((UnparkedCallEvent) event); - } - else if (event instanceof QueueMemberAddedEvent) - { - handleEvent((QueueMemberAddedEvent) event); - } - else if (event instanceof QueueMemberPausedEvent) - { - handleEvent((QueueMemberPausedEvent) event); - } - else if (event instanceof QueueMemberRemovedEvent) - { - handleEvent((QueueMemberRemovedEvent) event); - } - else if (event instanceof AgentsCompleteEvent) - { - handleEvent((AgentsCompleteEvent) event); - } - else if (event instanceof AgentsEvent) - { - handleEvent((AgentsEvent) event); - } - else if (event instanceof DbGetResponseEvent) - { - handleEvent((DbGetResponseEvent) event); - } - else if (event instanceof BridgeEvent) - { - handleEvent((BridgeEvent) event); - } - else if (event instanceof OriginateResponseEvent) - { - handleEvent((OriginateResponseEvent) event); - } - else if (event instanceof ParkedCallEvent) - { - handleEvent((ParkedCallEvent) event); - } - else if (event instanceof ParkedCallsCompleteEvent) - { - handleEvent((ParkedCallsCompleteEvent) event); - } - else if (event instanceof PeerEntryEvent) - { - handleEvent((PeerEntryEvent) event); - } - else if (event instanceof PeerlistCompleteEvent) - { - handleEvent((PeerlistCompleteEvent) event); - } - else if (event instanceof QueueEntryEvent) - { - handleEvent((QueueEntryEvent) event); - } - else if (event instanceof QueueMemberEvent) - { - handleEvent((QueueMemberEvent) event); - } - else if (event instanceof QueueMemberStatusEvent) - { - handleEvent((QueueMemberStatusEvent) event); - } - else if (event instanceof QueueParamsEvent) - { - handleEvent((QueueParamsEvent) event); - } - else if (event instanceof QueueStatusCompleteEvent) - { - handleEvent((QueueStatusCompleteEvent) event); - } - else if (event instanceof StatusCompleteEvent) - { - handleEvent((StatusCompleteEvent) event); - } - else if (event instanceof StatusEvent) - { - handleEvent((StatusEvent) event); - } - else if (event instanceof ZapShowChannelsCompleteEvent) - { - handleEvent((ZapShowChannelsCompleteEvent) event); - } - else if (event instanceof DahdiShowChannelsCompleteEvent) - { - handleEvent((DahdiShowChannelsCompleteEvent) event); - } - else if (event instanceof ZapShowChannelsEvent) - { - handleEvent((ZapShowChannelsEvent) event); - } - else if (event instanceof DahdiShowChannelsEvent) - { - handleEvent((DahdiShowChannelsEvent) event); - } - else if (event instanceof CoreShowChannelEvent) + + // if this turns out to be slow, we could consider caching the reflection lookup + + try { - handleEvent((CoreShowChannelEvent) event); + Method method = this.getClass().getMethod("handleEvent", event.getClass()); + if (method != null) + { + method.invoke(this, event); + return; + } } - else if (event instanceof CoreShowChannelsCompleteEvent) + catch (Exception e) { - handleEvent((CoreShowChannelsCompleteEvent) event); + logger.error(e, e); } + + logger.error("The event " + event.getClass() + + " couldn't be mapped to a method in AbstractManagerEventListener.java, someone should add it!"); + } } From c1ffa9bfb9d0c8b81ba3a0c57b8186ab4ef1b3c5 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 13 Sep 2018 10:44:20 +1000 Subject: [PATCH 208/802] fix for method name lookup --- .../org/asteriskjava/manager/AbstractManagerEventListener.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 7b4c4ab07..4cde7dcc6 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -489,7 +489,8 @@ public void onManagerEvent(ManagerEvent event) try { - Method method = this.getClass().getMethod("handleEvent", event.getClass()); + + Method method = this.getClass().getDeclaredMethod("handleEvent", new Class[]{event.getClass()}); if (method != null) { method.invoke(this, event); From 3cee51e8f65ad7ac46bf72807a5f0255951eb969 Mon Sep 17 00:00:00 2001 From: "Roberto da T. Goncalves" Date: Fri, 21 Sep 2018 13:25:03 -0300 Subject: [PATCH 209/802] Change sendPackets from Integer to Long --- .../org/asteriskjava/manager/event/RtcpReceivedEvent.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java b/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java index 7baf0f440..c5d9682c0 100644 --- a/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java @@ -71,7 +71,7 @@ public class RtcpReceivedEvent extends AbstractRtcpEvent private InetAddress toAddress; private Integer toPort; private String sentntp; - private Integer sentPackets; + private Long sentPackets; private Long sentrtp; private String accountCode; @@ -429,12 +429,12 @@ public void setLinkedId(String linkedId) this.linkedId = linkedId; } - public Integer getSentPackets() + public Long getSentPackets() { return sentPackets; } - public void setSentPackets(Integer sentPackets) + public void setSentPackets(Long sentPackets) { this.sentPackets = sentPackets; } From e7a0239571226eae2d0089e7141473e616e1e3cf Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 9 Oct 2018 09:59:49 +1100 Subject: [PATCH 210/802] Add support for PJSip show endpoints Discovery of Manager Event classes via reflection --- pom.xml | 13 +- .../action/PJSipShowEndpointsAction.java | 62 ++++++ .../manager/event/EndpointList.java | 200 ++++++++++++++++++ .../manager/event/EndpointListComplete.java | 89 ++++++++ .../manager/event/StatusEvent.java | 39 ++-- .../manager/internal/AbstractBuilder.java | 24 ++- .../manager/internal/EventBuilderImpl.java | 113 +++++++++- .../java/org/asteriskjava/pbx/TechType.java | 12 +- 8 files changed, 512 insertions(+), 40 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java create mode 100644 src/main/java/org/asteriskjava/manager/event/EndpointList.java create mode 100644 src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java diff --git a/pom.xml b/pom.xml index e345440a1..832f273da 100644 --- a/pom.xml +++ b/pom.xml @@ -71,17 +71,12 @@ - internal - file://${project.build.directory}/mvn-repo + + ${distribution.id} + ${distribution.name} + ${distribution.url} - - GitHub - https://github.com/asterisk-java/asterisk-java/issues - - - UTF-8 - diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java new file mode 100644 index 000000000..f33aa8eaf --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java @@ -0,0 +1,62 @@ +/* + * 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.manager.action; + +import org.asteriskjava.manager.event.EndpointListComplete; +import org.asteriskjava.manager.event.ResponseEvent; + +/** + * Retrieves a list of all defined SIP peers. + *

    + * For each peer that is found a PeerEntryEvent is sent by Asterisk containing + * the details. When all peers have been reported a PeerlistCompleteEvent is + * sent. + *

    + * Available since Asterisk 1.2 Permission required: write=system + * + * @author srt + * @version $Id$ + * @see org.asteriskjava.manager.event.PeerEntryEvent + * @see org.asteriskjava.manager.event.PeerlistCompleteEvent + * @since 0.2 + */ +public class PJSipShowEndpointsAction extends AbstractManagerAction implements EventGeneratingAction +{ + /** + * Serial version identifier. + */ + private static final long serialVersionUID = 921037572305993779L; + + /** + * Creates a new SipPeersAction. + */ + public PJSipShowEndpointsAction() + { + + } + + @Override + public String getAction() + { + return "PJSIPShowEndpoints"; + } + + public Class< ? extends ResponseEvent> getActionCompleteEventClass() + { + return EndpointListComplete.class; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointList.java b/src/main/java/org/asteriskjava/manager/event/EndpointList.java new file mode 100644 index 000000000..723027f02 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/EndpointList.java @@ -0,0 +1,200 @@ +/* + * 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.manager.event; + +/** + * A PeerlistCompleteEvent is triggered after the details of all peers has been + * reported in response to an SIPPeersAction or SIPShowPeerAction. + *

    + * Available since Asterisk 1.2 + * + * @see org.asteriskjava.manager.event.PeerEntryEvent + * @see org.asteriskjava.manager.action.SipPeersAction + * @see org.asteriskjava.manager.action.SipShowPeerAction + * @author srt + * @version $Id$ + * @since 0.2 + */ +public class EndpointList extends ResponseEvent +{ + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -1177773673509373296L; + private Integer listItems; + private String eventList; + + private String aor; + private String auths; + private String objectName; + private String activeChannels; + private String transport; + private String outboundAuths; + private String devicestate; + private String event; + private String objectType; + private String contacts; + + /** + * Creates a new instance. + * + * @param source + */ + public EndpointList(Object source) + { + super(source); + } + + /** + * Returns the number of PeerEvents that have been reported. + * + * @return the number of PeerEvents that have been reported. + */ + public Integer getListItems() + { + return listItems; + } + + /** + * Sets the number of PeerEvents that have been reported. + * + * @param listItems the number of PeerEvents that have been reported. + */ + public void setListItems(Integer listItems) + { + this.listItems = listItems; + } + + /** + * Returns always "Complete". + *

    + * Available since Asterisk 1.6. + * + * @return always returns "Complete" confirming that all PeerEntry events have + * been sent. + * @since 1.0.0 + */ + public String getEventList() + { + return eventList; + } + + public void setEventList(String eventList) + { + this.eventList = eventList; + } + + public String getAor() + { + return aor; + } + + public void setAor(String aor) + { + this.aor = aor; + } + + public String getAuths() + { + return auths; + } + + public void setAuths(String auths) + { + this.auths = auths; + } + + public String getObjectName() + { + return objectName; + } + + public void setObjectName(String objectName) + { + this.objectName = objectName; + } + + public String getTransport() + { + return transport; + } + + public void setTransport(String transport) + { + this.transport = transport; + } + + public String getOutboundAuths() + { + return outboundAuths; + } + + public void setOutboundAuths(String outboundAuths) + { + this.outboundAuths = outboundAuths; + } + + public String getDevicestate() + { + return devicestate; + } + + public void setDevicestate(String devicestate) + { + this.devicestate = devicestate; + } + + public String getEvent() + { + return event; + } + + public void setEvent(String event) + { + this.event = event; + } + + public String getObjectType() + { + return objectType; + } + + public void setObjectType(String objectType) + { + this.objectType = objectType; + } + + public String getContacts() + { + return contacts; + } + + public void setContacts(String contacts) + { + this.contacts = contacts; + } + + public String getActiveChannels() + { + return activeChannels; + } + + public void setActiveChannels(String activeChannels) + { + this.activeChannels = activeChannels; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java b/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java new file mode 100644 index 000000000..e1a1a5dd1 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java @@ -0,0 +1,89 @@ +/* + * 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.manager.event; + +/** + * A PeerlistCompleteEvent is triggered after the details of all peers has been + * reported in response to an SIPPeersAction or SIPShowPeerAction. + *

    + * Available since Asterisk 1.2 + * + * @see org.asteriskjava.manager.event.PeerEntryEvent + * @see org.asteriskjava.manager.action.SipPeersAction + * @see org.asteriskjava.manager.action.SipShowPeerAction + * @author srt + * @version $Id$ + * @since 0.2 + */ +public class EndpointListComplete extends ResponseEvent +{ + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -1177773673509373296L; + private Integer listItems; + private String eventList; + + /** + * Creates a new instance. + * + * @param source + */ + public EndpointListComplete(Object source) + { + super(source); + } + + /** + * Returns the number of PeerEvents that have been reported. + * + * @return the number of PeerEvents that have been reported. + */ + public Integer getListItems() + { + return listItems; + } + + /** + * Sets the number of PeerEvents that have been reported. + * + * @param listItems the number of PeerEvents that have been reported. + */ + public void setListItems(Integer listItems) + { + this.listItems = listItems; + } + + /** + * Returns always "Complete". + *

    + * Available since Asterisk 1.6. + * + * @return always returns "Complete" confirming that all PeerEntry events have + * been sent. + * @since 1.0.0 + */ + public String getEventList() + { + return eventList; + } + + public void setEventList(String eventList) + { + this.eventList = eventList; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/StatusEvent.java b/src/main/java/org/asteriskjava/manager/event/StatusEvent.java index 60471f7a2..075fab112 100644 --- a/src/main/java/org/asteriskjava/manager/event/StatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/StatusEvent.java @@ -57,6 +57,7 @@ public class StatusEvent extends ResponseEvent private String readtrans; private String connectedlinename; private String connectedlinenum; + private String language; public StatusEvent(Object source) { @@ -511,19 +512,33 @@ public void setReadtrans(String readtrans) this.readtrans = readtrans; } - public String getConnectedlinename() { - return connectedlinename; - } + public String getConnectedlinename() + { + return connectedlinename; + } + + public void setConnectedlinename(String connectedlinename) + { + this.connectedlinename = connectedlinename; + } + + public String getConnectedlinenum() + { + return connectedlinenum; + } - public void setConnectedlinename(String connectedlinename) { - this.connectedlinename = connectedlinename; - } + public void setConnectedlinenum(String connectedlinenum) + { + this.connectedlinenum = connectedlinenum; + } - public String getConnectedlinenum() { - return connectedlinenum; - } + public String getLanguage() + { + return language; + } - public void setConnectedlinenum(String connectedlinenum) { - this.connectedlinenum = connectedlinenum; - } + public void setLanguage(String language) + { + this.language = language; + } } diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index d929a3e51..6fa31af4b 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -5,9 +5,11 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import org.asteriskjava.manager.event.UserEvent; +import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.AstUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -41,9 +43,9 @@ protected void setAttributes(Object target, Map attributes, Set< setterName = ReflectionUtil.stripIllegalCharacters(entry.getKey()); /* - * The source property needs special handling as it is already - * defined in java.util.EventObject (the base class of - * ManagerEvent), so we have to translate it. + * The source property needs special handling as it is already defined in + * java.util.EventObject (the base class of ManagerEvent), so we have to + * translate it. */ if ("source".equals(setterName)) { @@ -69,11 +71,16 @@ else if ("class".equals(setterName)) // it seems silly to warn if it's a user event -- maybe it was // intentional - if (setter == null && !(target instanceof UserEvent)) + if (setter == null && !(target instanceof UserEvent) && !target.getClass().equals(ManagerResponse.class)) { logger.warn("Unable to set property '" + entry.getKey() + "' to '" + entry.getValue() + "' on " + target.getClass().getName() + ": no setter. Please report at https://github.com/asterisk-java/asterisk-java/issues"); + + for (Entry entry2 : attributes.entrySet()) + { + logger.warn("Key: " + entry2.getKey() + " Value: " + entry2.getValue()); + } } if (setter == null) @@ -95,10 +102,13 @@ else if (dataType.isAssignableFrom(String.class)) value = null; } - if (value instanceof List) { + if (value instanceof List) + { StringBuilder strBuff = new StringBuilder(); - for (String tmp : (List) value) { - if (tmp != null && tmp.length() != 0) { + for (String tmp : (List) value) + { + if (tmp != null && tmp.length() != 0) + { strBuff.append(tmp).append('\n'); } } diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index c9c2a3b48..2887119bd 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -16,10 +16,17 @@ */ package org.asteriskjava.manager.internal; +import java.io.File; +import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; +import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -28,13 +35,16 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.event.PeerEntryEvent; import org.asteriskjava.manager.event.PeersEvent; import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.manager.event.UserEvent; -import org.reflections.Reflections; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; /** * Default implementation of the EventBuilder interface. @@ -48,6 +58,8 @@ class EventBuilderImpl extends AbstractBuilder implements EventBuilder private static final Set ignoredAttributes = new HashSet<>(Arrays.asList("event")); private Map> registeredEventClasses; + private static final Log logger = LogFactory.getLog(EventBuilderImpl.class); + private final static Set> knownManagerEventClasses = loadEventClasses(); EventBuilderImpl() @@ -60,22 +72,109 @@ class EventBuilderImpl extends AbstractBuilder implements EventBuilder * find and all manager event classes in the package * org.asteriskjava.manager.event */ + @SuppressWarnings("unchecked") private static Set> loadEventClasses() { - Reflections reflections = new Reflections("org.asteriskjava.manager.event"); + Set> result = new HashSet<>(); + + try + { + Set classNames = getClassNamesFromPackage("org.asteriskjava.manager.event"); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + for (String className : classNames) + { + try + { + Class< ? > clazz = classLoader.loadClass("org.asteriskjava.manager.event." + className); + if (!Modifier.isAbstract(clazz.getModifiers()) && ManagerEvent.class.isAssignableFrom(clazz)) + { + result.add((Class< ? extends ManagerEvent>) clazz); + } + } + catch (Throwable e) + { + logger.error(e, e); + } + + } + logger.error("Loaded " + result.size()); + } + catch (Exception e) + { + logger.error(e, e); + } + + return result; + } + + public static Set getClassNamesFromPackage(String packageName) throws IOException, URISyntaxException + { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Enumeration packageURLs; + Set names = new HashSet(); + + packageName = packageName.replace(".", "/"); + packageURLs = classLoader.getResources(packageName); + + while (packageURLs.hasMoreElements()) + { + URL packageURL = packageURLs.nextElement(); + if (packageURL.getProtocol().equals("jar")) + { + String jarFileName; + + Enumeration jarEntries; + String entryName; + + // build jar file name, then loop through zipped entries + jarFileName = URLDecoder.decode(packageURL.getFile(), "UTF-8"); + jarFileName = jarFileName.substring(5, jarFileName.indexOf("!")); + System.out.println(">" + jarFileName); + try (JarFile jf = new JarFile(jarFileName);) + { + jarEntries = jf.entries(); + while (jarEntries.hasMoreElements()) + { + entryName = jarEntries.nextElement().getName(); + if (entryName.startsWith(packageName) && entryName.endsWith(".class")) + { + entryName = entryName.substring(packageName.length() + 1, entryName.lastIndexOf('.')); + names.add(entryName); + } + } + } - Set> managerEventClasses = reflections.getSubTypesOf(ManagerEvent.class); + // loop through files in classpath + } + else + { + URI uri = new URI(packageURL.toString()); + File folder = new File(uri.getPath()); + // won't work with path which contains blank (%20) + // File folder = new File(packageURL.getFile()); + File[] contenuti = folder.listFiles(); + String entryName; + for (File actual : contenuti) + { + entryName = actual.getName(); + entryName = entryName.substring(0, entryName.lastIndexOf('.')); + names.add(entryName); + } + } + } - Iterator> itr = managerEventClasses.iterator(); + // clean up + Iterator itr = names.iterator(); while (itr.hasNext()) { - Class< ? extends ManagerEvent> clazz = itr.next(); - if (Modifier.isAbstract(clazz.getModifiers())) + String name = itr.next(); + if (name.equals("package") || name.endsWith(".") || name.length() == 0) { itr.remove(); } } - return managerEventClasses; + + return names; } /** diff --git a/src/main/java/org/asteriskjava/pbx/TechType.java b/src/main/java/org/asteriskjava/pbx/TechType.java index 834d5f2f8..eb767ddc6 100644 --- a/src/main/java/org/asteriskjava/pbx/TechType.java +++ b/src/main/java/org/asteriskjava/pbx/TechType.java @@ -15,7 +15,9 @@ public enum TechType implements Tech , DIALPLAN // CONSOLE is sent when a call is made from the asterisk console. // These type of channels are ignored. - , CONSOLE + , CONSOLE, + + PJSIP // PARKING & SIPPEER are used during call parking , PARKING, SIPPEER; @@ -23,8 +25,8 @@ public enum TechType implements Tech private static final Log logger = LogFactory.getLog(TechType.class); /** - * Extracts the technology from a fully qualified endpoint string of the - * form: TECH/NNNN + * Extracts the technology from a fully qualified endpoint string of the form: + * TECH/NNNN * * @param fullyQualifiedEndPoint * @return @@ -70,8 +72,8 @@ public static boolean hasValidTech(final String endPointName) } /** - * returns true if the endPoint name contains a tech descriptor even if it - * isn't a known descriptor. + * returns true if the endPoint name contains a tech descriptor even if it isn't + * a known descriptor. * * @param endPointName * @return From 31d4a4cdb316fbaed45601f6bfaadfbbb029147c Mon Sep 17 00:00:00 2001 From: Yuri Orlov Date: Sat, 27 Oct 2018 17:19:07 +0300 Subject: [PATCH 211/802] Simplify AsteriskVersion constructor --- .../org/asteriskjava/AsteriskVersion.java | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 55d51d8a0..1e36976e0 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -40,54 +40,54 @@ public class AsteriskVersion implements Comparable, Serializabl /** * Represents the Asterisk 1.0 series. */ - public static final AsteriskVersion ASTERISK_1_0 = new AsteriskVersion(100, "Asterisk 1.0", new String[]{}); + 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", new String[]{}); + 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", new String[]{}); + 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", new String[]{}); + public static final AsteriskVersion ASTERISK_1_6 = new AsteriskVersion(160, "Asterisk 1.6"); /** * Represents the Asterisk 1.8 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_1_8 = new AsteriskVersion(180, "Asterisk 1.8", new String[]{}); + public static final AsteriskVersion ASTERISK_1_8 = new AsteriskVersion(180, "Asterisk 1.8"); /** * Represents the Asterisk 10 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_10 = new AsteriskVersion(1000, "Asterisk 10", new String[]{}); + public static final AsteriskVersion ASTERISK_10 = new AsteriskVersion(1000, "Asterisk 10"); /** * Represents the Asterisk 11 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_11 = new AsteriskVersion(1100, "Asterisk 11", new String[]{}); + public static final AsteriskVersion ASTERISK_11 = new AsteriskVersion(1100, "Asterisk 11"); /** * Represents the Asterisk 12 series. * * @since 1.0.0 */ - public static final AsteriskVersion ASTERISK_12 = new AsteriskVersion(1200, "Asterisk 12", new String[]{}); + public static final AsteriskVersion ASTERISK_12 = new AsteriskVersion(1200, "Asterisk 12"); /** * Represents the Asterisk 13 series. @@ -95,7 +95,7 @@ public class AsteriskVersion implements Comparable, Serializabl * @since 1.0.0 */ public static final AsteriskVersion ASTERISK_13 = new AsteriskVersion(1300, "Asterisk 13", - new String[]{VERSION_PATTERN_13, VERSION_PATTERN_CERTIFIED_13}); + VERSION_PATTERN_13, VERSION_PATTERN_CERTIFIED_13); /** * Represents the Asterisk 14 series. @@ -121,12 +121,7 @@ public class AsteriskVersion implements Comparable, Serializabl */ private static final long serialVersionUID = 1L; - private AsteriskVersion(int version, String versionString, String pattern) - { - this(version, versionString, new String[]{pattern}); - } - - private AsteriskVersion(int version, String versionString, String patterns[]) + private AsteriskVersion(int version, String versionString, String... patterns) { this.version = version; this.versionString = versionString; From fadcd4cff6444b34d56c051fc576805774400ffb Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 30 Oct 2018 14:37:46 +1100 Subject: [PATCH 212/802] add short term silent wait activity --- ...giChannelActivityTransientHoldSilence.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java new file mode 100644 index 000000000..76ea0f229 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java @@ -0,0 +1,70 @@ +package org.asteriskjava.pbx.agi; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiHangupException; +import org.asteriskjava.pbx.AgiChannelActivityAction; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +/** + * Waits in silence for 10 seconds, then hangs up. This is useful where channels + * are waiting for some external action to redirect/bridge them. + * + * @author rsutton + */ +public class AgiChannelActivityTransientHoldSilence implements AgiChannelActivityAction +{ + private final Log logger = LogFactory.getLog(this.getClass()); + + CountDownLatch latch = new CountDownLatch(1); + volatile boolean callReachedAgi = false; + long timer = System.currentTimeMillis(); + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + try + { + callReachedAgi = true; + channel.answer(); + long secondsOnHold = Math.abs(System.currentTimeMillis() - timer) / 1000; + if (secondsOnHold > 8) + { + logger.info(ichannel + " is still on hold after " + secondsOnHold + " seconds, Hanging up"); + channel.hangup(); + } + else + { + latch.await(10, TimeUnit.SECONDS); + } + } + catch (AgiHangupException e) + { + logger.warn(e); + } + + } + + @Override + public boolean isDisconnect() + { + return false; + } + + @Override + public void cancel() + { + latch.countDown(); + + } + + public boolean hasCallReachedAgi() + { + return callReachedAgi; + } +} From 086a87fdaa1bf1aa91fe9210b6314f1f2852e5de Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 30 Oct 2018 16:40:28 +1100 Subject: [PATCH 213/802] add hard hangup on second iteration --- .../agi/AgiChannelActivityTransientHoldSilence.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java index 76ea0f229..a488030bc 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java @@ -23,7 +23,7 @@ public class AgiChannelActivityTransientHoldSilence implements AgiChannelActivit CountDownLatch latch = new CountDownLatch(1); volatile boolean callReachedAgi = false; - long timer = System.currentTimeMillis(); + boolean firstPass = true; @Override public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException @@ -32,10 +32,9 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I { callReachedAgi = true; channel.answer(); - long secondsOnHold = Math.abs(System.currentTimeMillis() - timer) / 1000; - if (secondsOnHold > 8) + if (!firstPass) { - logger.info(ichannel + " is still on hold after " + secondsOnHold + " seconds, Hanging up"); + logger.error(ichannel + " is still on hold after first pass, Hanging up"); channel.hangup(); } else @@ -47,6 +46,10 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I { logger.warn(e); } + finally + { + firstPass = false; + } } From b71154432b123f359fe1769f996dd6b6721a6eb8 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 14 Nov 2018 15:48:38 +1100 Subject: [PATCH 214/802] improve logging --- .../pbx/internal/activity/DialToAgiActivityImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index 77084901b..f25ea6ffc 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -76,7 +76,8 @@ public boolean doActivity() throws PBXException try (DialToAgi nr = new DialToAgi(this.toCallerID.toString())) { DialToAgiActivityImpl.logger.debug("**************************************************************************"); - DialToAgiActivityImpl.logger.info("*********** begin dial out to agi ***********"); + DialToAgiActivityImpl.logger + .info("*********** begin dial out to agi " + _originating + " ***********"); DialToAgiActivityImpl.logger.debug("**************************************************************************"); originator = nr; From 0e3baa2ed0f9fc85e08de8fd2af24a99d8af5ed7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 14 Nov 2018 15:49:32 +1100 Subject: [PATCH 215/802] first revision, reduce contention --- .../managerAPI/OriginateBaseClass.java | 198 +++++++++++------- 1 file changed, 119 insertions(+), 79 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index c693bd65e..6bc7cb846 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -1,11 +1,15 @@ package org.asteriskjava.pbx.internal.managerAPI; +import java.io.IOException; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.asteriskjava.live.ManagerCommunicationException; +import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; @@ -30,6 +34,12 @@ public abstract class OriginateBaseClass extends EventListenerBaseClass { + + private static final int MAX_CACHED_ORIGINATE_IDS = 100; + private final static ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(2); + private final static LinkedHashMap channelToOriginateIdMap = new LinkedHashMap(); + private final static Object channelToOriginateIdMapSync = new Object(); + // Used to set a public static final String NJR_ORIGINATE_ID = "njrOriginateID"; @@ -416,7 +426,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) // appear // within asterisk. - checkBridge(5, channel); + checkBridge(channel); } // Look for the channel events that tell us that both sides of the @@ -428,111 +438,141 @@ synchronized public void onManagerEvent(final ManagerEvent event) // to ignore these. if (event instanceof BridgeEvent) { - final BridgeEvent bridgeEvent = (BridgeEvent) event; - Channel channel = bridgeEvent.getChannel1(); - if (bridgeEvent.getChannel1().isLocal()) + if (((BridgeEvent) event).isLink()) { - channel = bridgeEvent.getChannel2(); - } + final BridgeEvent bridgeEvent = (BridgeEvent) event; + Channel channel = bridgeEvent.getChannel1(); + if (bridgeEvent.getChannel1().isLocal()) + { + channel = bridgeEvent.getChannel2(); + } - OriginateBaseClass.logger.debug("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ - + " channel2 =" + bridgeEvent.getChannel2()); + OriginateBaseClass.logger.debug("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ + + " channel2 =" + bridgeEvent.getChannel2()); - // Now try to get the NJR_ORIGINATE_ID's value to see if this is - // an - // event for our channel - // If it is for our channel then the NJR_ORIGINATE_ID will match - // our - // originateID. - // We need to try several times as it can take some time to - // appear - // within asterisk. + // Now try to get the NJR_ORIGINATE_ID's value to see if this is + // an + // event for our channel + // If it is for our channel then the NJR_ORIGINATE_ID will match + // our + // originateID. + // We need to try several times as it can take some time to + // appear + // within asterisk. - checkBridge(5, channel); + checkBridge(channel); + } } } - private void checkBridge(int ctr, Channel channel) + private void checkBridge(final Channel channel) { - while (ctr > 0) + Runnable runner = new Runnable() { - logger.debug("Check " + ctr); - try - { - ctr--; - /* - * wait 100ms to allow asterisk time to make the channel - * variables available. If you request the channel variables too - * soon asterisk responds with channel not found. - */ - - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); + int ctr = 0; - final ManagerResponse response = pbx.sendAction(var, 500); - String __originateID = response.getAttribute("value"); - - if ((__originateID != null)) + @Override + public void run() + { + try { - // Check if the event is for our channel by checking - // the - // originateIDs match. - if ((this.originateID != null) && (__originateID.compareToIgnoreCase(this.originateID) == 0)) + boolean retry = internalCheckBridge(channel); + + if (retry && ctr++ < 5 && !originateLatch.await(0, TimeUnit.MILLISECONDS)) { - if ((this.newChannel == null) && !channel.isLocal()) - { - this.newChannel = channel; - this.channelSeen = true; - - OriginateBaseClass.logger.debug("new channel name " + channel); - if (this.listener != null) - { - /* - * sometimes it's not actually the NJR phone - * we're originating. Otherwise update the NJR - * phone channel to allow the call to be - * cancelled before it's answered. - */ - this.listener.channelUpdate(channel); - } - - if (this.originateSeen == true) - { - OriginateBaseClass.logger.debug("notifying success 362"); - originateLatch.countDown(); - } - } - logger.debug("Id is " + __originateID); + logger.error("Rescheduling checkBridge for " + channel + ", looking for originateID:" + originateID); + scheduler.schedule(this, 100, TimeUnit.MILLISECONDS); } - break; } - Thread.sleep(100); + catch (Exception e) + { + logger.error(e, e); + } } - catch (final Exception e) + }; + scheduler.execute(runner); + } + + private boolean internalCheckBridge(Channel channel) + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException + { + boolean retry = true; + String __originateID = null; + synchronized (channelToOriginateIdMapSync) + { + // remove and re-add the value to move it to the tail, this is so + // when we clean up we'll remove the least recently used item + __originateID = channelToOriginateIdMap.remove(channel.getChannelName()); + if (__originateID != null) { - if (ctr == 0 && this.originateSuccess == false) + channelToOriginateIdMap.put(channel.getChannelName(), __originateID); + } + if (channelToOriginateIdMap.size() > MAX_CACHED_ORIGINATE_IDS) + { + String keyToRemove = channelToOriginateIdMap.keySet().iterator().next(); + logger.info("Removing " + keyToRemove + " when checking " + channel.getChannelName()); + channelToOriginateIdMap.remove(keyToRemove); + } + } + + if (__originateID == null) + { + logger.info("trying to get id from asterisk"); + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); + + final ManagerResponse response = pbx.sendAction(var, 500); + __originateID = response.getAttribute("value"); + + } + + if (__originateID != null) + { + if (__originateID.length() > 0) + { + retry = false; + logger.info("orid " + __originateID); + synchronized (channelToOriginateIdMapSync) { - // We only care about error if we are on the last - // attempt. - OriginateBaseClass.logger.error(e, e); + channelToOriginateIdMap.put(channel.getChannelName(), __originateID); } - else + + } + // Check if the event is for our channel by checking + // the + // originateIDs match. + if ((this.originateID != null) && (__originateID.compareToIgnoreCase(this.originateID) == 0)) + { + if ((this.newChannel == null) && !channel.isLocal()) { - try + this.newChannel = channel; + this.channelSeen = true; + + OriginateBaseClass.logger.debug("new channel name " + channel); + if (this.listener != null) { - Thread.sleep(100); + /* + * sometimes it's not actually the NJR phone we're + * originating. Otherwise update the NJR phone channel + * to allow the call to be cancelled before it's + * answered. + */ + this.listener.channelUpdate(channel); } - catch (InterruptedException e1) + + if (this.originateSeen == true) { - logger.error(e1); + OriginateBaseClass.logger.debug("notifying success 362"); + originateLatch.countDown(); } } - + logger.debug("Id is " + __originateID); } - } -} + return retry; + + } } From 8860425bfc043e48be6932bc2a97628f2ece502e Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 15 Nov 2018 11:26:34 +1100 Subject: [PATCH 216/802] Fix to avoid stalling the ManagerEvent queue in OriginateBaseClass --- .../managerAPI/OriginateBaseClass.java | 231 +++++++++++++----- 1 file changed, 168 insertions(+), 63 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 6bc7cb846..78cc29e06 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -4,6 +4,9 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -35,11 +38,6 @@ public abstract class OriginateBaseClass extends EventListenerBaseClass { - private static final int MAX_CACHED_ORIGINATE_IDS = 100; - private final static ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(2); - private final static LinkedHashMap channelToOriginateIdMap = new LinkedHashMap(); - private final static Object channelToOriginateIdMapSync = new Object(); - // Used to set a public static final String NJR_ORIGINATE_ID = "njrOriginateID"; @@ -426,7 +424,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) // appear // within asterisk. - checkBridge(channel); + getChannelsOriginateId(channel); } // Look for the channel events that tell us that both sides of the @@ -450,96 +448,205 @@ synchronized public void onManagerEvent(final ManagerEvent event) OriginateBaseClass.logger.debug("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ + " channel2 =" + bridgeEvent.getChannel2()); - // Now try to get the NJR_ORIGINATE_ID's value to see if this is - // an - // event for our channel - // If it is for our channel then the NJR_ORIGINATE_ID will match - // our - // originateID. - // We need to try several times as it can take some time to - // appear - // within asterisk. - - checkBridge(channel); + getChannelsOriginateId(channel); } } } - private void checkBridge(final Channel channel) + private final static Object sync = new Object(); + private final static Map channelToWorkerLruMap = new LinkedHashMap<>(); + private final static ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(10); + + /** + * Now try to get the NJR_ORIGINATE_ID's value to see if this is an event + * for our channel. If it is for our channel then the NJR_ORIGINATE_ID will + * match our originateID. We need to try several times as it can take some + * time to appear within asterisk.
    + *
    + * A job will be scheduled to do the lookup so as to avoid stalling the + * ManagerEventQueue. Subsequent calls to this method for the same channel + * will have their request added to the same job. + * + * @param channel + */ + void getChannelsOriginateId(final Channel channel) { - Runnable runner = new Runnable() + Worker worker; + synchronized (sync) + { + // remove the item from the cache + worker = channelToWorkerLruMap.remove(channel.getChannelName()); + if (worker == null) + { + worker = new Worker(channel); + } + // add the item at the tail of the cache list + channelToWorkerLruMap.put(channel.getChannelName(), worker); + if (channelToWorkerLruMap.size() > 500) + { + // if the cache is too large remove the head of the cache list - + // it should be the least recently used item + String keyToRemove = channelToWorkerLruMap.keySet().iterator().next(); + channelToWorkerLruMap.remove(keyToRemove); + logger.info("Removing future for " + keyToRemove + " when handling " + channel + " cache size is " + + channelToWorkerLruMap.size()); + } + } + worker.addListener(new WorkerCallback() { - int ctr = 0; + boolean done = false; + private final Object workerCallbackSync = new Object(); @Override - public void run() + public void handleResult(String workResult) { - try + synchronized (workerCallbackSync) { - boolean retry = internalCheckBridge(channel); - - if (retry && ctr++ < 5 && !originateLatch.await(0, TimeUnit.MILLISECONDS)) + if (!done) + { + handleId(channel, workResult); + done = true; + logger.info("handled result " + channel + " '" + workResult + "'"); + } + else { - logger.error("Rescheduling checkBridge for " + channel + ", looking for originateID:" + originateID); - scheduler.schedule(this, 100, TimeUnit.MILLISECONDS); + logger.error("This should never happen, handle result called twice " + channel); } } - catch (Exception e) + } + }); + } + + Runnable getTimelinessChecker(long expectedMs, final Runnable task) + { + final long expected = System.currentTimeMillis() + expectedMs + 100; + return new Runnable() + { + + @Override + public void run() + { + if (System.currentTimeMillis() > expected) { - logger.error(e, e); + logger.error("Timeliness problem, task is late by " + (System.currentTimeMillis() - expected) + "ms"); } + task.run(); } }; - scheduler.execute(runner); + } - private boolean internalCheckBridge(Channel channel) - throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException + public interface WorkerCallback + { + void handleResult(String workResult); + } + + class Worker implements Runnable { - boolean retry = true; - String __originateID = null; - synchronized (channelToOriginateIdMapSync) + List listeners = new LinkedList<>(); + final private Channel channel; + int ctr = 0; + + private final Object workerSync = new Object(); + + String channelsOriginateId = null; + + Worker(Channel channel) + { + this.channel = channel; + scheduler.execute(getTimelinessChecker(0, this)); + } + + void addListener(final WorkerCallback listener) { - // remove and re-add the value to move it to the tail, this is so - // when we clean up we'll remove the least recently used item - __originateID = channelToOriginateIdMap.remove(channel.getChannelName()); - if (__originateID != null) + synchronized (workerSync) { - channelToOriginateIdMap.put(channel.getChannelName(), __originateID); + if (channelsOriginateId != null) + { + // on worker thread for consistency + scheduler.execute(getTimelinessChecker(0, new Runnable() + { + @Override + public void run() + { + listener.handleResult(channelsOriginateId); + } + })); + } + else + { + listeners.add(listener); + } } - if (channelToOriginateIdMap.size() > MAX_CACHED_ORIGINATE_IDS) + } + + @Override + public void run() + { + try { - String keyToRemove = channelToOriginateIdMap.keySet().iterator().next(); - logger.info("Removing " + keyToRemove + " when checking " + channel.getChannelName()); - channelToOriginateIdMap.remove(keyToRemove); + String tmp = internalGetChannelOriginateId(channel); + + synchronized (workerSync) + { + channelsOriginateId = tmp; + + boolean moreTriesRemain = ctr++ < 5; + if (channelsOriginateId == null) + { + if (moreTriesRemain) + { + logger.warn( + "Rescheduling checkBridge for " + channel + ", looking for originateID:" + originateID); + scheduler.schedule(getTimelinessChecker(100, this), 100, TimeUnit.MILLISECONDS); + } + else + { + channelsOriginateId = ""; + } + } + if (channelsOriginateId != null) + { + for (WorkerCallback listener : listeners) + { + listener.handleResult(channelsOriginateId); + } + listeners.clear(); + } + } + } + catch (Exception e) + { + logger.error(e, e); } + } + } - if (__originateID == null) - { - logger.info("trying to get id from asterisk"); - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); + private String internalGetChannelOriginateId(Channel channel) + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException + { + logger.info("trying to get id from asterisk"); + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); - final ManagerResponse response = pbx.sendAction(var, 500); - __originateID = response.getAttribute("value"); + final ManagerResponse response = pbx.sendAction(var, 500); + String __originateID = response.getAttribute("value"); + if (__originateID != null && __originateID.length() > 0) + { + logger.info("Got id of " + __originateID); + return __originateID; } + return null; + } + private void handleId(Channel channel, String __originateID) + { if (__originateID != null) { - if (__originateID.length() > 0) - { - retry = false; - logger.info("orid " + __originateID); - synchronized (channelToOriginateIdMapSync) - { - channelToOriginateIdMap.put(channel.getChannelName(), __originateID); - } - - } // Check if the event is for our channel by checking // the // originateIDs match. @@ -571,8 +678,6 @@ private boolean internalCheckBridge(Channel channel) logger.debug("Id is " + __originateID); } } - return retry; - } } From b13c2153a02c9624bf163ef77916aea081624622 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 21 Nov 2018 14:42:54 +1100 Subject: [PATCH 217/802] reduce logging --- .../managerAPI/OriginateBaseClass.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 78cc29e06..95bc60486 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -508,7 +508,6 @@ public void handleResult(String workResult) { handleId(channel, workResult); done = true; - logger.info("handled result " + channel + " '" + workResult + "'"); } else { @@ -633,14 +632,19 @@ private String internalGetChannelOriginateId(Channel channel) final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); final ManagerResponse response = pbx.sendAction(var, 500); - String __originateID = response.getAttribute("value"); - - if (__originateID != null && __originateID.length() > 0) + if (response.isSuccess()) { - logger.info("Got id of " + __originateID); - return __originateID; + String __originateID = response.getAttribute("value"); + + if (__originateID != null && __originateID.length() > 0) + { + logger.info("Got id of " + __originateID); + return __originateID; + } + return null; } - return null; + logger.warn("Giving up because: " + response.getResponse()); + return ""; } private void handleId(Channel channel, String __originateID) From ab2d296e64b78b4d7cb9458943dbf038244dbed6 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 22 Nov 2018 16:51:45 +1100 Subject: [PATCH 218/802] add missing property in bridge event --- .../fastagi/internal/AgiRequestImpl.java | 1 - .../manager/event/AbstractBridgeEvent.java | 11 +++ .../manager/event/BridgeLeaveEvent.java | 87 +++++++++---------- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java index 0db6f7a69..ca74a14af 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiRequestImpl.java @@ -31,7 +31,6 @@ import org.asteriskjava.AsteriskVersion; import org.asteriskjava.fastagi.AgiRequest; -import org.asteriskjava.manager.internal.ManagerConnectionImpl; import org.asteriskjava.util.AstUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java index 5219b63ad..a727ea969 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java @@ -16,6 +16,7 @@ public abstract class AbstractBridgeEvent extends ManagerEvent private String bridgeName; private String bridgeTechnology; private String accountCode; + private String bridgevideosourcemode; AbstractBridgeEvent(Object source) { @@ -91,4 +92,14 @@ public void setAccountCode(String accountCode) { this.accountCode = accountCode; } + + public String getBridgevideosourcemode() + { + return bridgevideosourcemode; + } + + public void setBridgevideosourcemode(String bridgevideosourcemode) + { + this.bridgevideosourcemode = bridgevideosourcemode; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java index e03969b6c..293888c8e 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java @@ -5,49 +5,49 @@ */ public class BridgeLeaveEvent extends AbstractBridgeEvent { - /** - * - */ - private static final long serialVersionUID = 1L; - private String uniqueId; - private String channel; - private String language; - private String linkedId; - - public BridgeLeaveEvent(Object source) - { - super(source); - } - - public String getLanguage() - { - return language; - } - - public void setLanguage(String language) - { - this.language = language; - } - - public String getUniqueId() - { - return uniqueId; - } - - public void setUniqueId(String uniqueId) - { - this.uniqueId = uniqueId; - } - - public String getChannel() - { - return channel; - } - - public void setChannel(String channel) - { - this.channel = channel; - } + /** + * + */ + private static final long serialVersionUID = 1L; + private String uniqueId; + private String channel; + private String language; + private String linkedId; + + public BridgeLeaveEvent(Object source) + { + super(source); + } + + public String getLanguage() + { + return language; + } + + public void setLanguage(String language) + { + this.language = language; + } + + public String getUniqueId() + { + return uniqueId; + } + + public void setUniqueId(String uniqueId) + { + this.uniqueId = uniqueId; + } + + public String getChannel() + { + return channel; + } + + public void setChannel(String channel) + { + this.channel = channel; + } public String getLinkedId() { @@ -59,5 +59,4 @@ public void setLinkedId(String linkedId) this.linkedId = linkedId; } - } From 314d6316d4e2662ad1642bbe11325fbab6c9bbb9 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 17 Dec 2018 13:42:47 +1100 Subject: [PATCH 219/802] add missing properties for bridgeConf with asterisk16 --- .../fastagi/command/ConfbridgeCommand.java | 10 +++++- .../event/AbstractConfbridgeEvent.java | 35 ++++++++++++++++++- .../manager/event/ConfbridgeJoinEvent.java | 15 ++++++-- .../pbx/agi/AgiChannelActivityMeetme.java | 10 ++++-- .../agi/AgiChannelActivityPlayMessage.java | 5 +-- 5 files changed, 65 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/command/ConfbridgeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/ConfbridgeCommand.java index 378eee5e0..dc58fa3a6 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/ConfbridgeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/ConfbridgeCommand.java @@ -1,5 +1,7 @@ package org.asteriskjava.fastagi.command; +import org.asteriskjava.AsteriskVersion; + public class ConfbridgeCommand extends AbstractAgiCommand { /** @@ -22,10 +24,16 @@ public ConfbridgeCommand(String room, String profile) @Override public String buildCommand() { + String separator = "|"; + if (getAsteriskVersion().isAtLeast(AsteriskVersion.ASTERISK_10)) + { + separator = ","; + } + String command = "EXEC " + escapeAndQuote("confbridge") + " " + escapeAndQuote(room); if (profile != null && profile.length() > 0) { - command += " " + escapeAndQuote(profile); + command += separator + escapeAndQuote(profile); } return command; diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractConfbridgeEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractConfbridgeEvent.java index 944cc4b56..0240e90a2 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractConfbridgeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractConfbridgeEvent.java @@ -10,6 +10,9 @@ public abstract class AbstractConfbridgeEvent extends AbstractChannelEvent private String bridgeName; private String bridgeCreator; private String conference; + private String bridgeVideoSourceMode; + private String language; + private String linkedId; String admin; @@ -149,5 +152,35 @@ public final String getConference() { return conference; } - + + public String getBridgeVideoSourceMode() + { + return bridgeVideoSourceMode; + } + + public void setBridgeVideoSourceMode(String bridgeVideoSourceMode) + { + this.bridgeVideoSourceMode = bridgeVideoSourceMode; + } + + public String getLinkedId() + { + return linkedId; + } + + public void setLinkedId(String linkedId) + { + this.linkedId = linkedId; + } + + public String getLanguage() + { + return language; + } + + public void setLanguage(String language) + { + this.language = language; + } + } diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeJoinEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeJoinEvent.java index 2405f369e..f4111f1c7 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeJoinEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeJoinEvent.java @@ -12,11 +12,22 @@ public class ConfbridgeJoinEvent extends AbstractConfbridgeEvent * Serializable version identifier */ private static final long serialVersionUID = 1L; - + + String muted; + public ConfbridgeJoinEvent(Object source) { super(source); } - + public String getMuted() + { + return muted; + } + + public void setMuted(String muted) + { + this.muted = muted; + } + } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java index 1194386ee..66f383787 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java @@ -29,10 +29,16 @@ public class AgiChannelActivityMeetme implements AgiChannelActivityAction private Channel ichannel; - public AgiChannelActivityMeetme(String room, String options) + private String bridgeProfile; + + private String userProfile; + + public AgiChannelActivityMeetme(String room, String options, String bridgeProfile, String userProfile) { this.room = room; this.options = options; + this.bridgeProfile = bridgeProfile; + this.userProfile = userProfile; } @Override @@ -46,7 +52,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) { - channel.confbridge(room, "transfer"); + channel.confbridge(room, bridgeProfile + "," + userProfile); } else { diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java index 7aa2932d9..5e4318828 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java @@ -26,10 +26,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I throw new NullPointerException("ichannel cannot be null"); } String tmp = file; - if (file.indexOf(".") > 0) - { - tmp = file.substring(0, file.indexOf(".")); - } + channel.exec("Playtones", "beep"); TimeUnit.MILLISECONDS.sleep(100); // file, escape, offset, forward, rewind, pause From 1e9711e1f8a4e12edcc8e16d76ad3e56f4009a24 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 17 Dec 2018 13:44:25 +1100 Subject: [PATCH 220/802] change from meetme to confbridge --- .../pbx/agi/AgiChannelActivityMeetme.java | 18 ++-------- .../internal/activity/BridgeActivityImpl.java | 33 ------------------- .../internal/managerAPI/RedirectToMeetMe.java | 22 +++---------- 3 files changed, 7 insertions(+), 66 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java index 66f383787..7746b2568 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.util.concurrent.CountDownLatch; -import org.asteriskjava.AsteriskVersion; import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.manager.TimeoutException; @@ -23,9 +22,6 @@ public class AgiChannelActivityMeetme implements AgiChannelActivityAction CountDownLatch latch = new CountDownLatch(1); private String room; private volatile boolean hangup = true; - // volatile private iChannel ichannel; - - private String options; private Channel ichannel; @@ -33,10 +29,9 @@ public class AgiChannelActivityMeetme implements AgiChannelActivityAction private String userProfile; - public AgiChannelActivityMeetme(String room, String options, String bridgeProfile, String userProfile) + public AgiChannelActivityMeetme(String room, String bridgeProfile, String userProfile) { this.room = room; - this.options = options; this.bridgeProfile = bridgeProfile; this.userProfile = userProfile; } @@ -49,15 +44,8 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I throw new NullPointerException("ichannel cannot be null"); } this.ichannel = ichannel; - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) - { - channel.confbridge(room, bridgeProfile + "," + userProfile); - } - else - { - channel.meetme(room, options); - } + channel.confbridge(room, bridgeProfile + "," + userProfile); + if (hangup) { try diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java index 2c9d83eed..cd51e531a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java @@ -19,10 +19,7 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; -import org.asteriskjava.pbx.internal.asterisk.DurationRoomOwner; -import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.pbx.internal.managerAPI.RedirectToMeetMe; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -87,36 +84,6 @@ public boolean doActivity() throws PBXException success = this._bridgeLatch.await(3, TimeUnit.SECONDS); } - else if (pbx.isMeetmeInstalled()) - { - // As bridge isn't supported we need to do the bridge using - // a - // meetme - // room - - final RedirectToMeetMe meetmeTransfer = new RedirectToMeetMe(); - // meetme room is empty - // find a new available room. - MeetmeRoom room = pbx.acquireMeetmeRoom(new DurationRoomOwner(30, TimeUnit.SECONDS)); - - // redirect the lhs to meetme - meetmeTransfer.redirectToMeetme(_lhsChannel, room.getRoomNumber(), true, false); - - // redirect destination this is not the marked call - // as we want this to be hung up if no other calls are left - // in - // this - // room - final boolean markedCall = !_rhsChannel.canDetectHangup(); - meetmeTransfer.redirectToMeetme(_rhsChannel, room.getRoomNumber(), markedCall, false); - - // TODO put some logic to check that the meetme actually - // completes. - success = true; - - } - else - throw new PBXException("Cannot bridge two calls as neither the BridgeAction nor Meetme is available"); } catch (IllegalArgumentException | IllegalStateException | InterruptedException e) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java index f5f2ce284..4a8df6d69 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java @@ -17,8 +17,8 @@ public RedirectToMeetMe() super(); } - public boolean redirectToMeetme(final Channel channel, final String room, final boolean markedUser, - final boolean passDTMF) throws PBXException + public boolean redirectToMeetme(final Channel channel, final String room, String bridgeProfile, String userProfile) + throws PBXException { final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); /* @@ -29,27 +29,13 @@ public boolean redirectToMeetme(final Channel channel, final String room, final * set marked user */ - RedirectToMeetMe.logger.info("redirect to Meetme channel " + channel + " room " + room //$NON-NLS-1$ //$NON-NLS-2$ - + " markedUser " + markedUser); //$NON-NLS-1$ - String options = new String(); - if (markedUser == true) - { - options = "qdxA"; //$NON-NLS-1$ - } - else - { - options = "qdx"; //$NON-NLS-1$ - } - if (passDTMF) - { - options += "F"; - } + RedirectToMeetMe.logger.info("redirect to Meetme channel " + channel + " room " + room); if (!pbx.moveChannelToAgi(channel)) { throw new PBXException("Channel: " + channel + " couldn't be moved to agi"); } - channel.setCurrentActivityAction(new AgiChannelActivityMeetme(room, options)); + channel.setCurrentActivityAction(new AgiChannelActivityMeetme(room, bridgeProfile, userProfile)); return true; } From 6498e816bc8c23da0c532478c7f6416d15b0b865 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 18 Dec 2018 15:25:41 +1100 Subject: [PATCH 221/802] Add support for setting sip header on originate for PJSIP --- .../manager/action/OriginateAction.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java index 140a9e0af..6e81525ac 100644 --- a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java +++ b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java @@ -484,14 +484,16 @@ public void setAsync(Boolean async) /** * @param earlyMedia the earlyMedia to set */ - public void setEarlyMedia(Boolean earlyMedia) { + public void setEarlyMedia(Boolean earlyMedia) + { this.earlyMedia = earlyMedia; } /** * @return the earlyMedia */ - public Boolean getEarlyMedia() { + public Boolean getEarlyMedia() + { return earlyMedia; } @@ -566,4 +568,25 @@ public void addSipHeader(VariableInheritance inheritance, String header) } } + public void addPjSipHeader(VariableInheritance inheritance, String header) + { + + String[] parts = header.split(":"); + if (parts.length == 2) + { + String varName = "PJSIP_HEADER" + "(add," + parts[0] + ")"; + String varValue = parts[1]; + + if (!preventDuplicateSipHeaders.contains(header)) + { + setVariable(varName, varValue); + preventDuplicateSipHeaders.add(header); + } + else + { + logger.error("Already added the sip header " + header); + } + } + } + } From f80d28cf6a8b1b4752160bcdbdc8b1f744dc3210 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 18 Dec 2018 15:25:51 +1100 Subject: [PATCH 222/802] add DialState event --- .../asteriskjava/manager/event/DialState.java | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/event/DialState.java diff --git a/src/main/java/org/asteriskjava/manager/event/DialState.java b/src/main/java/org/asteriskjava/manager/event/DialState.java new file mode 100644 index 000000000..42217bacf --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/DialState.java @@ -0,0 +1,205 @@ +/* + * 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.manager.event; + +public class DialState extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + + String destAccountCode; + String destCallerIdName; + String destCallerIdNum; + String destChannel; + String destChannelState; + String destChannelStateDesc; + String destConnectedLineName; + String destConnectedLineNum; + String destContext; + String destExten; + String destLanguage; + String destLinkedId; + String destPriority; + String destUniqueId; + String dialStatus; + String privilege; + + public DialState(Object source) + { + super(source); + } + + public String getDestAccountCode() + { + return destAccountCode; + } + + public void setDestAccountCode(String destAccountCode) + { + this.destAccountCode = destAccountCode; + } + + public String getDestCallerIdName() + { + return destCallerIdName; + } + + public void setDestCallerIdName(String destCallerIdName) + { + this.destCallerIdName = destCallerIdName; + } + + public String getDestCallerIdNum() + { + return destCallerIdNum; + } + + public void setDestCallerIdNum(String destCallerIdNum) + { + this.destCallerIdNum = destCallerIdNum; + } + + public String getDestChannel() + { + return destChannel; + } + + public void setDestChannel(String destChannel) + { + this.destChannel = destChannel; + } + + public String getDestChannelState() + { + return destChannelState; + } + + public void setDestChannelState(String destChannelState) + { + this.destChannelState = destChannelState; + } + + public String getDestChannelStateDesc() + { + return destChannelStateDesc; + } + + public void setDestChannelStateDesc(String destChannelStateDesc) + { + this.destChannelStateDesc = destChannelStateDesc; + } + + public String getDestConnectedLineName() + { + return destConnectedLineName; + } + + public void setDestConnectedLineName(String destConnectedLineName) + { + this.destConnectedLineName = destConnectedLineName; + } + + public String getDestConnectedLineNum() + { + return destConnectedLineNum; + } + + public void setDestConnectedLineNum(String destConnectedLineNum) + { + this.destConnectedLineNum = destConnectedLineNum; + } + + public String getDestContext() + { + return destContext; + } + + public void setDestContext(String destContext) + { + this.destContext = destContext; + } + + public String getDestExten() + { + return destExten; + } + + public void setDestExten(String destExten) + { + this.destExten = destExten; + } + + public String getDestLanguage() + { + return destLanguage; + } + + public void setDestLanguage(String destLanguage) + { + this.destLanguage = destLanguage; + } + + public String getDestLinkedId() + { + return destLinkedId; + } + + public void setDestLinkedId(String destLinkedId) + { + this.destLinkedId = destLinkedId; + } + + public String getDestPriority() + { + return destPriority; + } + + public void setDestPriority(String destPriority) + { + this.destPriority = destPriority; + } + + public String getDestUniqueId() + { + return destUniqueId; + } + + public void setDestUniqueId(String destUniqueId) + { + this.destUniqueId = destUniqueId; + } + + public String getDialStatus() + { + return dialStatus; + } + + public void setDialStatus(String dialStatus) + { + this.dialStatus = dialStatus; + } + + public String getPrivilege() + { + return privilege; + } + + public void setPrivilege(String privilege) + { + this.privilege = privilege; + } + +} From 4fa37f1b232481c37f644120860bc7ea3b0a2f60 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 19 Dec 2018 13:55:10 +1100 Subject: [PATCH 223/802] implement DialStateEvent --- .../{DialState.java => DialStateEvent.java} | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) rename src/main/java/org/asteriskjava/manager/event/{DialState.java => DialStateEvent.java} (80%) diff --git a/src/main/java/org/asteriskjava/manager/event/DialState.java b/src/main/java/org/asteriskjava/manager/event/DialStateEvent.java similarity index 80% rename from src/main/java/org/asteriskjava/manager/event/DialState.java rename to src/main/java/org/asteriskjava/manager/event/DialStateEvent.java index 42217bacf..ed22a173e 100644 --- a/src/main/java/org/asteriskjava/manager/event/DialState.java +++ b/src/main/java/org/asteriskjava/manager/event/DialStateEvent.java @@ -16,7 +16,7 @@ */ package org.asteriskjava.manager.event; -public class DialState extends ManagerEvent +public class DialStateEvent extends ManagerEvent { private static final long serialVersionUID = 1L; @@ -36,8 +36,13 @@ public class DialState extends ManagerEvent String destUniqueId; String dialStatus; String privilege; + String uniqueId; + String linkedId; + String accountCode; + String language; + String channel; - public DialState(Object source) + public DialStateEvent(Object source) { super(source); } @@ -202,4 +207,53 @@ public void setPrivilege(String privilege) this.privilege = privilege; } + public String getUniqueId() + { + return uniqueId; + } + + public void setUniqueId(String uniqueId) + { + this.uniqueId = uniqueId; + } + + public String getLinkedId() + { + return linkedId; + } + + public void setLinkedId(String linkedId) + { + this.linkedId = linkedId; + } + + public String getAccountCode() + { + return accountCode; + } + + public void setAccountCode(String accountCode) + { + this.accountCode = accountCode; + } + + public String getLanguage() + { + return language; + } + + public void setLanguage(String language) + { + this.language = language; + } + + public String getChannel() + { + return channel; + } + + public void setChannel(String channel) + { + this.channel = channel; + } } From 001c21ac1e6939beb4893f58e8c3d4865a0edd8b Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 19 Dec 2018 13:55:39 +1100 Subject: [PATCH 224/802] handle null header --- .../manager/action/OriginateAction.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java index 6e81525ac..6ce73bf81 100644 --- a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java +++ b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java @@ -570,21 +570,23 @@ public void addSipHeader(VariableInheritance inheritance, String header) public void addPjSipHeader(VariableInheritance inheritance, String header) { - - String[] parts = header.split(":"); - if (parts.length == 2) + if (header != null) { - String varName = "PJSIP_HEADER" + "(add," + parts[0] + ")"; - String varValue = parts[1]; - - if (!preventDuplicateSipHeaders.contains(header)) - { - setVariable(varName, varValue); - preventDuplicateSipHeaders.add(header); - } - else + String[] parts = header.split(":"); + if (parts.length == 2) { - logger.error("Already added the sip header " + header); + String varName = "PJSIP_HEADER" + "(add," + parts[0] + ")"; + String varValue = parts[1]; + + if (!preventDuplicateSipHeaders.contains(header)) + { + setVariable(varName, varValue); + preventDuplicateSipHeaders.add(header); + } + else + { + logger.error("Already added the sip header " + header); + } } } } From 526fa992cd6b549a7364c5d8dfd766bd885dcba1 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 19 Dec 2018 13:56:04 +1100 Subject: [PATCH 225/802] handle null channel --- .../wrap/events/ChannelEventHelper.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java index 85d9ae047..05810b560 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java @@ -22,18 +22,31 @@ protected ChannelEventHelper(final org.asteriskjava.manager.event.AbstractChanne protected ChannelEventHelper(final String channel, final String uniqueId, final String callerIdNum, final String callerIdName) throws InvalidChannelName { - super(channel); // we must have a source but since don't have one pass - // anything. - this.channel = ChannelEventHelper.registerChannel(channel, uniqueId, callerIdNum, callerIdName); + super(""); // we must have a source but since don't have one pass + // anything. + if (channel != null) + { + this.channel = ChannelEventHelper.registerChannel(channel, uniqueId, callerIdNum, callerIdName); + } + else + { + this.channel = null; + } } public ChannelEventHelper(final String channel, final String uniqueId) throws InvalidChannelName { - super(channel);// we must have a source but since don't have one pass - // anything. + super("");// we must have a source but since don't have one pass + // anything. final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - - this.channel = pbx.internalRegisterChannel(channel, uniqueId); + if (channel != null) + { + this.channel = pbx.internalRegisterChannel(channel, uniqueId); + } + else + { + this.channel = null; + } } @Override From 37d1062f1089e428b9523e5fc5a39d5825d6bd0e Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 14 Jan 2019 15:42:15 +1100 Subject: [PATCH 226/802] allow abort directly on dialToAgiActivity --- .../pbx/activities/DialToAgiActivity.java | 12 ++-- .../pbx/internal/core/AsteriskPBX.java | 8 +-- .../core/DialToAgiWithAbortCallback.java | 62 ------------------- 3 files changed, 10 insertions(+), 72 deletions(-) delete mode 100644 src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java index db557e4fb..bd743ea86 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java @@ -7,12 +7,16 @@ public interface DialToAgiActivity extends Activity { - void markCancelled(); + void markCancelled(); - boolean cancelledByOperator(); + boolean cancelledByOperator(); - EndPoint getOriginatingEndPoint(); + EndPoint getOriginatingEndPoint(); - Channel getOriginatingChannel(); + Channel getOriginatingChannel(); + + void abort(); + + void dial(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 2a8543126..2db41d60b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -905,16 +905,12 @@ public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, Agi return dialer; } - public DialToAgiWithAbortCallback dialToAgiWithAbort(EndPoint endPoint, CallerID callerID, int timeout, + public DialToAgiActivityImpl dialToAgiWithAbort(EndPoint endPoint, CallerID callerID, int timeout, AgiChannelActivityAction action, ActivityCallback iCallback) { - final CompletionAdaptor completion = new CompletionAdaptor<>(); - - final DialToAgiActivityImpl dialer = new DialToAgiActivityImpl(endPoint, callerID, timeout, false, completion, null, - action); + return new DialToAgiActivityImpl(endPoint, callerID, timeout, false, iCallback, null, action); - return new DialToAgiWithAbortCallback(dialer, completion, iCallback); } /** diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java deleted file mode 100644 index a768a7f7f..000000000 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialToAgiWithAbortCallback.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.asteriskjava.pbx.internal.core; - -import java.util.concurrent.TimeUnit; - -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.ActivityStatusEnum; -import org.asteriskjava.pbx.CompletionAdaptor; -import org.asteriskjava.pbx.activities.DialToAgiActivity; -import org.asteriskjava.pbx.internal.activity.DialToAgiActivityImpl; - -public class DialToAgiWithAbortCallback -{ - private DialToAgiActivityImpl dialer; - private CompletionAdaptor completion; - private ActivityCallback iCallback; - - public DialToAgiWithAbortCallback(DialToAgiActivityImpl dialer, CompletionAdaptor completion, - ActivityCallback iCallback) - { - this.dialer = dialer; - this.completion = completion; - this.iCallback = iCallback; - } - - public void asyncStartDial() - { - - Runnable runner = new Runnable() - { - - @Override - public void run() - { - dialer.startActivity(false); - - completion.waitForCompletion(3, TimeUnit.MINUTES); - - final ActivityStatusEnum status; - - if (dialer.isSuccess()) - { - status = ActivityStatusEnum.SUCCESS; - } - else - { - status = ActivityStatusEnum.FAILURE; - } - - iCallback.progress(dialer, status, status.getDefaultMessage()); - - } - }; - - new Thread(runner).start(); - - } - - public void abort() - { - dialer.abort(); - } -} From cb8a3105a136243937f0a76a36c27e8175c8bd13 Mon Sep 17 00:00:00 2001 From: "eric.lin" Date: Wed, 16 Jan 2019 23:45:25 +0800 Subject: [PATCH 227/802] 1. add support for Asterisk16 2. add supports for Call Manager 4.0.3 and 5.0.0 --- .../org/asteriskjava/AsteriskVersion.java | 24 ++++++++++++------- .../internal/ManagerConnectionImpl.java | 6 +++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 2f36006d2..4972506f7 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -28,6 +28,7 @@ */ public class AsteriskVersion implements Comparable, Serializable { + private static final String VERSION_PATTERN_16 = "^\\s*Asterisk (GIT-)?16[-. ].*"; private static final String VERSION_PATTERN_15 = "^\\s*Asterisk (GIT-)?15[-. ].*"; private static final String VERSION_PATTERN_14 = "^\\s*Asterisk (GIT-)?14[-. ].*"; private static final String VERSION_PATTERN_13 = "^\\s*Asterisk ((SVN-branch|GIT)-)?13[-. ].*"; @@ -111,14 +112,21 @@ public class AsteriskVersion implements Comparable, Serializabl */ public static final AsteriskVersion ASTERISK_14 = new AsteriskVersion(1400, "Asterisk 14", VERSION_PATTERN_14); - /** - * Represents the Asterisk 15 series. - * - * @since 2.1.0 - */ - public static final AsteriskVersion ASTERISK_15 = new AsteriskVersion(1500, "Asterisk 15", VERSION_PATTERN_15); - - private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ASTERISK_15, ASTERISK_14, ASTERISK_13, + /** + * Represents the Asterisk 15 series. + * + * @since 2.1.0 + */ + public static final AsteriskVersion ASTERISK_15 = new AsteriskVersion(1500, "Asterisk 15", VERSION_PATTERN_15); + + /** + * Represents the Asterisk 16 series. + * + * @since 2.1.0 + */ + public static final AsteriskVersion ASTERISK_16 = new AsteriskVersion(1600, "Asterisk 16", VERSION_PATTERN_16); + + private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ASTERISK_16, ASTERISK_15, ASTERISK_14, ASTERISK_13, ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6}; /** diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index c196f3a39..5e2a1f8e4 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1381,6 +1381,12 @@ private void setProtocolIdentifier(final String identifier) && !"Asterisk Call Manager/3.1.0".equals(identifier) // Asterisk // =14.3.0 + && !"Asterisk Call Manager/4.0.3".equals(identifier) // Asterisk + // 15 + + && !"Asterisk Call Manager/5.0.0".equals(identifier) // Asterisk + // 16 + && !"OpenPBX Call Manager/1.0".equals(identifier) && !"CallWeaver Call Manager/1.0".equals(identifier) && !(identifier != null && identifier.startsWith("Asterisk Call Manager Proxy/"))) { From b7c35d5b6a49900e05a5481478a2cb0134ab2e4c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 21 Jan 2019 17:21:40 +1100 Subject: [PATCH 228/802] implement MWIUpdate and MWIDelete actions --- .../manager/action/MWIDeleteAction.java | 54 +++++++++++++ .../manager/action/MWIUpdateAction.java | 78 +++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/action/MWIDeleteAction.java create mode 100644 src/main/java/org/asteriskjava/manager/action/MWIUpdateAction.java diff --git a/src/main/java/org/asteriskjava/manager/action/MWIDeleteAction.java b/src/main/java/org/asteriskjava/manager/action/MWIDeleteAction.java new file mode 100644 index 000000000..8b459de19 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/MWIDeleteAction.java @@ -0,0 +1,54 @@ +/* + * 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.manager.action; + +public class MWIDeleteAction extends AbstractManagerAction +{ + static final long serialVersionUID = 1L; + private String mailbox; + + /** + * Creates a new MWIDeleteAction. + */ + public MWIDeleteAction() + { + + } + + public MWIDeleteAction(String mailbox) + { + this.mailbox = mailbox; + + } + + public String getMailbox() + { + return mailbox; + } + + public void setMailbox(String mailbox) + { + this.mailbox = mailbox; + } + + @Override + public String getAction() + { + return "MWIDelete"; + } + +} diff --git a/src/main/java/org/asteriskjava/manager/action/MWIUpdateAction.java b/src/main/java/org/asteriskjava/manager/action/MWIUpdateAction.java new file mode 100644 index 000000000..cb2aa9ad6 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/MWIUpdateAction.java @@ -0,0 +1,78 @@ +/* + * 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.manager.action; + +public class MWIUpdateAction extends AbstractManagerAction +{ + static final long serialVersionUID = 1L; + private String mailbox; + private int oldMessages; + private int newMessages; + + /** + * Creates a new MWIUpdateAction. + */ + public MWIUpdateAction() + { + + } + + public MWIUpdateAction(String mailbox, int oldMessages, int newMessages) + { + this.mailbox = mailbox; + this.oldMessages = oldMessages; + this.newMessages = newMessages; + + } + + public String getMailbox() + { + return mailbox; + } + + public void setMailbox(String mailbox) + { + this.mailbox = mailbox; + } + + public int getOldMessages() + { + return oldMessages; + } + + public void setOldMessages(int oldMessages) + { + this.oldMessages = oldMessages; + } + + public int getNewMessages() + { + return newMessages; + } + + public void setNewMessages(int newMessages) + { + this.newMessages = newMessages; + } + + @Override + public String getAction() + { + return "MWIUpdate"; + } + +} From 18893be716cc48bbde82adc789c2a2005272ab2d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 22 Jan 2019 13:29:28 +1100 Subject: [PATCH 229/802] find pbx wrap events by reflection --- .../manager/internal/AbstractBuilder.java | 8 +- .../manager/internal/EventBuilderImpl.java | 134 +------------ .../wrap/events/DbGetResponseEvent.java | 2 +- .../internal/core/CoherentEventFactory.java | 176 ++++++------------ .../org/asteriskjava/util/ReflectionUtil.java | 175 +++++++++++++++-- 5 files changed, 233 insertions(+), 262 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index 6fa31af4b..58406dc82 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -43,9 +43,9 @@ protected void setAttributes(Object target, Map attributes, Set< setterName = ReflectionUtil.stripIllegalCharacters(entry.getKey()); /* - * The source property needs special handling as it is already defined in - * java.util.EventObject (the base class of ManagerEvent), so we have to - * translate it. + * The source property needs special handling as it is already + * defined in java.util.EventObject (the base class of + * ManagerEvent), so we have to translate it. */ if ("source".equals(setterName)) { @@ -79,7 +79,7 @@ else if ("class".equals(setterName)) for (Entry entry2 : attributes.entrySet()) { - logger.warn("Key: " + entry2.getKey() + " Value: " + entry2.getValue()); + logger.debug("Key: " + entry2.getKey() + " Value: " + entry2.getValue()); } } diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index 2887119bd..e8546f632 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -16,27 +16,17 @@ */ package org.asteriskjava.manager.internal; -import java.io.File; -import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; -import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.event.PeerEntryEvent; @@ -45,6 +35,7 @@ import org.asteriskjava.manager.event.UserEvent; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import org.asteriskjava.util.ReflectionUtil; /** * Default implementation of the EventBuilder interface. @@ -60,7 +51,8 @@ class EventBuilderImpl extends AbstractBuilder implements EventBuilder private static final Log logger = LogFactory.getLog(EventBuilderImpl.class); - private final static Set> knownManagerEventClasses = loadEventClasses(); + private final static Set> knownManagerEventClasses = ReflectionUtil + .loadClasses("org.asteriskjava.manager.event", ManagerEvent.class); EventBuilderImpl() { @@ -68,128 +60,15 @@ class EventBuilderImpl extends AbstractBuilder implements EventBuilder registerBuiltinEventClasses(); } - /** - * find and all manager event classes in the package - * org.asteriskjava.manager.event - */ - @SuppressWarnings("unchecked") - private static Set> loadEventClasses() - { - Set> result = new HashSet<>(); - - try - { - Set classNames = getClassNamesFromPackage("org.asteriskjava.manager.event"); - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - for (String className : classNames) - { - try - { - Class< ? > clazz = classLoader.loadClass("org.asteriskjava.manager.event." + className); - if (!Modifier.isAbstract(clazz.getModifiers()) && ManagerEvent.class.isAssignableFrom(clazz)) - { - result.add((Class< ? extends ManagerEvent>) clazz); - } - } - catch (Throwable e) - { - logger.error(e, e); - } - - } - logger.error("Loaded " + result.size()); - } - catch (Exception e) - { - logger.error(e, e); - } - - return result; - } - - public static Set getClassNamesFromPackage(String packageName) throws IOException, URISyntaxException - { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - Enumeration packageURLs; - Set names = new HashSet(); - - packageName = packageName.replace(".", "/"); - packageURLs = classLoader.getResources(packageName); - - while (packageURLs.hasMoreElements()) - { - URL packageURL = packageURLs.nextElement(); - if (packageURL.getProtocol().equals("jar")) - { - String jarFileName; - - Enumeration jarEntries; - String entryName; - - // build jar file name, then loop through zipped entries - jarFileName = URLDecoder.decode(packageURL.getFile(), "UTF-8"); - jarFileName = jarFileName.substring(5, jarFileName.indexOf("!")); - System.out.println(">" + jarFileName); - try (JarFile jf = new JarFile(jarFileName);) - { - jarEntries = jf.entries(); - while (jarEntries.hasMoreElements()) - { - entryName = jarEntries.nextElement().getName(); - if (entryName.startsWith(packageName) && entryName.endsWith(".class")) - { - entryName = entryName.substring(packageName.length() + 1, entryName.lastIndexOf('.')); - names.add(entryName); - } - } - } - - // loop through files in classpath - } - else - { - URI uri = new URI(packageURL.toString()); - File folder = new File(uri.getPath()); - // won't work with path which contains blank (%20) - // File folder = new File(packageURL.getFile()); - File[] contenuti = folder.listFiles(); - String entryName; - for (File actual : contenuti) - { - entryName = actual.getName(); - entryName = entryName.substring(0, entryName.lastIndexOf('.')); - names.add(entryName); - } - } - } - - // clean up - Iterator itr = names.iterator(); - while (itr.hasNext()) - { - String name = itr.next(); - if (name.equals("package") || name.endsWith(".") || name.length() == 0) - { - itr.remove(); - } - } - - return names; - } - /** * register the known ManagerEventClasses for this builder */ private void registerBuiltinEventClasses() { - for (Class< ? extends ManagerEvent> managerEventClass : knownManagerEventClasses) { - registerEventClass(managerEventClass); - } - } public final void registerEventClass(Class< ? extends ManagerEvent> clazz) throws IllegalArgumentException @@ -216,9 +95,10 @@ public final void registerEventClass(Class< ? extends ManagerEvent> clazz) throw /** * Registers a new event class for the event given by eventType. * - * @param eventType the name of the event to register the class for. For example - * "Join". - * @param clazz the event class to register, must extend {@link ManagerEvent}. + * @param eventType the name of the event to register the class for. For + * example "Join". + * @param clazz the event class to register, must extend + * {@link ManagerEvent}. * @throws IllegalArgumentException if clazz is not a valid event class. */ public final void registerEventClass(String eventType, Class< ? extends ManagerEvent> clazz) diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java index dd7aba042..9939a4a40 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java @@ -8,7 +8,7 @@ public class DbGetResponseEvent extends ManagerEvent private final String key; private final String val; - DbGetResponseEvent(final org.asteriskjava.manager.event.DbGetResponseEvent event) + public DbGetResponseEvent(final org.asteriskjava.manager.event.DbGetResponseEvent event) { super(event); this.family = event.getFamily(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java index 808ffa801..c18f5b9fb 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java @@ -2,45 +2,19 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; import java.util.Hashtable; +import java.util.Set; import org.asteriskjava.pbx.asterisk.wrap.actions.ManagerAction; -import org.asteriskjava.pbx.asterisk.wrap.events.AgentCalledEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.AgentConnectEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ConfbridgeListCompleteEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ConfbridgeListEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ConnectEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.DialEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.DisconnectEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.DndStateEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ExtensionStatusEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.MasqueradeEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.MeetMeJoinEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.MeetMeLeaveEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.NewStateEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.OriginateResponseEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ParkedCallEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.PeerEntryEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.PeerStatusEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.PeerlistCompleteEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.QueueCallerLeaveEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.RenameEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.UnparkedCallEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.VarSetEvent; import org.asteriskjava.pbx.asterisk.wrap.response.CommandResponse; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerError; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import org.asteriskjava.util.ReflectionUtil; /** * This class maps asterisk-java events to our internal events that use iChannel @@ -48,104 +22,78 @@ * * @author bsutton */ -@SuppressWarnings("deprecation") +@SuppressWarnings({"unchecked"}) public class CoherentEventFactory { private static final Log logger = LogFactory.getLog(CoherentEventFactory.class); // Events - static Hashtable, Class< ? extends ManagerEvent>> mapEvents = new Hashtable<>(); + static Hashtable, Class> mapEvents = new Hashtable<>(); // Response static Hashtable, Class< ? extends ResponseEvent>> mapResponses = new Hashtable<>(); - // Actions - // static Hashtable, Class> mapActions = new - // Hashtable<>(); - // static initialiser static { - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.AgentCalledEvent.class, AgentCalledEvent.class); - - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.AgentConnectEvent.class, AgentConnectEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.QueueCallerLeaveEvent.class, - QueueCallerLeaveEvent.class); - - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.BridgeEvent.class, BridgeEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ConnectEvent.class, ConnectEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.DialEvent.class, DialEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.DisconnectEvent.class, DisconnectEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.DndStateEvent.class, DndStateEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ExtensionStatusEvent.class, - ExtensionStatusEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.HangupEvent.class, HangupEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.LinkEvent.class, LinkEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.MasqueradeEvent.class, MasqueradeEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.MeetMeJoinEvent.class, MeetMeJoinEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.MeetMeLeaveEvent.class, MeetMeLeaveEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.NewChannelEvent.class, NewChannelEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.NewStateEvent.class, NewStateEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ParkedCallEvent.class, ParkedCallEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.PeerStatusEvent.class, PeerStatusEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.RenameEvent.class, RenameEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ResponseEvent.class, ResponseEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.UnlinkEvent.class, UnlinkEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.UnparkedCallEvent.class, UnparkedCallEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.VarSetEvent.class, VarSetEvent.class); - - // response events - CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.OriginateResponseEvent.class, - OriginateResponseEvent.class); - CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.PeerEntryEvent.class, PeerEntryEvent.class); - CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.PeerlistCompleteEvent.class, - PeerlistCompleteEvent.class); + + Set> knownClasses = ReflectionUtil.loadClasses("org.asteriskjava.pbx.asterisk.wrap.events", + ManagerEvent.class); + + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + for (Class< ? > known : knownClasses) + { + Class< ? > clazz = null; + try + { + clazz = classLoader.loadClass("org.asteriskjava.manager.event" + "." + known.getSimpleName()); + + if (!Modifier.isAbstract(clazz.getModifiers())) + { + if (known.getConstructor(clazz) != null) + { + if (ResponseEvent.class.isAssignableFrom(known)) + { + CoherentEventFactory.mapResponses.put( + (Class) clazz, + (Class) known); + logger.info("Response Event Added " + clazz + " --> " + known); + + } + else + { + CoherentEventFactory.mapEvents.put((Class) clazz, + (Class) known); + logger.info("Manager Event Added " + clazz + " --> " + known); + } + } + else + { + logger.warn("Skipping class " + clazz + " it doesn't have a public constructor with one arg of type " + + known); + } + } + else + { + logger.info("Skipping abstract class " + clazz); + } + } + catch (ClassNotFoundException e) + { + logger.error(e, e); + throw new RuntimeException(e); + } + catch (NoSuchMethodException e) + { + logger.error(clazz.getCanonicalName() + " doesn't have an appropriate event constructor"); + } + catch (SecurityException e) + { + logger.error(e, e); + } + } + CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.ResponseEvent.class, ResponseEvent.class); - CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.StatusCompleteEvent.class, - StatusCompleteEvent.class); - CoherentEventFactory.mapResponses.put(org.asteriskjava.manager.event.StatusEvent.class, StatusEvent.class); - - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ConfbridgeListEvent.class, - ConfbridgeListEvent.class); - CoherentEventFactory.mapEvents.put(org.asteriskjava.manager.event.ConfbridgeListCompleteEvent.class, - ConfbridgeListCompleteEvent.class); - - // Actions - // CoherentEventFactory.mapActions.put( BridgeAction.class, - // org.asteriskjava.manager.action.BridgeAction.class); - // CoherentEventFactory.mapActions.put( CommandAction.class, - // org.asteriskjava.manager.action.CommandAction.class); - // CoherentEventFactory.mapActions.put( DbGetAction.class, - // org.asteriskjava.manager.action.DbGetAction.class); - // CoherentEventFactory.mapActions.put( GetVarAction.class, - // org.asteriskjava.manager.action.GetVarAction.class); - // CoherentEventFactory.mapActions.put( HangupAction.class, - // org.asteriskjava.manager.action.HangupAction.class); - // CoherentEventFactory.mapActions.put( ListCommandsAction.class, - // org.asteriskjava.manager.action.ListCommandsAction.class); - // CoherentEventFactory.mapActions.put( MonitorAction.class, - // org.asteriskjava.manager.action.MonitorAction.class); - // CoherentEventFactory.mapActions.put( MuteAudioAction.class, - // org.asteriskjava.manager.action.MuteAudioAction.class); - // CoherentEventFactory.mapActions.put( OriginateAction.class, - // org.asteriskjava.manager.action.OriginateAction.class); - // CoherentEventFactory.mapActions.put( PingAction.class, - // org.asteriskjava.manager.action.PingAction.class); - // CoherentEventFactory.mapActions.put( PlayDtmfAction.class, - // org.asteriskjava.manager.action.PlayDtmfAction.class); - // CoherentEventFactory.mapActions.put( RedirectAction.class, - // org.asteriskjava.manager.action.RedirectAction.class); - // CoherentEventFactory.mapActions.put( SetVarAction.class, - // org.asteriskjava.manager.action.SetVarAction.class); - // CoherentEventFactory.mapActions.put( SipPeersAction.class, - // org.asteriskjava.manager.action.SipPeersAction.class); - // CoherentEventFactory.mapActions.put( SipShowPeerAction.class, - // org.asteriskjava.manager.action.SipShowPeerAction.class); - // CoherentEventFactory.mapActions.put( StatusAction.class, - // org.asteriskjava.manager.action.StatusAction.class); - // CoherentEventFactory.mapActions.put( UpdateConfigAction.class, - // org.asteriskjava.manager.action.UpdateConfigAction.class); } diff --git a/src/main/java/org/asteriskjava/util/ReflectionUtil.java b/src/main/java/org/asteriskjava/util/ReflectionUtil.java index b2db5fb20..64eebc6be 100644 --- a/src/main/java/org/asteriskjava/util/ReflectionUtil.java +++ b/src/main/java/org/asteriskjava/util/ReflectionUtil.java @@ -16,16 +16,30 @@ */ package org.asteriskjava.util; +import java.io.File; +import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.Enumeration; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.Locale; import java.util.Map; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; /** * Utility class that provides helper methods for reflection that is used by the - * fastagi and manager packages to access getter and setter methods.

    + * fastagi and manager packages to access getter and setter methods. + *

    * Client code is not supposed to use this class. * * @author srt @@ -38,7 +52,8 @@ private ReflectionUtil() } /** - * Returns a Map of getter methods of the given class.

    + * Returns a Map of getter methods of the given class. + *

    * The key of the map contains the name of the attribute that can be * accessed by the getter, the value the getter itself (an instance of * java.lang.reflect.Method). A method is considered a getter if its name @@ -47,7 +62,7 @@ private ReflectionUtil() * @param clazz the class to return the getters for * @return a Map of attributes and their accessor methods (getters) */ - public static Map getGetters(final Class clazz) + public static Map getGetters(final Class< ? > clazz) { final Map accessors = new HashMap<>(); final Method[] methods = clazz.getMethods(); @@ -56,7 +71,7 @@ public static Map getGetters(final Class clazz) { String name = null; String methodName = method.getName(); - + if (methodName.startsWith("get")) { name = methodName.substring(3); @@ -65,7 +80,7 @@ else if (methodName.startsWith("is")) { name = methodName.substring(2); } - + if (name == null || name.length() == 0) { continue; @@ -84,7 +99,8 @@ else if (methodName.startsWith("is")) } /** - * Returns a Map of setter methods of the given class.

    + * Returns a Map of setter methods of the given class. + *

    * The key of the map contains the name of the attribute that can be * accessed by the setter, the value the setter itself (an instance of * java.lang.reflect.Method). A method is considered a setter if its name @@ -93,7 +109,7 @@ else if (methodName.startsWith("is")) * @param clazz the class to return the setters for * @return a Map of attributes and their accessor methods (setters) */ - public static Map getSetters(Class clazz) + public static Map getSetters(Class< ? > clazz) { final Map accessors = new HashMap<>(); final Method[] methods = clazz.getMethods(); @@ -123,10 +139,10 @@ public static Map getSetters(Class clazz) return accessors; } - /** - * Strips all illegal charaters from the given lower case string. - * Illegal characters are all characters that are neither characters ('a' to 'z') nor digits ('0' to '9'). + * Strips all illegal charaters from the given lower case string. Illegal + * characters are all characters that are neither characters ('a' to 'z') + * nor digits ('0' to '9'). * * @param s the original string * @return the string with all illegal characters stripped @@ -183,10 +199,12 @@ else if (c >= 'a' && c <= 'z') } /** - * Checks if the class is available on the current thread's context class loader. + * Checks if the class is available on the current thread's context class + * loader. * * @param s fully qualified name of the class to check. - * @return true if the class is available, false otherwise. + * @return true if the class is available, false + * otherwise. */ public static boolean isClassAvailable(String s) { @@ -204,8 +222,9 @@ public static boolean isClassAvailable(String s) } /** - * Creates a new instance of the given class. The class is loaded using the current thread's context - * class loader and instantiated using its default constructor. + * Creates a new instance of the given class. The class is loaded using the + * current thread's context class loader and instantiated using its default + * constructor. * * @param s fully qualified name of the class to instantiate. * @return the new instance or null on failure. @@ -216,8 +235,8 @@ public static Object newInstance(String s) try { - Class clazz = classLoader.loadClass(s); - Constructor constructor = clazz.getConstructor(); + Class< ? > clazz = classLoader.loadClass(s); + Constructor< ? > constructor = clazz.getConstructor(); return constructor.newInstance(); } catch (ClassNotFoundException e) @@ -243,4 +262,128 @@ public static Object newInstance(String s) return null; } } + + private static final Log logger = LogFactory.getLog(ReflectionUtil.class); + + /** + * find and all non abstract classes that implement/extend + * baseClassOrInterface in the package packageName + * + * @param packageName + * @param baseClassOrInterface + * @return + */ + @SuppressWarnings("unchecked") + public static Set> loadClasses(String packageName, Class baseClassOrInterface) + { + Set> result = new HashSet<>(); + + try + { + Set classNames = getClassNamesFromPackage(packageName); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + for (String className : classNames) + { + try + { + Class< ? > clazz = classLoader.loadClass(packageName + "." + className); + if (!Modifier.isAbstract(clazz.getModifiers()) && baseClassOrInterface.isAssignableFrom(clazz)) + { + result.add((Class) clazz); + } + } + catch (Throwable e) + { + logger.error(e, e); + } + + } + logger.info("Loaded " + result.size()); + } + catch (Exception e) + { + logger.error(e, e); + } + + return result; + } + + /** + * retrieve all the classes that can be found on the classpath for the + * specified packageName + * + * @param packageName + * @return + * @throws IOException + * @throws URISyntaxException + */ + private static Set getClassNamesFromPackage(String packageName) throws IOException, URISyntaxException + { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Enumeration packageURLs; + Set names = new HashSet(); + + packageName = packageName.replace(".", "/"); + packageURLs = classLoader.getResources(packageName); + + while (packageURLs.hasMoreElements()) + { + URL packageURL = packageURLs.nextElement(); + if (packageURL.getProtocol().equals("jar")) + { + String jarFileName; + + Enumeration jarEntries; + String entryName; + + // build jar file name, then loop through entries + jarFileName = URLDecoder.decode(packageURL.getFile(), "UTF-8"); + jarFileName = jarFileName.substring(5, jarFileName.indexOf("!")); + logger.info(">" + jarFileName); + try (JarFile jf = new JarFile(jarFileName);) + { + jarEntries = jf.entries(); + while (jarEntries.hasMoreElements()) + { + entryName = jarEntries.nextElement().getName(); + if (entryName.startsWith(packageName) && entryName.endsWith(".class")) + { + entryName = entryName.substring(packageName.length() + 1, entryName.lastIndexOf('.')); + names.add(entryName); + } + } + } + + // loop through files in classpath + } + else + { + URI uri = new URI(packageURL.toString()); + File folder = new File(uri.getPath()); + // won't work with path which contains blank (%20) + // File folder = new File(packageURL.getFile()); + File[] contenuti = folder.listFiles(); + String entryName; + for (File actual : contenuti) + { + entryName = actual.getName(); + entryName = entryName.substring(0, entryName.lastIndexOf('.')); + names.add(entryName); + } + } + } + + // clean up + Iterator itr = names.iterator(); + while (itr.hasNext()) + { + String name = itr.next(); + if (name.equals("package") || name.endsWith(".") || name.length() == 0) + { + itr.remove(); + } + } + + return names; + } } From 80f40746fa478ab892858035a2aa22f317bb1829 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 22 Jan 2019 13:33:50 +1100 Subject: [PATCH 230/802] add some missing manager events and attributes --- .../manager/event/BridgeEnterEvent.java | 14 +- .../manager/event/DialEndEvent.java | 12 +- .../event/LocalOptimizationBeginEvent.java | 40 ++- .../event/LocalOptimizationEndEvent.java | 30 +- .../wrap/events/BlindTransferEvent.java | 327 ++++++++++++++++++ .../asterisk/wrap/events/DialEndEvent.java | 263 ++++++++++++++ 6 files changed, 675 insertions(+), 11 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BlindTransferEvent.java create mode 100644 src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEndEvent.java diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeEnterEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeEnterEvent.java index 34c17d1fc..6128aff73 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeEnterEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeEnterEvent.java @@ -14,6 +14,8 @@ public class BridgeEnterEvent extends AbstractBridgeEvent private String language; private String linkedId; + private String swapuniqueid; + public BridgeEnterEvent(Object source) { super(source); @@ -58,5 +60,15 @@ public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - + + public String getSwapuniqueid() + { + return swapuniqueid; + } + + public void setSwapuniqueid(String swapuniqueid) + { + this.swapuniqueid = swapuniqueid; + } + } diff --git a/src/main/java/org/asteriskjava/manager/event/DialEndEvent.java b/src/main/java/org/asteriskjava/manager/event/DialEndEvent.java index 256302652..39b459ae9 100644 --- a/src/main/java/org/asteriskjava/manager/event/DialEndEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DialEndEvent.java @@ -12,6 +12,7 @@ public class DialEndEvent extends DialEvent private String destAccountCode; private String destLinkedId; private String linkedId; + private String forward; public DialEndEvent(Object source) { @@ -79,7 +80,14 @@ public void setLinkedId(String linkedId) this.linkedId = linkedId; } + public String getForward() + { + return forward; + } + + public void setForward(String forward) + { + this.forward = forward; + } - - } diff --git a/src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java index 5b8948789..a05baf9ae 100644 --- a/src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java @@ -17,10 +17,8 @@ package org.asteriskjava.manager.event; /** - * Raised when two halves of a Local Channel begin to optimize themselves out - * of the media path. - * - * Available since Asterisk 12 + * Raised when two halves of a Local Channel begin to optimize themselves out of + * the media path. Available since Asterisk 12 */ public class LocalOptimizationBeginEvent extends ManagerEvent { @@ -71,6 +69,10 @@ public class LocalOptimizationBeginEvent extends ManagerEvent private String sourceUniqueid; private String sourceLinkedid; + private String localTwoLanguage; + private String localOneLanguage; + private String sourceLanguage; + public LocalOptimizationBeginEvent(Object source) { super(source); @@ -485,4 +487,34 @@ public void setSourceLinkedid(String value) { this.sourceLinkedid = value; } + + public String getLocalTwoLanguage() + { + return localTwoLanguage; + } + + public void setLocalTwoLanguage(String localTwoLanguage) + { + this.localTwoLanguage = localTwoLanguage; + } + + public String getLocalOneLanguage() + { + return localOneLanguage; + } + + public void setLocalOneLanguage(String localOneLanguage) + { + this.localOneLanguage = localOneLanguage; + } + + public String getSourceLanguage() + { + return sourceLanguage; + } + + public void setSourceLanguage(String sourceLanguage) + { + this.sourceLanguage = sourceLanguage; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java index 61e27e10a..1407bec13 100644 --- a/src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java @@ -17,10 +17,8 @@ package org.asteriskjava.manager.event; /** - * Raised when two halves of a Local Channel have finished optimizing - * themselves out of the media path. - * - * Available since Asterisk 12 + * Raised when two halves of a Local Channel have finished optimizing themselves + * out of the media path. Available since Asterisk 12 */ public class LocalOptimizationEndEvent extends ManagerEvent { @@ -57,6 +55,9 @@ public class LocalOptimizationEndEvent extends ManagerEvent private String localTwoUniqueid; private String localTwoLinkedid; + private String localTwoLanguage; + private String localOneLanguage; + public LocalOptimizationEndEvent(Object source) { super(source); @@ -341,4 +342,25 @@ public void setLocalTwoLinkedid(String value) { this.localTwoLinkedid = value; } + + public String getLocalTwoLanguage() + { + return localTwoLanguage; + } + + public void setLocalTwoLanguage(String localTwoLanguage) + { + this.localTwoLanguage = localTwoLanguage; + } + + public String getLocalOneLanguage() + { + return localOneLanguage; + } + + public void setLocalOneLanguage(String localOneLanguage) + { + this.localOneLanguage = localOneLanguage; + } + } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BlindTransferEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BlindTransferEvent.java new file mode 100644 index 000000000..2e12b2e24 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BlindTransferEvent.java @@ -0,0 +1,327 @@ +package org.asteriskjava.pbx.asterisk.wrap.events; + +import java.util.Date; + +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class BlindTransferEvent extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + private static final Log logger = LogFactory.getLog(BlindTransferEvent.class); + + org.asteriskjava.manager.event.BlindTransferEvent rawEvent; + + private final Channel transfereeChannel; + + private final Channel transfererChannel; + + public BlindTransferEvent(final org.asteriskjava.manager.event.BlindTransferEvent event) throws InvalidChannelName + { + super(event); + rawEvent = event; + + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + this.transfereeChannel = pbx.internalRegisterChannel(event.getTransfereeChannel(), event.getTransfereeUniqueId()); + this.transfererChannel = pbx.internalRegisterChannel(event.getTransfererChannel(), event.getTransfererUniqueId()); + + } + + public String getBridgeUniqueId() + { + return rawEvent.getBridgeUniqueId(); + } + + public String getBridgeType() + { + return rawEvent.getBridgeType(); + } + + public Integer getBridgeNumChannels() + { + return rawEvent.getBridgeNumChannels(); + } + + public String getBridgeCreator() + { + return rawEvent.getBridgeCreator(); + } + + public String getBridgeName() + { + return rawEvent.getBridgeName(); + } + + public String getBridgeTechnology() + { + return rawEvent.getBridgeTechnology(); + } + + public String getCallerIdName() + { + return rawEvent.getCallerIdName(); + } + + public String getAccountCode() + { + return rawEvent.getAccountCode(); + } + + public String getBridgevideosourcemode() + { + return rawEvent.getBridgevideosourcemode(); + } + + public String getConnectedLineNum() + { + return rawEvent.getConnectedLineNum(); + } + + public String getConnectedLineName() + { + return rawEvent.getConnectedLineName(); + } + + public Integer getPriority() + { + return rawEvent.getPriority(); + } + + public Integer getChannelState() + { + return rawEvent.getChannelState(); + } + + public String getChannelStateDesc() + { + return rawEvent.getChannelStateDesc(); + } + + public String getExten() + { + return rawEvent.getExten(); + } + + public String getCallerIdNum() + { + return rawEvent.getCallerIdNum(); + } + + public String getContext() + { + return rawEvent.getContext(); + } + + public Date getDateReceived() + { + return rawEvent.getDateReceived(); + } + + public String getPrivilege() + { + return rawEvent.getPrivilege(); + } + + public String getExtension() + { + return rawEvent.getExtension(); + } + + public String getIsexternal() + { + return rawEvent.getIsexternal(); + } + + public String getResult() + { + return rawEvent.getResult(); + } + + public final String getServer() + { + return rawEvent.getServer(); + } + + public String getFile() + { + return rawEvent.getFile(); + } + + public Integer getLine() + { + return rawEvent.getLine(); + } + + public String getFunc() + { + return rawEvent.getFunc(); + } + + public Integer getSequenceNumber() + { + return rawEvent.getSequenceNumber(); + } + + public Object getSource() + { + return rawEvent.getSource(); + } + + public String getTransfererUniqueId() + { + return rawEvent.getTransfererUniqueId(); + } + + public String getTransfererConnectedLineNum() + { + return rawEvent.getTransfererConnectedLineNum(); + } + + public String getTransfererConnectedLineName() + { + return rawEvent.getTransfererConnectedLineName(); + } + + public String getTransfererCallerIdName() + { + return rawEvent.getTransfererCallerIdName(); + } + + public String getTransfererCallerIdNum() + { + return rawEvent.getTransfererCallerIdNum(); + } + + public Channel getTransfererChannel() + { + return transfererChannel; + } + + public String getTransfererChannelState() + { + return rawEvent.getTransfererChannelState(); + } + + public String getTransfererChannelStateDesc() + { + return rawEvent.getTransfererChannelStateDesc(); + } + + public Integer getTransfererPriority() + { + return rawEvent.getTransfererPriority(); + } + + public String getTransfererContext() + { + return rawEvent.getTransfererContext(); + } + + public String getTransfereeUniqueId() + { + return rawEvent.getTransfereeUniqueId(); + } + + public String getTransfereeConnectedLineNum() + { + return rawEvent.getTransfereeConnectedLineNum(); + } + + public String getTransfereeConnectedLineName() + { + return rawEvent.getTransfereeConnectedLineName(); + } + + public String getTransfereeCallerIdName() + { + return rawEvent.getTransfereeCallerIdName(); + } + + public String getTransfereeCallerIdNum() + { + return rawEvent.getTransfereeCallerIdNum(); + } + + public Channel getTransfereeChannel() + { + return transfereeChannel; + } + + public String getTransfereeChannelState() + { + return rawEvent.getTransfereeChannelState(); + } + + public String getTransfereeChannelStateDesc() + { + return rawEvent.getTransfereeChannelStateDesc(); + } + + public Integer getTransfereePriority() + { + return rawEvent.getTransfereePriority(); + } + + public final Double getTimestamp() + { + return rawEvent.getTimestamp(); + } + + public String getTransfereeContext() + { + return rawEvent.getTransfereeContext(); + } + + public String getTransfereeExten() + { + return rawEvent.getTransfereeExten(); + } + + public String getTransfereeLinkedId() + { + return rawEvent.getTransfereeLinkedId(); + } + + public String getTransfererAccountCode() + { + return rawEvent.getTransfererAccountCode(); + } + + public String getTransfererExten() + { + return rawEvent.getTransfererExten(); + } + + public String getTransfererLanguage() + { + return rawEvent.getTransfererLanguage(); + } + + public String getSystemName() + { + return rawEvent.getSystemName(); + } + + public String getTransfererLinkedId() + { + return rawEvent.getTransfererLinkedId(); + } + + public String getTransfereeLanguage() + { + return rawEvent.getTransfereeLanguage(); + } + + public String toString() + { + return rawEvent.toString(); + } + +} diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEndEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEndEvent.java new file mode 100644 index 000000000..49d5cc2d0 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEndEvent.java @@ -0,0 +1,263 @@ +package org.asteriskjava.pbx.asterisk.wrap.events; + +import java.util.Date; + +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class DialEndEvent extends ChannelEventHelper +{ + private static final long serialVersionUID = 1L; + + /** + * The name of the destination channel. + */ + private final Channel destChannel; + + final org.asteriskjava.manager.event.DialEndEvent rawEvent; + + public DialEndEvent(final org.asteriskjava.manager.event.DialEndEvent event) throws InvalidChannelName + { + super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + if (event.getDestination() != null) + this.destChannel = pbx.internalRegisterChannel(event.getDestChannel(), event.getDestUniqueId()); + else + this.destChannel = null; + + rawEvent = event; + + } + + public String getDestination() + { + return rawEvent.getDestination(); + } + + public String getLanguage() + { + return rawEvent.getLanguage(); + } + + public String getDestLanguage() + { + return rawEvent.getDestLanguage(); + } + + public String getAccountCode() + { + return rawEvent.getAccountCode(); + } + + public String getDestAccountCode() + { + return rawEvent.getDestAccountCode(); + } + + public String getDestLinkedId() + { + return rawEvent.getDestLinkedId(); + } + + public String getLinkedId() + { + return rawEvent.getLinkedId(); + } + + public String getForward() + { + return rawEvent.getForward(); + } + + public String getCallerIdName() + { + return rawEvent.getCallerIdName(); + } + + public String getConnectedLineNum() + { + return rawEvent.getConnectedLineNum(); + } + + public String getConnectedLineName() + { + return rawEvent.getConnectedLineName(); + } + + public Integer getPriority() + { + return rawEvent.getPriority(); + } + + public Integer getChannelState() + { + return rawEvent.getChannelState(); + } + + public String getChannelStateDesc() + { + return rawEvent.getChannelStateDesc(); + } + + public String getExten() + { + return rawEvent.getExten(); + } + + public String getCallerIdNum() + { + return rawEvent.getCallerIdNum(); + } + + public String getContext() + { + return rawEvent.getContext(); + } + + public String getSubEvent() + { + return rawEvent.getSubEvent(); + } + + public Date getDateReceived() + { + return rawEvent.getDateReceived(); + } + + @SuppressWarnings("deprecation") + public String getSrc() + { + return rawEvent.getSrc(); + } + + public String getPrivilege() + { + return rawEvent.getPrivilege(); + } + + public final Double getTimestamp() + { + return rawEvent.getTimestamp(); + } + + public Channel getDestChannel() + { + return destChannel; + } + + @SuppressWarnings("deprecation") + public String getCallerId() + { + return rawEvent.getCallerId(); + } + + public final String getServer() + { + return rawEvent.getServer(); + } + + public String getUniqueId() + { + return rawEvent.getUniqueId(); + } + + public String getSystemName() + { + return rawEvent.getSystemName(); + } + + @SuppressWarnings("deprecation") + public String getSrcUniqueId() + { + return rawEvent.getSrcUniqueId(); + } + + public String getFile() + { + return rawEvent.getFile(); + } + + public String getDestUniqueId() + { + return rawEvent.getDestUniqueId(); + } + + public Integer getLine() + { + return rawEvent.getLine(); + } + + public String getDialString() + { + return rawEvent.getDialString(); + } + + public String getDialStatus() + { + return rawEvent.getDialStatus(); + } + + public String getFunc() + { + return rawEvent.getFunc(); + } + + public Integer getSequenceNumber() + { + return rawEvent.getSequenceNumber(); + } + + public Integer getDestChannelState() + { + return rawEvent.getDestChannelState(); + } + + public String getDestContext() + { + return rawEvent.getDestContext(); + } + + public Integer getDestPriority() + { + return rawEvent.getDestPriority(); + } + + public String getDestChannelStateDesc() + { + return rawEvent.getDestChannelStateDesc(); + } + + public String getDestExten() + { + return rawEvent.getDestExten(); + } + + public String getDestConnectedLineName() + { + return rawEvent.getDestConnectedLineName(); + } + + public String getDestConnectedLineNum() + { + return rawEvent.getDestConnectedLineNum(); + } + + public String getDestCallerIdName() + { + return rawEvent.getDestCallerIdName(); + } + + public String getDestCallerIdNum() + { + return rawEvent.getDestCallerIdNum(); + } + + public Object getSource() + { + return rawEvent.getSource(); + } + +} From 594782f0371f2d3af201c826b1aa30742e848923 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 22 Jan 2019 16:17:35 +1100 Subject: [PATCH 231/802] added channelId and otherChannelId to originate action --- .../manager/action/OriginateAction.java | 28 +++++++++++++++++++ .../wrap/actions/OriginateAction.java | 17 +++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java index 6ce73bf81..4d3ab62c3 100644 --- a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java +++ b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java @@ -77,6 +77,9 @@ public class OriginateAction extends AbstractManagerAction implements EventGener private String codecs; private Boolean earlyMedia; + private String channelId; + private String otherChannelId; + // starting at ten saves on a formatter. private int headerCounter = 10; private Set preventDuplicateSipHeaders = new HashSet<>(); @@ -591,4 +594,29 @@ public void addPjSipHeader(VariableInheritance inheritance, String header) } } + /** + * this will be the channels uniqueID + * + * @param channelId + */ + public void setChannelId(String channelId) + { + this.channelId = channelId; + } + + public String getChannelId() + { + return channelId; + } + + public void setOtherChannelId(String otherChannelId) + { + this.otherChannelId = otherChannelId; + } + + public String getOtherChannelId() + { + return otherChannelId; + } + } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java index 4f54b84a0..2c507d8b5 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java @@ -36,6 +36,9 @@ public class OriginateAction extends AbstractManagerAction private long _timeout; + private String channelId; + private String otherChannelId; + public OriginateAction() { } @@ -68,6 +71,9 @@ public org.asteriskjava.manager.action.ManagerAction getAJAction() action.setAsync(this._async); action.setTimeout(this._timeout); + action.setChannelId(channelId); + action.setOtherChannelId(otherChannelId); + return action; } @@ -144,4 +150,15 @@ public void setTimeout(final long timeout) this._timeout = timeout; } + + public void setChannelId(String channelId) + { + this.channelId = channelId; + } + + public void setOtherChannelId(String otherChannelId) + { + this.otherChannelId = otherChannelId; + } + } From 5c23310b37212d885e94dda1fbb9b576cc6e3c8b Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 22 Jan 2019 16:20:11 +1100 Subject: [PATCH 232/802] add wrapped DialBeginEvent --- .../asterisk/wrap/events/DialBeginEvent.java | 253 ++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialBeginEvent.java diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialBeginEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialBeginEvent.java new file mode 100644 index 000000000..0585813d0 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialBeginEvent.java @@ -0,0 +1,253 @@ +package org.asteriskjava.pbx.asterisk.wrap.events; + +import java.util.Date; + +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.InvalidChannelName; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; + +public class DialBeginEvent extends ChannelEventHelper +{ + private static final long serialVersionUID = 1L; + + /** + * The name of the destination channel. + */ + private final Channel destChannel; + + final org.asteriskjava.manager.event.DialBeginEvent rawEvent; + + public DialBeginEvent(final org.asteriskjava.manager.event.DialBeginEvent event) throws InvalidChannelName + { + super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); + + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + if (event.getDestination() != null) + this.destChannel = pbx.internalRegisterChannel(event.getDestChannel(), event.getDestUniqueId()); + else + this.destChannel = null; + + rawEvent = event; + + } + + public String getDestination() + { + return rawEvent.getDestination(); + } + + public String getLanguage() + { + return rawEvent.getLanguage(); + } + + public String getDestLanguage() + { + return rawEvent.getDestLanguage(); + } + + public String getDestAccountCode() + { + return rawEvent.getDestAccountCode(); + } + + public String getDestLinkedId() + { + return rawEvent.getDestLinkedId(); + } + + public String getLinkedId() + { + return rawEvent.getLinkedId(); + } + + public String getCallerIdName() + { + return rawEvent.getCallerIdName(); + } + + public String getConnectedLineNum() + { + return rawEvent.getConnectedLineNum(); + } + + public String getConnectedLineName() + { + return rawEvent.getConnectedLineName(); + } + + public Integer getPriority() + { + return rawEvent.getPriority(); + } + + public Integer getChannelState() + { + return rawEvent.getChannelState(); + } + + public String getChannelStateDesc() + { + return rawEvent.getChannelStateDesc(); + } + + public String getExten() + { + return rawEvent.getExten(); + } + + public String getCallerIdNum() + { + return rawEvent.getCallerIdNum(); + } + + public String getContext() + { + return rawEvent.getContext(); + } + + public String getSubEvent() + { + return rawEvent.getSubEvent(); + } + + public Date getDateReceived() + { + return rawEvent.getDateReceived(); + } + + @SuppressWarnings("deprecation") + public String getSrc() + { + return rawEvent.getSrc(); + } + + public String getPrivilege() + { + return rawEvent.getPrivilege(); + } + + public final Double getTimestamp() + { + return rawEvent.getTimestamp(); + } + + public Channel getDestChannel() + { + return destChannel; + } + + @SuppressWarnings("deprecation") + public String getCallerId() + { + return rawEvent.getCallerId(); + } + + public final String getServer() + { + return rawEvent.getServer(); + } + + public String getUniqueId() + { + return rawEvent.getUniqueId(); + } + + public String getSystemName() + { + return rawEvent.getSystemName(); + } + + @SuppressWarnings("deprecation") + public String getSrcUniqueId() + { + return rawEvent.getSrcUniqueId(); + } + + public String getFile() + { + return rawEvent.getFile(); + } + + public String getDestUniqueId() + { + return rawEvent.getDestUniqueId(); + } + + public Integer getLine() + { + return rawEvent.getLine(); + } + + public String getDialString() + { + return rawEvent.getDialString(); + } + + public String getDialStatus() + { + return rawEvent.getDialStatus(); + } + + public String getFunc() + { + return rawEvent.getFunc(); + } + + public Integer getSequenceNumber() + { + return rawEvent.getSequenceNumber(); + } + + public Integer getDestChannelState() + { + return rawEvent.getDestChannelState(); + } + + public String getDestContext() + { + return rawEvent.getDestContext(); + } + + public Integer getDestPriority() + { + return rawEvent.getDestPriority(); + } + + public String getDestChannelStateDesc() + { + return rawEvent.getDestChannelStateDesc(); + } + + public String getDestExten() + { + return rawEvent.getDestExten(); + } + + public String getDestConnectedLineName() + { + return rawEvent.getDestConnectedLineName(); + } + + public String getDestConnectedLineNum() + { + return rawEvent.getDestConnectedLineNum(); + } + + public String getDestCallerIdName() + { + return rawEvent.getDestCallerIdName(); + } + + public String getDestCallerIdNum() + { + return rawEvent.getDestCallerIdNum(); + } + + public Object getSource() + { + return rawEvent.getSource(); + } + +} From 3e93d50ead6d189c49ab66efd888f908cce67de4 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 22 Jan 2019 16:31:11 +1100 Subject: [PATCH 233/802] update OrignateBaseClass to leverage OriginateAction.setChannelId --- .../internal/core/DialLocalToAgiActivity.java | 4 - .../managerAPI/OriginateBaseClass.java | 311 +++--------------- 2 files changed, 52 insertions(+), 263 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java index 5787084d7..bec7f02bd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -21,7 +21,6 @@ import org.asteriskjava.pbx.agi.ActivityArrivalListener; import org.asteriskjava.pbx.asterisk.wrap.actions.OriginateAction; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; -import org.asteriskjava.pbx.internal.managerAPI.OriginateBaseClass; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -32,7 +31,6 @@ public class DialLocalToAgiActivity implements Runnable, Activity private CallerID fromCallerID; private Thread thread; private final Log logger = LogFactory.getLog(this.getClass()); - private String originateId; CountDownLatch latch = new CountDownLatch(1); private List channels = new LinkedList<>(); @@ -70,11 +68,9 @@ public void run() originate.setPriority(1); originate.setCallerId(fromCallerID); originate.setTimeout(30000); - originateId = originate.getActionId(); Map myVars = new HashMap<>(); - myVars.put("__" + OriginateBaseClass.NJR_ORIGINATE_ID, this.originateId); if (channelVarsToSet != null) { myVars.putAll(channelVarsToSet); diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 95bc60486..0974973e2 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -1,18 +1,12 @@ package org.asteriskjava.pbx.internal.managerAPI; -import java.io.IOException; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; import org.asteriskjava.live.ManagerCommunicationException; -import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; @@ -21,9 +15,10 @@ import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXException; import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.asterisk.wrap.actions.GetVarAction; import org.asteriskjava.pbx.asterisk.wrap.actions.OriginateAction; import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.DialBeginEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.DialEndEvent; import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; @@ -38,9 +33,6 @@ public abstract class OriginateBaseClass extends EventListenerBaseClass { - // Used to set a - public static final String NJR_ORIGINATE_ID = "njrOriginateID"; - /* * this class generates and issues ActionEvents to asterisk through the * manager. This is the asterisk coal face. @@ -83,6 +75,8 @@ public abstract class OriginateBaseClass extends EventListenerBaseClass private final AsteriskPBX pbx; + private String channelId; + protected OriginateBaseClass(final NewChannelListener listener, final Channel monitor, final Channel monitor2) { super("NewOrginateClass", PBXFactory.getActivePBX()); @@ -94,6 +88,8 @@ protected OriginateBaseClass(final NewChannelListener listener, final Channel mo } + private static final AtomicLong originateSeed = new AtomicLong(); + /** * @param local * @param target @@ -126,9 +122,8 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has final OriginateAction originate = new OriginateAction(); this.originateID = originate.getActionId(); - // the double under score "__" is to cause the variable to propagate - // forward to the new channel when using local/ - myVars.put("__" + OriginateBaseClass.NJR_ORIGINATE_ID, this.originateID); + channelId = "" + (System.currentTimeMillis() / 1000) + ".AJ" + originateSeed.incrementAndGet(); + originate.setChannelId(channelId); Integer localTimeout = timeout; @@ -278,6 +273,8 @@ void abort(final String reason) required.add(UnlinkEvent.class); required.add(HangupEvent.class); required.add(NewChannelEvent.class); + required.add(DialEndEvent.class); + required.add(DialBeginEvent.class); return required; } @@ -296,7 +293,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) final HangupEvent hangupEvt = (HangupEvent) event; final Channel hangupChannel = hangupEvt.getChannel(); - if ((this.newChannel != null) && (hangupChannel.isSame(this.newChannel))) + if (channelId.equals(hangupEvt.getUniqueId())) { this.originateSuccess = false; OriginateBaseClass.logger.warn("Dest channel " + this.newChannel + " hungup after answer"); //$NON-NLS-2$ @@ -372,7 +369,10 @@ synchronized public void onManagerEvent(final ManagerEvent event) if (originateSuccess) { - this.newChannel = response.getChannel(); + if (newChannel == null) + { + this.newChannel = response.getChannel(); + } channelSeen = newChannel != null; // if we have also seen the channel then we can notify @@ -383,7 +383,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) // notify. if (this.channelSeen == true) { - OriginateBaseClass.logger.debug("notify originate response event 305 " + this.originateSuccess); + OriginateBaseClass.logger.info("notify originate response event " + this.originateSuccess); originateLatch.countDown(); } else @@ -399,41 +399,20 @@ synchronized public void onManagerEvent(final ManagerEvent event) } } - // Look for the channel events that tell us that both sides of the - // call - // are up. - // We will see a number of channels come up as the call progresses. - // The LOCAL/ channels are just internal workings of Asterisk so we - // need - // to ignore these. if (event instanceof NewChannelEvent) { final NewChannelEvent newState = (NewChannelEvent) event; - final Channel channel = newState.getChannel(); - - OriginateBaseClass.logger.debug("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-2$ - + " state =" + newState.getChannelStateDesc() + " state =" + newState.getChannelState()); //$NON-NLS-2$ - - // Now try to get the NJR_ORIGINATE_ID's value to see if this is - // an - // event for our channel - // If it is for our channel then the NJR_ORIGINATE_ID will match - // our - // originateID. - // We need to try several times as it can take some time to - // appear - // within asterisk. - - getChannelsOriginateId(channel); + if (channelId.equalsIgnoreCase(newState.getChannel().getUniqueId())) + { + final Channel channel = newState.getChannel(); + + OriginateBaseClass.logger.debug("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-2$ + + " state =" + newState.getChannelStateDesc() + " state =" + newState.getChannelState()); //$NON-NLS-2$ + + handleId(channel); + } } - // Look for the channel events that tell us that both sides of the - // call - // are up. - // We will see a number of channels come up as the call progresses. - // The LOCAL/ channels are just internal workings of Asterisk so we - // need - // to ignore these. if (event instanceof BridgeEvent) { if (((BridgeEvent) event).isLink()) @@ -444,244 +423,58 @@ synchronized public void onManagerEvent(final ManagerEvent event) { channel = bridgeEvent.getChannel2(); } - - OriginateBaseClass.logger.debug("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ - + " channel2 =" + bridgeEvent.getChannel2()); - - getChannelsOriginateId(channel); - } - - } - - } - - private final static Object sync = new Object(); - private final static Map channelToWorkerLruMap = new LinkedHashMap<>(); - private final static ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(10); - - /** - * Now try to get the NJR_ORIGINATE_ID's value to see if this is an event - * for our channel. If it is for our channel then the NJR_ORIGINATE_ID will - * match our originateID. We need to try several times as it can take some - * time to appear within asterisk.
    - *
    - * A job will be scheduled to do the lookup so as to avoid stalling the - * ManagerEventQueue. Subsequent calls to this method for the same channel - * will have their request added to the same job. - * - * @param channel - */ - void getChannelsOriginateId(final Channel channel) - { - Worker worker; - synchronized (sync) - { - // remove the item from the cache - worker = channelToWorkerLruMap.remove(channel.getChannelName()); - if (worker == null) - { - worker = new Worker(channel); - } - // add the item at the tail of the cache list - channelToWorkerLruMap.put(channel.getChannelName(), worker); - if (channelToWorkerLruMap.size() > 500) - { - // if the cache is too large remove the head of the cache list - - // it should be the least recently used item - String keyToRemove = channelToWorkerLruMap.keySet().iterator().next(); - channelToWorkerLruMap.remove(keyToRemove); - logger.info("Removing future for " + keyToRemove + " when handling " + channel + " cache size is " - + channelToWorkerLruMap.size()); - } - } - worker.addListener(new WorkerCallback() - { - boolean done = false; - private final Object workerCallbackSync = new Object(); - - @Override - public void handleResult(String workResult) - { - synchronized (workerCallbackSync) + if (channelId.equalsIgnoreCase(bridgeEvent.getChannel1().getUniqueId()) + || channelId.equalsIgnoreCase(bridgeEvent.getChannel2().getUniqueId())) { - if (!done) - { - handleId(channel, workResult); - done = true; - } - else - { - logger.error("This should never happen, handle result called twice " + channel); - } - } - } - }); - } - Runnable getTimelinessChecker(long expectedMs, final Runnable task) - { - final long expected = System.currentTimeMillis() + expectedMs + 100; - return new Runnable() - { + OriginateBaseClass.logger + .debug("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ + + " channel2 =" + bridgeEvent.getChannel2()); - @Override - public void run() - { - if (System.currentTimeMillis() > expected) - { - logger.error("Timeliness problem, task is late by " + (System.currentTimeMillis() - expected) + "ms"); + handleId(channel); } - task.run(); } - }; - - } - - public interface WorkerCallback - { - void handleResult(String workResult); - } - - class Worker implements Runnable - { - List listeners = new LinkedList<>(); - final private Channel channel; - int ctr = 0; - private final Object workerSync = new Object(); - - String channelsOriginateId = null; - - Worker(Channel channel) - { - this.channel = channel; - scheduler.execute(getTimelinessChecker(0, this)); - } - - void addListener(final WorkerCallback listener) - { - synchronized (workerSync) - { - if (channelsOriginateId != null) - { - // on worker thread for consistency - scheduler.execute(getTimelinessChecker(0, new Runnable() - { - @Override - public void run() - { - listener.handleResult(channelsOriginateId); - } - })); - } - else - { - listeners.add(listener); - } - } } - @Override - public void run() + if (event instanceof DialEndEvent) { - try + if (channelId.equalsIgnoreCase(((DialEndEvent) event).getDestChannel().getUniqueId())) { - String tmp = internalGetChannelOriginateId(channel); - - synchronized (workerSync) + String forward = ((DialEndEvent) event).getForward(); + if (forward != null && forward.length() > 0) { - channelsOriginateId = tmp; - - boolean moreTriesRemain = ctr++ < 5; - if (channelsOriginateId == null) - { - if (moreTriesRemain) - { - logger.warn( - "Rescheduling checkBridge for " + channel + ", looking for originateID:" + originateID); - scheduler.schedule(getTimelinessChecker(100, this), 100, TimeUnit.MILLISECONDS); - } - else - { - channelsOriginateId = ""; - } - } - if (channelsOriginateId != null) - { - for (WorkerCallback listener : listeners) - { - listener.handleResult(channelsOriginateId); - } - listeners.clear(); - } + originateLatch.countDown(); } } - catch (Exception e) - { - logger.error(e, e); - } - } } - private String internalGetChannelOriginateId(Channel channel) - throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException + private void handleId(Channel channel) { - logger.info("trying to get id from asterisk"); - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - final GetVarAction var = new GetVarAction(channel, OriginateBaseClass.NJR_ORIGINATE_ID); - final ManagerResponse response = pbx.sendAction(var, 500); - if (response.isSuccess()) + if ((this.newChannel == null) && !channel.isLocal()) { - String __originateID = response.getAttribute("value"); + this.newChannel = channel; + this.channelSeen = true; - if (__originateID != null && __originateID.length() > 0) + OriginateBaseClass.logger.info("new channel name " + channel); + if (this.listener != null) { - logger.info("Got id of " + __originateID); - return __originateID; + /* + * Update the phone channel to allow the call to be cancelled + * before it's answered. + */ + this.listener.channelUpdate(channel); } - return null; - } - logger.warn("Giving up because: " + response.getResponse()); - return ""; - } - private void handleId(Channel channel, String __originateID) - { - if (__originateID != null) - { - // Check if the event is for our channel by checking - // the - // originateIDs match. - if ((this.originateID != null) && (__originateID.compareToIgnoreCase(this.originateID) == 0)) + if (this.originateSeen == true) { - if ((this.newChannel == null) && !channel.isLocal()) - { - this.newChannel = channel; - this.channelSeen = true; - - OriginateBaseClass.logger.debug("new channel name " + channel); - if (this.listener != null) - { - /* - * sometimes it's not actually the NJR phone we're - * originating. Otherwise update the NJR phone channel - * to allow the call to be cancelled before it's - * answered. - */ - this.listener.channelUpdate(channel); - } - - if (this.originateSeen == true) - { - OriginateBaseClass.logger.debug("notifying success 362"); - originateLatch.countDown(); - } - } - logger.debug("Id is " + __originateID); + OriginateBaseClass.logger.debug("notifying success 362"); + originateLatch.countDown(); } } + } } From b8184957678bd38656c89a198c01782417ce0918 Mon Sep 17 00:00:00 2001 From: YangChihLin Date: Wed, 23 Jan 2019 00:32:44 +0800 Subject: [PATCH 234/802] exten and context already defined in super class and decorated with protected keyword, also remove getter / setter --- .../asteriskjava/manager/event/CelEvent.java | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/CelEvent.java b/src/main/java/org/asteriskjava/manager/event/CelEvent.java index 1c1873d45..af872505c 100644 --- a/src/main/java/org/asteriskjava/manager/event/CelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/CelEvent.java @@ -29,8 +29,6 @@ public class CelEvent extends ManagerEvent private String callerIDani; private String callerIDrdnis; private String callerIDdnid; - private String exten; - private String context; private String application; private String appData; private String eventTime; @@ -98,26 +96,6 @@ public void setCallerIDdnid(String callerIDdnid) this.callerIDdnid = callerIDdnid; } - public String getExten() - { - return exten; - } - - public void setExten(String exten) - { - this.exten = exten; - } - - public String getContext() - { - return context; - } - - public void setContext(String context) - { - this.context = context; - } - public String getApplication() { return application; From 624ba31332f3e5f52b5e52c31d990fb2fe0b1208 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 23 Jan 2019 16:27:04 +1100 Subject: [PATCH 235/802] removed duplicated event member fields --- .../manager/event/HangupEvent.java | 25 +++++---------- .../asteriskjava/manager/event/JoinEvent.java | 12 ++++--- .../manager/event/ParkedCallEvent.java | 32 +++---------------- .../manager/event/StatusEvent.java | 22 ------------- 4 files changed, 19 insertions(+), 72 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/HangupEvent.java b/src/main/java/org/asteriskjava/manager/event/HangupEvent.java index fa54fab92..cccacb909 100644 --- a/src/main/java/org/asteriskjava/manager/event/HangupEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/HangupEvent.java @@ -17,7 +17,8 @@ package org.asteriskjava.manager.event; /** - * A HangupEvent is triggered when a channel is hung up.

    + * A HangupEvent is triggered when a channel is hung up. + *

    * It is implemented in channel.c * * @author srt @@ -34,8 +35,7 @@ public class HangupEvent extends AbstractChannelStateEvent private String causeTxt; private String language; private String linkedId; - private String connectedlinenum; - + public HangupEvent(Object source) { super(source); @@ -43,14 +43,14 @@ public HangupEvent(Object source) public String getLanguage() { - return language; + return language; } - + public void setLanguage(String language) { - this.language = language; - } - + this.language = language; + } + /** * Returns the cause of the hangup. * @@ -122,13 +122,4 @@ public String toString() return builder.toString(); } - public String getConnectedlinenum() - { - return connectedlinenum; - } - - public void setConnectedlinenum(String connectedlinenum) - { - this.connectedlinenum = connectedlinenum; - } } diff --git a/src/main/java/org/asteriskjava/manager/event/JoinEvent.java b/src/main/java/org/asteriskjava/manager/event/JoinEvent.java index b9fef7d76..b626dcbaa 100644 --- a/src/main/java/org/asteriskjava/manager/event/JoinEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/JoinEvent.java @@ -17,7 +17,8 @@ package org.asteriskjava.manager.event; /** - * A JoinEvent is triggered when a channel joines a queue.

    + * A JoinEvent is triggered when a channel joines a queue. + *

    * It is implemented in apps/app_queue.c * * @author srt @@ -29,7 +30,6 @@ public class JoinEvent extends QueueEvent */ static final long serialVersionUID = 0L; - protected String callerIdNum; protected String callerIdName; protected Integer position; @@ -45,7 +45,8 @@ public JoinEvent(Object source) * @return the Caller*ID number of the channel that joined the queue * @deprecated since 1.0.0, use {@link #getCallerIdNum()} instead. */ - @Deprecated public String getCallerId() + @Deprecated + public String getCallerId() { return callerIdNum; } @@ -53,7 +54,8 @@ public JoinEvent(Object source) /** * Sets the Caller*ID number of the channel that joined the queue. * - * @param callerId the Caller*ID number of the channel that joined the queue. + * @param callerId the Caller*ID number of the channel that joined the + * queue. */ public void setCallerId(String callerId) { @@ -75,5 +77,5 @@ public void setPosition(Integer position) { this.position = position; } - + } diff --git a/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java b/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java index 3420473c0..b8c681d08 100644 --- a/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java @@ -34,8 +34,6 @@ public class ParkedCallEvent extends AbstractParkedCallEvent private static final long serialVersionUID = 0L; private Integer timeout; - private String connectedlinenum; - private String connectedlinename; private String parkeelinkedid; /** @@ -74,42 +72,20 @@ public void setUnqiueId(String unqiueId) setUniqueId(unqiueId); } - - public String getConnectedLinenum() - { - return connectedlinenum; - } - - - public void setConnectedLinenum(String connectedlinenum) - { - this.connectedlinenum = connectedlinenum; - } - - public String getConnectedLinename() - { - return connectedlinename; - } - - - public void setConnectedLinename(String connectedlinename) - { - this.connectedlinename = connectedlinename; - } - /** * @param parkeelinkedid the parkeelinkedid to set */ - public void setParkeelinkedid(String parkeelinkedid) { + public void setParkeelinkedid(String parkeelinkedid) + { this.parkeelinkedid = parkeelinkedid; } /** * @return the parkeelinkedid */ - public String getParkeelinkedid() { + public String getParkeelinkedid() + { return parkeelinkedid; } - } diff --git a/src/main/java/org/asteriskjava/manager/event/StatusEvent.java b/src/main/java/org/asteriskjava/manager/event/StatusEvent.java index 075fab112..be7009575 100644 --- a/src/main/java/org/asteriskjava/manager/event/StatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/StatusEvent.java @@ -55,8 +55,6 @@ public class StatusEvent extends ResponseEvent private String writetrans; private String bridgeId; private String readtrans; - private String connectedlinename; - private String connectedlinenum; private String language; public StatusEvent(Object source) @@ -512,26 +510,6 @@ public void setReadtrans(String readtrans) this.readtrans = readtrans; } - public String getConnectedlinename() - { - return connectedlinename; - } - - public void setConnectedlinename(String connectedlinename) - { - this.connectedlinename = connectedlinename; - } - - public String getConnectedlinenum() - { - return connectedlinenum; - } - - public void setConnectedlinenum(String connectedlinenum) - { - this.connectedlinenum = connectedlinenum; - } - public String getLanguage() { return language; From cbfaf57ea64f933607ff1ee921f49f698bfe04ba Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 23 Jan 2019 16:27:54 +1100 Subject: [PATCH 236/802] clean up some possible NPE's --- .../java/org/asteriskjava/util/ReflectionUtil.java | 14 ++++++++------ .../org/asteriskjava/fastagi/SimpleAgiRequest.java | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/ReflectionUtil.java b/src/main/java/org/asteriskjava/util/ReflectionUtil.java index 64eebc6be..ca9d4f5f9 100644 --- a/src/main/java/org/asteriskjava/util/ReflectionUtil.java +++ b/src/main/java/org/asteriskjava/util/ReflectionUtil.java @@ -362,13 +362,15 @@ private static Set getClassNamesFromPackage(String packageName) throws I File folder = new File(uri.getPath()); // won't work with path which contains blank (%20) // File folder = new File(packageURL.getFile()); - File[] contenuti = folder.listFiles(); - String entryName; - for (File actual : contenuti) + File[] files = folder.listFiles(); + if (files != null) { - entryName = actual.getName(); - entryName = entryName.substring(0, entryName.lastIndexOf('.')); - names.add(entryName); + for (File actual : files) + { + String entryName = actual.getName(); + entryName = entryName.substring(0, entryName.lastIndexOf('.')); + names.add(entryName); + } } } } diff --git a/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java b/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java index fdf132eef..1d1cd65e5 100644 --- a/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java +++ b/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java @@ -28,7 +28,7 @@ public class SimpleAgiRequest implements AgiRequest InetAddress remoteAddress; int remotePort; private String script; - private AsteriskVersion asteriskVersion; + private AsteriskVersion asteriskVersion = AsteriskVersion.ASTERISK_13; public SimpleAgiRequest() { From 50c63e253de93787faeaa1895b59f7d0b64d4190 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 24 Jan 2019 11:00:15 +1100 Subject: [PATCH 237/802] clean up some logging --- .../pbx/internal/activity/DialToAgiActivityImpl.java | 2 +- .../pbx/internal/managerAPI/OriginateBaseClass.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index f25ea6ffc..071be8c2c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -94,7 +94,7 @@ public boolean doActivity() throws PBXException if (!this.cancelledByOperator) { this.setLastException(new PBXException(("OperatorEndedCall"))); - logger.warn("dialout to failed."); + logger.warn("dialout to " + _originating + " failed."); } } else diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 0974973e2..e6fa83a9d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -215,7 +215,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has } else { - OriginateBaseClass.logger.warn("originate failed connecting endPoint: " + local + " to ext " + target); //$NON-NLS-2$ + OriginateBaseClass.logger.warn("originate failed to connect endPoint: " + local + " to ext " + target); //$NON-NLS-2$ if (this.newChannel != null) { @@ -296,7 +296,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) if (channelId.equals(hangupEvt.getUniqueId())) { this.originateSuccess = false; - OriginateBaseClass.logger.warn("Dest channel " + this.newChannel + " hungup after answer"); //$NON-NLS-2$ + OriginateBaseClass.logger.warn("Dest channel " + this.newChannel + " hungup"); originateLatch.countDown(); } if ((this.monitorChannel1 != null) && (hangupChannel.isSame(this.monitorChannel1))) From 3576c01ffefa9cbb228f8cd28f25b555cfb83599 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 31 Jan 2019 09:44:31 +1100 Subject: [PATCH 238/802] update readme to reflect new build in repo --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index b048bbf07..db61ef3e5 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,28 @@ Asterisk-Java is available from [here](https://github.com/asterisk-java/asterisk Maven Dependency ---------------- + +Asterisk-Java 2.0.4 + + + + asterisk-java-mvn-repo + https://raw.githubusercontent.com/asterisk-java/asterisk-java/mvn-repo + + true + + + true + + + + + + org.asteriskjava + asterisk-java + 2.0.4 + + Asterisk-Java 2.0.3 From dda71206daf6938c6972992daac694cae9ec82c5 Mon Sep 17 00:00:00 2001 From: Adrien Martin Date: Tue, 25 Sep 2018 11:33:23 +0200 Subject: [PATCH 239/802] Allow configuration of SO_TIMEOUT in AgiServer and default value changed to 3 hours DefaultAgiServer use indirectly SocketConnectionFacade which has a default timeout of 4200s. This timeout is triggered on long AGI calls like Dial. Infinite timeout is possible with -1 value but not recommended (no keep-alive protection). --- .../org/asteriskjava/fastagi/AgiServer.java | 10 ++++++++ .../fastagi/DefaultAgiServer.java | 18 +++++++++++++- .../asteriskjava/util/ServerSocketFacade.java | 10 ++++++++ .../util/internal/ServerSocketFacadeImpl.java | 11 +++++++-- .../internal/SocketConnectionFacadeImpl.java | 24 ++++++++++++++++--- .../fastagi/DefaultAgiServerTest.java | 4 ++++ 6 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/AgiServer.java b/src/main/java/org/asteriskjava/fastagi/AgiServer.java index c5a0261bb..8fe7aff1e 100644 --- a/src/main/java/org/asteriskjava/fastagi/AgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiServer.java @@ -73,4 +73,14 @@ public interface AgiServer * has not yet been started. */ void shutdown() throws IllegalStateException; + + /** + * Connection is dropped if it stales on read longer than the timeout. + * + * @param socketReadTimeout the read timeout value to be used in + * milliseconds. + * @see java.net.Socket#setSoTimeout(int) + * @since 3.0.0 + */ + public void setSocketReadTimeout(int socketReadTimeout); } diff --git a/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java b/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java index 82dd06ef5..7b4088a6b 100644 --- a/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java @@ -31,6 +31,7 @@ import org.asteriskjava.util.ServerSocketFacade; import org.asteriskjava.util.SocketConnectionFacade; import org.asteriskjava.util.internal.ServerSocketFacadeImpl; +import org.asteriskjava.util.internal.SocketConnectionFacadeImpl; /** * Default implementation of the {@link org.asteriskjava.fastagi.AgiServer} @@ -62,6 +63,14 @@ public class DefaultAgiServer extends AbstractAgiServer implements AgiServer private int port = DEFAULT_BIND_PORT; private InetAddress address = null; + /** + * Closes the connection if no input has been read for the + * given amount of milliseconds. + * + * @see Socket#setSoTimeout(int) + */ + private int socketReadTimeout = SocketConnectionFacadeImpl.MAX_SOCKET_READ_TIMEOUT_MILLIS; + /** * Creates a new DefaultAgiServer. */ @@ -295,9 +304,16 @@ private void loadConfig() } } + public void setSocketReadTimeout(int socketReadTimeout) + { + this.socketReadTimeout = socketReadTimeout; + } + protected ServerSocketFacade createServerSocket() throws IOException { - return new ServerSocketFacadeImpl(port, BACKLOG, address); + ServerSocketFacade serverSocketFacade = new ServerSocketFacadeImpl(port, BACKLOG, address); + serverSocketFacade.setSocketReadTimeout(socketReadTimeout); + return serverSocketFacade; } public void startup() throws IOException, IllegalStateException diff --git a/src/main/java/org/asteriskjava/util/ServerSocketFacade.java b/src/main/java/org/asteriskjava/util/ServerSocketFacade.java index 196602ea2..dcb90d1e3 100644 --- a/src/main/java/org/asteriskjava/util/ServerSocketFacade.java +++ b/src/main/java/org/asteriskjava/util/ServerSocketFacade.java @@ -43,4 +43,14 @@ public interface ServerSocketFacade * @throws IOException if the server socket cannot be closed. */ void close() throws IOException; + + /** + * Connection is dropped if it stales on read longer than the timeout. + * + * @param socketReadTimeout the read timeout value to be used in + * milliseconds. + * @see java.net.Socket#setSoTimeout(int) + * @since 3.0.0 + */ + public void setSocketReadTimeout(int socketReadTimeout); } diff --git a/src/main/java/org/asteriskjava/util/internal/ServerSocketFacadeImpl.java b/src/main/java/org/asteriskjava/util/internal/ServerSocketFacadeImpl.java index a947ba014..5d9bbc64f 100644 --- a/src/main/java/org/asteriskjava/util/internal/ServerSocketFacadeImpl.java +++ b/src/main/java/org/asteriskjava/util/internal/ServerSocketFacadeImpl.java @@ -28,7 +28,7 @@ /** * Default implementation of the ServerSocketFacade interface using standard * java.io classes (ServerSocket in this case). - * + * * @author srt * @version $Id$ */ @@ -36,6 +36,8 @@ public class ServerSocketFacadeImpl implements ServerSocketFacade { private ServerSocket serverSocket; + private int socketReadTimeout = SocketConnectionFacadeImpl.MAX_SOCKET_READ_TIMEOUT_MILLIS; + public ServerSocketFacadeImpl(int port, int backlog, InetAddress bindAddress) throws IOException { @@ -48,11 +50,16 @@ public SocketConnectionFacade accept() throws IOException socket = serverSocket.accept(); - return new SocketConnectionFacadeImpl(socket); + return new SocketConnectionFacadeImpl(socket, socketReadTimeout); } public void close() throws IOException { serverSocket.close(); } + + public void setSocketReadTimeout(int socketReadTimeout) + { + this.socketReadTimeout = socketReadTimeout; + } } diff --git a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java index 9b823bf44..9ef606a43 100644 --- a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java +++ b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java @@ -155,12 +155,30 @@ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeou */ SocketConnectionFacadeImpl(Socket socket) throws IOException { - socket.setSoTimeout(MAX_SOCKET_READ_TIMEOUT_MILLIS); + this(socket, MAX_SOCKET_READ_TIMEOUT_MILLIS); + } + + /** + * Creates a new instance for use with FastAGI that uses NL ("\n") as line delimiter. + * + * @param socket the underlying socket. + * @param timeout 0 indicates default, -1 indicates infinite timeout (not recommended) + * @throws IOException if the connection cannot be initialized. + */ + SocketConnectionFacadeImpl(Socket socket, int timeout) throws IOException + { + if (timeout == -1) + { + timeout = 0; + } else if (timeout == 0) { + timeout = MAX_SOCKET_READ_TIMEOUT_MILLIS; + } + socket.setSoTimeout(timeout); initialize(socket, StandardCharsets.UTF_8, NL_PATTERN); } - /** 70 mi = 70 * 60 * 1000 */ - private static final int MAX_SOCKET_READ_TIMEOUT_MILLIS = 4200000; + /** 3 hrs = 3 * 3660 * 1000 */ + public static final int MAX_SOCKET_READ_TIMEOUT_MILLIS = 10800000; private void initialize(Socket socket, Charset encoding, Pattern pattern) throws IOException { diff --git a/src/test/java/org/asteriskjava/fastagi/DefaultAgiServerTest.java b/src/test/java/org/asteriskjava/fastagi/DefaultAgiServerTest.java index a07921314..3fc9ca04f 100644 --- a/src/test/java/org/asteriskjava/fastagi/DefaultAgiServerTest.java +++ b/src/test/java/org/asteriskjava/fastagi/DefaultAgiServerTest.java @@ -123,6 +123,10 @@ public void close() throws IOException { closeCalls++; } + + public void setSocketReadTimeout(int socketReadTimeout) + { + } } @Test From 95a96c7a2cb048479d450d9287ca83f082e37ed1 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 4 Mar 2019 09:45:12 +1100 Subject: [PATCH 240/802] Fix to make init error more obvious --- .../pbx/internal/core/AsteriskPBX.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 2db41d60b..db81f3baf 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -96,22 +96,13 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener this.bridgeSupport = CoherentManagerConnection.getInstance().isBridgeSupported(); expectRenameEvents = CoherentManagerConnection.getInstance().expectRenameEvents(); liveChannels = new LiveChannelManager(); - try - { - MeetmeRoomControl.init(this, AsteriskPBX.MAX_MEETME_ROOMS); - } - catch (Throwable e) - { - logger.error(e, e); - } + MeetmeRoomControl.init(this, AsteriskPBX.MAX_MEETME_ROOMS); } - catch (IllegalStateException | IOException | AuthenticationFailedException | TimeoutException - | InterruptedException e1) + catch (Exception e) { - logger.error(e1, e1); + throw new RuntimeException(e); } - } @Override From fbd492dd19233b7f619af6d7a40b526e2fc0c910 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 18 Mar 2019 16:07:08 -0400 Subject: [PATCH 241/802] EventBuilderImpl: Only log missing event class once Signed-off-by: Sean Bright --- .../asteriskjava/manager/internal/EventBuilderImpl.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index e8546f632..89edec986 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -48,6 +48,7 @@ class EventBuilderImpl extends AbstractBuilder implements EventBuilder { private static final Set ignoredAttributes = new HashSet<>(Arrays.asList("event")); private Map> registeredEventClasses; + private final Set eventClassNegativeCache = new HashSet<>(); private static final Log logger = LogFactory.getLog(EventBuilderImpl.class); @@ -228,8 +229,11 @@ else if (value instanceof String && !"listitems".equals(key)) eventClass = registeredEventClasses.get(eventType); if (eventClass == null) { - logger.info("No event class registered for event type '" + eventType + "', attributes: " + attributes - + ". Please report at https://github.com/asterisk-java/asterisk-java/issues"); + if (eventClassNegativeCache.add(eventType)) + { + logger.info("No event class registered for event type '" + eventType + "', attributes: " + attributes + + ". Please report at https://github.com/asterisk-java/asterisk-java/issues"); + } return null; } From 68bcdf5c36ec3432c3fafa00891a27bd0175c189 Mon Sep 17 00:00:00 2001 From: Nathan Date: Sat, 4 May 2019 00:34:17 +0200 Subject: [PATCH 242/802] Implement semantic version checking for AMI version (#294) * Implement semantic version checking for AMI version * Apply code formatting to the version check code --- .../internal/ManagerConnectionImpl.java | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index c1503b7fe..39e3e52b3 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -92,6 +92,19 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher private static final int MAX_VERSION_ATTEMPTS = 4; private static final String CMD_SHOW_VERSION = "core show version"; + // NOTE: identifier is AMI_VERSION, defined in include/asterisk/manager.h + // AMI version consists of MAJOR.BREAKING.NON-BREAKING. + private static final String[] SUPPORTED_AMI_VERSIONS = { + "2.6", // Asterisk 13 + "2.7", // Asterisk 13.2 + "2.8", // Asterisk >13.5 + "2.9", // Asterisk >13.3 + "3.1", // Asterisk =14.3 + "3.2", // Asterisk 14.4.0 + "4.0", // Asterisk 15 + "5.0", // Asterisk 16 + }; + private static final AtomicLong idCounter = new AtomicLong(0); /** @@ -811,7 +824,7 @@ public ManagerResponse sendAction(ManagerAction action) /** * Implements synchronous sending of "simple" actions. - * + * * @param timeout - in milliseconds */ public ManagerResponse sendAction(ManagerAction action, long timeout) @@ -1320,6 +1333,30 @@ private void fireEvent(ManagerEvent event) } } + private boolean isSupportedProtocolIdentifier(final String identifier) + { + + // Normal version checks + for (String supportedVersion : SUPPORTED_AMI_VERSIONS) + { + String prefix = "Asterisk Call Manager/" + supportedVersion + "."; + if (identifier.startsWith(prefix)) + { + return true; + } + } + + // Other cases + if ("OpenPBX Call Manager/1.0".equals(identifier)) + return true; + if ("CallWeaver Call Manager/1.0".equals(identifier)) + return true; + if (identifier.startsWith("Asterisk Call Manager Proxy/")) + return true; + + return false; + } + /** * This method is called when a {@link ProtocolIdentifierReceivedEvent} is * received from the reader. Having received a correct protocol identifier @@ -1331,44 +1368,7 @@ private void setProtocolIdentifier(final String identifier) { logger.info("Connected via " + identifier); - // NOTE: value is AMI_VERSION, defined in include/asterisk/manager.h - - if ( - // Asterisk 13 - !"Asterisk Call Manager/2.6.0".equals(identifier) - - // Asterisk 13.2 - && !"Asterisk Call Manager/2.7.0".equals(identifier) - - // Asterisk > 13.5 - && !"Asterisk Call Manager/2.8.0".equals(identifier) - - // Asterisk > 13.13 - && !"Asterisk Call Manager/2.9.0".equals(identifier) - - // Asterisk =14.3.0 - && !"Asterisk Call Manager/3.1.0".equals(identifier) - - // since Asterisk 14.4.0 - && !"Asterisk Call Manager/3.2.0".equals(identifier) - - // since Asterisk 15 - && !"Asterisk Call Manager/4.0.0".equals(identifier) - - // since Asterisk 15.1 - && !"Asterisk Call Manager/4.0.1".equals(identifier) - - // since Asterisk 15.2 - && !"Asterisk Call Manager/4.0.2".equals(identifier) - - // since Asterisk 15.3 - && !"Asterisk Call Manager/4.0.3".equals(identifier) - - // Asterisk 16 - && !"Asterisk Call Manager/5.0.0".equals(identifier) - - && !"OpenPBX Call Manager/1.0".equals(identifier) && !"CallWeaver Call Manager/1.0".equals(identifier) - && !(identifier != null && identifier.startsWith("Asterisk Call Manager Proxy/"))) + if (identifier == null || !isSupportedProtocolIdentifier(identifier)) { logger.warn("Unsupported protocol version '" + identifier + "'. Use at your own risk."); } From 84daea6a4ced4dfddd758f2e46c971525fd861c5 Mon Sep 17 00:00:00 2001 From: Richie Chauhan Date: Fri, 24 May 2019 04:09:13 +0530 Subject: [PATCH 243/802] Added FilterAction.java (#299) --- .../asteriskjava/manager/action/.gitignore | 1 + .../manager/action/FilterAction.java | 107 ++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/action/FilterAction.java diff --git a/src/main/java/org/asteriskjava/manager/action/.gitignore b/src/main/java/org/asteriskjava/manager/action/.gitignore index 454bd64b1..e7f72c23a 100644 --- a/src/main/java/org/asteriskjava/manager/action/.gitignore +++ b/src/main/java/org/asteriskjava/manager/action/.gitignore @@ -33,6 +33,7 @@ /EventGeneratingAction.class /EventsAction.class /ExtensionStateAction.class +/FilterAction.class /GetConfigAction.class /GetVarAction.class /HangupAction.class diff --git a/src/main/java/org/asteriskjava/manager/action/FilterAction.java b/src/main/java/org/asteriskjava/manager/action/FilterAction.java new file mode 100644 index 000000000..d81436134 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/FilterAction.java @@ -0,0 +1,107 @@ +/* + * Copyright 2019 Richie Chauhan + * + * 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.manager.action; + +/** + * The FilterAction dynamically adds filters for the current user in a manager session. + * The filters added are only used for the current session. Once the connection is closed the filters are removed. + * + * This command requires the user has read access to specific events(manager.conf) and system permission + * because it can be used to create filters that may bypass filters defined in manager.conf + * + * There are 2 Types of filters: + * Blacklist: The event you no longer want to receive. It starts with an exclamation. eg. "!RTCPReceived". + * Whitelist: The event you are interested in receiving. eg. "RTCPReceived". + * + * Regular expressions can be used for the filters. + * + * Evaluation of the filters is as follows: + * If no filters are configured all events are reported as normal. + * If there are white filters only: Then it is implied that all events are black listed and only the specified white filter events are returned. + * If there are black filters only: Then it is implied that all events are white listed and only the specified black filter events are removed. + * If there are both white and black filters: Then it is implied that all events are black listed and only the specified white filter events are returned, + * and then specific blacklisted events are further removed. (Limited use cases) + * + * @author aavaz + * @version $Id$ + */ +public class FilterAction extends AbstractManagerAction +{ + static final long serialVersionUID = 5537508784388696503L; + + private String operation = "Add";//No other option other than Add at the moment. + private String filter; + + /** + * Creates a new FilterAction. + */ + public FilterAction() + { + } + + /** + * Creates a new FilterAction with the filter specified + * + * @param filter the whitelist or blacklist filter to be added. + * @since ??? + */ + public FilterAction(String filter) + { + this.filter = filter; + } + + /** + * Returns the name of this action, i.e. "Filter". + */ + @Override + public String getAction() + { + return "Filter"; + } + + /** + * Returns the filter operation which is "Add" by default. + * + * @return the filter operation which is "Add" by default + */ + public String getOperation() + { + return operation; + } + + /** + * Returns the filter. + * + * @return the filter. + */ + public String getFilter() + { + return filter; + } + + /** + * Sets the filter. + * + * @param filter add the whitelist or blacklist event to be filtered. + */ + public void setFilter(String filter) + { + this.filter = filter; + } + +} + From b2685fe7dc853226d473d818a70d035fa90586e6 Mon Sep 17 00:00:00 2001 From: Peter Katzmann Date: Fri, 24 May 2019 00:41:54 +0200 Subject: [PATCH 244/802] From Asterisk 11 to 12 most QueueEvents now uses Interface instead of Location. This patch will accept location parameter only if it is not null so it is not possible to overwrite a correct parameter already set via Interface. (#296) --- .../event/AbstractQueueMemberEvent.java | 62 +++++++++++++++++-- .../manager/event/QueueMemberAddedEvent.java | 13 +--- .../manager/event/QueueMemberEvent.java | 48 +++++++++++--- .../manager/event/QueueMemberPauseEvent.java | 16 ----- .../event/QueueMemberRemovedEvent.java | 16 +---- .../manager/event/QueueMemberStatusEvent.java | 11 ---- 6 files changed, 98 insertions(+), 68 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractQueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractQueueMemberEvent.java index 1ae38cfc1..3ad13f6c9 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractQueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractQueueMemberEvent.java @@ -30,8 +30,10 @@ public abstract class AbstractQueueMemberEvent extends ManagerEvent */ private static final long serialVersionUID = -7437833328723536814L; private String queue; - private String location; + private String _interface; private String memberName; + private String pausedReason; + private String inCall; /** * @param source @@ -67,9 +69,9 @@ public void setQueue(String queue) * * @return the name of the member's interface. */ - public String getLocation() + final public String getInterface() { - return location; + return _interface; } /** @@ -77,9 +79,39 @@ public String getLocation() * * @param member the name of the member's interface. */ - public void setLocation(String member) + final public void setInterface(String _interface) { - this.location = member; + this._interface = _interface; + } + + /** + * Returns the name of the member's interface.

    + * E.g. the channel name or agent group. + * + * @deprecated since Asterisk 12 + * + * @return the name of the member's interface. + */ + @Deprecated + final public String getLocation() + { + return _interface; + } + + /** + * Sets the name of the member's interface. + * + * @deprecated since Asterisk 12 + * + * @param member the name of the member's interface. + */ + @Deprecated + final public void setLocation(String _interface) + { + if ((_interface != null) && (!"null".equals(_interface))) + { // Location is not in use since asterisk 12 + this._interface = _interface; + } } /** @@ -107,4 +139,24 @@ public void setMemberName(String memberName) { this.memberName = memberName; } + + public String getPausedReason() + { + return pausedReason; + } + + public void setPausedReason(String pausedReason) + { + this.pausedReason = pausedReason; + } + + public String getInCall() + { + return inCall; + } + + public void setInCall(String inCall) + { + this.inCall = inCall; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java index 0dca02434..090f6a5c4 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java @@ -40,7 +40,6 @@ public class QueueMemberAddedEvent extends AbstractQueueMemberEvent private Boolean paused; private String stateinterface; - private String _interface; private Boolean ringinuse; public QueueMemberAddedEvent(Object source) @@ -200,17 +199,7 @@ public String getStateinterface() public void setStateinterface(String stateinterface) { this.stateinterface = stateinterface; - } - - public String getInterface() - { - return _interface; - } - - public void setInterface(String _interface) - { - this._interface = _interface; - } + } public Boolean getRinginuse() { diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java index a5ade6482..381bf39a8 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java @@ -61,6 +61,7 @@ public class QueueMemberEvent extends ResponseEvent private String stateinterface; private Integer incall; private String pausedreason; + private String _interface; @@ -93,25 +94,54 @@ public void setQueue(String queue) } /** - * Returns the name of the member's interface. - *

    - * E.g. the channel name or agent group (for example "Agent/@1"). - * + * Returns the name of the member's interface.

    + * E.g. the channel name or agent group. + * * @return the name of the member's interface. */ - public String getLocation() + final public String getInterface() { - return location; + return _interface; } /** * Sets the name of the member's interface. * - * @param location the name of the member's interface. + * @param member the name of the member's interface. + */ + final public void setInterface(String _interface) + { + this._interface = _interface; + } + + /** + * Returns the name of the member's interface.

    + * E.g. the channel name or agent group. + * + * @deprecated since Asterisk 12 + * + * @return the name of the member's interface. + */ + @Deprecated + final public String getLocation() + { + return _interface; + } + + /** + * Sets the name of the member's interface. + * + * @deprecated since Asterisk 12 + * + * @param member the name of the member's interface. */ - public void setLocation(String location) + @Deprecated + final public void setLocation(String _interface) { - this.location = location; + if ((_interface != null) && (!"null".equals(_interface))) + { // Location is not in use since asterisk 12 + this._interface = _interface; + } } /** diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java index 3b44bd2e1..8070d8286 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java @@ -11,7 +11,6 @@ public class QueueMemberPauseEvent extends QueueMemberPausedEvent Integer penalty; Integer status; Boolean ringinuse; - String iface; String stateInterface; Integer incall; String pausedreason; @@ -118,21 +117,6 @@ public void setRinginuse(Boolean ringinuse) this.ringinuse = ringinuse; } - /** - * @return the iface - */ - public String getInterface() - { - return iface; - } - - /** - * @param iface the iface to set - */ - public void setInterface(String iface) - { - this.iface = iface; - } /** * @return the stateInterface diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java index cb3b90728..3b61e9907 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java @@ -37,7 +37,6 @@ public class QueueMemberRemovedEvent extends AbstractQueueMemberEvent Integer penalty; String stateinterface; String membership; - String _interface; Long callstaken; Boolean ringinuse; Long lastcall; @@ -95,20 +94,7 @@ public String getMembership() public void setMembership(String membership) { this.membership = membership; - } - - - public String getInterface() - { - return _interface; - } - - - public void setInterface(String _interface) - { - this._interface = _interface; - } - + } public Long getCallstaken() { diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java index 4619cd2b6..e9b552ce1 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java @@ -30,7 +30,6 @@ public class QueueMemberStatusEvent extends QueueMemberEvent private static final long serialVersionUID = -2293926744791895763L; private String ringinuse; - private String iface; private Integer incall; /** @@ -41,16 +40,6 @@ public QueueMemberStatusEvent(Object source) super(source); } - public String getInterface() - { - return iface; - } - - public void setInterface(String iface) - { - this.iface = iface; - } - /** * @return the ringinuse */ From 47f22d4c48b20d67857f94834f8bd782ef809fbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20Endr=C3=A9dy?= Date: Tue, 23 Jul 2019 01:48:48 +0200 Subject: [PATCH 245/802] timeout may happen in addNewChannel() (#303) if a simple GetVarAction has timeout, it will try it again, and don't skip the rest of the addNewChannel(), because of an exception. Or if it has no more time (SLEEP_TIME_BEFORE_GET_VAR interval was not enough) to complete GetVar, it will skip it simple. more details: https://github.com/asterisk-java/asterisk-java/issues/302 --- .../java/org/asteriskjava/live/internal/ChannelManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java index 709263f1e..cf97155f7 100644 --- a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java +++ b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java @@ -222,7 +222,7 @@ private AsteriskChannelImpl addNewChannel(String uniqueId, final String name, Da { channel.getVariable(Constants.VARIABLE_TRACE_ID); } - catch (NoSuchChannelException e) + catch (NoSuchChannelException | ManagerCommunicationException e) { try { From 9c9e9d41f46a02938be2124b9cd27af39e4c9a6d Mon Sep 17 00:00:00 2001 From: Paulo Nascimento Date: Thu, 22 Aug 2019 19:42:59 -0300 Subject: [PATCH 246/802] Fixed ManageErrors ClassClastException (#309) --- pom.xml | 29 ++++++++++++++++++- .../wrap/response/CommandResponse.java | 16 ++++++++-- .../asterisk/wrap/response/ManagerError.java | 4 +-- .../wrap/response/ManagerResponse.java | 8 ++++- .../pbx/internal/core/AsteriskPBX.java | 21 +++++++------- .../internal/core/CoherentEventFactory.java | 15 +++++----- 6 files changed, 70 insertions(+), 23 deletions(-) diff --git a/pom.xml b/pom.xml index 832f273da..c8492c322 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 3.0.0-SNAP-SHOT + 3.0.2-SNAPSHOT The free Java library for Asterisk PBX integration. 2004 @@ -76,6 +76,12 @@ ${distribution.name} ${distribution.url} + + + ${snapshot.distribution.id} + ${snapshot.distribution.name} + ${snapshot.distribution.url} + @@ -141,6 +147,27 @@ + + maven-source-plugin + + + attach-sources + deploy + jar-no-fork + + + + + + maven-deploy-plugin + + + deploy + deploy + deploy + + + ${project.artifactId} diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java index 825c04fe2..13d6706b0 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java @@ -1,21 +1,33 @@ package org.asteriskjava.pbx.asterisk.wrap.response; +import java.util.Collections; import java.util.List; public class CommandResponse extends ManagerResponse { private List result; + private boolean error; - public CommandResponse(org.asteriskjava.manager.response.CommandResponse response) + public CommandResponse(org.asteriskjava.manager.response.ManagerResponse response) { super(response); - this.result = response.getResult(); + if (response instanceof org.asteriskjava.manager.response.CommandResponse) { + result = ((org.asteriskjava.manager.response.CommandResponse) response).getResult(); + } else if (response instanceof org.asteriskjava.manager.response.ManagerError) { + error = true; + result = Collections.singletonList(response.getOutput()); + } } public List getResult() { return this.result; } + + public boolean isError() + { + return error; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java index 36cc5a57c..c82e5fad9 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java @@ -1,9 +1,9 @@ package org.asteriskjava.pbx.asterisk.wrap.response; -public class ManagerError extends ManagerResponse +public class ManagerError extends CommandResponse { - public ManagerError(org.asteriskjava.manager.response.ManagerError error) + public ManagerError(org.asteriskjava.manager.response.ManagerResponse error) { super(error); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java index 545f61b31..c035eb46c 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java @@ -3,6 +3,7 @@ import java.util.Date; import java.util.Locale; import java.util.Map; +import org.asteriskjava.manager.response.ManagerError; public class ManagerResponse { @@ -30,7 +31,12 @@ public ManagerResponse(org.asteriskjava.manager.response.ManagerResponse respons this._eventList = response.getEventList(); this._uniqueId = response.getUniqueId(); this._attributes = response.getAttributes(); - this.message = response.getMessage(); + + if (response instanceof ManagerError) { + this.message = response.getOutput(); + } else { + this.message = response.getMessage(); + } } public Date getDateReceived() diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index db81f3baf..960f82e85 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -160,7 +160,7 @@ public BlindTransferActivity blindTransfer(Channel agentChannel, EndPoint transf /** * Utility method to bridge two channels - * + * * @param lhsChannel * @param rhsChannel * @param direction @@ -512,7 +512,7 @@ public CallerID buildCallerID(final String number, final String name) /** * Convenience method to build a call id from an event. - * + * * @param event */ public CallerID buildCallerID(final AbstractChannelEvent event) @@ -560,7 +560,7 @@ public Channel registerChannel(final String channelName, final String uniqueIdPa *
    * Use registerChannel instead calling this method with an incorrect or * stale uniqueId will cause inconsistent behaviour. - * + * * @param channelName * @param uniqueID * @return @@ -587,7 +587,7 @@ public Channel internalRegisterChannel(final String channelName, final String un /** * remove white space - * + * * @param name * @return */ @@ -644,7 +644,7 @@ public void removeListener(FilteredManagerListener listener) /** * sends an action with a default timeout of 30 seconds. - * + * * @param theAction * @return * @throws IllegalArgumentException @@ -741,7 +741,7 @@ static public String getSIPADDHeader(final boolean inherit, final boolean target /** * Waits for a channel to become quiescent. A Quiescent channel is one that * is not in the middle of a name change (e.g. masquerade) - * + * * @param channel * @param timeout the time to wait (in milliseconds) for the channel to * become quiescent. @@ -907,7 +907,7 @@ public DialToAgiActivityImpl dialToAgiWithAbort(EndPoint endPoint, CallerID call /** * Creates the set of extensions required to test NJR during the * installation. The context must already exist in the dialplan. - * + * * @param profile * @param dialContext * @return success or failure @@ -988,10 +988,11 @@ public String addAsteriskExtension(String extNumber, int priority, String comman CommandResponse response = (CommandResponse) sendAction(action, 30000); List line = response.getResult(); - String answer = line.get(0); String tmp = "Extension '" + extNumber + "," + priority + ","; - if (answer.substring(0, tmp.length()).compareToIgnoreCase(tmp) == 0) - return "OK"; + + if (line.stream().anyMatch(answer -> answer.substring(0, tmp.length()).compareToIgnoreCase(tmp) == 0)) { + return "OK"; + } throw new Exception("InitiateAction.AddExtentionFailed" + ext); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java index c18f5b9fb..1599917b9 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java @@ -19,7 +19,7 @@ /** * This class maps asterisk-java events to our internal events that use iChannel * rather than raw channel names. - * + * * @author bsutton */ @SuppressWarnings({"unchecked"}) @@ -174,12 +174,13 @@ public static ResponseEvent build(org.asteriskjava.manager.event.ResponseEvent e public static ManagerResponse build(org.asteriskjava.manager.response.ManagerResponse response) { ManagerResponse result; - if (response instanceof org.asteriskjava.manager.response.CommandResponse) - result = new CommandResponse((org.asteriskjava.manager.response.CommandResponse) response); - else if (response instanceof org.asteriskjava.manager.response.ManagerError) - result = new ManagerError((org.asteriskjava.manager.response.ManagerError) response); - else - result = new ManagerResponse(response); + if (response instanceof org.asteriskjava.manager.response.CommandResponse) { + result = new CommandResponse((org.asteriskjava.manager.response.CommandResponse) response); + } else if (response instanceof org.asteriskjava.manager.response.ManagerError) { + result = new ManagerError(response); + } else { + result = new ManagerResponse(response); + } return result; } From 486b0529d40677b549ff3defd6cf7c78ed6056c0 Mon Sep 17 00:00:00 2001 From: Peter Katzmann Date: Fri, 23 Aug 2019 00:44:59 +0200 Subject: [PATCH 247/802] setKeepAliveAfterAuthenticationFailure is not accessible from application (#306) --- .../org/asteriskjava/manager/ManagerConnection.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/ManagerConnection.java b/src/main/java/org/asteriskjava/manager/ManagerConnection.java index 442f9a2e2..b21a77055 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/ManagerConnection.java @@ -19,7 +19,6 @@ import java.io.IOException; import java.net.InetAddress; import java.nio.charset.Charset; - import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.action.EventGeneratingAction; import org.asteriskjava.manager.action.ManagerAction; @@ -207,6 +206,16 @@ public interface ManagerConnection * @since 0.3 */ void setSocketReadTimeout(int socketReadTimeout); + /** + * Set to true to try reconnecting to ther asterisk serve even + * if the reconnection attempt threw an AuthenticationFailedException.
    + * Default is true. + * + * @param keepAliveAfterAuthenticationFailure true to try + * reconnecting to ther asterisk serve even if the reconnection attempt + * threw an AuthenticationFailedException, false otherwise. + */ + public void setKeepAliveAfterAuthenticationFailure(boolean keepAliveAfterAuthenticationFailure); /** * Logs in to the Asterisk server with the username and password specified From caa2ad767f6e0cc4284cf9d525a94c119b423029 Mon Sep 17 00:00:00 2001 From: Peter Katzmann Date: Fri, 23 Aug 2019 00:46:02 +0200 Subject: [PATCH 248/802] AttendedTransfer Events misses optional transferTargetXXXX parameters. (#307) These are missing in the official Asterisk Event docus but can be found in the ARI documentation. --- .../manager/event/AttendedTransferEvent.java | 358 +++++++++++++----- 1 file changed, 269 insertions(+), 89 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/AttendedTransferEvent.java b/src/main/java/org/asteriskjava/manager/event/AttendedTransferEvent.java index 3795665e2..07778bf76 100644 --- a/src/main/java/org/asteriskjava/manager/event/AttendedTransferEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AttendedTransferEvent.java @@ -6,94 +6,112 @@ * https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+ManagerEvent_AttendedTransfer */ public class AttendedTransferEvent extends AbstractBridgeEvent { + private static final long serialVersionUID = 1L; - private String origTransfererChannel; - private String origTransfererChannelState; - private String origTransfererChannelStateDesc; - private String origTransfererCallerIDNum; - private String origTransfererCallerIDName; - private String origTransfererConnectedLineNum; - private String origTransfererConnectedLineName; - private String origTransfererAccountCode; - private String origTransfererContext; - private String origTransfererExten; - private String origTransfererPriority; - private String origTransfererUniqueid; - private String origBridgeUniqueid; - private String origBridgeType; - private String origBridgeTechnology; - private String origBridgeCreator; - private String origBridgeName; - private String origBridgeNumChannels; - private String secondTransfererChannel; - private String secondTransfererChannelState; - private String secondTransfererChannelStateDesc; - private String secondTransfererCallerIDNum; - private String secondTransfererCallerIDName; - private String secondTransfererConnectedLineNum; - private String secondTransfererConnectedLineName; - private String secondTransfererAccountCode; - private String secondTransfererContext; - private String secondTransfererExten; - private String secondTransfererPriority; - private String secondTransfererUniqueid; - private String secondBridgeUniqueid; - private String secondBridgeType; - private String secondBridgeTechnology; - private String secondBridgeCreator; - private String secondBridgeName; - private String secondBridgeNumChannels; - private String destType; - private String destBridgeUniqueid; - private String destApp; - private String localOneChannel; - private String localOneChannelState; - private String localOneChannelStateDesc; - private String localOneCallerIDNum; - private String localOneCallerIDName; - private String localOneConnectedLineNum; - private String localOneConnectedLineName; - private String localOneAccountCode; - private String localOneContext; - private String localOneExten; - private String localOnePriority; - private String localOneUniqueid; - private String localTwoChannel; - private String localTwoChannelState; - private String localTwoChannelStateDesc; - private String localTwoCallerIDNum; - private String localTwoCallerIDName; - private String localTwoConnectedLineNum; - private String localTwoConnectedLineName; - private String localTwoAccountCode; - private String localTwoContext; - private String localTwoExten; - private String localTwoPriority; - private String localTwoUniqueid; - private String destTransfererChannel; - private String transfereeChannel; - private String transfereeChannelState; - private String transfereeChannelStateDesc; - private String transfereeCallerIDNum; - private String transfereeCallerIDName; - private String transfereeConnectedLineNum; - private String transfereeConnectedLineName; - private String transfereeAccountCode; - private String transfereeContext; - private String transfereeExten; - private String transfereePriority; - private String transfereeUniqueid; - - private String transfereeLinkedId; - private String transfereeLanguage; - private String origTransfererLinkedId; - private String secondTransfererLanguage; - private String isexternal; - private String result; - private String secondTransfererLinkedId; - private String origTransfererLanguage; - + private String origTransfererChannel; + private String origTransfererChannelState; + private String origTransfererChannelStateDesc; + private String origTransfererCallerIDNum; + private String origTransfererCallerIDName; + private String origTransfererConnectedLineNum; + private String origTransfererConnectedLineName; + private String origTransfererAccountCode; + private String origTransfererContext; + private String origTransfererExten; + private String origTransfererPriority; + private String origTransfererUniqueid; + private String origBridgeUniqueid; + private String origBridgeType; + private String origBridgeTechnology; + private String origBridgeCreator; + private String origBridgeName; + private String origBridgeNumChannels; + private String secondTransfererChannel; + private String secondTransfererChannelState; + private String secondTransfererChannelStateDesc; + private String secondTransfererCallerIDNum; + private String secondTransfererCallerIDName; + private String secondTransfererConnectedLineNum; + private String secondTransfererConnectedLineName; + private String secondTransfererAccountCode; + private String secondTransfererContext; + private String secondTransfererExten; + private String secondTransfererPriority; + private String secondTransfererUniqueid; + private String secondBridgeUniqueid; + private String secondBridgeType; + private String secondBridgeTechnology; + private String secondBridgeCreator; + private String secondBridgeName; + private String secondBridgeNumChannels; + private String destType; + private String destBridgeUniqueid; + private String destApp; + private String localOneChannel; + private String localOneChannelState; + private String localOneChannelStateDesc; + private String localOneCallerIDNum; + private String localOneCallerIDName; + private String localOneConnectedLineNum; + private String localOneConnectedLineName; + private String localOneAccountCode; + private String localOneContext; + private String localOneExten; + private String localOnePriority; + private String localOneUniqueid; + private String localTwoChannel; + private String localTwoChannelState; + private String localTwoChannelStateDesc; + private String localTwoCallerIDNum; + private String localTwoCallerIDName; + private String localTwoConnectedLineNum; + private String localTwoConnectedLineName; + private String localTwoAccountCode; + private String localTwoContext; + private String localTwoExten; + private String localTwoPriority; + private String localTwoUniqueid; + private String destTransfererChannel; + private String transfereeChannel; + private String transfereeChannelState; + private String transfereeChannelStateDesc; + private String transfereeCallerIDNum; + private String transfereeCallerIDName; + private String transfereeConnectedLineNum; + private String transfereeConnectedLineName; + private String transfereeAccountCode; + private String transfereeContext; + private String transfereeExten; + private String transfereePriority; + private String transfereeUniqueid; + + private String transferTargetUniqueID; + private String transferTargetCallerIDName; + private String secondBridgeVideoSourceMode; + private String transferTargetLinkedID; + private String transferTargetPriority; + private String transferTargetCallerIDNum; + private String origBridgeVideoSourceMode; + private String transferTargetConnectedLineNum; + private String transferTargetChannel; + private String transferTargetContext; + private String transferTargetConnectedLineName; + private String transferTargetExten; + private String transferTargetChannelState; + private String transferTargetLanguage; + private String transferTargetAccountCode; + private String transferTargetChannelStateDesc; + + private String transfereeLinkedId; + private String transfereeLanguage; + private String origTransfererLinkedId; + private String secondTransfererLanguage; + private String isexternal; + private String result; + private String secondTransfererLinkedId; + private String origTransfererLanguage; + public AttendedTransferEvent(Object source) { super(source); @@ -174,7 +192,8 @@ public String getOrigTransfererAccountCode() return origTransfererAccountCode; } - public void setOrigTransfererAccountCode(String origTransfererAccountCode) { + public void setOrigTransfererAccountCode(String origTransfererAccountCode) + { this.origTransfererAccountCode = origTransfererAccountCode; } @@ -328,7 +347,8 @@ public void setSecondTransfererCallerIDName(String secondTransfererCallerIDName) this.secondTransfererCallerIDName = secondTransfererCallerIDName; } - public String getSecondTransfererConnectedLineNum() { + public String getSecondTransfererConnectedLineNum() + { return secondTransfererConnectedLineNum; } @@ -936,5 +956,165 @@ public void setOrigTransfererLanguage(String origTransfererLanguage) { this.origTransfererLanguage = origTransfererLanguage; } - + + public String getTransferTargetUniqueID() + { + return transferTargetUniqueID; + } + + public void setTransferTargetUniqueID(String transferTargetUniqueID) + { + this.transferTargetUniqueID = transferTargetUniqueID; + } + + public String getTransferTargetCallerIDName() + { + return transferTargetCallerIDName; + } + + public void setTransferTargetCallerIDName(String transferTargetCallerIDName) + { + this.transferTargetCallerIDName = transferTargetCallerIDName; + } + + public String getSecondBridgeVideoSourceMode() + { + return secondBridgeVideoSourceMode; + } + + public void setSecondBridgeVideoSourceMode(String secondBridgeVideoSourceMode) + { + this.secondBridgeVideoSourceMode = secondBridgeVideoSourceMode; + } + + public String getTransferTargetLinkedID() + { + return transferTargetLinkedID; + } + + public void setTransferTargetLinkedID(String transferTargetLinkedID) + { + this.transferTargetLinkedID = transferTargetLinkedID; + } + + public String getTransferTargetPriority() + { + return transferTargetPriority; + } + + public void setTransferTargetPriority(String transferTargetPriority) + { + this.transferTargetPriority = transferTargetPriority; + } + + public String getTransferTargetCallerIDNum() + { + return transferTargetCallerIDNum; + } + + public void setTransferTargetCallerIDNum(String transferTargetCallerIDNum) + { + this.transferTargetCallerIDNum = transferTargetCallerIDNum; + } + + public String getOrigBridgeVideoSourceMode() + { + return origBridgeVideoSourceMode; + } + + public void setOrigBridgeVideoSourceMode(String origBridgeVideoSourceMode) + { + this.origBridgeVideoSourceMode = origBridgeVideoSourceMode; + } + + public String getTransferTargetConnectedLineNum() + { + return transferTargetConnectedLineNum; + } + + public void setTransferTargetConnectedLineNum(String transferTargetConnectedLineNum) + { + this.transferTargetConnectedLineNum = transferTargetConnectedLineNum; + } + + public String getTransferTargetChannel() + { + return transferTargetChannel; + } + + public void setTransferTargetChannel(String transferTargetChannel) + { + this.transferTargetChannel = transferTargetChannel; + } + + public String getTransferTargetContext() + { + return transferTargetContext; + } + + public void setTransferTargetContext(String transferTargetContext) + { + this.transferTargetContext = transferTargetContext; + } + + public String getTransferTargetConnectedLineName() + { + return transferTargetConnectedLineName; + } + + public void setTransferTargetConnectedLineName(String transferTargetConnectedLineName) + { + this.transferTargetConnectedLineName = transferTargetConnectedLineName; + } + + public String getTransferTargetExten() + { + return transferTargetExten; + } + + public void setTransferTargetExten(String transferTargetExten) + { + this.transferTargetExten = transferTargetExten; + } + + public String getTransferTargetChannelState() + { + return transferTargetChannelState; + } + + public void setTransferTargetChannelState(String transferTargetChannelState) + { + this.transferTargetChannelState = transferTargetChannelState; + } + + public String getTransferTargetLanguage() + { + return transferTargetLanguage; + } + + public void setTransferTargetLanguage(String transferTargetLanguage) + { + this.transferTargetLanguage = transferTargetLanguage; + } + + public String getTransferTargetAccountCode() + { + return transferTargetAccountCode; + } + + public void setTransferTargetAccountCode(String transferTargetAccountCode) + { + this.transferTargetAccountCode = transferTargetAccountCode; + } + + public String getTransferTargetChannelStateDesc() + { + return transferTargetChannelStateDesc; + } + + public void setTransferTargetChannelStateDesc(String transferTargetChannelStateDesc) + { + this.transferTargetChannelStateDesc = transferTargetChannelStateDesc; + } + } From 3902ce65875bd8dd346056cd29b47f72f2b082e4 Mon Sep 17 00:00:00 2001 From: Paulo Nascimento Date: Thu, 22 Aug 2019 19:50:35 -0300 Subject: [PATCH 249/802] Feature/check dialplan exists (#310) * Fixed ManageErrors ClassClastException * Added method to check if a dialplan for a context exists --- .../pbx/internal/core/AsteriskPBX.java | 43 ++++++++----------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 960f82e85..bf3557ef0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -948,34 +948,27 @@ public boolean createAgiEntryPoint() throws IOException, AuthenticationFailedExc } - public boolean checkDialplanExists(AsteriskSettings profile) - throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException - { - String command; + public boolean checkDialplanExists(String dialPlan, String context) throws IOException, TimeoutException { + String command; - if (getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) - { - // TODO: Use ShowDialplanAction instead of CommandAction? - command = "dialplan show " + profile.getManagementContext(); - } - else - { - command = "show dialplan " + profile.getManagementContext(); - } + if (getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) { + // TODO: Use ShowDialplanAction instead of CommandAction? + command = "dialplan show " + context; + } + else + { + command = "show dialplan " + context; + } - CommandAction action = new CommandAction(command); - CommandResponse response = (CommandResponse) sendAction(action, 30000); + CommandAction action = new CommandAction(command); + CommandResponse response = (CommandResponse) sendAction(action, 30000); - boolean exists = false; - for (String line : response.getResult()) - { - if (line.contains(ACTIVITY_AGI)) - { - exists = true; - break; - } - } - return exists; + return response.getResult().stream().anyMatch(line -> line.contains(dialPlan)); + } + + public boolean checkDialplanExists(AsteriskSettings profile) + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException { + return checkDialplanExists(ACTIVITY_AGI, profile.getManagementContext()); } From 955db85eb68cf8a4cb98a292c1620eec779793c8 Mon Sep 17 00:00:00 2001 From: Paulo Nascimento Date: Thu, 22 Aug 2019 19:51:25 -0300 Subject: [PATCH 250/802] Feature/reload event (#311) * Fixed ManageErrors ClassClastException * Added method to check if a dialplan for a context exists * Added ReloadEvent class to listen for "core reload" events --- .../pbx/asterisk/wrap/events/ReloadEvent.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java new file mode 100644 index 000000000..4a236c971 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java @@ -0,0 +1,8 @@ +package org.asteriskjava.pbx.asterisk.wrap.events; + +public class ReloadEvent extends ManagerEvent { + + public ReloadEvent(final org.asteriskjava.manager.event.ReloadEvent event) { + super(event); + } +} From b0ed40a5499e9e54cd36e4bec17eef6560051580 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 29 Aug 2019 14:16:31 +1000 Subject: [PATCH 251/802] fix for BridgeEvent --- .../bridge/BridgeState.java | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 98a7295d1..ab6bfffb2 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -30,7 +31,8 @@ class BridgeState ManagerEvent destroy() { - synchronized (members) { + synchronized (members) + { members.clear(); } return null; @@ -48,8 +50,7 @@ ManagerEvent addMember(BridgeEnterEvent event) synchronized (members) { - if (members.put(event.getChannel(), event) == null - && members.size() == 2) + if (members.put(event.getChannel(), event) == null && members.size() == 2) { remaining = new ArrayList<>(members.values()); } @@ -62,9 +63,7 @@ ManagerEvent addMember(BridgeEnterEvent event) logger.info("Members size " + remaining.size() + " " + event); - BridgeEvent bridgeEvent = buildBridgeEvent( - BridgeEvent.BRIDGE_STATE_LINK, - remaining); + BridgeEvent bridgeEvent = buildBridgeEvent(BridgeEvent.BRIDGE_STATE_LINK, remaining); logger.info("Bridge " + bridgeEvent.getChannel1() + " " + bridgeEvent.getChannel2()); @@ -80,30 +79,30 @@ ManagerEvent addMember(BridgeEnterEvent event) ManagerEvent removeMember(BridgeLeaveEvent event) { - List remaining = null; + List remaining = new LinkedList<>(); synchronized (members) { - if (members.remove(event.getChannel()) != null - && members.size() == 2) + remaining.addAll(members.values()); + + if (members.remove(event.getChannel()) != null) { - remaining = new ArrayList<>(members.values()); + if (remaining.size() == 2) + { + return buildBridgeEvent(BridgeEvent.BRIDGE_STATE_UNLINK, remaining); + } } } // If we didn't remove anything, or we aren't at exactly 2 members, // there's nothing else for us to do - if (remaining == null) - { - return null; - } - return buildBridgeEvent( - BridgeEvent.BRIDGE_STATE_UNLINK, - remaining); + return null; + } - private BridgeEvent buildBridgeEvent(String bridgeState, List members) { + private BridgeEvent buildBridgeEvent(String bridgeState, List members) + { Collections.sort(members, BRIDGE_ENTER_EVENT_COMPARATOR); BridgeEvent bridgeEvent = new BridgeEvent(this); From aa400209282135df639ed63efdcea815cee80353 Mon Sep 17 00:00:00 2001 From: Yuri Orlov Date: Tue, 12 Nov 2019 01:17:36 +0300 Subject: [PATCH 252/802] Cleanup (#316) * Remove unnecessary null-checks * Simplify boolean conditions * Remove unnecessary visibility modifier * Use standard charset constant --- .../java/org/asteriskjava/fastagi/AgiServer.java | 2 +- .../live/internal/AsteriskQueueMemberImpl.java | 4 ++-- .../asteriskjava/manager/ManagerConnection.java | 2 +- .../asteriskjava/manager/event/BridgeEvent.java | 4 ++-- .../asteriskjava/manager/event/DtmfEvent.java | 4 ++-- .../asteriskjava/manager/event/ReloadEvent.java | 4 ++-- .../manager/event/SkypeChatMessageEvent.java | 3 ++- .../pbx/internal/activity/DialActivityImpl.java | 4 ++-- .../internal/activity/DialToAgiActivityImpl.java | 2 +- .../pbx/internal/asterisk/MeetmeRoomControl.java | 16 ++++++++-------- .../pbx/internal/core/ChannelImpl.java | 2 +- .../internal/core/CoherentManagerEventQueue.java | 4 ++-- .../pbx/internal/managerAPI/Dial.java | 2 +- .../pbx/internal/managerAPI/DialToAgi.java | 2 +- .../internal/managerAPI/OriginateBaseClass.java | 8 ++++---- .../managerAPI/OriginateToExtension.java | 4 ++-- .../asteriskjava/util/ServerSocketFacade.java | 2 +- .../asteriskjava/util/internal/FileTrace.java | 3 ++- .../util/internal/streamreader/FastScanner.java | 2 +- 19 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/AgiServer.java b/src/main/java/org/asteriskjava/fastagi/AgiServer.java index 8fe7aff1e..16eea9520 100644 --- a/src/main/java/org/asteriskjava/fastagi/AgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiServer.java @@ -82,5 +82,5 @@ public interface AgiServer * @see java.net.Socket#setSoTimeout(int) * @since 3.0.0 */ - public void setSocketReadTimeout(int socketReadTimeout); + void setSocketReadTimeout(int socketReadTimeout); } diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java index 104579866..0831b6290 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java @@ -164,12 +164,12 @@ public String getMembership() public boolean isStatic() { - return membership != null && "static".equals(membership); + return "static".equals(membership); } public boolean isDynamic() { - return membership != null && "dynamic".equals(membership); + return "dynamic".equals(membership); } public Integer getPenalty() diff --git a/src/main/java/org/asteriskjava/manager/ManagerConnection.java b/src/main/java/org/asteriskjava/manager/ManagerConnection.java index b21a77055..5316ee0c8 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/ManagerConnection.java @@ -215,7 +215,7 @@ public interface ManagerConnection * reconnecting to ther asterisk serve even if the reconnection attempt * threw an AuthenticationFailedException, false otherwise. */ - public void setKeepAliveAfterAuthenticationFailure(boolean keepAliveAfterAuthenticationFailure); + void setKeepAliveAfterAuthenticationFailure(boolean keepAliveAfterAuthenticationFailure); /** * Logs in to the Asterisk server with the username and password specified diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeEvent.java index 46e203467..872e6b9d9 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeEvent.java @@ -256,7 +256,7 @@ public void setCallerId2(String callerId2) */ public boolean isLink() { - return bridgeState != null && BRIDGE_STATE_LINK.equalsIgnoreCase(bridgeState); + return BRIDGE_STATE_LINK.equalsIgnoreCase(bridgeState); } /** @@ -267,6 +267,6 @@ public boolean isLink() */ public boolean isUnlink() { - return bridgeState != null && BRIDGE_STATE_UNLINK.equalsIgnoreCase(bridgeState); + return BRIDGE_STATE_UNLINK.equalsIgnoreCase(bridgeState); } } diff --git a/src/main/java/org/asteriskjava/manager/event/DtmfEvent.java b/src/main/java/org/asteriskjava/manager/event/DtmfEvent.java index 6740c6d36..329328b43 100644 --- a/src/main/java/org/asteriskjava/manager/event/DtmfEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DtmfEvent.java @@ -219,7 +219,7 @@ public void setEnd(Boolean end) */ public boolean isReceived() { - return direction != null && DIRECTION_RECEIVED.equalsIgnoreCase(direction); + return DIRECTION_RECEIVED.equalsIgnoreCase(direction); } /** @@ -231,7 +231,7 @@ public boolean isReceived() */ public boolean isSent() { - return direction != null && DIRECTION_SENT.equalsIgnoreCase(direction); + return DIRECTION_SENT.equalsIgnoreCase(direction); } public String getLanguage() diff --git a/src/main/java/org/asteriskjava/manager/event/ReloadEvent.java b/src/main/java/org/asteriskjava/manager/event/ReloadEvent.java index 087ece01f..83a931c3b 100644 --- a/src/main/java/org/asteriskjava/manager/event/ReloadEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ReloadEvent.java @@ -120,7 +120,7 @@ public void setMessage(String message) */ public boolean isEnabled() { - return status != null && STATUS_ENABLED.equalsIgnoreCase(status); + return STATUS_ENABLED.equalsIgnoreCase(status); } /** @@ -134,6 +134,6 @@ public boolean isEnabled() */ public boolean isDisabled() { - return status != null && STATUS_DISABLED.equalsIgnoreCase(status); + return STATUS_DISABLED.equalsIgnoreCase(status); } } diff --git a/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java b/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java index e3a95a253..f8d4f37d9 100644 --- a/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java @@ -17,6 +17,7 @@ package org.asteriskjava.manager.event; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import org.asteriskjava.util.Base64; @@ -114,6 +115,6 @@ public String getDecodedMessage() { return null; } - return new String(Base64.base64ToByteArray(message), Charset.forName("UTF-8")); + return new String(Base64.base64ToByteArray(message), StandardCharsets.UTF_8); } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java index 115967350..b43a2ad4d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java @@ -110,7 +110,7 @@ public boolean doActivity() throws PBXException DialActivityImpl.logger.debug("dialout succeeded: dest channel is :" + this.acceptingChannel); - if (this.validateChannel(this.acceptingChannel) == false) + if (!this.validateChannel(this.acceptingChannel)) { this.setLastException(new PBXException(("dialed extension hungup unexpectedly"))); DialActivityImpl.logger.error("dialed extension hungup unexpectedly"); @@ -123,7 +123,7 @@ public boolean doActivity() throws PBXException } finally { - if (success != true) + if (!success) { this.hangup(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index 071be8c2c..46deff592 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -116,7 +116,7 @@ public boolean doActivity() throws PBXException } finally { - if (success != true) + if (!success) { this.hangup(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index 8426910e2..6718043dc 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -223,7 +223,7 @@ public void onManagerEvent(final ManagerEvent event) } room.removeChannel(channel); room.setLastUpdated(); - if ((room.getChannelCount() < 2) && (room.getForceClose() == true)) + if (room.getChannelCount() < 2 && room.getForceClose()) { this.hangupChannels(room); room.setInactive(); @@ -241,7 +241,7 @@ public void hangupChannels(final MeetmeRoom room) { final Channel Channels[] = room.getChannels(); - if (room.isActive() == true) + if (room.isActive()) { PBX pbx = PBXFactory.getActivePBX(); @@ -345,16 +345,16 @@ private synchronized void parseMeetme(final String line) throws NoMeetmeExceptio if (line != null) { - if (line.toLowerCase().startsWith("no such command 'meetme'") == true) //$NON-NLS-1$ + if (line.toLowerCase().startsWith("no such command 'meetme'")) //$NON-NLS-1$ { throw new NoMeetmeException("Asterisk is not configured correctly! Please enable the MeetMe app"); //$NON-NLS-1$ } - if ((line.toLowerCase().startsWith("no active meetme conferences.") == false) //$NON-NLS-1$ - && (line.toLowerCase().startsWith("conf num") == false) //$NON-NLS-1$ - && (line.toLowerCase().startsWith("* total number") == false) //$NON-NLS-1$ - && (line.toLowerCase().startsWith("no such conference") == false) //$NON-NLS-1$ - && (line.toLowerCase().startsWith("no such command 'meetme") == false) //$NON-NLS-1$ + if ((!line.toLowerCase().startsWith("no active meetme conferences.")) //$NON-NLS-1$ + && (!line.toLowerCase().startsWith("conf num")) //$NON-NLS-1$ + && (!line.toLowerCase().startsWith("* total number")) //$NON-NLS-1$ + && (!line.toLowerCase().startsWith("no such conference")) //$NON-NLS-1$ + && (!line.toLowerCase().startsWith("no such command 'meetme")) //$NON-NLS-1$ ) { // Update the stats on each meetme diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index ec85a7704..4ff574bd0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -438,7 +438,7 @@ private final String extractPeerName(final String channelName) boolean wasMarkedDuringSweep() { boolean ret = false; - if ((this._sweepStartTime == null) || (this._marked == true)) + if (this._sweepStartTime == null || this._marked) { this._sweepStartTime = null; ret = true; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index 7dc40fe70..84fb33e2b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -115,7 +115,7 @@ public void onManagerEvent(final org.asteriskjava.manager.event.ManagerEvent eve public void run() { - while (this._stop == false) + while (!this._stop) { try { @@ -142,7 +142,7 @@ public void run() * don't care. If it is thrown when we aren't shutting down then * we have a problem and we need to log it. */ - if (this._stop == false) + if (!this._stop) { CoherentManagerEventQueue.logger.error(e, e); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java index 961e653c7..8bb06f666 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java @@ -71,7 +71,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint ((AsteriskPBX) pbx).getManagementContext(), callerID, null, hideCallerId, channelVarsToSet); this.result[0] = trcResult; - if (trcResult.isSuccess() == true) + if (trcResult.isSuccess()) { try diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index e014684e1..ce437a63c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -69,7 +69,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint ((AsteriskPBX) pbx).getManagementContext(), callerID, timeout, hideCallerId, channelVarsToSet); this.result[0] = trcResult; - if (trcResult.isSuccess() == true) + if (trcResult.isSuccess()) { if (trcResult.getChannel() != null) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index e6fa83a9d..a93d66d0d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -106,7 +106,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has this.originateSeen = false; this.channelSeen = false; - if (this.hungup == true) + if (this.hungup) { // the monitored channel already hungup so just return false and // shutdown @@ -207,7 +207,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has this.close(); } - if (this.originateSuccess == true) + if (this.originateSuccess) { this.result.setSuccess(true); this.result.setChannelData(this.newChannel); @@ -381,7 +381,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) // that the call is up. Otherwise we will rely on the // NewChannelEvent doing the // notify. - if (this.channelSeen == true) + if (this.channelSeen) { OriginateBaseClass.logger.info("notify originate response event " + this.originateSuccess); originateLatch.countDown(); @@ -468,7 +468,7 @@ private void handleId(Channel channel) this.listener.channelUpdate(channel); } - if (this.originateSeen == true) + if (this.originateSeen) { OriginateBaseClass.logger.debug("notifying success 362"); originateLatch.countDown(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java index 640038158..038276faf 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java @@ -36,7 +36,7 @@ public OriginateResult originate(final EndPoint localHandset, final EndPoint tar final AsteriskSettings profile = PBXFactory.getActiveProfile(); final HashMap myVars = new HashMap<>(1); - if (autoAnswer == true) + if (autoAnswer) { RedirectCall.setAutoAnswer(myVars, profile); } @@ -57,7 +57,7 @@ public OriginateResult originate(final EndPoint localHandset, final EndPoint tar final AsteriskSettings profile = PBXFactory.getActiveProfile(); final HashMap myVars = new HashMap<>(1); - if (autoAnswer == true) + if (autoAnswer) { RedirectCall.setAutoAnswer(myVars, profile); } diff --git a/src/main/java/org/asteriskjava/util/ServerSocketFacade.java b/src/main/java/org/asteriskjava/util/ServerSocketFacade.java index dcb90d1e3..c0fc5020b 100644 --- a/src/main/java/org/asteriskjava/util/ServerSocketFacade.java +++ b/src/main/java/org/asteriskjava/util/ServerSocketFacade.java @@ -52,5 +52,5 @@ public interface ServerSocketFacade * @see java.net.Socket#setSoTimeout(int) * @since 3.0.0 */ - public void setSocketReadTimeout(int socketReadTimeout); + void setSocketReadTimeout(int socketReadTimeout); } diff --git a/src/main/java/org/asteriskjava/util/internal/FileTrace.java b/src/main/java/org/asteriskjava/util/internal/FileTrace.java index aeb21b7a9..bed1fa36a 100644 --- a/src/main/java/org/asteriskjava/util/internal/FileTrace.java +++ b/src/main/java/org/asteriskjava/util/internal/FileTrace.java @@ -8,6 +8,7 @@ import java.nio.CharBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; @@ -28,7 +29,7 @@ public class FileTrace implements Trace // ok to share instance as access to this object is synchronized anyway private final DateFormat df = new SimpleDateFormat("yyyyMMddHHmmsszzz"); - private Charset charset = Charset.forName("UTF-8"); + private Charset charset = StandardCharsets.UTF_8; private FileChannel channel; private boolean exceptionLogged = false; private RandomAccessFile randomAccessFile; diff --git a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java index d3e92c1e1..89ce1888c 100644 --- a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java +++ b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java @@ -5,6 +5,6 @@ public interface FastScanner extends Closeable { - public String next() throws IOException; + String next() throws IOException; } From c7719490e633da92292140a1930c09d85804d7c2 Mon Sep 17 00:00:00 2001 From: Mike Manturov Date: Tue, 12 Nov 2019 01:18:29 +0300 Subject: [PATCH 253/802] Compatibility set to 1.8 because streams are used (#317) Eg. in AsteriskPBX: ```return response.getResult().stream().anyMatch(line -> line.contains(dialPlan));``` --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 6af40b84c..af4d8d86d 100644 --- a/build.gradle +++ b/build.gradle @@ -9,8 +9,8 @@ version = '2.0.0.CI-SNAPSHOT' description = """Asterisk-Java""" -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { @@ -153,4 +153,4 @@ uploadArchives { } } } -} \ No newline at end of file +} From 0fd7563b42c2aef6b7d11212288bbc66d7b0e1b2 Mon Sep 17 00:00:00 2001 From: Brett Sutton Date: Fri, 15 Nov 2019 08:13:20 +1100 Subject: [PATCH 254/802] Standard maven packaging. --- .github/workflows/maven.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 000000000..91106d3f4 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,17 @@ +name: Java CI + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build with Maven + run: mvn -B package --file pom.xml From 27278defa99372d56f3d1a24487c7dabf600e98e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Hern=C3=A1ndez=20Bossa?= <18150289+ehbossa@users.noreply.github.com> Date: Tue, 10 Dec 2019 01:00:12 +0100 Subject: [PATCH 255/802] Make builds be platform independent Prevent maven messages like: [WARNING] File encoding has not been set, using platform encoding XXXX, i.e. build is platform dependent! --- pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pom.xml b/pom.xml index c8492c322..9914cb3a7 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,9 @@ ${snapshot.distribution.url} + + UTF-8 + From 78b1a444dec322a8afc097063330439133d7df65 Mon Sep 17 00:00:00 2001 From: Giorgio Maria Santini Date: Wed, 25 Dec 2019 12:31:58 +0100 Subject: [PATCH 256/802] fix for "Unable to set property 'lastpause' to '0' on org.asteriskjava.manager.event.QueueMemberStatusEvent: no setter." --- .../manager/event/QueueMemberEvent.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java index 381bf39a8..03ea11873 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java @@ -56,6 +56,7 @@ public class QueueMemberEvent extends ResponseEvent private Integer penalty; private Integer callsTaken; private Long lastCall; + private Long lastPause; private Integer status; private Boolean paused; private String stateinterface; @@ -258,6 +259,25 @@ public void setLastCall(Long lastCall) { this.lastCall = lastCall; } + + /** + * The time when started last pause for queue member. + * + * @return the time (in seconds since 01/01/1970) + */ + public Long getLastPause() + { + return lastPause; + } + + /** + * Sets the time when started last pause for queue member. + * @param lastPause the time (in seconds since 01/01/1970) + */ + public void setLastPause(Long lastPause) + { + this.lastPause = lastPause; + } /** * Returns the status of this queue member. From f38f7dc22a6d07684c6ac35a97bb837e152f98c5 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 21 Jan 2020 15:35:07 +1100 Subject: [PATCH 257/802] add null checks --- .../activity/BlindTransferActivityImpl.java | 620 +++++++++--------- 1 file changed, 313 insertions(+), 307 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index bf2535db4..058a619ee 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -1,307 +1,313 @@ -package org.asteriskjava.pbx.internal.activity; - -import java.util.HashSet; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.Call; -import org.asteriskjava.pbx.Call.OperandChannel; -import org.asteriskjava.pbx.CallDirection; -import org.asteriskjava.pbx.CallImpl; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.activities.BlindTransferActivity; -import org.asteriskjava.pbx.agi.AgiChannelActivityBlindTransfer; -import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.DialEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; -import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; - -/** - * The BlindTransferActivity is used by the AsteriksPBX to transfer a live - * channel to an endpoint that may need to be dialed. - * - * @author bsutton - */ -public class BlindTransferActivityImpl extends ActivityHelper implements BlindTransferActivity -{ - private static final Log logger = LogFactory.getLog(BlindTransferActivityImpl.class); - - private Call _call; - - private Call.OperandChannel _channelToTransfer; - - private EndPoint _transferTarget; - - private CallerID _toCallerID; - - private boolean _autoAnswer; - - private CountDownLatch _latch; - - private CompletionCause _completionCause; - - private long _timeout; - - /** - * The new channel that was originated for the transferTarget endpoint. - */ - private Channel _transferTargetChannel; - - private CallImpl _newCall; - - private Channel dialedChannel; - - final Channel actualChannelToTransfer; - - /** - * Blind transfers a live channel to a given endpoint which may need to be - * dialed. When we dial the endpoint we display the 'toCallerID'. - * - * @param channelToTransfer The channel which is being transfered - * @param transferTarget The target to transfer (connect) the channel to. - * @param toCallerID The caller id to display on the target endpoint. - * @param timeout The time to wait (in seconds) for the activity to - * complete. - * @param listener - */ - public BlindTransferActivityImpl(Call call, final Call.OperandChannel channelToTransfer, final EndPoint transferTarget, - final CallerID toCallerID, boolean autoAnswer, long timeout, - final ActivityCallback listener) - { - super("BlindTransferActivity", listener); - - this._call = call; - this._channelToTransfer = channelToTransfer; - this._transferTarget = transferTarget; - this._toCallerID = toCallerID; - this._autoAnswer = autoAnswer; - this._timeout = timeout; - - actualChannelToTransfer = _call.getOperandChannel(this._channelToTransfer); - - this.startActivity(true); - } - - public BlindTransferActivityImpl(Channel agentChannel, EndPoint transferTarget, CallerID toCallerID, boolean autoAnswer, - int timeout, ActivityCallback iCallback) throws PBXException - { - super("BlindTransferActivity", iCallback); - - this._transferTarget = transferTarget; - this._toCallerID = toCallerID; - this._autoAnswer = autoAnswer; - this._timeout = timeout; - actualChannelToTransfer = agentChannel; - _channelToTransfer = OperandChannel.ORIGINATING_PARTY; - this._call = new CallImpl(agentChannel, CallDirection.OUTBOUND); - this.startActivity(true); - - } - - @Override - public boolean doActivity() throws PBXException - { - - boolean success = false; - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - /* - * initiate a blind transfer of the call , to the specified destination. - * when a link event occurs this call will be removed from the active - * call list. - */ - try - { - - logger.debug("*******************************************************************************"); - logger.info("*********** begin blind transfer ****************"); - logger.info("*********** " + this._channelToTransfer + " ****************"); - logger.debug("*********** " + this._transferTarget + " ****************"); - logger.debug("*********** " + this._toCallerID + " ****************"); - logger.debug("*******************************************************************************"); - - if (!pbx.moveChannelToAgi(actualChannelToTransfer)) - { - throw new PBXException("Channel: " + this._channelToTransfer + " couldn't be moved to agi"); - } - - if (!pbx.waitForChannelToQuiescent(actualChannelToTransfer, 3000)) - throw new PBXException( - "Channel: " + this._channelToTransfer + " cannot be transfered as it is still in transition."); - - // Set or clear the auto answer header. - // Clearing is important as it may have been set during the - // initial answer sequence. If we don't clear it then then transfer - // target will be auto-answered, which is fun but bad. - String sipHeader = null; - if (this._autoAnswer) - { - sipHeader = PBXFactory.getActiveProfile().getAutoAnswer(); - } - actualChannelToTransfer.setCurrentActivityAction(new AgiChannelActivityBlindTransfer( - this._transferTarget.getFullyQualifiedName(), sipHeader, _toCallerID.getNumber())); - - // TODO: At one point we were adding the /n option to the end of the - // channel to get around - // secondary transfer options. Need to review if this is still - // required. - // TODO control the caller id. - this._latch = new CountDownLatch(1); - - success = this._latch.await(this._timeout, TimeUnit.SECONDS); - if (!success) - { - this._completionCause = CompletionCause.TIMEOUT; - } - else if (_completionCause == CompletionCause.CANCELLED) - { - logger.warn("Cancelled, hanging up dialed channel"); - pbx.hangup(dialedChannel); - } - - else - { - Call call = ((CallImpl) _call).split(actualChannelToTransfer); - Call rhsCall = new CallImpl(_transferTargetChannel, CallDirection.OUTBOUND); - try - { - _newCall = ((CallImpl) call).join(OperandChannel.ORIGINATING_PARTY, rhsCall, - OperandChannel.ORIGINATING_PARTY, CallDirection.OUTBOUND); - } - catch (Exception e) - { - logger.error("New call doesn't seem to exist!?"); - } - } - } - catch (final Exception e) - { - logger.error("error occurred in blindtransfer", e); - this.setLastException(new PBXException(e)); - } - - return this._completionCause == CompletionCause.BRIDGED; - } - - @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); - - required.add(BridgeEvent.class); - required.add(LinkEvent.class); - required.add(UnlinkEvent.class); - required.add(HangupEvent.class); - required.add(DialEvent.class); - return required; - } - - @Override - synchronized public void onManagerEvent(final ManagerEvent event) - { - if (event instanceof BridgeEvent) - { - BridgeEvent bridge = (BridgeEvent) event; - if (bridge.isLink()) - { - if (bridge.getChannel1().isSame(_call.getOperandChannel(this._channelToTransfer))) - { - this._completionCause = CompletionCause.BRIDGED; - this._transferTargetChannel = bridge.getChannel2(); - this._latch.countDown(); - } - else if (bridge.getChannel2().isSame(_call.getOperandChannel(this._channelToTransfer))) - { - this._completionCause = CompletionCause.BRIDGED; - this._transferTargetChannel = bridge.getChannel1(); - this._latch.countDown(); - } - } - } - else if (event instanceof HangupEvent) - { - HangupEvent hangup = (HangupEvent) event; - if (hangup.getChannel().isSame(_call.getOperandChannel(this._channelToTransfer))) - { - this._completionCause = CompletionCause.HANGUP; - this._latch.countDown(); - } - if (hangup.getChannel().isSame(dialedChannel)) - { - this._completionCause = CompletionCause.HANGUP; - this._latch.countDown(); - } - } - else if (event instanceof DialEvent) - { - if (((DialEvent) event).getChannel().isSame(_call.getOperandChannel(_channelToTransfer))) - { - DialEvent de = (DialEvent) event; - dialedChannel = de.getDestination(); - } - } - - } - - @Override - public ListenerPriority getPriority() - { - return ListenerPriority.NORMAL; - } - - @Override - public CompletionCause getCompletionCause() - { - return this._completionCause; - } - - /** - * cancels the BlindTransfer. - */ - @Override - public void cancel() - { - this._completionCause = CompletionCause.CANCELLED; - this._latch.countDown(); - } - - @Override - public Channel getChannelToTransfer() - { - return _call.getOperandChannel(this._channelToTransfer); - } - - @Override - public CallerID getTransferTargetCallerID() - { - return this._toCallerID; - } - - @Override - public EndPoint getTransferTarget() - { - return this._transferTarget; - } - - @Override - public Channel getTransferTargetChannel() - { - return this._transferTargetChannel; - } - - @Override - public Call getNewCall() throws PBXException - { - return _newCall; - } -} +package org.asteriskjava.pbx.internal.activity; + +import java.util.HashSet; +import java.util.Objects; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.asteriskjava.pbx.ActivityCallback; +import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.Call.OperandChannel; +import org.asteriskjava.pbx.CallDirection; +import org.asteriskjava.pbx.CallImpl; +import org.asteriskjava.pbx.CallerID; +import org.asteriskjava.pbx.Channel; +import org.asteriskjava.pbx.EndPoint; +import org.asteriskjava.pbx.ListenerPriority; +import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.activities.BlindTransferActivity; +import org.asteriskjava.pbx.agi.AgiChannelActivityBlindTransfer; +import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.DialEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +/** + * The BlindTransferActivity is used by the AsteriksPBX to transfer a live + * channel to an endpoint that may need to be dialed. + * + * @author bsutton + */ +public class BlindTransferActivityImpl extends ActivityHelper implements BlindTransferActivity +{ + private static final Log logger = LogFactory.getLog(BlindTransferActivityImpl.class); + + private final Call _call; + + private Call.OperandChannel _channelToTransfer; + + private EndPoint _transferTarget; + + private CallerID _toCallerID; + + private boolean _autoAnswer; + + private CountDownLatch _latch; + + private CompletionCause _completionCause; + + private long _timeout; + + /** + * The new channel that was originated for the transferTarget endpoint. + */ + private Channel _transferTargetChannel; + + private CallImpl _newCall; + + private Channel dialedChannel; + + final Channel actualChannelToTransfer; + + /** + * Blind transfers a live channel to a given endpoint which may need to be + * dialed. When we dial the endpoint we display the 'toCallerID'. + * + * @param channelToTransfer The channel which is being transfered + * @param transferTarget The target to transfer (connect) the channel to. + * @param toCallerID The caller id to display on the target endpoint. + * @param timeout The time to wait (in seconds) for the activity to + * complete. + * @param listener + */ + public BlindTransferActivityImpl(Call call, final Call.OperandChannel channelToTransfer, final EndPoint transferTarget, + final CallerID toCallerID, boolean autoAnswer, long timeout, + final ActivityCallback listener) + { + super("BlindTransferActivity", listener); + + this._call = Objects.requireNonNull(call); + this._channelToTransfer = channelToTransfer; + this._transferTarget = transferTarget; + this._toCallerID = toCallerID; + this._autoAnswer = autoAnswer; + this._timeout = timeout; + + actualChannelToTransfer = _call.getOperandChannel(this._channelToTransfer); + + this.startActivity(true); + } + + public BlindTransferActivityImpl(Channel agentChannel, EndPoint transferTarget, CallerID toCallerID, boolean autoAnswer, + int timeout, ActivityCallback iCallback) throws PBXException + { + super("BlindTransferActivity", iCallback); + + this._transferTarget = transferTarget; + this._toCallerID = toCallerID; + this._autoAnswer = autoAnswer; + this._timeout = timeout; + actualChannelToTransfer = agentChannel; + _channelToTransfer = OperandChannel.ORIGINATING_PARTY; + this._call = new CallImpl(agentChannel, CallDirection.OUTBOUND); + this.startActivity(true); + + } + + @Override + public boolean doActivity() throws PBXException + { + + boolean success = false; + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + /* + * initiate a blind transfer of the call , to the specified destination. + * when a link event occurs this call will be removed from the active + * call list. + */ + try + { + + logger.debug("*******************************************************************************"); + logger.info("*********** begin blind transfer ****************"); + logger.info("*********** " + this._channelToTransfer + " ****************"); + logger.debug("*********** " + this._transferTarget + " ****************"); + logger.debug("*********** " + this._toCallerID + " ****************"); + logger.debug("*******************************************************************************"); + + if (!pbx.moveChannelToAgi(actualChannelToTransfer)) + { + throw new PBXException("Channel: " + this._channelToTransfer + " couldn't be moved to agi"); + } + + if (!pbx.waitForChannelToQuiescent(actualChannelToTransfer, 3000)) + throw new PBXException( + "Channel: " + this._channelToTransfer + " cannot be transfered as it is still in transition."); + + // Set or clear the auto answer header. + // Clearing is important as it may have been set during the + // initial answer sequence. If we don't clear it then then transfer + // target will be auto-answered, which is fun but bad. + String sipHeader = null; + if (this._autoAnswer) + { + sipHeader = PBXFactory.getActiveProfile().getAutoAnswer(); + } + actualChannelToTransfer.setCurrentActivityAction(new AgiChannelActivityBlindTransfer( + this._transferTarget.getFullyQualifiedName(), sipHeader, _toCallerID.getNumber())); + + // TODO: At one point we were adding the /n option to the end of the + // channel to get around + // secondary transfer options. Need to review if this is still + // required. + // TODO control the caller id. + this._latch = new CountDownLatch(1); + + success = this._latch.await(this._timeout, TimeUnit.SECONDS); + if (!success) + { + this._completionCause = CompletionCause.TIMEOUT; + } + else if (_completionCause == CompletionCause.CANCELLED) + { + logger.warn("Cancelled, hanging up dialed channel"); + pbx.hangup(dialedChannel); + } + + else + { + Call call = ((CallImpl) _call).split(actualChannelToTransfer); + Call rhsCall = new CallImpl(_transferTargetChannel, CallDirection.OUTBOUND); + try + { + _newCall = ((CallImpl) call).join(OperandChannel.ORIGINATING_PARTY, rhsCall, + OperandChannel.ORIGINATING_PARTY, CallDirection.OUTBOUND); + } + catch (Exception e) + { + logger.error("New call doesn't seem to exist!?"); + } + } + } + catch (final Exception e) + { + logger.error("error occurred in blindtransfer", e); + this.setLastException(new PBXException(e)); + } + + return this._completionCause == CompletionCause.BRIDGED; + } + + @Override + public HashSet> requiredEvents() + { + HashSet> required = new HashSet<>(); + + required.add(BridgeEvent.class); + required.add(LinkEvent.class); + required.add(UnlinkEvent.class); + required.add(HangupEvent.class); + required.add(DialEvent.class); + return required; + } + + @Override + synchronized public void onManagerEvent(final ManagerEvent event) + { + if (event instanceof BridgeEvent) + { + BridgeEvent bridge = (BridgeEvent) event; + if (bridge.isLink()) + { + if (bridge.getChannel1().isSame(_call.getOperandChannel(this._channelToTransfer))) + { + this._completionCause = CompletionCause.BRIDGED; + this._transferTargetChannel = bridge.getChannel2(); + this._latch.countDown(); + } + else if (bridge.getChannel2().isSame(_call.getOperandChannel(this._channelToTransfer))) + { + this._completionCause = CompletionCause.BRIDGED; + this._transferTargetChannel = bridge.getChannel1(); + this._latch.countDown(); + } + } + } + else if (event instanceof HangupEvent) + { + HangupEvent hangup = (HangupEvent) event; + if (hangup.getChannel().isSame(_call.getOperandChannel(this._channelToTransfer))) + { + this._completionCause = CompletionCause.HANGUP; + this._latch.countDown(); + } + if (hangup.getChannel().isSame(dialedChannel)) + { + this._completionCause = CompletionCause.HANGUP; + this._latch.countDown(); + } + } + else if (event instanceof DialEvent) + { + DialEvent dialEvent = (DialEvent) event; + if (dialEvent.getChannel() != null) + { + Channel operandChannel = _call.getOperandChannel(_channelToTransfer); + if (dialEvent.getChannel().isSame(operandChannel)) + { + DialEvent de = (DialEvent) event; + dialedChannel = de.getDestination(); + } + } + } + + } + + @Override + public ListenerPriority getPriority() + { + return ListenerPriority.NORMAL; + } + + @Override + public CompletionCause getCompletionCause() + { + return this._completionCause; + } + + /** + * cancels the BlindTransfer. + */ + @Override + public void cancel() + { + this._completionCause = CompletionCause.CANCELLED; + this._latch.countDown(); + } + + @Override + public Channel getChannelToTransfer() + { + return _call.getOperandChannel(this._channelToTransfer); + } + + @Override + public CallerID getTransferTargetCallerID() + { + return this._toCallerID; + } + + @Override + public EndPoint getTransferTarget() + { + return this._transferTarget; + } + + @Override + public Channel getTransferTargetChannel() + { + return this._transferTargetChannel; + } + + @Override + public Call getNewCall() throws PBXException + { + return _newCall; + } +} From 8fe3e4cb2601dbe3ea2f187b006e0dc1596df1b4 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 28 Jan 2020 14:12:36 +1100 Subject: [PATCH 258/802] clean up java 11 warnings --- .../fastagi/AbstractMappingStrategy.java | 24 ++++++------ .../live/internal/QueueManager.java | 31 ++++++++-------- .../manager/event/QueueMemberEvent.java | 37 +++++++++---------- .../manager/event/SkypeChatMessageEvent.java | 8 ++-- .../manager/internal/ResponseBuilderImpl.java | 2 +- .../pbx/agi/config/AgiMappingStragegy.java | 20 ++++++---- .../pbx/agi/config/ConfiguableAGIServer.java | 7 +++- .../pbx/asterisk/wrap/events/ReloadEvent.java | 8 +++- .../internal/core/CoherentEventFactory.java | 17 ++++++--- .../FastScannerSpeedTestOnSocket.java | 11 +++--- 10 files changed, 93 insertions(+), 72 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java b/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java index b78607c7a..bcf043784 100644 --- a/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java +++ b/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java @@ -28,8 +28,7 @@ import org.asteriskjava.util.LogFactory; /** - * Abstract base class for common mapping strategies. - *
    + * Abstract base class for common mapping strategies.
    * If you implement your own mapping strategy you can derive from this class. * * @author srt @@ -42,7 +41,7 @@ public abstract class AbstractMappingStrategy implements MappingStrategy */ protected Log logger = LogFactory.getLog(getClass()); private static final String[] DEFAULT_SCRIPT_PATH = new String[]{"agi"}; - + private ClassLoader defaultClassLoader = null; @Override @@ -55,11 +54,14 @@ public AgiScript determineScript(AgiRequest request, AgiChannel channel) /** * Returns the ClassLoader to use for loading AgiScript classes and load - * other resources like the mapping properties file.

    - * 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.

    - * You can override this method if you prefer using a different class loader. + * other resources like the mapping properties file. + *

    + * 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. + *

    + * 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. @@ -75,7 +77,7 @@ protected synchronized ClassLoader getClassLoader() for (String scriptPathEntry : DEFAULT_SCRIPT_PATH) { final File scriptDir = new File(scriptPathEntry); - if (! scriptDir.isDirectory()) + if (!scriptDir.isDirectory()) { continue; } @@ -105,7 +107,7 @@ protected synchronized ClassLoader getClassLoader() * Creates a new instance of an AGI script. * * @param className Class name of the AGI script. The class must implement - * {@link AgiScript}. + * {@link AgiScript}. * @return the created instance of the AGI script class. If the instance * can't be created an error is logged and null is * returned. @@ -113,7 +115,7 @@ protected synchronized ClassLoader getClassLoader() @SuppressWarnings("unchecked") protected AgiScript createAgiScriptInstance(String className) { - Class tmpClass; + Class< ? > tmpClass; Class agiScriptClass; Constructor constructor; AgiScript agiScript; diff --git a/src/main/java/org/asteriskjava/live/internal/QueueManager.java b/src/main/java/org/asteriskjava/live/internal/QueueManager.java index 360bd5dda..ce41982bc 100644 --- a/src/main/java/org/asteriskjava/live/internal/QueueManager.java +++ b/src/main/java/org/asteriskjava/live/internal/QueueManager.java @@ -306,12 +306,12 @@ private void handleQueueMemberEvent(QueueMemberEvent event) return; } - AsteriskQueueMemberImpl member = queue.getMember(event.getLocation()); + AsteriskQueueMemberImpl member = queue.getMember(event.getInterface()); if (member == null) { - member = new AsteriskQueueMemberImpl(server, queue, event.getLocation(), QueueMemberState.valueOf(event - .getStatus()), event.getPaused(), event.getPenalty(), event.getMembership(), event.getCallsTaken(), - event.getLastCall()); + member = new AsteriskQueueMemberImpl(server, queue, event.getInterface(), + QueueMemberState.valueOf(event.getStatus()), event.getPaused(), event.getPenalty(), + event.getMembership(), event.getCallsTaken(), event.getLastCall()); queue.addMember(member); } @@ -396,7 +396,8 @@ void handleJoinEvent(JoinEvent event) if (queue.getEntry(event.getChannel()) != null) { - logger.error("Ignored duplicate queue entry in queue " + event.getQueue() + " for channel " + event.getChannel()); + logger.error( + "Ignored duplicate queue entry in queue " + event.getQueue() + " for channel " + event.getChannel()); return; } @@ -460,10 +461,10 @@ void handleQueueMemberStatusEvent(QueueMemberStatusEvent event) return; } - AsteriskQueueMemberImpl member = queue.getMemberByLocation(event.getLocation()); + AsteriskQueueMemberImpl member = queue.getMemberByLocation(event.getInterface()); if (member == null) { - logger.error("Ignored QueueMemberStatusEvent for unknown member " + event.getLocation()); + logger.error("Ignored QueueMemberStatusEvent for unknown member " + event.getInterface()); return; } @@ -481,10 +482,10 @@ void handleQueueMemberPausedEvent(QueueMemberPausedEvent event) return; } - AsteriskQueueMemberImpl member = queue.getMemberByLocation(event.getLocation()); + AsteriskQueueMemberImpl member = queue.getMemberByLocation(event.getInterface()); if (member == null) { - logger.error("Ignored QueueMemberPausedEvent for unknown member " + event.getLocation()); + logger.error("Ignored QueueMemberPausedEvent for unknown member " + event.getInterface()); return; } @@ -573,12 +574,12 @@ public void handleQueueMemberAddedEvent(QueueMemberAddedEvent event) return; } - AsteriskQueueMemberImpl member = queue.getMember(event.getLocation()); + AsteriskQueueMemberImpl member = queue.getMember(event.getInterface()); if (member == null) { - member = new AsteriskQueueMemberImpl(server, queue, event.getLocation(), QueueMemberState.valueOf(event - .getStatus()), event.getPaused(), event.getPenalty(), event.getMembership(), event.getCallsTaken(), - event.getLastCall()); + member = new AsteriskQueueMemberImpl(server, queue, event.getInterface(), + QueueMemberState.valueOf(event.getStatus()), event.getPaused(), event.getPenalty(), + event.getMembership(), event.getCallsTaken(), event.getLastCall()); } queue.addMember(member); @@ -598,11 +599,11 @@ public void handleQueueMemberRemovedEvent(QueueMemberRemovedEvent event) return; } - final AsteriskQueueMemberImpl member = queue.getMember(event.getLocation()); + final AsteriskQueueMemberImpl member = queue.getMember(event.getInterface()); if (member == null) { logger.error("Ignored QueueMemberRemovedEvent for unknown agent name: " + event.getMemberName() + " location: " - + event.getLocation() + " queue: " + event.getQueue()); + + event.getInterface() + " queue: " + event.getQueue()); return; } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java index 381bf39a8..d61646a53 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java @@ -50,6 +50,7 @@ public class QueueMemberEvent extends ResponseEvent */ private static final long serialVersionUID = 0L; private String queue; + @SuppressWarnings("unused") private String location; private String membership; private String name; @@ -63,8 +64,6 @@ public class QueueMemberEvent extends ResponseEvent private String pausedreason; private String _interface; - - /** * @param source */ @@ -94,7 +93,8 @@ public void setQueue(String queue) } /** - * Returns the name of the member's interface.

    + * Returns the name of the member's interface. + *

    * E.g. the channel name or agent group. * * @return the name of the member's interface. @@ -115,11 +115,11 @@ final public void setInterface(String _interface) } /** - * Returns the name of the member's interface.

    + * Returns the name of the member's interface. + *

    * E.g. the channel name or agent group. * * @deprecated since Asterisk 12 - * * @return the name of the member's interface. */ @Deprecated @@ -132,14 +132,13 @@ final public String getLocation() * Sets the name of the member's interface. * * @deprecated since Asterisk 12 - * * @param member the name of the member's interface. */ @Deprecated final public void setLocation(String _interface) { if ((_interface != null) && (!"null".equals(_interface))) - { // Location is not in use since asterisk 12 + { // Location is not in use since asterisk 12 this._interface = _interface; } } @@ -284,7 +283,6 @@ public void setLastCall(Long lastCall) *

    Device is ringing and in use
    *
    AST_DEVICE_ONHOLD (8)
    *
    Device is on hold
    - * * * @return the status of this queue member or null if this @@ -313,8 +311,8 @@ public void setStatus(Integer status) * Available since Asterisk 1.2. * * @return Boolean.TRUE if this member has been paused, - * Boolean.FALSE if not or null if - * pausing is not supported by your version of Asterisk. + * Boolean.FALSE if not or null if pausing + * is not supported by your version of Asterisk. * @since 0.2 */ public Boolean getPaused() @@ -335,7 +333,8 @@ public void setPaused(Boolean paused) /** * Returns the name of the member. * - * @return the name of the member supplied for logging when the member is added + * @return the name of the member supplied for logging when the member is + * added * @since 1.0.0 */ public String getName() @@ -351,10 +350,12 @@ public void setName(String name) /** * Returns the name of the member. * - * @return the name of the member supplied for logging when the member is added + * @return the name of the member supplied for logging when the member is + * added * @deprecated since 1.0.0. Use {@link #getName()} instead. */ - @Deprecated public String getMemberName() + @Deprecated + public String getMemberName() { return name; } @@ -381,26 +382,24 @@ public void setStateinterface(String stateinterface) /** * @return 1 if is incall 0 if not */ - public Integer getIncall() + public Integer getIncall() { return incall; } - public void setIncall(Integer incall) + public void setIncall(Integer incall) { this.incall = incall; } - - public String getPausedreason() + public String getPausedreason() { return pausedreason; } - public void setPausedreason(String pausedreason) + public void setPausedreason(String pausedreason) { this.pausedreason = pausedreason; } - } diff --git a/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java b/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java index f8d4f37d9..67ce040bc 100644 --- a/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java @@ -16,14 +16,16 @@ */ package org.asteriskjava.manager.event; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import org.asteriskjava.util.Base64; /** - * A SkypeChatMessageEvent is triggered when a Skype Chat message is sent or received.

    - * It is implemented in chan_skye.c.

    + * A SkypeChatMessageEvent is triggered when a Skype Chat message is sent or + * received. + *

    + * It is implemented in chan_skye.c. + *

    * Available with Skype for Asterisk. * * @since 1.0.0 diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java index bdeb91964..223210165 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java @@ -64,7 +64,7 @@ else if (responseClass == null) { try { - response = responseClass.newInstance(); + response = responseClass.getDeclaredConstructor().newInstance(); } catch (Exception ex) { diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java b/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java index 6ae110963..3f1bf3038 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java @@ -23,6 +23,7 @@ */ package org.asteriskjava.pbx.agi.config; +import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -74,16 +75,14 @@ public AgiScript determineScript(AgiRequest request, AgiChannel channel) { try { - ret = handlers.get(script).newInstance(); + ret = handlers.get(script).getDeclaredConstructor().newInstance(); } - catch (InstantiationException e) - { - logger.error(e, e); - } - catch (IllegalAccessException e) + catch (IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException + | InstantiationException | IllegalAccessException e) { logger.error(e, e); } + } return ret; @@ -97,14 +96,19 @@ public AgiScript determineScript(AgiRequest request, AgiChannel channel) * @throws DuplicateScriptException * @throws IllegalAccessException * @throws InstantiationException + * @throws SecurityException + * @throws NoSuchMethodException + * @throws InvocationTargetException + * @throws IllegalArgumentException */ @SuppressWarnings("unchecked") public void addServiceAgiScript(Class< ? extends ServiceAgiScript> handler) - throws DuplicateScriptException, InstantiationException, IllegalAccessException + throws DuplicateScriptException, InstantiationException, IllegalAccessException, IllegalArgumentException, + InvocationTargetException, NoSuchMethodException, SecurityException { logger.info("loading agi handler {}" + handler.getCanonicalName()); - ServiceAgiScript tmpHandler = handler.newInstance(); + ServiceAgiScript tmpHandler = handler.getDeclaredConstructor().newInstance(); if (handlers.containsKey(tmpHandler.getScriptName())) { throw new DuplicateScriptException("Script " + tmpHandler.getScriptName() + " already exists"); diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java b/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java index f981a5ed4..aeccd167e 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java @@ -22,6 +22,7 @@ */ package org.asteriskjava.pbx.agi.config; +import java.lang.reflect.InvocationTargetException; import java.util.List; import javax.naming.ConfigurationException; @@ -32,7 +33,8 @@ public class ConfiguableAGIServer extends DefaultAgiServer implements Runnable { public ConfiguableAGIServer(AgiConfiguration configuration) - throws DuplicateScriptException, InstantiationException, IllegalAccessException, ConfigurationException + throws DuplicateScriptException, InstantiationException, IllegalAccessException, ConfigurationException, + IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { AgiMappingStragegy mappingStrategy = new AgiMappingStragegy(); setMaximumPoolSize(500); @@ -44,7 +46,8 @@ public ConfiguableAGIServer(AgiConfiguration configuration) } private void loadHandlers(AgiMappingStragegy mappingStrategy, AgiConfiguration configuration) - throws DuplicateScriptException, InstantiationException, IllegalAccessException + throws DuplicateScriptException, InstantiationException, IllegalAccessException, IllegalArgumentException, + InvocationTargetException, NoSuchMethodException, SecurityException { List> handlers = configuration.getAgiHandlers(); for (Class< ? extends ServiceAgiScript> clazz : handlers) diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java index 4a236c971..71424c7a9 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java @@ -1,8 +1,12 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -public class ReloadEvent extends ManagerEvent { +public class ReloadEvent extends ManagerEvent +{ - public ReloadEvent(final org.asteriskjava.manager.event.ReloadEvent event) { + private static final long serialVersionUID = 1L; + + public ReloadEvent(final org.asteriskjava.manager.event.ReloadEvent event) + { super(event); } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java index 1599917b9..c90c6c39f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java @@ -174,12 +174,17 @@ public static ResponseEvent build(org.asteriskjava.manager.event.ResponseEvent e public static ManagerResponse build(org.asteriskjava.manager.response.ManagerResponse response) { ManagerResponse result; - if (response instanceof org.asteriskjava.manager.response.CommandResponse) { - result = new CommandResponse((org.asteriskjava.manager.response.CommandResponse) response); - } else if (response instanceof org.asteriskjava.manager.response.ManagerError) { - result = new ManagerError(response); - } else { - result = new ManagerResponse(response); + if (response instanceof org.asteriskjava.manager.response.CommandResponse) + { + result = new CommandResponse(response); + } + else if (response instanceof org.asteriskjava.manager.response.ManagerError) + { + result = new ManagerError(response); + } + else + { + result = new ManagerResponse(response); } return result; diff --git a/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTestOnSocket.java b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTestOnSocket.java index d4844921e..125493749 100644 --- a/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTestOnSocket.java +++ b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerSpeedTestOnSocket.java @@ -24,7 +24,9 @@ public void testScannerSpeed() throws Exception for (int i = 10; i-- > 0;) { - InputStreamReader reader = getReader(); + Socket echoSocket = new Socket("127.0.0.1", FastScannerTestSocketSource.portNumber); + + InputStreamReader reader = getReader(echoSocket); System.out.print("Scanner " + i + ":\t"); long start = System.currentTimeMillis(); @@ -57,11 +59,9 @@ public void testScannerSpeed() throws Exception } } - private InputStreamReader getReader() throws UnknownHostException, IOException, InterruptedException + private InputStreamReader getReader(Socket echoSocket) throws UnknownHostException, IOException, InterruptedException { - Socket echoSocket = new Socket("127.0.0.1", FastScannerTestSocketSource.portNumber); - InputStream inputStream = echoSocket.getInputStream(); InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); @@ -92,8 +92,9 @@ private void fastScannerSpeedTest(Pattern pattern) throws Exception { for (int i = 10; i-- > 0;) { + Socket echoSocket = new Socket("127.0.0.1", FastScannerTestSocketSource.portNumber); - InputStreamReader reader = getReader(); + InputStreamReader reader = getReader(echoSocket); System.out.print("Fast " + i + ":\t"); FastScanner scanner = FastScannerFactory.getReader(reader, pattern); From 5364570a0be71823254825958afa0f69b66f3f75 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 11:59:07 +1100 Subject: [PATCH 259/802] fix for memory leak --- .../pbx/internal/asterisk/MeetmeRoom.java | 1 + .../pbx/internal/asterisk/MeetmeRoomControl.java | 6 +++--- .../asteriskjava/pbx/internal/core/ChannelProxy.java | 12 +++++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java index cfd3ab204..722953b9b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java @@ -158,6 +158,7 @@ public void setInactive() this.channels.clear(); this.forceClose = false; this.lastUpdated = null; + this.owner = null; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index 8426910e2..a39f4cfa0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -125,10 +125,10 @@ public synchronized MeetmeRoom findAvailableRoom(RoomOwner newOwner) { final long elapsedTime = now - lastUpdated.getTime(); MeetmeRoomControl.logger - .debug("room: " + room.getRoomNumber() + " count: " + count + " elapsed: " + elapsedTime); - if ((elapsedTime > 7200000) && (room.getChannelCount() == 1)) + .error("room: " + room.getRoomNumber() + " count: " + count + " elapsed: " + elapsedTime); + if ((elapsedTime > 1800000) && (room.getChannelCount() < 2)) { - MeetmeRoomControl.logger.debug("clearing room"); //$NON-NLS-1$ + MeetmeRoomControl.logger.error("clearing room"); //$NON-NLS-1$ room.setInactive(); } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index c5b470db0..4662d6932 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -41,7 +41,7 @@ public class ChannelProxy implements Channel, ChannelHangupListener private ChannelImpl _channel; - private List listeners = new CopyOnWriteArrayList<>(); + private final List listeners = new CopyOnWriteArrayList<>(); public ChannelProxy(ChannelImpl channel) { @@ -240,6 +240,8 @@ public String getExtendedChannelName() return this._channel.getExtendedChannelName(); } + private volatile boolean hangupCalled = false; + @Override public void notifyHangupListeners(Integer cause, String causeText) { @@ -248,6 +250,14 @@ public void notifyHangupListeners(Integer cause, String causeText) listener.channelHangup(this, cause, causeText); } + if (hangupCalled) + { + logger.error("Hangup was already called and the listeners removed - OH NO"); + } + // we will blow up if notify listeners is called again + hangupCalled = true; + listeners.clear(); + } @Override From 6d607af4fc4e48bf53dbc4d87e96674311f4e08d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 16:12:42 +1100 Subject: [PATCH 260/802] attept to setup deploy action --- .github/workflows/maven.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 91106d3f4..24dce9e88 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -15,3 +15,9 @@ jobs: java-version: 1.8 - name: Build with Maven run: mvn -B package --file pom.xml + + - name: Deploy to Github Package Registry + env: + GITHUB_USERNAME: x-access-token + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: mvn --settings settings.xml deploy From d06903ec476913b298cdc739441dac92c96402c7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 16:17:47 +1100 Subject: [PATCH 261/802] add setting for git publish --- settings.xml | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 settings.xml diff --git a/settings.xml b/settings.xml new file mode 100644 index 000000000..1854d58a1 --- /dev/null +++ b/settings.xml @@ -0,0 +1,39 @@ + + + + github + + + + + github + + + central + https://repo1.maven.org/maven2 + + true + + + true + + + + github + Asterisk-Java + https://maven.pkg.github.com/asterisk-java + + + + + + + + github + ${env.GITHUB_USERNAME} + ${env.GITHUB_TOKEN} + + + \ No newline at end of file From 3f3ac2c0c3ce826aa890f8f5e94add229dc1cb89 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 16:23:39 +1100 Subject: [PATCH 262/802] test action --- pom.xml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index c8492c322..a326cdec9 100644 --- a/pom.xml +++ b/pom.xml @@ -69,20 +69,7 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - - - - ${distribution.id} - ${distribution.name} - ${distribution.url} - - - - ${snapshot.distribution.id} - ${snapshot.distribution.name} - ${snapshot.distribution.url} - - + From e88ce41a73bb7340bd2142c68c4181b79acdb824 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 16:28:11 +1100 Subject: [PATCH 263/802] test action --- pom.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a326cdec9..64a65fc44 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,14 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - + + + github + + + github + + From f17601a4a22815071e1444f82ba8409606e84837 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 16:31:47 +1100 Subject: [PATCH 264/802] test action --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 64a65fc44..3176d0fd5 100644 --- a/pom.xml +++ b/pom.xml @@ -72,9 +72,11 @@ github + https://maven.pkg.github.com/asterisk-java github + https://maven.pkg.github.com/asterisk-java From d4fcaea944d2b3e08065f18743bcbb404f589851 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 16:44:15 +1100 Subject: [PATCH 265/802] test action --- .github/workflows/maven.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 24dce9e88..c04e1eb5d 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -13,11 +13,9 @@ jobs: uses: actions/setup-java@v1 with: java-version: 1.8 - - name: Build with Maven - run: mvn -B package --file pom.xml - name: Deploy to Github Package Registry env: GITHUB_USERNAME: x-access-token GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: mvn --settings settings.xml deploy + run: mvn deploy From d3440ae2c689e638cf5623933b4e62b77309e61b Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 16:52:06 +1100 Subject: [PATCH 266/802] test action --- settings.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/settings.xml b/settings.xml index 1854d58a1..cec7116cf 100644 --- a/settings.xml +++ b/settings.xml @@ -20,11 +20,6 @@ true - - github - Asterisk-Java - https://maven.pkg.github.com/asterisk-java - From 4930821b2caf0a1228373feff3da43832cda9a59 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 16:58:36 +1100 Subject: [PATCH 267/802] test action --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3176d0fd5..e90004944 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 3.0.2-SNAPSHOT + 3.0.3 The free Java library for Asterisk PBX integration. 2004 From 2fca00fc89cd8b1221368ad5d5d363c1e397df67 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 17:04:22 +1100 Subject: [PATCH 268/802] test action --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e90004944..7d5978c08 100644 --- a/pom.xml +++ b/pom.xml @@ -72,11 +72,11 @@ github - https://maven.pkg.github.com/asterisk-java + https://maven.pkg.github.com/asterisk-java/asterisk-java github - https://maven.pkg.github.com/asterisk-java + https://maven.pkg.github.com/asterisk-java/asterisk-java From 75d6f0f4dc6ec0e802f65cfdbc1e325b47c0da44 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 17:26:15 +1100 Subject: [PATCH 269/802] test action --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7d5978c08..70dd8c38c 100644 --- a/pom.xml +++ b/pom.xml @@ -72,11 +72,11 @@ github - https://maven.pkg.github.com/asterisk-java/asterisk-java + https://maven.pkg.github.com/bsutton/asterisk-java github - https://maven.pkg.github.com/asterisk-java/asterisk-java + https://maven.pkg.github.com/bsutton/asterisk-java From 7237b03cf8812e12334918b2a6bf54360f01be82 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Feb 2020 17:29:52 +1100 Subject: [PATCH 270/802] test action --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 70dd8c38c..7d1bb0b6e 100644 --- a/pom.xml +++ b/pom.xml @@ -72,11 +72,11 @@ github - https://maven.pkg.github.com/bsutton/asterisk-java + https://maven.pkg.github.com/bsutton/asterisk-java/asterisk-java github - https://maven.pkg.github.com/bsutton/asterisk-java + https://maven.pkg.github.com/bsutton/asterisk-java/asterisk-java From 2110e5728b1910633923ad08cae1d4b8552cd6de Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 10 Feb 2020 09:16:53 +1100 Subject: [PATCH 271/802] test action --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index c04e1eb5d..e5891291c 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -18,4 +18,4 @@ jobs: env: GITHUB_USERNAME: x-access-token GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: mvn deploy + run: mvn deploy -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=GITHUB_TOKEN From 5aea51159cd60614a88a296ad6940c626abd3ea9 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 10 Feb 2020 09:19:27 +1100 Subject: [PATCH 272/802] test action --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index e5891291c..e4c8739f2 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -18,4 +18,4 @@ jobs: env: GITHUB_USERNAME: x-access-token GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: mvn deploy -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=GITHUB_TOKEN + run: mvn deploy -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=${GITHUB_TOKEN} From 3406319de0bccf9795b83b65ba59dea1220c1445 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 10 Feb 2020 09:24:25 +1100 Subject: [PATCH 273/802] test action --- pom.xml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index 7d1bb0b6e..494c1c74d 100644 --- a/pom.xml +++ b/pom.xml @@ -69,16 +69,7 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - - - github - https://maven.pkg.github.com/bsutton/asterisk-java/asterisk-java - - - github - https://maven.pkg.github.com/bsutton/asterisk-java/asterisk-java - - + From 935e67a0440ad5da8f955726fdbcdea1f6021d6f Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 10 Feb 2020 09:33:35 +1100 Subject: [PATCH 274/802] test action --- pom.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 494c1c74d..035950fbe 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,16 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - + + + github + https://maven.pkg.github.com/noojee/asterisk-java/asterisk-java + + + github + https://maven.pkg.github.com/noojee/asterisk-java/asterisk-java + + From 3c8b3c351221f29691e5823659d1bc0bb9f74247 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 10 Feb 2020 09:35:33 +1100 Subject: [PATCH 275/802] test action --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 035950fbe..7d5978c08 100644 --- a/pom.xml +++ b/pom.xml @@ -72,11 +72,11 @@ github - https://maven.pkg.github.com/noojee/asterisk-java/asterisk-java + https://maven.pkg.github.com/asterisk-java/asterisk-java github - https://maven.pkg.github.com/noojee/asterisk-java/asterisk-java + https://maven.pkg.github.com/asterisk-java/asterisk-java From fbad1764567ecc747a67ebea07a5fe4502e1a8b0 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 10 Feb 2020 09:43:32 +1100 Subject: [PATCH 276/802] test action --- settings.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/settings.xml b/settings.xml index cec7116cf..bace1d49c 100644 --- a/settings.xml +++ b/settings.xml @@ -20,6 +20,11 @@ true + + github + GitHub OWNER Apache Maven Packages + https://maven.pkg.github.com/asterisk-java/asterisk-java + From a21761696b14801495ad62850211bc96f18aa96c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 10 Feb 2020 09:51:14 +1100 Subject: [PATCH 277/802] test action --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index e4c8739f2..6f6d67e38 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -18,4 +18,4 @@ jobs: env: GITHUB_USERNAME: x-access-token GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: mvn deploy -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=${GITHUB_TOKEN} + run: mvn deploy --stacktrace -DskipTests=true -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=${GITHUB_TOKEN} From 4c4a99e9a2a49b04f62c28641d3f0e67d0e58d56 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 10 Feb 2020 09:53:07 +1100 Subject: [PATCH 278/802] test action --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 6f6d67e38..696902d69 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -18,4 +18,4 @@ jobs: env: GITHUB_USERNAME: x-access-token GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: mvn deploy --stacktrace -DskipTests=true -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=${GITHUB_TOKEN} + run: mvn deploy -e -DskipTests=true -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=${GITHUB_TOKEN} From 7be1655105561c2f182ebfac6294a6b90244bcd0 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 10 Feb 2020 10:03:18 +1100 Subject: [PATCH 279/802] test build 3.0.4 --- .github/workflows/maven.yml | 2 +- pom.xml | 2 +- settings.xml | 69 +++++++++++++++++++------------------ 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 696902d69..e4c8739f2 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -18,4 +18,4 @@ jobs: env: GITHUB_USERNAME: x-access-token GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: mvn deploy -e -DskipTests=true -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=${GITHUB_TOKEN} + run: mvn deploy -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=${GITHUB_TOKEN} diff --git a/pom.xml b/pom.xml index 7d5978c08..857fb4d54 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 3.0.3 + 3.0.4 The free Java library for Asterisk PBX integration. 2004 diff --git a/settings.xml b/settings.xml index bace1d49c..17620bd4c 100644 --- a/settings.xml +++ b/settings.xml @@ -1,39 +1,40 @@ - - - github - + + github + - - - github - - - central - https://repo1.maven.org/maven2 - - true - - - true - - - - github - GitHub OWNER Apache Maven Packages - https://maven.pkg.github.com/asterisk-java/asterisk-java - - - - + + + github + + + central + https://repo1.maven.org/maven2 + + true + + + true + + + + github + GitHub OWNER Apache Maven Packages + https://maven.pkg.github.com/asterisk-java/asterisk-java + + + + - - - github - ${env.GITHUB_USERNAME} - ${env.GITHUB_TOKEN} - - + + + github + ${env.GITHUB_USERNAME} + ${env.GITHUB_TOKEN} + + \ No newline at end of file From c32a81346a189f518cd8325c568800eae902ba1f Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 10 Feb 2020 10:14:02 +1100 Subject: [PATCH 280/802] test action --- .github/workflows/maven.yml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index e4c8739f2..696902d69 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -18,4 +18,4 @@ jobs: env: GITHUB_USERNAME: x-access-token GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: mvn deploy -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=${GITHUB_TOKEN} + run: mvn deploy -e -DskipTests=true -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=${GITHUB_TOKEN} diff --git a/pom.xml b/pom.xml index 857fb4d54..509be2999 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 3.0.4 + 3.0.5 The free Java library for Asterisk PBX integration. 2004 From a3dc303067ed0a08c12f54f043c6ab64fadae58f Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 13:21:58 +1100 Subject: [PATCH 281/802] test action --- pom.xml | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/pom.xml b/pom.xml index 509be2999..1fb6a3ea8 100644 --- a/pom.xml +++ b/pom.xml @@ -89,29 +89,6 @@ true - - biz.aQute.bnd - bnd-maven-plugin - 3.2.0 - - - - bnd-process - - - - - - org.apache.maven.plugins - maven-release-plugin - 2.5.3 - - true - false - release - deploy - - org.apache.maven.plugins maven-compiler-plugin From de13b05d71a05de56676b20ac9d1490009b723a7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 13:23:39 +1100 Subject: [PATCH 282/802] test action --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 1fb6a3ea8..6ce426ae2 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 3.0.5 + 3.0.6 The free Java library for Asterisk PBX integration. 2004 @@ -72,11 +72,11 @@ github - https://maven.pkg.github.com/asterisk-java/asterisk-java + https://maven.pkg.github.com/asterisk-java github - https://maven.pkg.github.com/asterisk-java/asterisk-java + https://maven.pkg.github.com/asterisk-java From 8e92bf586708ce3fa7f0a1772a638898f3bb4cdb Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 13:28:25 +1100 Subject: [PATCH 283/802] test action --- .github/workflows/maven.yml | 2 +- pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 696902d69..c33f45e0e 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -18,4 +18,4 @@ jobs: env: GITHUB_USERNAME: x-access-token GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: mvn deploy -e -DskipTests=true -Dregistry=https://maven.pkg.github.com/asterisk-java -Dtoken=${GITHUB_TOKEN} + run: mvn deploy -e -DskipTests=true -Dregistry=https://maven.pkg.github.com/asterisk-java diff --git a/pom.xml b/pom.xml index 6ce426ae2..8c3b590aa 100644 --- a/pom.xml +++ b/pom.xml @@ -72,11 +72,11 @@ github - https://maven.pkg.github.com/asterisk-java + https://maven.pkg.github.com/asterisk-java/asterisk-java github - https://maven.pkg.github.com/asterisk-java + https://maven.pkg.github.com/asterisk-java/asterisk-java From 4d98547d3ff143a068eb0c584be4e80503bd306d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 13:33:09 +1100 Subject: [PATCH 284/802] reinstate plugins and test action --- pom.xml | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8c3b590aa..7adf4d62f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java Asterisk-Java - 3.0.6 + 3.0.7 The free Java library for Asterisk PBX integration. 2004 @@ -89,6 +89,29 @@ true + + biz.aQute.bnd + bnd-maven-plugin + 3.2.0 + + + + bnd-process + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + true + false + release + deploy + + org.apache.maven.plugins maven-compiler-plugin From e717b3909419dd0bebadd4aabd212d83192f7a7c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 14:34:36 +1100 Subject: [PATCH 285/802] for version 3.0.12 --- .dart_tool/.gitignore | 1 + .dart_tool/pub/bin/.gitignore | 1 + .dart_tool/pub/bin/dshell/.gitignore | 3 + .gitignore | 1 + pom.xml | 21 ++- pubspec.lock | 194 +++++++++++++++++++++++++++ pubspec.yaml | 12 ++ triggerRelease.dart | 48 +++++++ 8 files changed, 276 insertions(+), 5 deletions(-) create mode 100644 .dart_tool/.gitignore create mode 100644 .dart_tool/pub/bin/.gitignore create mode 100644 .dart_tool/pub/bin/dshell/.gitignore create mode 100644 pubspec.lock create mode 100644 pubspec.yaml create mode 100755 triggerRelease.dart diff --git a/.dart_tool/.gitignore b/.dart_tool/.gitignore new file mode 100644 index 000000000..b5a718a86 --- /dev/null +++ b/.dart_tool/.gitignore @@ -0,0 +1 @@ +/package_config.json diff --git a/.dart_tool/pub/bin/.gitignore b/.dart_tool/pub/bin/.gitignore new file mode 100644 index 000000000..35623abbf --- /dev/null +++ b/.dart_tool/pub/bin/.gitignore @@ -0,0 +1 @@ +/sdk-version diff --git a/.dart_tool/pub/bin/dshell/.gitignore b/.dart_tool/pub/bin/dshell/.gitignore new file mode 100644 index 000000000..b650a938e --- /dev/null +++ b/.dart_tool/pub/bin/dshell/.gitignore @@ -0,0 +1,3 @@ +/dshell.dart.snapshot.dart2 +/dshell_complete.dart.snapshot.dart2 +/dshell_install.dart.snapshot.dart2 diff --git a/.gitignore b/.gitignore index 647fe6c60..b0fc6c27c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ classes build/ /.settings/ /.metadata/ +/.packages diff --git a/pom.xml b/pom.xml index 7adf4d62f..4fc265dbf 100644 --- a/pom.xml +++ b/pom.xml @@ -1,13 +1,19 @@ - 4.0.0 org.asteriskjava asterisk-java Asterisk-Java - 3.0.7 + ${releaseVersion} The free Java library for Asterisk PBX integration. 2004 + + + 3.0.12 + + The Apache License, Version 2.0 @@ -149,18 +155,23 @@ attach-sources deploy - jar-no-fork + + jar-no-fork + - + maven-deploy-plugin deploy deploy - deploy + + deploy + diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 000000000..b9b4a261d --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,194 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + args: + dependency: "direct main" + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.2" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.14.12" + csv: + dependency: transitive + description: + name: csv + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.3" + dshell: + dependency: "direct main" + description: + name: dshell + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.3" + equatable: + dependency: transitive + description: + name: equatable + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0" + file_utils: + dependency: transitive + description: + name: file_utils + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" + globbing: + dependency: transitive + description: + name: globbing + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.3" + logger: + dependency: transitive + description: + name: logger + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.3" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.6" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.8" + money2: + dependency: transitive + description: + name: money2 + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + path: + dependency: "direct main" + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.4" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.2" + pubspec: + dependency: transitive + description: + name: pubspec + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2+1" + recase: + dependency: transitive + description: + name: recase + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.3" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + uri: + dependency: transitive + description: + name: uri + url: "https://pub.dartlang.org" + source: hosted + version: "0.11.3+1" + utf: + dependency: transitive + description: + name: utf + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.0+5" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" +sdks: + dart: ">=2.7.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 000000000..e3067123e --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,12 @@ +name: asterisk_java_installer +version: 1.0.0 +environment: + sdk: '>=2.7.0 <3.0.0' +dependencies: + dshell: ^1.4.3 + args: ^1.5.2 + path: ^1.6.4 + + + + diff --git a/triggerRelease.dart b/triggerRelease.dart new file mode 100755 index 000000000..ce815524e --- /dev/null +++ b/triggerRelease.dart @@ -0,0 +1,48 @@ +#! /usr/bin/env dshell +import 'dart:io'; + +import 'package:dshell/dshell.dart'; + +/// comment + +void main() { + int major; + int minor; + int rev = 0; + read("pom.xml").forEach((line) { + if (line.contains("")) { + var parts = line.split("."); + if (parts.length != 3) { + exit(1); + } + major = int.parse(parts[0].split(">")[1]); + minor = int.parse(parts[1]); + rev = int.parse(parts[2].split("<")[0]); + } + }); + rev++; + + String version = "$major.$minor.$rev"; + + replace("pom.xml", version); + 'git add .'.run; + 'git commit -m "for version $version"'.run; + 'git tag -a $version -m "$version"'.run; + 'git push origin tag $version'.run; +} + +void replace(String path, version) { + var tmp = '$path.tmp'; + if (exists(tmp)) { + delete(tmp); + } + read(path).forEach((line) { + if (line.contains("")) { + line = " $version"; + } + tmp.append(line); + }); + move(path, '$path.bak'); + move(tmp, path); + delete('$path.bak'); +} From 20637d55faa17776fb2a1b7f2082a988a253db38 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 15:16:23 +1100 Subject: [PATCH 286/802] for version 3.0.13 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4fc265dbf..55fd05ef9 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.0.12 + 3.0.13 From 7a5fd1d7e60bae7e49aaeae00653468f93a4ebfb Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 15:44:34 +1100 Subject: [PATCH 287/802] for version 3.0.18 --- pom.xml | 2 +- triggerRelease.dart | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 55fd05ef9..316d7f322 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.0.13 + 3.0.18 diff --git a/triggerRelease.dart b/triggerRelease.dart index ce815524e..dd8089beb 100755 --- a/triggerRelease.dart +++ b/triggerRelease.dart @@ -9,7 +9,9 @@ void main() { int major; int minor; int rev = 0; - read("pom.xml").forEach((line) { + var dir = dirname(Settings().scriptPath); + print(dir); + read(join(dir, "pom.xml")).forEach((line) { if (line.contains("")) { var parts = line.split("."); if (parts.length != 3) { @@ -24,7 +26,9 @@ void main() { String version = "$major.$minor.$rev"; - replace("pom.xml", version); + replace(join(dir, "pom.xml"), version); + + 'git pull'.run; 'git add .'.run; 'git commit -m "for version $version"'.run; 'git tag -a $version -m "$version"'.run; From b9fb40b08d77e44817d12d2faceecdd897614eeb Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 16:43:42 +1100 Subject: [PATCH 288/802] try nexus --- .github/workflows/nexus.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/nexus.yml diff --git a/.github/workflows/nexus.yml b/.github/workflows/nexus.yml new file mode 100644 index 000000000..3dbcd58be --- /dev/null +++ b/.github/workflows/nexus.yml @@ -0,0 +1,28 @@ +name: Release + +# Run workflow on commits to the `master` branch +on: + push: + branches: + - master + +jobs: + release: + runs-on: ubuntu-18.04 + steps: + - name: Check out Git repository + uses: actions/checkout@v2 + + - name: Install Java and Maven + uses: actions/setup-java@v1 + with: + java-version: 1.8 + + - name: Release Maven package + uses: samuelmeuli/action-maven-publish@v1 + with: + gpg_private_key: ${{ secrets.gpg_private_key }} + gpg_passphrase: ${{ secrets.gpg_passphrase }} + nexus_username: ${{ secrets.nexus_username }} + nexus_password: ${{ secrets.nexus_password }} + From 9c59c8872c9aa9cb96a7977f1e806e56fc4d4bdb Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 16:44:10 +1100 Subject: [PATCH 289/802] for version 3.0.19 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 316d7f322..25e40869d 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.0.18 + 3.0.19 From b5c98f6d8bc945786f12983c4be2decce25fb692 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 16:52:25 +1100 Subject: [PATCH 290/802] test action --- pom.xml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 25e40869d..ec5ab2cdc 100644 --- a/pom.xml +++ b/pom.xml @@ -76,14 +76,14 @@ https://github.com/asterisk-java/asterisk-java - - github - https://maven.pkg.github.com/asterisk-java/asterisk-java - - github - https://maven.pkg.github.com/asterisk-java/asterisk-java + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2 + @@ -277,6 +277,17 @@ + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.5 + true + + ossrh + https://oss.sonatype.org/ + true + + From ee46ad5443e42a4f052a6453522f15d215b3d71c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 17:03:31 +1100 Subject: [PATCH 291/802] test action --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index ec5ab2cdc..5d939e1f5 100644 --- a/pom.xml +++ b/pom.xml @@ -258,6 +258,7 @@

    ${project.name}
    + org.apache.maven.plugins maven-gpg-plugin From e6f7212b4195531551c80d55bdb5080a8e0df721 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 17:08:13 +1100 Subject: [PATCH 292/802] test action --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5d939e1f5..e209a4a4a 100644 --- a/pom.xml +++ b/pom.xml @@ -236,7 +236,7 @@ attach-javadocs - jar + deploy From 76f6d9fcda9e5cc04f92b1e8546f5cb1ad1d3442 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 17:12:51 +1100 Subject: [PATCH 293/802] test action --- pom.xml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index e209a4a4a..3c1fad907 100644 --- a/pom.xml +++ b/pom.xml @@ -161,20 +161,20 @@ - - - maven-deploy-plugin - - - deploy - deploy - - deploy - - - - + + --> + + + + + + + + + + + ${project.artifactId} From 5d9261722173c0af7faa59075c89816bb4a1f6ed Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 17:13:40 +1100 Subject: [PATCH 294/802] test action --- pom.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3c1fad907..a9a0b31c9 100644 --- a/pom.xml +++ b/pom.xml @@ -162,8 +162,6 @@ - --> From 18118dda822890f5b0b6d5db908415c675763af9 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 17:27:13 +1100 Subject: [PATCH 295/802] test action --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index a9a0b31c9..dd281a868 100644 --- a/pom.xml +++ b/pom.xml @@ -229,12 +229,12 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.1 + 2.10.3 attach-javadocs - deploy + jar @@ -279,7 +279,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.5 + 1.6.7 true ossrh From f6c21dae0338804459318eaec27f697d528b20d1 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 17:30:24 +1100 Subject: [PATCH 296/802] test action --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dd281a868..ca51c5564 100644 --- a/pom.xml +++ b/pom.xml @@ -210,7 +210,7 @@ - release + deploy From be759553672a7fa21ac73bb10157aef93996cbb7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 17:32:57 +1100 Subject: [PATCH 297/802] test action --- pom.xml | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index ca51c5564..ec053f254 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.0.19 + 3.0.19 @@ -161,18 +161,18 @@ - - - - - - - - - - - - + + + + + + + + + + + + ${project.artifactId} @@ -239,6 +239,14 @@ + + -Xdoclint:all -Xdoclint:-missing + -Xdoclint:all -Xdoclint:-missing + + -Xdoclint:all + -Xdoclint:-missing + + Core Packages @@ -256,7 +264,7 @@
    ${project.name}
    - + org.apache.maven.plugins maven-gpg-plugin From b3345dcd1b79894ac45d36793fc25893aa3db053 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 11 Feb 2020 17:38:24 +1100 Subject: [PATCH 298/802] test action --- pom.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index ec053f254..0e2fc1d3c 100644 --- a/pom.xml +++ b/pom.xml @@ -240,11 +240,10 @@ - -Xdoclint:all -Xdoclint:-missing - -Xdoclint:all -Xdoclint:-missing + -Xdoclint:none + -Xdoclint:none - -Xdoclint:all - -Xdoclint:-missing + -Xdoclint:none From f789b2f305e8e232c8c79f8118a92fd29708bc7c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 10:28:53 +1100 Subject: [PATCH 299/802] test action --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0e2fc1d3c..25c495688 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,6 @@ The free Java library for Asterisk PBX integration. 2004 - 3.0.19 From 75dc4b49d38d46ff1df606e3a19c47948100bc5d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 10:34:11 +1100 Subject: [PATCH 300/802] test action --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 25c495688..a5096d607 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,6 @@ ${releaseVersion} The free Java library for Asterisk PBX integration. 2004 - 3.0.19 From f3f07624607ecf8316fadbdf9ce416ae28580b35 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 10:38:20 +1100 Subject: [PATCH 301/802] test action --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index a5096d607..25c495688 100644 --- a/pom.xml +++ b/pom.xml @@ -8,6 +8,7 @@ ${releaseVersion} The free Java library for Asterisk PBX integration. 2004 + 3.0.19 From 06c29482198b026bcfb5c73b93b8cecd4305bc29 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 10:43:51 +1100 Subject: [PATCH 302/802] fix for signing --- pom.xml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 25c495688..35e957b14 100644 --- a/pom.xml +++ b/pom.xml @@ -266,7 +266,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.5 + 1.6 EA919AF2 @@ -274,11 +274,16 @@ sign-artifacts verify - sign - + + + + --pinentry-mode + loopback + + From b68be378a1beafb39145a7495f3f64dc2e40b06f Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 10:49:27 +1100 Subject: [PATCH 303/802] test action --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 35e957b14..2b4e0c9cb 100644 --- a/pom.xml +++ b/pom.xml @@ -9,6 +9,7 @@ The free Java library for Asterisk PBX integration. 2004 + 3.0.19 From 7d65bdb0cc640513dd053049fab4538c60dc4585 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 10:58:47 +1100 Subject: [PATCH 304/802] fix for sources sigining --- pom.xml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index 2b4e0c9cb..f914959ba 100644 --- a/pom.xml +++ b/pom.xml @@ -149,18 +149,18 @@ - - maven-source-plugin - - - attach-sources - deploy - - jar-no-fork - - - - + + + + + + + + + + + + From 520e21b11addd85fa33b40b0cb7881576a36074f Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 11:21:40 +1100 Subject: [PATCH 305/802] remove unneeded configs --- .github/workflows/maven.yml | 21 --------------------- pom.xml | 24 ------------------------ 2 files changed, 45 deletions(-) delete mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml deleted file mode 100644 index c33f45e0e..000000000 --- a/.github/workflows/maven.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Java CI - -on: [push] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - - name: Deploy to Github Package Registry - env: - GITHUB_USERNAME: x-access-token - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: mvn deploy -e -DskipTests=true -Dregistry=https://maven.pkg.github.com/asterisk-java diff --git a/pom.xml b/pom.xml index f914959ba..21e65ab10 100644 --- a/pom.xml +++ b/pom.xml @@ -149,30 +149,6 @@
    - - - - - - - - - - - - - - - - - - - - - - - - ${project.artifactId} From 25045d1fd71125d27cff06b3b751cae1dab5b03b Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 11:22:21 +1100 Subject: [PATCH 306/802] fix merge conflict --- pom.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 65d543105..53ff11f40 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,7 @@ 3.0.19 + UTF-8 @@ -85,9 +86,7 @@ https://oss.sonatype.org/service/local/staging/deploy/maven2 - - UTF-8 - + From f1e46de7accde45dcddf6a647a7a7634d96a9ccf Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 11:22:39 +1100 Subject: [PATCH 307/802] work on release script --- triggerRelease.dart | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/triggerRelease.dart b/triggerRelease.dart index dd8089beb..09dddb2f0 100755 --- a/triggerRelease.dart +++ b/triggerRelease.dart @@ -13,6 +13,7 @@ void main() { print(dir); read(join(dir, "pom.xml")).forEach((line) { if (line.contains("")) { + line = line.replaceFirst("-SNAPSHOT", ""); var parts = line.split("."); if (parts.length != 3) { exit(1); @@ -22,9 +23,17 @@ void main() { rev = int.parse(parts[2].split("<")[0]); } }); - rev++; - String version = "$major.$minor.$rev"; + var postFix = ""; + if (confirm(prompt: "Is this a SNAPSHOT release")) { + postFix = "-SNAPSHOT"; + rev++; + } else { + rev = 0; + minor++; + } + + String version = "$major.$minor.$rev$postFix"; replace(join(dir, "pom.xml"), version); @@ -35,7 +44,7 @@ void main() { 'git push origin tag $version'.run; } -void replace(String path, version) { +void replace(String path, String version) { var tmp = '$path.tmp'; if (exists(tmp)) { delete(tmp); From 38d8a250ffb030d6da0f52e549726a55d59ac4f5 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 11:22:52 +1100 Subject: [PATCH 308/802] for version 3.0.20-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 53ff11f40..b0f3390d9 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.0.19 + 3.0.20-SNAPSHOT UTF-8 From dc4069d9d84c86dd9cc3e3f13f652d09911856b1 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 11:27:36 +1100 Subject: [PATCH 309/802] update release script --- triggerRelease.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triggerRelease.dart b/triggerRelease.dart index 09dddb2f0..2e905d402 100755 --- a/triggerRelease.dart +++ b/triggerRelease.dart @@ -25,7 +25,7 @@ void main() { }); var postFix = ""; - if (confirm(prompt: "Is this a SNAPSHOT release")) { + if (confirm(prompt: "Is this a SNAPSHOT release (y/n)?")) { postFix = "-SNAPSHOT"; rev++; } else { From ba7b9f35f2c79506cf747ad7af055b3268448769 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 11:33:39 +1100 Subject: [PATCH 310/802] only release for tags --- .github/workflows/nexus.yml | 6 +++--- triggerRelease.dart | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/nexus.yml b/.github/workflows/nexus.yml index 3dbcd58be..3cd1e8344 100644 --- a/.github/workflows/nexus.yml +++ b/.github/workflows/nexus.yml @@ -1,10 +1,10 @@ name: Release -# Run workflow on commits to the `master` branch +# Run workflow on tags on: push: - branches: - - master + tags: + - '*' jobs: release: diff --git a/triggerRelease.dart b/triggerRelease.dart index 2e905d402..831ff1096 100755 --- a/triggerRelease.dart +++ b/triggerRelease.dart @@ -41,6 +41,7 @@ void main() { 'git add .'.run; 'git commit -m "for version $version"'.run; 'git tag -a $version -m "$version"'.run; + 'git push origin'.run; 'git push origin tag $version'.run; } From 04bb008fe6ea8023c55408564fab67387b8f7f3c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 11:38:35 +1100 Subject: [PATCH 311/802] setup for push to maven central --- pom.xml | 61 ++++++++++++++++++++++++++++++++------------ pubspec.yaml | 12 +++++++++ triggerRelease.dart | 62 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 16 deletions(-) create mode 100644 pubspec.yaml create mode 100644 triggerRelease.dart diff --git a/pom.xml b/pom.xml index dd224e463..dc84ea5b7 100644 --- a/pom.xml +++ b/pom.xml @@ -1,13 +1,20 @@ - 4.0.0 org.asteriskjava asterisk-java Asterisk-Java - 2.0.4-SNAP-SHOT + ${releaseVersion} The free Java library for Asterisk PBX integration. 2004 + + + 2.0.4-SNAPSHOT + UTF-8 + + The Apache License, Version 2.0 @@ -70,18 +77,16 @@ https://github.com/asterisk-java/asterisk-java + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + - internal - file://${project.build.directory}/mvn-repo + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2 - - GitHub - https://github.com/asterisk-java/asterisk-java/issues - - - UTF-8 - + @@ -183,7 +188,7 @@ - release + deploy @@ -202,7 +207,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.1 + 2.10.3 attach-javadocs @@ -212,6 +217,13 @@ + + -Xdoclint:none + -Xdoclint:none + + -Xdoclint:none + + Core Packages @@ -229,10 +241,11 @@
    ${project.name}
    + org.apache.maven.plugins maven-gpg-plugin - 1.5 + 1.6 EA919AF2 @@ -240,14 +253,30 @@ sign-artifacts verify - sign - + + + + --pinentry-mode + loopback + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://oss.sonatype.org/ + true + +
    diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 000000000..e3067123e --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,12 @@ +name: asterisk_java_installer +version: 1.0.0 +environment: + sdk: '>=2.7.0 <3.0.0' +dependencies: + dshell: ^1.4.3 + args: ^1.5.2 + path: ^1.6.4 + + + + diff --git a/triggerRelease.dart b/triggerRelease.dart new file mode 100644 index 000000000..831ff1096 --- /dev/null +++ b/triggerRelease.dart @@ -0,0 +1,62 @@ +#! /usr/bin/env dshell +import 'dart:io'; + +import 'package:dshell/dshell.dart'; + +/// comment + +void main() { + int major; + int minor; + int rev = 0; + var dir = dirname(Settings().scriptPath); + print(dir); + read(join(dir, "pom.xml")).forEach((line) { + if (line.contains("")) { + line = line.replaceFirst("-SNAPSHOT", ""); + var parts = line.split("."); + if (parts.length != 3) { + exit(1); + } + major = int.parse(parts[0].split(">")[1]); + minor = int.parse(parts[1]); + rev = int.parse(parts[2].split("<")[0]); + } + }); + + var postFix = ""; + if (confirm(prompt: "Is this a SNAPSHOT release (y/n)?")) { + postFix = "-SNAPSHOT"; + rev++; + } else { + rev = 0; + minor++; + } + + String version = "$major.$minor.$rev$postFix"; + + replace(join(dir, "pom.xml"), version); + + 'git pull'.run; + 'git add .'.run; + 'git commit -m "for version $version"'.run; + 'git tag -a $version -m "$version"'.run; + 'git push origin'.run; + 'git push origin tag $version'.run; +} + +void replace(String path, String version) { + var tmp = '$path.tmp'; + if (exists(tmp)) { + delete(tmp); + } + read(path).forEach((line) { + if (line.contains("")) { + line = " $version"; + } + tmp.append(line); + }); + move(path, '$path.bak'); + move(tmp, path); + delete('$path.bak'); +} From eaa0b55992b989ba897abf810ac37c6100aef671 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 11:39:41 +1100 Subject: [PATCH 312/802] for version 2.1.0 --- .dart_tool/package_config.json | 176 ++++++++++++++++ .../pub/bin/dshell/dshell.dart.snapshot.dart2 | Bin 0 -> 2884872 bytes .../dshell_complete.dart.snapshot.dart2 | Bin 0 -> 2878464 bytes .../dshell/dshell_install.dart.snapshot.dart2 | Bin 0 -> 2884872 bytes .dart_tool/pub/bin/sdk-version | 1 + .packages | 29 +++ pom.xml | 2 +- pubspec.lock | 194 ++++++++++++++++++ triggerRelease.dart | 0 9 files changed, 401 insertions(+), 1 deletion(-) create mode 100644 .dart_tool/package_config.json create mode 100644 .dart_tool/pub/bin/dshell/dshell.dart.snapshot.dart2 create mode 100644 .dart_tool/pub/bin/dshell/dshell_complete.dart.snapshot.dart2 create mode 100644 .dart_tool/pub/bin/dshell/dshell_install.dart.snapshot.dart2 create mode 100644 .dart_tool/pub/bin/sdk-version create mode 100644 .packages create mode 100644 pubspec.lock mode change 100644 => 100755 triggerRelease.dart diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json new file mode 100644 index 000000000..82aa5c22c --- /dev/null +++ b/.dart_tool/package_config.json @@ -0,0 +1,176 @@ +{ + "configVersion": 2, + "packages": [ + { + "name": "args", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/args-1.5.2", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "charcode", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/charcode-1.1.3", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "collection", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/collection-1.14.12", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "csv", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/csv-4.0.3", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "dshell", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/dshell-1.6.1", + "packageUri": "lib/", + "languageVersion": "2.6" + }, + { + "name": "equatable", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/equatable-1.1.0", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "file", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/file-5.1.0", + "packageUri": "lib/", + "languageVersion": "2.2" + }, + { + "name": "file_utils", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/file_utils-0.1.4", + "packageUri": "lib/", + "languageVersion": "2.3" + }, + { + "name": "globbing", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/globbing-0.3.0", + "packageUri": "lib/", + "languageVersion": "2.2" + }, + { + "name": "intl", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/intl-0.16.1", + "packageUri": "lib/", + "languageVersion": "2.5" + }, + { + "name": "io", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/io-0.3.3", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "logger", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/logger-0.8.3", + "packageUri": "lib/", + "languageVersion": "2.1" + }, + { + "name": "matcher", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.6", + "packageUri": "lib/", + "languageVersion": "2.2" + }, + { + "name": "meta", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/meta-1.1.8", + "packageUri": "lib/", + "languageVersion": "1.12" + }, + { + "name": "money2", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/money2-1.3.0", + "packageUri": "lib/", + "languageVersion": "2.1" + }, + { + "name": "path", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/path-1.6.4", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "pub_semver", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/pub_semver-1.4.3", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "pubspec", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/pubspec-0.1.4", + "packageUri": "lib/", + "languageVersion": "2.2" + }, + { + "name": "quiver", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/quiver-2.1.2+1", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "recase", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/recase-3.0.0", + "packageUri": "lib/", + "languageVersion": "2.6" + }, + { + "name": "source_span", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/source_span-1.6.0", + "packageUri": "lib/", + "languageVersion": "2.6" + }, + { + "name": "stack_trace", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3", + "packageUri": "lib/", + "languageVersion": "1.23" + }, + { + "name": "string_scanner", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.5", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "term_glyph", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.1.0", + "packageUri": "lib/", + "languageVersion": "1.8" + }, + { + "name": "uri", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/uri-0.11.3+1", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "utf", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/utf-0.9.0+5", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "yaml", + "rootUri": "file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/yaml-2.2.0", + "packageUri": "lib/", + "languageVersion": "2.0" + }, + { + "name": "asterisk_java_installer", + "rootUri": "../", + "packageUri": "lib/", + "languageVersion": "2.7" + } + ], + "generated": "2020-02-12T00:39:05.317797Z", + "generator": "pub", + "generatorVersion": "2.7.1" +} diff --git a/.dart_tool/pub/bin/dshell/dshell.dart.snapshot.dart2 b/.dart_tool/pub/bin/dshell/dshell.dart.snapshot.dart2 new file mode 100644 index 0000000000000000000000000000000000000000..e7f5002572b3aa1bfe1e0befdbfda81ac1d8daac GIT binary patch literal 2884872 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

    IvC!zgy$m+}A$I3n$AB-}1& z-AY;j3@8C}QpA>dnk~~BlX1My*fR5MF>{oZiK)-^?6}xCV{C~rPbP+j z>+g`Mt6yK}$Xq05UL$3K9FZb4Hl)NLG;<3D+A|+iXhM5=m=~ zq|L@qD-(v;`a7t3y_xSDF`t<+zp)rc)=)9)94QM1OQcw13@W&?re`Jg)+{R}CTpQN z_RP9L%(`95f_#}(GRB@LBnv7C2xUQo-*K-aD@V*Kk+Q&r5!l9%6IIH>fB{v?>M^R6 zgV$QahoE=7?Ip}!qJRs(jNI4+Z zod-@XH0Ka6{bHU+%6qU!*uX|?rm2-jrdEPC5AwHRj6JW%pkUrp_?E_*pQ#*q z-`ewjG#~|1Rd~E*cz+=e4x$+b9=b$Q&Ay~q30#|$T=OM>q z%G;#X^C1n$9cXmruggb`m1>6RDt==A##P8G=VL-rd)!1nu!Xnfr>XfqWO`eBJfOSs z_vBXtj5)y1Z_@K29(UQO6Pr0V|6xA=sr+Z4+@m|v^N$S6e*r004CL5YVp#sm@J%}f zJ+scAl@GfEQDXi(!%U~49?gM%{&)GufDM*@0THplV#`0S=KmhSg~t2C3P244jt?}B zf-`Id;;@2Y2&o*zX-@>!KuX1eOSOUt2!j4%8PKUxG*`I-7JtDFoU1@BNR3LRSWs#! zD6kb|>A0$iDuz?%q^|;(GOaBZRA~i!7%WW88%q36DDDJ*K_{@+{YmA`8$h)qFYqD0Z>{gYy?toO{1O*9(d0`rQ4?M70F!@1D2Nhn5^dA6oJffWD`dyxAjcjF(HO4=wo&2@g>pT7n6j zyWd40x*J3Gdj;X?1=I%GGjTrWhvNW|U z3n6Zd9?L36%CvcR<0IgS)UqA~|7RTT38o>8xaU6@&QMlmDEnM?j=TrWxABos49D-8 zwu;{~1GJ2M>DmJ!Ltf{e2Y6+VOm3@wT1xqV@-su{aQvmHHg74%&OtcvZLgfhZ+*qA zd@=&Gr>QTBe3Z31%4dk>3#9T{J;LUQekbWDzZTSWly4HtACSw@Uv8e($HFY9udI&p z%8~Z+8hxk$BcvS0^Bm6Iwkzqxq~ zO$t`T+A1z|SDX)jCmWLBSdWS;;0ukLRgr=tXeu^UY=ydyi*gWeuh^y!f*NyIfJ-)a za*hhWts=)$0S4LpJ!24pQDwq7#3jzFc(dY%ijPpf$r+xCuP80bcUAJxshEu*ym)&h zzWM^PS{d6T+Vmev5*36z`*f5o4NHR^U zgf_T$5ukLAv{!cPr-N8(<>LfduRM%b8mZaT%6A#OL}zFauY`t>$Eu&65(l0lNv7cgBbcl z4nc;uoYp52M|RR!J$wOWvWF)dU3wUO&K90a@P+44dV6@Oq58tmA6ri2Tw$iWF9a$N zb2I0M-L`PKJ)9H14uwkL5|&pP8@|E9hYzn01LM#j`7+F7C!~f^=Pdzy_){iWQuuq8 zc2@W}b}5ctUp1N~wXvjCm_9(#sw<6k0aY`Nq*aTM^uF~~_pziijieqUX)wfA2vk7` zf&HwiGR{%eB35-PRUMSTtTtA=IICVjwV5nd{h?I-M6t?BU@uogx1omN8#%su=qkSY zY_x$nw@`fn<`$|GXl`L}O3fEFzwG@9tweiLcuUPOcrXpd^R@l)?kj+n+7Sq0Dg|eC z)Y2_3(0jGC0!w?2JP5qZ45Y8c5e-?p*a&1vATYJpj}mKdmuheB5$>xptFnQ&)ozn& zH&c+QA!}1f4r{Aw8~ey%?Sa}?Yo7q35jm`Vp0bb})*iLhexlaC-y>|j%HVWI?QbKM zTBytWUI3d0>L9XPFCLdTt8Ox+vTjM;ij$oMk^$fz;S zQGb=aeh$+@dOh^x)}wLC5E81h>Tied$5ZU}8yPR?^-yD5k8+OsfW1D$%z!BeWWa?o zEJK@_p_}oUUjL|>;Z1w}Q8U9QECcB|A>phBa0r#qa602*yY~wi$Xt155;hvF714eQN9U4-R0F#!LkD>N5lK>hL4fzBeTC~ z6o)mQWdM_(Gb<8i5N7#%*AClDjf+Gw_46DRyH{St z@AdX6c5e~OVCZg`l1&_rM9PB0LfQYqwl z*2L?ZXqQOTK(M-+XiToX*k`7JOGs_P&|}*_Q<`3}G`-UD0207jYI+CnKC@%&Fwv&( zn&=`hvtMue)9BZm(UcEd$jxgW+I(d*X4!a|1oB}{Y@Xn09)q}q$ebJ+rFq`y=EZ8W z6Tvqi)veGX&1?B_j%H}sOrea9&w_^5W`^DpCwJw4xXuYd-^GT|pbqiAk9@@6m-xca?~ zPy!Ndm-CLcCHA)EW}+KdBGLnth%lf;IY`tn(%#l$raH({8M5qed&f-m3qItv54E@3 z^#14tw00`uEwlscBHEYQ+vhNj(b`=sqE`yq?^?yTZ$Sl2bIsolMnJ)6?e=cD{SlD) zLvp`4Qf&WJX-D^Gw!B8WGf)O8A%FXEGZQPXV}-qAzENIBvRR%X^H0^Y5#J{Wty1# z?_)CI*k6hSm1cqlmS7Ue%>Ki~`ul&_4^dZ6hkYPmx&5E4ACM1ltQbb$1F_11;XT66 z3(5TEr32##1Q){EzXO-A;tyOEC9U(oLP+0%HPqz~O*#1N!8f}1f;%8tpyI*z;9*oe z_!-`2&wB7@xZR|~rbY}ii=&GZy9P>K;NqQyeF)WMd?%rG@H-3bUFLU^E@+sYh1~qE zWpdYbaEANyUH7c-x`#ljte#yeFLo8%y8?_yq%Md*GRTD}8A~epuJ-j^?JV_FqDt3O z{7A9uD_hs6_O3S!6RiuqJ#vtVM(C{XwlHHV37r(*Jz{D1m*cdYY^1ehT;!xM2H(UADK&s9-y~OtjflYhxAe6p-kxz)XYO)ne>Hb zJX9_nDyAS)GahOs_BeFp&>MX;*dmLB<0JcN%4xIaD8RWSM!M znPujfK3Qg7VPtV4>Fso__)N5qglU^$DR4i7=d~Vg&OC7V%OD7ELBP8#fEq=B?~`6S z!S_3S+AF=ov&i?_sPgFHW(^z#;>{W=;SVedS&DE!-FiH06a}A4!HjY|@R~K5=?*xO zC>)iVwc5}haNR;doC~gd@z5%kVc^>VJf-p&oDElyr2DrpZYI}5y^42<$T z0v?WXJ@^v-BPg5leL?wt0l{Z|16Ww(!G=;aKdc;i zLS|zgK^dsM7QSg7JTvgD#Nz-p&7K!fXG5pUY4}J6=k0hl^sUJ3`&mUi2$um0gIu`M zfY9t>DkERT9}I7lm-|#?cH4;+nf zoO=U&hFXbgYc$K;&3JY|0-~t%6A?mZlwj2(T=<0GnS+*@n>`YE%`Jd;3B(eVp4&p0 zRU=>>o4$?H-oV5y5pwR+bouh!FHyI-FX}c3YTR;4`yQobg9OlirBxq6RXNtf&4c_o zMx!ckMyoP!C<`*HGB2iYRpyQUS5^80!+DcQGt9fp=q=%z*(0cfjlmB^Uqcm`hkiyq zmo@vmyZNzLv4*f+cy^m3##>3o=9L+J09+vgf(7ANa{}KpsK&g<5wt-W3M9DjT2y!5 z2Ry_B@84F@-+v$ihKYny=bw&3=MRk*I{!i*1`{&PUuH&4W1M-j6xqzEn=w z*2)Pxrg6f~9h~scvz#Dbi~eLgCwR`m^C>52e}aBz;pw+%@sboy&{ttE*aS{kl7wYJ zi&5q}gk3}NEDjD%7@(iSL4+__#;HM$8wv5b1G}c-ql9Q=L62SPdD`=WuiHY~Y%r=( zuf?mMK60t&Z?*pj?I`*O_eR?8q>rH-{Q!;L?02I@k2RJKsn=0}VAaoGs?JguYR|!g z04(Ehk(aT3H_P2-Ya0R+^;J%aa^sp_jJ7-%DvtiFmMJFXRcRb|e|7y8R%)i2aA@^fZ5 z)jTa>xcW!Db~IM&?`A8GGz{ahkXav@AZqb8Z8YNak#YuE_wN0Qb`@eLxwj*7wM|Pg zA~P{u_h=gk5#D{otvv+Se78jEMyv8@r4%94IJE;v3wyzPi&ej1srHigw(lV5 zl7U!kgL#iUoE1BDKEvCfTz?(TlPRYYS41eM(?V2GPM<=72Mo&TiDqC50#DNC`aK9! z*8Ptp)@h92hs0@mWsl%{a;o0gOJcndLD!rw>Ww;cvg3zo1|?R1Tn&L7Q}pL8`t$mS z0EGd+{sMvg9K}tg{Z&r=4c@N5Q8^F7GfaQCM@T*U6r_`9P0_!$=wExmZ!Fh0C*}GT zxqfxu!*czDT#Jy)ET1){%R9sijjJ7H>>KMH<5qx*NgVrBAk9xwWJUtWUf-K=}p z1Ar`NfUzxTS8oPl?sOk;d&6+Z$~x710FGMsc8B*_(fg*`3mxE-N!-U76Gh&yMepw_ zZHDpH_68@2z7e`_FoT_m#F`INPQE8OgByG+bRUMNsj~Y?RE=}*gl&i%d73YcQbl>h zSA&dAEFK_Ze`dgM98W za8!Wz-7sMNo%;D!-M-ZAaWKehBW9kaXt}KBiW1R~Y!X z_feq9+ip4o84T}!9f1)(c7I?79z)ZZfeZVi zI-bkmnu6+hmcy|C+~Bzvj_Z_l9!~}wo22JdPa7P%egVIf69QkOb*ebQPxayPz71jj zVd2zL(8O`vGPq1lJPG(i6H{72zi?T~waOlg_AY!tdm@tc)5k5_v}J^n%hWH|PanTb z@=1XaN}dq_bv$XAM7PI11{fA>d8Iez2&5vky^>2@&q*P2=P@_3=@-%(E>UW;Nlo!e zu0GCv7+h(S4#q2a`gqR$kmVF!A184=LhydL#>?dL42<4DXR+!RFT=js*X0xo=l+Cn zw@7cu#EOt>={>x)bAdnP+9=F|T`_dcw)S5`2&H3&T9si627lmi0o@2$hFy_nHFfI2 zaqjI-`7%CMPShuXXf}Bc!%dbQl!~+J@yq0Eh~9I7%P`E?Ip=|D0>q$k}MyDD+siov&l~z zh>=_?GSt@pBkViiqbS<{ckhyefLIU~g!N(|asnDfL2NM;0TVQI2!s+!EK$MkYv0|w zz1bvpsdwp@MhXc6DqR##>>{tCU@xE`3MwLk1;O9mSF+)q&mS{DQ0Az{Qc!yR42mPSyG<-lsTPA6DwI`0%6rN3%mTgX!4x6hd zBC{;5tlbaPD58J2V9T3<=eS_YpA3x9SAqyY{v8M$f_EkXxE~IZxvKH5Fm-O=vU?aVI3CI#tyw{2S zyrbDj2fKczcanEL?IHCz5r%H`PV$gUcxhHb%|Y{r^#MG$(gcSWS4Dcg?0%9qZ>`fC zbW_C%?hNgS;(ab`D=3E4-7u3Cuo?rli02N%WoOTjhj#F=b$DAyZR|~Wyj=B&S&X*P zQAfNFK+l=|E9GuaWxpE~h*krCtYI_hFk~DR?Ldcd8R+;9?Zp`5rcIlLgFJVDN}G3| zYRpB@aeR;3fOabE#uld-y68516v@F7XX2~0KW3w@Ij8X9+!N&CKRPj-Z2TSP%#KpG zk{-yGoY~#mb0wqNnSF)2lZTCSW?$DKEXl!coSFS@_HO?rAb%7P;`_0mlZXGPH6if< z-mAyw#My8VT*^7unG@Xs$1S9ca$a`kj8Lo5mAJg$*fm+oS>()_)gDXhKUi}P%c;r0 zqNJFWgNZU)oKzTy8lLl(J?AYyjbTu^Id9|b-EXNM+~Gs)%{h?sGwO0aK}BcIFPegC z#@r`KV9$85B zUE>?oE(X3arWp9{a^gf#n>fb$+`5j`st>h`JRlFgXEa|!*j9X*=W60RqthHt-+Lz8 zeW$_p1FG+s8C$Q$HU+^}&=b$Ycrd~!bmRF7CmDkXiN=G;JzMd5D3Iszex3l_4+kle zF~ThBvN3Ck+u&=#*PcopLvn3D#xk-h1UVB_gFVc9ybDdCh&;?)?^iQ>oaa z*tl8B0p*9jo(p+PLA|T0=m74v($_5hf$Vb zS1&c+cDsrWHOhn4S|n9(AUAJQf(iu_<%w&X8Q=|nte6yq4sJYkb%AAYjiatE@Hku( zG;%R~2K6FSZHW$+JWG94ebW6sYG@FZ$*!v8;XjlIlOZvw>NDzESa=89G7^WWFL7a{ z?m|&t1J)zf6vKCzVgU4KMa2}41&!Bwp|-x4w6i76k>I(IjZ^k8Tnvhc+Et2nX$E@jL_ad3qIAWsMq%`-PZWZ@8pe;aiWx4s6>-AAlY;u}A+uhpNd&CTJ zd4G;#Q_|d9+%LzdIe?*Si(=E#+&kTS`+AR}v>d_EC^kLK^MFU~>;0tzY(|>L@2TqR zJ=Os>GfnTV$MyC8+5t8zO}|VZ)z^Ex11v4AW>d}UeZ414*mYtt+UEUfdXwJ7sK2%A z>-ZZcsZM?`wvoaz)ZasU?A!-OC-(6sB@nSr?+i_`!S&I#^%j;WN(w?4N2Y-9;D{$kMa$aS>6?ti$01}HJb*+TN0>rPVY{$(RknI88O^U z^1HxhAi}W(Dyoy6Wkz7S1h~(+HRbaDlxe1#>`lhT8jH4z~%k*-vIce-=_6|FU`-J`gzhGm0$PU6m zKVFF`>=Rr~fiI?m1UB8l($kEOjc;(sLhwS~kia;W9nGUh5*R0NcKQV80Gr`pbJMc7 zWxt($0N1DN;R(=zLt^>Q%pv=Im;n(MIoQ0koH04K=HNzEKKF!g0%znr+$llMVo}Oj z%*)GWIoRSf-&MYA3eX2wc9L%#c?2?6e7C?6v5kDQks)j&UnYPN+sJpn3FLQ~;H+zc z_b;fV;l6CUFS`J}4F6^Du01;07r>E-a?^70)mj{;wPdF+Y}zcow!2FAl!@Pzbe6dn$hts$v=+Qrob`*o}S?S8^VnryB*#qWBqsdX>gw)FiwddpRlb| z{Fu?HIFI^W|9YN>3$_U?EB|+@{|5vOB9ii!SV1<}0{M5jn=nR+&(E^Cm|e=BA?4%l zR7kk8M}NfTeqk_X%yAIXnZL$L6osBX|HA|pZBYZgoqsriIV|rT0$b`}nP~<06x?5U zIe3i1fIys(aFdseqXMiyM~qau3QbHdD35a%RI6KI$w&o_ybZ9KqBeR6hCu~i7JLJR zg#|lWk}WvER|lnnLsl$MQ+T#o7!$TtZsAL^QsG5P;RW#esRUS=g>`smTH(Wmj|VUZ z#Z42@UZ{|V|HwK_F3gT|7Ur4tS6J&T>|l3u>#6VsKDpy8d}T0r?qXfYj4DdtKo@t9 zX>(suG&8nnu4f~U*p==&E5hA!TzHBa?M00NVgvn5;jtwbJ?ku5XXaf54FT1|ra^X+ zi$0Tz4mpdyvUglFfmTfS}f`_pR$}OX zqAXD^@2QmcK;l9(aruRj#2~i3AxlzMOXzVEKEXDG00ib-3+eiZ3dgm zD~rUKDLs5ZDF;Fn zTIKG_FG71o!Sg8S!0!G1p}j;9eyF4#iO$MHrUs$rQu#-_yQ-_DSFTFB0z@XH}~eZ$kpNVkv^N zYI_F)-tXYvXAyHQhzU8Jp(t%NWfF?9x)sdyz&|`R$Q~LLg7HQQEd&+NHi>LXJT!1< z1VYl(znov;R`#DFxx}Fl80yU7v7PXa^68>zM{ITC|CDV zsxhrxHQ^1Brny)zT$JNrccoR2tiGYT0ebfdj;{J9^3ZB;HT4Rf3PL1Q&w<;# zpg<6-Z=--p1mK%1)pyg|oyB#Gv-%N}qt!Kbx!S8#E6BCTLu=AnHB?94N}=&_mpWRl z#+qtfHD*fgPOJX2##S>9#UcLTh(Qc__z%ZyUZ*LS8XQuox!Cs`)pAWjg7+kwhm`lE z)!k8d&x$yt?9EfwJwzU2MBS5kGl^49wh*?FbWN=*s4D@q5BCpAty@ut8ex1dj40Ku zO<)&5t1lcC=dAlL*YsN5p0KU{UZHMh-Ir(&^;fw2q4U$~u^>=?ujqbwFg`Ce-&sGc zqoS|Z&@B3C^^fwD7~?T)*F0ze%kIuK4<$h%QU@FDI}Ik$Hxw$;P_>yzt`$;+dp`cv-u-+=wY&c}2UvzJ3?>lb2o=lJC>FaKou+r$AU z=YV@ThGO*}j>f2S`N8E_7qQM*Q6N6EblSQ6i1r`w*0cQgux)v&pnMAt4i5_r_a-;= z#J7(IN)58!AR#a_l4~hHkv^v3F>DlUsA#AG(o?{99k$vxHeQJIa>H7^0Si6LGtIlI z8fd@#c6>+4+weM|FT@~DzlQ%d;^uR@RH0D>qQ;cQX`njRs-ea^8t;eqB93>YGr3WT zlN)_XqX(tAh0#VK z?MXs zkQ+criTO=0A|LzUF-@P~UWndJCwQ)M)8D-;r=Wb!bHw)$nkClUk7A<($Zo#Es<6Z> znrFv0FJRcyF2*+>jdHO#XLG%K3%pYEN>d74*aOx4m9zO>i`pXy^fn(dshuIDtT+#Q z+xrqi2V0u9V$h1A^ra6kDFl4E<|_W#4@`NlxQWDK;6gi1a<8B%VY8KVn$}KU@m8F3 zh1m$C6?;qq$Y5QuU)@ReAAOt#lMUQlxrOf%XmL4P>l)WeOh!LQ*OzZEGJ9j!!|mO$I|eD zn~>6idT7j4m!T+_susnTHR)mtnjGy$5L+zF2NK zrL~+4+nOelMim-kT=&bZXS?ZRGfmSus9_ljfNr_$xiwv~ zoS-&R^(-y9^>(@SVW}0pIp+uoFfIO5r`}rZY&AO3wF&GSB(=6$S_!!)I$K}kq9?V! z6M-h7SIECahoa;1y_LPi_?0)?eA`OoY^R*mF} z*10N?BbQc<;Yg)bHz#wt+SkwyEer^v&9Tz`PXRZMiQ zGKUP#RY40|g@p}6K*9#1?oC^@dDYf6-O;CAg!DkQlRW%KBqgucjkYj+)t~lNf3E((ik`s-n_}|nj5v99W_t?M@#?1&B9pH0gq*93I#jre4Mr6w ziA-{_A#7<9hQH;P)(#+wCO z^VN6^Jl_bm6_?@pk6>%*0UCSR*aK;6&Rrv|xz~;rJeomL3jxPe%tL8wM&S=b0KvZI zR{lm$x@HFas@ab~nAiifdqY^0p;kbAl{L48Z7t|jL2k>7^ukX}gXc}bRvM4@ZFpV- z5auFa^uvtW!@_Jq=z<}H|6)NH%qPdtH~tZ8vw+i z^fva$Y^{sdgIzF^UCK*<^-q+;KOQSjkIhj^l;wTdWr%HcxqcU4fAUh|D3p!f{D;y! z!b@Y_@aS-`C*~+Cl(hEYGauFL%ym+vxxkM zl3fiUeR_`CU%f)bMRcArGfJZBx1zL{6v||vtWJ^Cu?fTjf3nq0-qXi|$m)y)c7=Z& z=$6zhPKe;2=1(3P`D~8gm7?O1wfcmGz`@ixIP71des62bxnBLANWcmzwKz7cEq`v< zs_%$>RH!KAuc)7gZ7bLLlO4=6NBv3tTYm%bkv%Vgc0PFtkJg{?B=Dkks5g94L>sDI zgLYYlEch4OMj(z$yi!XgmXcdY)#lIz${LpGN_%3pG*i(skm+CSN~#+$%Reev({Q&= zj;49Twr8%jSc3C9Z&37~)-n$L7v^QdqdoG|e z-R{X9Q)3<>)y>=xIEBX&2f5b>vb$-JyArX3Za3`aNM5Bq$(nLuI<6GU6%8Yh@2h6M zpZhQ4`5r-UrJmfswSz zZ}HUgh3D(`((2KI?D=bu=cpjzu4NA>U$w*J?3txa)n(lksSVMo4>!xKPY@)1tVd7e zDI;apr^0&}W!CRe^@Z(a#x+6u(y(oHJeAq2tK_6Ir|7k~DRYaYuT%AA9{sw;8Ie=s z&^xUfo^5#k6l^Om#8Zmr3&FNJgu*&(j9FUA&aQ?`lX5|#D3(22o21?2fS6HziCNkl zdh27OSnh1?KiZRh*+?kF3^a0as6Cn$&&Cz3nnsIZb}hi)aFXW5?r~eP7K(Ff_1q}! zr?oIYH%YZkyu<9LZDoGy9C6LI_C*5Wjn#he-voi_ryWOJmW$POT=2?OVKfWOb`Qqi zlY+KZu)D{@!P}xc6>n;b81-5CinzCXj)~BHr++LEDsHSE<8&BD=^h+G8Jz9uhrb*_ ze@L);QdJ+jG9fItL(lgsc>A8c`sL&NrYd$kkdit3tqa4gX+mr99^Sp-*BYOy) z-P7dhtdl)0xM!+GQy~A6XN%MGtl6=;7im9adEPMD4Go$%+q1{>gXa&JH3_)Nn_8}Q z8Te7pAHYmMUJogrUvcTxubeuT>tKbm^-J|@yw?jNyB2Y<4PhKS=8xM4dTN|gpJvvI zK8I=rQ@Hw4_w%5rpMEFvyV!NYc-^l*uTy8~!3}{>T>bPA%O|s1f7!i($9$3bKT) z=mZMljx`Jy^qbUWXzf_D>-o|z*{GwQ8y7H46<6vWW z7_};e2A?DJ@lmWQU5!(3iDqLXVNUfbE*e=X7eIZyOVxp+I$d3&KJ8#P0Xtz(ALJO4 zqgW_iEyM-`Ha>!Zwz4*-tGn=b0NYne1Uv4WJ3yr1$7!Q`qSamI$_zxdHeFq=u2kQN zY+F&+s_&Sw&FEmh`l8rReT7vxSbe%CYcB1-ZHp}0rP_bnVuLhl_E*Z zg@pCjX0VV`%T%YKL1yuNY$Nn!0S17U*H2U01wDaa7*?lgDAKquxV>16^jet-w&&l%b3(AK_2R*vfwkxdOu5SkSj zt_tTVxG=^)9UTY03gBOYUK{faeq^Uk#~Tu;V%pEY4e!l(@5TFLynn;{S5e4&3?@P^ zyr0HYZ@VEt)pv{?jOK?Rd8%b~8LPPdTXko*jbX`VK9PHsYFkQ?(P2{{X`r+j+_A=r~!O zC#ln%>NxksWU8o|pt|+;V{sS>sVkjoZHK{6ympq|#gZlUOQ-r?r&KPMf?-jL)|*ZZ zIkg0H9+u%^K5dWoIr@}axI{X&FD=>r1{0g^YRuNT1+G&S?T@f+LxPLlO0cme%zXpF z;@yuU*VKOQB{Ug23E`e3cLR}(Q6W5US{~ZMqc5;>o=Tp#tdMEsIc0fp^wH^EW_f17 z!!EEqGs$yJhcs-q<(Y*LBhB)p!IOQP<(Vy{War_41!@{*#>QS?GBo9ydAKWjMb1rj zES*F&B~>GtThxj=jcwMPQH{^d%YGqyTh17&MnY%Lew#e}XI7srIs1b+Ir}Fmd%rXL zBeNoC4W?uD;gY_;MLFk!*c^u`Jsg?9o=Hl{xl$Ygf;Y~`^BUzq&pdecpcFIlj>Gdl zfanhZqaWmUodDxKN`b2JY(mri74NUmWY59-7~YU?Miw|w+1UE|>QkyGTe4%LOS>q0 zHWLrH$~=pSuQ_t|WmuRf=~rD9S>OCgkYsC0-C|DkV;j4(VWprCi7Pr&!MI{@`b z4z_8&x>r4^oda!+K`Jn4Q5tCd2ZqhqyV(U=xl2b3oAnF_+dN-89~%E!4CIcO7=~$N zR?v^vLkjfM5C?lwG3<;eH!t8Hsk$AgOZEH zyAFgrPDe7g&(}O!o;wzdJz>TxBM)?jO{>M*Iy9v{2e$`%FFc#uCIvwkd@xmT1TI#4 z-TYn%pM!s8zB}GMnCv?bSK4;>72MeCf*VFLZi^swxNjk>bOkE9TE60_#7Ev760Q(l{|zpsD9Zb$qcNCaE=0C|LN zIF9op-WF40ywtkSV2YR2RA;7mT>zcI6mK%Y{)H)CV)XxFinjoPo>Tv1rMH;^ND>e> zoU^%I9Qax82sgZ6QOVWwywpx2GQzhRwXuUm$FlAgJ2JqI*XOgl*?kNZqW451?6G;0 zJTzy)bi9?7K#4((DPgQImX%tm7b5i=^YNJ%kv_+wnWmKC;NNCJYJ<#Q_qw*?P}}!> zjnAaG@Zp!_Si^pW23^9GAfMI@p`@jTy#VV;QJBpHpWnArJo% zT|k$G4Lw;2S?omzdvU(;pz*YkBMM~BVfT-2StL9Zku?3XlE-@@cxSQ#KCv&h;(t zw(MT@EH?G(qD4~6m+%Y1Surs!9oj@Ik!h8wmFj~x1)&wznAHS?R+wNNMPF#WivXSV zfYACBfSyz7LTfoWc%v6uNtI}WGwk|#g1z;13b0fnS9Z8@Xg^>PQMVd?>t6)3w4oIb zOV2I4vEs73Guv9AE5Wv$;!bRH3XR#Kh|3s-^cdRwx^+EmMBDl@ZF=3h(@p|8=mPo6{N{}c>Q&vr8ZT`+*(!NL&H zO`L=u{)L2&HiWhbBDx78x~VfI+9pm(?f;}i+w}jVq&*w-;F}iVX~6TXVB35)o~!Y| z4BNa`u)VNMux;@Owik=>>=JA*4a0+>`%4VZdxC9i6rP}93&-PW7Hlt5x6QQ)5WHLf zq%hlF_5+9!8T|Bv+4e4-2kC6KeIf`dv>G?xuEP5mj|;PH&jL)UZfu@mXN!Ra%3~NN z%%a#w3*58Zi(=Rk63h`8l7GCw{f+zk7_|}rwg-Su7I>VVi(^3+*ry9T3p|Ts z-0LDuo2UD1fv3^4Ax4jFhl;~I>nyCFFYx@OUl60@M4EcTh;;Evowfmtz!G6J`(c6Z z#2+#clRAf)1lBN`+a%_O$oR_W_w63squ9 zY75{cqa`K%sW@3@9$gFDw!agZq{m!kg`@`)^jP*8-+JxQ>nI#Mualy&3-lvug4^@q z`h=R{_DZ-urKY&O8Lp41Id0#CJ)%x?CZfB8eYrsYSpP;pE(#Mt5qk5(`f*+@+}1<~ zq5p(Q&tD|{rv&#p_Gx6P-of@R@DBGTeVp{l>=dnkCQP06{BN~L!W7$;_OOn`iJkQ%2ZXJCizCJWfW(y=X zD`6tzCre$PuJk1V3_RI$5_`rZ?^*O1_<+{PG3<39HSRJV!0HoKFuGq|GMO2Gh;auOrP%DT><9E`?(7ugvscTWMcGN&89Y&f zlzlhPfPb|uI~xZ)UUkXYD?QnvuTI?V9qOhK|b^Y}o{J$laVgay3(9HMLmVrD+)D=FtwUJN%i7@={_7#zPz zO3uxabC)JCK83-)9+Ru$_NLrIIX9TVFfB#I$r@|BpiLKpAi>o=0GrgIhW(+|EwlJ9HD_bE@WrFg>T zW-i|^cHb}lrN{|8)P1DfEL+(32i#;7(YPvuF92hsZ;b4}Q1bV3`>{pv_068Yb$$iJ zP@(Ce6fAMlF5>Im{^4dAQRAQJ_TNNaJ&t=9NdB}0C5L@Z(x>?|5JX>SBeNWaXJY^e z-j@8Y@$#5__V40_;m0)m`y~J8+#BI+ivK6k=|65Zy1cV^;iSCYJPRq$$y=M6Hvb=3DNO@*h|7v3T&tM#bm(-R1ccZ39Vi6WCI_fX&T8PLYydO;M!$Cf@4UK}6Xs z<*(~pT@Lp3f`WGob{9dXacRL8=5NTue-KX0Np(pr__^SBgfBy%i%awi?fnY=WbZRN z2rd<#&CxeKl3Xaug_kIW7lmza&W^O{l)_<{cSM0;J{YUWZNiKX+E;Q6a74Y&1Hc~)^J5A2S$%WrZh5HiJN*4Ll$+huC7lS|d z$wf}3s82_PCXZ5z67YSO8>FHUJXNG|(AMPzQqi2wj7cuKPbzvsEqaIu@O0N>Xv;#8 zFTs5W@wh0!d8`&eSG-w1SYY@HA%eFhu)9$PwFtY#-Ygf`zLcVGX@cRK1;v|-x0bH} z53|5n(Od8qP>X&B3}3m@Gzx;B&F#m9;<7r-7c`5kcdD?Y_OF!>!gFT(FYtQ;7s z1_p+0Z@m@aP)Yz3A4#c!je*VJ_W`b4Kn|jRYT*g7G07$b(w2 zm9SXV5X834;A>KFt62@CkCfm?pl%(sQgZNkoKzyXgMU&!obk5Ql4T_i!89^I?i62A zYm-ZKxkOb<9_w5tEo(!CeA=AcK>QrF6*AIqh?)zY1j1SH1o zCud53QcDj;f(Vz%iE(A$ie*R2j-qJiqN?aTk6iYS91t+l5al$JFyXbtHThqFiy7S`iKZ z+BV^XqO6z_5x$DMrHahX!dKBm!lzW!6PAdctk@t`tT82z%A{1h#`9qNQ!3u2PNmWk zXQ}djwel{?kAyJ3@;TsoNU790F7_X;b1OGn`k?Yq*fJIRU-URv!Pct^{Wc8-DX3tdM?t?tG3BiJCv$d!nU2yN6Ma3 zwVN7x)!{14#F)J(Zf5^Ose(PS6PIC{iZnIk2qDXe;te^aP#-CD4(Bj+%M?!y#UcrI zuH`0&hQ!IC5n3oAZ2ND|NKVu)LKCIX_|BD`9GWkM?$knyD6ZK|5$|!U{e<%6P_7d4 zM2IP|+7E3vjSqbYRz9YN)>6JM_Bdx{=xd9Wp+lUNTId*ICRQd_pA#onJLT$rO7;2w zhLLn{^<1lcSKnr)uUPI>zqNYyq_nNv|tLFJYS0~q;BiHm*Ybc9f%+Hsw zC+ORcT@tfv(g-NmEKzF~kc&5Mspdf!d%|pu?IT!2N_fZ#5sJKg~Lk@c5uP+^yL|ii-3ddQ_;TsPVxwLyL~wUlpH>` z!uF=+G__<|Ys+a+Z*A$P3Ct+mceuPoT@Hn_E0g%Uyl(j#T*AH);8)b;FA`WEu6HLB zZ}~?FOkwZZaOu=?Y)06XsV)B*ulodcC{b>RR+gWJZ>G7)sG*12;Gj5U@M#UbdAtT+ zO2Yu!JAQ4$jiAVtjt%2CD-EM~vi}0F)R3+=OphcR-muW#u&{xT54_$_c^V`K)d|$1y{VAAB$Z7x{b=ReL>6BMVX-AQt(TkLl$ydy(`KM6(xW|p zSz7m=l%`$O88v-rHXpg^gw*tt(gY*IjHl9kt=jZA{MAB3U3_zDG|UjSxhDZ!OqH6) zE6qt1yM2rRie8z9$0yj{s1R&#UM1Mx!qVtF9>KN~u=llTS^2c~jM~;{ygP(r3E)0jUQJu83*;ucCEhxXCQejJ|XA45X z8$1#w$9~FipX-+DoOWg)IS3qvZ z@3Y=;U+h}q`5@wN8EhB(rZ3BDgZ!Rhyl%V~qxa?zOqv-{8O9!CPj*)n!)|=a-#A`i z?4^k^(l$hvXkhv|O7CsbZ%s*KtnibVL>CABLbF+WUWMy-n$6ntL5yhZF=wt~9PH1G z>`-7V9T5U56iGMN^ z2c_K8YVL1VIFe!RrId8X%mGM#0p#0vVoZnl{`%}t0qUNE~HWO-C4-|*zownzl&OaZOKvOz@6h zkIWJ0$KdSw`F5yiE&r^r?UNk1P+MOkq02MSjD`CXcs4Hg%XF0jgbC%yPmh!H@00Rx zQ}Y)@@@o?(a5vv;ks6=B9@bg8l;5o8*G6KxSOsTL!LM>*v{dkW0`s#I{LBzW{^^)Z z>DE?{NhyUFVJap;Ds=Idc^(RY&)+)O$&A9$n7^rppwaR?PLqhltS!!HiN+d(%K^&?5~W% z<%O+9SQ%u+W?mb~!}Hp9W?uOGMd2<0)j8=xa^V+J;de?Q6v?Nbdtj_W^0Et0!gn;j zs6P$@RZ2y@l_FTKpMFjqA_W&+VFpjcy+B>1qH#*mjgjEwqO>@<=pLzPu~IabfO?eY zWTX^G`7ouFi=I?X7q7PXqB2xKl~m+YiZDnt)3_8=b5crCjW`I8TGT`d&9a`#C|Y0i zVllcp7UX3u+Cd(&8j3z>FKZE5E_yVjv4jbO`=aAT5HM`B6bD{he7;oNRVfz3w$I)q zF*bV+xp<^he5q1=aRh7{48^bxKie$`a&e|qJVz;>773=psl|8jP+W1Io>GjjvlZvZ z7w4l;)oL+H^x1BFRGAlb;Gp6nQ7bM2?0XP4)x~ODmiBI#;$WvUXtt|lIVhxl1hZWq zkca zBx(V)^Uv|c9M6d{fn;dh!0bVRC888qq6Owr2?Sl!6~g z!5vx_Af#k~Tq2s9eNf4HqE>Pqr6=|bD!D*( zmq3qy@f-?10-B!Fg-@QAJU~h1l1Ek3#cLJE7Um}QDRCz-->{M*lT{_fh`2&6DW~}C zxP$$jQL>_BRmo{IJL-IJOTjww@E@PL?o;v-`fj;ohr}K1H;$X1HvA3PVO!)DvtQxD z5gvarJK->dj8c1P*9t5Os%ac$X%F&HLnx&kBg!vCi%=Rz?)J?h(W#}wN@49Q2Rihn zr8laj*M@CheqoMFlyB$&ZfV{CxwKpbiv(RNZIMc=P)>Fn9C@6s4~~;dw@RgJ z6ZGEfcdMb#fr2UhpmZ-pv#vdhVWo#SGgC`{FC{J%5OJ8cyIL;mE0y7#9+0XRpqnjL z$_7$~LWALb0GSRiOSG3Imd!IuR(2!aW@4di9Nes)my$#m`_0NGiN3N)VcS0TPN1Fvi~5AdEq9k?BkEMXvf(UiE!bff zM7`_eG00#Df+aNUE$RAnFXQq!VGPT4U^?=FMp{Ay~_*z&Ohr1HsHc?vuDXL9*&x%_3V9K&N1qg?*3RQ{$`zMTM6Lv3e3|7TV|YvqS1wtkQk^8WaWn2NXx zEETmdk!6o+_1(gT{IMtZQ;*u3QyDp1)lA4sI5sgVA#3r&8sAxxi92N|iXCiR{2)q3KD`NQtYu zNmcgt#1Z0ge+A2xtCHoao9OZiO4i=YX#;Rp)kKpTq3J31YjV{RxoVkGh3;kFJab;V z>M5z}z78#rlUntnR7JxPc8re~JK{X&(M`wk8{|Afb zB=)K9Mm1U8SK^LN3NIw2hMIzWx#m2< zgI|kiOj}0v{_4YZGNiPGOKJ5<@{pNSW5?T?a4=0WEZ^1iu8BolZZ6bZCDmM_)Wn5t z`|a)Kf>bk0s<}m}K__N{)kVVank;)wRt@jMftcnOBNpvcTqptipyqM4<{_k*OAL}~ zbpCBhGd-+qF+H`Wq6U*5tdWnXV{2N?L1v;{^Nv=7etCbPIWE*LM-`>k?5+70t%^=M z@K09$QY+P*M5dPUBh~g$Y8^x$&68lfS?i2**Fwea--;Q_YqZ)S?FeB~^MPjVY^`=; z8`x6|6MFwH1SQul8&vxQrca+xYta?%@5{e5<*9|XLO3@cNcwAQwA#Y9Ng5dOVZ`&oOqb_K#yYX86l=Gj^u#^d`7Eh`!dU(K$CLr z=LMlr!TTNfQCseB;3qhYssg|~z3~1O?<)nN5E{`l1Mfa~KZ!SX)_H)Za26d5>LTEn z2#!IpR)MX=hIE0g64+{+(PdFs$hjZq9R%Fw+qG*~65s#FGnFm@HoAa~jgrt6Nozni zdzMlN@U@VSEE4V`lb1ao@x4sGwGrP=^3f(F9`h6Ot&jL%KniR_#P=8ZHo`Ym5R9&i zRUg~LiA9UZuooQX1a;-@K@im!5E*WOg}%6IexZM|e`Z*i>#{SLV`L)^qtjDH?}h$% z{U7#aFBs80C1!dIX<-2?2u86j9bgwMEc~<(R|39h#&WTjqKrNZ!@?Llo?cOGE8>E0 z^aEcCXCqpnpOE#XNQ3ZP8^yM@A;iqk)e8d`J37tEyew#pm#4S##_69 z(~6yu*i@qA7A*&iz19gvEPNFw#8Qi1Dta5Cuk+A>a?xjM(ax~#`?v_@QV}Ll-Y{gf z=m>#1@hQbNF}64+dn%a|#k~OUp%q_<*NuY1h+9~FQ_axYn;>#dT=Fvx?CGgP_;5kb zm4ITB5^D82qUbGNz%DhjiR8&9c{LgI)`!$+6yt4JppgxW4a3?t!_}be3XC7nY=>~Esoh@Z#<|aTjA${dwv;mgd=~AsZv&2& z79CytJ`rIup%#6BRU)AlEi^KvRfj3xjwKN4`cp(sc|=0Rl)52MzDfP+h7}HB|0OEx zW`dGUYTaVIUe)Tbo_pv$cinw>eeS8ly5ON7g~ACALta>SsP1?@F4|>p0Ig`R`>Wmo z2mLs2QtJN34M%_THfHp87=sr!-q4t`0_SF|Ise8qc+g&Lw#M7>W~R(GVn$kE@0n*T zMi55@v2i`YcD2LMoEu;6;MG6kS)z+;j+L7)Q<~Aq9ri}V5S#y+Zxo%)K+Ygv&Mm8%R7u_o~@+PIMz#{&NR&7NcVm6rstyswsK~mxuwv1{?ZFv?9-3?tx zbKTFF>4HEBe2Y{{)d<<=WM-tJ`Ngc>q~z7zNI7w6RR+vBKRtK z^>}G@lCpXv#b_gcWHiygdZMVTo=O3Txd2n6tCz~Fvy|0n7C$zU_6`b-y(nW$&H*ci z!>c{=YDHQ7=szORB{#^{4}<}ZFm-j~>Ss`-&$!get2ZdCS5p9ABQF74lGmIouNfe% z>94MVhWzOfqD@OhW+g&n|HSMy&>%lOBCokdT{Dba>~kww(5o*W9VBSrmZ;0Kwfm>Y8Pg++ke0@VQr>`*|I{e8IjDvz|jsjOg9xP5>$h z=ZNBSWLdH=L2{aK_VYc-Lq}WMd)DVKCfMH2FibZHY+q+sGQqy?48y!HwlZ~wEd|Uw zzB7zedqm$`%J=ztO8Y<5{qv+^&QSNy?;zNIAjVB{5hULLc19QQJlRP9)&;CRhY)n` z0@e-$?BBWoH0iZlMd#YrjEm2LVpt0ea%5d&S8+}~@9ENwicimVxs@NO7*3E%qUkvE)wGJbRBgeae>|X2g!nU7dx`WzY z>+0dW5L=FR^jfzW&Z~Q%X-P`LZ@F-I!Iy z-PaTFj4ED#DZx5d@p_tcV4bU&K5}|y6|c{xc%3`w^_2wcTx09k z0(M4?t%vdcuQj%wrX zEQZ@aqOuXydGzeAkb;fSh)4TF3O1rPk6sQb*oe;P=vYX>MyUOxvmgZQ$%p>dDdt$4T$5b@rK-MrI^_dOO-UpV{%tSLs5mzb`6;cw*yw9{jD z4co(@Z1vPAaA*{*A{5#U*&GR@|7(kC>_6YFwxjDo;kGRV> zZkSK| zq7nLFTZqWh0DO5C{o`1FAgu7+AdbNQv2B<&@*#EnK$%>uL@cazI3Ga#W_WV2mTwNV%*3d2O9_biLTot#1p87-P9$K8}8&tW&^0Pk;?bd}iR1${O+@e25qSo{k#JPN5);A%!74C60d>=?SuK?^b0a3h|1_)zFIyv=5vy>a75_dR zA~t3R9E*fhxW2;k6Og=X_EGR1=VKXAJhlg7jYnC>4rm_`P4!-jVa;#=CxW=K6Y*qF zuA&InEpS<+n*CM^fU{r|A5Vtkb})PF)BW)8E~78CZwTL54S6)ch~>>;Y=ua{bw(eM z-XE?vj6Q?tB~sF36!u-=A~KOF>91ze+ZV;EKE2TygwnLls93{K4P1~w~L4I@@g&R5`^f)7E#`3ao2!wDCO4cM;9R*KW3>tJN zg#+tzCl7+5H=|9TJOvKk{ASqpSKqF%9l@EAr0|kqK1b|F@*(`{7+8?xMgk5{OhbYu z15v-p(~ZlcEjtpv44}@6;uV{Wc6#zrUfszBaOU$mPDU4cvXQ+3%92stCwFx~Ygvnz zqdHSA!ZSE5OvEu`?Dzszb^u0l04Qv?8KbE(Q<8{1W@SdfJCnS>ce3dK%^>I>XF{og zoMHbV?!y$fbG7k=I5>z<9Sljyhs35}iT2d}5yQh&;wiOI;wep*?e>?DGy&ctXaFg& zZBC7}gWicfA)OO@QVn`5%Y1U?x&EOC?wLWOq@k% zW^pu07Mj~lG!LMWOoaC+A9yjm1HqIja@a1MNAb{tLuL?e#|3N2I+Xv91UA!yT&js%u^l#m#5s1l#8u4 zanDfbswst}tJJ@|flryMsG89ZggsK?>LDdW= zqI0THJ2T?LFp*8FW{f1NW=wzx%(x!l#12%=m@E=_7J-SX8F%BkzpbaBbdM752P3#$ z-tiVzg95RIP?+IE>h{C0+`^x+9G%0A7PE7J`A(lupYfeYu~8~}xx=^;bvJu7p2=Zh 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%0DZ&p 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

    7@R|?EfaU!XAhIMwa@& z7o*SYKapDXLLBo=mM#pij!s|4G-hQ3dp=)J4v?)Td-!`@j7UUBP#xHa=|j zpH5v8ibJ24rT$A@U;e-QFWIcmq%Kp0J|heL-}^6^_1V-F&&Gv5`#+)ohS0Rr9clJ| zpStSNIP&+G40)W{|3m6a^Ww-q{7>Y+JyJk@`7!mC>2c^EFC8>2?_BDd@p0&L{|;K| z2Yw>G*U!ZAj+p(wq`o#a4*ko&gRXDrwA<`IpZdm_IQ02T2R#|96shYnWN6p=O9u_B z{x$V2W$5%PpfBB6^0(AF=H`B~-2UHW@V~6*|HJ&0t`RnJ0pLUX$H6cBSEW#JS|Qh& z{l5eJRz>pPFRA1g0e;(nxa1cvspNkE{0>F(KQ0~kG;@Ffct)Bmd4Q4CQeSryU@;mF z=>B%g9nb^(u0C;ay$oKTwNUW?-&z8gx=VvrjL`xO06yZnICukqE93Zp5##tk5*f#n z*+-xuksQl5s&Rav(VxfhfySgw*h1sVH~`<3|^mF{?0sA0Uu`$TmkTj z@$p*V3K{(0O0JBJA2tVC0DQ6#m%PQL(>YABCBUaX6bEl9OJ1Ly|1-4!ycNKwS>oWW zWXbCrwf&7sQXz)87BMInWW{kIap$rQ;<9?*#A##Gc zTRH>$$y;RbKxcr{o~XXIXP=9Mcl`_S z|4~EhX{Dt*#@NWMY{OZ2~zhDk@2e@!3 z4&Ge`|1Xs&(1Wy!JI!7{z-^z);9mbF(>Z2wfolM6e_I9*Tyx35eR^{s4dBk@aqu)* zEq}W}ul*~X|7Z^M1h{)!9K5Ft{$F%Xmu9^WnghK6?)@kZ-s_)&2YSnr`y%p_fxva7 zK<(y0AAo0fj)V7+!Ru4Y-x>TXLkqMmeE}Zm83*tC|AE)nwgj%1C09Muh^+|)`T<4t@i`X{(sfaQ%R-zym>yr2Jpo<%900${aNRK$Ikzv`riidr9I-{xBYu?Wx^$|ga&R0`10;? z@Z0}Cwba+-CYmCx{-nwEC7A14enEz->rbp z{GXC13_}C6w5@r(@AsZF+vWj$4|bbM`_pXmWbpsqw#+aGW&?b0d|nZl{TFKaAJeUR zOwngF2j&2L|F^Q_fjO5H{9b?`JRAqV_n(3X?yE=V)D*{?19JiX^@%w6+)D>O)f^xN zdRPG`1^VAxMJoAbgV;(az-Gty>hzuR4T1UbO`q86h~1aH!TM6#_$W4}8z1YKV=cty zc+p?)c3R-MU9)#HYpmM^>T$Axp6)NFdqK0-x$)5u=9?M~H5)tjK1R+?_EO=UyjL40 zi{hOkub(P-**{Xe?^bK5{;6b(V;yrQM}>FhBW;-XDc%pgG}J&3ig#|lmYPfUHP$h| zWUBCfS*r=-m+*e;prOX_exIbJ0&h!d9m_nX;IT}tCX9r~>YHn*5+2(iT}#b1V+Ug$ z+wdM0Uc>m#eyaJv1(IJjS(~%q9FkwQ5qU*d(Q0rL*|u26Hn~ED*W@-$7_kq@3a{l&+At4LJQI20RFNd~1;uM~tA?6$6WO3x$MTI-cs%)n zof0#risH3zrlICGp?Fsg*HRxRyAtczj)DrW<15-Q?@+u>SsH3yH;UK!buCpSTM_Hn zt~aXix<0H8bDrXv*J!BuGb!Fx-)pHG$o|7R_Uc0_yzZ?vVZyyAUXS)#Y5~Q&Mw@no zC7TZG*lRng@UD%&8%*sbGJ@ju#D{)WT8*rsc)iJMGK#JX+LN7zb!?v|D!e{7Yr{NF z@%q}e)NK^+`mZ$9!fs@HVI6zJW))t4y(UadzW(Ip7e$gnk>U;bLqjF>t!^r2Y{)Bhi^IEEecl*a$D)3GLFa0SMUiwmP7)id2&$Ltt?=JHCkScB9 zod(|UcU5@9f6|009!2we_jg+A>omV(dupg97`dGR-uSI5ya`54m{|Ev*sr0McqrZ^ z^4gXnA1U9nz?(c-g*TbJ3Z{gK;Z3j-uJ+}=W7+-G?OMw3~!n?zcIWS zS8Ku&ydQu!)1tzgS)vIO!<+S_h8n}0{gQ@C@O}i|obOe5_jc8UiQ(OQQA3U4%^jej z61;Q3oA;~=Z{7+`m>AxCr-mBCv%IUNo+P{b>evU=?ZE@u_8^A$V2U=TRK5?94;UzA zN8~#XyoYmD@;$7z`54|KWtx~V`5q;&j91}3Hc}HNhWGeY8fpyhi8&f7 zk?&XFJz1r~dvcd1ObqX-RT^px@99$-D#62!J@#33d+@BbJt!SS>)UhWYZXe)N{eaz zSonpOdVy}zV_)#8_b}Wi*&;s8wjcJ0v~F_9HV$aZGEe}o9Zt#P!qOtt(okxV{=ngc)8?j9!g18 zHKKTVk7%j$DPDe9OI=5|)v=LjD!fQY6Q;T|#VgeIZ`D~8uh^yyi>IU5NynDopu#JE zKoh2BD#feN+H=kO6tD6ZP1xEVX0myXtv;^8tKl_aV)diuM-8<$m*OoNtf8WQko|J( z;%8KNi?tTlIv7 znkUj-aqQ~fRd_FHXBsj2UY?+d8N+)eM@xl#*a*k2nXSTGqqTv>L#cdgwIjX7OK5&y z(~goB|4jG3v2V0e;k}`qQ!MFA@!r(tcZq}ItXbxas8oN_HQ`>o)HjI_x?UKG2gDE^6->*DK z@pfx_sa0mW6^-5Vx=Ox1-)ityJx}rWwa`+JP`v#X4R!U6boUv1aDWQ$;6vIll@#ym z7c|tD8dJO@+WzCE$LNML_Sjw(-to(|F*i`WZ?4x+U+zWmPG~LnWf$FJ#-2Q&!aJqS z*-H}Mx7wNz!~0I#D-%3yD`QWqM~-K-BgdDIQu)qm$2hNypz?jM?L}W%LwAy~KdNii zIc?2)6)*3?a(`;4$?vO=QoNt1YpL(k&139&yuvH5+_2}hIg8=_Iz}5)!uw4--gp&w zU69}3`>ODM*RCc_<)8a%0f=veKniPR5l5!31JR`7JXOij!+SCRbc^tp*t)L)%p zrIw0k@n+x|RUMqImK&s zR)hE2GZgO%?JCb}8|dCIU8|WYyjEHrzfNcNx|GHmyw~Z>UdL&z=na-`_tLfNt-@<} zpC;xT^QnC8k7}u(Q~5e*Td_C$(;Z&APOqr&Ivv-#mJ|YDQl9B9ipfjv=tdMK)>a zdcC8Pq}Mqux`j$|-FYo_E0yGWZGC$S8<4OsOLxOg6<&XBnY~p(@djwy$hR9&yqm7j zr1JIxx)n<|sI3Zb(B0ZFA5*-+Yc*87>C=-U4$<~2poh$42bS&@)x1J?i?#);V}`V( zsKf3|Kpm1#QSa!NKp&byw_fQoRHGf;o!Zfk)CTD8($;poHdIJ4M`*{3WPFGHR=SaD zD;}w}Vw@tzQ#nU#=VGAKF@SFD>I6A&y^?OU(oNW?(&z-O)#6>F2t}RrdqV7Cms3fn zX!}AOr{y-29ag$&!&Ru$v{s5x`zY%4NeQU8^`@vZo=v2qAHmit-AvRwdBmcdsjYX? zh($N+6HQz)V!^&C-5i5To;f#Y!qhRh(>_CY-|R&CV^p4b+Pa7E=jeth-Tm8Cs1GD1 z#J*z^&ERHt)Qq6J(mzZy(ir%rF&$o3iT0pVyHzFb%8U1o*|XU<5LppuySmX z(mkbDp+1#pwHb82rh9ruLhL(lqOv}dpGbd&?v2ttH(!PNTya9EmD8+3k>h%`Me0Ev22}f_DpY%QLa4jw2wLaVj&|_o*K1S* z?wo}1!_mTF8qNx6766tkjvj0gZUZav#oS6{nZaRC_ zg`$acH$}}koJc=KH$Lg|HmFeZv~@bxCgpF}#EsReu(nMly#@9<=?eO*@CqK(#KfCt zQqNUbnn;&=j3RA6f-^V9(oIgf;yo(V67AeHj#@gTe$=v}1Uf;*?j~Ku^D5Me#MW@s zYqXpy_a($0-H~dv`sPIXQ*>LCuC|2=wN^Wu!|QRIDC#0dLhLbgbgNr@Ad&tO-Or?3 z`l$+a8LJ5;J!#UdNbJqV_MwulPHb()K1;VT>0bUph53qEgNb+TE>KBd)sDyNm~k&q z)Ytkagdfk){Y$zx)cx@r+WxqJKI726nOJkiORehq1{zE}+aXYtz#zKNacLz^+Y;0EMUKq?!8)7?%&hS{}FpHMg5>lLhOljmZbYIu}z(baWpn6 z={{DE%RknR%kdWA8H)Nzb^_|8$yC-)6YKt@H|Y)~-IjhTS+^wSbTUg(KYvw&Dm^LF zZ9S`@;$^|x%>iso(tV*?%h7FblNjm^in(K00)5JLRMMT+M0yR~k)+!_K_%&KUqYy< zbj?oprMB(BJBDagz)z?rCX77`&G|vb^FD{P(do|fy6SLb_JF7&~*vnr(tt5 z_8{qws4ew~)>7-3=_ZPLbaO)N=@E*0LOaLA+lHJufXzp`lWM)5(&{zVqMk}DlNt1> zuV)w3ZlfEC^i85F)FxXJLfv;8mG!cp66qgP)MnEY=yNmZ4kCT?YgMSt6UU=->DrL~ zipLXUS5nj#fkZmqrNY)BeJh;`wN+vd5kocIo)}v~Z9OZI4%B;rnxcB%t8b&7%Se{0 zZ}U|`+{a6?BJ?{z`TEU#Tts zn4BG2Y2>M6=F>T&zN0IV{=7jnVPlZKQ)!*voZ29q!^k1%SuNNYr0+ydx2C>3%;DS| zv$qSb2(DRqX75e;X7Bwu_+Ay<`#>9q`@^`_hRxpB;eP|}zPOxuW?whl9|6smXAbA# zz5v&qpv}j19M>TDci{5on8W$F56(CH47fj=WA?GQ^l;yd^z68Qh%jN?hrr(rZXyqn z?ILhq!u=rbS-7@>e+>5*K^uzeaa?Zri*WxA*X_7AB7Onxx8$3{g}6@z|1_?%pd(y3 zioBeIzZb3~+%&TR#bmFtMl(QU$g2*ZfvG%oTp7(`AebOl}C8^WbxYkc)M)m1CrN={J;Zqb>; zWt{5>4l6N;ZG}SjK=%kkxEx=d3~m912gU0yF@!7RFH^P?3cb&JzcPd?363{NaMY#S zmjZgX1vfJdjAE)#=;-IT#c?0YhVhwxd;-=n#&I8&ib4Dg$9R@=j2Ahh*a0Dn9HlOY zE*^4)%R!>xkg>J6yG!ula&iRaz_zY5WXLt7&bYZPJa>t0yW=)bd__ZW-hCzn0k+1Ok=0uL&0sc?iV}oS#}`{ zUtHci%la_l;EXAw*jXsV84Jt(gMeHE5)M0h4<3q~{VDG5A{BD>o-WyExabyUR|&3P zD4$^(5NqlhUL@cHKL@#r{TiPT=mL%+M*i(x0| z#j7L>(b-^vjB5i4z}RkrJM$GKAY;&pX+n|hyzLL)Rr>G}d?=PNWV;Z!7o;UO27kq2 zFxj3$QRc0gcP3lg%cj>0lnI%$lfz4K_A-DCVsD|yd6#o`gYYsEW;A=XLF@z4yUuON z;pMP@IpMx+FX!h}B7BJQR=~`~zfwTxGhd*0S_4^q<}1WYN;7jE?$*sT z4N2mR%=cM7^XvAR8{FOTt#Ki9A0Q9Y19i-<_4szRQ5*osvzZs{x9gdC1V*2E(SEyx zN51_U$D<-<*juulczeqvf2|Dkiq`1o6@ztt`$TI&#jR#omm`)!O80ltwfx_K}Wu>*?yA>grXiM~a;p zy*a$vyujoNr-ffakRhb@3=xW4Z@D(OQ(1-(fy(M#2i>Gbk{{6so8kI~<=xHuy8ZxH zRd&4V58m~&$#o)@q;mp^Qrp}H6U9MIefzrcO;~ykq&rz~{ZVJ!*2wlGWnCBZN~e~E zUnZxPi8l&G?#}M+p7t=)&k&5&yKf*K#@L{N`)1r@#_JwS+#k`xa?gf4b_RlbA>3-C zc6&&`jWi(ZMipVQNB{q|B>sIgzsEvPXm3 z+{cl<;!eE#xRW@);N&l#3+^-EIAT;%mHLuXOfx(US;5ncu#DnOLXjua$sO`0k#P7aRWrkLlaw+Gu57f!M$G2LWi0_n;3( z9wr?ZV7?(9(rkLq;_li`OUFklZ}=6t)5!3(VtHRHm2j}g&);W^TU+CL4%c4BxNRpur<| z`XkLOJD5coN{yG!DBh0PclpNn_At6w&G5~Dht>=qX?tQd!$)dBtY-LpaK~zfk96_s zn&Deb0>)~F?{j$mQO$rd?|?`Le224IF}j#Cec!@EmFYW2&?RMNHG(^?Ot_6Ztc-DI zOI*WgXz@;=D2vOwGOJD>MzbcVhWxd&25~rele1>V`x+>06iD~tpA)h5Sx?hD>@DjB zrI$c85$|LN>(CVpC!NC1nq)TX-uPFU?*@W5OU!zUiG7thtAM!aj~D=(kyXle&Uy<2 zrZ-GkYlsCwRO8OgjByv~bn$iO(Lzynv+VZS6OzLCn!2hu#}kyq;vB6mPJ9-6EMi}m zJv4h9qr02n>9cQx8xEGu9)WwT1W8r=nPB$?&A4kME;|XuKrvSfMgAuKdko=qB(uZV zRR5K9;D{r-A@=(246LSyP!wnpNC}R@@P*`$)d%{)L(>Uh9Lj{>mTeqEuE4l1fw^2@ zl6ZA&U__44Gj$D|Ww^j0nHcMX81aUIZG+v#tGfofvwSdJASe9o+8!G@5rNRNTq6{T zyx2+n2+7yc+33Aut+SYoSzyp0<{;Et_P31T_h`bTdqet; zeFiZXocHbT8^iBwIHwF^9ylB98;s!(G@J_tF&~`I?4KFKAF4UdCI&GK&NlltWB4Nt zhc}23aCX~w8^a%KI6Y94qhKMU_5&De>d75?K~rpB4K2q`1*L9lKdBB7(aBJcfr?P8 z_dEiZNQQcQ7Gj(cuik|+tX#cg&_IU>qk@A=Z+GzJwLwKV?n=VBCcE8sU-V~#;IRNitQwTD8j!0R=Z zMd=Em8t=zg7U7^MIm9BoKw??+ph7^DJ(fi;DuktYg~PH)R0s%hz_O@PAprD{Wznk& zVFliTuq^sWA*{x043XWQbRazS;D9ZuJx8Bt<(hnua+fOYY4wtmfWNeAn66mlF=H%@0KNV zHH3?nB?~o#KP*c$B^O{UOH?KI3bvzKmZ(au0{clVOH?ISjSZoeC7O~8G_@>Il^h=9 zHM1=FLrL~M?5VUYZK)x&uq^GW5I)2%M9b0}6awUEWm$@ofMv6U945=sdlUlXXk%Hb zDY*b=S*j{IY^dQaOLH|*+F6#?CehE z6L$AlmW31o^l^=4S(QQnXqsi&n+gG-JuS;VRR~+L@5Qq0fI>i&K9*%aDTM9Vd16`K zP$BHXwh_y6P9f~Ujt|T79tr`e^tUV@q$Y&7SeB1e2>Y@5!m@mpLa4^R3Cr@w6$0eA z$+Fz15Wd1r2Fvndg@6z@Tb93~5RmK;%kmF3grSz@yA%R>YHwM7LLnf^t(N5~I|X5w zWkqvMh}$eHIw=Hb>~_nFz6#+m9tK-h+^!Ig;W@5l#Z(PpxMjto3IQJ{9AR1ER0z<= z-If&*h48I8({EX^L?OUVM_E>^QwV491k$qNGlhU{9At07FVth`1cz;Gv8Ru0w>CRtXFQV0N@Y*{&5LzrS&`Gi71K~1%+%u)z- zcr;^KS*j3#G0n1awLMTH*V_B7= z330DwRc{Spu4UC-8p1rwDpg*p&8~BnRnMwJ7{z;qsH3-Ipko|{rJth*M&GY@WWX!^ z=pZA*F%rw4BgHJEXh-luIcPV z?sP4)!N9i8?ig7(d)65bbMV|KPP01ifTt@wx7ud!K=5+hRHKybCWKMtR6k+d7*H z=ON1}l5lhkG=QAt=K0EV1j~ry5uz^!%AW5z&oOaYY?wT`vzNvC#6`%tmiIOgyn5ma ze}Tz|)r+(A4!_6L_M*e(5ni)54Jl2gS?9fdY+jPpUCw-jB@^$OO&Q)>$*g}&rWYqF z9=Vbv!F$K&T2DhNrs@bzCC}l#kMrL9P2M>+?+g-~912YjyUz4JNaEnIYwE>$+Ve@W z1B~KaA?geGa@L41I ztULIun}w`F1Xp+y3d_tIT4y|Z8&fsi*8;g=YTkE|bFDM8MpJUl3r2CC5Y4t_yKqz@ z8{QdHNOlljs*vnF-0iJMGE6pEQ?kyXZn|`zo?XdjFScf5A?fHglGPj(3Jy_koBf42 zGbbbaAT#)u?9+VqAAI(CYc_IwbQ?_`2fEk1pbGEtHzqvZpThgEu=+12p3D}&BLPcd zlD|37?e7B4N4&qQAi3gYJFu;PggDdcA46gqMVAl_9u1xoo8U3Udytvc2Y(ftz(Iae zRSo{mTEvFZw8kj9g{at6Y$x_cg!d7K)r%dlGAjL~2x4bMxRypZWfVP#&_}#QoQMb? zND*!qi4BooEJ6k%jH3}Q7)384Ocv*hFCfB)2!j+J6tVa~f3XOUAi{IR?QCKceTX24 z0kH-VNS#E4T(L$QA&dwWGy-oFvk+mCxK`YP2y_upFRmB2Xd~1i0+w%(LJy-j9}%{R z`$He1;CICeUOWb`^rJ$NdGvQ3J9gy7bDa3SI9)C@2BZ+ni5JCt2nqFTG7f=l!iAD0 zLY_ou&4pS@gnU9EK%s72sH+MH2haECLw&eVFYz9&afA^C)Adj~AG(zb4M}A8GsgIn z_|RA`H0n?M%hQ)AaHo2N$v>vg2tM;=Fq<6#5gNq=^SQ zp&FJ8Ef?K`GeWPy^)~4eEJ8H2A@oH~XQ+F3Ox>Xa@M_f^Itm?q%Y{yeQ)SIEeCQW0 zbWX_tQpho|Tux(>LXHWpb|i)Sg=mgBr*~dUr0``dg`5HKs#9o?o->4$L(XtM=MFAs zm^f9d0aBFEdd@UHXCjv~PG--E)!2TGWBf<>91E8-_fP!WV|*K*vyjVq=1=@7l7?~u zkUAgor{|PYahCHri@2O>IlSCL5JMv3yv66d#^t;!v*Y44iSf7aIiGMjAN`4cM~we9 zpRtXK;Ehu~O(Kw<({S%;g&87(^i3jj;86rn(iw=eFl_+iO$4gDElvIMY< z&#mEdE7g1nU^W0?fw`}<98QSxLS-AV(w4iG%iS#5Ea?THp<{gRJ}&o58KAD&(3{oG zJ`jEY!mpxla7Lby#I}? z21gq6fj~Z1T&THPmg`n>B2e z0Qp1s{2RG^j5ef3<4*#N=JW63^3&CPMF6NMe>%(M-v^_~$bS^Br%91NC`9vZ`Ptzc zP~>}KMV_ArueQkZqY%H6%P&*99EQ(d!R0SiG)z)>1Gw*yLdf6L5q6osjmzJngn*Lv zbNPD|Lxoll=o>EosJg+;|CP`Gk;^|T8!yQyt^K*Qpu&y$a04!^)3Ax2P(7>LLW*z- z%Y{=(KEqeT)r;iwAt4&RF?<`g&#>Wrv3!O{z^l%uEljJl5u|W7d?A7-{ow<#6e0$A)hQU#BaJ)qkt?`JGX;?0Bki~dr<4Rz zh;(DQNKaB$ksD#0k)d2!?{QXC~*_yBNMsEI4#H=fZR{op~#asF8X;c z@~oEc0Y6AunMf3_N|KF7g=l1X7CI;zI`!$ddxAO&C zxPnhLd|IiJWyqsk!66Og&wRmIu0YcuQuFE8ghCc3^M!h@kdYy2HKveFrFvS3!Bb&7 zVjP9A#loJ%I2H)e!U2WDiWb5+zKR(~;c$4>#-UFy9E(gA&fp8DaD@})hJYwZ9wVbe zDSV1Ae3UDENM^^I5e%cqD5B8A7iMyWf`(7!Bkc&$Vqp}kZE6MW$juJCJF2006{POtDczVIAZ z_`S>~S)d~ssn6`l7hT2`HBw7h)Q&Go;fh+x5+nc?rSU~qaYbEZb^>4rzUXGIXrKmg zBwutVS9FIQLk)-w6-{NiqS>UKDtZX6CrBASCPa%~Eb>Ojq71)|m0?i`UUeB7(u)cp ze;HR)tTz0jrCiY>#mYzuYk~U~so+H$5Mc{f1S2I%kcy;e4_CBH8{rrtd`E_pMdzX7 zD8m)~t^`0&9&N%!lf|iY#D*3geRtHvMO$D!hYs>E2%N(3Q8ORy$VF3S)yw%NT>_+v zUdM9L0mOErx4|`>+I-_b|;=+j*E2~Cd@wFAXRav9Bs zgvDI6P~A=P(G`4j5f_aQ(c{J}wbjwL`RMChbd4-6WmCgzB-OR(Cg5))tx$A7@K5s5 zBV06Yc5$>=)rkJiM}Ov`KmHjm*2NY#V!7hxB>Tnf;Ob1W|AY`NPAl$TT!QQ$j%B}i z2)yd->(YzwK%o?mCTt*=1Q)W*ktxi*n_|x zMoOS$BwsRtD;X=X>9m&cXM=AcDlK^uuIEW+o)V%Zu98s6&&bTtSY}EJ;ZZh_Mri?If$^?jUEG9!SFr=5ZM9G%6NRX#Ao#jeL5~Y_;AuVRH_{xKcDiO8+g*<)mSK=~}*YHCMVq&DZqrrSC()jig*lcTfTMaiw2s z1pJmSJ<+t$VgShe=E-)K1`l)PU#ZQh{71h0G*^B~HWxX^wCUz641DSZ?HpQ&3JkC-<`Uzm zSio02!&N*fv18401!ia!S)^I62zTTwO1O$5aVpinw3t+}n5(D(g(}P_^_CT{BF;Ke zz!jKdU}mqf>o6}!2L9de{t7h7=@k-jBbt~k$fl?=((LLpk&sIpb%gUHv( zSiUOT!K==fF1@ldv|QPptGp_fj5N%zyq>GPE|v=V`L*>a!MPsY=IJUf?Rv%WO^M zXTfjERW(-dP~ue_%T;wCB3AW)>pCLhi$b(&VAUPfWar#>F%hdq!mAe1m|iu3ubReH zO_8!38_ZQ%fbuBm_p6@gtL$8rRilwA3@)m|#K5X5_^QQR70g9d097!Ss&&M`s$eWt zU+`6*aaFJvr9V+wTh$T1>Ht@@SHq^J7qg7_s zQQe8JZpT$~8a{=aEm?APPnN6hM~t%i7PvBqsstfgJ+^v!4JpmjF;!L1g;%XALwfZ? zNdF10dV#v;S3CJ?fvbK#v9L(ZN6A#g+PK+Hh z{n$*ANt50#&aZ8G~gi=+m(eu^6bJf49;p58}u%w!%TuoyI z5AxQ)l4?3Y+Zi>mq#9~TRv}t5u;z|hvOaMprk>{qpE|`YpPMRYF6_# z%eb1wa`=RPujU=TW*t}ax`s`Sfs6}?Jlpu1Pq~^;^T!D_+>yiu)G1b`X8pXavY*+nqJoYgj zB?yf1(5JXAFvi1S#&{&3F&?dDjK`kEwG7{afFWA_@w3ZdAVY;Bxu zf0D4sR?SLK+F08rJLbxiDp0PrUYjheAe7OJzJa(Bq(1m3FhVt>w+@9v`k^l>VFw$q z&$OaD{#24bRaYmo);`j1(+1)yM0McbyA0CAhGIBqF!V#f%TE~Bb$MNw0i3{I3z4=P&GK_CSp}mEUPSB6~X#Q!b&oVHA1m1*><@N z@-!zfdRq!{(;txflDF(^9Xjx~t4y{oY4#_@3epR8ms(z1f3~x2g27_Dg#duG$Lj4NvJF}dlSg3kVlc}A zQx=1HC=Rm(Fl+4ZI7oXzHUa?V19;$IS^KBB3*<%Ldt%#xGVD89-oB@wa9j`&gSY?6 z+kfQkhXwoox}=6%g*UKKD z8jP2P65(gzck4xc_(#N=p$~N;u^WhMNnF$$J-O2#%KByL{fiJ?Jj44JuL>pBRBKP` z1#AI2$6BmcLKD4EOIW?NKOqtwS#QDJfn6V=QB+5x$(AYWSnD(r2jTHf)?=Y+WZm%D`3&>+`%d$7IbmSzUtFT9=gklki$-jBp_|ln&oa)~Lyvp9WeNLc=To zFEDwm%j=RFHSRVz!}=-PE%q)2u)kt5tjAfa^)%r^amiblq(<3DjFu);l+=i*F@$>| zr4m2+L4~g|Lg`Z3lC=n5DOvuR5UJIWCYxq?5<}l)9>`lsegtdtx}+vOgd?G;f(sSQ zV(l_hPrJIQj)6=SHXkN6G2)s-V913$BsF;)`TH36M=6!~$q#vapApJo;|NLK25v1? zkehLfXY~W2{GrEfNA%%e0EV(fMs)`9W1$=hcqb)%9uW8FtCx^B#ObTTecA2?aRb<& z2nSQbzk)5rtewNB+s3{7|tzKrb?|weV{i0c>w=SiQ`kAToyVZ+)yc z=&d(c$4D_G%na)wwzYLo8cC&_xFLL@k9CgTI!D#%l0lEvfJio}sF_OZULx4vy9Z^n@y%|eFt0|fd&MiM{9n{_A$TB>@ZxKSv#p0pWkSF%jz z8pJ_o)Yx_kPKeNR)?WaCV>rZmIi$C+!YUp9)L3gxygw(D&*l401o#tp-E z6Co1Au%+X!G7Me1ZF~olZ3-1j+(7!Z$C$wbd0WV2bH>o=OQt4URIugOB{dyJjEAZ1 zZ4^I4dP{BVY==uts2>hubDuK;Y>n7lwZJgEWOKvRHn&x%5CTG;ZM;50B1=}M zH;7+={;seoIU;SY#HegLCO#AFF{Yi zzbApHw|1s?9ptg1EjL6+4Z?O?>kZ_Nmt%gi4k2W`1RuIa^(wEpl?>uo2!hd9vpl%A zk+L3CVSz};nf~;V@p9H{L-qsY!LQwB_L4@b5SvEX!BK6+7Fs^QEh!APL zM=Pr?UVXZC8E<{dWL;~ru1a&9LjF$I_8~(hll7gn2t=U+Ewm1MP1fx+fO9$^nA+=M z1lHe8)}N$Ue$s#2Fy6nsGgI3y-PROCuT+!minNGM+#VZx^`|90&}8dLsSuLHxs}EV z^&E`yZg!DLy1WkXC_V5h;6o?U%#8b|luG>MhjQM-2$fJGLRJMBrj1n2LvicFFpuEl z6;j`V)^smAkG0nI;cN8~m=94PhHNbi;(pLi+jPc=fmA>Y+^v6*JBsJLK|CN-+FIDU z86(CRlhzi(#QS9j!5m<_%NS`WGt*-+|1gMOfq9SZVPm9`%zQv%TF|h44W?krF-Drm z%wUX(iNql=t88nHk)|>e@AeXbEDa6fVK6sjzSqDpLVEEE*|?bw4}05o%5I~@c8Iv` zT&nFSI$ms_sTY?(&9R}-K`7ah*@lK`l$v?9xRNN-l6e!QbW6>=i^jsUY)j@eO6#AR z`KUw_wt#4-#Prn6ycqF)5EoJ6q}0r{G2%z4C`W|K%TG0=G`HCC6$NCYn>liY#om{?` zeJfNt8ah&vBdul1cc652^h|cNk}0P_8SEIA>=;8RqY>*2C}SPdlOriI*_fRgD5rC>J-5dc~+BjyQEiybRdB5l>wlc2ug*pw3C6)GB--$DM|@wxj}6qw$z zpWcmlGthAYl|a}g)ufqg9O9liXoijh%xCc?`Ux z@j}4u9wX?ec0vwG6_`~J;fk28U2DWxLP9x>p*?qIl z;)XT|`1}h_cN#@FnS`eQ6zK$7`~=sxq!Vb_7_RSZ#C0WHr!$GGA6#eb#B~>3XC1_a zN1u+*LpKt=HZ+Pq2$k-1_be}(Psdo+;?6)?()ibXFCmgn!Tm7q^7vO7Xbnml;TGIJ zluIfR5MS2FPK#jp!J6Dvg1e+H$<*K4J~WmQe;VO_0|=20Bp8$K{*-rrjZaVr?$1e> z7NPM<`=9Rqf%oW5?w`|yUC1HXdVp0l^4T1(=L&>=j`ws-YlBG~=NVLWugP;e4abN- z4o>&X<2}!tJP)KrTBD|FVtS>Rg*2wgvs&;hjiqeztp7j4z5_mrqWyn2cex{Cqqr1T zLXU!mB3(i#0wzd6P!T~?~@P*q+GDwfy!s;F2{L`C@0XlWgJBnqL9nP$6! z?@<;#bS((X7eiT@W>-Qf_&GZ_G#M|G+@5K6EBG*#OBF(oNTCIkE3GQzkOuE$Ed&Ls z&3rXf4yTh6+6~|`uHbi9!B0|Y=&jI^$dhcQgYp;piu~+Gh@auM0vBVsa4NjkSiqD@ z7*A63!eY2HpkFjJtQa05hI>ijuE^zAR;03d(wA(sJkFKP&kIis-wuo;4H$jGGz9eL z^1}1O&~T&=5JGnxF($ksyfPf1Tu-tDN;tpX-L}n$VJUgxQhJ?5`U>y`xR>JT_Td@~ z)2EP)H~caZJ<63W&I!NUNeqAL3x5DWEK%XZoH^kiMcpNa|McOF6~sv201fu?houOy zX?EwzZXL#t)O+*UdHO_pl}7rQ^2com`22L()bu-mHY-C?Mg2jaet(h%djG>2dS6kO zeEQNPlqhGY2eU+dy{Z=hoWoRFQLpjqr3n5i{RolFkbcULe&))S<64v){bN!8O4pAg zc9y6g(=1Q7{#8o4H!gEw*={HTd3Igwk0$V@ddmBk$^ zn+r`lvY78lP9ZNw%GJnf7WElbfP{8>z*X?GR2n%DITZU0a!7K93mRUf0Q<4}7?w66 zayar4qRb3yAvc7zlOu96I-W3alf$=g<(U8vNeGQ2CvsMd{3S>JsCTy?Xl>ih!s0(S z>f*abTkvx95{k&qiMA7?>2eeUav~Wvbdan&lJ!M}#pP&kmNGXw1fa1g8RnI8bTok` zL~o8xBfhR`!dLX(Xr;whl#E(U`AW%&E)k>4l;~ri@P@^gm7xOa5nhRgDIz;JT7>XM zVnB(mCs1CrF1iPU9A5sy?4KSzXw6D_(YK?AIW7ndh6cFkF**7klJAh`p_YZ{mrC@r zdiUj51mCHs#w-;*8~p=`zqS&`n#s|>8WP7YQetV8*uSfy7Kvk>V%^XzJ?zANLAUzT`x1yr!SSZ)lh5u}%{z(#DE6q|s=?JPE8cPX*yl-PSm`36e-aLfzJJ?+Gs z#8_B~`6+>q_C4CiiVIG1m4jHvt{j{jtK+-Ij$WX~o<@>>8Pa!J>;Qas!{?1X2VWE~ zzxiS>!S{5Ad9^?GI(#S59b5&!NTsn8vG4NnKB3tWt$~X<{-OYhO+FdM?kmQ8|Q9&!1U2ltg+y zmz%!~cXWj0dw;F1N=7*34BybVSR972IR(>uA~G^iG|;l+Zh+81;v_n}5D}{p9c1}43H6ko}1=~QM zooDnE9I!N4t_&-q+=AD@$k$@QC+!Q~v3T(mKy`o`JQdt96E9b=83~OG@ZwVs(Gc4k zE$oB_W+5cZIWOUOKHa!8!TxVjsjr2rKYCFJ2cc# zyf^&zU1@PrX-&N7h6yGP$>0=+<-ecOEMR_GL)iA8VHf1ZL-7JMH+=%b2KI@^S-QOV z`gl2797-A5T8vj_l2A~)#vwKxHgE-Jv&8tz-uSZ!ow7#x_*=gCYxVB*RI9ti-)72P z!B<>CB@N8+FYz+a88r?Sp~Lg`6y<@9wJ^2tQt%BunsO?{N*6*wITd!YaymDruvg*a z!a*p7Jv)kpW7NXoM5oboOS3}ZEN>xZtOQ4e?}>$b#KN#x_^7XNQIfT;g~1e0A=_Sp zqMDMi5FD}@M<}fD7h-xypXZ%hu!SqT$uf=?zUeP~fuO8ltqY-!r587YHiB|lNrb{5 z{DmhN;)4ZS0Y!nc#G)?VBC&y+qN{ODCeqmTQ*;f}Z3|9W^@CSWayp4cw`oP=f%0au zf>Op5%_%a97B(tMdH6%&%+Fvrb>pX3Ef0w2fNTDy+ZgKlSd8 zn81m{54=ThCo#mLTs%m zac6>0$EzEi{RHZCttBeOJ$=R9lNog_9^vp5XEv~?6c42wtcvMhJUT&SbWBfzur&`fAL2s@*Ay-G5K}+#TFRUdhs9L;-4F+ ztW5Q-#DXIs7b{(CNmKB(Rs7tQBJW+(%WnU8huIeZ43qt_h;%qo<_VehRbWoZ zF#CDrdCU*{M1PO$XMWfx26*Ik%n$p-K#$C38V&Y|K_2-{28VrOu+vCEc0Vc==UH!7 ze$4k(h$m#X@?%(Upa4*I9z`GkG%mQS&vCRU1v+FKF8$#0c(Po_C6tq$8wV`DZ zGplk0F1`HATBSN%hD$2brfG}4Xj@vPYSTf)TBT}_5RhglO@{j~t5jzm_8npDORQ2g zEY61&{Dqz(XnQ4X2QvSJty7J(Jlq%c7E)R(z%HFc?NdSfK+@i!G_?A&$A-aOy-ujA z*@E_mr2UeJw6`qtye+*LHcU*p=$KsuuZU%z;ppnU87RX=@9=c*5KFr>M}T9la-@xz z>%EijRQV z2zPNA&7?B#X76_2?cf2}R5=dslN6*{^47y`Pjf>EI3bmyuX%ePXQZ$+z6pmP@X06sY7VzEMCPW{yI0$i6)I+jA?w;#@|WROXxEyU#xkr9f)| zjd%DSp&*sQC&6u^T>4_2yZKg2zBou&ABrL6(zjLeVXe#{mU8KP!S_1E#8xhSA2H>! zCztE{3AQ7L?EAgmosnwkmj331Y3Y{!D-k_V^7kT83uKN}K8CHXPjc>VUvTd3HJm$R zBA_rJV~8q4Xg25WfsZfipCJn#c`EZ?km0?-BQIk9t1`Sf9y!eX7>q`H z9`mqDB`f0IQ|X;c0jB%rI3gFZ4=RED%yt}!kl=@OI?l5$Ea*v?gE-5z?ocb<_6zNIIa#>jdV1$|Fx+<$38RiXwQXnblBUaK3 zc_(aiIm+g4%F}|fQ&P4jVxTS3ePxW!F+n*ZDF2g`R}!)EYaHA0?5BL?P`*-Ox}X9o zn7lao)oG|9+*n9DvGRL2wYi|CD$3vW?yGLbmLZtCjfkq|Av(-$y+_ zwSzl=Uy#*jh>Rt^FF<^+9M8FXkd+FWm1JyDQ#80bC|iH3dwb=bEZ7OXjeJPxZGuQ zkSegfG)~E<4upME^m{v7v>ZX8~DlsL7B_AFfRAahrvovBuRn7-Sb=8 zk|m>2<@GKj9n_1I3gsJnSGKr;`c?qJG=3=5#d&af7GbHS4`t3usvr^k*0AD1zEEJi3V6sk&z9#itVa! zr}5*4IYta~j#u`lSam;*@1X22ztYJ$Mdc+ydDbpF2|QOhnhfMuOJp3sI@p^2?}UEY zGmCj&NaMyUhZ~VOY?Hyb@S#n{-iChQ|DcoAfh)fTl}!?L^-UyASI^;cQIQTZE+*ya~^Xocro-oI8_h)|%uh5TfzpUbyJ!G|3@MKa3Wg zIjNH5u<`8H1;fJsq)+8jZWE17lHCW66Gw+CrJtm8ZKZwa;Kp#)!7;F)gPu17b+Klk zvTG?4T44qd|CCeY3()%j!Ko(~`PmNw3N7MFsZ!o8KPA77%YA>gl01h1amHgnZ|5zSrvUpANmNJX8+dRmv{xrQ*8^fzMD6Ic{?T;;iZ*J(?Bo{IXwjUfFvAyR)1@=XLC|_he^xC_}64 zy^*3H)-aPGd)oj-^<*PJZ1D1paFe403f>2ar^wS~m{bx4pGg7svkTtq6%^@P&fU8` zo-D*z1+PNr7Q{s0GV&};h$whJPQpytwBY@v&GK#X{YrPY36-f)!LK8v^9$bpyn+t| z_QN>Gpe75xg8b}f6?_mN0@%7fT5gJja^u@JdOc!gW!C~ zaSP!bz~Eg2dFTum$~T=#kX>-u$)^-!m{hIaX5Pem)Gm;Wx_WLdPaj4=+o6x(b&e?x zV;DCb_hvngd=dpRvVpbVoD3{1KpEC04Olpb0<3I?bs~WUQFW#m!=-AuOx`U2*xbA& z*(4V@jgf$FmNz$C;cHxPL*#)d8uI9mIeN4OYjlM#dU5g!Uo0>mb{b=lW~aQ5_6T)$U)2-@*6I5bdwk?q;nDTf&76> zaWsj^aT?9^)%>TI|Y(wja<;3^Acn^`%tq@8q~o8v^DE$U*md= zH`fO7>_P+<2sZ)m7l`&YhdCwLPSC9;OV!F{O8Yc>2t}LR49L~WwRGY5Gz4!!aI}(} zhH9bUtq9Ig=A^Zv+{V(Na~mKJ;cqK4awrco*XeXB%c-E2eOw8^Pm3-ECMBohfM*jt z*484`+)aFTDio#3RPuiP;JcYh-fuX3w~+GGF9*I`X};_?DUDYivZ@0ay8D^<&!res z!9|_2Pfd52w2+NUt++qF$)wT z-tts)+CL~HyEZ6nXhIg{Qm+(|nJ!&TDi5>^{KW^&U+#r&}=U(DwuOgZEsT zd4~nV!8T*IRP9UgUE0>Xlfj@&Uxn&^1kjVdlYv2~7KiUU=3)eQ`e^p_J%hq`Nh;!g z0Wj|vz;Kp|t(T;*{~Ev~tO6UIbMt2tjLBRw9TLpIeTO)B@qyrfE0YRf+{@;ABLl}N zz7zak+CXVvfB!FN6RQDKKg=@&s=A2&Uo_@T+Mm`_;l*YJwJ z4(NqIuhYmo@Qnua{nnvi8&2rgr18F!mP}vhGCWdsU~XW3;5f3l4Ef+=B?~A3{nQay z3YU6(K!*oCKG`0DbpWuQp9I;*gabP=y*ESU_5_|rUKrt}!1ML)L4D=GYjCbp0x+fx zx{)*HyNtO~b+C1?T`&aN4}u;(-_f1|ly$HRT*^8~8fW9IgJS{s*Q|rL+gS%KTjvE* za4s_2DhC(C*`oxP!FiEo{Q$ClD)>wY>XUpa=pn;;3b3qShRd?XRNXY|Zvpt%tV5ig zbqJqQLaDEkLYLON2VW_N+QI3gggU|*$+CV>st(-~x z$~oNL&N)m9NaLKtr0M)?&f%NvoWs*t&N))}o_hC?E95Y$eMomDyb#Vnmh(L1ygj^I z?+$a`7|=t8`zXM&J_wfz9VX4ZN!DKg@b6ilwX@dgj4ZZ5CEbn8Oj$>@580^bZQ#_g ztmjMB`gna(eoG8KmO7~4LIKX1;?zk)x2HFKF8suXetzBS|6ccw9KEWOpl{8jA<>wP zm0NH9K)U{Xxfctn408sT6X9{;M5MVANv(HZcV(haa@``L5)lYQvoGOAu1${&w(;%) zo+L&>QUn9Rb*%`?6N$4@&S5*jNM4p6skW2f&1L6BPDjq7V(&qsoA~s|Z^mutfKt>! z_;U0DIO$5X6=kSKv0HWBU@j-xQ;ZH2qP^@<6R(fJP#+zE$PYN<%3+Q%_y|B%G=eJ8 z{{H7g#ofP`7|?1Vf0LcF4ejGH7E09x&Vu1ME5Mtxa5HKu1jN$)k#|8JJ41jaK*2Q7{?~S~ z2jPOp+84|=bBvl)i8aEoHpnos#FOcJ!BGw?Ee2kd2u#nQkQm+YiHfaOJzL_ zlGdXwPc2L?6La{~4{yBi%g;*zxgNGJ|kFw<-1)$e! zQq5Jp!kr!FYy?pnNItZBzf?2!p)_+2(gKD<%XeC5mQ4@zv4B*wLMl%)=O$w%!;XFc z(IKfu+9Ca?t@$9~(pxb`5TMtkciNf{0i~f|l09_;qK-&MuvLl?S^9*zkOPU9iS`$5 zNYBxDoQ!QFoy{~Klw^0kdw5?Xl+{KSGKr)pr)Qe;j7Lcrb!yw2c-n zBO=wvS#qv67+o7_sq_wcDg~KY;_gQIHE@VSit=YEYtY zlqL>($S~t#RhlP1DI<-!0HH~ICsBSyl3xH*o8)`IU6|!gL7(|N7^^$@CZ1^T0zF5X<$^@dol^@~ql)Dx5x$u*$t-6THB2k&ADGyS7 zk}k~zg0f6f9&X^{_MRP-Qk(dGN!gnuE-Ei;%8O0#DI*fD{yEC~qVkoXe3VJjV+6cC zK-sJOfYc9gMEeF_Evb`1S%PlfV$oLW>eIiK;79GRr-ifR|EA6?-^|Qa^@2j z>N#J#rl@}a^^eA=YAZrrBh~nN`G)v#u-;t3P<^9)w>3fa-GJTU8!}DFE@r;VSPQIq zzNNkjV96Gi*H_ULD*&tj!?KGBUV*v}sQY~{`hMWK@KFo(f4(1@qP_!EoXSUrHtIsc zi~{pl-(UXy5O+%`@Kwp?6vWz#6rX}M!kE?BmR#N&sAuRN}e0YMS>}E;3gy(W)&nb9sYDykbJ2o zFfZ_M@M7>|2?&;|8UtvdAR>)q zE4V=pu14$zTegA~tgw(OF?di8LR}uaAt7TN$>lq_!B-J?L=L`9ady#htZuBzif*9j z-v`fzR-z2n=!ErbDg{~5L)1KpRtdGELN^w#P~Q-gk0#<3nvG9s3Zd+O6h4&e2<3+E zvkD&?_m9GdZpNDwQ{~Xj_3j(q{g=Y$h8{rzO%6SQ1Z%B=go5xt!3q+WYC>y5rQwd? z2Yr&VafJ3!kSaS=54TBWLmLjg%6AQmDPrhrG4!Dndbi%4Ge$0>J`085)r5qL;fusD zCxxI^P&BHVVv`JV?%@jO9{CsN9@P(z2hRpP?{ePRtacT zq=!pvS{p#C9Fwt8>@t>v*52^5;jf7nTUR*3Zy;pRdiI~R-U6*p(!+1rw2pw*_n4xM zl`i9P&^m)}dv_pOe#V!cijYO?_kYmRoAH8vS-RfLqNQI_?;e+hiQ6z;#uHMF-bK&U z#}h5s%~3{u078tGp7~E&gF$Odx<1&ZH5{~pn9hw7m$3r0Ch2$R6465S5Uu+WvS?w* zIIr$?4`@A-u6t}+3qb2I=67S2%aB0JtLN)Gh*rp=Rf3R3EB~Lg)_~ULbbXCY3p2}& zoiO1Wt6hc+T6^?^`j68l4^)WYdC%K0XzSg0YUr4xM{EI$CxKI+itvyK{$d?pz<9w>bB> z4tUT}$L-Tjp!?Oy{mkf`#D6!Pr#7SF_s|349*z0`*9MKOO*k#fdw(EKn3)v_@ zSPRXTnS#Re@`C`d1q4=~=vs7@z*4#yQ}18Dm^3 zJrDr9IRDh^A6zPfke8ArDTC_Wc{f{3DzN&4$pV&_GFejcSR7+gp~IX*{J*lia0*8` zsJx*5g1jJ&s1fCD1h8UGNl`w8D;-8^eD|F!gZ2iTRXf8{bCffp$_dIjN%;xn>uIHC zy#uN?lhqV}US(@3yv>DgZ1{84i})VdIqDUiI;fou8jVG@pQK{tnpe-(XR-=O$a|HR zO}Xj~EbVQbMD-C-y<1YDjo8UVb)l?2kfcs4K%g+Qohq@S{f1Y(a#cU0uu@bj1$Bd@ zt|kJ+BBd17?Xp^(q+xLgoZUQbQDGl&|58-nlvJ2^&n5!;Aw4 zqJ7x^g)XO2E!9er6iHLsv)YHjp$3rs(sOAFd#Rark+uTznsl_SzS*d>+6YF7S^&S6 zeranKTEK;5nb;=P%ADN1t-iNW%IyGlmV36<0|43!eB%H+9r7PUos>^1r@^a3{)V|J z=rU00oeEPea4?Cd0I9Dy_N9=a3vVdHhEatBuQ>|V?LFvFmD0|rNi15)5UapaI)YhN zyDImjWcbQ(&X6VIvU8OAqM``O;!LHzQEem9l?A<(c)C(zBfWqFj75U7k0oLkVPH{F zY*eC=1?6K4YCP@024f9vHBLMRUo~wtPW%oh%j|8LW-g;ns#R}QXQ&#_>DG9t&R1#T zr5`I)uDS@NU2yjGe%EUp=P&h6_MCA`$L;`bPbYlH+G%oCe0}OsZyMo6FcG z)oLBFk2#L#d`}?}mbTd%sZ;c8sPSBFB#ugt%%p}ew!4fyK%1!DMT=ne)q0?L*oqim zlG7Ff)%p}0r_o|m&PUdG^IX%&Wn{;ZC@ml(q87yxcq82aMdD!824<3tSKCtWo-|9Q zli8EzbCqLV#$M$3qjuJN9s2xNAc`FSqyUXT-c-0MQ=;u+g0Qz0FLr!|oC&W1lx0PlRO014i`Fo1d^ zf>*YAmrfDyUUcip-DEH3$;o~20;|h-5}AGI{mch8$yR|C_9^nSA865gRJqwjPk44_( z?|e@gKN#CF0NsQc^`?(G_oPekjKQ;yb5C~TS&XNgbKk6h`DQ7`0jbuX?H?Vv)M1vO z;HW8k@JV$V2N5^lzpUvP@+^S+{ja8>w;(YcCVft-4O|is({wojc^;5)fk}katt=NJ3D&tzU8hWwd!fOJ z1e2S>W&!3q)C7jcIlvEdB<5BRC z7<@+#V%okXxAAZk{31R0wS^OEiQ#CK9D=R(mRz8OI*OtGLa1vdn)cboIH57=p&M^iZXZMC0BXA@mGOL`d(5p)ZBd`wlLJ(E5e2A!hnK;%2dJi;~zS&U!NSHbQcAv$Lh53J%51G zMd-o3L`ulJ0IrHvwl&u?AYMxV z@I3%`#-41ezm^~a;QIi+5lI(af1!JPSU6nKQ-Sf9eMG$NWdc{Ggn_48g69yJP;U^!yE0cg%kc-LXi{ ze}>XfZ_NKNlWIuL|ArvOVL<-Qq?(Wlnh{y!z1)IUcqzF(({R8qXME%`KEnN$*A$E} zzHKyr735Hm{n&go?1C(@U{a>E9TkY5aWb!9R>54<$**@gbQ3RCKd4(9JOye2mM^~N z0G5ywzCRhNci+BN`GEAPf|ZOL<2_EV&BK=_v5fUS)u6YC1u$E0v{bKxm*s-zfw{}~ zyzb|W&+`h76nvVT9@7gxGkzjQvf3Cx*k8uW(gH@w1 zMVe*@Bd-kF3N}G!3dSv&Bs9jm)PJxUfoWARo?vxn95%iO-YV6=vTWK#YDdA?A{&)N zRPCtyjMIpGPBma{n|6`!DaCjlF-MIba*dC8)i_R2m+`Swi^=oXIJPRxO{~JOi|VEz zt%~C9;QFY7hI8!Gjgk)%G>It(DLL^za=bstdUof zcXVdUNVRYc{0@#b{|YgT-hpo(mTQ(Txk-m_@)qtc{13Re2~E-uFMdC-6jGghM#faF z5JwO0=nS*{h_Qul2!)?`3*Q4^wsMtzotrO8@f6`WiyjVSaJ1)DgpE}+IP}WyMZGvL zy<~mIY-(t^=z35*z!@KpEW$@}iyrk9J<9N|weWBc51NkQRRV9ljW<@NSELE==*Xfs zfcL$p=zE5j&G3p-GN};=uedGeExy#o%ae@bH=feD|>MK${Rf^ zZ)6BF8N$lDGR+zr;V~e(6i0?ot#W;d&7wo=Ut5p*=ZAd2Xjos;sVeqr?&b7TYPAd}!vrCRe= zb6UkfNH8sQX-qd4P>?2nX0P*6?}R#u6C)SrnI+~L*nzgwFwbXjd1keVaZ9o;4H3+J zlDV_qJ!7%-wLT!ve93&HL0rxE74v_HD<-Q!o_W&z9(35M1aHrnf0bayFt^@K=bo|P z>Q{29qvX=HEx-o-7;Knx#MqL{<&rKS;&bvP13V=Ih>gI79JZ@Ua!SzctUDKYPswB! z6Uh=wV8;BA)vC7ygV3aKU7Lzz(rn-I2_R$a2HO+)Uh*djg<&k|QnNanuk zR^+}`T=k%^YL>KWM$_C^&1=X#J1e-V070L)YK^k07`|faeEnCgMVnYvp{-g=>HDuL zPlEJSM_#l5g^m3{#M^a+1vHE+5?7%IkLpng$)AN8UhE%_5?&; zjs5-^cn|l~$kqSlN3K4}@vHyvtp0=LyoPn0HMmF28uH~eEfa~?VEIBPIm9)i8e(&k zu~WIcHH+3PMOm*6XQ#3P+VJqlJ&YD7T%|>kv2FDq%TZ1FMg+Yy3=10#7 zu7QS(>R(f@tbvkjSO1!W$-36o93;&CYhF%*^fg$>p!(Om?4!tgU|vEMkTuN?qxu=? zFNkyom%HXq-n-U`ls$9SwiVZQ)7FYaz~W{t#>yl&YX=gFxOSwnb|`$7Fsz08l@Nxt zqX@JATG&2pkiK>tfyA}rd=xqJ;s$Q4Fu1`7v8Htr*WM$qC0X>5R+RyJXc?(u;@X9o zX01_)b9lm9Q(B9TGh;DE`P(wgZAcX7j1!oB*X~c$KOv%VgKJ+SQsUb8m9=ldXR~@F z$(ObkI~K(1u_Q=edyGKh+G9S7ocUxUR#_OV=Bzy>uKiwK`yElY7`>Jlg$%6Y8+hmk z9&*;T7T0ys*0m*~R%Nd10)L`u*Fl{ChwFwb>xRH*aky?ok{xXw$@S~~*X1NZ`nntf ziR*HF6gg{J1BX_anl>eG-JEp`8amKAI$hE~Pz(+$6CKF6t`_JU#C3;+b^E1tB>jy# z(7G2X7pnu|dtzUR>%NiK(QspzxObw&IFgW1gSJzN*9+qMF4}sWj7*exJ?urv60f(! zXZ=WJeS`R{ZzMkJE%903NPN~?;zzDwsMqw8VF@a~{ZziE5#%_36-hf@w89oQUp}@1DfN{vCiw$KPu&I$4 z?l$0F0JIjSiw!3dy!$sm-0sU0H>QajQ-uwGNE?1_!antFRxjGd=7>lPeH%OS{KkHs zjs1wCd=;jqoQnLn# z1P2((H|^)Mv$OLy{ZX2N`nAlbVreUHDaN`PAKTZd=aqIVy$TCNyuyzW+F#nU-hF@V zh_R(ZI?YpxW7(*}zBK!mJ|vbd(@GZ-AJ*(!O6_XTzNKqQ%NiQ9w1PDz zx?bsLiNw4@-$8?%N^b_>?kEG zKc~EnSl-EBemPY-yJ@m@Ifh6iMc<+u%*uzC-_TH<<+-dnLs?>ZQk8054u0l%(m1Vr z4dcQ1B70={`zbl)zxm4lB1y$5yo!sl3KuJ`O!B4lhJd(?V^VF!(25Z?Peb8@8V&W1 zcT`NIAgP=ccf<9O%6UIiIh}bG3o3AmA)#VctdJ^}BJ&eW#jJ=`6gQ}t73<{+RL`7q zOvS9&RfN3`RQ*cDm+)T3`r^onvp9}k*|PGoq>3w6 zULjYaGtD{2bg)Y7r`s~1R(2p7{VTgCLE*~o1QIK|Yb?^6lmI)7_8&2}vX53d80qFX z_{tkSl~^cX=wUi$<#e%fj#_ya5n;SlJ^(M{EhVqgR~c<+l}hSa{Yk~Fd?6v^-bzfr zbMb|p&xOhlrAjOw=A1|>xN0Sp6GnYfaI>@YDl8#9bHu7va@9r2;#IXymPM^RO`hrriP(Mqe{tN>P4e-@CS!~BvlYlV7)g$?fs&DmFvop5dUe$9v z)pJ-L<<-kP)ytT-sygDSCc`cYSiRm;y`H@OebqZW)jJrpRrPb8YV;K(=v95#Q_a>Z za`);Jo@#cUMZT)~oTvI6B?zpkY3`|M&b*syuJF{bYk31THN8AFy%^N0mzrS-W)p?0 zxitaNYVJs|U-JOXLr}nKq7AV{$=EWyCHk3ETT@?iXba{6TK!V@cGMiEAocT_6L5Xh z&mUs_9Q9O#b+uJbIN!;JisMr47WbA`JFv_#>ueHRI#ZBHY$1y|BLQQQwHI+=mbfK5 zQ~!Xa<&3ZLw%oSmP7DytsKj42W{YP_XbY4U+rGgGTU2QaW|D_ml7VGd%80RB3}MSA zWy>nSaxA;XmP4K`*!M`vf*3*D*ZH zuCaAu(yp=9!zo+uvGK;rTOn?QcXZ@dd{JxbF3;9o49~J_Y(12;Yi#`xcyHTydGgk8 zExb=gZvC6%Ydd*rJ25=Vu2DNQY1gR5%dWMPZ9Hbzz>YOvTk5GTWeApCqjpcyu2K6s z5MHnmm|de5U*g(!iD%m-48gK%Z0nM=Yit|JDckzl2+XdrZ8{o>#DCipNxQ~2OdAii zRJN5+LT1<4RtN8Z9!T|}uR|P$24FuQu3JE0 zv2LMi`I55-tT%N^ogZA#aIl0I>!MO!kTRh;SFMW?9y2=Dl?ZheTHQtfK1Sz!JcX}& z*;Ds26UljG1*-eB?qssY#ky0OG;Dx~R`(m>aK`a0ac66JCp7j2Q`lL2@6NXM?uFfO z0)OPrt4U&0vU=~#OW%2OC2lz3yY74hcQEbJcFrgC4E+;sdUA{>^v^)Jlv!$)K+MVY^Y1S+6%ibY!bz~ zLGG@eyu7O~h)i)AUr4pPM(w&`*FlsNrY&lJ$F4jIlGS8#1Q66EB8+*$a4P*uC@U!(vRD94t~p!%yM_-?Y?mLWeJ9OVfPi%Zm3p^Do9Dm z+udvTbs)K$<|4d*xF=`#xK85kDe~?KNK!}Y5Wb2w7|j#jjc&5&Q*pN{?0!Pt{V+w- zNNtS=X<4D&RGR07-Bt4L4HQY_v-5Tz-2DpZ?Nml{+wV^+w(`gdkL@Z zO-1Bs#^gz?-SGo zQ~;0x#Q+6qY}=O)H?ao|wxD+G+am14wl>?hV#ArV4>QS<-_eZ_`MR(VI$FbABJF#} zj^sG^RE2ZjelO>qwuf_1?~2FZ+%srwzgVHD^g~=%C_X7Oe68HRo`YCm}-T@Segfr|~yZT`XVhGG7Ls zK?%q~Tt{ad#gN;}?Oo=7&x`BhjPr=QQohnBpVePTamLdScS8QIt^N~8 z=r5pq#xDTqocwoNIRub*9+#3Dzg((QoQe~7vgp6zl9`U|au$qE3fk8xhgdQsj=Skj zQe~<#1I^rUO$%P1ygSo;%{U8L>!3VP_5@r(c~npqWXd6Aci4*#6~81;2`WV#XTEMX z9}3h#SsA|=sb!_Q-o3OIH%RUk@ZnD7X@pMD+vXUhajl#FQwQaH{U{QOYBNQ_XutFX zdpX4VoB|h5%T8&=BPUep(h^(@&!5CP(wVg(m)q+Ffp?W zmXfDVSJB&=@TYnhf1(H^y2|+?w0j z;;OkTexX#SwbI&ZBRCGd5)*>ff&AujJJ35W z6hO~@1AT??y>}qUO6Hvlw^8FHm1R^nUf1<5_hPtG-?2K1H=O7xdA|F73sCqs8ycsN zk1f@?5o3I+Z?#V+x+htUNxs5*_wpNQP3bF@eKiQob@INKJieC_^hjg%edap_9{t(n_#LAE63vg52s6O?u2J~{r$ z9sE<`Es#p{V^e4OdvqUP(Eo^)4r^eRZdCS2|0bUI|HtG1PXd)V@gMOYYv9CxQuQAP zVk1s|>)`(@-jb*XE~s}uemA2Y=**}G`Xs1RmVsL>;Jr4m|syv;Y4b1J~HU%bAoHdV5J;{;=X(?W#9?IuEHwm7Is&~$l$X$d=&gh z41OsGKW#{LCRqylwgJvL{*@kb#?wI|!+Zx9mxdPeN@y9e;)-7))rC%lehp(QoVq_+ z6)z0&6r?^DcEh!<{A?nGj=b=Y@CdAa_CVH3Nx8rssNqFoc$yfVD22z>yPtShegL>! zS-Jcmt=5o02zxwX)Oi`+Ly#XTtKrJFCgak>kC$OGCWNhd_^J&ylN)sazC(DuH=S?v zkwr1QT@G(XHfNMggjIP1mm7YDSHdsUyI0)kino^P!taDX*GHvrn#p^@WO}kL4-KEu zM*#ta(^KH;KiIt`0^P&XDfLc*-i~!x&6IRB*@~U|Yp!@3sZPH^pQGa=I7Cv1QN<>y zKdeWH3H*}8_+0%loI;cZ{V|)A{$E$TEod0}X8k`rC+VOOZ=g}D|HmSMu?&@!tM35% zlY+j3p-Z~{k}KX0=+EjO=s)q?5@2IJn&99wOb*uXE=SQ`V1EJZZw37ehP_08*%iMG z$mb$ykzpwe`L`r;l=v8ARtw5m_9Aad5iFSG>Fi@c9U>pw zHxRss?}+20LAjA%_|9T9O^#sIBrmXf>-*@f`0UJ;>=QZ(;1K{_@s?6ubZm5TbT7F1 zfN>MO69L9e^gg)OsKDlQHqu9z5Ph!{#S9~#V)V6r7X9^7bY&7~eh47u{$-~*_wuVb z_Y=_aS48l93Plv!zBCih20Y(zZh078OLSpoH^5Kx*%?rJlEE0-X^W48$iotHBGx4SulkKh3hNrR7TcN*%1?3#>HcsXdb1siRdBM8Tap1@6C$qI5;Y zLySd?qN*1>p3^^a#jgU%wdw&CU(#YE*ENuQMg7cTwDBmazK*wQ-WAl>ZBqIXSG+f9 zoKVkdkarq=RMKdyO2fC*sS|)LtvTGLqmPy@Xl)o7YxL22*1Ns=oc<}gfcg}k-#NE7 z01sB++S{Dl+Z~Sw&wh}iiI9ibyS<+yWh=PH2*SefP`9|2t)EgGx&`%z$sFguk>ehR zMP-h>h8;WT$pS;HABU@C?->b z;r^RU-6p6LsRaj+Ox<6PFN@I3d>u%xP&eRJK8vK(Kys^!B`fndn?F9YRZGxK0+m)2VwuFYj*fCgPPA7$Sgsd z-asT9MCNO<1}%a*g|?u9icUaAr4a6UouW$6@M;oRu{*`CdUv24Q!+%}pMhs7o&$LP z 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%0Ama5!b4Qsf-LQ&L(O>Yz9Kv5i@a^NlYOD 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≷2Pt-F-kXLvF2)D*h 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%0D$b4CxkmO|Nh%omd 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%0D2wAKa{>0{E~y$;6RGfwp_)m^wB45pTUc2eeik- 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

    Dbd^nX8Y^R(i@I4Ra+16Au?ncMVPJLF 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�(U28ClRd} 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

    ?t&+=x?{?TF6%m~y#!C=^Mj|^n>T{6(QiAT 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¬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 z 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 z z4oHgK%>#E{>KU&~Qf*jpD*804;=VWa7HCM1ewO>b9~#il7)MEU&9S1pg9XA?W$sY} zWvxBpUVL(N;!k;P$Wm)p2Ele0yy1s#IfSuz{Yjj25S<6)FEQ)Jy<%$twHULE%?B>} zs*T=M5^zn1FQsG6uges1m=|t{Ig-S<3WU~KO+eR$$7;MzPgF_4qAWMP8%S0iM$e!& zoK6w4mOMQHKi`RqhXfgN3dzj*z(QVInF;X!?mXtZu$ctLum&e8nLGxiVCacbChx^8 z$!2McQL=05{Ok?ttZw6QDt3^8K#-0pD?WQ%t-LFEr9oycS(4PfTjvg#-rXpexA{*w z-;amKWKzv3s|$}>s|q9=pxZIZ&*gN1@L3xUR&s&)#B~*D&6Y96oTJTFvCSHLMWQ8L z{hUZqhPm{yL9KljYZ4X0vUDWfR!*P{EFO|#m;obB%#@O0fppe8(X4ZbX>py8!i&Jg z2{YMm_L(g}1&+%yU4n+>*MLPRWMMDEHM5y(U~7Am=gdNIU~Y6`WQMU}dYs@juBmfy ziUic)O7!jR&SFZXD8}COix5YybGe?5%NhM*`ta@rT!7g*iU0kCPB`sh;#Vzeji>GZv?#0l#x*%(-OAHY|>NkR15QxJnR_RJ0i+r6Tqq)A` zSZN|SfYTy-IZdocZHlX1sQd*Pc}#HU43DQG#je1PHZ)Geeef<_Uan|p>ddvy1F&_d zfAv*hg)>HGdRn&b79cPz06nGdiss-&EGO0zdaTqjC0ob=g{(t`ZWZcEWfr?YtJRG` z#J7^77-xgogaqMjuo$N_1Hr{mUjbKSDg8NSu|TlFM-5w2z^k~Yj_4Ms6NtgF5NCyR z$g+DV#uNArjv7m(kOy8=ba0`Zx=+0s5z`MTvEhdj=osV-UnfMP062spjSc3y7FL%- zmp~Hk38be`#`)TYY`-hlRx%_k0pM@LM06WCgBMg56E4EEc-V@G2Rby;bp}Jb{ylMu zLo|ajlH3@SStWht?!4m0in36r{OtR2=H4RFGx(i2xOF9Z_0?y+S zSjyg!HBPP|3D-e$7>Rdn15)Q(H%laPsCFf1*QBQH^ak>JFfF)|9Eq)N_!PP{OBNZQ z8Ba~sd1VEF0OI;%(o5Yq{eqH2o?)8}WEU9F6v17|nn*R=M# zoDroaPSImiLzRuVmiv&>3BmE$sak9I`BE2F1b!mvy;gWski<~O<=e2Oz!s>%fuso? z=$cQ2Fi{=1x=-Joo}Zq)y?A|cZu0u{{6E67yBO5gdCW_+6(KQ6P>HarmOo!f}`g zHb<|ph|0pE8mbQ^hb}W-0>A}@M|>cHO)UfXknqnYPyHvDQ4)B-Qx7mwJ(?ooHQE&ay$ z$IDY6?`kGnZSi0SQ=G)=3(tM|aHAJ{P~UXy$Fz0_NcBrklBbbBXeFg;gHo&-Q@Gj~ znz~H9XH`H^v4t?tM%7#F!%G4VOnN@|-V9;O~ zDSJgGAlZ?5wEYO$=^vh2MFBNbvtXW%;x}-sdG`vkqeFti?;25fMmY`n7D|9twP9!k{16=Px!EBHRQo~@3is?_1 zEGa$b-Iq-6@WY}`SAzdho2(qpwNGM4M&)>QQ`U&rAFokNN7*}Avqb%bSuw77X1N-4 zx$kI2R!4E(SKs1;%#%T)#h_~9S~T}Z+bg4fmI%P*%{T+i9-=b|sP|NKh_W>9}*&y*5G1+b+ z(e7i!DQ{qbiXj+Han;|H#k zcL5hiOtJICu>`dlWY6!95J^b|QOE?!%VXZw>=I2xQ4m+YkP8b&u^p~|SfpJ@G0J6a z6b%MsFb1+Zb4H2?1#=p1f;S03%1)_BBDh0xOu0_ydL@dZ@pSHn5pl1>@fzxK3jTc6 z^Hi`E^9NoCw6ri* zs~J5)m&5UiHTc7Ru)0KXD16l~yTF*|HXFn0)LVfg2A6vyUljls!x%;y&YkN>;Uq*} zXP-!OemPij-i4k~Y@x!23o5yIntbmE?hDIvUxx=&o0Ib1iY-L38^rr00YVZ5lW$ki zkwk!UbV`|5<0!)|7v%T82wkpWD{iInT$CE3mJM{u^ROyR+tO8&NOT-;j|3?#b`;5- z|CBkLGKUi#5$Z5)Z$F|Ds>8CGz79u5a|8QeVIM;%N~jLA%R^b5bP$s=Emm_u{dns- ziE~bDV-QDzl+zW-3t^?9AF4bbbD*3Qkk}51AkI$6DtD?*jDMOLX zD5Z5@Eud?CP=~h>@nMLa*LCCwN@l*|5xEW>;%jDCR-75KH|g(>61VGxh&jZ+#&tYY zS%u3)y(YRgy)V`e)viI^4)=1#@kkHzbY{d>3PV!A+Dmkb|#=A9_X8GOVG z9|R#bw^j#h_w7{K!4h5rEy36Uol^Bj*p%Wxqad4u+chAVv6N)tx^KCR4Eq%{uq3O0 z$?9RtonhiEwqzBTWap^3D=Z8W#k4yU3)l{P22VH^cv$<9CdHPGf;(_FIjW&d(23t- z)s->kR9TS*B7&yL27yAelQ1=dm47=DnZ%Tfs=zoE6sZ^4Cm2c845K!oW$h60BRI{z zcc$P1C6osH5zr7p) z41IYW$?p&wPm2ibUarHkPa2I-d+E+rW0`!jASeFppvQPe5hG!kMc;&S9JV&eA)7#M@Co{~JbcwVaE=~h&Pnn|oIy&u6 zd4`}NZKM;yIsOaNtAO8SDr}A=QmV4$Jk`H8lNNfuqbXsxO zp{-+sM)qn#6{s0`Q&i2$yx_m?dq9p+_igBenj*!?fdCJMF*C&tltD`PPynqJ3n*f4 z!?nTP5EQ=0kV_DdJxV*UsqsQ@;8fAMLTg@!-7!-AU;bo)#h+zgmG1Rb%U_qLzdcZ% zo$0@u4eZJKKFv<=&rX+z4rRy7H^17SRZnK$l*h`~KF%h~({rDeukFoll`qx~;_JCX z+2|+P&GPZ`t+Suv>GATV$@0ZZgL`&m$4VnJgO^Kp@9q8O-1N-o-0$x7e=+@W`P;jv zv#Gue`D;&rvydY<_$Qb5m9qY9AUl#B>N|e;(9r(M z$9*42j`AZ1_wTNhvQIA`JiPyK8C5?U9XNz)du!E$y<9Iu_&cj}AUQ1#OfKlth&j(>IV!^`{UW?*%W_@ha*;0n*Ds(t|4oNtcgtZ;r_Q9^ z_zZ0ZN--kemz(fp@aTspoN8+dy#-l=whzyBC|O(bIVi8|84Lz7Fy?NVX*1;SQzqJ| zuZit}_=-nx_^pdu2Yc9+LUwgcc_urx8e{|8jxi%hHQ^u$9}vGEo~rNL0{j^9LCp*X z5bA6;R<<`*7^fhbH=(}MeBRusRlbvGL)r&zw%UBm(=W;to5m|!I1}@x(xmq% z4e0qNv9=Kmf=*Zm|g1fOn^HK0GwKZ6SmI{WZt9u>6BG#JE90@m!TQ{qV zoy645G61LmqntYZ!3djceB@dW6q!N;X|k>2tFC$umpXrng?s8e$&vr#i_P{N{jal+ z$BTd@DG9nXO&?s(nw&y+buqs$_Lg?+NXzT=CmL9xThYSIGs9yfpo_*P;@Rju^i#1i zjm&NVCwQJpb5mDaOk!l6nk?kVdc}&SR}#l$xS5hLwHymztA21J5QZi_^hZ9gw0kunN~?^^se?gbQy^t)ie*=;uYus{Y71p0 z?T82q!WCff&U0;G<1OqhYBNj&KtaR0L-2EVR1@mgvi{C^inOfH3dXJ#xW`3qtfGod zPXtv=Vl&!MYc(+)P9gEKL!}f<6MS?i;GrGw8w%p_-9CAoR)5wxu|({eqSOmH2FTzr z8r_nDlK`a(bIuYru~$KhIA)y3A-lHsXJS+EJm+TH0p;Rc1P7#z*I6x0nz*PZCBn`M zV>2ohVUj$<8s+V?7B_U^OGLp=SL!NzW5NN>x^G+rj4*HP*kOI1IJ zXa5wU!9*`}k-?`riTZp&3iB+sX-WE$OU2rgWz}38tR#^HGBu30;Q^N};X73Rs0zud z=@Eiv{dx2mTl3f*f!HAH4s5b1qWeUvlIv3eIy_^O4$Onkx#~Rq9o=3oXm1hl!1W3`iU)Mj zIt0qqm6n~xv7aps#4=!H-~%Et^^G>^+$QolL(3UNq5_hhXi?dyGoVe$iqJv8X*jQj zf)ao=CY!Gd(yrJt0RzCXj>0SE$7f@Mi)&5wH7jN^X-G)I)^tJ0c!Q9@ISl#eJDO&g z87VE-Xb?T!L7-f5t$@_&pvbVKHIl93gdH32(6c0PuPi(ix)KMt&ls1Udc?6C!^GSA z1&Gm}yj%t93)G-WN^;ZUN$=Mha^PEIE~w~iN*v9?Xsy<74GH~m0&D_pRVii`j0c|4 z{(F#vtW>Ekx@j`7t8rvQ2uaBinFMWo8 zv;*i18gC`^jzkR-D?~N(8S)-WNh?2#tIqB0Q4DgzWw92n#lq&0kO1MlIl5)VL@TIj z6^a1+ME;9c;2FUK@m&i}Kls%gy6vYP3c@p0h(L*;j^_cLhGW8O(HWH#gmw)bbp`iW zXrPW#Qt@oxn~#*tcClcn$DzIiO5k!*^V~+t9VcDd_5d=-K3%y&xd>F~d(qD>UyjR& zow2XGnsb11Mv@QY(WsT3S;f-Ak8R~>MK5X1kO6pceH9cuaWSXI_vvLu>>uXKbC8XpVu6ncM#W0=sXIebma z1TP7UQ|K;Et48wr&?SBp42B-a4~2=bZIozUT~VjZA9z+sb2x)ckq&b>a{;F#$|Ehr zx@#eYpdg7kI0>|zgQb0+2h|E9nbvBYx2`bc>c=@q=dZI~p;GQE;z4Bmu`Qp^FeJs# znLO+^LZ3LNcnxS)l4tO1j9KLVLZ1Fz8&kgXY)T^}#fRcE<-Dztds|7TT8ItnZ4yD( zW3}_ox!badFuxYhoFkvW1}_r8LIg{J^xteCpPjrT`;&vw#tgv7=_v8$a9EN_<$3!G zsTq`-!dHPdReXfxbiTPQj5N1*o#Ww!nzrtC-~g!LE^sTXa{~HF7YmBXN{?kaml+nO z8B4NG)6{ESwgke~RnBaF36$u8#P}E+4U5ogsnNs#j{)QOX2r(xNm>ejx{wVqrd# zLeen5^=??JtG363^8fOo1r1DIzc=^cx3%)U1Lb?y%5&3SUmYxEr}upHQFf$!_mdNQ zKmGR1=%w=Mfl_v9cXngsVBh%Av5SX4{b(5b`nUm{d;EtF^;JesPF+3p@x|JSt4DU% zu3kF);Rhe}?`Lk)tJ&`dvv0F~*B&~F@BN${qu4c#Y zuIyBgO??sdakqUGxzdKY>&wJx!??4Mxz_MUlBLBQYWQl~^MChu2MU|S@!d~xBjxr6 z*ux@-L4pJRr+)$y>Ie?_*K)!6_J*bsp`rnv)b&<#X1{@A!__0~7@N_&E`%EN4^5ou zHQ%$KRg<{lJU0sCIsRz60XfZnUv7yYN1>DcPrUd_n-H~ov+YiNSWx7iFUg z0(Q#ZDM&#s3C+Grt-#Gd*<&Cgftm#=0u>&^&8JU-nZD9&{|SjFwqoOI@A>m!!Rf9a z$p?Z@U?y4dDu8bEq|pEbO(5WhE&&4wWXKmW3gQd{1q+U0-oa;NCbX<{Cb{Q4mw^L? zYA{M*zCasUkZxbs7>?9DLxg#!)#)e@TY8BJ({QaS5R2nTr1d;4x!c1lF=8g9vZIe$ z07vbxO^O&0Ujl+8G`J202=y?Ab-6#DJL)l2NXW6rV@DEAxS;y)LsP9hQpl3>X%Ymv z=|R!V)J9xU5`AKq7K|_g!hz;?B#vjrq$85a<55G-2Z0S>-x%y)Vv&e0pB_^;i0z@u zOQ9cc5ekN!1;*8uNb8zB^^d=1`oa*orf$KB0&as_dpFjaNGHQH6k+TVz=H`}h9_c6 zxa)H3sbp%##Y7CbuOq>VUL;}7B}`HYlnYb$+l0nJyTZ?M3*a~Eia(m8y2`RVe#%5lLt(W{gikO5P{FlXH+8A|8h5qkzEp0FE1=d^c)-{;lQA$_ z+fbIR>KQ&TOFM~=@f|&TBb~|?nWZS9DlKJro{Oq?sNhe-YWvRb`;GgAssvDQFpdL@ zTmm=9>T<$_oLN}8^b7@r;!Koy?+snsc*FQ{Rjdf1nizU3Rbo^IEPu%v5Eb~;Tl}%0 z6rKxExQJI8!{|XS@WLu}E3{)-g`wJ->?tozs(jyQ@KU)=-o~ODmG$R6@Omw{Rn1e0 z_$#?&7?i96fp>C26-uEax+P7Xqaz?Vha|J(B>sdcFZDtX&EG-Nb+YEt)vU~ATu zL+dLPMa9_z9gKL@4NswR+h@gzKz7EwOjC$Vn6SHa!xoMp=DsSF#%+>WwnmEcERJQR z0xG_`&f;Whtq}Z!Wfy%(VTQC2U(iGGPi8zLlD;%sn!9`I1|sJtKhM4`&rX-`-krU6 z3m?Coy(*u-8qJPgIhc)S-yHign>kv({mqF3mqril{h*ZH&5oSPcAuGoEqv(6K}5ap z>UoieSRuiA&`%00!UkbH;*N)9{;26UM}5j zZP1HPo7S6K@{mGW84G-h{A?Q5%>)zbZKM+vnl`(j%4N;-9xu^z%~p{2caWsHg>5L& z#WhA-Uz6v0O*4!MpQZaB$cvaIq0zjTPC6hm4d_Lw;&DN>8-M zZ0XP(c-bko;Ba)DeJ7@J9x-AK*li6Q(;|%zbm>~8MR=zoo9*dbBH^>xo{XTf0f>99~KhR7vK(KO1ftQ#1KW4?X}Khdw?Kmkd(?U-ES|FSGDhY zeS=>91R^7Sj-hj{Y1EI17}DiDyTP*RM!6IOER)Q>teCD{Iq8Ud0s5|xr|!Xm#~6CV zbqllUwg%6Ne3x-0VZ}cOM51-*rlo}jP)+_NAn~Bu$wIy~SE5C4_~jtO83{(A)1;BG z4hB=WzVnOCp5RO&Bia(+QdRkv$DmM|M(Vjf`U_K=N83#%Q~JwMm_uW+f4}Gw)M-+c zUFHo=oUJ6L;g`dbP&+IVoT&H}gU4`G4U*$>l(2S9lL4Xsi{lO%!BvqxH{)}hc)Mu$K@*S})@1QnA%Kr#@ z@|)|N=+Do6b{TPZl@mkHX`F?MK|7Fr`9LN^ZKSg2p+4+!W`*&I~2=%nnbII zgO|!v8y;fj|6WqJa-3jvDxLE=K34|^vH#F`zRYCqHeaTwr3V?|0-&FsxwhcNd(NFa z$rptue(q0_44?Mhz4c^+_STM5n|UJJjd`9ATmoH5%18>F=jS zYtnkE!`tZ+L)$;D-b^%bA1<#b|14^0_pW>Cp{DG$e-a+v9h9F{ZR!q!$y^GxR55qe z_vge$BL06Rpb#rRvnI0REd2tS(GKwJB)Q+s34zN*U&k`xVcU^q;=QuWnW4&qT;>D3 zxuOq$62^(08>zNe?5J17q-Pq(+GA5T7F z^4w|wqv=l=5&z@+8oI-hGIh*^O|-Zne?}-C*l9JlfiW>ZWAB24u8Z=gqyjPs*#xRC z{)}T~uS~_*(J5|%|373m=hWxfbatS0vvT3;mD2Q?a~Drs-j&TBy>eg{p@KIC@p~M< zWA^){Jv)iNNAY{Xe$V0W41N#qLR()R8Mu1(!ih^ryfl0An_b!6PcI*sL~G~K(s{IW z9<9n>ent!Oi<);ooz!xCK91iZ{PyGbu>Bs|m5ucXT1=I*eBj&KPqJrZA%~09r8iqh z(zPj@CjW67-qFA9=)?Su9CnG+$`q?YF`+gH_lVlPq6+DVjgR73YXc7HtB=phbw@HTcaZy2PY7KDHY1x2qDLh>NoA;VB60Rd|xpJaN1 z#ih#9(h|3~wXuqeo?uVV=B~&!T=Vb=X^;c5%^)EPzvJd_u=C_QHm|my@(9Ca ztEsVi9YtVbr2$0O18H56Zs-wr;9~BD``d6(ROMfUa^o|1cojede|JDZ7q=9v(VfMk z*`X}1Rn^9{ndD7JE9S!N*3c_yQ2zxA3lWjYn9MR`_wz7zlW7zawlm66Y+|84rx)&O zFNClYrvuu23_Bt3<4g$RV@w)f>$AY_Ewoh0M|*$?t^~}?>zKdQClWL$@hvueXqT6~ z--ngSUxZvHdloS$62$_%Z!|LOM1qRhdfqj_^KKqCRERtTv>L8zJD7FsR29Myp(5FM zy^a6&&;LoC1@9JvXss0@5iupNi$O$1pQ=a>)t=FT)IveYMB~*^5!kNs5kU9hPgOJD9Kk^o4_g`_ArO-3dI4aqS$FUk43f;Tz-Nx5Y zxslTE_D+0NIx%!`GQ8Z5S?ueajX zhf>T7g7|{U;!NYk&DQ3F`Wh~CSL^g@Wu|g-djnz@mwCHY7qpQ_*!@rR1v@=N+ID|_ zdXQoJkw|!GD|DEe=%H@0$aWY7fn#fkZP{MK=~wvZK=?dh#aQwhcoKtuMeHraScYlK zP~u_0V99>Zh`@#wik37u7$U8HEv0jNv}+jvp;tee6(kCd395 zy+lBjuY$fQebw8Kh6ws83lOXhB5Xbe)5eyxHbIZEge{3FR2b$FOy@aMs(C8?jR zDdg&*!te-JnYgZpT9w$u~_WWW83UXHdXsq z5pu@xPH6ay2^Z#OGh*eu#6-nEDJD#-^q}Ynxt__$QzwS`OhT|_y%VPHJVXmcn8VzF zsN~&zN>@rb`RCHFt@eE8GA$jSh22wZ5HEN~rg6BQ0qYL>bsBVs3w!0N@1V^{D5vNk zNnB{U`wM;J2~K$;@^xc)$@^LIM9kt2Nl$!8EUoU|!`*`Ye``yFHuV%8d1)Ef5@@u{F# zW`Oozw8Tv(S8Wb*;#qwYrePkf3tYBhHbM0O$L$0yC%jl%4zTe9sF#0U*Rv*5P@9wt zN>0IG;8|I@?VSf{;iT|~ zh(VQuz!F3WXmQ^yq>YC_%fQm%g$e1Tb)6KR^1@hfOfnuO);DT(KXS9wj)dxQIr9$@ zFe^-FiKYi426H$eyi80XXP_icA+hf!ipH*fbtB|4tPUU_PF#Yb;e!5%HRN%r4e|tvJUg&hXXOM;zTPxv zD6j_8<()Z!v@7gDBlbJFfXfKy0G*4F%RDiEyaFX~aozG=2n;8FV^Fw!`}vluPvQiYr^vBigek;Hcqe|a#1P6Sr)OFDp|y)$9SCH9?zfn-PWRF+s`_l`&nr##43bx6Jl6;dy9NU7(G+iPgG29y#c>Vt5Z^SVZBkPo3a~Ox zXo10*A-b}UtKj1hAbq2`2#-AvU`XMZ)v+^X79M802-emf&+^(7f{|rsxEG);2K9UmOWc+OzBvYn17y7W;tn+c^{i?-0s{#6sgPu#)#!;xMPn1aavx#L1tOQg6fKfB1Lu+2a)Eejz%&%Q&@Q*!>g09Vja>N6Y??fA+ z(U9vz=2ed-q~{W%Po-lXLt(hC@)w%R7J$AMT6To=3Ro^uNLp1I?_3R}4LSv280nHT z@ZN_sgrw{U64D-a5(;OKolY}dXs_9one9M*TCLX{hca(A&#&pI$2<$-d3=8UV|Uns9{ zBBRz;dN1YTVAJxs1#R3{mWLMVJv*JeF0Em9dcMJT3h?g)K4~UGPp!Z*sE3)eal9__ zu(O9)BR`J3TkAGtKAmejy0i-X7KLG{F=1zcc=TzUQ;_aEv6E1*2QLwvpinPr>CU#C z<-)Dy_c)NN7cm#w?KUsqz+OFyJq72<_G2VdsV;CEss_kbke_f<{&efaN^5~)Q#c^2 zH`l-)$vbesGwXC*J{s)S6iZvd*pSRC6c1cN&4nkd!v-XB4I*6FQB>h-UNnvy%|$!$ zK6jzt)Jy~t-_A-z>jfhbO_(=_I}TVG^c0D8_g*$)Y_`)p1Q4|U-q<>{@}!`mafnyG z5&sLDhJb|813i5>l_edjMSNC1L!!!ERd5gjvypvtn#$wyaEY$fGubp^@ z@O?+4(8`NVh_*XTLeVBV&NN%moK=ODA>0v#DG5?R;{L$Efs^_y8{P*|NVqyoB(D_= zrzn037E&mQ3&b|LA#H+PM&tXzIVe?A%IzeEMr?(tM261q>||Ca^<0 zNy*M;puSShY9s=i-l3sf*`%qSX=*6DeKdviGJ?XLRYtF=`cgH~7)@a*9%u=$hk13$ zn{TT7)F+L;fi{O2BxlVfE7O*eA$O zA`M;qC@qMp=6KQf36WU6WV0)JM)jQp#gP+uQnH+GAZdc%Tsx3Nuy3ayNDl=KL7K_y z2%;an?~an@q~FnzEa1GAt`KT;(-!1qH5BEGkGK0%@k?HJ)EXSx z-}HuGQf~;e@J^b8P}YvRgSQ{G2YIri{t)Vj20`^#>rmqGTa?f_9fAu3@wlOUPLW8B z@GioL}$oE zk#8|CX#*;El(p`X(z)!82zw`Z@bZZZD+P`Ejr*{okqj^Yn~OmNEWMo&MC*AGh}^oG zn@sF-vs*=QEwOB3IKRursx;(b77V}Y8C`+SEO<8AJB<%XD;iA^pG8hkG@VhV8p{#q zKT043&H^&BVMX1~ZyOO&SpZ1Uj!q*X5OBe$8Dd+8CI@@1$@I*WGE|4HSCHmJiHnY0IQ@) zC81R7*hX^!Nbwk9HhUrA?-ax=;|4=P{!QVaB68qI;~s7C*$Z6_@TX~kVCZuoY||_H z`@Cc>SnpD)xVI@#kK^q1xb2+I=oi~^&^p+HxDuWV?s69YOyfnzabc}!CO!*r5<06s z;D)JJHmtjn6Vk?NA$==N1Sd!lPgIu-7co-O9>h6^gDQ%FPGl0`C!Q)ln^Fiu~pCPmGvV-^D$rR7Zt z!T|FMP>MIxfgE)Lj`AyC8hIi_jt0((P){;#`dx~?VYDfrdQjPZx`KF|I4kzuPto9{ z!GnOpZf6awyr5b?N0d*5nh83!5V=!l=e{BWE@NT+gmzqYD`eqWfY;+;?v@FFq}j<; z6G#;|y-#DO;JJcW1Z~IqlcG5+NgQm8S0tJ%vLbh3qg$NeS;jFy#3)iZ5IE@JsINV% zzi5k&h7FM)ka`OnaySMBO$5M0M{t)v0vp#_Z5(LyP%A=1b*9F)9!d)!0k|5`6Z&VW zU1~~c3@DqY^1-UC6~T{@Tnp+&)O$~nCNw0cmHe;VtJnNtdgdAZ&oo|`hidPn5S zqUMl_$+ALzro56lh4Y&)HtOrmW#cpGPpCQcDC!_Ku%t?d z-h8L;W&cY-eoaoa3=CBU24B7ElL|SpPL>cPt*TO~BVTlx8uzhZVDnT@i|L@LW`E~* z6@;5-g!D-L{B_qaSA>QE<1r5MQDaANGJ=UJ3(`U1nCv_Y>CG&S5DP5F$sGi&>a~t8 zgd&t9c{iA3!pY8Zz-X@wo7SVjG)E&|1J zH6G6oHM|>iueH!gj~V75xH^f4bTx zTz)n?Cvkp?U+@FcoT&)si>tSP8!?Vz6dcq30Di5`Je8PHz@(Aa`L?Ld3q*yK84u+{b>Q~Q&dTgTE9$Bqu6q_O$4+X`nnw3s%($sC9Wa_3*ss<-Y7q)e_*Kw3b zI6rYo^~+T;@$&fzDggZF?FJOM6<+_ejuW>lqT4-&h9FE$JLPp>jmi?5xoPL#ao3z3 zv%>9BxNKT(GGkYuqc)DsE%S08`0rL!+cY3VtHT9;IOK!#b<*~ZO~+I2Y!)#|uxtfB z5v?v9b565+>@ngnRwavmF$d-J57&bQ-uTj&EL;Hr{Qx3gFj5!4vXCe&$2t{m z^hNEZGJQils{mVi)2B$PGz}%hQb2J?_FPRLOok2u{D)Qy*gGz!z;Se(MB~-s($bPv zA$x@vs_OlIC*3MRRjdpc`a*N%VKOIEi0qJzOhgy^2f3)Ggk(kv#P?V#T%i&oZpM$$ ziAS8F)dzGP0RnTIzs>;4XHsN6Jjq);>W>uN812&xuyjH*aiv>ti^)0)8d2n2%oRmx z=rBHv1gs%YdEQOuqO%fSn@ICSwJ4H0bYaJmu&}ru!D?E|P04ma`c1?Isc$1?DVSEA zo&(JyB?mF<+=A*F&Yo^;HJ9tqn|Z?(wDUi2%W+X_5XF^D#B36NBK$K4Hb<0BpGB#3gXu=;WjZALjz_r4xu^yNl}fLNh^Z*V4;{BrqixefTb{}J-1;<0??bL z#6$oxv`9~zQeTrccCscPytOqM0Wod0Vi!+UPMvZE7ISsH@*v!SmE7mWtE5OOxEVUZ zk1Ow7QxDWM3&yXbJ7>D0Zo&Hfb(yZNIiyFlF%x37k`K9)%p3+naz&g7HOMHfqTZv0 zVhKJ2b~?P5@QdqI5tD72b64eDyi!C!uk>P6Vx8%-wpx4zeWyokA4u747V$Iq7u-Rp zo@)$N=TkNy+|Tb`I;^5v@bf!EaEnt_M z5C+&?cyKFrNOeQ6YAO&TlvF75)Np3(?DSkLshnU zfWT@P4Arg&*J`S%ZoSahbLi(VP5|+yp7QL>o->!w-e`9EXepb>_912I zsS2AM%69KBWfw+E+5U^4@p|03?DAlC>QpHkIbF*3T|80BhKIAu!`ackQg#Ww4rPM_ zrR>b{Qufuj{{4MFMmC0r_r54)1IO@tq?CQTEBm4}cV~JWFx*xczTI>B0){e_okE$@ z+3tO%Yz9O67R_GFYH0opAmZQOpOB9ivrD_OtEIV_-`%-{R_3&o+k1v4vi@w}A&dY( z973IgXs?#-{=Af3&d#tMwsA5W$%YBU?DT=L0|5L^`R?4kS>%PkvuF5Ap!pQaA3uPx zqxSB-_zS#zjR_e9T%3kez}NI)fH#ca-;V?0!R*rc3`ylLmadepe|@2J;lhbN%;f3p zv&xC`$r5T;0mn&Tc`CbCzIU}e_tohu+1>KJYxp#i-TD2|DK<1)o;!vI7~Hkey}7wt z_dYGn?knBBcd#_~?H8r5XAci%XUli*4PQ9W4`h9I@Ce)PyL39kq-Y0cvVF%7ocQe1 z4*>QxAfsz{M=qYuFwGTI96z|bgjD-y_V=Iu0P|EE>c23QjSiNxLr1TCa0X;Bnun{u zM;hB)X4!v2dWXgY)YT`g^~T6%dwXlEwJ}nAy8UQ)8JQ9rcn%Nl$_O4vCfc?7#%is# zxjM4ae$rT58y>4&sEv)RH6M+%H+4y$^F1y z0998Tn`{ApypU&l9cXN9uP>rkq$%-t-UH6EE`Pts%hDT*3{Ca-mOcD-3n_{1wpe^d zFe8Dt!ZQpb*?R#c$o&bRYP>5{erKE#fl+awh4&*YSQft)oPaIGbW-!giRGW2t^69K3~;%FvlM}rlQ z)<&kGH)ue5MT{WkIXI5!RK<=ogKf~X0@l{xFxmLyL#e^dLaJI%nyUy3GLkkv@9riI zv7}E1z5--&VNmSV$_;E%-jwgvffx80zH?_7DQa)snpj_-z&$_C3RrKW^~`F_%tE8nJ_(}838Er&cB?B2p zGhNw*7Zk6il#C7@BNtP&2f3GcyijC-)Z}V^LK2k#e6xbgVBSlP36X7cl;ajV|_#E;9hfGSLx(?b#7aM_?a!uUaiLs?_rE0jo zi5FYVGwCmcVH^jgO{}Yv&0O-j25U)2*uu?MixZNf9Ybhu#erjL;15MW$jdMvh0=S~en0pH@G_X2%g4b9=a2R-ValOgXQx@acARdL1 zaDA%-Z=6P0ku22qf_yedcVVbjI&=y~LfPYUN~#UwGZd1(xWzPi_x?0)i<2AV;C)6| z7-J!)`JHL;VUM+&tFRF@Ohco^5J15d&fpJlNk+^_FeH#mTNqpjQ(K3yooX**iU)0VLcL}hE6T8xO-7}Kx_~)Tg2<*)o5Jr&_s~ov4uz0!lR^xE^s*zp@mdtn??{NhEX7C5^Z&?d84!h zzh^I9K7YCY<>S>?M6|F-U59J}1A2od&S?{mI+`e~h5_#Y-N-6)eFl^ijD_~9ucEN7 z{6Sc#0H3&j)xX|e?I)oa<#_vfMq*<|*>phxhA9Q$WKD)3hPEJtqp@`} zwgFg`GQLb#%h@m12SDD$G^&$3^a3Y#v=cZH=x*SA9e^e3x`1;o2aa(Uu36E+S6awd z2SyFX4AFuX#?OvJ9jeL$goV`CpF&SZme{e{=wRhEUJup;fn<%idi4MPyW=O}HO>xw zdKli-f0NB-qhDs$jf_?tve>nclpxM+wdKq_;~NYKMc<9|M-J)w)>y|hhxXeS^t&u$37m$ z_py)R2;X!3qhoAj&um}z?Qr(VC!c0}_wL=FeZF^}{Qhp=zEej|eZ)==@2-Bd2Y;*h zZ|)lZpWT%qB6s5)eRH)9H|_b_cyQC=(IWBum26i(sAeL zISqTffo!+D(CSZcCsyFUdji9xR;kP(69pu8yP>B>CjT&hYxcYQ2t{0D6sJfSgeTXV zYbcDpl*%TQam2KelsA81o_{93mykVb>tcn1ig3LIzOK?TK~%F`Fu>NnzJFu5z4d|w zgD_o0r((U}gpK9@c`OUd;ty|6U!S^rU-BF`YP?yrGCzA`wz~1G(frHc1P=Vj&ZLIX zt!`jV$&Cb+_R9As&W?^=I>-JWH=i?T6%nNjMkfBCr?aWG)&^b2xE=t3!e9t;P_Olj zS8w6Qqh$$kTyLyD!dnLSRv>%P!y;DFqPW?Ua*JAS5%IC%DzgDz7dnBpWM}EQlHI`# zKG}M`u3ayRaX`;VZbHMIEaX^q z%kKXe$uFN_>ehMr7@pyNQ(z3C>=MF^N9=7HDzl<*;J}}?6_o-6m0j^tp%oM~`1FJ_M>G$H>yQXBJ*i{I`Vo)+tTfOg z2msRtIs-izmcUhegAyPy-plsAQ>E5->>wG1w-*@vWS9fWj|D}`Lrr;M0O6D-lgr_h z0HXI-G=SW0k$PyLhTEbb?dUlta6yRqp?e}_h?sxtcKUIp{j{;%eB5jx(>aE-QQ`hlC{5#+sFgrSB4QmVwcY7Tn@H#|WCcr+DhTxbUj4P?}thoYX+k%x1L$%5udC39z3fKYo ziZ#f-6rL??UXkCdVcP|*;LPsWC~q;rJ`2z(Va@`#l*2BMq5)bIXUK0gX}0M*X>7<{ zv~9>6tNF7@^*%g~fLn8#kF7BQk!%-7w~|J*Nu1O}A5w3Sq>-CC zD)G!W&-)bR(Bj}wVfy@_rp;O;E-E52skbpU&!KGq?LgRDaBX7P+Z#Mtu)5Lw3+04S zIc(pZ$yx}S`ke6c_N4K0YCqA+AaBY?=m!SSG5!T2%0v8?hZ+&E#;f;|~oyqx2aJ8za`5KFYGIEbXP_Ezhua#0Z+l=mP!;0wfnwGLw7 zF?SOhByS#`1>r$S4i^QXgaQU6gNrzCl^Mk%z(!{!Aj+-+?uH$(Fd9=xHqc1`*rf~s zKcTJKVl@bqSrt1kUkz2lvrzCF9%JbK)2;Ifo%zCqrL_tqIZ>q1XlnGJ5yhU7>1hCg zfg(EmG_f72Ga$Rb4(G|k`9Dt}aq*LPkpssHe1u~?etyhuw#LKdC(SkI4^S7E!Ktum z;fBseqamj;wKk4snT$353QB~&kSB1(Hm`eq0nlOV%QEjNnTteF6Tp3u(ZZu1+Ir?s z=0w2|X%^-XlbtFMHs8J?hIn$M%fve^wtXh`N;>JkFxP?nC@pJ+*?twh3G&)yFe)kO zhYs|{jG8^g`#)^NQ-}ca0kSw$?X7J;kS?`V*CJ5OKRV!6#2@!)*k2c0?mpmTO;ozl zzq=VKUv_^Dk4^Bwkg>q3r98^>fG8KBs+ukeLPqo)_Rb)!ow>*fb|EQJ9`h?GB?e92 zaTj>R(!Z9N0eJo<2xbp-^yMy}{aYh;D4uNL{taGXZ zKm&9R_MqXRK~oOy`5A1Pu|nc?*JIJ>Pt^P=Mt)QWZftX`-0tuR=<8>_zOZeQxTtNQ zVb9gS$8ow3Gyt@~#(4FImQ{z2Ie6kD=_5}jl)E_LD8@#f#R$IxK1Bez`m8!~GRK?D zzO{wSSLA&QMj#y-AE1BNA3fT97->!DPmj$G2VD)3EavcmlrsYs6QCJgFbf17N9Q)F zbkhL{OUR_xluH$emvJ7m< zHJKcqw5esRSCJ;FF42yTbaBGMAZr74;^gw$HWeB4YSddK z6wP~x*Ex2ErXNq_X5utm1{f@QNiKi14#}F3EJQezbpWU34i!|8a0TO{Y;3$hA6E9k z+MciPCZ;aOp4cWR$76uL=92el1^^D zR@8wwREG>YnN$>Rqm4Sxk?AZVBJ=_|eRFoU&m^_6C2L@5*nDAEub>R>)x{-@Dw!Za z{i%1f1 zMCm3LV4z<-uiMf69Mc7?HcH-31SM4j5cBIoVNo>_iBX`}ASPz&`7+`tzzQE~ei0jl z5(iC5(Q(?Y*1Q>ekI3kp>?9|JOcZ5mg1aF6S6a)W=qjI9d?Cur0h84%(7iE8k$0t2 z)JrqciFtS3s8Z#^(m8}0XPp=PX|gJuHKtH?(KHmGpfCkpL!aA(gN6M~Xd8kUp~X8m zNZ*9+4eUTSUl6aPm}2dRZlQ}l6nBFzbG;Zo7QoP@g;^zXIGGt8lq9YZJsVdn%H7Xe z%j*96G#=49Db{~9t%suWbOEbELz1cJ5iTZIwiagrZxf~2wI)UHd+1H3N(J8S5CZJ#9+QGIC%n~Mh@v*TPdH3P?RJ4vQmvSkSMI?VZ65R5YZe9vB*Pr z4=P$1bts!2Fs~yFMbaq%fKGLJh;qAb{0#jhPt{`)n@o_8b2!|=QJxn|yp!S^I#O`a&9;q+Z9;FUhd-SB!V(HLiBbczEt>1M++h0zm zftQl;NK56n7A9qn0DFn>wAGotnW1_V!Kz#_j8}!XiSX&vdo00%>do}HFxy5`SE~kW zdQyCZ9=nsv8iUBkrq`neny`IfqD&72Nq~mD*J#M51oyZ+3?Zd14GD_71A1dXO69gz z<`~4&hGPgZ+7B`3As*I35QYUGZXY0q5pHHAHIcpN^-6seX}jQFk3KqX_rRx}M8Sa~ zB;*K$Df+CqG(lJ_qrnHdk*#6Z#P;Oos_t5v|1;iBp{x~tBS4$Pn#mwGtCS&%f3%Jg zK@JV#Xf}q)fC$6{>4tpYsrTc-%Xd;}|z3-ju`83J5voRt}{_B2vLo@BkboZkzyB z2vD|4PwH)3in95W)+SnJ#l6%`rW%E?f{#59e@zu>G@?JX$Go)`A<3JKs$-22!wN`^ z4N(u}UqU;D(~8*amVItA6cZP(KKz#z$zV1!igZ%h$wT}0eU{xmzUS2GY~mzSh27lK zpWWGgBD+$)b8q(BJ7eW5N3xmS{n@ed?7i7zb5}16BjMGpFU#YXv)f-CKY!w4|8#bs zeDBWHiR!=?<*arTIjoMBZIf2Toi5+Ga01D@=57s-0SlA&j`H8n?v=9H zi$|*$$|y2-;LO2qarz4ev!3E2FOxG|_>dm8T6x!WTWqlBDXztaZ=K4ioqzWqpfYxx z=ej`Q(m;-bzwYx~IE;ksnLb_&30nsnbPg>|`l%s!8Z_TXcoMdjL)MX-`7LMRSKNV` z2Z~I%RUxExZjdCBVSY0>+$|)h%GQ_y4gZ} zvvjb@HlT4J#6Gnb9V9*b(m5>Wz9HYvLWgZ;gKCFugo)57>?MDj*tB{QTy`M{N^Lud zF~*^HIq%g@3|UPtW)Ohyy!vpru$=1I8|7=qvaj!czAHPu!}=%?@xqV1QdB|Hb8-LU z|J!YW{7oEq^pkx%9VN`OB%U%P<>yZnFdWX*SVZ43c!p)}%Uw(9yKn)L1Z~zU$PKr84$j0FtZFPBEx9v?!6=7mO zwur+A$^wRr*9=LV_E6{vnhrx~VmskhOEN8^Zz6`xkTGGq3>*qp0-o7|RRb|J0W}o` zWoqNpxVe$c`?SVUs;Q$GG7UtnB^rm&l}@y&5B9iU^Ng|rp2kM)yd=KJZb`}bL6h{qV2DQ_Tkrt zn59Z7R&jt$^zt|}h8o1s*vL}T8=iNxVHzf>&&l0t>Bc2aRSnB|c^|$tp_GN#2#NTK zI7z5EKuc`+EUB!6R6;6D9QNkP0n7wZiliP*h6?IdCHU$lxY^S zkzr|r>E(tR;PQxw32lZ&q06L)p;%8&L-AdrtVp+^onDnffzu;A z#{KN3oA<`%^p#naM(yr~;Fv_#5IuAqvinHjEH2OmWS-m#Z(eS# z?v$kdetniWK%(v#>hcS<=iIU*&($h9umNYuNpGile+oLn@#>{ zOGCvdPWCQu;i4`h7GF{}Pxdr4uV;waK6z+e&imjr=?@64Cs9Ka1a0}02~AK&#c8zm z^vyF_6A-4t&^<;DMP%a#tbQ0d3*juAQbrG#){n4GS2~%4 z&ef|A)yZ=ZE}lwh?(V^T$9I3e|0r^u-#AdZ_3_^8hq5nDW%s`M3~nCeM8EqHyd|F> z$}U#2z8hns6WOIBwVP$6Gta(6n)c&k*~sw44>CA*ravjqov2g~;^iqgIgp#Li<3i% zM(wKyKcemC)C{-9f9~qn_?s}>x)@-y8YbLfeA)B2GrSV#h$!OZWIvAKrQjsnZ&+W! zeNQH%Qr(nK@l&QH;y$yLkfj@Ur#G4I zs4W?Oc-f}#Q$Jyw-#*jx)(kO(H7ZllLnI*fO2VW;<+|tp0ReY1@%jSfiIT1}F zl_cshGYVoeL1Ue?i)-I7WVGAaTStKaYT&|s_%L+KkzwTa z*8YF?-t4)~Bg+%3Pl3VEENbCSg4+jhxfdjGL2%K+O@c^JghYZ6NvXOUWKke+N!}KS z%f!%F@Bne`4igV7s-S~F_yw4!fs9gxjuq#{cj-!Kt;)4BkmJm&yXTV1P$q_a)Sq4 za-+LDan7&dB%w#rsdSa1PKC$h+Om@ChJlS?f{{H*CzaKX--~O`#kOzX@@^x&La}Zb zFkDC2Kd-&#oZh71Ue{e&Aalq%Cgg!;Hg(&XM~vNbHh_k@zPFtLnZU(z;TrNh<1Zw5 z(XQx|N6XDj(IJ%Hg!=~m7iQ1pa$YG1o?Mz%iIr?c_jbRVOdN{}vyo6Lr$^|kfN8W` zkh|9~*cIN+wl2lCf(vL2!5>$wL_VWax-Gjj97vUZJX}oau@tjOk4WEWO@hfk!4Far@^uvUKcLY7`kYRL?4`Pceh zys^wgX9u|gNZ>y%gW6Wof+%-cjVO0nfea+dT{YToLGqGkltVI{zOt7Ak9^5(JTgq* znO+!Ist|J}8DCprb9-$;SVECrE})B7(+w47C$fpa>Jxs`jKJ}_I8U9T$IGf#Y)E<{ z5pnrt>qZyC8t9iYd>l8m;90xeh0<{WBWgxaC0ryUKWa351F1R^ydaDL%Cs+m_)?(6 z(+(TP3jxfD$_*SOd;KT)OyHH~S@;s>S+n^<4}}1^BvOPDMyu1Crmr-bH0mygHD)O) zBEg1PSjD{>Z+yip#sU(_XIIyHzd<^&W@8-b)~!p@X7%2gf|krR-hs5&Gh<{tMk87j zB5*goBB^ymLgGq@9nQ_+^o<}_hX^|%4UFt~HP_%FC;504>HK;vM3&rQjM}DB?g$pl zvJtrf+`e1A-6*-^r!a8g&Ji=+4 z5vj@*>T&2+~zeWi-tbW(y|2C0T1 zEjMk=3xj1|5m1L;sfQFm;p_#Te}F$B=7F-!YLcezRLbw%iix;h6x8(a@q@7|(gQ*s z-5G&3NpBN!Ae7CpL@I7!(Ci`%NS#c+X*U83q-cDDO7=+4XRzdNqf0slYx*af@h8M^ zd`E+`pv%dDWGMxaVoj}lOq0wUL2|l~^o`XDO>y`YCKu z92|GrPo{r--dt@o8uR)6wfn30S4JB5?@v5H0j#N}OaF$(XJpGof+^@)GE^ZUT^pta zMZyEH0*zKlPCsr(F2+bdJ`25Ezd7{O;<_=b^DBjP(=fBBG`> zpH{D!?T7RaFSUq3!uE|9tfwVT(0md-okk?A2BmuXl?+E8R*s^sO~@m; zB-mtdG1&e!7Zew=vN@bvZnRKdXA?{1RX5lux4yY~Z)Q%G%WH3b!IZa^&1SmKlf7!r zT<$aBZGZQ_OJLW*ft#~Cwr}6Q=kW0l_U_)jXXxuaSKrAF41Dqa=ezN8>df}t+0mof zvE5l~2mzwmjnQmwS2jA5eKh#>zQIrSWpf9z+5OqfsiACoXExc&Ch-33huJnl%o}@m z@7=p^=;nbNL$ikt%r{;i#ZU*0^GA3u-RZ?C+Q zjqN-)IEPngr?OLn9}Mo@v3GFlVs?5u8y|ds@c7{Dxlgk*GuiHJ_?_%v#fQ;VLnq^= zX5ZF*vDo`z{9NmF>#Stj$6peT`Cos4=TTP|kf9bO(Ai2MS}O=6TuZXAOXSu<@8!xO zBeT3RUspwQcSW&M(nh{^nHTU!3HlM|feQj5*E{ym zTHavAweCZn-c@K?MZTd9t5!NRLvcI5bNwngHsqIQu75<428O~mT-HnN4Go@!PL?snUhT@ca&D{3RjFxHScsY?(<_k{ zN}sU~K%n&v-1}#>5+D!x^3ojLy|e4`J_G8e`R=5a99A=?s?~g7QZh^ztj|&=seBF3 z=#Lp+s|(@iq-a6oc}ng`eOvh3=cIKDID}~FmK5s)mw1IY;!yijqh5+c zDDoA=79pi5we;79;Ka&dRAwlulHtD`6qPB2Nm_)x1)7lq^!%^h&Gzoj4j(_s6A~|c zUl_%6=Xl8GBV4&SmTmj+?2#iU@Z|T{$@mRKr(nnj@Np~WvcKC9Hjsr`CyYSh*H+Yvp}+#vgr*tJU~!Z z|7IQeX6-)UQs*(A&w=)4!-bv$p<@DPO#-ubAveYBLZ1KAe_VL9_)q^xX}d6g_L(xV z$`C<0asf1$-3%Kbxb}~@=*BVW#kdiW=}1+B=AjZSE+A%^DbOp*8k$swga%<0cZE0d zJ;F7}en12^66`$dD~1h0K8o=kDqjrBn|zaiF;4n8R*%t*I^RBLSnSC}1*LJ#d~a-) zkGv#6Qhpqo2b~!+#3n}=o5+aQL_F-SVp&}lDSt{FaM)tyuXVser%I)AN6$4Y$F7Rv z7>t`GU^GE6HF!i1`;3W*d9l>U=M7myY9pBqNs!?zvy(iS_uN{8js`H1fL)Cfqz-JD3bawbPU7It~ij zofhy)DGbv%*Gt`#*+Ri1ID`rpN0K}QVtcMJ_WQ90CIK^>)J@LeBJF4904uegaqAg zIhR(UdT}LSlPstcmCXbLS*jnzZa}SJW)OB0Pe>qKo0$k46xEbCd?W#reDJf1X@^{i5J4UMS9b!ArKRcS4<8a5)kw}ro8|2gRD_mpr!XuVKv_56 z+zv^1KtAKTfoA2v!_?x{;pvkoKy>mzWR{q91k?K=w@pnr}OCP2v1T9iN22ZwhXfG@VrTmKT6$}I|IVMz8=_<+=jAQ_#eKkD@wL+ z4uJC!)Z5?uYwdn93?$#`5M-YdEMet+JGfG?5#HWhJT$L=afRWog=k2jsaUR#+rp~H zs)gcMGo5F#a{5K5`tgnD^@y{B@l(uXMtBmHJrKUEE z^Jq?!nJOy;Bh!p4wD6kM$BknOHB^>+kz;hNem`o1MzFwDw@%vFT}|PTj5;EhmZBZ)5F3O+(k*|Dw~kPc=)Qe5tO!eGCM!A)Ano1riV* z0m+!lU73cdPQI$VzST1`2KGix3tW$*^XodU=>_D)eNx3MWc!FtCr6IPyFq+ndx=%9 z;n68(JRdH!F!QK{MHw*{w-kmMK$X5A4`s1L`9uN#Y4hR-v@R6H#_1B3+ZVnWh_p6#ksPL?lj!vtkCBAVnwt{P;%7Hd=YNP~N za%Y5~pL-CZ8_cX+DG~M%cmPz!_oSYQJ=gG6EGv zUPNDyJ5TVq7ahrvV}j*bHN;k{H44)MSniU)fe12Zzu0z44t~c~`YW)vhn0O8>flLl z)ps#rDJ)oq@!Wc9)*v+&zZZzA{&Pw_)fz_Q3KdhiTQZtreAPmN5ytkgN_O#EN@OxM zfRBQ=Zyphhe5stewXit(;EK0j~iA&(oHs_}dTtNr2Hzi}% zA4}7f1%Nh(D==WjlQ_@8p;2=vd>j zFXpFCb>e#KwjjrsJ;Zgd@ZtH+1KD>RvGTx9?ZEx}A0fulz z93`+SueSjN?L8KTT?qBcX`%k)byQqN*nQZaVI`>tGEJ!BZxw&ah!yKrQ|A(A)lTEvicum8x8`}%F2>67-FJ`C8}@%i%LB@ z%oY>M+-WcLkYf%@K;&V&-wlPW1bZpEi~{57iW?cT-8H$CL9v#jF?F4z;Xglxge@l1 z4>Zk6nz@<3;S7X00P#ZqNIz`?QUV_(=Ha5k!2KVIbX?W1u8u-uY<_d^|cSUF<6}VPlz=C`>lv3nHl)a zKx_K)u_M`MhqJkfVWe;v+m+oI&W;|)u1;n*&JW&v@8G$!M-JsjhQ{)lk!v@y;lbO} zw;4crV`^@A0NFhK&#O}hj(<9keK9+{?ZV-aeS3%AJ#-N9mD9tA4<6YuapWMQQa(J_ z%v$ficZgpP?nSnVZ2bHzaziwZ?HxZbbm)Ua`;T8bnO)94yL|n~K(_D1v6COPj=qz9 zcIm@I+3jB=Ff`khP?DKu2*{!*Q2gVOKbHX_?^x4#4 zc3~pBn&nwz`?aYrvxC{^6OC=#w;mnZGKhY+?f(S-*>*15gYHk1LS*{Hw0!r=1kF%< zXAhu{QV`^S_EWR+(zdeU5X@ph zl?79AU961Mdqbx<9ekQ1GekH%@Ai6~M;*NOB%upk7+O{lb1&jW3{VMy71C?7?9Ln2 z&~~22Nw`R}SbW}kkD?DPwD=Q-VH zRP|S%F^#vtg0mlav=(tM<4JxJcAnLjCs6=jCE`JlFAn@tUJpWA(T6;ZDNso;06{Uw zz6Lz42rNd2hqhs@HZF}{X*?8E*xaN8a(gCC#z1J1qQ223Dd!J}ru?ZXP}#*Hgv!g-5`Q^hH;e z#C8!KaDd~2+hP|!_(dcrw7<7Ufdy9?|w_Ff3~o8fjvsE zldYV&sxUmD2`S#WefaeI5-=r-2$&@Plo+kCuyc`P_a(kc;Fbsq0t<(H^Xi?O*GEB; zTuvh&=}ZKGg#|oC^ytyp;^Jb?iry;!-S2)k_VVS+u^)f@F?^7ZXY`p_jpec->UAg{ z4-#&Gj{LnrxyMN7KSCS9IO6aW!x+O`4~wIb5uI)2u$Sb`8?ct(;dSOLeS z@*i1aI-f0C4QG}EQn;vqn8GKp=W8$sQ3!Zm?7M){4{@oKXP+=A(p7OQ0dum)i3#KpwzyGXi~@qv zsJV=M?6u1; z5HuTj#KoqApxH?6&7r9%N90Zv_M(hg41xxZgcn)3K(JvI%)3In!D%JxvBM1~pM?VV ziG{YW%JiXVv3Xg#^`VG(8&YD49h~L}vJq{_-3rzb1VWydRbajRpZ@XT*u#JNk3uYE z@xegh3`MOG)RH~nl%mCau|s@4V=B==k04)XWp=43%RMWiK@@m>TCyKbrGVUmSR=Tt ze1>VE9{V^vsqM%C6J=19^e_ith(e18Ws7W{_X*9OHxUOB{hl;jW4gf;tBRE^h>%ui z1+V7>jVmmi9G1|{uxswZqT!XSl30!cmX;Mh{?fyIQA4x0&LXp|Y9Uc{znRi^xsTWK>^ z;=jxLq7slQ*iuDNcUO=tVrclA-WT!B3X+0DuF3%2=khNlbi0gn7|LFMQH}H^(bi$> zqFG_HM{{PVo9^^dxHOvM>W#txnDFy#xl*J{p* zSVT3n5f{dbwK2bWvQ!DxmUJ;8wpv*!XR4kLy=rfz#`v32gbM=hq9Ya<5cd9d|sTbYcg z0e(m#q5!GU?!Z;jdo-4>`f9OGQC#a62f~^Kc2r^-Da0~^=^qb5s2FS^CWK|>{absJ zlNFgfn?G%Bfs?ha;x+L$kPqFldjueI4G&?A1%AcxtVb)4eP%?%_Mx&lk3;r>5c!#_ z2qj>&21@8CCp0>9pdiWGAoG6mH+PK&nSzJh1I!+@=mq2!61yooiP0$r3@x~8|U=LssyQXI0vk)v}G5pK`q~D0tCKlEJ%UatoP+x7C>;TvSz-L7irz;tZt+e|w z!6FIMV=K{L6SV(}MVylgo%k_GxKzZ)>X&Ilz`6Htguo%WtIf70xm^m)!Z0I!MYkPy z*HxE0!WACBqZrf$3KR>9aP`^f32Op6OuV*FgN7P+k{x{CGHa`zetM(G4smQ2V-+K% zE2(J6rS|2mDv{JAN|t077sA7iHZXZ_bdy^7xy?IdEm)f`YSmaq~wiepFD zFej)vPTU#^L~(b7QIx=-9xQ)0gPLR*ioveSRTTlX{9~5$rk`p}|Swx5$6ZVhbw=fD4 zXP3fPreBQ;>cIHd-by{1li*rO6)>Ch}et?zqL zcgth+F~!~-ZyxUE(*f%IS50^373~1)J<@{mTTJ!(qy~|v)M?uR+JTrw^iNzLWK!XK z-Met^Ek1>S;Tw#sL%v~LVhO<0RZvB*xD}w>t_7_?_5T+zrpaX|sX~>M6u?r1LoT(y zL0CXfZ#F6UAxZ%^MB=v=bGo0~GPXEYP!>Eqj13!&QyQqBeO35+?Phka` zxQTvxmxTHT8y9Q?L4AQhE}n7oZdkm4*c|X_VMUrMAE&l2`Z9#<8tt6QJ1&xF4%<}6 z3U0%S(k42i(5YZP-d^EE9mG`+VKMVazY8bDZAFg3SsRyV3A2rvbO^lU+>D`n!R&me za*2k>eZ!i@bH19+=#m*XrQM5PNVqaL-j@Q>BAafGQMY4z^W}H9d}4(@O&b z&9hg(+BR_W=FWjHZ{Iq9dwAfB+am)5Qz! ztA317)$GdP=YzLzUB5Wk96Ue55Y&7)+mr3RGMEkT*t>iC;gikQu8A!}1KI4YBZFW4 z`r_cNFK2I#4bBa3o0=HNzI<=+?BGp6`0C)`^&8U{1;E8@?8D~C&rk0;on1WgcrZJ4 zAj;E%Hffj0~fE~-kSY-7=f$rPiz_9z9mBkpXS$(9y~j^1HrBzG1&E! zfs3a<{c?9BJ9i{IooyTX5P_)MD`BY1Ai4S|(fbUNK{B(6r;tr1R(tDfYu%NJ7G60X zU*uDtD2I`KX#xe3>unkGm!vymyNBxtK{Et>( z91Z{K@@aI5D{3$qs?3?4I+)U@2;gG5mEhHzz5lCS+0c$`Y;5dQcHqFlY{aJ*k*a;g zR>aFMx2o02{F}e@@ToWk%w75Kb@WYc6L|0KM}Lj@L^Zzf!>!Jbot0oOdj)=A2|Cn? zuYyGfk0q=ukqP4B!1BVHm;^&1I&+qHt;6WYE-bi9{+oO?`2>NYciRXlT7#=f$~l72 zxgbhkv=`?A+1Om`MkeKOI#qX01J-6;e-B{*B&$l zk>~e@xE_Z3z$)c=oCi(uz!r>JP!tKXC%;~bu_*$sA}9iM6k;GS@(LvQ6JUEov;zG8yg&xq zS^Jsz2xzP)D5n`cnF4k^F30ERvbf%;E6ivtuUkObm!phm!y*>EVxbQ=7x;PRR)Lax zE7ZS`9}B;i99t9>9ff^t4JD{n8!+v+8i<8yR!1w!S=bnH7PzI8t~iB%*b}h_D5K&C z*0(RX`}AMAb`)q`q&2naVYz1EZ-sB$hLXMQA9mt92gO|QIdV`0%)nyoXfq{EwSN zx!9(a9OaVN2bV8<>(8He8A2o}ubK_5by-)oBKa6oN#AGY(82rKKRV>Xu;=BI+&QWM zlP!>dx~%u_2rFzQ=!v+{W4D0%jd}h-I$mX^a`&NUoY6LxqLm~#e9gHp*YfEo78abV zcNaOt%i7d1S9HT#Y8V;5Nm+FxXe6q#qQx?&SpR91YgL`HrL=e)L~=6(>5(K%m>EvU zY}o?7YA0srNu~XE0hXI||HW#G7<|`X;)hNz;1FMvztSppDoO?WJ$~jm@r6HZC)t#B z0xkY%2JY1&Y9W`)4n;HlB?{<%5QkAUjaX$#3_;dGtW#YtvV>Vu1?rVgDO%nqD}+OhA*`-is-X2~BYidVF2eJ?MZ#~jFynDxiK|HPePIkOTpsdP# ze;}EXQR2Zvn*nYnvi*0Vae03OU4Ko+*y1w7CSeWlr~) z$dwnjEILA_f%)hKTU?UD$k9mu3ntm?F8=^VM&UX#zh3)^_~7h~q@Jf)u+vPxlkDx1_{3(K6QATNCHCUZr`2x3%OBbSb@Y3Vx$AXoGS84#YkZq)2}{N>xobYT5bhB<%cL zHY~<+ecn8~}7b zQ|)RYYu0~MQUD0ENwtg)}XX|G>CNC@D>0de#@DaY0iOXgHV0nM+ zd)_&9Do%-YXx=4OB$*GlB#gn}k<_Gu`o}`*(s;<~ScAup|0Av>!w)hGX%7*&)?pVo z<2m(bX%RLS$q7C=U+z0N zmbu@nA8ng(aF_dxUOO*ks__v8Y0V4XY(i{B{PmlZmY@4LO!oXo8&8%1fwxnqib!U0 zOc+%CRx^#-3ICL=yO|RdH2=$qaG9^@GFOqUOZ|QOr7w0AsDv=UKPyYFu>)c*L#tXj z8UTX|;iKVLtdYvK)zJ_#jBtSJ_Zz%%kmCuZjt#_$4nlrz#1dkY3a-QL2?0_fd7zcp z0$L#p7Z^kz4Fu z%9;Bht@Sm~mdp9>>A$PhJ9K4zIJDMuv z$!Z=W%d+)H?dnAvF}PaADzaZ0j@(wD%B(brd&T&Jb&CSjBS<8v7R29?>(k^Zok79l z$O=5`2`-)qM))jL9%~zd41_KEDo%cMSbY=PTqRej3R*(%Ir3)-Bx4Z-Y;tI)H}wd* z{yMJDv8zN|VkKAj%}>UmBbDMSAVUAy$bB5nFKj%Nyn;zSg2Fu~ou>34%N+7kLab7> z)mp!Fg5vzbv813|yf-yN_tx#lO>G+(Av@68u(FMpMsBVGgA#=S7=ffsfKtb#v=yfz zbEUcEs>UVPn?6XTM(NQ44Vlor?&`2(=<*As$WnVSE`%@v5>)Mrb*^_KMRAxcKE(!e zU0l}D7Ks>0iH;_#4M{4|wrv%)c}4S)UUVIGS>hH?l;|?m4ToBNoP$PD)nTN5o@?%B zbR8Yk5CH3#>YXvTez=nQz-@}wsVn7SN$7wb(8y*Hg23O~;7Wyq%f6LNB8wtM=?~lB= zz4An@SP63^&v@nA3Ryek7Qogte*XuW%aN^m?l3Y-zcuxwJnwm4k_f5S2 zNx97=C%vxiL1HfCAP1k`labgfc+X%*VVtBg`T#Ao^ki)k}_zTFrTCT530A$|c*cP_6lwI!6= z0|NxFxHl1vakTP#T*s>oBHIL)UQxw?x~P*4AlPsVqN)C79w**34paAjfqf?NHsC_e$=O{5 zY|P`Diy&&hEl4v4S%O2|BBvVwP#HdSU3LRorfXb@9_kZ3l#KEM1d%WjCjl^8w;iV; zLcpMKIh%kE2;){#l(m6BiqV+jj&CpV0=S&TA>F4ef?({={zZv5Hs;tb4CK%L#h>F} zMr_vAsV8?|G;@Uz#kDdzGu*jA?dRi`LUJw|fD~(@ELn-;BlJ@Si zNt{+go4}jwa6@b{dC~O zV!`N`%x6l^}Fe{n>eA*uX(h2!UpCa?;fa%hr-VHWH4lA7l2c zO{~}QZrLUl7UF(z$h&%@qH6RC=c&$G+-vL?EK9Ov#7iO0oa2A4)5w{U*PmiPWyT(_u`ONkWcxHdHxDt>|M z7LKe<%aozPYlOnU;LAp!dQH~ACZ#ncjMFobs zu|tV#iBX2g3F7<+?ZR@a=&i^pxfE;b`}uDz3gR$1vFIhCrNq;`fqWi<=*uzmsjM6s z6p`=-ioE9J20jTbYW2>6{;bXOZeN|5T&)CuNNpa$eSg;G3wvs_jGO%V&)R(8XFp$? zcT#){ZQgINQiMTlrL)0~ICAmuN68gJY3ePUR@jZk!)BO&yV8~3hYG!k8>qCs^H*{a2fgNIn>(={ z(shhR;(c0PSlr6G6a8D=F#98=F5EL9#>WEXhp3?>>~=9(ZSOLmD)0odDj6i-X~Oi< z`Sl-6U=Ewxk9Q=d2S)%BAj{UAM=X_W$$57Ax?T8o5gfQ;z`1$o(CT9F1j$4b(wdg^Io7}rQ(a@-{=^$Uf`=suxL=m!{60GGw9ip-cEQ+9Ys z-u@RIMEVP17G=NBk>I5*Z*@q3Ux)=!?Jk_{kXeiEW*{>Lda1~a+FI|rc`b^)V9*#b z9)Ux`Es5c&0)^nUSQSF`xiG$ow<3ZNRzMG$Du5tv^cj^zx1@t2UNI^hs62N7*`vh* zq-DI9SBybgeO7nA3p313ZuKrG*$LvqO?;YVie;fEFE7Zr+&mI=%$OF+xKdC(J^r|d zHxJukS*^%hHWuLwJ=KFO9Ajp%dzFwBivZ+cefcucLH#1}DEk7tXrt$F5Y5O? zAe)i9rD7QYImbd8J@7bIOb+wJ^HhdKV(ANu!+!%Ho z1qx7n_*~1}nN|BObbnzb>N2$!Rsu}MR-|U_FYM3q$6~S!4p0B-1X@T!iw8qDqY!Dc zy0gPUZZtpEagod+wUL%ckQElKI{2V&tv*Ao=DZD?;^PAvYk5nvhbJ~*2S|ubdMj&% z+HC-s$Uyp~IKYx^S*xT+tT(D6vNDi*O_BgMJ(|Fo9EtkVsM7dqjh=Z&qB$&ZwQyK& ztX4`A@I;|R|1_%BoYbkML>K8MxMPTL;wB505?e24G2sl6049$IGkJIvcmGz9SsUc3 ztSJ16<}NeK77nrL%A5l=po?4l^lJ#e&)keA181~qk#GKF(MKGf(1GhP z|7^@)KC-H)(tmHhf$m>8Vc6FnQ}<_on>lLx^Puuf3-nwDT_+K|CFp1fA_Dtaf;Q%# zHDg!bADa<1-0u>kFN;*%CsjTlHlE5N>A6{8_x;bu{=bPiWEB6Z;Zz#|i-7z${rTE6)V(BB zWqU85J?btaPv<=8J=kpL5l4j>8GV3H`5-Skgu6a|d_MQb3N~S{Ex1iW2SNYcgxBQO z-0eH}re^Qa48ha;wmzBQ309w5dR0vWt(iyVId)`J|6VheaFa0T(X{LItOq8D0zZir z0l|R9PfoAGhy*{*|NTqdd1T9>+!Bv(ZQkmvL%^v|ona0VBK!}MWKuuaKIO=2>d1gq z&|uefQCKXGtjQ-_Z>FxBnNx3xZu@}M^)0F~bq8^Qh*hSsrNJz3a)pwqr90bdr9P1Y zqUttnbpXZP<7dB=lH}&vs}Q!H!8!4~z1Ts%bXYQI0mh{_u^QFy7!y1b-@Z|>Z>=D_ z$4xTz1FjV@6PtA4B<}?L(hG18f%@hHWGRN2$_uM_L>)g8`Oo^&3Vqs{RYwdReX2yz ztL-Q2%h0mfu{Y$RytZNBHmqH?@Pq@{?8k&2_8&j`E+c{Q;~Q)xtzOwkEVgar7TvTX z4Q5XrH=LpVGs=mFh`_4#5Q>quVf0^ta2;c~TQDIjBzX}IS3c!?Vuu#PF`T^DyXz}U zZq(2&*f7Z>U_>!B;VtX|X96q}uc*x0?<}hcAkC5D+RC=B>x{CK#E75ny_`^jQ~= z3QD3a?3}d@JiZpZ8TXZ0VQc+`2C?A0PYtnkie21VGccv9=d@z6bl*ECO=~JrKWo&I z?k`>^U{YKJJz;mkxo!giN%Az+RuEwrN5!ny3a<3DYkl{^0=%==3`4f!l0SdTzDmQw z%Qtv-z{XRVMP=u8@n~F~dDRT7IvTKFvcsU{`ZoN78A@r$BSvd{oKg&nF22?T1Ng{( zAuWiUW+T?2l55=wYcegKEC7OUub7}BI|^@qN|?u+y8p^nAkKBzJDBVCIzRp_@WS7U zXJD-rhQ@&?5!w-ia|aLLAp8^*hs1F(ox|D4_pN#llA|v=MN;u={rOsV31KfTe{pH? z3UtBt;=uYH1a7IXuDda&aLgK4q7(OZt7{?%IJ8kg4YQ7N7N;ccKORok0X#KT7g)DX zqE5211>oA+oco@2E}iUWtp#gja zA_t7gtgp00NlSE?H&*br>}`scF(U_9|>}55pI$^iTKi^DPa+tG|tJ z$aP9z>^^@9LZ5F;Ji-so5jMe7%t<_^|9Rm2MNwZKOU>TLRtYO*Tjr;&|M34I;na@v z*`>kTM+Z-QvX4olwhv~bM@M!dsZ&02djB{xMh#?NA3fUKHJFVwj^e*tkMF>Lk!=0q ziG86E+14)%&K({+(GVy*03|DwIPVL`)Qhs|Ed8|e( zk=5jZhW&P9aL4wennwNrU^n-lIC^qlesr{P`0)1aTeoDN9A&%aM|j0*Xw!rF;^^R+ z!J8+qoy3gy9zJ|*bbQy)(AM|g`*6Z^xGGi2Qf>Y(BJW zYc_e*D}QO*XxI4AuCpBU;SWv{>i%Pgckj9kxbN*e=>1m$<=xReq@JxKHi_H22ls40`QF}bBjyb-*x+3&<@n_y3%#7jpfKF1P#d}1e3 z{f~hZkM7?6{_uN;_U_p?gv@1}{?S8+4>gay|2cmB=>%d zH}#*sj!WQ(h$$SqK_n}&6Iy3Ac-b0T8h0bO-+OeGZ+GP*{An}Ss;52jFzqryjZ~7 zRY+b#5bQ0j%qJHi=FvAQeMqJ6zWa_dm)}QTEas0H%D(pF+DLprlOvILEuQ23+cg>n zk^JkTx8_gz{T{}J@#Ky%j=F~jUGU~XcU?_p3$z|QRhzNu)6{UJ^*ZAIkfAM^n~zly zB9&&;0N}HybwGkI4Rf%^A&_ePckR_K4GAKg`OuhRdmd|cRo94?yv6o&c>>t;qR8_$ zD-kuE5Ff01ipPLqaWpxL)0+N^x#>GIx29+BP2JoIsZ%J8lP?Rl;k0-aYB^z=9Ee6H zgW|XpA;Lab$6g9q_wp41heo6KS?cupHBnGJ%t7=8 zd=}n?Wg_e1vdZ7$IOopy{lM+y8^KL~pbTjw_9{A*(3+;Iu;%!?&x*e_5eG#rbOPSQ z*Lls=pUUm_1xt>R>c;x?(=fWgm4YbmlShL)MZEa_s8rP)3{A8Q>R+hUY&)}M;L7m8$7cpk9lE{u zi)>)v$id+wM~?45m>)bio*g}yeSGBFo^0#sQ>{xM>>b=SkPQzVIdo(niVoh|ePhp8 zM}}M5N49Q}Z^?sID$z~UOORq*eVdfJwGyg|pdDU5zybOX|BFkXE-fcRsg+iP6zbGg z5mWV`m_rw}N5b+`$rf;@$Px2Z7Gv?)PG8SNMSIX0-<--&*m{mCFbA@fq_0eg-Gvte zfA7ZxV%LM)kbCd>EDCD)vDDLjBvot+8Ij$ktbzB{c$Lv;&3L1X76U=(CLzc1NTM?1 zobar;z)Vg7#|&;-7R$gX0>6@R`T>K4?e;6opW4)!jsEoU5HEUu#?t@=a!kcx;RKeE zA-033D;XI^4yuT)5p4ojXD*LG11R6Emnp->Rr85&zxS9670=9=##&cv6%TLgvNZCi zNPrF8`J+O7N$Oke=MHPtceB2djAQGsW@j&D2Tn{4$LFNu0`XlsTR<7oGOez^7$*gA zI;+_Ue?DATfxZHFf??_3e&no`*th`f0EcV9U7@)Caqu|q@)XcM0I-f7+YT3YhTh_8 z=lR-%`i|Nwi!b}v(W*7yh5PHC!W%25k@l+>PGhgIwY{?bEPn{j2|pBNP2ff%7AUJh z23@*=r0RGH5P!kTvmm7;#W8GnSN8HLiGJzk%iRUo7eJ>^yUX|m8{s+k!ir+s)rZfB zkM<&4qq46B%mzr94)tD8(lRw>ZvD|+tl3no2JCs#QTs@qC`o>=iF*uaMAVqP`Ms4B z@>=W_pm=!Pl|HO1JC5b%a1p7c?XCw5V8?zSfN-+F0Gea7iYZ9R*>seq2e%5zog2e*KhUGs_&`umQ*%f6n-2jo%)TQu#rrBA=6h>1`=aWazH#=_`aR5KbM1{{p?YjNj1F} z&IJ{%hkJmc08vAU6AoJ#)H-VtzXmZV=kp%=s9qPxl1@n6WpwQn;6kgUOSa(nuc6t( zcj?p-D)b?I2gEK62sx@eTnb%l=Qq3E@8zT=Ul9gFWH8E_{$1xOMn=UEDu5Yz6yBni zFvVvY*+u+KoDAL2xpTp`^F#g-zJT#1d?hyK0CVNL7xLduwobQBhc+jPaz(xT!l{yd z`rZz%S$q41n3pH4h#;Qw1w`S3r9V+cbUFUmgT#}SkQXD@+~0|f`s^8SgLj_*zr{aO zT}(Z6p%PMJHzrON@+q<_t~Y&r)>}Lqlv%J!&;-ewIz6l@On(Nq;OAr25#jm(b0!}TfdVfsNhJc=(E@lIi#KAO z1dT(od6wA6Bw7O6{R&&d#Q*_jrAMCITwiLYjziMdK*IRh?MF9jh|7wT7}vI?DU{Rrz~6pD1)&0@(P3D!k>^G9Se3;W7v$1 zQ@IiYD%Gy-Q!pK1q6;eWMK~}`swhx^FT!0qdK0hMp2w1yG_4)~uGBZhOgaP(s0^lU ztfVm$RuZibRmM6 zpCkrIIF140!3y6D)eMR!cEBaCAlzv`nf~#4bG325*T9?T4Td(!jyAHPg+H{`lg~GK zgJFvOKet{kJX_XCDPcCn5ywNtM(xL7QJVB4hep`dMxo~d@AfZ+PSLH|@XGRe;9eyk zP%M81By7O+Y|ywu+k?qwG>2%kjyptn*+dIy@AeLKF_WUWFPG~IFJo~bar&`wq4G)9nH3#lwU@U3}nYY$z}(#v1^DcxcKQi*_j%flhIy3a{!{<|A4j!i^Lc0 z`@af?2OlMdW@eB-vN<7W@-vTN0N|t0kXP~23hh&dFM0uaZ{I>`3u%elMBN{o6FYJpISXQ7bw>3rpqIiK50%B){mba49f6XAit;SDX*M~#CqGy)r z{ts0NuW&CT{FL2V)sVP~uu=}~?2>H)d%TicG4sFo+RcV22+A(f#y^km&gsTCOsS#5 zhFdzsz#6S`*#z*=R!&aesLbY9Wp#UDVNK;yT`d2hv%0npx4JDiP-2*i;EJ5C(P(T{ zCF|I$GDd&eYIwVlAG6=KqJB6G$_Puz=U>)o{tFzAKW&}-l`!3G;N!6)pTDzrU$(8W zZ4#_-_zalsp7)1#{HugLf-An0O*n^1Z11*mfe#uP2y6PoGC`vqWrF_++gq&HK17Ub z6HM^UjHlKkU0}j!%0!H>Zj3xfo&hAhe^uQ32o_>q_oI&GE)e3;(`k-hO50fXn`qT%Q|EV^)kkpP-jZhyM##|Nh;1$w3J zc@E?N?)hBvggXV1NFYw8BMYLX6_!}84?$$&1h%L#B0>J?u(_I3)G_s+QE90h_P+=> zJ_l}mY&1KO?ai*fvojm~`1FMj;raaR;+5=t!iQB%J)3RYG($G}7FP6EZ!49u-T3(y zq>mW;+FgACc?=vwK>z*!iLF*~jDGZ|cpfT3(?=% zzvjc9Tm^pP1`lcNSqpx^jfVtH_Lq{x`io$;)^v-(TGNzL4a>?C9~s z$HxwTnjNW-W$0GmzcrKNVJrdu=K_;ke2PaV7eSed*?;&~b!7P`5&c0)=^nj}PM=iN z5Z!@*f5*YN1f4+c>#QKQAK@R+v>61FKVL>zJ?`%Pc;?YXD?+rim*FC+Rco(yy0osL zA}o$t*uz`c6pT>z*vlkto<(PIw@ItvAzXTmQ1poxEq0e_lw=uPK3Z-4Im}B_Qh08% zQ219;cs|rz?&9XM*8DKkltQifQKkSYZ|mBV z@SH=-VF(PaOsuPUiXA88o<2Rc*u$U4xgTwRPc9PXaxxe8%Q4a}D-e{fpY7<0+_dAY0hhU}joC!X(2L zdQt3Z18a7BC7-)}cjhlNT$52~-%Whi%290hbD8P5fztcmQMXH^_yFIPQ}~B8wZMy~ zZD4FQ=ksPyABbaKm=9tZd`yHThJ4ZiKi>5(9{$O;YMAHjDxk@}z5(l!EFfH;utU)w zLesFOb=|>l5IO=eNnL{J-;*p42P1ZWWK>2gT07}m3)9IL9)m)Gspweas6D$C;}itT zx&poYuh+q8#bz2nz>NA7l*6gO`S3%Bx0~o`kRENZm~d;Qv4->vFvKk}t+~YiB?A$f z6(HZ-xrur&7G5&31Bc6ylV!+cA%-J#4Ku*n3t9r$Ip43w4p1#y9>*Rp6v?S*f zHvh=P26Tjo1nB>&Dfr|~m;WJlIu zi8XUvz9acT^~k>yY<_2W1Q8$(br#pxNDi|75rVXUB%@F8qNj$il1m^eNngk2p5SzE z%ERpGUi24c!uW6oOH}nwaqoQ5hBv@TgJjHy*~wjr8SK=@V8GZ&KoJ;RcX=IG26N8Y zK1a;C0ZKh`;66-CRANAPFwAs-ZmFUFFT7%x%!QqZVMQYdtjZN;qR?(+a4kI61KtbD zYMvf5IM&K)b$aaij;*o20hfO&jpt84fLqK{D2V~5mU+ebZcGcYo>LTUaE3aeE`}0t zj)9<<1^S>^MXv&#$j`u#R?Uh2tcFMT^=utDPqP zm!oo|jXVB;6E@p7cV<8)h-41njck0H()Tk&nHu#VYtsX66+-o`Gl%ir>$0z;`;-WJ z?I-#Y{bg`4l{R_|EAVIg0FOs!KE2XIHYgp?0`epwc$(#A_!KP+HNBATVUif*}WB4HK*ImKmnHtEi zs1H+CQp1V>LE+J5ji5GBiQd@nTCMNmu`I7m2!1$b!%ea&fSTkl#f;39SdnQ8Mg)Be zxa*AEZp)qDwXYhX7SLQkt28svxRelD&N0X@bh(OaJiK*>LdFPuD+<@%-Pz>8?b*io zCxbT!zdrv-_Vu3p=!fuNO$^Q*%Ptuod5 zf$a8)Y;MPG@IRW!Qe91$85iRC_ z{J%l76{G3dKLw+yYiBhWg_`DHb*s7`%^YEZq&eV7T)*7b_rR3qXHty@+8Yl8hFe3O z5-udjRSqBs#{MWYQCTKzWWsbVr4lS1h>UZB^g%92AY*({NhOJjOlAjbTLo}%EdwgCz7Gs2f4F@J?lm>80MFallbG0z~^ zDd`WkL16~$)aZ*bEU?tz`kBQIJ`^cx+KZZ_^OJ~Kx3;RV=>7ufQMP~*=OU}13N?kS z2skExlKYGx)I8jxKt1>nV8D2p&jmJOu`}Ut;kK^f3@!(P-{`Xw!UebyOf7-501Ls2 zyj7%EZR8`Z%_9YHopfljSpc|vkATCD^-C2(YnZ}tT@dzHSxA*!Wr#7eSAOC| znC@LCPMK>e(w?ReOPdt`#ePMcB|xZ1rcOybymShaEo+xDvy~c4n5ImHm;j%Wio7y*83RQ~Bprz2@YdfbvyZn|gD_%>I zxM(FqjR$_tm&K&zB0LRkzw5Gy+rN04j_=3aGsQ2E2JU$&VG`j|Q3ilx(lXr{f@FU~ zlBV7dLqMYe8vx6+u~kailO^+;sB1Oj{teE2Tr>|1mYlK5b5ASJ4V?7pLa#Cdv@~4% z$Y(80A2&1hF4n6hCj^F%aU-}nE}nh>-|_%y361EFE8F$ZDRB-N>>~Fl_gAJ^g?$s~ zam*LCRQ0p&9N7RuZhO}07Q`l70L{Q*45M}l~ctA)y?K*v&DA3p&DPK z#r%IQ{+EJ5JZ?o+Qyz`G;}lk|b=Pq_R=jLVBP3B=A(-QOpo=mK53G&|r1eD*8L>wM z$S1C1OO`SGS-9VW(O&EFIxhuInBLR~s8(y?L3+2R2(MKJG1t|bg+e&eQTOptkP{5Cd|;y0wH{AXJJ}6hvkulU~oJU6HdAciw{;T z)Pn>FC`gpK_`S?cZaq_J(L>oKWD`}0-r*=VMJfnmg*OGa)scLF7EDTxEr^Cl^VTdP zK&jPF17Svj<(bC}=!QdfdEq&=v8C<{*!u$6;N{zHKH``yEw(U5@|KN9NNj>o4Lz~z ztBDOE^`kzF^Kzg{wC+Cf8lawB< zca~v%#CY@w{(SxMW8ODY^pz((>h)W4KS_{bRRedXAbQ$`P&rw}iBgh6tzUx^muWr` z6pMApNqX_K@{(ee2u4nAj7-SIWDl2qSMj_ zLY@z8&ESPTwK+0Jbmo&=-JYq(D?W46demwre!(u6J6EB1BS61PZB$xtkP$v+tVh zB!ZR&pTS+kA8$W4rYbeD5Hn)?f*~20fzf!0GCOc0{(NHEyt^I}1a}vs9~!*X@^p0( z1C*Pjawxc!0I}o95hERN(4-d*UwaT?9ZX{i!C<>FY{dgwgaR0=Yas*a-PA)Hhyp`zzl5_b_#MciilM=@0&-kt5d zv^Sgka_;^2vy+3z_GZ&N_rNCo_3cv!ve{ps&Q3P6PaDV1U&u}!9L{!T*N$v|cW5v> zeRh0!FSFYoY2vS$f$W31Y~P{dmvQIq)9mOM*|D=jM+Uzb$WEU;cm&tohDVMLZ~y$@ z*7v_en=5-i1AtTeanEgHa{th;Zyes4?a8z8Gq@|44`h2rPK_TsGI%V*^|rZfgL7Ap zUdtMz*=Y9Fo>8V}K5;9_twaGs?BO8eg2DQiG=>Y#C!X^S3o(ZOH~$Cd?@!wpj_W4D zv175Cyd1(Z80Oq4j#^-vWj{n>HAjW=!la>3f><#et3jHp$yhyXkX|lthRE@&Y#3(5 zqAlzd_Ft^T!wm&`l|k4n_?N61di3(J32>U>;H~*Ui2@840ywgulZBxzRvTBFVU30S z1vBs})48pQO}7dddzc6TlyDOlX$WFRMcJsP_WW-r9vn+saI4qU`)vWN`;G4uDyy>| zgA_&DTx>~@P-19QrVsqX-laiHP0U|$YIgFwu7>vanTaQoG}00WvtUnJ7pEQFXNX!z z^>}n&6euBT$8Jd;sX0#mR_Rwg%+enyQlzk(ZxZEU=OWp@KrN19qd|yG&<+8!df8u= z?%vT~wEC1$psKe_AX-g44uh*&X%H4SS;caILNYDHE3|q@9Ly{AJlSavDV6b)jkd>--q1=g$}wCik*z6!Of)g+@yg zMaVJ8%5F}d1NaRiAe6CSqb0|rl*tOJ)y>AI%gO_S7Iv70f|ZLrg#Us-p(-ma`_Ne- zU2yl|J>nKD3UG(vM1`Z@;?{Z(#OD$rEUvHenQSDng&R$5B(3~6@ZHhm`2zX1`3h>{ z*rrZTNrll%!g5yE=@5wULP$mk14G!DIL%U53Yg_nw*)9oY?A1gdh+}TT8)gjrPj;< z2}v$!%{VOvZPbC`0rLVc%k-N}b0p>z5onP> zkz$OL4b4$#nAX}fkR(Nmki<_AfIbuX=fv>g?8xW`*}nZF*}-h|%<*H{W&GcXne4*# z_Xcp=e6CR+nEVczBgsu>-4ACtLip6*@+mznxzg z|J~I1Up<%~Kh@G-?=L+#iJX+br$91#Ot+p&SM?IfNM8_yaIyfvA`*(yiVI95zXhX> zqJzsLQ4UBBy#I`1iyj?`#31&;peTwdU1lMt%apKr2?cR=(*m3s`CEu(P9mP8GWuqM zP#A?i)g;^!41h>S*$HjE6b$sk}9ZTFsckPHnY28(xSauP8{ zBxT0jM=kpN>F8;WfPh9uX;350m_)`ZST}PMtNca*Sww(eNO~)-g-Bwrk60{;ax$%Y z0~qFL<1Tt()g7l{eAw-R43Er1NMy(4k?K&q68y`l^hnW!6y~3!d@Xm1;wfzq`90by z+}~{i4vkSF&QJ!T*#t=x;~OH(G)+S>CT$e$-R^RTvFVE!+jw7RQLCXTYlaZ!+@`{VBy!tdvN$OZRNO8mkPO!wqT;o4AH6SAe0{@+M%dlPM|q`k4TQToF{ z-X0W>aU>^GMHPcVk7`qDr$!5^Jg&UY0cefNgNCSOu|d)?QMU~|20Ph7}u zBHh&|pS%+fFtoGK|*19VbEu=>nU*tnJD9639C8lK&$#xkT zwq=tLUabsl&KRlv@BaHg%fXwLgH;WRLA{Vs6H8uMO3uGK{b=$u{~;QiE?i_(>8!oz z^xEUM@4yZw$G==-m87gwcdyRO*kv8~D!P)859df{6%scR*}@+t^)JzPMp z#}2(^pW`6G3HIX|9$g;$7X@`^#Uza&tXtvh1opIAtPgkAL&OMfFqqbK=3N-@EvJLAoAI`*sFJ zE?n(-{No7kSPTBEN=ACMMN%2MAO@4J7$w66>8M>4(ONuOUP&K3P)Tsn zXk>?!N%$OvmAsjdPICIA$h9_uf2f*p+IXM)hl>8q3@ckYyO zNEupas(}1KiB(#=R5Tf&q@rtjcTZ}PT=-Arr9gACxGvSk@8G#J@pb@_=w4^UMdXdE z7a+J$JV!`ACL+B2Dp)+!J7DFd@o_py8=BuA@bJC?_J4w(>Y7KX)Ko5>&QIHj{h=DG(m(2>YwMsI!Bo=-%J^>{HUafA7^B)qyw%VK(>GGXFr_*tF<8=D7;gJWEl?l>Er ziVupCCOIEsKFu*A>n}RbxLq@5E2I`-5`Mk2;^HfI48KjRbthPan=$vECLG2hdaid? z(T7Iwgoq6oQzQ`y0-lB4;!+LijG`28;WAep{#Zx=^Tu6=eRvC^a^xpE{K#BbZ;O9<#j3`RX<%`@)x#r z6+E4F6Q&?K8Ui;n#jcoA9n+gNUQR%DsOB=!fm_12;m5iM3&rEsuSi#{{}XP=tvwY9 z%{inIF!ZE~`-*iD7%dqC=pxaP-@iYi0fVw%(e4lJi{h#wMw}igv6dleGs3_kt}D2D z1UDS~ckT|-6Kz6Hvof+GHGxc(ahJ}3k^A=*zvCqBn%3mu7HPH`bOm<0 zk-R-Lh?}$Q2jkw*fPKL?f@QHhuXT@M3srV)4VNsD<3xo;YM@>Pog&dyysNw%NdIcO zs_J3QgJU&Pb;ZLntk0U^A8R-_m z=*s779iBxVU3E{Z0KF-KO_3&-W9mo-`~*oX@M;^v%$2%BK7bKi%w)O}xuJ=5UBF#c zk=IDIiF3N-@ixD&2Zk`?PltCTU&#BodRoMJ8Gcyok;d4rHgsVC6`qWwCutd2v>Y*D z0R}AD24&hO*NMplQVbaf;Qlb(YJ77b&GI99&r zfS}_4;6XL}vYSH(v*A-avZ0|SB5TIa-M9b`!?7#b@naY1TsS{Dd+Xxp-ihN|h6d+$ z9X)h@==`yBa4lTUnn#asA3)U2)L^!MX!_>uxl>!-ojN{vi6J+8uW{BisE&YRg4yub0`cy{%RFS4&@uVi1Jo<)iMkd$tS$=&4W6 zoH;&_U3n)v+9!C&tia-2czf4{=I`G|;kDJD@zkp4*z|1HaSk{F+W?}Z0zV8R{?$YH2Pa^}Zgm6qhE^5P{CmrhCLB}-OjGZ-jCgiT8><^=NV56>UF zx=PQRK8g%`uM5OQt*;&z-{?MrJR~A@ijZTRpHDwX*E(6)2=o`dNF+$ZR>pxU&$wU& zIDd4Xr&JX-c+HNL>8eA{`arM+skczJ+D5wGQW>{~$gpWw`kV|vKna!0^k`|9_gS9- zw1i_EByAZPDrBw`PqDfVT%vOa{Pvw+i$`|O0mPQfCm2SM;~FYfT_WRDZGuN zOSaB2{9PfG^gRfUe69N>PzHL@4#|o!Fp5^BcDG{s-(D>s@0H;C0*t}SNz}zphB#Fq zDVQ%<#5%1}uLKD-ZDh(m0!X>K-$GME86X(BMcJ4tN2Ru+71aYJR)!s5%ZQ^m&)X-G z`S$YVrq~x~9kK1bOZ96ZneV4x;=)Q%t*5#=kvTCceY9UQW9qK$__?BJ#dRjOOR15 zUKMe~XkjoBeH<-u%AW$O4uSkwhrtrB-y{z0p{>Zl{S~fQA|ok5SM1tzQ?aU|x>PqJ z+Ze0xG$S&@I(buNC>Et8)fIBO6b3BpYplk|u~(HLrMq?HH49WG{L)0?LREU)c zB3XoUu1FJl#649}@4M zWRliwaolpQ@Mq~8xo2Rag;o`0_9wA)SA^}L$DAF|uM~L*E);r*=MsX9eEt`zbdc^H z5)f~?m{^sH#BWBDkh2BPDFh`de9=2V|aygHz0n3myfcq zvg7Y$=f<;BS#vVm_HlM-E<5v1c4=rlyOE7wn$8ZLJUDbN+xG4pt`kk}!U#UXhi&if z$Dh$ap~eIWt&9?s7%1NU0g+k*MNsmg&;Pr{e}UEs##w_H3U-Nw-piH6B+^lg6`d|h zLcL(8z%ea;R6#D{*5x%khZbsWWX-6l%t6&HUNWWxbg0d@-yW`Yk>8bB9Cbu7UejB! z)`YxG=c!431Z24-a|#10?|9B@SgPS`Q#yFi^l0@LFJ4GjAqsb`+g4Zt<3o73AlU6T3PYI-L$N`@ zu>AaGGc*VA3;8Q;c%di;A|*wOQ5XoF_^CS59s@g)c^7BOuk|za`|ma`EU3S)_$Agf z7`X~cE)NM|gN4$CbtD&AP0GJjLBfxXMkOSHm-&<{-ow}TOXJ$ zeq;~@u!>|T2y9OpO|Rgwx9*B$N@>U6lNt~(EK}H6ojLDHR3@=LZ`SUIYi`2vrlidI zbipmB_for1_W|5C&mQrSV0v}f=o;RvV9GJ5O^eIx(3T>Um$z|B^F{XF15|$Pbf|MJ zEH9@+GqqP&6yLB}HbluQRc7)6YFg02rx9o0Y<@qM{}6R#z?=V`8RC90eOQlUHZIKh zjoX{}0{AL^VDdVH*PR$3T00Fg~9^a7r#V`FO&y*FO()!UMLTf7B;ge@$j#HDpe`0$OZMs=apJ+91n!o zr)G-9ScMFXYh~sw!)%=>r(&uu>T@w+U`@!HL=hj8;el0Py$hMfj4(<|hHQCYUC1cc z(%a)r6?;b=19`5im)6h{Ja2D{j3Y()T3X495Zu}X*+bL(R_mCC`on0_+*dwr?`3H> z1!71m7d{kPL?S8FkHu;2Kssq%D}*c%=fa>ivA$w%$vhGwOCco15yW(4yK#{V&+N2%kyeY~uQ`v6zM8(>l*l`UUg#EG{eb7Tjn1)Q-mbfveX>!P zUi~4`s47E$n{JDn?s;n+rf)pWfp;me@620YxA(~E^lWw)ETugyNeq9L?Mgw4ZJSAT z-Qhg9_*KJGL0uF%!=ql12~|=GA{dV^UQ+BV=GWKp`bztfb#_I-G($y~u|feZgHrg8 z=1G-+*!gvY&^C)t42Nc*?3%ZRH#c~O=DudY(zS^@tX>&qe_ZPL1%R|fY|_HgRL|B2 zLEyqdiQq+hOnw2}5ZQS>4$_b<;r5IXQ(=~=-n&0QRNxCy*1NO|=b8;SJ=v_Nc(xgj zbAIRy(&{=(D-{=*SNU6HRQ{zP(|KXSP2kWB!kvHK{MnCP{RWK+oZ}7J`JN6(Wzx1F zW&Gq4)5fP47bgGoQx!MTRf@-#E>x&gT({%|vvVs{w7-3TdG4!tA^aBV`lndAu(lVF zB`*=;L$g9@(l)L=TE;(OyI2-mfuX3lj}yp$4J|@Rte;TJg_Lwco1{W)m7W3|Ts#v( zyRh zS!S%&O{BPxBttO>KdEYgm_mnR+f-|{kPSU%VEqZ5iWiNTgDD*w3$ck}HUN79+Tf|Q zd#;Fo?;v+9G!1^|ICvk3A}(O0hDK>v^itXgnv$2)nsB!K*OJg&m2lz41=C3L;@Ve} zZV_KD+Ivk6V+jyL?6;aa&I(Y;f32xi*!ieh_`9aQ?O&Be!)C6jm~2{rP5!E>o3IuR zAu^TPx^bsV<@jf9?TWlu+U~WDe7hDTzQ9i64zDzx!d;TWZjCise+}v(-6sb5>3C4) z8(Vq4tvG;S#E$MD!VOAx;rtSTBRvJ2Bom z^Z&E=rrU8GNxEQVooq~9-YThEJGBNOh?yXO#KslkA`lA!5*rDy)GCM#CV?cGB7kIP z0;E7ueP()o+;e9B%tOr2`ElQ1`plU#k1;>`3FZ;z`)u*>h>V0tN!8uAZn3KcAi~4l z+}zyE+%`W22f%Xq?Q;3;3+1&xmfs#Mmj~X3YvLsS?^AJ7oPvX3s&sDT(s-%=t>2Zt z!2ka(!Wr@1e|`)1JAe4Wdmns$`pg%l%J@6Uz_sc`?W>jdZl7K}vy7m}3$@bOnYmK+ z;!Nr4-@fzi`|p4J;k%!myLkDdcTQE#j9flHcK*`!m8o)RV&d(^6BqyX6F4`n{r>OX z`?P=H^w{9=aP8cc{x{*5s1CwUQW_fn;1-=9@12*2aDQ(>SFkB6-TNcbyBf2E&~ z-AL2q!-tswk0dD)0*L9r^%xQYk|Y}MYl)DCOv2o922qo2=>Ts=8kwCv~)PW z)^^!S;!-a>*9q<_h(0t)ZBj9Q6Kx^oivWzGd0mC?3(R|yK=DdWk@Eo^{AY!*5geDEaMf*N%2YY(HCNC)Wzbg1UHyI+PaFFSJQ$g%zPpE~srhKGY>fXMVDRqIPPA~z0wZA4dqgRLE3SQSwq6{sW&qCLdz zssVfa9UF%~;w+|0KSUaGJ^L$}J&B2B=zA+?Y zqn=jE8*B<8+KeBB?WeSzr>j3NZ6mQh&}C5L3l_o_fe~tCl|taG5QYm+x%XsYTnl1+ zG!Vblff%@j-<5uZ^(Bc0PY16^<0z#Y<(Rmu^^ohvrQbyBdpZL4f-s6j8DFYB7#Pm+ zNH_t^XbN^60=gQk+3#D%l|%C`jv`PTvz;Z6#VJ#M3JQD&`!zce5~#9aZGE~r*^Vfl zn5}=X8O7zGHSt*Vifp0RJB_x9zcbXMzsR4|IKlyjxORv%W>V2#5EG02DZt7hipcbJ zi8w;|7?VxAO*rq)D}Cqqi$9jR_WJq@Nj$9B_iLn{ z$WX7pry`LbHh)&Wn{q@35DAgUJ|A%d1ys3MawcYHpphR>9RB9?{SvhE_xnnpC8bXX z2M5ZfnX#dA>EwxbKYF+CeO!ldYV_359}?*2r@tzVebHA!Vw1i6_=CPuf9d3BBcs=T zS1wgQ`{?73OP_sm^3?mMKX~(l-~Fz1u3Y-?ZRv(BKN|Uz&92pcTS821w*r6Et!4l0 zh$AGm)(@y!prqS)ZEO^YMWf-F91;HBbB)4dY#D@-Yk4z?pb2k09Hz(Xt-a>=&3$jw z_nWs%pM6mZXOz%O4uB^=_l&aBd5p5vQmbxUCe~?hd$`Of>;_v1px$cuRWbtBfB8SL z`DJE~cxFwLynTT|zrh;Gw?+KtCYJ91f7+Ay`z26;>ECIS;kVpcG6y1@H$VZ13fcJo@{ zhX~lpe+b3Pfk{6x$q~to^c_Bk;E3bsUmb|dSHBQ~H8{iWI7qJ!LiV#?2t$vk*;j|A zR|i3M!fc+!AO$m~GJ`RG z^fLftWFA;5m<}x8tdmp-Dj<2(L{$-4JVZkic>MSg%}vSS&c-%MGhbXu3Y|l7$9acZ z6WXx@{Lo1TRo<}WpA;Yf(EpkRellVJY+!IEge0@Bn1}f-<2-tWUE)0|PC{NQ65I@4K(L7kJQXVlIL{PNb z$&jSE2AMkP^dx0%48tyGg&($x)-O>mD!{3y~3p479Q$w5r3YWop z)Iq6hwwk`Xv9Nk)9d3x-1~H`h%rIKu=7j|Ia8#Xn^cW{byTf#+hJazKpaF5;X&ts9 z_?Zn#>7U77XK&ZnXGgRQ>~3=#m$h@u)Lr)wHa0{U<04N0va~oex3WGbfYj0$Z>nSr zJn7b<_(uB9D@uGJDzJOSdNyc$zukDsxY(X8$-244*dJC5a~r z@z;(pjVh`q-%Kwr*|{hU9ADHDM0zq}(4bhjlD!t{xnOnoA#+hS#sU`9NrmUQ!xWM0 zGUz5TGUuqjhiWqW$wP@y0+k7MN+}x9({o%Ai%MovJPjRhy6zxJ`LG&e3ew{S=*M<_ zFeL1OJHo-dFV~6cW@tTNC^_hQ0acB`48>3k@|9`gDE|~o)R7M1iIAmcS$P_sL>-~W z9>hyxwFGqS7GI`rKrQoUS4Bu))s^}RZ!v`3MT@V|Xn?vWpan5+_y*7kFjL)dC-rv( zScj5J6$jnDVP~&r3;43Xb%uy#S(Oz3rI&5=(SWS!m4ncRBMm5lAsJ8 z90@R*!O3mNKjjgKY*U%b-S#d#2`t>-fnOg+08}MtnI5~7lr%`;4w9U zP`^5ZjMl{m`gdNN07lRCktymLNk9$ic;N!az<+S1Mtuj?pV|o`+q(JOm9u}9vwsdbOVVG0t|VJWwyV(Sugzm}Oh!Cn9L@Lc)lG5X{1hXC%7Kd$ ztG;{kh7*6TE-e4cteF015t|U#5w*S5+12WIxYh`fjk`yKOvZ+i4FebrTm1dL_i`T! zQX6IfFgof0b%^x#lX_cDSWtavB|v|kE($x)W8B*U#d?&7n-Qjs!s7jG3s0V6O6}2R zr-Lk!(TTB1d>Qdnu1(;bZo+dQI&_Fth0D%5d-ivd%j17wWEHc6h$dl|)xd0HR*Rwe zZ>9w;0@b%#`*K-GZF=P!;1D?aWxNb%!vC_05_CXt#GJZ>a23S>B3oi2xkrWf;IV+= zvNCzz)`NsBkIz?*NmMIpCpg>7aW9&V5kKkt_ekwISp@~`#}of3RS7>ld8+@D(#adA z`p=Zc%F`?5+e<4qrpl{tmT#<_K3n>#ys~y<^2^d}d1bjeHJN;P`*gW9@F~LF-bN08 z-1zKdX(0LJlTUF!`P9ctZ-30!t0U9l={vtIz2`=qBQS$BLHlP{6vW*HM!NK$ovn>e z1V>Y9DEOcLKWxn|GtSw+1TzkI=rmYUvrR2Sl!kBt&>Egzo*Pc)QQHSQou(fYxu)_m zpP+6ae#5V9q`|LN0$bwi_&Q|)cN$1<+LtrQ4EPuLAg<%RrzZ@a8YNzwM|T#r)k5c9 zq=_7WJP+T%$5}g(et&s`xyldghr5VbVS@&qNDVaMN>!N)YOKo73E^(`j3)u>hap+y zviy9brSEz9$lnQJzxVckK2iGYx2S-5J-w7Rr5N!krc{E1)6WaVOndC2L8-ir*rdG{ zw3#MRumuB=Si}Cy-xLw$`M(6BbT2GLAL?KF4y6~wUu94tEFICPZY2c6PwwtRsvaED zwy=wM7?d1F4npOCmI=H|@wwhOSf*1uVOe}PI6?YB!;yf~1`STpx8eaeThH`9V#3p| zaE6yc=~yA9ZDu`~CCGYYzj_-r?&y-*n{uIM4xr0(SJje_TtbgQxelW+o(pXU<4`9* zl|MEc&-pd?t3|7BBwKQ5(cQrpUSRGn1A1v{Y3zu>uG&9S-)GXjObIvrWT%G!(gTg} z6YWO;!#?J4OtNn>#1VfpCD?(+yPDvnI#~1fwO5Jj&Y{tG%^svtn{m^8ki)UMMISA z_H)iKv;}q^f`Vbt+_`>~c7ez8jeHHnN&Y1e4kv%x-fCaIFrCO)UWt!T8^S zy>7RmAMzVfq5~EHhuE~}8-6uVfD=*{T(u1-pCl^zh4Z#osDX~uc>Cj6WLg`sGIUf? zmG8ROF+WCnhCKcQKqc5>klLJz9D!N4o>HDfJE1{_lrTjjzE1H6+c3Dd6#;Q)GMZk8 zQ$!+hQyEvAW`_3JA3wf+*qb1Vp$5@mfBn3#UI$1x4OIm#eNkF@_xkzj$?0Cg~bzz^t&e`gu+koILnfU!cW$$ zGs=&mdQbBZozR`(;Zo(H4HpccP~5$ z_kdRFN~!6qk^!5447%ktT2b2r=<-K<4^Rfo^;YjkDfrdiZixecBS$0BLCyWJrJG<2 z(~`iL{6K8SDQ_Xp5<~)p zQF?qLa&j%?V77g*W%$s^^yn>`?oYSadf062?z}>~9A0wp6~g5-53f0xg6@*Q0a>=}^T(-yEV{Kr-(!y2V0xgr+s(Sv&D2_ruCwO@Ml>Wt~M-J*3d)Qegd=G5Fi zgd4@!hjb-e&vLJ|JWdggSnhw z$b@8Ti_;e;scvqaG6Sn>*O7vDJc{5j(%Pw`EF8uYT|!2;E~)~zHp71_8*B>qvH%SL z2KWo|`Y3Y3KMl63NVoZSFe{+w+$KLmI!5L*=0_us4}s|9M#kd~+q_Rl#>;nQ3@m76GQpIpQ>reot16)Rw;;5|hi)In8e%)+d*7-<7BlQo1_;*69ACPIC7 z{wZG~P-PkQYuoxWw*W^VNW+_zEyU*N%Er6ZgIjAPO#sSun^c_ z>WEgrA`VEOwfwA+jj@kVHv4KI3y4W5auSfpv7Jzq{bVoMKfLT6Buhu0Q73#TEh z2L;TgiSiVn3=u-OI5w-`USuu;Fl2t%X~cXNmbz&p3jh*ECsA%zK4$XhQfq$)1^$gx zWT9rT4wS?9Gt;X=L##{#dHWrtW8Bxc0BH{v!^_u_eqGOruojL){i-GxTec1lo*pvO z0;)zDEF)SNY;4>Xi0?o+FI#{`_`OoDi@@Hl0SP`RWO%y;+6Fbl6N>8(_HjE8kEQHN z2TNH16`e>^0B>v3Rs#VEy^wwr+x$=%Qq_>C0IYi?R_T?1@8OKWd+kK;3NBLVCshxA zLIGoE(&0C)Lt&;JvECG8MK`hXM>RbzQFCQdTjlA&*7Z9OV&2~d5@;LDMX0x%Knm?n zbw{9Ta?o}%3xML(5`YJ<5#1Kr^?d>EA#(7E9$g#-gT61}BpMe37@VU3!@y?MKpJF9 z5dZeqDZ^1Nqun7Ck-RA#*}q4b0Ab9^wW1N3IO?;dR(PN1{?4c^pX(lcD3bQR2s&AL z-yfWgxX>B^k;XcB(A*`XY?)Xv|GS&uP4x#N+^e zw1O^;{fCOJ;8$F3R}s!#4`4YDEJ|qOb!L0>u0!m{4P&ty?Vz^KVoze%w5PK z;o*hZ)koN|R6Y**X&0B`_1Xlx5}!4=c4i?pI-wEMR!7%B2uXuoUO?*E!z;<3 z@JG$A&fNT5FrnB)byL4_gm$XnmyN&HV3_1uf`WVEys&PklC%{+78|Pp$VJbzcK;)m zSU>lSkzA+360}9WPn&f1gADm9IYQgg$${2zpnO2P4x{zj2ofY6>AhYk?Eb9zh~{71 z4ZHv75QlX`e>k_=s*~V_&cWtcrLEc7i-~Rr8N#4nYqHziYieO!UrnJX5EaeTsN>V3 z)Bpzt)dNYo9rh5xNMa$@9^gnP`Cz0F2IjPQnW&Nljy(?;^=bzcp0L3HcTpG`a;Lt_ zMdoowq!5Q-7s&11S&z0UbT;&tr6YyimKB1bvA=b9ou?ZeSe;>z1>B!h8D0BUGA2&L zcBF7S;L%MgFc56UT|!fZVPHo`kl0INBYY&rfqi;BjAn>X#1c|aNk3FNRYb`6RST>H zJC(79opENzaT250LGcfShlVL4+bn`e>ife)JqRM#QK1uOT4Xjy3Jq^X+J08hNtUG-8vEm*)t zO7%Hul~)IGD&3G<)=8fs3hq!0cIa4GzHeK|BL=xcpkb0IA|`vvbQ^8S>)Q+)Fd~cF zm@BB^Y*5FgCvHdCm(jtxgMyHhGi7jdmoB@KTG}=#Fq7UOrTAsf}%@vcLXhQ+kg3)xSmyTklgcf)%FjD{w4_pF_ znF~1+a9)y5(Aj0V#p$WNDo^&UYKYBzK`jDj1cO3izCkwJmI;odmQ+Yw(<6qjJqTX#awRE~%YYMq>My2oWOSpKxNeIpwK zEPeZ)S6F3m2OluOT8?o#V_PPyCNzSAKKvkHB(9beX)gz}Ms|P;NoIvuXOmK|z7H0hhDOPDdgVSSR!q9c%uas>Vj&gnWDJTTDbm6wC+smF+lPr!VEUG)QiB0Pj(h1uKQ=-z)K zkrH2Sw=EvU7j~0}!G&&jqS~#Z4Kgse2pamA^>p0nH}K4pPFf(EXpFHpJxnsmt2@Q= zWbK%2(?bW@50-}i$_i40mhlxlIXDL#!E*}&GZYzgY@FiG3EiwzdPp}(2=qNX+$AlN z<{^2+VE4GSixdg#%sz)n`cPB?#OOA5TTkf|!;u$NQpJ6UHE!^nEv12)F96RGI&{Iu z%&>6wC3Mj+xkHXGmx|}Fp0?|c_Ub4Vk6kwLU1thDg~ffAwWzRkA{frs-~x3qU`qo| zg?1*vsST89jZ3?D9Lm(HT!Gjt@tz;!4IiNN?QLeooP#q6# z(1AG4egikt10SiRCqK^~sBB0-^xB_P$h63ta@8N~M9a~k6IX;OJHv%Yv0_WZNr-z; z2V^LV&9>Hu9uVT*?FG4h{8)m8y+d;S_@#ZbhnQ1KF@f9P)+L8X|1(BkH|o5VPtWWxdJJ&FTavIS6BTm6*qc>G$26cgAz`!s&@yjz0OO$b+wV!Jww^1-- zNA9HBs3DP)R*;$LN-}blzoI}Na@RqRsxfqu%1Fg}0(PNg;I1SMCZrVeV*Y>vY^aq~ zwkonfN&|Yp@HQCQI@)G|Nab~ia%{AD=XMqg8zC@3Ee7Cjaxu4H8n_FnC)w^K{fG>d z?C^f-?>MS=z~mijfQg%2fgf=ULCi9qg@y$=uL_eiluGaHky-#c%E%h)j*{6(*(|qW z?4*wf9G46oXb@CGLm}io z&I_DjyM+`J$Bk>aX+s?;CQJrxn7Qw9N(#)|MM+oV*8V(VTX0ne1dN8*>7Wum8?H0} zM-it6(il-UhvgaI)>vydkpF$y!Fd^*_z8?iq;tpx*s^^FK4-{AVqy{29}t8H@|Fau z`s%@Jk)F`>Ym1;E<)p7b9S|3!IGAy1Yw+&aglajq_cS*gh#7xam^7AEs8);cfK#cSU6V}%9y`9ZPpdUKgn=G<2zgehP0>E+`L^Oam3%Wv?zvG=F_(dx z!$%+or+;^ZB79}(Ztz2m=3`{UChy7ON}mOn(A2!QC!)jBJYFk9o

    (j4gJ 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

    wV)d9t|Y?;P@Gl9Y~4u*kZEyLr+C!gO39 z(D+bY8LSRO!%$(F3PKVm=sJ0VjTOm>0}n9{f*@1|wwJ0@Ll)3t-7H=|@xkhj&Z^TK z3=U~5y==4>T3eF$kqi6aGytzrsre;6-nqEi$d3Y6PuxS!vt$+rD#b7WvH%0DVz#?Z z0)r7wVPS-Yy_c;{jMd|~_>l=Fo#=o_A=JFZS(L2_w=*o3ZulR-Q1l4WQ#Z)c1Vjj$l@m8vQdsMwPL#CbSNdly1 z?3pRfiM<5ksuX(dR`k<^sm~YcID4A=!;83etLN#HEqLd7v!T$ zBelyUV!FFb++}crO(?vo4v~0fFBAKi9u_X+)PDq}%vquuinOpO8(reM+7Y&3g~ad) zh(>EZH}K-FO=lTs90%1`AWY|j4=+6?cH_lV2*raLKBr}NK8hSG$DhHKWL*hOifHawrrYuE@VeKXkIODX-Do+JzPrTN_ zLexd{F+0GI$m@yJuUyGWrfnqiM*7DMJu_Ow+B87{ZM$W{x58lw_9}>Oc-6wgssM>p zG&w4~4yNnR9%|lL?8L*cOTvvw0c2$8=D3I*)%E@p!Ro2y$n@kSW4x-bEX$H#LSNS! zn&-z2ScD`XExu|j%5m@IE#!oDgHWlztmAe;^MlrzVqBoQ#Xr$71sAZc=>SH@nlD8} z14)GYC5e+wirYY7NQ$MIn%K#$r(sO~vdWCkij`>uz-ZzTWEgOApU3CYQ z9^%ZAl=7oy1>6CZh_y?gxzVypcErSpBFa)SPGk6iV{}l&gR*92sI(~TrEug92Z@ld zT8D{c+#IHMl|l*6{P2cH*d-jlh%G{QfT(Nt1#gBV+c_cKyu|z~v0cc!z6HGx5889; z^yd;8Z0F%AQXH|EtlNy4nkgN}EPicB%Mlm~ZI0SO`50N_y15bZ!>XQ;bchg-6Ijl} zddneFlPMjdXhrIV2*tia=7j4$Pj}o|8IagbF)s(IkS;?%Bv)F!K;|E4xSMwP=(c?2 zu9WBnCnwGv_pWKJR;&Gl#Qu$#!M>`D+`2ge%tme@Cz`zn8yh{0$pxP(xu5t`D*z|olRa%nB%cGdg$t<;a-j&fn$w}28qXVvr zlF#5d6P=r$TYg9(r&e_ghNVo@FzezahB<^=7E5d!#pxzUf+MGwg`0ALQV27Z5Yht1 zDUam_V`Ti_|7ZVQJbLu^uwnkVPs#Z~C)2iX&BYvW3ES8y`@oWR&`rnK`=CwOU7j(t zqct)OZ1Uy?2D&Et9O=Ih;hvfzqEb57ag(@Ky|60wsbe^0hX&Rra%{J-QF<-x-^LwR-A{RdOK9?czkFx+?l!M?t^ z(SsR2-N&b~gV|?Cvnxll`~7`a`{u6qeK*_p?ZfLwK0R>i)TPVE@AqXRhYz1Pab)oF zU>}c4-plq5)Us0p=c+hocRPau}x~`C%BRBC{_5YPR~_?b@~7*^z;>N6zj$ImS;T z_UZW1qa!1Lz{8W*hqHl^?ATebdOr$l)^=PaN8J z>d?UOdA3(QgzpFUog6rHo>lKxt6x;l9LuUxSF+hlm$T1?&RzWW=EaGz{tLKm>)Z`R z`Rw7V{llO1W#@d*N)D9k=s zV67F-aK6pKPFZlcW1IO?pIhSX=Iv8Vo=tOg(q{(`OH?^=BFQ7=0tB0Wxajtm{qS-c zhL&KBFULIvmgyiaUSaSyaRyNGQHEoZ$#KSd1yf~3jxr9>nP6jX2j;|i;Q+eBdP7zk zN0^AaKmBRy)zX`b>Al)+;F1^|;Bi+)i8F;3ge0BjrZ+M%AmC>)M!mMD{(^YmZn5Nq zWT1^G>du5yKZ~Zn#0>4Uv7Aau^C(9k>8H7wtW3@H?5!QRPmECQ3a(jU*IASO6Iuu;96#6sc6s zRff>rp&Cv+t-X2bU>YDy)_DK-LzY1lZVQ~X3k@smnxmBDE`aE8l9j-F!-I2v)#bbo z-PQGppOT;QDgYl|8Y2MKK%!(_t{Gu9QAMpXO}7@4R;UXK9gI84hS7mZ*DII3Snis5 zE_b&)FCH)k9k3<@&4hRK61k`+6*ZfM6s}X2uYFV;c4QLQur9$Q{fs|(Qhj~{#`W`C z{O86^{0phXf#Bz(DV38ZUAK+m$r%3O6&5>f%o7q;)_e&o8t0~yBGY9(g zlaoXF?=RH8s9lO5$N}f^`pWt%cY6!FCZsDoy>atO4YvqJ)o)Qhd{#lC-b=V$@N>M$ zokokeK^7y`d0Q01SaJp?*R}2fk_9}6XfnyQtp#QI(S~<5kioAc5nmt5BRO?*)de=% zf-hgsU}6C8;T$Wtm>enckrOhtpcOhUN&po{yu$)t0-Ocpn}?3ml@`y&E<&*)*gujY zOWpcgqWgR$cDQQTdGyzTS1#1O6x>+RT9*r0X#M|CULF# z>n*tKvTE*n?AE#yW`dD(`gDL$9l4*Bsbqv1zjoar7#|c&LQ4t2AZ`mVYLC?t__=q% ziBr1W4$Uc9)Mk9lPgt9GKo1V6Z9B|31{;ykVHfu41<-Z));j={pau`oEy;~rU@0wt zZ?;~((j!S$&c-z_(xN0`B={L_dkGGDKN4ea3PhqTjtUA>4b~cRQ*rTL6*2Oqr(V@J zLWFJ)I;~jUr{{8fo10I(l1vqFs->Oi6J;k==FNz?|E&bFAcw_1=ml;&6j0(S)D79? zd%$(7zJ@d%E+R$uFro=kPhD1e!kN>dt}VGwmeVi(@*7cX(#0MoiFS{58}e&85CJH z(6a0N<(FZUI!+$Z*vd*`w32SMvKib)rIV?V!Ek{9;_i+>7@J^Y4i7cmB>A(~pdDB| ze=m{~lKiOWImexclsOegLAp#h?6bp6&SQIzeZY=o=xcSJMno_tRdAY?5r?6IcwaGQ zaVbX%P9w>{`aw3S`ErH||1f~XKM(a&T*C8|jfja;<9-58=~1?|p$0_cYGp*X zM}p6p(J%@Bmx(i>hvQu05a=Pi>p?lZE#RYyz(I=kL2@Wp8MYAe^E@uG8W7g*CFmLBIek&HB*xCtCnxk^g1 zm^6Ijh_1}#zC~MiU^@rN??rCYV&b+>)v=mwUJn4chGj+~l7w7xlr<>Im*9g4Pa-E| zQ&&t_Rl3YxZmH`x@yr?h!@Dr}2R>NI%zIZDtPYkMC#anqJ z2Rtr_#$bcEMv@o)ZV!jsEHIAT3Y+zlbUj%3%dQPqh`w>Va@b`>lO?F!?;_e8ehEX% zk-&Rak{t$kQ?R-1fpYoOdFh?bVTHX7BzZ-3{-m>{5k?2y(7}9b_=UlO2)n_EtORsS zGk(#0^e5V|I051Y0=J$!>!6(*lo@6u?U5J%%n$#=?vq zAD|{1_n>hZB&;Poc)$r?a3}~kNz!|%KUyBGquRjKK&ah8ZhK$_afu7_252Rt?*u(0 zaC3r=C!Gf$d4m1uC+tNJsULrQ4uc=ih)114a>n!GOztdQ(jlZ!e~TerUg1W>8k9{u zGRR=@dL6!`Dr{570**0sIuFl7ESwEdr$9%}7NJ@(-mNgg7F_0LkB;?4J$Q3DqIvL@ zyiF2}fNPj;;~VB6l}Zaw!vZM^QteU=l+=Y&FC{m2U?UWo?MbAp2!mkMDz+fbL84~1 zLBOuv!bxORpB5(2*mx-;Up{1Bx&s;%aSt#cgE{XZVS# z^N%Q3o4znT;Xt8!;LKbU)Eq%`Ck6*`tsxMvF(lCP`GYtSb43^AkrMnF#N0T!^hfxx z*EXwBeZ;p07LVu)6I2^Ps74IgabqD^M2kOhpc`v1(e?4l#ix~d z1sZNbdK*k2I0YqQL8Aps>ZM!9VrIp*lH0U;YB5VRW#33vN27_T3GP)y0g*){f_YGU zrv}4L5Y$2U9Y}H0l$kMhu$;Rhr=t785fe(i@VC;_Db^LO5I5arR3YTL*PUzthmCU| zs5IqOqc|%>Q&y5nHlM_?M3KCTSBN(_XbLXSw?jb)Hj4!}RH0l>X3b#irA{|lW1|Af z%{0PM9UA8x(`mpvV_&SXJzopS+-cYtnFSn`M(huHE0<@S*+3 zE}qB+j`d}SGGv^;bmDR~J6G+?9-g^&K07&nBpW_)ueLk;^uSm9PYn!S#GkKsBl-P} z+Rf}LUw-w??(D=j)4Q{)ec6RCvi^bofo$KA>{NFB}T?zz61*(+b2&!!Ic-F@)sxr=AceBF0=S9ZVe?ss#afARH~-}Yx; zW?v2y!_(E-fs0ow`-Z*Z1hFaIpg~1KIeIY1zL=ZCPf)>}a>PHV}QV$jgfH^(B*B zaM8kG5kk8?e`mbC`3C#xD@|B<5_62TzlK(zE#zLO>B_nK!OYb3?EJJKQrok~#Y;J& zFXAR!bOc_4iSW?{SNYO!6Q-3LH%NtR8=YaovnbRq#A?~Q$Vvr?*7eF1hLF@XfdDDB zio*|0!ogB>{*~=Q`G`YvXkG2*u?LL@x8Z7@yluHFTpbV6+0!Z1F9?WqiR0%Aq=K z+vL5#6$tML!QmxTK~A>j8hjZ|93{&Ir<|+I$W1hGLhzK#DOzTx``b3j$;7N$fX4)_TU7z>6ox z>}1Mv49(7pByKcDC@Bd2aAWnNvH4S@vE~6nHbJ@qP0>?^m~&iZM@F1W%{3&B;+;h4 z;?RzC73Pz&S-;D4t}BGXw4eH5Wq2!+?MUxk+Sjb4`lKn~|i2G2T&Cc>-yrSU7*xM&FLWzCv_@AX^uLH3PtqC^h)Kh}U#$&Y;<6BivKfl0I&I%Y z!c(;tYoUg8hx0~5lfp^1BfVKDuoy?y-RXfr#a@G+?9xGy(<_)@9H@4EnRgMb>Wv5z z+CYR>!MJO3XjRg)aeQ!tr|V6P#b+VfZa+BcLg5|uAE4Z;p|U&i7;XE+^>eR-yM~^$ z0u<*+!FZGaNjxL*`+NuBtH@t?6`Cq3Ec7tP1_oqinZ$8Ijx6+uV<0c52B=f=dU<=(+;3k zL!+^-msqGu!A#PAv$ja*-YOHP;qQ72^A)0)RUfF&Q`M%=XW?~O&A1eCyk2kEqok+d zZHb)ag)$~vNpb0qiKS7{?|c^|q%bXEHgY>V#do%J|8o@=DgYN!&^hlz=dtQGFz-#M zh@>AQ?ua4tYk4E{4GltCj{h7)o@45nIE<%hf`UxD zZ7s(Rp{m|b%5a;oK@r}%JqjUh3cO&w`dVS1BA%rSI7KNW{!|9$hg1cG?X8!h@S1dr zRWH&@Bl9s`0J+fDShT}D;5U=J=Qj=k^&{`0nsy@_I4=jT@^Qu#Ep`q&*udFLHh9!5JoynWP>4Cu zaE_A>g&~uPMoI@-!vM0FQ=-owYFWK}Sif7Blzgt`Zbp_Pdsr_8(!W*1N<6GoKr2nr zO&bvxa8z*TeZk6mS^*K6M7$jmCOOWh&<8g?LpGGV;><-QAU!jaf>C`qDNJpOwv9XN z2i!^ZJ0u+fthY@$w8Ml$sZfWWx->=kj6*?0ie)w5ka4Z(zIlkNII}y^1P3ZM;XuM| zj_@>C)&@G&#IUziSTR71GyT4}*FjZY8`onYX@-*`*GxMvL&lHWh(Z+l8uiZSHpc!wp!xfA@H&gLcWjb-uN#uO+ zVgr_db3Vs{IjDo0tO1Rn;@owPEw>msn}}5AJGT(& zPkwBXEOB5M*)s1^rjiZ5W7$XG7DF2r2~2#Pd4*Nq{71JMph*LDEHO>IG)b(J5_fsz zg)Ew=bXn=y6sLPh)$p`ndAqcMX|bKg(sisY2BNq9VuGo4r2*?Zyi6+Uj%HNp!G9ob z?apSq_eU2<+A+UA1~*fO!QI(+*KVKOSHZjecymq4pGAfH*=+XR+>E{Z z@@h80Y$^=kiFrZD;PDnMQ6yY}_St!wuH^z#eZ-r-Z%&^R#LKBy7g``h|&=<_o##-b`KWLrsK_&z71S*igm=snXuR9fC?KY^8tk=d_j1WFyz> z^muX`+ih~Y4R+E^sMT!gwmNljvlVv3lY%U*#Q=)hd=dt*(NkS3MrjE(L(C?&IFV?H z4jk+XLcTYd)&csv4#RAv@e;RR6f%C?Rj)3F?T!O|V*$74YR)GAO!vTic9AxZ?9dyG zdUt{4{2Oe*txjX{vH9l40!+bHEmR$=_|Fna70d2I<)@AMdNnTZag{h4zV_9tt{X)q za97fK-ta}CNaVVYsxC-DwJq42*io^=fmn>nD244kL8SguUCdacmcj6~uVWfEKul|y z)2o`RO`4qt19WNHt60~enzkg>d=qhNg~mE{cmZ)o)hDJCu|d4te2vp8J@-|rYqgRd zdh!}|Sz2%|H0XOMWX*NcSL@gi@Nd*tZ{&IFmh6OA)qIy}%oEEEtY&PMcY09zL38Z~ z`l2NV7)A^u?~(I(aj&B4VMT;T)-VLcw0;sOSPXph%HGqf( z#rjs?sRsg&Fe{ZBJJXSqx^yUp5&9NC-E6UA7WbI%UPWj@SuVUmkO?$HZ0G3{8gEwK zz4VqY2}?j#tE^U7w6IG+c+M<^y=?ed<2)(3t15Jw)qMyL=V(2dv0p7xomVWyLa^-L*#B@TA#Rx*?j_k$6=NXoY?&c zGd}+8yL0GZ_Qi=)qr=0e`eu;W>`F3$v^N%`$vFC$o0tE%49u@%hIxemnu(3}*5)Qc zz-oxW8(%~Upaz~pzb{STfy_rM@TJyT8<^=)uO~Zz1*PhL^*{e*nE=iL5W4`jE!-YV zMwUD#TP!_Ws&Cdmh|NISzkhS#E}#nU_huBZxYz~!aBHl>KLu+bH7dMmAZ4AZ_ErI( zZf_7sbAKVWfb|ujs#Tl+;S+pB<>KdmrD@*EVGUQbIF||e7g0v$lssfC*>Y37E7=92 z8f#eoVM3QvJi2IeV{8dSO5*FeV$>Rfj4(s4mcHm{FTn_2Xs$NUFb+^nE;4qmv6OE< zc~t;)$6zEN%J7N6bjNDx&02l6xp<2?>>fn5s=ldB;9O?7+xgD}^l>72td8 zyOx72#mk{PQ#2v%!xkK`xL>q{wBc0&QI8Kt$Cc|q+Vph+lwp-8t*g~DX?=zA&c~#6 zMSCP|QoJ0xbppPrrPiu)t4cYRcWY(`^8r91Jd^+26xGV_HJH##G>4089WOEhhV_sq z0RI++Ki@Lb5Uol7e(u_Csg>>Pc5Bg0|L-B{S7~kHkP4c7jJ{N#Q2ZrR5z{wq!hTx9 z+6EfP^+zToSiru96=r@l_YT>tHgAZ14iL9)Rs9P%BiGtkQLm~Kvhr-9<&mhCEQV(0 zuqpC`VD|^fh_1_$j%1N^=DIwYUPClL*3RgGeYjcK+FZVBqg7m=utVBNARX;Tt$p2p zDh{A=knhPYEMep>0yZf>d zf-7qVEoer(S-TjL*csq!#V7{h_pbxcGJLf{M?&cQ<*1QZ(;BC6DHG643ZrA!RmEXGip>{9LTkln6iu^gI z7HyDY<1rJ4UL;r@3@cmhSMjpFsAYzQuh?`qEKYlYujVlYW>)VL>GaSavdUon%f4`X0tL#*-uI zk@VwOHnv4}b|d^&KfbAK&fXzOY zb%crFgq48um2Oq6NP!xn(3p$DH(ObPx5SwpR!t(}JhVV!DOzrE2;jvP91Qc8kOO8< z9fAJof3r&{L+P7z@?FXH-o}33EgXzJad`O1$JKqG9@>-bJ&Mn} zZ)bZ?9v(h<CI+1@Ffq&*Ku;0;_60SM;-x&I)(U+B>> zxQxYwIO_g^pFX%x@L5}Sj-}!d7tvb)oPi0tiO0xzT(;2s5t|{5xcM5`ZAzkOd{LDc(ZV%bP=|guBWwp(&CP*S=ydl*OJama zVuy)a@Kt$NfW{UD&{4{I{pdrAIBz7QB$u)4mLlp)9(aur6@XJZJe!k;Sa zrdi|{`NGX`R9RgDllVF|K3?;|uVwB$vyER)^8fk&{a35!En}j#wR%eI8Kr!8)8TER zr|yD%)GnE}D5w(iMqjCT-|_ED1Q2@EUF3vNs~l)ql{zcL^(Qev>|w$7D31^;SR!{M zC^IoXiZ+>V!;&1z9hVd$XE`zqO&(G!(UPTY1PxA5RvEdyB+oBwF-aT|8)vTh0(KTM zcE>yYgIShZjZ4n(31^y%NGe(mA>eEnGX3z5(DHM=Y=`=99YWhg3m1th^z(TmKOnZ` zDM6GUT*%J06r~;as}NI+O1e(@f#}Ht#}Y-W;QNiH@az`;##1xC7v{UfTxq<<4imRQ z;#%%up{mS%`c|g3vTFLGP}N#ppz|Gjy?(xTo8*3n9{k6jGQY9ajH*=b6lt+wEyQ!T zuYzu-yY&iF%KAc()e^YY12yE>jdlxH&dtABebGYRDGpGcj^#xPq%qU5taJ&LI~OYe z&e>hTWKPFT?BpUHomxhPI0IP!-on+0g941x@5S-wWak0#m?;) z9ko%l(k2U(#t`PhHGhPP2d~MESzOfPunjkC`Iy0&R690Z@)7f|ME-Z*C`!tqQ@$&; zc(nlqi(OCwKL*~kAl;Zw1*Aoq)w-X20cPIX#O`_6OUC&V_qb4XL9`7nPxQ4?sq$~i zMaj<&0tUAnfCOxsK>Rx&+r;bdP@u@6COEw>oTCaake`lvh|O}=(ZP^V#F~58VZ|Ro zS!!-{0%ETmj9>OF1p`0(?(XE=@AhZ+FaPckZhigTrR;9?cc=BAy{EFhHTi!G?$G<$ z-UsqOKI8w-;ZS8L@dbHBJGrh?o7M z(A%UY&AGTnlStiQacgw11f3G?ZFAa=JUCb$N~}tYSm{QJIBjLN=^3Nq>l_ zFo8rz$NtkJf1&EKR-1sTNVbFg#u4eKufh%wpP6GTp4p<9b3bm3Hs>025(d*U@|wsA ze>pAYNRK2I(6Gr~N8tpSH(0v)EYc%k=E11UnP1nAu3`Nt=>wP+fXCJt+_sFYpg_Pj zv&EIL*y7n^rXLdDK;#@Y4d5}_{t#F}raFP({zBncRiU8q6=&Y#0RFlr?}9LZ0q0kR_Jup zigf4QS|W?PbMW;%t3UDdv;9O}-qT-IN9K+uQc_5UAMd(a^0Gk(m*m+^Hx-@rESriR zy2A2b-LSgCI?r^+lmyxi$*>~`nh{(tND{E($4_sA8m*BJf*JuUYW!4!+An*)uvzVR z_UX{4+2!eP_I@sF1;k=tZva~a$FjYHSR8+Du+Z?;A& zBXK3ZedeY^s1b7boFp<}FtzUVR-^(a59XynfrYs{bJfisTPr^xE^G8Ubb%z9slM9W zTyJB`=Oymx!NE2p*PbB!ah`6QXfORR(QLQ38tsWoSFe74Vbmg|ra5X;ge{X;_*#2r z$5n`v%Mzi9n>Sl6WYe^(4h484&1-SD_QdFO7AXuPN| zEe9;_G=4;;erBbhH&e3vzu0Q)MTT!ZF1Np*|ChaDgT?|jv#_*eqO(-u!hK-kw`J6+ zdovI2^oWTx98h`e$gzYo3M;Ke>^4YNsMaDJdha$^ccv%rJh1A_u(1Ps>|ti|>ft+{0c`Ypn*nWad_j<=xt!{@a=Pg&r}G_5uzR zDa2-ilXZ9Rt@-Be%7y!CPt>+e@A>~7asSD&f4Zij17`V zH^C?-L+^^l?f;q zmDg>oV83Jqw-PRcL39^S0{Pxij33O+J?fD-E3KC0&Y;oc@#0}OnWf(mlZSU_9!&R$ z$|`OAG8$po@vdk*n3?T$;#sA0CZHjDO?Ft`j}19H`EYt+ZtlU{EKNypAb)x=D2W0v zpb?uxZj;yQR_KFSMwXO!%r3tqmeo6=F?VPB_dT-B8dd^729h{5 zh#bwk_ayAIbJMfE&Wvj|)Ep=v`?u{kPLoJrk#a))VT$rHfld zuo_xKPM-RYxB-j&^R75OnCex&)>PqF^=7Yy`cYD<{8?EI?&A0^|u5Dxpz&p4==65hk?R1!&7@0HX9r1WP zb+5mrtVLF7&P*U zV#mqXY(K%W0vT`ND4v(24o@pzeHFhRK{vNvk38jxPoK!bHKi_AcNlaJ4*B9t@WcB0 z4c&tutEekB^3F2KE&rB*aMsNA$}{X}Y`qq2tD_8X8(FO{w%Q|j^RT`+Hy^+GsfqkA zKgqj4=tuwd7mOJ;@Z|o8irs81FU3D?T;f z6Lp=Xk6NqAcX1#kPsE**K7nf`c_8kM^a(r+xd&M4r%#YtHR^Md3*qDmSD?uQSqG+1 z$o|QbXf>2RrwU7-aCwk>0`olo1XgnH5vrXXI)b`< zrAw*SsubzcGm%X}sSAxnT&2)wog1Tblw~e;0VG1rLRY&0!ssDO`K?OVB9MG(>{4fh znk|;-LLN~M0;S8SQey}v$%R#=yI3VB2^e?L4M`^BWA?ieyy3}O^ z-8xI4btTp2rbzImE__90NAz@d7P{1> z^E4R+P-hOHI%koK7?F^QCD=FJm3k=GAr&My#>KQ@8(ny8XG*=B3jNb4^^0Bj0^5)> z2wkN9Po&hZb>YQ0$*|u|uJXcWAAD)@7vss@TDBUHC0k?ElGqiL5?-B^&zo!2ayS`8(N> z^LMjP@OucKPvZ9|J`bP2mz_I*JKK-X{5^>01Nh7Lhw=B5^IzlH-K>i5$K?H8)EoT5 zf2rW%5dh)ePw{&azo+nf2+xk4e;`0As7!$S@jHxn1NeJD$`GkL*=OGzN0Pg1$Bv!+ z53(cu`}gMR{{D}$vxl?2hqAp$n}`4L0blXq zX!KB@Xqivttv*4qldhtFqHq+#aR<|b^`H*_2^+4)o%5*04?UXb$9wGY`NF|mOcZv~ zOX3ouNcg{}ZhTLvo66?lM5ehZYob-1w_PKJZa7;_>#U#I$yg2eqWjJ2<0dC&CQFl1n`bUKeSh z(?uQSrRhNFc>F8DAkOI=-R{v}{Gah2w!`(&@J*o)|cQ7o@o&AgMJjOozvc`3@ z&7A@QD{Jy+>;mwox7Mw2_bkwsXHF7rhvU<9VU6i&qr=(pY$&UJ`3Yz zqoc~vQCmOAxo71n)iuQpM?Dq=p_SuA*z#U$;NEzg7r~Wz$lSrRK~S>@-L30+77d)> zd8Y}fGK)YVO^zTbNp)iw_xZLf&t)EHww@!>4EJ;+5p#Q$p_4fAC|4iW5fY5eEoyK^ z6}1IiOa70fsxORhi#9;mTXcUHwveC&2tXqC_#|UuCsGmR#~jC@ha^G zPN6jrGgW!=T-Dt3r?{XS-;mpi9~n=DZvl&GIVJl%cg)nYVw!SPv_Dy?Gs1-YwDRF` zWjn&NJH`-u!8m35;W1=8B`Iw^4JRRZdSfyIYZ*%4T;IZ(Jn|%m*~BMJ1WZ0E=DPJD zziA*X61iUGxWXvE5b(&#fp2D*k5pqtaY%ld}#k(Nuc?0V#b^my)b1X{=a%R(45&hA;ZTO8}!_<{8D6^bq9 z6XW{k<{hm%0%KQ&nCs|0FQF=xzXjlf6Y{vpd}WIVc96C=FN&T9Pfh+*G;@OdxWUoK z-Lg9Rl6Dai4MoiiXPiKnaXuM4=gR%9P#S+JIfU={ws&Felr%)b`azYpu1_#>BzXM9Q;1 zu*&#w1XBPeD5Npr!8o0$*3uz}^pF~QmOmSZaMzhGt*vPWq4CUqoCiP*f{Gn2KLlWa zKGtOpHq-p0hnrg)Yf5v)!DOd0v#bor9Nf!@J8zFcue-)re_1Z2>)I|eGg^x^Nku{G zfxc8}^SS)FHH6YWyF2&&>>W9S&ldDPb@1Z~ZfS0=f$y42M9)m!sHY{Vojvf)*>E$VnfK37q=`CLf|f+&{LytjUx@>6qpd{Od#rYnRAFjlam2YGHx0} zBd0vfGF+euBWqOE#2)A^H;@Y(NCKMI8Hz)tzP{cNybMTltJa0U=@Dk&0-g;xt<4s0vzRS%mqtewSp1ABB;mO=~>E{6S zvjT*C59!pNMu;q%P=}d$OCx;IP3}ACEq$!iaP@2gD!reUegk~1<+r5y-Q&?_ouo#O z7-U4E+&syO=tcBo^iPAmL{+oa0!L)|OauqSHm_7ff{+Di#he*+Rn=9x(<@jk;s!Gk zKRHF8)evdbNe3psg(ilo<~1rCQ%14Ve0kU5(FeZTk zwY+bIXRx$Z+k@6&N)3=_%PH)0wSi$Ep6>v&zOD=QL!J6?P-gz^ zU^;??>_A==6D)H)VN2b{8w(AxaXU8uWI!M4)Z0;*S*PB2WWs}0sGM?Z{3~Wt$wMe7Uf=$by_n89x3L-c6 zXm@7|5PCPZ*DjrCq5t;CPPNyF@hxNheKX=RVC6w)`jcL&t@m1T<|q2`#lY@9oNZgR z6^Of^`>^JvntsOLpRsZEAO4%UClAl-d{BCi?#jD#WMOgc%!j=vN@G0>XG=pp3m?dz z>nBR*dS*X9Tbk`HP4rCmOx+neSDKsuWMT1q>E_&*lV?j`%=RqKRKDz)>mMu49h2X) zxW{|;RB5)-v+!BZ{Po4s+$H%nTbjFYwel4}v&aMGBB&@prX0DdA8e1tL2%|Mp*hqg!YP-um)UMG*(I7Fof%9qWTFEN8H` zfqzoArih$X-9sMGPpec&K9EU|G!l902E^@tse_MX#Q1(VKf)j)3+(pK5_=8BL?((- ze>(g%&#>iGrz=jVgS?dnPpNsn&o##`aw;jUTPJ1sDev-JC`2qm@9(Me@@4iFWyZ0Y!djN=DlSF z5Ecx;e@q2?JAG2rRIsuOuPOPdY!9)HhC@fLiDO5m6Zjz^<@*myLLKZGf%7Fb%~nQj5D12tjKw z4G?Z5{oGxyt%19$n<1aKQ`fFvo>&4x}Efyz$((**jPu%1^=KAtF7dbD@q~> z6MoI&QnWCI;wZxu+6GUhcnj&~IkY5<=F*E<(TpF~YR_ov-et}#RAPzC;6evPJnp_0 zmU-#w5|%KVJ6mPC7Mh)QpCA2@`Tv6>bMp(g-}-mQ{)`y?_dj~?)bTg}{MP%WlUemF z?0N5?98WgS#i4<*fzeBdIAe{!zlUf5*1iAf|BW&IC~Z~Nk|{FbaVyUgg!(1bee7QD zHn0P_xLE@+!YCH=vwUym_QKLK(-jDeNoE}nu~QRC857eqx@|8qf&D54sf64f6Yx$$J(w2i!5@0yJ1&o}8IM z7!oek+D-cLGIDK~*b;#Id_h~lj}kHH|LXo`IlHJZZlGf)4!o0fP)Niy^b5=?I7k6(}+mSUB{Q!TN`eO-tmQmxoHz6@G?+h#6DRpxVY}U3PV=a1JGLz2|Jkl+jR1$eW zz9a%ZjYshu7OC5~H-Ei$Z@a!%-ou=r7w6B%i$;Ob($M+jw4!&7t{81m+;o#1_|#O; zPkI%bx@o%ItT}ppT$^iP#f|G{em?p>3!zU+GjD!8Hd^|8x^(wX7cYMP#l_Lzl|E1r zL=~pw#kU8RLQto0pI#gs81e+slLnpyaMI|%{68^ibooM3ra-bra(icU>oLr)VsZua zk`XN(kSjV%`@8i^_`eNbPI+j)#1Q$$SaNjk?a(Jh)8c9f`Z=+W_f{ZH$VPlfzbTO} zH=r;*4}gl$=OW}5z_I#k)abh(H*zIU)KaFfT`()st_cyl7bLYlsh}T4959Iq@kx0t zve}P)RJz`qp0!zRuyeeE3n1$?$j&6_o;-;YfLzm8+wlXEejuy>XAA;pbRmJ{rsjA^ zJPpZDbk`Tqm+)(AxLt99!{L;}Ik0RVCJtQa#NGrcT)RUYw!Oc(>5`M=2`asB%Y2J2 z>aNsRCOwy8rpFk1pr4)?U#&%aVQ zW2Vrx25Zj?Fqe!8ar_c>r|R53V9Pn4!80!q(@3bb3UK1fxux z=`B^%wy)e;o1QM!9#?+w$i~z!L;}@_f$-gd!d5AQ!(JCfjwATEDb1SfrZY8#vMboz zawHh^U~gxpv4dxNhQw#0^AMSG7T-V__nf!^FTuns_4|@)%x{G@*N#$z0fOt36}ayB zfMsp>`pQkq$VdIugr5DOLzn^+WSJcEm=8nIHI)Ya-%JRdOwShUA=K#+eVp5$&)q*S?K=K8vW>hdhdz$?Oa2`ZY|GGt= zC_Jx}Uj=uDXczN^RSo~!FY}A;BUD;6+Wkpy&dlq2R?o;VsgeY@z$L4&AEv2jzpcRV zg>r?83G{!H`OBfCU)~=*Z&~Uwc4CP~jS)e^yU&+|vL0AT=q%D^jj$c*^@={xT6bDe zdix|#N1u2d&33W>33WyV40i{ZxPIqC^4FU8JV)TZ5RH@dtMKfisWzK_#5ynS0U!43Ld&9Mh0$*4fY%@qOB>TQRPY z2{b$8i>jH>1g`=*7XsT1k^(QB8CgL~RkqT1U04E7ycxe0SRASFAOGRrTPb?__#D*I(F>+QvZ#<(v9;AM@mCyE*~ik-0UwMf2#*B z=TiT>Lw_h8J5o9~QF`~}Oi$@;6#7KhGjIdaN{ttOB-On2*?~8L;2*_V6^Il#qJ{ga+S=!NPR9xOU6kGN6*#xESN;%yD9YPSin-Z^5;rM@m4})B!q{ao@Jnz~sU+PDt9Mef{`2SQt^^89B1> zof`bGT=#2;f*=>%gS{QmGY|CDThA`p_y13OoG_z z5MZXu>;Q;w2#w0Sghj8h0h|8s$t+kT;$GRgZ5Ulz$X05s86`JVNRJTu--pe1D%%Jz$e=K4WBa<-agGI@2Y{zH9Rwh8_xmCUW>?$z!TGluwj!{Yc%Y<#gYG;)*ACao<^YMLm9Bu?ew-1I1*8bA(5$1Tog|6L z62V6xP*9(X_{fI#K%$jaUB+`}gjv~(#Z4kGg6~(TL*F8ZLS7w0ECdC=i^D}MZOV}tg!^BkOH<~yly5zA zdxiFd@jo)()wqF=XtzeML<-10(NRQvq6L@V^f?cOG8aLab?Rm+9Wn<(fog z=*BV@x;#4GU`8KYGdK{9SS|d|RCv)88Q4Q?s@Xc3l^G$Sr`p52xxmf?SI)-=uo!W( zM)sii7G%QkObhSyIHPp4jw!*!;5;%E6G#HOjG{YS$yH7S%#Glk7MkjLVDP4~1GRTV zc^cjV%prb-jN)2#%VH2wBaf;al{-zrVFb^nGyNdfEY(0Oc$;fd%oMmwGJI;G-x#-$ zJfC+!hfE2RdT)30TfLd0ibXdc${+(cxevc8myy|47mrkiT`>89@;^IAo|#F^icD?4 zLR;W#CJF)Nbk+YIw&w9xD6A1UGz1kmGJ#Du^^5ROk;y;ML@~iy6gIRt8({R1%ZzXKA!<;@V}^p2D~g&tRyx#rV+se!?Y6Wy+|VXA#oA2_ zRnunlmH8=c6mM}d9b%U0-vKP1uuw7;Pzq0yXGf^-&&-^3NJmV_BKpz+NYHs@<5qr*vmNPB7zIR(@%~;efRgJe^7di~`NZB$D5YOS8Nw&(4&Wuh}V9=OZymnN)~Z z5n-LvxU`}4Oohvn<=OI5yvAiXLctEMZ&aluwyv{s_g-awvLa%!N!_r6=<>95?It<6k-6N-Dt z4a3t3l?t0DS>Gp0C*P>l0=@ANF0I-RRSGsut_%$EdK`8cx!1_NfrAWkPpm&!BhU5z zJ4ED}bvQ1%lW74kS!W1Ueh$quu(SL45_^}228Q{^z{cLz<|p;_;VW0iMn|tAZjYK! zQ|7+(h_)4I#LYx1eb6U7~SPnIVe_={sTn=d6W?d5H7vJ!&Ntu-qXDbpKwE%0V*ifI+1Nkv9}h%#oRF?Fuc>GUfp(z zeq!|6%EjK8c)n77+#jnZ3cf62CWJS1lVTs!1!W)R8sSKTE1eC?oSt}Y7}?Tn%2gsQ zXJnA4GITzPNu6Ni3CE;h!hIKL7J#_9HAF9PckQ|1tqa40gTvR*aSxAC60`?vfq0Su zI@STuqSp)00^=DHbBo_+Ll_>Yte+g1WuZxnZ8E8>TU9Z)iRmhjpz#Lp( ze-2SzUvnCjSI4A!h=M%&1@NzkeAUPasFz0cRHDwv?(;}jM4^mXw%*JFieXZ8Z0Vdt zndJyF+Ho;qgZKXtnV>{OQyG;!Q`Xurh@`#|GU*>r-q-~mEIIJ(I^@lLfRHJ`UDdw- z0$jI9jsRN9iF!%!*4oalS{-te9r)1rW}N;sfsZ3J?m13QJVfA*)DFMpCXQuHg9m9*Nw*tXmg*cPX#e71qj^Lf zD?Xl??L!<5_vwJ+fxpZfjiGACjZUhY>55si32kJ?)_7Epv*`PrMNifkZYMEy;_K&u zz8FIUD?%es?n^0zJ;;uzxkAQV>DYjz+eLUhITh`iW?2>m!sGJMFaLz1#a^$3c-rUO zoB?i#@lGL^1?C2}7Q2ym5hp_XwQTXgsmqn6oVqiQIGbz}a|EI1(gMrVyZiOEr*yk7-w{g2 zFg1$M#g}2$UCw$Xrzwn8Cxc$X3nhd zSl0#%?=#QvfQ2d=A7k8CVO|s{ zja_O@b$2CKt-f}N*7``Rkw&KVGt$?~wy$k##R<&yT8pZNP*sc}0}4s?HzTWv^elSm zsNtDGEGEU|XDY!d!!zTSB6XT$c(bFW4hUgqMHoyX%2v`7jx~I{WNw_P%CS<}kst$v zaBGD_nvosioAa;|vQO|STJE))fRWfsy-X#|N0RQ%&ZeOLJNs=Xq%D@zQq7=8S9Pst zlnfLIo|cnZWHy;JUu-rhIL}Um%;-uaY3W|YLbaSOs?QU9#L+D%0-VH&UcElGAImR;KT2!1d zXn+griCdIa7Aa$?5RqLx-7u+1Ot@`h6)gk`bReJPN_~&-o5E6U9rteW`TIxUwC8-? zp2G-(;U)yC5``m^V>Y1E+fxU_gV`U}38kY{!8D>5Syir0`zMc8jT2&3TiPu&Yk+Wd zYUFq(jvV2@V-z^(4by9{_L$DcGc+j;+dXItt^5X^TNYvpJqAw0T!eyAX&2A}R1a$& zK_s-!ILJai+;I-O;-?`sY8dpoF=b-oAM)&@+t{n1Hz2lP9>adyS=+;p)}wNrhTr=P ztTG)LCJQA8)PmIOs2j=P4_MRFqZgacWulA+-Rmf7`oU^bzZN>X!Mn5C>1bI#!%Fz4 z|7a5UqO_&zdi@7*tyVEWH3eoD?&DNsM|1!UU6N zmRz(2N?Mt3^2eq%6AH4c$!C`?;sns+ZAUG+Yz!MSj3XRg0h)cXD~S<8oUmrYN(4;4gw5l(@ zxS=zmY~d5MHcQu)2lHfTize%ISS^E+T5xNed3vu00-UcuN2~s1I%)%T@Se2Cr2}TnMhP;z z@>J*(6cUt&YJ3Ui1pH-JJ2=UN8Yt!Xd1{?~1~1AZYl#sdh=umqz)Z9B`RM@O3NFKP ziV{^LuFi{1+Pc`JEu=SV>tfT!L@0VJVbqu@(2V>&N_Vq48m_f62y8XMGL5Mbo5XNx zH8C~Tu;1BPHO028+a5Yh;(T>Jl34Z=(`Z9Iim^bim~IHG)3pA4^k4s(uO2yfsdV!A ziBliFS1KPrGB!W@#+8$$(-%skAH7|=&@*s${PfA;Bc)3{V<*p+P7m}S>nVM4`NZ)f zrQVyDO5-||&fI+C6i&%~a3v`%T)bR5g;Q^zo;zC_ zKT`VW;;~a#&-VW5lb+J2ZyhNm*G~6d#-X><3j?LoBj-NGi8!Qwd=;s;@p~Sr!@UE2 z&D{AUyN|1&o~E1$dm+2omPZ`?s^*M??GANMSr8o6=qi&FpKdw7HS z>>F=fmH!>P^~T(B>Qc|Zz=v-fJ9g~N;Wy~}qn^Hj5Aiwt&O7gnaLUI>xjJ}x`bg(PcL+SeQ9=yjnclXv@ z<-HG2o;-O5|37>552gN|(uMbrA3xrU|DQskw{W)aLk&894!5Nr0ZaFH9r$7?sw@@o z%{Mi1sPO;rZ;(%~XS_FgKFfFzgUkY~NhFNaEYG2tuy+l;A@`}sDsGwYuOb7Jiq7M8 zGP(3h?zQ?JeoT9_ILT$Vu;FOv{RTEI;h!`PQh(zKq8XOpJ}$Rf7ekHXs-;mpJzIUo zu2?8bTtG$kBM#=2=f8$&;Pq=@wZ9jMy<(YC2UnmeadQEJo*Uv_=6>R#r0sv+#~Yha zs!)@9@D1-A;T@^^4`IibaW`0wuph4Y5>)#4m$*TyBqo zl9U0Q8;1hz5VQSDO!t+(U1$zKR1-x33y=Q$!3^LK9WD=bAdMhC(Z3Z{P%Wx{&2`T9{8kdwDoWybx^J&C0i%^RCXeB>W zy^hOJy08tw5j5zFa-Id}Q1A>LPr!k=iRI9h;qj3SEl$iXOx^*DM>@t?X_l#N)^Ql8 zw%f^$4Gu;GCP<}Q>T7c>OFb3Xa2;c(s_dFBdFu0bCh8(#j_@qpph)717C_4v7jg^ zJgfDe?|>a%PfJSAve6`7bKL45e^bjtyb^G%lA60c;_gfZoDtLWL3;wr{HS1xm9oTOwA(>fXihIbn*gsK%viY4eE^w z$#-?~@Q`|Va0BPNS>ws*Snsh{NY7$K8^&1;J@TeQY2Re>U|?V%)0lVc!#0JBZ4uRP z#)Odj-75Tz=52VoY#CQ*h|aa@NJ9U8dUJ6pEa#Ns=qe1TUm^wbGmSspw`qqFh5Jb= z^v}9LP@By$&hv(-Io`Rt0L{q1x4pHqj<=`j*aP+9ul3sZ{Q*!5yFrJETiwL2phH#g zs<0X1C{Y(d?DOJV1I#SYq%(_q=c|a8zTd6mqBdMOu%o>F*EApKx{Ua9tNH|nmDVY4 zG)L>?EoKOda4u8dZdZmNxJ=zY}R(+ zM1`QK;=$|29-SiuTW?_bM!s!Xp{{t$8i+apW5GgXD{lfv1b{IE1w5D-S#W`FO*D_G z5n-R?(RI^mY7lU)!S9qzk(4!aB#3k^Qb#1Y518C(uYGpFD_ z7P@+!1g%i~*O*}&x(D3?@qmN3PTfxPP1Fv8$K4`pqkT3qda!7IzEnl69gho11H zy@4RH%>wO@On;Y3pI!CucOeWrLJCp+bqDWbU`n#a(f|1W#fWJ5bt0m)VM#HA&d!9a zQ43V5&1GJ4Kh=~>1Lw6#5xAMXs)1bMa^{&j36ocAck2o-(PD0umZi86O8X=ll6Nv| zySU~|OhMTb$9)FSs$2U5)S=*v>@MIA{ z3t-L2tw0~(Fif3S^w`#f+~KOAyl4~tJ{HjCb~UcZ6~y5}Tq^*}6q*!zfZE$cQ_$4( z_VGihg?m6&GDe2O|Co-bUSrpLDa1TZ9_C zRc`k7I5-4dFmaT8#S|+<+ES$r)r~5QX&Nez#tjz|#RLcqV51zTH>>=dJ5E)s!9Yh$ zs&(R)ALvn>C$fRW+>7jgHP54HN!6C^MWA_6y%++EX z8x#4y6KMlR5ZPN5pwZ2pX*=utpqXm2vAjJ@ z>`n-j@Bo<11JeL^`6Eb20zlYYj*bA5IGjt-|3WHeXNeS^u*AC5H^48w=wvey>V)WQ zBfuJ~3nn;I%Y7OflHsGoY!HDVDu?bhf!p13fF)|Jk4c*@Ss?eliwq(68xPGh%c!o4 zytOU07zSn5BsJwLC-9C{OO^oGN$iOv0P*!m7XrImQ>`Ue2KnLQO3bkgk?!o{@Piti zw-K(;&2OYX-p5-R;Blc2aHFiYcs7X+>8h4+gM#ak_c?*X2j*PW0}2Y~Eq~ow$G6WV z`{WHawd2yvi>?Lkmz+SRsT!be8c{-@Sm@I2+~%$H>gM-Vi~93>TVC zGfkKS&4~5@T|M}z7jMzwCDHps7ZT{ak#B!~klZKgMr$gIWb{=MRVqcfqlUM6kdBE# zKNP89X^2LmGh_PZ=H~(G6t2I|9r^ZwwAw&m@MiM;&hArZAYky!>8{2&c53%qC`?~aXElj4ouv`&WjkcM=g;$L;nRE0eZ_Z|7LM~4r<4i8`rfHoDn- z!|wq+7x6uvnXue$kias&3bw7{c2iodIv$rwh+CZavceOR9~lky%g_}yraJWQ8AbI$ zA#f}qPe167B$Ho_D;SQ?s}aNGM}up)RTAaZn+;a%6a@rQWoun=nDIC3HZ$rKRZ9k-$!crI}wS}g*Nj`&0g=_?jlC~GwKYst{n@hgKA1BX3!W9laK_@gx^#J+B2PY^_VgMy&k z1(@Phr8IZKKcB+cq}EXFBi{@{Z}!P2zgNYNCMhoE zJn}t6U_PU3rfchRm3QxCb(_4i?7pPe?-1$WT$u^=hxVxqoitTk1Q*J@65BByC@@6UiZmLZ=<|u%3nl#QLCv#j5*X7x7yWTVpe?n zLZ%EMKol7LN=PTsk5(#-@|98?e1uY7M2T^~tQMoMv~+v{?M2nG`XY@y5A|`gpw=Sk zXylz*;`&OSS&l*kcxvv3laP4nh|U3ZPEgvdoA255v>{KjjA*5;WNnqzS3jZiqLtiW zNG`6x%#N&k8WLjFUJ*%q%N%9nmOWH+U=T~k$?FxkBq9P|TJDN`+|-#`tq@_$bPIEn zUN>jXf~z~pf6n*_0~INBk*L5KaP#n?F2jg3S9;2F#?#X;!t17^mfQW#N?v%L-1S)q zU_gctc387~!;?s@gB|?}Ye$}wpu=G>fit7?&2wNVo9#NcQA;Kovqx<6cDW|68ylr9 z5fE5l8#W?22UUwXU>_-4Oo+zV*umipa%z&{O1_O3z+{b`RgB*uH#7;#1*|iainy*XYTfN&tGOrx8LrW=K@zQl&;^piUNbBPbN^};+Z!} zH$On|`vL*pI(?*cec?U)`Meh}=YLoF^vL;3cpm&?-KuyFZgQJOJVsJ{gScYvBK_E` zZa==*Sbs{dgySE6bHzCjaUJqAc@Xy>{^30W_u_9{UMFM2-7}y6Rt3ptBAR}?yO;1E z(Ssk4jIUIE!HY<}Ub&D=-(;~T%8#Bm#?_y+9Fc@+zH^k4c zWX5pcZi!$F)Zsn4bs0GDI&Zu@>5;ORkHBaV2}dJ0ZAz+ZRfg=G76e0zr@)NOknIC^ z>ht6gb`CiExDbiCGp)5?JBQ9|`ix$Cb1@0SR z5A16+_HY&cu24DzES7+t|7L7_bi}%EXuA`Pi<(&C)_0gH^fr64CF!grF^ax|cixT$ z7rGDwnZaon*)PE(^iuGk>8B>n;KZ@F-o$%gpZ>0N{K#Jh`%8UC78gFegMSw8p1Jwu z2bbUe$4F$Wlhg+eK7i!dq_>{O28LMiAiA=)+IYV8aK}76|G)g7F&*$a1RrSJpFd>g zwqzN8Cu|n-z5OJXHZe=!A&N;rsM2HXSbx8>zX^vpA|&DAduoJkg2Sq~*L@W`8><`) zf|m()>g%g~5!7n6LDxATDjz%Zs}!BzxPT2ce#mYQTY0PU@Cu%VG`Yg}Y-nxZGzxar zw?V_+zKQJl@=iMr_rNl!ukGVnXWnDMUWx3lG(f?4zW@?ao@1x@J-P-EPPE1z_KzE~ z>yC?U2ObZAA4~`s_m8CP7T`C~Hh860d%8}Wc(}s;0y8pgqTz-Q>XZ{FmC&wZ%OJ~3rb#!!v3UT^pNf8Yv(1~SX zJvJna;+-$gRmhBBH-@C$lpCkS;kbgCzHq5p6c zYWYIC4!mzKw;{%=r~x;%WO8E{&JR-?e6hH$p8^}bYN@kf)d;2J*jm#+#;Z`3_V3F+ zlBo3Ge0gbU;j6iY`IXywDI{J{NAHAgElnLHXBXaU4Uk4!w;<=c*l$B8@}L>ibX z(>vY(Cw9}z!?)^>H_UN;uR1mgAq=s{$w!V|P=W{uu#;4nNO`OS6_svQBNMW0$u&Nq zb~2Z5FD$L(t>6Ww)HP^{p;^mJBMW^DAr}O{v&JwUa}HW`^s~D97@@@IA<#@ z&n?b{9VOXd_deM+vDO^b!pkkL-QIjNRbHt~FD%WKS6bCX22Q)0R%Yg!*2FPfWGe9( zg4#^r$=c2q4l;=O)2yFf3uM+%jDc7+@CvdudNV2iwLCLh#-Uv^Cia>b{T8<=u^Qb@ zW|kL{t7C&hAW0nVCkswv=+bs5+NJ8qrbWqt+5n2L*M3L_@dYJ`8?8iqlVfFiW@&i^ z@_S*LxXO0rD?Zl3(u(vgRfUjD7GKmExv9%^Vep2l678DSr=9-2klep~AsPFYY~3xo zL~yx^pc_=qGc7#DYTa*!^a~q>XzgY~ox^qFOXc}nY%bcaQ^w@Im4)eP41&9F49jmS zOAAvow`Nv2(X&4FsUJCcL?)fuPeghHVm*q{p$W$B^Aba2%F9Sg0#)xGNF>RXie>s{ zf>)0#6lik~!U;+*(G`nlhk7PjklTxvPK&>2@m4^geDjJs>EtCE>EfkWv@24{Zlrh@ zJPNe^bejx81ie58!IC5yORE^7@IAcsia=%xQlH%1q1&;%3M{Mb*07_-0kpUSib7#< zHxdg+_e!6sRLvtaf1CL9dt5~!QQdTNu&lyRm=?`@beEgy5`;h2-XMMY4`odZ9@gTt z!sDGRd1c;SwZ$|VNJuHn>7F#w;c$9d1O=I)NC>hB=gNjb2A82+%Zoua_0Q|e&l>L+ zLCsPPmvC_SGh~&R=(3`OON~}(vQpl}-0jv$1F=hwWe!da^84yoj#K>7@!>JTjwccZ5N~U$t4)IhAhpBjFcVOGlOjNMd)i;ICaVYt62U{s>iMK~1jn8F zumeP7{ix_ZWq-@QGg=(ZRp9iaX!q1Hqjst2nBG)3tBtyYmB~1&YL2OYcCL_&wBGMKJt=Ak4Mk-M$7->?ovh8V3 zq>vk(0@>oeV2+ja^KGGUj9O=`cpOqI3T1Yrd81rXG&bxJbQ&RO>O89z^ zG@UAG4Rz?J2bGnpfXya)CDJle#vU0P_HV)UW;GqgSrI4O01a$+;i-@Hi}bh$d*j7< zL!KQhlE@3Ny?SpsVQ+;V=7Bqkmr~e0!m9%0U)q*^EmPKvL%gx#LkP( zb>Fo6Ip=< zbJg9o4L1p81R-p?&$;Sz_wnWacFq6V^zzF4k8w4L%U!NL+pEzP{w`?&XWW8>d0e0r zf=t!cB!!6~gNfIAlq8#*5715HbnT)00QTGmaOXbKm~%N_?t2IZ-dqll=01Qf_W@M7 z4`4~QbTbI@mUmfBscyR}UcEu6^3C*HysNJ3;;MDuE4ZQno>-UgRc#&70723U?Ab77 zdbb`xs6)5O#J-Zf^DQGgZGE)m2CB$#-SAY0aSy@b5q`Wg72;>cD__0QBc8`wI#R!^jRIG}gSiA^02> z`F5Hsja@7hzdOu-NBHlkwyk!Xh1N0BK9$)jbF(mvorp~0$ZjNY6k(qV=}#3KgSIi+ zxI)*kYh`BAvj!bd1^-=0=I~zvM=Ur7bCLRR8JE^CJ%6s%dB&BiZsXe4)-^<7Rg)j_ zAJyii1fTkmRJFp;ioBMLi9RIMtBq(I;++@C&)S98lFO2nvI=c!#lufSKPP|htM2{1 zFZpTkXNQUw={P5qf|L}&19^b0O}D5HaeiL}D5v#i-#ScL{JB7WaBS{SQiYO$2T3eX zOf0P$dgolq5dZ_>WzNpdQXc)oHF9CcxT~zZs1`sdqyddV&2eQ?)%?9VSA34UJ$K1; z+~%#CA}^@`+!-vuT*JC_9I@Fz0GjA7M5x}MAheQ|OqQYO+L z?NHdGpfk2NR>W!50fwpHaTJGRh@$$rLuGbqe60F74ZlDB+RE&cNE8;Pj zNpiCz9cTR{1trVtFOSSjo0}*egXugIaM&1k$8<%+?_y^rF z4gR?_{r=H~FHV*&9xL5CajG=-W@+Kw@~!tv^T$hbLm!v!o+!;;PD;0rm!{t=P5r4f zc8vb_<-7f*g|jD0*L!Zi|2__7z47*2$KU(p*r}7f$3K4m%m-)RKmPWK^3CgKPo6yW z!FwNngqm*7pZw&rkz0MA4^=+<;_}RuJC{E@+dDM0c;V_OUIY1b{?F$I&-dUdk%1E@ zK00^p{ed%AKN{}8{^`yBk4~OBGw|uT;S2wcZhW3Ql^pwM?EQao{~i7P8Tau|M}Pm$ zTW`Pd#-IND=QoeN_4Zr8|0wu+?@#W(KmPs`_wlDc{{F<9Z@zWx?Kj{0eWE{R&kDdF zfB(hI$O*jM@y_o*Uby>i^1-Q-C*OYS52X)}eRS&lx%ZNRkIs&K&^wx(dgpZi*tvo0 zpL}+s|LnWH7f+nNaOvD9CwfnOoSaVnvGkFi5ks)X<|T@(31aW>AM{E=s?Lwx9BGlV7LPrz+E{Hg9ra3f^bT9c|0)CBdAw3GUK< zdUMI~FqsME)YPnUT6Ss$G(EqZnw?}$&d#*d5l%O!rRSUzy@}^<9aU;FIj=biIJ*fR zIL}UatlkVpOiWMv{Q?~J6HcbMdmQ$ZlPByrxsc$X!Y!Od0%vkUqJ6M2Q||m{{|X<> zqZ;}UR!FW`2s)`+LWOYrZ##Jc$8KWId|jjc30#(GfbfyfW2~O2F)?BM=%fkL8aQvR z?48`%f=1g5=*>G5OIyxRO)k!Ja$#<QZU??!v%{;~%~Sd+Y7D-+1$%-hKbw zlkb(@ef#8zciuhm?z`_CfAhnSKRlI?r8IS9AvtyRO8Mkx=P&=R1cF(6ihGf-vGE~# zBrp*k9FF<1O50w1E$;vEk9}mKW~`7=Ij=f}_;0)hwey4yidFY<*#JF#ivo+ZBZd%Z zJYGcvTE4def7-GH7$BRp*E(K`sN)D@QpU+0+^4vKAVwVNqY#Dl0lv|Tk8dFQP0oo? zwY)utl*jb$gSqgI4yGj&%TpKS0*1}{8Xg9vX0b14VxAxE;Is#YA5&juXP{-4E8Ld> zIl@O#beFtfY33ZmZroR#p*4s0czANd!qh@Czp#>2re;>m88*TOhwJU{?YP5mxRj5s zkAJo|fSt&iY!R9ly&mseQn*!vUe*UVZP*xi_8jq&unf4@7cXMYfEUd7qs{7LCqX7; zvu|yqwuV!Va!{SehRLE6kQ}i2u!gu$+)69YpVe^LFwHT`9&>n!aU;x>5kUB)D_(cd*WlDP zS7G8p<+)xA9QRe&z99CMZ`$Ry*;bq@&)>s~VT1t$VJ6G>78jQ)%gf1E<)wK%g0-CB z#WP;LA#!snA(czCk~ssqk1KTPVso4kTivdGe}UgO!y!+a{LR`bzaE9thIIEmQW-(= zm)?s5#UIskssV>G6G6qB%cy&UOt~+jmrdSF6!|1kyJqJY$hbf6TUp=A*+?-KX}_5c zF5qYZiCq&J1RL==VlnG$xXF!+PIF+enrSx@8^Ryde3R@qOo}A>n!~4m-O+wT0YSZ0 zyi=NBqT*JIY+w_RicYILDvMb6Ua*c=Yp@{o@B4#;-`R&escml{r%IH}R4qa{*CFIC+Xprfg8rV7(h<(AS> z> zHjz$L>F^c$JA&W>*DGtB42}(s+l+R`3DuKNP}wS#17ErgqXG$ihIrz?qh7C4o-<5x zapCl%P}Glk$mz!>w3J^aIg2eIn>fWZp_L|7;*8K=x7}J8=jCtaiwTm4eEhoiVJ!#F z0i+zKT+m7n387jNb;_uVcv|(y^tic*EL#erf8y(+=!c&K=Iq1AdC>p3i~g5nKnxBH z8v4i~=O=CzMLM5a>V3GK2kF~QknXHZ-&}Cgzb(6CWaE`FCmvpHC&kP0QxJJ^O9uU| z75v21NSi`R#F7Ow#63j2;>{V;@mW^%>^*kOs0Ch3niRgmEknn{qy7k&>dBq?fzjDZVE>VaCx|-g`yTokz9CW}S zwE3NT6S?R*9$1~ct#mMXJ0BeYE-nh3xDPG9;lUxdk=E4&p(e;-S*SpeZ-*9J?iJPsHSyxt z@_6w96vw&4uFw3A5?%_YAMWkvgBIUm{q*F}3Lto|HYJ{Px7;?Vw52e9N;XXY*1=X0Wc{x^^IPVLT9Jvl_ZnDQj> zx#2eFNM_~>?#_ex=e|}dnEN^(6#%Zw{I3%8&wX7S?aLC$4FXus6Ui-bU9`VSXkWfn z+`_xJtlWNYIUlzJu8a0p3GD}2#(!hibKm4#&jBuucIT(@y*Hw#toxzs!YS;!&86TA z9~8w4wzP3q%M+ggpdu)DZoDqGLu?B(w6yLN+XBjeTgTlNH}D&)qeJ5c`}8x9xaTrW zsKDXdXM86Px>Qh@3Iy*;3s!o@oVRm-D;RKJYphm`vZr79un)Md26AN2>>om0$u(u7N(Vh1P+=1)!1*~k&JxE?;86Zx*4Ri$S-d4^K;_8wY@xO-)q9~ zPPO|AUq)tiRcEz6t_&C+!Zq%&S?RyvUKnb4>dMgIzqi?F`&Ybkt7=~+l>c_x1l$+l zzn_N+_6t#gQwA@O0Dc|2Ik-2)Mqyb>?Zi3T!YhDB60Z9wPq;3CltJuW7J@ z4^G-sebe#N89A(Y$-VB!W zT{ShcRM1!asLn#zD~ z*nRX8_EQ6`pm1y$VPB&E`BzRlXcqnN;&GnE1c2fKpsV(axe#08ynxy-ymWjlX5QmGRvv)j*p9Qg zqk*oZKYU4F9P^Fu*}{L^_&$e}C#X2`9h%cJ{?JZ%wQ>%0V8!>cE|orvgu_Hno;tSr$;|m7ROQn@2RPsyG$7`e�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 j8+nDXSlkH^OJO`fET>$Exgu;xURZl7xyyxBf? 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 RM)dWOlh%(UvYm?#@u3 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

    psNQ?0LC7g?jNN!I07 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 literal 0 HcmV?d00001 diff --git a/.dart_tool/pub/bin/dshell/dshell_install.dart.snapshot.dart2 b/.dart_tool/pub/bin/dshell/dshell_install.dart.snapshot.dart2 new file mode 100644 index 0000000000000000000000000000000000000000..7ccb29853a07bbca7d13b53defb9310440431676 GIT binary patch literal 2884872 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%0AwQQ=~imlwc4VAkngv}n3o6su{7F513 zRid3T$bP2EZ$O7+2Aj|;e@=tbCiJS_gQ`x|3{h3uc8RJ>2mo_Hlw^kVV%37GJF2=M zq*(H-TA1!ctL~vdDo>RI&mNtqsVa>1z}Dn?AU46WOA@MJVyJr@L}!BN^Hm>K8`*BI zDy#-3JLam7tBpyThm$nva3^&Pys7FpKEI&qxK#C9m%jc~VgM&rU$CwkCl|aU`K34q zvQWFMs(KvjsfFqphH4b0{?rU>IPZly>SXD~>XPb})jnuaVza91V20Wj3S&QnVMA#34p4ha zsNTVlr7u8fc(j;nybUu+Rf6k)`-Ibn)^qys^PE09j?-6_aQfO8IDK6?+?Slb{wBDc zaDRaCDR4X{S^9>Fz|6)Ib1HPL`Xby^cu0Mc-i3E4gs*9w9@&mGDkL#i{ z(rIO7t4k1GDYx{A&P36WgR8L*^&06Qt|#u-Cw!RZh1RU4OZkhGGnS$>z0?~3-;O`p zPOOt3V^8XQLe1)EI_EKI{juuAes5G|7%AW+LD97=5l~b1+&3*GkbDr7Uzf0fLOPhPJ z%NIrSB*8qcFnn0Oh8=;B%uwkYpEjFk6Cl^!gF`wYWJu#P-9Y80HQ1P6A-2 zrD?^RoX@0;Qx^dK@&d~u$uf`Pl4XP1Y`Mj97X;z@w9HuU zhRhU+7K_0G<2{n1Yja7QBoERbXL0K+ZmX5bmX&4k;OT5%%2{X)nQEK6fp1()$EGX| zmhGs+%TR}wovaRlZL#d>(#Nn%X?Y3mC;tNRMv6b2iZ@$Oy4Yr_Tx&1P1FQqA);o}Vg!({AmhEGMJb)I51BJfUD;WjIlD`JPO)|G@y70xvUO;#^IBww&rDOQZt zu{&>#eZuDn)oO-~1M) z@XNW(^@%3iC6ry;Wr}SkqHA#(39@TjoXW0kErqh|A|tr*_t65IQ?fztCuwM01!=HV z!6?yUur+9zqfq7CW)EPWDzNR5Y+V{`^mc;%0I)|4w$D?r(c7b@=$(K)USRJd*>xIh z6O6hhdoE7Wk22U%3nU(}PM;M<_r!6{Gm4G&%km5C3ncp$8Un_w0{be-j^z}VFI}BLVi-vbRythPI5d!&y?^0 zc#Z6Mmtgzwj%Au{tyhkE6O#YR@x5~s`j=5i0~ad)MjrIV*{MMYU4|3>R6pt*fOqo) z|9xo6^ruW7X|%%qE+x)!&Iu4wUrI=wlM16H>KvZ3M^Y;}XLRXXdvWS5Cg%cvNS^3i zsyMGf(5z&ex?OZWDmrgcoNFkM5=ROTNoasG_ZXQD3<66Zz$B4~%S@Fvc0t zhRk$+a@4ibL1&{g=E4H1bqXuAa|?M+EcC8!g?^qDn#K&4aC+ECm+*b(haB%Xjuz6{2f!uIsc+AzbGmHiu(ftK!NdP<)Gtl{QDc zSvu$%>nbY!5yFtgGVZ#9Jb2G`wvqfnSKzX3G~nS?hi`e*h3nQ%M$ zWwG=XYbn;R+B#UcflO=dV@avOkU=8`j%L_Ozalz0>Mhd2(%(w|a4$n)(Ut(i>)gG` z+g*;))4NYcTv7&@{>Yo$L-=8ELj?EGLh6pxHKKcx;J&Dkx-50Iycf)o+{H+JH`laS zbYCgBuSmwx?IPq;XJdx+C-9t!smh~mr; zbid1?y?!nIB@e_FPZD)rC-;^IQlj`Vz0o9}#1E2BQ*WS<9Ca=f&vWJTh?}HlQGXt z4`v%c?_K$*{2ia=8B9s&T7{{mt^iBAB5;mPBgzSm|rQxr-i5s6wHSVW*F@Vl%f$#=aq8J$HVi< zkY&j!^bA%v2$nMqmQyoe6b6~QM|#PUYq`jR)=8(9EI3P_%&FyK%WavGVe)L53I%te zU@-}nsg$_Q82g1CSIV_43eTgQSk|(nFp_?dquvL~8!R>pIyoGywA`H`?4>aFLm1}K zmMA(DOSCY$SiL*f5(`uD12~nQVBt&_Zc>IW<95g8Z%79TABt$}1-&ejfU!X~d@$ zC1YiSgeZSulGjf#_Ysu8dP<1dph<{%I7>>C5VQ2M`6BZybCgMl8N1$6jbtu`u^+-9 zA?9l!A?9mHLLSXEuhAsLd@qv_Ol4V4hnk~k3*PP$()j}F{CiHnZ6MqpPQQIHoCLa> zguDzNx}(l5c+wCI34xz}kPr(ey#gU)hjP*1Q)3PPg6C*Ff5r1M^zhK{Wel72rBX5l zt54zS$MbDGH{ zo8Th%7oCNcNGS@I_Z7>VUHTo5M`lJ&Q(e7pEar$0UmBDwFvssG=Oe|kr5bOweRxZW);XV%qqrZ$-_g%5QyFu>Sjm@*AyRiq>BQ>-UoNXqSFxrl7X$ zWI;EgpfH1bnC%Hpu(4{n9IT(LTZfU4aq@0I#!8ATM=Hb{dDH zH?T~g0*IZsobCqu|3}w%07g-K|L^9G;|>)?@lae7nnYSaAod8Tlthh2>|pPwDE12M zUP--6uJ7e8y<94UR9b)&5Cv@X1VI5&v7m^E3Znndo87wve&7FvWoPEiym{}9AO>ywCnc>D%+6uHrwa$g1)niy zf5?W#06$xJN$@#i_EB^8ca$FfVLHD{+?sP)&WJp8C&V_BSI#){lDu*zN96^xiOJ_C zerC=LW6pzOPI^SY!a((;51;deUOu3h-DViun?j&Bw#g>GZloYwM zIgt*jvlO#9zmLxqO}V0)Vl_)4BSlG4aK4(N11T^-VJYtB{C*7EVV&n5N({cD^Si~Z zc|-F?+R<1BUsVN@mrPzZ?nxoRyvCZNymYuTH;{PPG-X_B-a|s((_-Eu5&gE#S52w=j-svjji^D_ACc_D3TzsV`$+bFO`X% z+Iv>TM@7p-lWt#PZ$oTYDx|~qHAXw8`&ccZv5V3Ep=e(V{KcZXa4c8lNVR`~oA35W z_8kapQAuP25y=jzuWZ3;jQvD{{U85c7&M8&H;j%Eq9dL#K<&n$YxRm-@hPPT^RXCA zWyWZ9JVjoj(eVo2K~jkuqBLsL9oYy}<&^4h3yyN5qgZtKBl=a-f^QX0Au7zSf#i3Smjsf3gakqj4-`nLNcz-#d;$k2 zvoACj-~cz~_B!u|7;f(o1Lj!^CK(IHiv=Tk1Bp2T-D@n!5DRAX1|R( zBDM71GZwUq1@#mWrI*%oUEceu0SKMBs$f4;;Pir@3w~3INyb)&f`8=KHCU~1_Ce|c zM(1GBiK%V{kI^|sbPge3THzg-CvaX96PWXE(K(YK5ZG;I=RIY*zu`{gJe(!Kc1s>&agX&R)XM7l2FR+pY8!P8p5GHZ zf2*>UjNU7(UbH4_t6`&jOKrRN7Rh@9C1nk})e8k#TWzCH&aeF#4SPzS_W?K`6ui$F zy^o!hdrG|beMJ?$R+5(B4H~^Zk#>71g{P>Zx5nbd*m`Y`DtcRavv(yW(fMU@tM@M- zSy&vkcT5$1{mDzJ=(~(mG1e%{Z=k!I=^JJAT`T&ois&P|s1erjzBH3BjXE~iCx>v- zJl!|n_ZFmxV-!dt_})nhT9n4p2TCKmIDZhw#j&-dO!8r*_CfzxcjBw#CErpCLU-be zB=|O}va=d-53&#TXJi-j5+5A(_c8hVsCj-*dHToDUWI6$ek`MBDtY>+D0zlb{dWx& z{BtBf)cXT-EKmPa_*m8p6ofqe?-Xn#?voPgaUqa}Gb@;DL8R-VL5^7RyiY~{2B`7SlvJfr-+D5LX; zW-I5LQOR=0*m;BfJ^CI1La~MNO4)`8mJ{FREAVO@Nq)m zGlq0T;1muAIgNoo#K12UgVY6EGmM2=F>pGTlg=Lyw-(-A_;BGCXdAj!riF#ilb5ux z@XfQeFs(3)PcF;?lv7j;pS2FUl;SRg)wq5x=P$&ks+zC7Oa{nVeZOwCTa!!LKmnJPx5v z#a^2u#^Cp25R+BwkFsoV=WlB8Zy}_Wf?$3FTl!`PTtb+84GE00F=7b)#`>dZctcNz zUgkKvo?#P03)$|PSEAUkt(uM-RqvS@a+yP@MH^=8G@)iwsF~thi$m*7p>^cU`Zct} z6xzX@$EX-Xhw$a5pP0@7g&6va<>xPoD>~OybS}k1f&X4~nW+fIGxMCFWJQU%yrL*s zDoTpdE@N|+P;_Igau=ch2IcIgvreeB*jd1iK9L4d#Q9M>Ez9Nc)Hf<&p-=vmJG5Qx!q|if4cB#d$Lf? z%w``BGZotiWmW+`Acj3YK67y%gVA@&OvM2P`vc!AODitIhMLM)ITWMWBW{au4dVy= z7@a>TZY>#Il3aQv6b;QMQ^1lb|RzJY+0+UMzVcqTl!msa#y2k_D!c z1;{hmc4dj(RDyYVs?YQEC8eg4Qq^-#NsFlj`f{BlUZ78EL|p+g5i%YAu=_Z z(k-UaEo!C%OTRLe(!3iHI;iwFQ|WK2XE2dd#`6hf7cp{1iDek~esl?^DZAQKcC{Mo z^0G8jnc5xA8&dX&sZ4Ff<_%}*Uq*U~r5`PpxmbF}PFXXtQzULJA5=c9f~1bdoUv1$ zL|#sVGxr#rMA?Zezmq%;WQ%$Ea{5dncHxxML{l(V4SZDzWQ`OSc*`y2IcT_HT~s~9 z3*~u9!GPb2%}d7eDzO~e{?YfW)PfGFd^LQ>gSqB%Sf(Ev{KaYIhoGC~zgfzELcmD1 zMVmV&q2fHoi>1Oy;bO(*goY+`sSzs{w^meD)HY%Ykg@`4yryCWd5N2f5Add049t+l zRnRO`l$(l!3gH!O5TbHZaWcvcsK4o)sl%ko{>XD3Z>}7S_wLI6l_R)xTx58CPqS4y zU97}5wvXFm?Nxf^+{!0=TFJ_n#LA~B0=9g9l3G~@q>BkDCsanPl`A6pO=E~xs)rC@ z<+e&p7&8G*<%P;amP*w2P5s#2sHV#AKp$1Ssu$8Kk75^wPzvYld3EVl~sk7 zssf^cs5Dg-MM(g)sZ~3Ks&8ynT>yWgfEk4m&SU^PX;nYs>r#KPuXT!5|B?)_JE-~s zp*q14oPsTAHyB8Q2QU-NuKzvZ6znl~AjV$C9w0CCw5 z-*Kuk*T5Y4cz4Qhp=MQPO&dief-x4Fo3D7|Yc|&8BS@^lXbECxCI8Trw3_{VX3h7M z0C-LgHP`${h|+4$!Bk~x?JAN%?Pg1DB*tj%r$n%|m@!(r-&VV`htb+^dNEpi+*XVE zMhJm1TKi{=QAk#(8(^vH8$((*kO4`0_#DxdmO9L$sDiDdYo5@hv;69&+Uk-CCo7J+ zTL{ERf$G)yg}QQU9ZWQ({;<9f#(Q0}ScgjWaeJJmZilIk%mQj=N7emos{2{>jIGz2 z>M^&=AmgdctiO~u)h8n4QN*37sh?`9pQ^%dsDHpzPYoKOxv74>seZodnZ{CLTCd)2 zs`o|{D_>Fye}o$bmhtiRA1dWgkMR>z|N2A2g!*5t^@pQ`lTpA44ZNkEDzc(^4Md#E zDnGN~La~9`AF$Lg$<#m#D@4n!4YN!QvsBN_hKEfJ538OuBCO$M-qb)nqry^y*VI5X zQp!6T>P!uFs^_kTHKv9&s%JJ!`2|u^|3oS8o08UW0;7b@rwx5RCv!`L@;{7Pnb) zE%mx!g9^03hG0Oe)?XuTvyQhutP3`(Kr8kFFrZuOuLba+?E+nJaTNHk3M|w5>%?ug zVYZP5(G4K2*7Wf&MbH`?hTO~JD%LWbi`;743!Y(7*w9aDMK_D6;9^H2>*z@2=O!G9 z+)y=%Nk`{z0FpOti)<^fK#3J9S{li=tso$NK!62GTOO`lvN_o|8BI1%lwiyk@Pe&Q z4Q`B*ieR08F|Z!69k!jsLLTq{=}~gCA5jIQCwQanM3U(Cqfqppd+^X@WoM1 zzcqofp$9sw-#Q+8{RSYT;2w)m)EI=(4|?9oiQ8eN(2``e1bYEXT5L)3ir7*k_7<)d zw@WWduUh}s1Y2UV)M@=|5#AxKG31y@BKxs)7!kLdd2=5FR@ENUg!&@n1BBdfe%26t zisEcS$U1~9HLo@VpN_6``?n%^y|~>n3hS1^XAqI?*~UI{i{Dai2tKETKw&>d&_T;V z>t;^609!ErgaaFCv|7t)NK{!V;;iSwU5IuX`CB10ZSX0Uv-M`g4L%*6THVUUSsy0o zGn5^66U?KxXt%yYfzPRdSxO)ftmdcSauM*1LfUpIToJlxc-s|lePAZnRdB7hlIu>m zHrUAZ6xJlyC0J{!9qa=DTX~BWGo#y5I0J7v7%SwB;&$uj)?L;=qlIk!irnmn{AoJ_ zMw8YfM(d%Z9J7BdX@as7blXl&zr8{rDu-N(9t!umBJ3tEeLnm+=jwK zB*v)_^(P4Vz_!s)NZ-0b2n72Dg0|rAci__4zGQD~BeNZVFbWT`ST`QL;117MRc^*F^bC@ED zfspSrj~KESDIs973qi*+k7ZErOO%sclILYCKk6UEN&+jciaOO zcMyv^9y9Qn$6_q*61Qhvo;4y1eFzl{mNmzcoBb3PvnKKYgT-aWtm~439scc!ZyU3w zC1o%2?*NB8&~)uUEmZ65cKE(Q9Yvkpei@#B;olFahJ_Pa)Z1=OL{gq@B~Vla;@Kna zkdmbvqz+ARITKH4G-8AGy#Tz7KP*LI&iH-y2I~?HRixpJT`2&!T5E{)J+z^TlgdI9 zFbywC;fQ|cos!gq*BnIT^gFZZg&z+>^gF$HF301d5auTs2;IktJJDGx4NPzaCt)WS zJL*rH9zePD7_y~J4_GuVL`yB@qva{XyApnIfnVP^|9)|&#bc?kJ<&I~l5s{oFpm3w zBkr_5XPrk|750JZP+zuH;V`8_u_7z=2Zr{u9a@}HY;ijOw@7-U^)@RubE$g(tan)- zh{Xr0H0x~a51LJD;QRdF==|S_J8k#d=GY$N<0OiRKIt*rV`>VLihfrbp7-(4QXo2^ zACSUf^Eh6-Cb)``?cYxa2Exx_cQndHW(1y1=nqWtoS$)F)cJoBcRB2iB1ah?XBz>$ zyv9-HD1(E3Xw9&v9_xO`5Ua}3$#En(;P}Sz2acM2q$K$P9tHnzc=yKt zhqx0+RdE%%lb`qiB3C`6~r@C*G zwgIv|zG?YO@l~w0ngU)shi!spp-DjfCs6Om?=F~%&Wy4I>iy&)LF9jjcc$ra4aARa zEA-9183kId;2Z=K%f^BWlWZeuoEZEF1tZ0RArXDo6zMfo0I47m?)!v-2}!hWD-~Qt zUarPX+c^IccNI)8NGqsUHvwr1?jkqkSO7MLWX@Dpbx4#f%jdX)mt$GJFBZHBWX-k_ z)ozw?eiB=zkO~SAyh$hsi3NU&pk!P`fmkW#YH+*G-^jVCpv{SLwGc*LQ}6+KSk{{; z3mP*Z0RQ8dZ`_Q6U0eYbw8HHnmD|*UV}cWxNS{=h!?b$$tzeEuJfc$rAJ(R)q&fTH zIB=SCC~Y=7DeiJ!?Y!2B+9;8s%xj#tkcU*rIYU(;C(3q+V>ZqmgLNF`iA!}pDmb4^ zVkYG9|YV>+uTJlTmxjQoPLO>#CO zs7XCCo9wJ22u5?xDn*25mgKm_iP7mEEhMJ8bpBHyf35Qa*Js!jbDu)~N95r&Ab&Hc zCIQjO?;(!+*x4+OcYaGg#ta|bpAMchsm{Ly7q9ZxuX>ZbzetXG=rd60mHmC4Wb2H{S2S)(La&93(;K~#RO*P|J}9?cL*zMO1z zVe*8%d7 zPPz`M5=8}!)&_SR=Z;lC_n=q>bdOT&fqOJ^-z~VW5#6YDUq+M)Nf%sG=rl!V-8Yk$ zRY+DdeinDR?{mNAUdwY5iV^zhe$P!a9rR<3CjQ$7GH8m`E#Z1?htZwQGN%I_QQ%~^ zOXGIANwGn`+lx1824P@{)7(W^i!BQ8jRUGU(cKWy?_DIg+mzCDx09C(fK*TsBwQu9%}U*8PTRr>$qESQiew;L!1r-c9vzd0X(}s#B!DALeHg$eAcmn ziJsxHG&4M7I1dz1sr{a*im2n#J$HN1ok?Gukpq@xpAf%E+!Mt7V?m|Jyhd@YeCkv(E?FhP|u$n6-AV0=#uC)0O2pxfO>~2 zievO%DS0t-{na^)3~#dJ9nXA32DP65iMzb1-gMtYbPD&dyuA;Shw}Dfh{jpAGRafp z$uicYdlz}_9G5>0G|^F^tGuo`+zf9a=dB=Ws0;DdMH^M`GQqo6^sYjlCPjqa2;7B& zcatJQ?`HC_jE-6 z^$lFr^*a9%Ae-lV!X;x7MX{$c*q zsJ-qVO>XuBff$nbC-Cw9YimM~ND_keyME{NyD!Bv9SGxiVr<2p~`-0Pdbvvj38kX_bCOqYMx;Xv*^YGk)=XGE=#>v_qGcf{* z!C1vn{f9LLpMqpE69*7&+B5B0T!%>pI;Yr>dY#-?^!PNsbA33m;CP&UrW2yS7+$pg zTz{1|zt z2FTCh9WzsLm;8L(B|krw@3~02Oa4;+1@#_XCNh@ylZXB0BKmiT{#`7m{-P&vd*H6X zQ*oS#CIQg{_XeIK2hRt{q_7@mJzQE~E*~G58%uXS(ya?@40OkFw$nlg670&<$>bP zthHGi44EHN@1<@s;p|HVd6k^{r$Z=C*bFkv8HOtU556zMs6 zV1j)^wG|bU4bMb7*4(~Xh^Z0#bBfCM(aD2A-H7b5+1K%~Wsw=qgig%94i5S$l%S4h z<4SCudtwpYaL7bE&ZFA^c>&*j15&YX2Qn{)eUQNxI|oUOS` zW#P`D@%))P;USW=oP&Hq&cVX3Fr+Z${HD^6xyK4I=M+%aL;o)mcjkSXx6_`e<+m3A{pI3L$9WE; z!=&L}LSl>)FL9X2fpH@2hh7x~3xSR+X>+TxH58v0nrw88XELLqi0DWL%11C1NpnoW zqN(FH$uR>V^VL=b5*l-@|cX=Q+a*!U@~N~-d2-0fINgDFFx92(J)=HJV8TV5)O1;5k5bT zpMz6bc@F|r3rHE8k@r;I^Ypnhb?llqpF9i^sU?kFd3ER-m!9Xz3nJ!m))^b~%9H3m zpXqsv`Mi$2<)Hgw2JrAg-dZz#UF-Wq_SGUO?*q8|b5%KfZr&ye7V*gGAt5Y$%MzRnS~ z5ZH*+{;^=+PG9+oUWP>3fbi~k`|&VH!(9?-jy_QS3mEr+qQD=^a0reo9J#T!-!a-j zrV&*lRG4V@hykzTdciT>=(y=D^p4x&9nYxfanIX(ipA;?9a2PpxRR^hsgp-$I0_s- z$6ruorJryF9e*)C)v>grOmH+99aU$eZjN_+5~F+{C_l_77aT{8jvrX$*hfwoGmmFD zPUq|LG0mZ7l;1D^HHDe{^Uh!VMfS*(wIN@%>2ZB zQ$+v6e8yj5M*iFR3kwEFWboSj=yeEu>ux77TPh5YTt ze5Lf*m$IO|52sAX?~2d=JuDD9eEceo7YfenRea+z3N9^(cP7BxU^y3zBsY~_0oi+* zYyhSzB1TpP(+Xzw)U$#+89~zv=I{ki6+F|so)ye97rYSB|5%{Zvx1l5ev{R+g10DG zD0thfxO&yI)B>we;1mk%O6@9eP)rmIn|vwo!1p*!z7!PE1&IYs*k8UmTRukNpptj^I6W7h>R`eYX~*t+4*U2o}FJOIKPeY>>7+O zoyp@fTuH7;?g`*|9Y1*>&UphiBLQu19)!c0H}|?0SWFz3Y0vH_tAM*@b%g z^P39KE-?D@!;EJa3h(DP1y{aVarNfe6%!%pY?jcmn6EfV%?rS{t*v3uG7A6;_k%!C%_sla{ z=H2LuhS&s}nCm^4rA>FwcfZvm12>ixsY`L^@@|jY*INeeB8xj1(I0u2$-wLeTSuU$ zIeeZwOu>S?#-g}-WS~iRx4TzU{le^>dp%>`LL1nR;Bdt3RQG52kh@4X2OhyyacJbds(2cENj(=)DX6EJe27dn5W^(Lkno zALXsyXUK!Q3g5t0hN9Vv8vRQ%ldU(qw`{$^1aDbPw%(nHycZOZ$TWj;dE;>3zQDPtLqNC@L5<7gb zi;hkae4A~GtG5#Sx_tXpLHoXAN^J9ePti%xzTX7j-=gmi$nzT}=uF>9z(5pciv9hq z{tMw7N2ZZ~bi9AM+C||5YEMx3D12oNE$GqVnSL}XM{QG5{YBVJUt{){!OIT58vRYZ zOT_;{g8!pfiTMAq${1W79hWAb%Uk4&2o!BQIb3iL>-TnlRS|Z zHyY(?Mk-~=c3{gbd?L17%b&?R(Mn<81upJSmUk0A<<5V3w{quyvW)E5RKEPZB%>Ah zZAa!S7&9e_@(FnIxbWp_a9Tje3xR=B02A-OZ5#xeaO=8Go}3X#3``23;@W;9dNqM- z$wTdb;3m9#_jwpiv5{fmZfv~2J3K_O$pg7jppc^hQFYeTWRC=b{%}sKW&n=`JAM z6&{I+W(t5P0#LGJUjz9y8G(Na^@VqXLT0yV3I~wqEaZh4iKxh9w4RYeVKSdkm>eF} zlS3iei{EcV4%cQB-e3424*PPM==~wi!bizN;w*fE!<@_;Y@!ss3T)~=>4mPsKu^sq zEM;1dTG${Ic1VRyz*!Sj34BhkGrn-QYR;t>{zzZO#iAoG6rNyJi|p;`h5zwEeXt)O z%8RTtkv3tkD}ej#{`7@Po?N12xm zVl9C}Z&A9W;H`uK8DoGGymP1!d`Jq;Mi8Ug7<{64{R_UH5PUaU|I&g@ygArG$aL~` z8Nm&~jYWN-f?Jr(f}fJ7cd1}jEcgXrnQu~&a>4!NCQ*`?6?1g5PMaP&KXfsPhG~Ns z8WhnV-$5|z+ACN68pP8bw%h2)_^sKOEo5q>IUV+bQL z*bu6H8tP04t&52(^e1l){Y%Jn^7R=-=N4U3bQdJ>7R117iUjhIiWLpTTl^Yr%ha9` zbkP_-p=eBaEKFBTl30Wy`{M-8zsfgc6y00&cu@=Rysh9dk%!@#kN5wm`B(ue$^y3h z@OY)}7u7}dCvF0=8#9WQ6|FDAuq*Q_1=&aBVaRA&;r|eYN?No_CCVcf9Rr>`;7Q3S zI$dlieh7HpVR(u!BoE;!z69_8O;quCKB4&P@I-~E;tU|$4rDiF6hB)0Y{|1|OTr4W zdE_C@;)|(zX1)tiVMkLjZDhe_c~o~=tiWF1VlTjKi3kB)YH^uZTouv(ITZa-PBHZM z&#B49>j;yY_4? ziJ^Rwk0!k&yQDx75DSSfaaC_()6&yRO8Ju764=wdIB1qi(3t(TK;@t{#z9WWDhd}$ zIwi$*CI_F3B_9L+7&{(YvYSyZm2^=OM!7ew5Wq9)e-&Qi81QJ zlcOP}upIyH&&KJ~GD`0*y}xXFbUMEDVREzlO_cw8tT$1Jh)XYBSSrSZWGu~Mna?Qo zaO{W*5i6Ef19v_yrXD7gZZ?*#XHlrFkV-!VqykL^KcRGcLTR_!P?WAIJ;kLADl;Ia zP&QC1gAMg}MK7vTgtFlZ>rxpkFe3tyjB_7&~TD5LKk$hT&c=a+jb$YMcK;zv_nL|$5kDKE!cqD|OS zx$;K1&5N0vbf|B7`Kof%|LAz7d=ukls!;xwhwZ2r%MV2Kr*6SXh4Q`S-*Et(6w8lO zkkSp8{{#1(;J*BL`F{Xc43H{dn4P+lr8ZY!F8UNcH!oD2S237NuehROG-#yl;Wz&ub5GR85mXSQbig?Ly8P*#hq~e#WFWnppOQ2>eMRG zzn%I^sF-V2Trp8mHK}+}ouI0C*;+A=BC;GU6|caJ55&D7R4h<>wu*%WRa%pjK@~32 zzlw5m1qQyS9#<2g=vbogWSu-Sqhe`Ad&M7M>K-QciU@f~pDNIXp3%%JRkmVZQszQd zykf<-5&b_aM|0sDbn>i>ijx)pRl-uu#54@bud*L`2vOw){}WMVVhmB`_=x_rW)wp- zJ)`oL%30MZK!j`*RCkh>RH5?TGf`E(0DmUyG+2|OO|Q(UbR$TNb_bO*##NP-m1qZ} zI#SupbYyzvYQAz~<;Ss7!nAYc=hjNp=+h;vd@Pk%-ad_sRZu>a7&4wN5i0js6<1IB zXwoZxtUQK1X^x=sFQptR|EB0Dhtw*KP<1g57l~DU5tPnGShlKj;XcH1tPQEU1RktP zVEapoP<4a33VL*UJ~g$rswpfUeW#)d(*jjbSgN2Wr)|tmsWPcGm(5#Oy`NBJj@l`y zRm%{2i?M2hxe5*Y>G{#AVq;a$tPJXE)#0Q}NrTT97^_a3t57YJnC9v}nu?J+t~b=*Szal&Wth5Bo7q8C3lcQhG?s(lV;&RliXk zf{<88ps9YJJm~(lnRLpG?VV$W(q!dg(zI$b&MIYvQ?Sy;%tsoL+?G*YT3sHV0`v5+ zl4ApT*pF<5)ao{&dabc~ITH(sh=yV)b~9Z*peLdjUJ$`*`EVh;Kw{3(#1c&gnZntz zXtvQR5SI*M?VUA@I(bG$xHw!}GaDzptZF3+x5CRRQMe6n^S(J;cp1@VLr2KkGZ>XM z*hWxubNE&?-Xm+$a11I9BzUm>^Jad|$eKHNspbv@6e$5Hk~=bL9;kV^_A#Kz1TJ1v z^AvfA@tS#f+ng9BhtJ?yL&vWyV$J(N^mmk_Y{eU2lT}@dWbE8kbvV7Iu%@i1-qzHx zBD$rfRjBzus#zH^@F}qgbd2F@w$Dy z)ZV7VGS}Wt!Is+Dcr9jjNqR=@)3vYEmO%Ti1(Up{_D%AzAKEKh98nHU=F@6%qP{jW zJTtoBcV|XzWo=vCLJjV|Qc||pEhGoe*RJ8z9R_3|N6lbZ&b6P{LL5=knNP0$lFB98 zF4letGr9I_3WAwj`?Xa2WyBDd3w5vk!&v)^QWgMrM-RlI< z$#-ScS?coYKLz>mjNLjnc`(@)S104G8UuBea4W_@kBX@b!ZN69t%Gbbvza~^>po=p zL;LD>N_AT!2F+Ym`{w2-UUOYHLf=zPd#1$K9S`4zrctcdBJ?h){v1kTuD^idaOw3| z)Q^p+rcggos!t*~(@*2XwMgq zTk0PJhOY2rHDr4Ii+ueX^=H^|^$TtFs6^T{rLU?NDFyXaj{0m07V2|simRuug4)-I zto1%b{g3Igt-eT!TdlN&^^IbEn22X-Z1qbBip5n$yVL4Bd29W8O0APKGU~V0f7O8H z5hq~$dpLz9vVNU>cSgfY4X-u!L*BV8?}mlsp}ZR`J$X0e_sScc5@lPZX4?i- zuSgB6@LFJOP?Up9ZP+F>?2#IFQ7CI$#D={T5leK`J2(6kwQa?QKNJN2P*m8n=n`jV zG@jo$uyHl0%41YDUQQnD(A6{!>!GS~Tn|-^$y9soJ!=}&Er86%I}|b-AC4GweWk{y z@Vdy@_>v->>5cF4jn+mq1*(B5HloONeeoq@m!+`)&Ig%NNR1v!M@o^`7@%OGvCyKp z&QOZRI;GLF;B&@^Wo~T3D}gmy_hdA#Yy4yz6P(u#>LYVF4Gs^z4*bNI=1*x zY4IG2pwzL&&;{LI)UnjXFA9s_vM!zI{1tf%7*(lDge#VeGA|hd%*T}oC=17u6eM;HT#`z`akQ@!DO2*7 zJc!^j%aUgZHH&AZc*2r8VM(ERiIZYyVq*_)SyDn#xbPjlE>=hSk14$;b;&_t$w^_! zZ<$NJqX1Se)+N8geIqI!Q$k~t&b9=K*4L%9!K8~5nvC&HSB25K(6=L+rVCB?WHy1s zzGbZF#isid`Q+ThPj9N>o0c|VPDxc4p=p)12^FC4jj_HDA2nW=)f9;s^w~YDHw8_g zQJ*a|ZOT$yvFKD8n!Z#=B~1s#Ce#w$UPgNszIu#Apj~J>W^4L^$fn&lLesyQO~jVM zV%Ablji$6MAaiK~zx2wbqhn;kAYXb_*3$72gJC>l%DQwC5l#ABuoS(nVLU#IoTa$V z(C4M;Drrma6_?)GL)y~&DG`yj^l2NummDQ+=_{E_sT`xEy{1M}NYlypW-PTYb+w`o z%5*~Byk==Jd1#B-(h9uQ4r%FPxYg0=Qr0iKpe<}04XSmYl=!846@_2=Gcq_JErmD? zM~q8PD+-_5+;8X=&4bO&{So{(=6H_b6BYQbck>kT3(XIjn_+$#{$`VCT=muXjPfhZ z3qcbddWFf;Y?YeP3mA?lHKaKc?gP{dHT#-DWhPFs()>#EQgd?^;i2uXsm+~2^QX90 zIb!Jd2rGGO^A~X2a7ziMmzsZUK8}=Z@Qn=q5u0H=84f5)+WaqzSoH|L96U%FNQf;% z2ySah1Zb_fWg_K+aYSm%458(IOAGADeu_?8TTp+Hjnc5Tyb^6#Z7uInQmKWgKSB*F zzRuaw(9#Std3kFr0w6p_pv>Y?G{KO>7$hEZ`j~LFG zfx=I3?bCXG4_B>&#MS{lT(w@R(Dg{lpw^j4p4oaA(#;D`#z%*r0hd}%o7MU03^sqE!w{XM2vys7mRu@tq_HK}cVgtqggHbca4?scqYV5F0ilG8Sj0z6Zuw+-jp z#$k zgSYJwiix^Gt*zLGzUka?7?z~9&Ew5&uM-Sz98hS>j(uTUC*PmZ=4q4LVgF>Zp^>Jo zoIJ#KTMgd5CY0N#(^RSyZ)&4EXL_^#xzN@vwQY|W&YRqu^{*&^SUk8}b(It4W-hLs43+)$~6<2T8+Y^NLM6n&_$$2B#;9Y1RtB9d}9HpWr zf=g?k$eY`*Bmb1N_8G|Rj$W)kkkS4?``iw6^)_m*c}@GXs%vatqLgQ~F(s$HgTjUO&Bpfi zN-a2m;=*R57p6>a-_E!1ZAaG^ouF#pPmzJ|2Xi|{O8pCaI)U8wUnxLnKWbK7y*h!^ z_J4#9z0jdmB+}7`Vn!9C0~T}t1X7HSfxNlnGJ?Tnj1#~33a@Q&tZ#F2kPYccSKElK8=R|pNvLBF1qdBqniW?J59Uof zz85-v6+3=Hj1)zGI*zN-f(3a#oB8L`I!^NDWzf#^S4~M<)}I%aUEE7T4`nPHvh0fG zkAj#uCZT0x$V1ldvI!&+WxMCH>zFQK5Qxr3mlD71zHkPNA92}}5yJ(KCQ3YqFiZGu zG+^Q~Sc4Zl>M<^>VB#QP>ayj+vUTFJPJ)p9jLSAFvZ5PyQiNrDl4wp!T85f-!3$h? zcG|LEU}Fth-UqRS<>wfg17o`AhD>TPmtUl`n8Na5;&Op7$H2zrV;TA+aryNGpxGv2 zd79F3i_34LFlqTcEHm0&I45KIQ_G)O{uz2$n!w;S%U>c7je(cH)*}U4&()+aH!sJa zgiZ1+FJR&pm%}0(@HCVYxuB6&rl`f`VG0$Nw~EUblPg9ZO;Imj%}dKSAowkvJU3(c z_T^ojGf|2EQL;Zk9x8<8-}Pj_{O{hjFO@{!l=u|`6{)Wn1zd+b#ubx#q`o3`*w8Ch z+$XI-*FNB=(&_W@E8bw2+e<4JQD_pb7fH!kfifF#R9Mj{t*9hdj~TFH!wQ(dM1Ig_ZvpSN^_y1@MuczJNbJgt z)z_|`wfYsF%PeAiug+LaTaf6dn3;Uq>U;Qv)%S!Sh)x_mlCk>D)eBa4Mh_0Hwvn6t zpe#5zv^tNEUmXZPgqe<{MDwIX^JD<^-zDIgjmL-QD^CCY8cu(h$1?#>CY~QT{SScu zu$j~UIGxk~G>OyyoXF{q4CeH|m^l5f8#(=NFLC-~2s`#Fo@Jc=_knocHpo$>HkB#|5EXM z!x^~O@$BUcasBYz${941ID@u}GxWI!&ySozx0W*)HgJY>FW?O4_2mrx<2b|lLpZ|) zH*#tK0^QQe&xkwoC*&uqr%@&= zyZyEDvk125y9_;tQC=5!ddA^z4LgkDxd{$7Qt(jc&km!gi9L@YpinuB;(6hWvnWr| z^5`JX66Gw4rz2u83d&iOXK@zAV7wA%QJzWgnAKZ4_Vc0#otg0*&cJ)d$xi|=*HR8NY5D7U zWBw*%{(3r4@eGYbb@Gcywj;l*09P(VlYLb{eG*#b{BQ79`zBWXu*vyoLjDQm_?F`d z%;UTy?sP72+MMg6=TV#v=Q>J_f6f9p&N`3s6wY0j;H%gr!3)tgn4C)#CTwYlFRWt4Mct8@USMh5hSzYDx}$OA$*y)(|}V# zb8x)sZE>e>fX}FCbUCN#Bfl^1^v}m%7l-pb8hm%TizvkDHXD?dsN($&gq$Txx)eBN zkbec!;ROE&h0Dl%@NbS7F8Q8Ql=&?Y%6!Q_DD&GUe-j8Qr<pP^&I%banx9%AmkdrM?Ex z&tJN`cXppK76XHNSd`Z(nejULU2$jN>Oe{WmfIkp#n!*+@pq0;9;C$Fh!*bgZsyUXc;!`o#J?0h0HLmhli0Kp!o{rTof08KO+6{NM1n3B@oNjsMO+ai(+$&VTO2iKt;X0re$kxOgd4D;IFG z%F)0Meu2d$V&eMBi#TyNoITgQ@UkTCw%knD_|u2C;%K!anVrMK=Xp`Ab1+ZG?EB#a z;4Cy6DpVRr#FjI~-O>gHPq}r&L38|Yk{yhaf=Xv2c8YYf0Y_+P z{SaE6gOGITZUat?(9IikKFfii`|j51cWFLIS(1UB`uVSqXjEvlAHaANqh&%&X16a z`y^&gFiHhUqFv5Tv?dxQImvcf&PlXn zx|V9JrMAbA0z)Wk8Qzj2Qfocjib(nBeGqIEMfY6T2IEt#!zEjM#30z!;nS3qY};7) zMZtE1WV@Om(r{|UY`0J-7rF>@thPI=Zf9ZlvM{i11KX#}oH+w4*ta7~d{S5o52MG7 zhAc{tdFcP32j^DJnDvjbtBwx4v?x2c}via*=u^u}GC*J|aRVpry+nK$XE^Cwtlq5_+@Nh|LH z?5)hO&iY~$i0e`*;k?~ic{hN2GXK+wbSEB5c~}9OE`(z46}z&uS^cs`;2t(mqRF}> zYXm4qCzBNqeUxrwv?(d+k~yWS@$Lp^D_D}L;Tx#mQ%iQ@;)H@IqR6?3r%n{0tgof(aK+o zUD-EgPc?{i@gJsXwDNw0G-bCL6wdY`lWkq~^SdthHKg&YgIv_xj~v3!>IMjzq=fpjXq14J_N7`Q*lReDXfBR^)yB zls*v40TN5X&2Sy0+L@3J*Vkk}B|HSzehaytG4MH46rthp?jew|GUvmbBe)rm77B1e z_LH0=aL`YYR?g@Ah@2x@Q_fcMqc{)3ZZ_t8mn1gGUnhzkI{90%EBA)n8M*HO3AMU7 zpLt*II}Ak>N$!LEh}?Iyrd(RFCnVnzlH6B&kQ@e*g}Js|j3;>>SUxO~VGYWi11>UTceE_!lHM-#L zC~%7kT&R`(Vwe9M|FgPaw+i%AqeW;}YGoO~m;K9i!7rmg?9XAq-?VZ7z=(X2E=U)b zp^lmS-3svKaay@h?2@mRGj+J>UIEJKD)4!&90af~pwk7vjsh{OOK4xN*2*EVD=;$f zv@Uo+1qQBBfTqi}auI+>3die$2cy9M6yUsHv~sc7Rd`L|Te{#kDzI>t0(>b^E0+Mc zsPIEwkS-A4HC~zz{WLB!pb8 zTm@iGXsb?K9|g)PaJ^Qp2C%#6a-Fy?3dEg;l+x6#mBV6J(G^AWbm9gTSTspZxnC>S z0Qg4HdY!m23RI~zfzMh1w-gW1i62IRT`F3$R<0AfiZ3mGUMGH}0*h5@O`Te~9>780@WfjP1DLt0PHRus|)@T1^%LBwg@S z6nH`fqGm4>yDF}(urz&u#R_+wLs`}$P9NauZfw<{B zNd+F&%BulJ{qLYgR0<@41sT6wM5Rh?2D(uK4tuzIe7 z_SICa909O0+(#Gc69sNifzN2=55%tUdEr-dA)N{gk5_@2T6rCS?}WQ`xMx)%D2&V8 zNqnz{weorZ57f-mh4d=0MymohYUK@LSIwO@O}daF3Vc}wey5c`1aMhxe_g0w6u4ah zzNXX48^x~L7i<60h0al?TnNIOYTsb95NfpHTKOZft8PyHO}fyzy`$B=)H@n@|5)s* zFK-;73!T?HT76sZXdbOj-Yj;RcbNBC=JI@~Kl&rs;J;etD!mE{KEWqj&LeYz z`A5PnSmFkoPlY9#s$kWf3tI>{T(F!cTF#3Yt}Klj6vK>`#KD#!RRw{YYNl~U%dEkc zX;m}Hqei6e_dcEcsn}&Hw3Jw{<@nI~svTpgh8JTljmFY|cjj9Zm9vnone!gp82w@D zO*L3P^EfG{-08)63wF4e9y(}ATIAvq2WW^wR)Q^02zlk=qGgVj7 zqlj9xT@27yI{9<4%Q?n5(R&hkU&!)yUJnoCg`56v##^<#oK&2J3sCacf_7NGyc46< zm{I6_o5+e9g$5Xf&U~}e8ZnHHee@?+@v25)x^tCtJ@UMWoi1T&Dmb@D&JU4f4m*Rw z)eJ~=?v8hU$t*gf^CycF(^;b%A@6yj^EjM$nw_U82f7d4bskUOKSSV@bk|511`Jjr zX)5nYcU|q82JefCcZO@0>j_r|XeV85yO~KWIJkj zm(S$FMgV09hBK-uc2^yseFaymRdK~8(NkS(1=nX**Ls4poiudU0?nVfzD{ucz%B!n zT(CJu&q*v?kQf@sO}W|qG$sbECbw0|V%~1b!r{i+%NV2JuCOVto-Eu;1ovv2yM^Fq zWa0iS!QG`~;r{uIEIjvMYw~L*&uc0d7jm%KCwR;W9=j4BSItF9x|qA!^DUR|`OkX} zipHo`a|kini;XhsRzfC5!8=;;UTpEAmX2w#G4WbdUK@1@==AzTa}y@T-%4Prv3 zT8|siyhC}TcSI&WKV}%4PeT}76ck-qO7>zkfE{Y}PR{g>MvRBp24}81>P`3F>b(nu zT>@mu{BX1PZsb1C5oJW&CShUXhN5tf$ahS)--Qu{)}P!q`7C{ z73i;EQ*Y-78pC)L0AU+|MBAIYTjDe!Onay$L$qB4z)#J;wNP`cY5uo`qSFtw4N$QC z)3Rt`m~(WGFlT#I0KszfJ<89TdpK*EhAf~uFwzI1~P0d@x8FofF9Te zA{Zy1Gd2mw)wrVJ+EN99EmI~IV~vDVP{}V0Knf;)WXWNrK+V@ znO?47E9!-9nSyNy5@GvQ%U(@r_!-!S0kENEbITq^TUX1T9@^L?SA5In9&A_jQLqh1 zqOV)NZSAKCVM?o4nO*_FA1$Xam5Nem)wSw-unkve>s5KKnyp|PDR#G>*LqRwt(wpk zXJES$fKjdETW@CArnXYINk7PKB*WG^z87uf1d0ocLZX?iceKveghrl$Z43Z&Tc2o! zSp?c%Y<-F1;|FY`6l_oQ!ba;sz%~|%UTb{^mDo%j>~5QJJ$0j7Orv)`r&2n$VTl4@OJq28l zIOkv%6DRKi=R~;I_G#tc#O|DnbH?jJV|i0H?T>>z0PWA4a;~5^Vja}V$HZ=28~%$f zL{p7u9ZZg|=?&obTKRXe+d05FMi)vV;6UEw97=Bhf7Z&!#cuZ)_bgp#JOO#$0>=*M%k# za5zp&Pop=0n7TeGc9)cue4@kYdIXN-O(iSn4PZa5d`j%DI8+&@3nde96mP1)Pz#Gx z+zVf5<$uKP>R-eCbfK#WsN+px_D0I{weo4PyLLqFjk?e^6bMPzPNFw}muTgG#qPRy z>O8v8wY;hB(O3zLhc5@Q#v|6{TKPY*yJ2pFR~NdDP)t<5t`nFD;4p1~6T26$Ui_0T zbUgvleJ;j?NdT6^>#)4hNgI-HK+j!v}@)qD|W)aCvKj6B76Tf6`{HN6hQp7K@QuS+}Pzt4gl8={? ztDc6TFoM%2ny*a^-IN%bk{FuGX#+QjUz)Eoztkr*O^s>3O^Ioq7iTm-G1z=>AjN!n zjUzF0Ibu&i>>cL6`h;$d#{Q1QP7K`w=v47b%N3RsUFcSYYLf+1D^SY2g@Z)lYlQ)h2>t;Ki2roDz%All=~?MT^Yt+DrXz^gNN>S|Bv>dT zETI`#)4Y(Ag5;jb+>|}t-JU9ihYC`=5xbJ5`iSA`y*Wqx7t^rID6N&GP^Rs^- z=i8GeZNR-*Y0^#%@r=?TQQAk*3xC7axI>N7NlE&hA{QR@8~I^Fjpj>4^MF_cqj{WU z9vOw}0=J5L&5O)d%N9^Pi&1PYfQM0RF7Bb&OlHHG6zfvWYXtMBM)M}oye?w6CZEVt z#)+WOyo(PtCt{~VOqM=Ap{MmbbzUR)&W)uJK z`~LsW`}sW2!er*&@44rmd+xdY&K>99iW6hdx?r~JawKnn>n2xw92$)hgpRkvb&urg zB)e|6;&HAa&A74@S5GTES9C7RHQ3>r;B;Ye?Vc-06o+eaVrw9_fM&a<(eYcZMGlwS z>3YJV!Z-&|kd*3*^BAjdkX@w|6X_5-bsbh*$bc>}a*NSE@=5g?RdSDm&a#-!)K+jX zovBnEo4Kr#3Dnn_I@qC3kklMmB_Ut1GPynFt2zTZQ=gR7#fpkC+&#yW(Qa9)$DtNU z>T*R5)CaTGRira@r+TPXXX;T&eN|Sgt#}NbsV5cneJecaO#R%U{@|pc_PyOnXG|OF zZ=@)9BZs@G(|v^nIovnYQK!2F>CBx0ow*;7-JK~W(+=H36gPGy-gBJXVzjS((tXhV zg6BWbSvJ#|`%O5Q&fHjrvUKMD{$Dz4kmdfnmBVwTkvzj?&j5>!p%YK8;+brPC!KiaIXsHfvj~3dt9K5M zS|{NiAF0Pv;_y^BJ#mYQY0k5mbmBQcWzTa|_Pj(} zw=WlL*?OdW@P7!_8VkV z6<-b`gAd4fRIK*CW@y4Bx~io5nERV(wrp-(qZZC<<8Tsh}Z+V_t$i8g#rowc7r`>#ZGA6?*ud z^h7T(w|C4mJlsc9sF&D1rJ&OS+X7if9B5Y-;)eVz>&`t%k@^$yVb-OE?1>J6i8$rF zYI|lUmt2HfS8RuQjWM#Kx?o0?Q@|p+z(5$%ASC}w`5RYryq1*#=Dbb*2@V#m{0GIh zicPU#GiO6`tu|d|lO|><*S1h3wl`N+ZbHV~PlQ2_= z*}Ow}L{Wwko#mCSOroN!EK#08CjQ7&Cn;W8Q79m7uFF!EqxICC3R2iLjlxMvxuUEl zF2-wMIoZkO?8(y2UhvbZ4gO>|%Q0ByYUel;wOF&1p`q6Dt^o`MENXv8of* zR@W_VXD)7UagkZs&Ur{=mNN+I($3C2va~V0>O}r`-O}3O%=6G=w?U?6afq|C*z{^% zHV_$K!OnN?>?}7zx}D|386nF(^w=$s6mqlaWrc*XVkXo1Jb!DJ^8^I=Ty=g%@lp`C z6K_gDM1$mKsv})j^S6l6A@XOg`L4z8#!%D{6f-h2*E4W3Gjpl98|Lj=K{l4K@2(B9 zT&vPu8x(4)yEljGn5MAz-gPL|wVV9dcRt8h4nu-Yu2*cXSJW#^#;@W|=iR&Bpa*Qr zGdK6}nLgJi2z{-?bwQ>{^X}I=??Lbut}j?wl3m}EUq{!kV^W+hWOet)T&}-yTYz%) z8CPDEtzO5=>J3DM7Wp>yek5!tGqu*~YPO>G0z%^AO}7^6sOUiOPE{WxPbM$D04J$W zDe6M<@?=%~!ir<2PxTQ?hZ^fr^Upv3c+wEgp_a<(O7dog=~T<`{0??qbLF2R04V_h zUQZ72wyeI92;fjJI@D8LsvDa8WR;~Cp~LgRzRP7?#g7KJZ1o4k_K&QhQ7{$aa5t3Q zDdY^_M#Lgl@ewp2Mu*Cuxvz0IaUVj$hnYF*cEE|O#g`{r;%?-qQ3qni*ynCvZSV29 z!=0HVs=JTu?oQq;Z4P&i!#%9ai&oNQ_Xxr)QHv9jg4v@6vw5<67Co`-bGV<7-B4+d z&kboWH>AyWtN27^adNb)WVc3iX0*>b+*`UFHuNpKw-I7R+U2T5tYUN+QvJO9HP3@c z^>9k6&HWJ^%!=J;Te#*_xH$K(cw|ij?Q5plQ~brYB9F+o@jRF!dm2^Sdw$f}(}c<& zvl52adKkfY#e*uO=h@Z{PZK9S_PWt5n6ukEJPy;#oY?Nnck072xo6Fuj_BBX(I*k~-H?E;D7C*^V>l zmN5cMn$wHHv=GCn%@nZD(o&1pPX66U0OQw@N7HQYEupy%Q7pJ`&{p?eF+SRYo@LM}Avzk+CHK!_e2fKsPmq!=M90WAo(`V-#dwYhdAhJre+$tZ zKr=iG#Q0bXqRHp(iY7$I0@~o&CC0~D&~^r`7NX+-)p))X~*Z6QYj- zdfWGj7@uZAn92Zjy%3!y*Z428N)xL1hI z02uYJ6XUrSxY`6C5TdyNPx#M?@y9IivLt^}K3*2Xh>?1@U2lx{X2#n9Rz&{Oe)B?P6#7YwFSfw%i0#cnbg^86lk+=?@g*h_?m$RKA-V*}#PCcpzSKgd zn{qxVM3(}r2=5f*PgvkK0`C)|PXKv0d|r${X(49_=_N#;lxrf_Mp}sRr%WVr10fFy z(WiiPjX=*&TL{xLkf(t>7I{XDFS8I@Pp2@;fUJ(7lssc0tdszG2FP2HlVV)95Nrb~ z>ponF%0T|i!$u3mMDnP9>po71DsoL;dLFFHX(7zIfH;8+&6^~~T^2%Xf!(JGQ5TR% zo+ids3n?N5hCV=ussQ)q9TDSh3#9GcCg=wEWge<0j|H;o3HzUNgs4ZZ$(QnP7UNzM z%x`0aB+v`6e}0Y__gUbmTF?jZsr-N#_gkRH0OzI&Q9rLOs0AYcw=PGq z%(FnVSk4_UMDqZCwj32*z6G+1&ijoJ&6jIdT(+XA7+-EeE3Pw{#)Rl{fL&Jf7UL@{ zusea??}g|JKvP!C5#t3G#Fpy`Dgczf0<+(R7F0r^)RjWC5YYY=N5y!N1-)uPMSw1? zz($y23u40_6=D?2H3iKIP#Kq)Pywrq2`T~9uVADYk6IAxc@h)_w75VPjm$K@wf#ZH^2phg=ie$_XU55aoqxcF~MO%RF`WC zZ!AOuwbBF&Z!*D=LUbj--h~f~@l_U>WrCxH=qiA-3Kxm-)fPC<1W`4v23TCUT8yu; zz__*N4vX=R3-Cq%ab>{~KOjBm5RhfHvx5ZwlFP6^bv-2$2VynhJM?SQnBQZc^6 zf>xQ~mI%=u0ADCU!Kt!9R&bEYCxvJgz)K~lZ+2RsS>G&JCPa72HPO^)b1}Zl1f$oR zY!xB83t(onuNZ&U0(%v8sIIlJH`0(7Kpu%tQeIF(dPjU ziH#BCFIeD66GTV%1%OY+R5AXd1|2s{5kfI7=OhAXO>Si}Cj@aJLD5CPd!{_{qwPV*CRO z{Ja+YK(1NUXw@}h{6iC5btQp5Oz?gPsN*UuA%A2+cN^gr>=vRQ0UW&wqo|K9kd2~{ z&HIGt#{gZcu-bmY03%tz)*9pZg3eg&X zOIJI^_$doqW`;Z~L{9-MUA;++pSHkC1DtOYqNf2KUHzUIKVyM!8Q_A0Li7y4A6H|n zan=H@u?EI|XXTnT&DWq!_}m27m~Fz$AB5=V0Q;^%lX}hq%_enLTOoQ5;OsR^#Q1p& zTwunDq?`vBU4tRz1q)&Rs+oQ*Kqa`S72smFq_PwXZm4==NC>sg_me$TKU1wJo$Uv zG2^2&#{Ea!JMbKK*mFvM+_7At1=zrzp(;O{4Va7{A^gkJkMhZ536@SWz_>|~h z@@dy_*O=fiTO2cfG!n#AUy7h1tZT088GHOU@WCV)-mT|5x}L_X7AME`2i|q#DjLkrTsM)~awClY02b=?Btk<}{A_pxKxoEL9{s-o} z$s_(J&3Chn2V$1%pLDg6tlFyWBgbH~>q5*NH>GDuZ7r)U=n3z-WBEBFUG1W%cfw-| zBlD|$=~+^TDC)!XL}Y!`wK(-s-3)a%p}gd=zM}4QsyjgNs&SZQ= zI8{o0l?WW_Yfj^-cBMrapnjxc0yX{@6S#$X%2-iSzeI>J4)r%l{nq40Yb#Egq8|Aw zmS4C5ZoB&`1pM0w=)T4{CdPdu2&OpPw@U7o8Ki8DX8~yv+6b8CKHbXYK38oY)s$1+ zU*kR~+x-)*Sa}+?a(S=}I;ttJ(zGi8j{}PtnGR1k$Nbz`y$ne0rif1*}x+^l`|3rVq z%1^4Nim^9OSWNX`gTlxuYz2XiYtR~GdENlq_hrvpCRV{0zo_ zW$2v2*ozrx$W4riAl2JA!I`np#4K;CR_WgMvbQZ!Lb;>4bnktNw=)rv6ViGg;vL?h z89Hw=9cM5lG}SxB;K)L14T&0GgY-sZub-%B(pd2>CmLEV!itXfu;jHYh8<_kmA?z$ zPbKfWrdBOqQEMQd_TA^}=Esgj$>&mhPs4|u5RO&rY#(hJ>Em0)`zn1Kl1<*X-Rav3%6*2(`}W8_ zLb@*qK0ydag&H0y- zbED-nYY1DG-`&#TFOvKb*^e9=GZ$z3oMj5}uT=a|_{ii#3h|dC>c0Lx{&)S)gBSZ` zy8oE$e~p6Cr+B-jWcfb4dv5;uLC~>hd=|cMo5KM zjQ=7hX&{(_yPm>KF?bn0QyaHsBAe*)RgKC zjV7o&oj?|fhSuQKrsGCs$9KdR9=L&_4fN_XuQ#%!=4_$o@@_PFV9$!VY)h>SzDX8( z$q{->3Bl6F{^pqltLhYb&lY+w#Bv;wzE1>kT$U2%k0&8BK{ALQ^s>#}&fL?zr|G zS8*yk^annynv&S_gZe#uof5vBcvA)L3d0~lYE$vJ8~pb=!bNI0gkZ-W22)44TnevA4abO&&8mNEzhCVPZvb*N zR?oP|ea50@_$@VzhSLgvMhbtD8h*b{c%@tU2wDdm!#l(0Yr|uuHY*~eM;f~#sPCEF zSb0WO97*RLkv_SRJ0a~&{21)uZN-F(3`&h;Cpd%FV452lW@Qf<6%(#)R%C8^H9I3v&O^g9_5w@={WAN6Zs@bUjw1FA84B)LBpf>n7yN)x7b>Npb{QvQ z8#e31p*zVbDEY-}a8JYi0Ekd#Q?$$FGs;9|n)7CxZU-+afG8V+b|w5vl(=ysgO-D? zTVwcqtbA(MdZEt5r_<15yB1#b?=SGODHqrs^^Jmlm_UazAe;iz6trF}1j1=}RRkYU z2YasCKH)5$8q+}x6TZPQDQApM9xrNF%V(S^PP?-$XP$rKyoR3H4-#T2+1V5&)FC;W z;$3|0O13hq9Z% z4p%pOYzo9IejP$Lg-_TOv&W_yomhCk4ew_18TCrFsXaCggm_C4dT0SJ2mYbU%-Pfo zb{BYF?Npm~o7xwS7`hI{uP4r0QRgB+Y$~e}h&^TW7w0FKQO+2o8%Qz7y}-R9p%3>`H*L|OpP>);Q#b$yQ#hoLnQl>Q3z;T+ay=ePAD(&i z%zlPGJWKd?vB}WKtO+ljVIl zafk}c@J@IQ!M}OnXY=N;JBp)sQmsC`v+!)5okA(V+bUEX+mjlm%)`@dq=qTWaB$3! zgc>p+*agoeZ%RT9o^QR>r=Xvq2G0*T>jr}triKDh>i|&}dzX1NOATHRJ+q&o1}|Rw z^J*#W^v0665XWn1w?QRScHsJ)vroMNlu*fCVDqQ%a(}#`jzLb6iBPG#kGRzvFKTxs zj~8vC)>%H|o9|oZQ~8wGe9)t#tol?6i62SAiQ3(uIqLhs_c3S|!y7ao`#xqA37UIA z^O^6QKan8cf9RS0Sc33@4d3s69;bm~!37@$P4nBzUqXx5#^02e{MWL2ip%ojJEs0y zB!8=n*nF)s^`THYXJ$J5_sV{ZI;Vc3jAdc6p_r>Be=kPHmA}$0%Rd+)ACdgSGh&Oi zyOToBko}XALM}?dF(v+ajEVwg`=90={-EqviHOyd<>>d=r=q=>x*XTDoc&QZ(qT){ z?w8N_kNMvXPPggTFm-EpVZ(`_Wy)s)Z3DL^SzlN9+#l#+hfbLi1+5!=h6IM&p+VE9 zJAC|s2%REl`t*R$CxKJeL2}5$e(*ULI2T0bbGE>@?B2j;3!sN)72zOsiX+w-iy#Vy zkd1n4Ete96jR>*%(Qv35Ri&M-1mjlH0nU;KXru1l1G02jE<$bTe{s>Xl~dnz#P%F4i6QR^e0 z33d$L6MWPv1K0|IXZB+fW(WK7ZGw*q&4UA3zG(NfQ=XH8<8Y>%*1esw8@V(Mxijq| zXP@34!B8OjgXfxHMd*Z0zc!IWXwS0cGoePIE0S{PLHINewNA>Rhv3sG)Fmm09)?dS zlyp?3HW)s|`1cW_vxU~PyO5F++6ujzt$1j!nFl+#l+Y{x&V$gq|79NZH=3?&%7f|8 zLdy?R9!!58PY+TaOh1OFhbRxGpSJU%Vng%j3=Bk)-wwVX{3)UN;E5pSqu9^Td=Td+ z1TUDH-v+hKxC0leJ?aJwkHxr~p|WA{UmSiiNoB*~6AG_LQrQUj ztP58psca;C{)ljf3Gbk4XpDR&(g6SZB05_{Vt1%4;y^5>$|7WzWVTRQggOQF%r?@4 z{QhOOLkyJ-BbCj#2=$C4mCg7OPs2%NI9HX|Mv%&KQ|)}jtP!EIM<8U6aG&s$gv!F% z;VFj3Ok)i{jNUpHpqQ~9gvxR!;lfNKsVoOcnjcxZT(aq@Ol8z5yj;-6!M`waNQ~te zTyi5@Ob#;yZ9Kp?BR`3;aTa*q1Q!e11o=!}!@SNSIs)X$=jLImoZ?>ai=a&e*f(#E zh*r@Au?WEga|_xefX=*CVr+&5V%3p>1%fsi;I_PDV(c*se8B|Q3fdHaHThSHu~`;~ z6&x0Fo1jgV&*Znr$LS|en_zwy6Fe$tj{+Q>kE4rbTOg+AS;&KeHVt4&{$VjDTi`Ym z{8-SY1AIIG{p4187Q9a6pUVFk2brNyZp*)vPvcLF5%a%8wkI{lIqdap@Ia2vyxh*` zpGx$IbHU_~oeYc)aA6!^pE)06 zgD`r>)6wf_gl4uG>i+hq`_U_#{s4;0Y~+6_=;k1VozW9_j3XZBrD_dj)NSHVl*FqVOP0bm*8i1m$iKCS1u{LxtU50T)Y6SV~M%c~@{ zB!d#BEuh9fS6y!=4BtTRCTdF|tnM!Lpm*xTL^9a8E6Krrpu8N1dOnC51or{SU7Zmd zt1Zs#;C?O5eZ0~JZte6N@KJO3FE|U6b5pHwId%;HlcC=TMd7DCneCA<+uOX_{&<|@ zJ-1G%2xI77oTI?Xeo_#|d-CC>uc^EjxFD6QjdB#%q>U{3MzBU&%K zmMv;e%4a=qc;3lVU@1lvyvE%+?4lTk?Xy}OmhkyC*o~|3DsLN zbcZSAQ@nRju6K}0aw8*|4wBg!dUKQHY2F*n^3?P4)Zy!Z_#Al_js-kt51y4 zAV#HuY7L`8_c;YrdO9OKm+QmY7b6_U2!913^bdBV5%BV-<@(c1l9_Zoh{L}}@^8za zQlib%$qc#pzHI+%=0ZVN@Mlv5H zPh{w~nOvNFU`uX*>U!c*%%TrwO2JO`qYvVH2*F_)dWIR$#Rs3s4L)NAEF<2*7)aLE zA$cP=_=ZVR#YnyY2{OK;$wlQu&2vM|O_FLN33cZkp?(?qU538p&@Gyq4?U9`vf?_< zsB}=RV^mCyAbBe{gymh9j+2b!H_S7-#*SSVnsPOzuXXY z;f>mY?EJkryt`Vv7Ij8$K4lEL1T$wy`Jc=ApAko`7v^q6?P>Y!3T}lMy&m!!Wtq3F zxSpIz@-`l@qU{O{BrJJXbdgqMnDTli5@Gy6uYycR!9b}XTQ2BbZJ(c$khmbnlo;Ow zqVKNy3g!{+C~!#yC<#U>>%o}p&nnPx@Kj4j!Fs7+om{Z8E~95nM#I2}1JS2a!AEkz zJ9UY^G>Ik|M1_r|Lc3gu<;f(G3U4%tW|>6YrNaB=LQDiE6FqDaEg`vuOh+NCr?+Vu zAviZmg{2wPZff&sRyVg0@-f@)M9X$f3y&DNQiv@Y%)2LYrSL00t?&n}1?U|`O{Jo1 zq@pY2B9S7d3{eVWFX(+p7qR_VG%f1jDC#B^-6t2}rN|`FiXKW9&6e4;Xo3+}(Ht|b ztF;B0jv`emdeYLcRgV>|;M0mU!!C-<>86>BrK0_E(X*BqXt9cZEczWi4D<+Nhk2|L+Y%FP4CmT!dGgMoGQ3lJ#TS&DfGo%ve zylxYLqsh}sp3+(f$lQ`5r6dnYdDuhmLPdl&7hk?g1eH?3%q4%T8n3rOiQtTc%h6$KOmn;M4v>;WP*)e=n zDK@!o%Pwlq$Y81-va@L(U`(pftvRk>VFKsKco(WS>RmDrz#D>VlD5 zda9XQs0s(@x9b>~TH4aPN_yvd+RDSw%Oz^Cak?PhdIC4GmiZz3L)TppQL|-+ zOIwz<+lmbvW>1B;m3Aa2N8Ov!d+?yQW_{S)((ZJZL!}RqXS(S*(eN}3=GpJm#3G;oux(9_N5La`VPEV=P2DTl~&bDExvXBI#aTv^n_H3rkT}% zNhVPGHJ?`clXfTdR@aHC>oDe8>Y$g8^*f-Gj?%hoQ`cQl>nE?!??i>Oj^<&E(L25( z-ks7y#(FOtL)MK%PpucLiX7{5rFB!Jb>p4u9w8odSqg@q-Ahd%U% zoNZmGtPxmZXt++po!LS%r`hv~IU|9rl_$(H278oEct+61wywe5%~N z?g%{@WqI96@463&2ywT=H!iZ*p;xu;H)$P8MxEAdVA)k=s3>_o+mPj6Lzc4UWd(*T zWthD%WVyFimQdNM%ie0+3;F1%BH23O*BX#$o(Wp*#h2C zrb=a2-s)DfS{6$$D|42uLTJj{bXanr>;SnOWp8@QUILp&Y&EQH*$14n44Xa-I*!XK z`%ik=FU~To%`&fhGXv!U3s|1&Ek`y!QD_7#zmap6H?gSbLz(5B(#yL#%kQ!LDAMww zM%c;T@-azaa}jomMTbbsm!+5coaIi_D;)u`Q2^4GZ}OC{sg<_83IR7;REV_Ofb#dD zQ)9*ld_HUGD8HnZp8?5Hb7mKPkgW1Q9Titg6?V0PjPq#hIh}pZlxB?4WHhO0U2T6# zY$R3OsaD)V1fG3*CKj42hF4(fOUHIY3~U`0^Q4L?W(~wDyNajOiuo2l>?O#m2s>;h%A3{7G)pk9YNt9g znyhJMz^E!Ku~UyVY(7-qmHYX$$``c3IK0nMdBR=!K6sdBUwOe7anHn~r^MWjd8a9L+8{*Q2V&{f@B2VPVhV^ES z;N%Z#Tbkm#*)$E2yWxE^N2-w{8-9kce;GNlv5A{LifswIv6XY9gIHQQvJo{5%aH>l z%ErN_C>ybT$`EDaY{$lB(#ECEjbx{_qHGMBqLiAVY^*dy*|^&fWswL`HoniNZ9J)s zA>-KigL~uGwW4g|oEx!ou2z&yO_N30bcZR*rUxuhHa*-*-UJDke91XBO_erHaBdo1 zN2X19Ylj)^c2lNJ`G!oJ)|l#<37IxwJ!sSGhI%%gcGD-ME%j{r+PUdsvP_#BBpdAJ z7N$&_+gmbiexQ}Sxw|3L=3&z2fzHiYb!6I%W|hfw$dqaGGDD`#5mTmO$h3J2pSF3I zp{LD9-J4&jm1*-w&dnIG)aq$7_7T?>qAiU~nYN%NHL`3=Ta1UcbaZXGl_0CY@bK%N zy2aF{@pGU5ewr!EORo10BY|>yG7%Pt3-ZS!cn>A(i1oC!! z3ci$VPxNoM-z;r!EpNy4of4x`=-d)}5&c_agk$@|()K=P2C(trcC56qiuMVN53{!~ z1|wKc^1N2JtnC{e+xJS_cgfq42}x?${z|fN=$UOlBW?fKO20X_%WS&c?40l5rS1Pk z=X^&KK5d7?82jzG4bsq@z)@*OcX`KsRthjC>ab%-+Ky3X>om-#uOH-oATEge;Rq^g~A z)s||zYi+^~s$NdYL9+8Iv*xe5Bvt*p=FhJBhfmun8cE$LSxI&5>@4lPL)v+(yc4aI zYb|A2owRftuye>xnu4c+Zxt`?oGR^{An!!YR7;%c+c}5aj-86MbBUD)mJRM)ju{Nc z&Nb4`xV*EdP8xP%o-fG?cfKj@JRP zN|ScoAkznllk~L<*~{Xxta(>A!EOkdH7mP<)pqQrG3(l$!DK?>A55OG2Sw#DtX&;HRP;g3D14?-1oJX@Z4V# zKGbS7(uoRTx81S3nY8;ldH0pocK4=)A?&6eJ@sQqLFkk1zI*orwfVI>OWNIA-rbdg zSecvY+dYEZj@{Fw-Q()#*Y2gruH8Oqw@coQne^nCijrc&cVc%)yEn_b(LqV3IaDVr zcAu1Xe<<&MyDrTa^|E63-$qvKX>2OA3R$tIJ@43aXCf>1^aYQf&8*lnOWHFvIV<)o zu|iT->?uajl`Jc0bZAX}cgxzF=h(YS+N;TX3+hO;cTq=+SkId?{;b5&GJ4}-ATIHXI0(I1W{-08zJqhKh24c zrlJpxUXNqnLTTTue>YhB{CwKJe4`-mqn4lQtdFIAJLP?-Aq-Kd&f52K+PVadmmU`eL=>XOM zSa&jEsRz!rbR76mI`EBr;EQUzZ+OB~57GdXOqI$hsrlg5hMEuFWU9FgYCd=`?>N{! zq2`0*rGum8gTsiEWx=H80rl^yPT`=^6 zFG>dw$p`n;l@rs$i6RAIzLXB0lMiCAcyd~PNlFXvICPzKsIhzq-IXMoLr7MgI_J<` zMtTon?9OTqO79^|`y9fwk1<1}99j$>HKw5-ib;o7Bpdpnaw{Ym`k})J`pUlyUDVw2 z*=nxGP+X5xbG<)CmSXt=`N-SgHOKIx1zR4@#qeiG^>p1U z3Op{Es{5Il3dHCswuBr#FDE&=rjUn&c=T)!9zENFN6(w;@#uMv!DF#NJTS-v&7d^= z8DSQS(G>o53jZSgIYdlg34zBgJF_NHP@eq2u&+7rIEDFx$iKH#V77GKAXBdnq+T7(WEqupW>e6>)M=1|r$J`ko}?L7xShmjsTGZ>>1_C6${K$)Z46B* z;b{lOwaJp4SiNeEHaLS7Ex%_UUdeVl-%ARm7 z!}?}$yoDt6#{83!Pv~xW$lCiX!=+Yp{eFYB8*6N2?S0A(FOrS}7dBlC?)QyleQiYhS3TOkO_Gd~ zwAc4;qU{LUzU}MNqMBg!2g?>4ides^aY?nc9$c*vyk83h@7IiiTc%68?$^OGt$y82 z)A|w>4uBaHbH6!>N(T-Vq2D&E9XKnA?ds&J2kt71i;?~PPBJ#=Z6;QaMa@f@(SJLx z=c>7EnzuJrGbuCre{6UqWrl!M^*@j6tK`h+{|ln;|MkB!BTInbS=Ry0YK$~zp~8(+ zCS^sIRppvZj1M#zYey<6Sa%B6#WG5>*rI%74aSfXw+V!gA-2Qovz?WcYnYq?Nj?z= ziP&AAcx7_7VdMiEstB`ST(zrXa33?(`KzJMtY1i-S?CNU)QQrBe9TU>@-h1kD+tTS z>|qoldyJKjh$Q<7`m+#nWzQzLEPFuCikgq|=D|L=9>j$;SaTVf^5(&rhF4PFpoNCt zLM!qI-Dc#+S>zAmYsi4htwQ?Xvw(A`GXj|&{1jq5_#ypyhnz?0>4kdvX~~wTW<||U z5)MG4HDG)-H{?A?h*fNeL=p~|Z+Mvv*MKMBU)yjEaMo|Q2INBv1JDD=|CI7zKpA8h z5Vx}5tWK%n8n6r3zGV9w@G{XJs3$K>WxzX>`2$W9d=mB008D%@Z31jh>PnJZ#8vG4Z1=6 zE)gFm;@9dEpQ@7)WC4RkqDJ{jE`@{XZHIhxN?RGFaBv4IQ-e`WBuXK5RpDi>DdWjp zRbJGJ6@>_SX~w?VGK8%QoIUr-96m%;CnRtBFTnoo)5!+Nq0#v~Y3 z{EH1EBH4#foj2t2y0Q;xVandYkbOuGl4MB#B-xGjc*r~ojh!X`YLAC3v)bb!c|_wi zV@O)Rg6~=?>OQHVq5j72)2&m|Y)1}K|DU&D1gxoi&o7?BQr>)&N_=y{a0q3EO)mKr%W6jMG% z*J_xxK_->u*szwQr(xK)lE|@P{lIltPb6g+CJ_r?Ov*9p*bSq;;;Lj^jdGWKGz@MV-MB zAJnr!BE_~wbAJa1=SXOAWIBA3-n{Avug-|&ZLSxdGO2Glav<1^%tm@f_O7;<^h+|V zkvXPe(Iy|#`bd>%pCQ_%^=X%zw6xcUH8msGr-QDFh_NbI(hvAm*qRCF2Q7)$CFIx0 z6F}yfQ|9J4X%q*Aj}pys(pbbe>Yh~m!M=r(ezb#DzX}E98Z73(a|pBIQIm)&ho~^S zl%V=tzm`~INe9DRU^FloHHWBjlc>(=*AZ0#sEmQyC?5$BVFI+_@QTW~cKUb(edI<2 zeFTdEi3msxNbyKVaDSu+k=#!tos&qwUETxsMaCD{S^z#!;>Osiolaf8(N`kC=!QuF zSkkDC8{H1R^B~IT`-u@?iAS$b-=s+Os^k z0rPZluEmA=&s;yHShg2`WXAF$aXXmcb_14Vn^P=rlmF3Lf8R5D3yvCy(U^Ojs6CG0 zE;xR!wri_EKjt#fj}dC=k!=o63sZ<2^YI8arac8it$?qu!<9wBh;TG< z!a9o4dYBa$V}T(ABE?IfkbaEHq{l)e{!l}=ZPa1!>yyV!Bx&sUYI}TW?78B1@#?-2 z;%NvuR)O~%q-pF5n%Bd94U#st!YrJRB0*y@!HUyq+0c9Jcf=24G8TbypJ7j9|Dg!J zw<3UJoSht8S%l;4k2l6OoU_kP;q3EVoPGXXoPE&?oPF_2oPEjboL!mA*7Yw*}hU%*IyuI9#f6m@zNmNwhNb+yqX zExt+63W;Pq1~B7`%=bPFlBW%lg*OUX5hHmMB!7x1F$pebOp;p!t(ZtAbjCH>d_jb9 znb6xL=_F_+jKm9)^`hP~!DRwgN7#H`PeF?^60~y@dx(0Q1j$5Nb3r$A;UGcNh-Bg{ zTp>|!TT8OkBpD}YF-G!MH8-iL2u%_|iJpiio^hEeXmKK$Gz^zt)Nf6YOnS^Dc|y>1 zM)F2AH~Df=Z(mDt(IoK++DamsjI5dL74_Q_B$Khvi$zo{XsZ~>evo`A>UY$VylIk@ z3EFBRnQ{}Zp`zX)K{DlTlcY+})-aM{ki0KqgA)OiqAAv#Lbaf+C6cMv;OZ^vof0Hd z6SGc&R?0|VzEj^8_0F{<*gC+(Jt=7Gh~&|$a7_{QE(wxHu@``md?{#UjAT7XeiN~y z%97<#%=9@kAqL4JQP3(F$wrWTDC(KDBnM5BR6(mGlIcj% z^q!*LH9<1Htx3{K(AF~&7f7l_y?ZUmDwCvxplx6z7eVres9#@8f}ti8_i91gNF+0^ z#C1*b8$nx{H!6e~sCs7H&U2g%_g3_b(#d*UGj6W?YEZuMYS2b{HE2y6J8HEV=4;z{ z-D@-BcPIRynHkuz-IUl6&mM*wP7VUni}Ud4$5Yh(=vASOsAkp-#)bNZ`u=!XsMhaQ}d!;QCVNO*0# z@mft)n$s2g7JC>A@IsC3TvKgddz+niPK^%$EeCBp3tkz{9!{L-;M_u9HfJB_!vx|- zLf|F#{=DSupP>|LRZzg%@woB;8VdLvuGL8Jd${Y&m)!J2;`ea!Ied485?^~RmOg`1 zI+-s=O@YAMFctVTUUpi8`wHAYWue6s?SOnv`BwSaJ-&;ci|EGMDm6N=2oHJ3*h2&D zb)prZ1r~<>An6C_rDl$+TuJUmqIOs=D6$n@Q8bq0!xQrm6%tw01Wrmq;&a4AJRW@5 z#{Z%gX+>=+=;h*ek+x`CtHEM_(d$JQZJctS!QhRei+I2b<3(?B+)Z?>P0#apNOr+>k-dh}>0}W`;%LT=Ki~AQZKqB8^42p-6gBTQ#Fc}m>q?^J+C)zmh7{g~5 z&*WPa&m?;{5=AHpAg_hxu9fJ z$>@?L5a3l7x?}=5D0B&o5C`)Z4I1JtnZvgznUje3B?SGTMJR zEPJx)kAXc|3jHm)7O&C0A)j;3cSh{lFreZcIJ6;1cbqW)oS+>Cw$h2$>1M*9Efove zoABQ6JZ!uX8*hlh`WAdnJI~uaFPmiGaf-tx?a$snVko^!VW z0Y2!`)YYz*7Kg{+3*|T9`)#cy*9{q@Y3(?jb0caW$>-Fo)Mn}jHje5yyzqB}ih@Sg zq_)Dn)^70%j@nV}0vtCp?C5wI$j3T>sTyAlBbN$P$x zT(ZLg%>#}Urq9wNE3 zQr*4ChZTS$hNfxUD!GT7v0>mXY9Gk&bLw=cO^%IWRWhGk$Hp5%$mx7rTn=@5hIcX; zq;VCGH{crNs?+gVli8T~YhRd4<$yjs3h8Fhx6!?Ahx+>|5SNhoPFy6{`Wv7Rz{Ups}j6 zexr4|UZeH-|Nlno-2b4_VzT`g?biAKS-WMhp})zkm*FdF7yg?KSVEY3ZP>;CZX0F@ zP}_`I0(|j5YsoJCZ?wn?w8}7rk4A)W4zVUKg58-+e*G^oQU}|W|zOhWr zrq70{p>Ur@oiAwL%jY~@J$>u9R6oEw$1~9$8-pf-l^S#+|A6P~`1c)H+B_eyJK7}A zN%V>InP#=fc@U!z!-kyK@z4*PS#9r8aK>bw*wB znzL_dhl_GZNYVb3&-v5*>EUiReGcLtYpb}3zAJUIrl6DcH_!$CyhJC+SknqmxBPmI^T*zK8rT)b_DrDeyVzKW+B0sBK|gtk|{kxd8o85O6e(#_llZ z0F6arFSBN73>Vk{m(|1ill8Cy&$Fgm4!l@x-`YJbaLnjo1wMdt0D4%lR4_gtI3HYU z_OJrK;F0yP0@O=Q@D7q)C3UdC9vv*CD|j1N>3HOoU>`hg#A8ZYa7?TX*>4b2$Xj(K zi0Qno8_~fEoUiy2j5xa(6Oh#N{%`z$COTODpZtFkh@X)nKHL8*`d6_A5Rwnr1FdV{SzaAz%?K^C!C5>~pt%&dE`wAIxp0IjK4Xc1HwSJDU?$lLcxQlmBe0tQx>B41 z4VQJN5d}?Z2YROkvW;<(K93V)jpcK}WkGKUiyB7fEa(sQGeQR=NukHk`_aMG!E$Q1 z(K!olmx6d3feFG&LvTm6ecL{qVwx2^m>zsp2|f?^8)hw(9ek5d3!XDNXTb}E)OOB- zU!#*1nXQA{&KQ|`oAqyO8Tyx0~0M>=^s{`l{7 z^0xlY*|(+R8i#8oXW#xfuIF%l!`XM_;QEZSSIs~k*i&LngM3oR(8hHc3V1kilxYw-`BEhuC@+8Z@Nj{gyU-qIvl9bmOL@Apu2w0{`zF6D!azlNzu;cCl;$@?Db2r9&Tm+4 z--Ws2SQE~Xe6UenA^^KaAEmk=XTD%>l$1z z#$836{n->mB_dW)+b^HX@0I`1^5%FmbpcvXc-rzGfs?5ve>Cn?TjkHhLv15vbbj&| zrRU3X{u9;qXZu<;ZoUsEO{_9%-263!P;1VP|5oxV;U0(zH-CG2{ysS$gI*SpD%|`R z5$=Rh;pU%Agaf4HpEZJI=i|JD{J)Lv+w!Z3Mp-T~49z`fe-?d;wJ3^Z*%(`GKwl#j z{fjLqdd0w~O%ri%%jl3wOf$yP^@Z|z0Qlid!dv9?${k8)^{h=_1P^2*#>5SUSbO+C zs0?kUTSxB2ZiCM_Wm2=yBFgN}C}X$7XO=Rz8D=a^pA7gcRi199FJT4&nmgcAq?9$& zms%rNIu(fp?*M3<@@z8?t(h>Nj_|2gUTda5Vfdsph}{jZW6Ck-aENPDK4fH+BQ=P1kvsX2K0tVn8s-?yRaw=zDq0DP!c*w zuHLe%J9&B9l-IzgqvV<_yT&u3Co0!sQhKzJiWD(+mwete$F)Fx7RHL1P1v$)DLL4W zQh~{$XKt)a&sWyMsz0z1E9qnBJ0#HWPmG`HIu+B^4Wx z;4lhxf_#vWh&|b1FF)^I*ZmSSR_sx=($cPR?!0)T6#m&!&24;X-{A6Ehz=)HgGj0=d{- zM97t+OKac#BWK@>LbZ1=d{Bk(V(exxq;qMnNA>Y!EFJ!sXZsCKJYaT-$K82?S(}l> zYwq@={|l`kkOl(nut4fSUb5OSbIV<9Bg4Y&H!|FL^% zCWSY@fngJ4_apRA%J0sb5QPkS%v18@Ue)jCDtol__6vUGHk{>cypa&|M&V zZVd;ccin@#uCU70v?rv_D5{)&Uk_Y`xL(5b7btBhvF_mZl*{QIW7C~rVW>k8Vm;x1 z(skDEY))nTUQ|`RkXfc>Mpyk{HyZnBVTZDaBs1@TN=dB??dpa z!oP1RV)s6F7X-mw4XrzI!W1HLAIG!*NhYuR1fJ_Ar8DQI83cFBMBUS!9n%P5xoZ3V zB2;v}sPnRaEuMPQF^&7T;HeKC)42Zy9Q{^hR0_z)eh}s-_n#gZl40~7fu7lq6o+|% z%lJ0jW$kpAr*`_um=>%o>+I1g$B+J&tb{4m&s$0y_D*Cp_Yu~g7f><8?)rf~Ly zFw=uNd~CRQ6lwdxT`*W1XWxGycW&@$ehro6te9=GFKQ_1zskiwbHSRp`N54*p;WQ(pB*l+ffzz>_ z1NNHh$1W5)4&9HTH>Vewo><;DUXY4C!gp<$6`1A-ERX_^WyG>$Q^=UwbFrlu?LVCs z@Roa+&WdrIOJGL;@kXPFW*MIrsE&mJNr59Q7|tvUe4If_kpkbi0_Uskhr@bF%o!UG z0Q;4p7%AAy6-0**Ks4rxO~`B-Y@b1Tk%E0)!Au5dF*P<30LCOxi4ewSj-)p z1OO9JP>U2ScLj9@#ABY=WC4}N6sl4Vw?p4zY+L_1zJ>q7s$(ccivLG=ce;fYV1VP= z2JYfp1UfU&8R!Wxi?*JWjj;3nu|}JM@zbNwbR++D{yTY2k3o05&EL|0Cm!er>dBaU zX@j$>+b}_6lf>9Ggt*(^!#@fkNRnPpLp$dwLE-ovyO$xmrg?6&sicOeVHU!f)p%bA~94BL=M#Ul=5cnS{ zgk5^b=Gb`eT+08@pK|EeYWwrIQ~!{wSezBU%n?p?h8x4rWf+t3>RPy6TDW7Z5MkPc z$J?ZEPnM*1x-N$?4f*`-u(0rgF#7D~ccKdWh83JAjAG5{E17^&xWE(*b1shXZY8`0 z0Uu-=#MJPfYWoW*j_|9_FeZaVL%k&C{kCT@p zeB4do3q2Aa-7(!<8BU6ebju2#m%_hG;V+rF#wO0JIMbEy8)+Qr6rqe`Yml8eDUu;Y zT9_p4(>8ooq^lz`(h(UfMS7Y54Q-u~A&6})79&js(GfL{$RZ^&Gm#)?WHHe=BFm+S zQ;sYHa65IUjqoeX@FZQgtjM!19g)|h$X?SJ6KWR*L_Uq2td0&1%tJr!#hwX1nBvOon3i|Hk$rhHY*OAsiR{apO5u@xdCT(Tr0mQ4 zU!?s9d=$n1KaTI_E{Auhh{hFhNeC?h8bHAggeE3pP*DLzd|T0ofQr5C_4J;*WcT(` zFGq5u2Lho5D=OFv78Joks73|5{+_Sdz009~9{zuGdiz)HGt!NNF7fuOh+iV!?;Dg10GYt@;W+i`139;4{QGPbt6( zMY#G3FvWbSSuFV6Nx+x6{_4}hdiA9h{K#7iext;2__1`L@U%jq0^V`mcq=@Q0@Q;F zhvOdZK{RqhJEj*-D7@l7I!@udNXJPpTvWIWDA@0WIb1^FL-HlygZHbXM6s|yD0Ju@ zCL+$5^uoHrMy*=vaC~TCmr%G?N0N?FuPS_9DtrY+TFH7<-Q%f+ABlx~?S-Er?vn@~ zKCSRaemr*K7M(|P{Yb|t8do&0h?Wh)9jEB3sE$)~m$hgS_&8X{aTeX(V}9jIvFH(d z5nA8NpJN+H1Ph!#o{N0;??$IY{Jk=Bz*Gv7OW;n7 zsI1acg%V7GF$l|dGL;pRUOK!KrWmcSV+0aQFBMAhk_kf~(c4Qe>oLEEo&0&JrB{ok z*E>p)kJs2K%i2*}sipUh5K1vkhRq}|1%q;-G*c>tv8?5dt(DnJ>lhbo5{4=$ebHLF z0dTEB+Dl&|m{__;D1A#ReIrb$rT&GUIusuSR%YPGr+&2)z6XV0%uI>T%7Uf>-Rr8B%kqO`Slrqzpz*Q?0o zg;-x-DSB_Td*@NAn$GaT+R=4})4K>5OQv`iN22n)iz!O5uX~_VSOz99ZJ0*$NZ2>FH?|seD4kP4YZU=#r(1yNS|TaX)SjvBGYvfOKCDh8;uj zPb`-XRFqbf(*nNkpQ!M&)qD(z6&=(h{>wjs0k)yc#Dzf&5GAFp9zotnaAia)>p_k4XpA@#;nDHDUW)y@Hs=HH8<{6e{+^Ciw}VU#C7$DRO+d7uiEe4C=!O;(_N?jGi3L(I_vs8v;4lg@ln? z%~LVKwXJ27M(j&c@p;#&qFOJhXxlsA^wk(ReyG|lUmxSEoveOnP(Spatuy=xce2at z9!25!x`lW}1C&Rs>UW^rNAJVf)V?0`E|K1m^Yi?8U)^N?Sc8A8AInRWB|oIh`EVQu z6OYCr)jvn{-#XNvD&N4yUz;DzXV+3~fSu@nI>GN?Mxf0P?SuH~ss2{Mzs2V7q~P+v z6H`V1+gAVUku3P%XLxuaCs>o_|A9~N{~5@mEm+pdGYJXp?@8%E<(A5qLz$8GSNR47 zD36siA@bEnPiK&8CVfb+^3N)OoiD+?ghS)1OaZpdvpk3e)aK3kaL5;IFWL#1KY`Rr@DZeL&BKBrZvE zCFP*Ua=f$ZFsQ1yx+{|G79joMtooHANRKDkF2Q(}pGt9*u_^3NdiAhs8c^`w z00tDX`tnKDV>Q;+k3j_z#=Cl^&O5#OrfN9Md^jMQ;jf%jeGlQsL}jEJnu=v4y*j(P z2pPYl-=@8}6ZsF=4p^yI&H-2*Uc0={{MzVlWebuky z?rS7SxYh=ySASa#RpSdW{J84xd(3ZdH*@JV18asLdM%>ymEiQ62{l+#^WlIk1jU+b z;%ZVfL}xmsD*ea>)YO{$6UCZm;%b%y^v9_jNldJHKJuAHdKoWf>e)4=0Doi=YwF`_ z{2CMM8u$iE;%YiHLTFH+eSpA`f$=rp)!7)M<8d`d!srxHdwN_ACQFo3wBo0uZZE4% zL1yuGH_5hksaTsDR}0Bg!I;voT`bhz7*`8piK1vQjy4-vO-ntf>D1cQakZ$0cN$K^ z;q+6_u7#i}>$QQnT4)3!*0L_vZWn61<7(Ugi(}m`WU06IXJn~`NqJ;kEt(WDb=4VA zb=y&ES}Uqcs=H7(_a@<}*~_FlSWs`pP^RPRE@z3uwV#(>w+J7@18;-h{spUX#)O{w@ zeG^yrCF4O0D&Rpb2SaKgc0^pjtYw#T2jakO7|9|4Gx*)BP9GImYKRNWWzSq(;ASn4 zNsd!+l4!t%=$tdeK(82RhzsOKGw*MrfhI$sDe#WgL<7yZThG>9yzsdMI{ElOr@RR5 zV^pArj|*(=F~4`uV5IaSQo8OGUVw?_~KS0kTgo$E4O<6UF-CxOx}|CrhxtJfXfulVCkI z%Pu$sn2-dC3Hc^)tnGul%47YM;i zY(oC zNHwgnfat2z!E{CHnhQp_*Fes1591Q!)=blijT2_6x#XNNYRwWu+?x6QRkCIgi>E4C zgKrwIDTrH>#d5$JFFV@T2wpb2O-~l^V|1sG*h6rW+PBV0^o?~F{zEsi6g|uE@xwBB*UoT<-FMVlC!ZV5+~slQRY5t++%Hom*B18?5lvz z#{GmsAN89mhInh^Uj%YJj9wiVLVKZfT%j`&xt*&YMw4zaG}9WI9$^q4x`v5+Oz3*v z7P=nsWH3w_i{AfgS_p?MhMu;D;G%nLIJp41z-uP?Dd|8cFQkOt3a=xD)X-a+WI`|# zqSui^b=VUUs+U5T2Y>WBnWi{0_a!0J9T(a_F=PbGE6J{8ley5V%*I4XP4Y8H<^9lS zp(bOZBl z9!nW^L``U!VfK}iI-{MLFa{>IOs6{*CmaC(ujNs*uR_yy6wOdBYQcto-2-iuoj`k` zC3gsX?uccKU5Kh}*=Y7DCo%3KDzg3a0N>iOwRI?pVrY4d-O(0XK0sJs69F$QSx_Cf zo|5cqXSO*fXT@L!fTLx96*)OFGb+(3-IRH>gyN znm4qLry%<=L%wxJD_Xy=Lo-ENZ`4fDS*^>&*2jd_6`BcZb$&<`fw%F&ht|B-VrHS@ zU{^(GE!8n@2)v6UV@J1kSn0gj-8eh6ZVF-VYz3*WlgairKECy1c_9r!t=|xmW_xin z=CuCAxBl6RX^-v;EaAmAlf4b<|C7m@E@~TWYr{I>Cl=Ts&p{LMIc?_>RBRh+*PbG# z4U%n3Zi6M~TZc`XZ7H_4%ZQMavb}8v5z&s#w)vymZgaFPK-kJM3o*C7AhoSV#zNW` zI@@XtN#zakZ8?5&%Ez^N3D?M)2!|C|^r+Of^~cYyLZ#oC;DYNT&U%WZ#DVWc;@FvZ!R%*xT#>l}ygec6{aq>n82T z+kcNtE5@`R=dJC3>h<|(ddHxSIEYoBSagWC4rKV#P5l##j*B{AFo!1=9aC)`mqrk1 zVv*W0U+lQW(E+J{`YV$S=|*bd9jm2|2O^>uJ7KJw%8$wj?aV+?196&9nCAnP8?%-oYRP3w}JM-&Vxed=lz*qcZS&c$I#BB;mofa&}065;y*LLt`?c^{&(ir9UmdC z`@^vg=Cq!BHbdjZ^=8L?9}zC;`-|y>#vItXpIgP zxc;6)&S!+v56fr1cm8cZc)= ziIZ*9O>(w$VEx}+#x1u)Fz7NQCqvg@3UaUzW4g}8gFgAqU~U8{rwhyMoUcn)HQ`w7 zp^Tm1b!pe7)af>{&tKF%N`42<&^2#EGBM`)t_2Zx7>qQRLVDMIT@Qkx-rBn!wRb(# zW8TviY3)~c*}H1Gaw$=qk_fFXc6l6KMZkGAs=Y!Rb-ma15mejzgoM+3e-gXC9on@! zT#sEavGyE_uE(k3hB#q^DcOf*WwzMi+HiJ{`HMlY>+b;FCJH@xNA@G8PzhPCU4 zpM(u?HltAF`j6l6yL=0oH5;J=zxdL`)GB8G7-o7?H;xiF&K5UbIcDP|&b4u@&gDPV zD%SWmE=t&V7n@`x`L=PX8_UFv>%@&~$84+tvHah}db>^A_&Saj#*tS2`f}s1j*W*w z^o*vKyRn6cN3b{|0aD9!*l<#!*gZ+=#&l%QU8KvH*^Qpiz0lT;IrN?q_Bj%%dl4bf zXGpp;K=Gut8%r>I9@i;WlJe_T?A=fmUo2%5)^2PO*z-6jW_7oV-917#7D&kx6g>=g z@9y5C55wKx3f*5u4a42XM|c0_=tfW9dv{p&n?~C=ofSzTe$yCj7~V9Qkn|x9A9ysR zZ(6+Rj!4fMvuQE!*aU^g7(JT4>CsKdR#?4ndfvGST5qqW|CxH?F=|PTFQKc_JomF(qs{Lubm=va z3xIe$xIP;PAzw<<%o=IJ`hwG|e_ zK3}wsqJeVjix_KO{P$S1_18pkn?c$N!{MuK(LH0^So^j(a2lZXjBVoxfqKTasi3&l zx@`s`-tX@jbG9wvx81vKS+wTbw!*Ou6UhDZG|jc`Y3sICL>1Otx!Y_66}Qmp1%u$k(fD(@1Am}FzGlN8DKdm_x8YBEw6JD8$ApFG2Q+cv=`o@@$&`lf zLA;8qHq!Y})EO#IsRZ;?9wnqMT;2V82%#4t*%_OA%->wfdJ5A;i1~mr^qC8PP|2+80&i{0=HkS!{6nwEB6*E&~O^jX0k^LMW^O>RX9Zn5v+@p@zqp0}V*X1$7QN3=>r_-%BOSr}gr+@`5T zgg&w3&%1~k9#M^m_=<2SrF}%fLj4Moy5OuIas7szu>~K>)NBKB`hz$zU5OY>%n#fK zZ3+C@XW)Xi@O_9vq%izMbfnosfzs{rLb<{z$JOsd-6NjUJjPCJKqH)(Iy?V zJPg1OxPC{o2)lkJA^ayT5`%moTKUz69`nHi+Cnix!{i0DRE(z?2Ks~Raj<5ITs;#{ z(t0Eky<`lGThKqQzOKi7h$pKB1-SZF1g<071kd-drDHr~630wjTOu5@@DzDBB)kX> z43#*-eC_90jXwJ9R?Ok{iRO*{suxwloGhhrmA1#{7^4hs<5Tx_y9d^PX;gm_ztH;;|( z=EE;?=B)|X@9+&=uJ=KwPvXqqorX*saj)de2e)$OLx&k2MjZ}2~$+~vR~?TT;iB#_I-wwBjx5NIZ~;_e2G!61cuj9XZC## zjQ<&ewVm~`x5t4NHN2G8W?myr1b`O3Pqv*c=t89 zOKfe58LZ>4wYp*Q9N8Z$ zw<4WG?n9ZgI9nHI$mH zn00a*Pi#4u&K%uFws%gVn3H7B8Qo((Hi(pBM$R~*K_O^CJUz#nW9RtHzjZ!tTaJ?` zBT1#^l#UQ{WJgXp7%a3+2L~Z1B;;WKZhvM20+x1iUKMj*6mr%@Wy6v45>e^uI3wqE zN=3@2b>N(ww6&*|;YDeY*{@x`3Kg`6Lgsa48;HlNCkwdF$J zMdcM51)F*}**9`@_9AQcO#s$`!<6{!``ONzq4P4F!ZcfOUZxkAnuJLXNWHn< z+^Sq8Qb8@8H{{k)fD~bF1Mb#RN|(!Bhi99%TO!<-&{6TJZ+Nmtin*^?bGP@H`^Hmq zfP-a8mKGFpUr&~Pl557Z)|{4$??L8%E`MR*49QY1yf=Lb*4!V74m19GsW)#--o<&# zIGk_IvXXZt1!!=|OTj%0=V>AWNXVbS3aTBTJTZTILjD|$m@_5$zLxSAGg{v_NxpA| z{3eD=oUpt8B{BakDgU)d288_2g?zZWShJLJ>+mU=thD_7yqJG5Vt;|`2QmLoDgOkK zX~EPCn_5^Q7B&clPzWsfaHC2qZ0E<}&G7HV z!r!GrXtEz2tjffqQ-s1l_41Lf5{jU?7%B7wiLdA!A}qRLgjjT^P=vF{7?8ET0W2=_K4?6MXspCWT6QAo*6PFCKd&SB78N2v5Y7=En)1MELz8pMbbZv z5Q}4kq7x@2T|7i69xN2c{xfMzjIrGtNf+Z}(4_vPi?0-lCq^e-e2q|iRdmvzgjq>t zM!!6#_!b5ei|-WlM~tdr>k~Cq{2=m{R&3|TndC;Pw`5ew`K7Z_O{iT~O(jz(NYzww z#mUu#zGF-;nOAZ>D(^7UOeN_hx0l?B;1L!SOCA?WRthEfZr8uXI;-Rbu_W7C0;wKP zVO3}=$;I=0mhbeE%91*mXZk=?(r7KICq$NWv1FrI(rznhCUn;7tR^f+e0ItA#MEAbPIbH-5m}}1 z#U4))OXKaO=Tclmc4?)T@V3&agl>{UQg7L5WrNEHLvot(EgMP!GDgZ^7KWQQUv>ck zk|v+95@o_dlP|kmESoKrf#r$2PtrqWHzbrT)Kp1XF4IG04nksjs7w~i0#X@f3n%W@ z^iWwaS`U?VC6sN6)oT9-VE<*w3F|(2IsX3 z-p8Y=+Um6tA*x#2=xw82-aq$f^-g=cQ3_V?6TM9d-VQBE@3*l@lqSXlL zVNXx<{)Fw-F_QOpiehcgR*ot5&pl{+CV8#YTmE4AO8GN1gC9`QIAZik3eZqm{#>Ny zx$;bU#s|eP0EJrt#xxp^VlkAK`>o~P9`i5Zm4_u+TChYLLsQEe#qtiR9PR&?jFY5Z z-jh)Ns#c2fpGoRcIhL$`$zW2ih!rbNmntC2UoteQR}7Apdd2XBiZM}Amntq}w3^f_ zo{va9wW36<@LMZb7EemQB9u_krm?8_7U}Y1dWtTN2aUmmBPEaUV9IoT#d5&pVdYvuC9a4Y8ln<5mzN9jol)tF@*|S`&`CT zKfY7yRUc3vGFw$LxnxYq)*&WS%{OPg&1a~OqADj1ruw9PGFzoy{{;Vp%4Imo45Np^ zKNXKCYfOwEcBRpZcPzoepN{AL(H?djoH+g^qJNp-|6g*}+w!`Tnv{Qag8ykv?EV%s zsr`aK$go(O_HPmWI|ToB7NfNb|J#E9jby8eyu<3$ySM+#1phaYw(a{`@c*hY(X6q` z1wv(dgod?N+Q#2WZr9)M!_zuCL*VyE%)Ebsf+C>=CbCV2y>x2qqjs3qwLs9)@-{#5OYP?No{?%_ps zpP=qx)Jz2n>Oq!&=wOq)5v)%5E&g#}^)pzJUePk*AM77@5-WckFZ$0F{BatqgJ@NP zf27VTWRf>Yy_L%=t(7fkuygo~%7-GXDzhn){ZNhD__WGGKB2OZ8S+A<%=ihFRg9HT zxkh7&*7(QexSqfT55=FS;aUnF@EmNDdaLJD-&FJ00N*dH)oK27<$7vKuTeTi@>GO> zEX}BMHz5D*;1H_ruHMSWpm~zqtG8Bf)d^TrGs!Ok=cVes)!zW8l+UPsIZ~eLZ>qoP z$8E>F;U(Z6tQk;a;bUw~z&#Yft+CWtPR4yj>aE#R^KH!^kpnks4kLg}@O%yRbUL6( z-o_>>_={q1#I=Vr|7FHC1=qcZg&1~7y>;fgL7feFsf39EC$&=-+-5M!Zvb{*T?RTI zpHWBebx>Dhop7hr8!!h3nSHG@5D1Pzb!ka?1MuJD}bZ=&Og*LHdc$2z=2`{YyPLnCM3p zf&JpY^I|SH1`0L$ZDski>L`f>I1ah4+*dj07UcJ&kM=WE=kMloxy zznD*`PhqoWp?)UIkx+k4n3+j_53Fvgf4IJwPV5J(oBLTkR$qKFt0%$Ask3tHtn&11 zqD#FGR^IyN`gc&sRlqi{35;$+{Y!eTgnAre z$f})_n@sWtVEbYH;n1x-mcBCT>D?Di@by21Zq=A-TyZKvkPDsy15x)x1qTU1iMmm0ilgcw|94c^yd zi8+<*X7~@5;H}A^Bn6-BvG8Ao{2nF{ z8wLvv1BC_?%L7@*kqI`~Ct<7gwPM36q2a-P zh}dA08lEO##8d(nBunL)GJR@xLpe%vsnAfTmpHXyo!GElYS`GHx3`6c*M)|c|1)ni zk7~Syv1nW-G~T5lVK8QZF9;wu9upc5MrA3)OO3z&GfQb9_%1^6Lg-u#lNB>GUI>ke zro2K3P0_-vN<%mYLDNif5XG{E=23#I-FzbTHt|h^n=we+s`!j1Iw?hKI88$-lC*cz z7>*lG+FLu27%gF%F}3O9#L-PtrKU@JEJo77JJOow@xz)Hg9`-RbT>tF%G~McO^-K8 zXhL8N-8rTylarckVVd-&s-|GS{oB+kG&Sg1WqgFDm#t0Rz@D$?KQJw=>0LC7rY~(x zyAi)U++M_{LqgNHdgbV}e_NZ5Gg_^i1g6=V2M`TwqbB)Nskd2ZzOWUV#kG*nXg()W z^yZ5wl8W9u4fp<{;|z8bz4_Y2(akqY&GUOKu{Z!!-j>#UH$SX-6}X`2&5u(wr(82V zy*aBnpW`cL5e_dl7bdgUG{-cnoYd^qiFa`F=c&zYqnkHL&FjK(7-E{=9U(S z4arGazs9vp>ZeXpjo4Dlr?%WZLTp(fv@AO*A1zM{Esskrs|erLq*!31?gwjLZ1D;$ zg+fcV)Z!qRwN!ywEbrHH(NYoC7upQ7r6HlEMbE|la4w{lw~3OapVsm#Z*AoePBY1$ zNxiM7wI;Pq#!i1eqqSe1w~lR_tW{SlnRc$Zw=oS0pP3=G_0q)Atuv(7D|;-aO{}h3 z=kvo_*=`D{^$v>VlxwG_wq^itwbZ&o$J+rPRcj7EVpwZAH8H7G(NQ_EwOMGbORktM zzfBOKwM%MkBVfgJxUT0-Pix(UHv0#3gRt#Ey@ z=E-o{j8f}g3|v$uKM;N)?o@)>Q8NGoouYHNcy z=!ZBAnr*fGkhTU_sxrqUe=ha5JK8HcgOJywd`3II(X03S_DYJR#@|k!?r5tGUhUNO z^@(Ep%R+m1f1cWRN$s!oSWYolOjqbIE%H~i?@eg`R;yaLdevB=!^jAdR8x|5z0h%i z)G;PZlB5oR$G79A(H%>rjzttpZ5vB39Zz>ab!ZbpKEA_Nud;VUQ(}aU99^_RM@3vm z3DM|1Leq2U9nBp$<5QnM#&>iEK97)Y(IqZ)ydKx_QWUACCek`S;uAXdXjXj3cTA01 zJB|P^+t%?DZm-Zz!_Kohad2NaYn|uyXRUKoIBT7k37r>7ofl9N)>8RJn#kd!!Pj-( z(4Vu;1^qeegkzcILFimAblxv@-bIwQCix{snb!FXpU`R3GS-=^WvsKf$6_9B>#V@- z4wx4oW1+*g01Z}BPho44eDs8YtP0x#ehe>Cno|K~R(YzzK>d_#iP z(JkENxSqiEDreyb<645NgR>Y8aTepZoWdSQDw^4;9H!RgQm^%O z>$@h^tlR5+hLx>uNcl#&0>C}iZ%nGCAGn_yHWt`;EZkZw9h~{dRL+cLBJ-b^Uj6kv z;vNTYBZJ|A7J0wqq(f-kw8*Pq4VNNg?HM>q-FPF@pc~& z{;LU)v9wrJuDJ%s#%C4!N#! zU6r{A2^(B#>~6%7ckmd8JpcyRVgPYudc+Urx*rk$@Q}J5p}3R%Wt3T(p14KPog}!2 z(~NWfNyff=a)SE`ZSvq=$y^8SWekf=6Wq_?lbmjs&28rY~pd1gZ95RFylbzt?Q zJ#!8r5v%F3m~8CF1jI6MHC7GxjU4R?SY1%Z1Ffj1DenW~Y)Gw_J3_58?0{y5gv~R-E z;pj&5B=7Aceu@K56Ur`%AUHOY2Hl6VN;gZ6%}6*`OE@quNj*)Ep+qO8IlkmaInA+> z;{dRp$6MQ?g4n zzoq~U37OdbpbZIo^-%>wLKdGWW(^XuVp;wuQ$p4dDeKH0%jqKJSRWFy#wTP=iXIZO z<}(5|By__%1pO!rq2hojH1{tu}nw*5!?c~ECs?F}m!GH_H zF(aE+vNaPpdox8+xwCibCa}D>zueiMB#PPJ3E6x4%boqblzp(rGAJ&p+&PAX9CLKJ zbCROVos%x*ToWeI%ANBVj_bDzInPEFIwwcMh5>Na3vH5*NQZLdoX*@)%pS^7BH7Ma zpF2v+c1{=W{q|5=&TBADM(6C3axh*GdXw}8C+7ShjmM& z+_Qz;(^-aC4d=$knLX#RL@z? zxC&Q3uKi#-AV%(!4&}w?jmq0&PzRwIFmd4?EB^?2xi*d1Ct?*W8$KdvE< z6m+x}&$A-pA6h(*)_MP}#rx z{cO*J${oBMOe}*t@t1x)1~|*$9t?VYxSxV+3u0qf9KkUN{=`X#@j!zhZETW$hzy1} z%=@@>*lw_&=^imaJ%g26b3>x3@Ugn57o{dn><6hFk3RkvitcA{m~Fq!zLOLkpJAU9 zsWSV0cJw5jPE&aHNAPX7h{Cf!gCuo@XMcvZijkuI8Oi=kkLAqgq7|MNqbWSQpC4u4 z5i8k)z*?j4`n3&+WBw7JDZej$w;&VJBIUWm>XbQklgQKLk zi;gzI(HNxz92+G^2Vwq8@%=6xcD(KQ)`@0HPHM+Hks>&bQ6&3m3ea(!k9Qo8R)Bv< zhn;cGQ7)6F0G+gTN-MwfLW-pFJE#7K0(7P&iq1uXGrhn3&O0UNZ9SH_=<+*PCpe#u zF2A!py8O;1oohvYm#Xb}bYr*zmg&^6js#uT6nQ*k}p zt|XVPw_WEW`%wzebr~r@*EGp>8CdPq6rk&F!L_)*2(IOEuKNi34+ZGL0md(|3^4`h zDu{Ds^`k`;;4jFP>}qy>s3|~Kzg~8Axjxitf<}8NKvy@u$Fxguy)3xcbZTF}0(8C2 zQeq15FL3cq#@Mlc{ zo|(c~&OF9h&T7Yndt8vSoIMp+0j{sXbO0_Mdcq={3f%!!DVQmSg(=OL0WhFp>~d_! zr0oIg6C7!{N>LrmSucfVK^<7HMZ{R#@6)$XKCf??ERSrNjEPYONJp&4tbgS{K0rMa zDNy+$<~RAAEG7k3we1$$1GW`BRxKzS2HOhu@m0zRt45Pz0Zy%Ly=^0{R%kdIZ5s&z zKOJWvaQ54d+J4|;@O@Xt=LZ|qAN!FIIg@g#bi`h4m+iIqY%J#VNXuSpuZ`fq{5L75 z0p}z87xu5ghioF?d~GMG(GPr5fHO!s;`qa9bgneAi3WC`o$g!-u)$z(#^X-2M`%^& zWIWSMm7Y`ZERoxM3b7%B#W|l(aL!k->(wARm-blBxyS0f7q?Y5X9jN1BB8<35m%b) zX4i5oy(|O+-r%|w0X$%40m(DPr8)2L*QA^Y{NLOb_h>GLEFRbIByl+VcmqzY9<9;2 z6Z8%rcKU(tEa^!0wCp+A_u_=#ku06;c?h5>z(TqSck4)&b3S`10#Zl+42DIUlsM@~ z{%!ep;rrh)>RCYH4fziufCv1~f9Su6Q2Rm&t}a}k;rg4ioHG*FTwJZV_HvdXLvSs| zl@A7%80BoF@>%{@MGqR(IPirSXF%vi`NXF!fUKu2AqMJ^-wo6E%_)e4S8mFj|uq4iXB@ z5iH%gQh13_cu|BKY1GuhrDEYjLg9Tv;avYC!M?H^-4W8!^g03?fJu48lV<{9p!;_0RtJdm0 zK0G^otf_l8;aL^2W0~HgQ3kL`gXd$!N*xH`lyJ|NbeD2H(4d@(ll`H(JKgO)zsGW3lXfJ8 z_bFqNnjm@?3El;Q_d3aY9bm)BM|<+jP#rFMR}0>U1n)A*yDWkeJx#=s0y^tdFHYR` z<_lhjx2nUO<+tErr5f)le;yBZB|&YgyoOqYiY2D_N33cOZqM6P z%#Gu-Q5?Gp=T&@_I?UlmTZvz%#ykC2;^B2Rc5#(+Oo|B=Pq{~-*pxd`@zF)1ijRq< zm9_teN>@+eC#$Du{9j*R8HaJ;WcKRL_MX)k}${0Ze=!ht7amh_%4Wq zMZF1;u!k>s2*NUa3I^y^7>Kt)>5{I)r1Lx&jKd~zmiPsnC1D)H!8l09<1oCXj(U&s z#2RCicGqFxuk{cTp&zm3)2#b>!MZ=0vZy4Ql+nn^7TZqS zC)f}%3rH|q-?c%Ru^%N4fBXl$VEX{yS_8!hlaeGIb-aU5Ro~8xeaE|CtC?nwLlnm> zB?k=||1_^?amMjGbLst!&nzmVwaIeb^fWje1t+#QjZ{Vc7qBR8d+HJ z^fz!NZ&WUjj=F}p;?2_ce1?qu59u6#UK z%p$pPE*TXhecx|FQZ0>R@BS(m&?rB`MTdzgV`bi-CKL!@=sE8Qxv0k!N>4!L)gw5cmxL_dCkOTL5!Dz`3TU`HMAeeyrTA;0-26@k+Y2aAF_ZwkCUXMnFBKi=YMHX zX)I^5#A1kYG2%bS+-p|ZS2U=tPnM2meUtU0SrzGZu_(g=(!C6@U$TD5CU*sWh?MU5 zY*6+P+^w2)voFB2E?xT0s8Jouq@H~@;{T~-N!pXNK5;Qgd*s)raLVNP>_Tk?NV8~o zd$tPD_neu_Ua!?eHXPFk+=w}+yr zTF2t6LbPim4{L!Snx2+_23|rLi4MhFm+|=*v7u7PzmVmSK0;wd&lB>mO;*P$7Yq4| zlT}ff3}tG|f0kIN!|eH0cz9Qhx8}pR8D+;ojc6pJ=5dzMP6z^xkk91HI^1-`A1F9b*bNqjLKC~k8eMSBk|=gYz9-VbfArl8Di!NGnLD50=86`-(wm5rL_>I-{?cO zLNt@nKidmKKr&FPn2Nl$7ra`qU+bR*Wc_Gru3%Teek4vm#G!u{yu(i^cn5{n`)Bx> z`e(sAdjBkVM=E#+%q#o*XTe8$R8;>Aqm}gc&w@P~T1j;O9CH`GX+>G!>B2B&Njd{V z*E8t3iJWERL#UWy#GM8x78e1dABMCPPCACO{b)$j{2`!c?hjFOuv#Z-ZV&4Xh`*On zp>k(P$7~yIJF=4psN-4XY7SRzEK4UWBWjRg(;xKA8PN_`vq_l+4nNpU_7U2?JKK*D zaoW$YQytTfts~nb0e!XB%73_0pPR4eAXv;G8MS>lht@IrqwE16|3&wZbA9aA791Zq+`WZh^1%Sg6xfgy^e7P7YtPPZpq%+V>y2%CC15z)9kNePmuist9=(@ z9aOor-%PZBDcC<_xzy>7N%mf%ql|;jYCl2vOe>p|Youe2ScmAsrU}{)qw+X z%B+8)bTtbZw|>g!*QdlDQO{S)3; z`eq>!=(Bc5tK?`5lQ1`Ey5kGS*V-ln3{3HkZ!4G4CI)$LjNmxN#34BTkQ^w(SdmF0 z9S){5wY>#I;Eb!hKTO~p#^fM4&zGDdh=7S8-FcaFCN^hXfHpM%B6Ox%owEVWW`%HS zwaLjxk|pPzM1<6p0qM?1oET))3&TW`%?U*|c9TYw$r93t$|6Lm&T7%QQ*?F+&KA2f zfcV3d1Fc@1uQ;4rdMx7-_4+(%ZP@uqg7ZsFY_78+n}nQy6Kl3fC>`$J3(!lM*9;ET zser? z$82s)1jjq|1Z6g-ciXf%y*r*i! zTy%euteyp>2^-YvJ_wxUN?NM>gpg^pyMODkT(AO%-DB{bk_o#;7le3V&?s}Otkj#&dBsWO*)qO zOlE#o0tUsi_>9bFBh{MerAVZUH@hqTvnpd!GlL@%M`yMsqq|(siJ2b=nY*ynRhb=D zQ)!u>@=170CbJi--Df0ZeqT8k)_5|R;aTP$%Y~QrPdBfXj%AI?nwC|_Ry?vsNAi)C zl2u6gz-Q@Z;2yQ&k#z&Dcw{YvhHV9&-!fE6LDD&6O@^s1GHXv z1ZWN+OJdzwL(7ZHa`&TYO7w_HnS)%FWi@1Bl0#e2vON9SYR~GQ?9gDIwGL%`S;*QX zWUXWAyHc@YOj{DftT!%Aka|dYX1yb1?PSRkl&iawRzZ|`Nac&HKC)u544g&YGtFYi z`juI>C^n5zn1f~g&5z2yz)Z`)*)ePtL`@d5&t~Z*S+@(>35+@IL(3jbKF5Jc>I4{E zNo}~k=Pc)^;yS@u#$V1^F2uNhVFhPNo`9=i$_6Zf z`Rt8z16cymE38&i^uT|;bkO>Mb)^%gKMVs>u4m(BR2E1FZ3}F-nb{UDDih707D@*l zgB^pNWHcKbW7r)Qz5{JLyprHpfM?y^?6?EZnoi^#8D#CB!Z<-j%JponC}Y$L3XaO; zYm}Q!kh{&%+GCmUDi@%)J|{Z1B{*Ku)UMM6wL6Jkt_Nn4dXdcmZ8PE3B*!1vw&#o! zowMSdLn`5*G6>Ewgky6~AOyjArR1D~r)Jt=5ct0N1y zZkq#kD9Qwr^JWNjlx>1-CU(d}G?!r9u;ajmKxKhFW3EVL!i>+K$ z`E+GbrLXc$MhUiPaFbwAPC^~wN6+*F%f%dhs*^3Qxz~UN7Q)JZ#{Cl5kc)6%&T*b9 z+^tyiMJ}x#j`O~NdkFDbuft6JR;kbSf$h^C?!{LPDkgno>rCRfc}8UkAV1pvFsYYO z@l*H=+pl!Dwi%V%r9S&<_Ongu30sz|Hp8Oe*cjqwL#XqPzQ;QNg!D?7Qt>o79vrXs=Eu8MvAU8YjHK}xZ4dZ#IPL^&|9tQAnr_+>M6$V;0;KO$q zl}7;dIMi*`aEb&mB6?FO14+0QWeLn$+|#*+CunfKho2 zz`tFCP3n9d=%Up;D&b0_^0?IJ8sVB^Qm+pKCuzWpB}N5jCA+S6EjFn)gn{%bPYSxj zlYnHno;2my!jRPjS!Pt80wl{-Y*KFwLuisssX^FJ16b=?Z&DY8f$bV_6$o#;fowNx5BE^4QF#`?Z(PSra!D9?m?+`rc~0tcb8d@Cy;+C22N1*>Fe=Xjbe?;h zNxdZuN@AdpQF#HNE8W+b)P-RXy&soi?KUbBKug^ZnbbvL5N)DLvGy1hD?rb?b4=>u zFvv}y9&Y8SM#To8&yBjfH4J2R=Rh~Yr#{^q-LIR}+rpq%h%R%0QE>qDsr!&gT@nU; zr?FhM$*4F1{3Fw3Qg7FRndBEodQYr3DlVxn^PJ2PCUt2TNK0S@L?PS&;=8~m^^P!b zwhr8CR5Ag)E%ONz)&?jNHrm5F@I|AN1z=`osY$&v4Ad*|iC2wEHh}e+>rCohVPG3k zx(kd-4nVJFerQtf4ui-Wo8mrhRB{3OF7t#*y(bL%fk2rUyz`{KtN~eqNxfGGWijQ6 z=F(+U@&QcBy2Pa37Y1IW<@1rNjYvlBfsg3G zAB{>8fbJ}hNqry;EY^UlUpFen00y(xn^deWGTCIc>y*D5l@b77%lgQqJ{ShRr&GRd zR7wH-F6)FzT^{^rha2Qyr0auq86&b+J zY>Wnvgn?`{=;4;1Fe>;`UiR*6G{{H8K)pe(_8Ao)fPdr+GO4R|V9r3D?HZ$^N_{!Q zb1pWikA;B~bRb4aKY+7y7MifgLXkM{X#w5ce;Ji3sV_GvcY@h>Hb(LP87h6~)zygW z%zbBw`UHz3&!kbQk^1tk%Ud=?eKIPtR_e=NkiXKbK848J4Fxpq_6^_@@^3GgMgzDH zmVi;I1J)P$$A+j+Yov5ym=cis3MvcM4^f|q;#V*A6)r7&#H>Ec_|>uRM5OSO3Rkdv zi-jvAC+HZJpww4%O40Bk>T_WZV~xrhsjv9!5~EptzMq5gBR{DaV<+z8VV?dV_0^q+ zf3QY4L){2=$85I_?n;i%Dl&XZfrPUu|-XqoB(_^{fIv%?n z>z=^Vt!5rviIAIZQbJN+Npi_0CF$5%_yY0*gT_!Yt%Nzr5Mbp=E17{$bEXL;Gm@#q zNV^Y?FbbHAgB|m{w3X^_X@)L2!52W~XN(tU8FZo_5=@m-$BvWZobew!c(;wKM zOH4|W)K@yU^!n0g!Nsa`DP3Cntj0v=QhF!8HCdV=l;R`>v;d__zP<8eUMO9itlAK4 zHYv?uv%Yj&DPEMNC{Xi;(jBGb8laz+nbJ4$CC@jLRlBkn>6dWIL6g!V^_7h+yQu7D z5IS_ivXnCTi`h>jESrUoW6nxeongX5CZ!dGd1aom77)6^gq3A2Clg}dVOdSG>JAh3 zniL!v@43{IQvLx5Gj&4GwdEf~6XJy!&&{4&VSHjm4P8O>+$(tSHVZ4fnnkFUpQm~r z6FtvM9$5NUT|yG2mkZK7Zk$0h*Ha;R;3c@~l9<7s&J0f{adH3Pc`d{98a+aJ-sjnq z;n_n0hwM3);W@@oe(~}dUUUhD@|gFG4DT6wAl*AA!#hR~EcafX;k}$u9P_4Sc-hFf z)O&k|_jZbOsNPi>-c=g%L$O|4hS#Q3KH|l3Dqbz{@EzW@8Q!&8AY+O5l?*Q%^vGKE zexBj|Tt}Pk{VBuy69tyxDBiU4SgaXfvrk(2SWLx7h~<|^<&&ta?8J?XaxGs4I8%cY z%hROtISh6q1e8&J9dU6V=K>;5^eA60l`o4TTuH!8UL%yG@@Jw5?F?qr32UTsc;F)` z1{l}hHNtMGd|edb76$tZgeIk3>Z`b`;z9aYqnfQ(eZ^BU)&bZLn0Uu7Cbi;)M4`fw ztmdF?ccoPnQH562i52UF3VdMsq&5%}Tk%###aomHq$XGF&8XO`1y)V2_$8y_7d`Np zJUBxhtOZtoCZC@nlTVu3!B-?wc`84SiB!IeA8S%Nq(1p&c^BN`ob7;~Px&K-JR$T0 zCFL_+-iujiq>0Mk3o?$2J1Ki<3Wtxpir4|D4Ct{;3xD)^2{%GihDi#%O4B~kYE2nV z`EhHthBZ9p0tREXrc7oqsx_0+DfKDkO0};9GR)QUrmXRmXj#+qW=L1sm9GB0DK82N zj?F(QZ>h?AqVk!feAHu^{#c~@C|^U`Y03%KvU~9)0A&4(HK#j^x7|8Gx}o z`i4gGh?eD>BKamp5ne_>y=D1QB_Djk5yE){!@&Bt*0y}hB;Q?8q|CB(Yi-N-g5-NT zid64Z55+LatdsiGBz2;C10<8DOGcdv%Ut^*87O3Y>{GzM|mbAhe$)6(lFa4)T{nv~B#ghM~9!tuOh)Df+@o2#Q)si1x z?UWq`gTEldUqGdn^8Nk{zn>m+&+<2A_?t9YJng&?stV32#mMY;sK_pewrO#_(uDnI6gaa>(DphH? z4@i|5F2lGz+{b#YROU#Pu730$ZZF)i&@YvKsj?!P;O{?m{ykFVrYHh(c`$Hz&7*u0^tq2|GV)In88)rS5$sCr4L>i%aPRJ|`&eJ)jf z++&$JFH#3p-%uS?{VY|%)iiUS!B~A}Mm4i9rTpr|jOs+K4yq?+R8I`oL3K(-bqWQp zAYoU}l<8QxeftP`zHNZex+rRZzWKs(!y8Rj-2T zLsIp({kZ*AP;;78gUvECbv`?`+^3>y%?UvfH6@Bn3KtLRRUARz|ds1gcXZZ zwoXqETpEC(qo=7IkSPVD>{Sg*3 zIhx6jsMG-=m*r%{=s-{k!1kC8w>2zlF|bt#Y>W$ZP>g16+b;B(Nmv;X_}(gL6HQeYn;niPCTq&~TRa{ZkU01Z66q5et=u%9LXeA20Yb}|zWr*x;)UytKG z7ACtGlCs&PYzB*p`pV#WaNtuUSkzJ=iiIJyeyvd7s>?8~{$+f7I<@}8M4|rEh~VlE zMGGzs5*C7I(itC`xTM_RT9dL>>I<$4KGyIDmNYae^M;_4g6xOy4#muv70e%t;XPO@ z1Y3k)P^VuWY?@}6Dh6LkR!jBj*`B&)sJLdLux7llW{j{VUdMF)8ElToZVh&0L}WK} zO)4t9;i^Qj;Z~smb~>}PT@OLXlN**A8kRP|nMtb|4dlhPLZK=@hOOd;Wi&)LJSa85 z7P?x02eNKD4*zfo4NprAk5jB#rW~g#6B@EuGf?VaYjX8_r|~lz0{D=`RIvg1_vrcG zHuao_eN291m4HdvCiOLrYn-qinoCFF4UN+%$bOK`fYiphi9+MNWSYz=)!0LV5A`Oi zUY+0TX^l<}X*8B6tL1v!CkUe6A|gW&U7>;vYeM6fLgPnKU6WH@OKm(NH2x+u_UX|y zg`jjos7G1n`9@l3B;**nL=2?~p;kq5Me(EwL;<5HSWt|D0*QdqdlRID zE+Ad^QZMCd8sYXX5K>8iPy!)9aufj(1w_yB5|9LaBcbBNYe_)c`H}Ac9 z^XARWn>Vw&)#mcup+f}mJYz2ZN-4*yltTssHcAka3S*R4V|9zG=pY(?w&Xb)Tk$OT zRg5uLOjj!K?!*vUHjpq{xRN?;v7qh4XzS2&(S0kvFjrhvD)2QrMy)R|ni)3S61U+N zKHAUgCK0O*_eFWVT#OBU1*;aP);|IXZ>}9lcVZ7clg9fqp)2 z!+F7d5l63&^7=UUjduz3ddc%%?8a`AVPoI8jVQ8E_^c3SJx(Y0HMVJZDri1m4w!tFe4d(@S;#Z|IJSAT|6*)asC6L2br0%uxW7UG@? zd?7M3%3CN3_oL%fZjbU7@q#i=J>WSVTX`N#eu=C6MKGC5Og7)pR@r=WfXQZzJE2TA zV_XR^=>#U5XGzA*Z^mtYlbB4~oEf({Q?OgKxgc(H0l%3C0nu8Ut3$ZOZaym+wseWx z(uHtRE(0TG%hTp90ml?Z^&NK2%v&&%7K@5}!~l*cZ;1dLkKIxQHizT3=z;Fn7^5@h zE$4I(H^Au6MvS&T809S$j84RE?JpU&PKet&fyr~7w6S$gySB>K1wtK?vem9^MOS81 zB#qf&1GlZ%79W^Gm2DZyHuN->Pa}2AHVuBlwsK`#vAPZC(O&#tVC>#j9kA}gXnct9 zOJ&;yb=%p7IA|Ig-(k|g!RPwgDph8+N@;*p6(x}Hj5a6Ipx#@Rce&COjP;(*eVZwFt}=;x$0nJWmR2lq^#|ChEi_Fjv2iRX8W+V z%67O2STlIG>?COYHVioagYXKX3ned;N|VF%xjp!gu^`rdu%+#O}Bo z-^6RD?7(}Z*=Q8s6fvww?|OrJB`d$$623?&p!3%UD~d-wd&#TXoMUzdZ23p5A*VNiln7v{m-Z z5qYtDEF|up_oBQTg`Mul?a#`dFGHm_*EUi1{H5%<9MXb;7nilJy~*=?6DizW8>Q5? z5zY#0N~QJ*rS@UbL)9ye9&lWh+CfS!UQEZOg{GC-=}N6Wk&^gItwpI_A}|sk%`Y+F z2yQK+KLZai?d?~8uKlt0O5HVRj|*)u)`iopu07+xx@L7ah#-tdsk=|9Yav9ZP-;xw zgK)s=x~p}FV!a%u8;zvYJ+Ib1OCY_a>xQ?k8!K9Rlew-^sVh8#c<(vD?ER{Ux07ap*!wkxSoqXHTvsF2 z1}2}@xbthbULBo}9dU7iO6`3r9>0zPmZMt;s*EpV0{RQ``3Ie@A-_nN9-Szm z3^Rmy9*;P)DUF0k#C;pTJb19==pt}>6V6it#}Y;_2?Stx0)E93OMa9UcOwJqhMB|$ zYYng|*<|t@qQ-n78tHj_1xH33z==mw&{xJ@7{o!ebiv(lfJI~CoF04zz@|{syf7o! zG%qZ}r!oObfgmsBP^MjIoV_#+ihN;}Umntz-rR;s5x13uR2ouGsPlzwOr3GKI>6`H z*XcV^FMLG5j)jh|&;{dig>tY|GTRlwG>x1U%vj^!ss<$;zy*_Vq5UM4iLNI_n z#|)6D&oO-^LpPrU?Z|^?lk z_YrAL!`k*esMoeH-gL>9l}{1c_w?(FMzuA0j*tlb9!BbpgiRK)f+7+6p%n?Fix5tQ z_8Sl-sx5gAGr*+KAs#~ZTgv8uPM#8$y#@vM!)h;JdT5edXih3!?B0kXYFzhbWoy(WB=j~Ei5cT(0(y0*8I2J_FdoG8la@NYR}tuH?FZ#few z2SY`O3Z+g=Kyu2{ty%jdw|<$ z|JS3u)ois2N&6@IHYfso?~v;bpY?%P_#fYoG?cz$7&c!u&-b_CqR%8V1RbV$dz2Y8Vtr zY8cd|ff@$IKn;Ul5^5l4X;2>ha{faNgSLgJVbBMJgtr=ps$tNVLJhUZ92`y<`f5R_ z0bk)k&Il#};mj2BajPGUH6*us=ydQZ!R!pH|NB(`!6%ST`=ybmQGdSLr1}rOz(Ilf zW6T+hPBQp9&~OqDryfw)5EGU7o9^(Da}3~ZG>i^ug>E+F4!=C6g+7cv!}{%zBSg4Q zj3K%UGK5^mA!mu^1kq3cQ};!Nd>!;fpxL2e`n)m}J0i?R&U6I$G4h^PgifZ@ylhn^(-w+Uap=D7|{4ZRqm_F>_ajpO&6oxz)pGKM__ z;IIz5te%6!b=X|WnIiPTmTm-1Am|GEHBV&Gp^Cr~h}?N<#9?qF_&@G}$pC`WCfob?SSy;0lsNpI9{zdWuQRUGvW;qB8oh)HkM z2gp7enDjoN%8c%S)Cp-DDzhd~nbD7N5KdOp0%vqj)MoVpwuFaCj_yNOmS+0+KN`~t zU;fklhZY$Pr#h(c(N0J++8QD?L>!$J<*n7@rLf=8cyMQYvgcDaAD?2Pq2G`G(l3qa z2hn&ul=M9MM-GBS!5L`u^+pnm!Ppp-U`%&NFa}|}fU^Jz#$a}=V>OmM=UK6*sn{_) zkaqi}vBOX-f|e+SiXHPV2MLXgp+h(9d!=}P2y)MnM$`;lBV)d6G!={uXYvRKU@Q#{ zW7{>9XKYlI*RMxfp^>ru{PKiVp3j+RAChQePavK4OXHS6G(>-eXk)+RAR*e=?*aG1 zt`Tp6Xk&kGDB8G)MyeWz_)bt&X(++?$SChV(O6%y zV*f|Qj!!~L^GmPPqS#ddjf`K-L3*)a=zZf$kkFUB`g6>0T_rsZt^d6A%Kc!{kgnIhW@5E;GizcH9_<{tRKlN=9 zntae86Yqck&mx307Q4YTj7~(|*wBgq7w(?&%adYBpo#P7*QWLYIouC&ih7Jsi6HAC!9sSxyDCIf|yi7U~rpvakF~c*2eL`T1km_4Jq{@cNNtj{| ziiY_K1x+dj!6Xb(I7{c*$o<1fwNc(f0_Q8>ymA+CUNMVW(}3{``X+1;-6OiE6}K;u z4j#Z3A+Ad#ljjUI_T(c-$Nkc@@n}W9S|S^pe2#-yV`I3+gP=0nd-AtPKZlOClm9@m zlkq)G)++jF%c1~N?$Y%kR0al9o&ZO_%PrAuU!?wsBDkR<_L1!=1Eai$MYYbNT2rP& zy;J7LmnDx8JJNd*+1{^aF^gUziYy8l0=1kfIm=VRhfL%I8j1LCwg zhj)S;PU#$QB=Ts0!xhfq9JJlaFTHweZW4>=z6)lrK8-rR`lwzznh9WIui{`E%Ea;q zcKhmgWQ4C?iK0`Ko(g{jywdQVjTM+V4lXb4l+6Wghq zf@~kg?LoK*Q;!ON^ceU|YXhul_|OIKDnh_%59k6iBb(MU#DE~gw1KpUn>LKJVZuo) z7{~N*q#ONGTrU_0Zxu3*>GyJwFb;a6vk4k=dMy%`7PMwX&<-L@KSsX}3OUl}=YIgz zO#g&{2)nWKbX+qt!U*=OE^yFZW}v7U?LrM?#)CkeftQf8y0Pb6q5K(-`{h?hNco?m z!DsX)jQ*(1jJ|-Dt6vs=jbfmw8RMX-8Iy&kjuRS1q-NmzC0tXqfFTYnz&HawB+j6E zHVI-{{mjr;KPNyJM-jQW+e3-zbKP-|k|N`JP}wHW$E3)(-AMcV(#+#fB&-ygBSpr2 z%t73}iTeRyzTlT|aE|&M3xve|9%2>H^UT|k?#4;uFPNUu-ZL?PBVA- z<*B)_cT{#}9j@!p#bzSdIrT3LE}u}fXStDb@I1&7RGXJT)t}M9)&#W(^=qRLTE4QCne-jMf8sNh?4HF~2+wl_C3?-HR{=pjxy00QzmverAt{US>}b_CxEr*}3$~t{2P}z|i3AjRp)F zvv(H8L-WK4`kD4E)N+p0GG_u3LPqmCKrI+?gf+}r&OzK7=GgvW4Na+O=d5mM4Rf{t zwiBM@cD;skc13wl3CCjF1D*@0(wy@&Zp^_xBF;v8D!D<=xrW-z`BT*9G!W*JZszK` z@dlRjbFo_#7?;pebH^aTgsimH%!ci`Frg2H1%8GC=PsrK=OXA8(u3w^qQJR%p#>f$ zth&bPoBJsl;M^~@_S^vH(O@!Hk9~QC0nU^C^7JBZfb($nbNah5zBn^Wp#xdgAk#Pj12ST{oW;lPuXSlhIo%WR3%jXt2dNtv=v*iLQ0u-12bQ%iK753`Sy0kz@L}VA6MoNY>;N}3 z{Tgk!Fq{m+NeRVa2TxP32QbPAqc9XBcx*)Ha*%NLhT^6XHJ8kD|ZKjyLphrsPNobklvhtv@koYSKCPR@c~i0m7kj5-2F zmj!=-pes58+G=4quGx8AT(=_Xg&njfIQ7COLA?;4Q{$tgpkCN3gc_Sfpf-8VQ}0s9d{sxo_d*v3q0ViJ%S)LwbjxY5Mb#<-3qwp^Emf>mcEIs zWJwY)7lq(UtwjffT4A!wB9R^pbzql00dC7465PZny^L1#%dmxJ#VEa*kJ8KH2&O*| z6)-Ufv@8X6U51T-x!2k2Lt)W_*%u)leCVVuSbJJ2%AHWKDR`n8MDx9C-B zxVT)#hQ8i>s3GKwRNOf#E}hPs5{Q;)%k(9hE}K+*5HINUOUw7SL#r%DYtOA=qu%l_ zL9_fU*epkEYwq8TmS%tZU630FRe z^eiUDD}X&~xDRry?2G!X#2`0c-%y{G3E@|cCNNez^NXlMvWKjQK^)TjP#amffWMFi zx?1@)@w)WxQdcGFU64!@rBxjYc_dBFOS) zdZ?|vNmlWuZWUx}gjR~Q0chgEGu%}Z+9qA|!Ww!5c9v zFr>;TQf&hH*ufywQ@xp#1P@^~%!isxy@ycHWI+_>C}3vorlUMUC=Z6BP$Pj0n|%2e zzB(L|r~`Bv^#Rug;B=y-qLvWKTpdMJ1IDACCf8ZLP*TaQSEWF?s-K2sYQ&7I;<<^} z5~;J8JfD+MSvn(i^-C@|`xNnmosdykp5q`fepvbe9*i(r0^${-DqlJ#g>&0|V?C@Q=R*=`Lh{!t67X zKpl`ep~yfJ$9D(w_%1s0pidV60?jA!1EGNU7{9#GE{ydg00>e1U4*gLwwWcGCS4y|iy3#fB2w(62i|l6aF&A_Qf-G^kl(JH5=Abdo4B znvi?z!qYBkqJx-F$S+Z&%uJnAL*WzG>x_i(iM0?u@j!_1Nq2)j={B8S2v6@V3lTmE z@dGA&(r6T!^b(Qu(McK!pM)(P_9R^4%$^y*n+;MsQPJ$4v{0uC8d8#j3@K?9nm#F$ zkcA;7c^D(zkdjIX0Vmpm2;~fc84}(siQGNNWrmdWE+HQdMLr(j1`Q`&2r;Cj%l|N> zWEsLH8+2hs73o<9fU&#`EI=6mkH3UQNRw-5MUq_CATXAE8k$em&thHxLJDD}1mco` z1#Zd{A+a#@NxY0pvcjRtW9RJ+nP`5i+!lgZ@4_H&y#@{)Gc zp{$Ri4C_Oo$I3EsoQ!hFaj;?=fSt}{haia?wj>rV$Kgl19!l42E}}`odI;&LB-vgX zXUt6wBW)tF1-JFRDDP)1Sc&o2iiOUSc9Q1{Cdp;GK}o4nGO~WhU74DZYX!g5Taj8} z^!c2zA)F4tNo_+oNq^?15)Rh(sjo;OPEzU=J^@nZ3M813mqJh74Uy#8r{*FR0!Hzq z;dmb@ZmW>?1BBge9rOV}A4%->P5eMh>gQDc8PVP}u+r{9>JMa@X-z2aFZy*=An4l$ zsBRk8Y^W}+(twd>reFFBmOV#u3)(A6g+c_~oUOZbWYS zToDfedU_45YB61>BUH2CH;J+@+<{;4ftL1&knmzQsV&`OpLpp&xG8j#aVKMi=kdTH zV+v?87N_7BCb=cQk}FN7nvp`7Z~&LydxOM$GIWLvjHQGAeIwn|vlgoUT_2#fg- zbdP{F6%L<)B+tN+blhUO0s>nk5Nv3<00Bz2VPanLt3bESMCL&1RkmfKqG%hN1IdfF z34|hSrG%0%^emiQTQ%v{<_~r#D)Tdf{jX6MC28zNk_PM0fHVYb4s?5jKxb1ourM&m z%kW)z?&(s!?2m$O;Z20xi+(*RD8!o3aUY4|=t{rt7g^NIMCy1Fq&*@~n4@2m_bU;B zxh3GqC*2TO{f}J)t)T8eqw0N~ ze#djEue_pP7~-DXHUL276SL7lQ_SjPJ+t0;N0NN2GZ;$bfbtHdgW-& zTDWFkkZb1p2I&vKlsySn2epF>xn}O>9K^$&ZsN{|TL~`(2_5ZNaM=9-C>{laOVn`; z2n|Ey_!u5g#0NXpVpCszLEPk zfXNY*B$G$;1MFkjH7Sy<__9YTzD zS$J}ej4kVN*ihEPpgyFpO0ux=6X+?hH=-X-sFP6RtkG0sT}3>=ku{fK5GiX3NkRCj zgr7zDHkPMwXFbbDV&sI*aM0d(D3AgNS@0xQW)UUTBnyYjf)gR3MU%Z|KTa)~{Y%!2oF+mYXtO2rpxbz0L z^0O(v$YKbz1~9>{vTKnJz#+#z7N4rJX&)k6--n=KiO|j=T@0Nlv%lizM|#hp@KsJA zd?lKm3^S+e1JB6NVNL;I6pIOp&jLAAP>xaP`59UMc+?7aJczVC1dK=i5eeP;9pWFgHT2EX1xphdS zg}|~TmxRmJh0{0SNwCk`wL=T#e&v_n{EK?Zs-|!SSB3dy3wujHhK5x#^$hHIjiqUu zP@bY+4}s&Vj(Y!S6ysa&-F$AY3OVZZKYBK1QDp4+NKxrooOOYU5$4GY(=`PAZYh%GL1o48Nqc1TlYc2sRUc#dUWAuA&0I#FLgXntYhk8N zzMjZ2R|ZR8gC|rAVbY6hMd=?h@*j!(M?tO$^0m!DzV^mY^0jRQ`94m*_IV;-I~L?? zS?B-*a|Dsw0a)ml6S`;j!j+q0ttTuN)IgUyrenchOz56VSmzlQovK}XU5HXDunO)V ztjBKvTEQcDaFj=L3dUlpDtJXqRW$S#l%b&t*60mI0TC?o3bugy7K-N30AFx{a6Zy; zLI%Zkv{);+)+h&q;kp*&k+18Rj9>7d61tOHLvQ86XT|_}4yi9DxRE5aA@c>?j)Yp) zO+uOs_?;Y1ZsNK)_`&P2th2Vl>WrKn;)w%E3Ek;gRV+l-!8JlA;Vvayek-v>KKVB6 zRQ);|&9m#=QS_=L&o*wj>#7J=(MWtcuCnd~6t(U{rl|IQsj!nV()$w%F2tap&^^-o zGfFFr0d?WCI<-(;;b2{L(X?(U#Ol*(BJ6DX<-i)DFqJ^I1*l4{RD6ZWNqMM+lqg7r7Y40T(00 z^(SAUxJvj6#rt_Lh@QDAGnY%d=I3CjDE1Y(Iq7Fs?{ zSZKLLtkd1F&~mT1Sz{23_AhBIRel`lv|p-f34_}gSWA_E$w3nR1kZ(*{{rk^Lzhey z^ejuc{w#~|AuDiltpXC!JKVXeSwW3cp}$=~N9zjM6QL`siXMTUQ85^q6B_o6irIjz z;5|bROID--mJL{-dsXBHnQTHPx;YOx&^R&j(c*f!h%lnplpBZ?c^ zv8RqV3>g}fPZ^QIo7i}PD9;2a(Tz4@ooBl!jCoT8LH;6$ z-lb`9+w?ZlhtPf?%DCw>$iGRC9f~O9rppAxQ!t|b)IBO&0#?~fSE3k*j7GlJZUpdq-J0^<&V=C?u3AHUH%w_azzTi#f2F+HkVaJ&&i^SN-qRN#x z{He!MDtEI-m@AKvu~wc48Dc9DUuIaW=_-Gw{Hyv9OFLeh2eu=k%@fd`n=y2;_N19{ zGaU-qoJhZx3vmL0r(^)pAoeg3c-p*^2x$7-9GLzZ+ScaXWLsFI=#i(*w1nKOFCoPd z^Q+>BIpo^X5&2slhg4fSkyJrz+A<0ax@91M7xgJ%%REA!)~H1SBjT1K%GMfXGmUI* zima`)XR;LzsVF9lEN<&VbdP#%#ePU&2&Y!w`U(WtiZeAqi^9kY!`zw%*a^bGEEXU^ zWw!o8I^KFsoP8(tZX+Ywc02u&|3$sq%tF1rfY6?G#cgC7+tMNGHZ0d!JJBKfZE%Rh zA^KR{ZKt7l+a7%=-bUMy+k)GW2&Q77-G*&Q+h7YWzQx5-J|=Iw4&&YSGXQHa0%Gbr zgfXEC2hLddbT(pGU(vW*H416GU)p{TI?tiNxLY-igNTxz`5*_jY9Z3n&uB}dO?KnC;g({U-h-lq@hV~$Mhn~C9BweGjO--&yeVT z2A<2lL|WTU8hh0*RdH$vfLsK`81Zf< zAUKe+LX}>fk3y?+^g?NQj(Sy>`sM8LIO#`)R~e|j)qByGsu97cqVIgPF*Ki@zGV$U40h46)fz-s zIbSf?6;2ESYT4BS2)mkxBD4%q%Xg%fU1*kFReovrk5G#}pq5?xIf$!e*WrJt#n2aY z6usQ_6*RG{LG%)u*!7cN&ixLWFdD$f1le|*sAwEgW@mDD-$^ytjVG zXQB%%_$ANxL{HJU-7Fe63?3Ew!R}#5KQw_qpvc9#(X79v3ec9@zq1AD(TvJbPu zaB7U#h6+8$6yU+9uf8We?}4|tC)F?cQ=n&H3G>^7Z50A>J@3)}p=YY?o{dObL(Ojw zJ?Xxus!`Y3bI32}4MqLXHhajr_IwP$%Iv}jr$X{O0NA#xD6<(_6nh~hUwv#>WsLnGZK+y zGp=r@+uP|@wd1NC-L|9K3@mHvy3%b|UIKq%GVY(jOM3BV1m&@?J3@HuUCFqgB3{*t zODk{CI@)8ab5OKYN1 zsr!p^5J^Ukh|1_MRz{PyN2VVk8=cHAorkx=!a4rODesX`LjCQ&fRCfhks*Wzn1mpl zM|m?t2=%x8{y-My--T4?m-bGDg(3VzMuoxI{}u;v3-ccVnD0ihc?C}m(YnY_J=y;$ z?ADJ}if222|2OVFqqaz)x0J`??mIGb|8+vc77yOBO??W@;%5^fb|?zjxv#wx!Q0ym zXnPUS3Ub?f2X9&SZg240+m86{eUyH6d0b|_o`|A|2;niE{a&^Z!~4R)p2+$#vXMkK zD1>ZCW3tgy98Mt7S4Mv%747vQtwZ`AD&j|>NJV?mzX-&B;1?Qt<9-LsdM_Ri)t~jD z(&#kI-s5_&6BE42^Aqvj_Z(6mqyym1PgN1`eOPG|i2Z;!t!MU)X$x-q7SONhV7X6! zH=FKkidk;o>r??+?4s8DR`RSV_`I#G#DkV9(za&396)9hmd)+6=y^AIJ`9~%Bg>FcTkv^B?K7UK{fC!`) zC3&Dvl3)5*l3xbi%Rfr;pqC|i$h}B^Nb=ADNXI34*dj?D-d&PMfbWR!C3)mRr1O$I z>MKbejWo_K$>YZ$)l2e(*^)dFvP@hj$&*@2^5mwH{Aznio(lN1DUv*Wxg^iHD9N)S z+gyhv&tE3V3yw+h$~Z}W^Q0u(T1&D!SCTW|mE>&5oDG?B$|X5>pCspXl4MVYBx{=_ z*?S{WA==^jFwZa4V*3q9P5sirlSc1#bQUPPE55!Kj+bgst{>^02yZrXq46!1dV(H+ z1sy1kNPHB~)#m}dM$orjM0zO#pSPz51N1tB)&u%SgnCVf{z}k;7|;(6kMKN3(Bbsa zzTX*m48W95KtkBfK{(>xhh}MKB;)`tJ#WH z7av~v6_eM&w{cS(K|IG4J_@e%Bd=*ff5JR}P#q2}N3!^(!(SM^zXlYF&-whtat|Z- zGn4mIRGc5`J%po;{7_H0=Wjwe+!pCcllS8Q%HjJ3%9(IYVknD&;xKv71ySA*D3`)D z14CI0l%fdLO&X@pB5F+-cs;=Ib`IlV1=8^0opcT9*?ZUy*O3<8jDoYKF9(7lbgOT0 zdEOEmf1}a+8#tm4u;Z|BEduammNz2eA4HAtdcbf^1_a({L|$(|@V-3g<`#h7!oTz2 zWwab&f3cHmISzfqKgj4TXK|g^o4*={#VezY&`kvCX6*%B$z(lizmG6j-U{gGCh)yz z`7S;}*N){1U9%t3vLV*;o55`PTe18WMK6&h6-wH4=%=6!5}Urlv|H87@lVJ1O4w}l z{;pRI71Wv(K;+BL++FU5Bi6X+VxBMmj- zBOI3#mL{kPn{>@3Sm|0&kmeHXhV}`Y@CDyLl!St)yf3uocraN>D2vLwsND_?u8Tw( zjpPAQSeVul94{n%mDJbh{j;$a&FbaE=M(#dXz^Y^k`mJ+RSVPK~haXIY}i+H7JCBxN?%# zBPVlZWWaNsgv#_QN}8@(YIc$wR^-eFi0YAdOu2LnTFNNEoAv zegP&_@(|c0Ca0y0H~PXFtE4OPK1%*LL?w@?ms4&^xh+&BPXKf${&fdGV@hlG7b;2V z5L8LZ!wpsP5LZc8Qc3Z6sN@k+NpW0+A?411O1h!&^~oEP-wLQCd28}pynaF@$=mVm zZNE^-ttRa;h|(kFxsXCzn*DHROqtDntB^a=tLf)B_b0I2uTD@#FS#JvIYCQpow!RRNTodSOy#b2Fzr`rQ zXdTS|8jaSGK_yuy<63kz>pWbGXGW>6Px7wz6e+AE0SbGX6jtKERZr?_C7uX_H8!BS zXb8D6WlPGTfa+3qq#WXU5UNY5F~p@Hctiu%l6y_sa}aQaHNje}tInEE*X)O@&gwF> zw-$#-`oa}!E_Jo1(bcT^QOPx0PbjhEBS|iWdsg})XrRRB!SDm?nY4CBUz5g4?4w>z z?UWi7qQt&{yplRC!ot2>N#j*NK(?jsjEIH6I6{j-e;^>W`1c(OFs8oE{~C>{$AUUc z#oQXs&M|bCQoqD?EF-2mKhIUzhg4X42#V`VDl9#TtA3=y(oZ7{skH$W#zOqxt$(Ms z2&gbMJeAFFD4o=X&rdhS=c)0?9jS2fQIpmm^8K88J*|zd!ZeAl*$-D?n#s^Utxc0i zpGir(H41M)XP>6NE6Orb>ly`#Z9v)(N4(M3RM(=UglmHU zpOd!Aw0bNTCN2$!XV~QPRJb-6nPq9mOsmK1nSPPEBwQPU%nRvvnzUYeCJyxQX)9bC zs$Nd-m_FE~k#B)I#-%?iGG7VTh9Pruy33^9sAs}!W0bSQwc*GtNIz;?Jz3Ah;WL)m zCtMqW%ySucnKb%TD`TsdSsAX4R4->dkTJ=m(WhD|GXvoXMp+xKjY8&Y8963xh@NQ` znMcF5(a0>#IB(ME+p&xi$Br3gR=73>nLpb)m^88|%Cy}oGV8;&vFc^pW42i)I8-8Y zn8+*$*Tx}prEQZ*qfeePN<@>0?c(O)+IVE{wS8^U2I!geHhY@&lf$(M$o$RT#-!25 zAc@khn@4!KHc`E7?`n@RX~Xo)=L9AE;z`IHZGYXQ4c9YgiA;FJuOQQEFEp*DuYNMN zLZBtLhHI0NS!F+I@(HtyvkN6GL77vK`GpakHbdX*GQk zl-N4j@XW=~?Nns;bUYV2(9Z;@kE6fi6+_|`II~8_2nT#Da=jhn(A7ewyqD-(j|T8S zzp99hFgW`2eg(ICI+#pz%yFoCCvm(^*X)OP62}UI;#fgr^Hg+*iUmjo$mWjrW!!Cn zQ=Ja?aw?po3e4?rzKg>#0JXs2GZtN^0664pVLb|5`hoL3%Xfo{8LvtF283cP*m=ir zShNm*KbEB2AMh7WmG2!%N@ycV>G@t7m z_$7Dq4daZ3NnsPfW`dDwiMf3_h|3Z;CmsqX036Q5?THZhKiCk;IHR@{Ji@@kC>dfC zcNT!^*-`u_HH+Tdty1=JKtKUav?6dl zj(@*OzPnMZG38TSGBu}MgerVW!z!fwM8FmTsPkzg0xkCvsYhpA{=qGCJ$ppz&BsLyd=yN}8=zQAsFU+g`%=55F2(SH86WEt(P>h95RBB4`T}?+_iflJ*q)9}eaT=> z9j2zfW49NFJsv{NAkHp^~Aiax-_v+Nu1Y`oz5URHu^6|yR)b-%KNl9HV z+6}a5xYS+X{hd^lWYTQldm!~x+N~HB=YsEBLB5|6knyEagE?HV2f_CW`2MM+UWuaq zq$P2_Y0&GI=NVtSdNu8iv<_(_BncXcOQYkZT;8-U1SGy`@XIC3^hw4*M}Z#?eWvv@ zn9~L*Y5j!IOr>htFfiAcGCW{DHf??yLdNQsU`|KU1@on8h_bOCE@&Dinly`&wnFFi zW$^`*rh$Pitst$=Ak6|jovj!28`4Ob^dsmiL0_e$RSNo9#h;lpFUSw1olpDOASJa2 zeNbs>7t?;`G?t+CA~~kP{NSRsWEYe6m8NR5O-_( zfs7bD>-aLn#bR04+Is{f!%DwIz5fKOI)1$$urD&NXAFJPuVvhkfqB+oIo>c^&A1T~ zU!~zF!>sp6B_q<3(bg|l-EBEpcv{JL#FEj4-Hj~#kPl8y^=ihzjHwx4NmB9v__i+v zWP)D{AWiAEK?G!;fo-sU$(o1U0x_l2(TR-xtux*(-hu{;Odf#gcrBQJXS>tZ1+9Dn z%qg7A&BS)EtxKSNU~CQQVu-c1F(|eUimi>%spUlB2PVy>UbS_##n3~s@pd@Ov~MWb z4JF`z$O^66;HpWM`61m^6v%~dT$fl|n!#*yD7G|FK8g$0RJCRLw+TfA|MU!wpwaZ?y=YqAZTM7GRY`>DK?DakdW=H?E(!{?A~nqO0j(| zie}T5?Gj2njOi-IcDb$D_D8&}9sqr-KRVXl#1L=4i9pdYb{wX+w^i(B!GMo%_6He< zqNG^+qXx6Rhi)ONJ(@Di_Wl<8^SJuJvVgSv0rX4SL`LBRkK(41_D>!qEso@PfY z#c`()2`n(-IXW2~o$y6_)>w|t_$wwkM-;Bbm7n@r3HY*~aQ8EDPW-#nY3` z)fS86Y5Z9Pg5rxPBvx^}AnL#hQ60mH0+}W)TfOR-;&{yoPv3@@6gyrG)WNZYfRZsR z%&|OZGmdz&ncJ&IyN}A2F=N_Q*l&<>f8Y*rTPyt zCkH;Y;dn2>ao8{Kd`chfaC*Y=DeC!Uz(^e55`o!KZ*kzz#m*Zn^f*F-;~G&(61gGR zbadWr#zWQgNcB#0kX6rzolmxQ4k%ns-jQ<%@rksYjP$jXqGO$^!R$;4l;X@_r8x8A zoi1V$Vu~g$N4@IY;@s~-JK07U;+$IpT5}#HAho;`p%$j8z^KWz#Yax(_pT<+>%bFT zQE~nqmDFDI(unE0Sr@|MYVMb7hL~OVs;(BedW1Ey#np;KBNf+uA)2(f?k6}|FVlia z%T=$sdb@_YFqJ1PGQ_!_4~Xd+ML_n$EzvbialIm#@gup#pF)(Ciff^;PaSH~^1#;S za%4`!q6eNPRoCdsq+7{oG`h$dM73NP2=z6Qs|@+{a3-vun?^*8tJ>`HtFGOCc~>XB zm3ltxdb_pjSP^}eHqv(wj#;{XFuSf>T$h3MSP;u?Xzgw)u*`Ti!rjGFA^TbH#m5 zNW+I7_hrTXjbKfqs>S^a4ah(hwx9H@BXVljW` zad5Kj2?N7`e2tY-%WiDx#FM;cBtpJy6baWh15%y5dt`De@*Ot>1{u=I z7UZ2wK07k$O5;34hPNSe8vdn2GGp=r_7~=nybMM2ZW|cElM@NX{QzAfjX1LHnoYD) zuBDC9N?Iw`Ud49JG`>wt#lEtEQi{-&%A*LEV)mYN;m>xfMFQanD?Kr4um*8t0xy8bR-q+kKq zF2MGs9vW%8!YCW5aW`_$rG7rrcJ-gRP~>N7Jt83;Q+r6h`+;DzM&lCo#KIpd+;CsV z{}9Ds9SXF68d_DL!Um?*oupO&gEvT8O-CG0Xq77a-lcw=imAZgpRcV^f2I!XXmsQX zZ)MVIp=Vo4wzaJu5KAetw*5a%Kc)OXCDMarDR@^#%1P}rT5t$htCWv z_}Z%0J0a#dljc|JGdg5Ema&LM1Ts2O12;pbFlIbWFq$ee`eK^+w}?Q-AcHw$gqktP zFYg`4BLW!{j2RO$XfGSyY{o?V6;4scWL!6l2xQDKbkCTBB3L&vSTg2-Pfqs?c$M6D zF~nyq0H~mQ#%u!Nb#@uEqu3W(5*Y5zM3#S4(vIs_6hzpIDlN-Mx8YC%t(`KK2kVqg zKvt(ssMG(kcFL&DIGgb{Q2)7hdfzYa>&n(nUvXiSj2|o+mjE5cS5CiMGOn^ateha4 zN!zE^+itaWvsLkhlMN3D=!=nO3HTq25lBicM}{Ywlon1lS8H2t$iitqnAh0eu{Y&j zgpD4Q7b~6P1Y|$li@>XX@S-2;huTivU+CGw_G1)vuokv!QPh<>YrC~wChdS)Z@lOd`w7UrXBs|rM;`fz#MqyJSN@!0e?k-^RulvL^8VLZ#N;jT9d4gy z*LWnxPA4dZSH6&dj4ws#8b)I5$>3{K?8#AWJ{m2j*H%YMT^COVx1)yBn!h zB8K1Hq#ac29S0nzob!1=$q|gXI6fvImG1Zqf0N@v7A-8GgpHk-7M)OzRZ&NSyb9_Vo{4m5((XTaiJXTabS=VjOJEZ*fj z7o`8w#U_0&0O(zkL2*SWE=ka{c-LXI-ZjKE&xMsi`UjXYplqXSDc!OkVLu^Fjvz~{ zE8fuBmAYn47)^@7c|NS0tJ3JIbnOZdhh&0kJIdcKnx&g-kI}Wqbp)trT~{ssTBbGN z#>RmlbI>0E{Xx}rz%L(sht!V<%2~DEJ;uG54s}tu&P^`?;GMv|!c9Gkepn^Q9u2YX zHw|WYy4n3^l&Gzw9VWwPx!v3jqub&3fCMtRo%oADeMlY1q8XPQgW_JLy3rXAO(1h& zX8f^QpV=w1Pv%^7NW|1_&JmdpW}b4d{V2wBjVV>4eim@~(kGhhCPEXeJaInkIo zF%vTd$&xtlWX@1C@l5QYZ<(=DmwFenEX>TvO5mZO%tb+2atZh!qc0Ve zkD?lcf{2s}-YA-tHL-QpR6Z!j+tC)EsP$RaEG-Mq@%q{t;<8c$WoDIT?EqK$0StX1 ztK6Vul}C}^qt%$SPeHjm>u7dn7^mD5r2H^D6I75Z>tp=o9tsOp7-O=2G-v&-W?_+X z_y^Ii$M$?U`-axp=Hk^*O(dN1=-$~+n6vvR+0jwz74+6>z}4)2M8coYH)oHF@;$%| zU($~DY>~Z)Nu_2d5)KLXo?4$9mHYInNT>xNtlWnJ!sYfQAWizYu{5*t5LPZGieTtL zUs#3@%$<=tmrt!B7G*H!#w)o?^GI1|{!LOCI7cM`}n^j9IH&P^j*>TJO2n^SCyQZ)SN~1w{7r zz{WmnOi#~XV|t#aYkdcm1;{+hqkLVMa?GCOKnr*>{qj2_EuK~QGllf7y%XcPV)p#4 zc&>-&T{8sq9`>wRYp-bcvRtZ?S$kB`B3XX$;hVy-+P&IicyWjp9oj}F?Sxvdjn=07 z;-Fpx9knrmnrL$fNXpk<|A+F81GN;*_AkoURw+JSav?LCWzxB`bO+6ghfBXl8|weuG3Ofc_r=4)xYkq4))g?5GeVA>x+ zA1ub(!t8Bp@!k`l^0p6h#H`)I+nwDj-rkD0r^uqoK-<-`yBA%L?OTLQ8;W<3z`D=u z9Te|{-~MiMy$+pQct;9Q(v{BI7Q;lG&W`cEZuY7c@3No_2_ce`3|Z`6@fIjvO=Klq z(Y9#2A;Y$RlVO{{f(+Z@z1tu|PKXS<1Sq*xXKgc+fz|W}#e31>{glKY?#Znb@9!2b z-0Y)|vl?&i*}`{+;=9%2gL}ncNmmqK2aB(@PNQv!_4PC;zF3P7-ptX*sWU{!`o>US zcwepe&Go7IFY{Qjk6xq1=PO@20m*`VF8uxXSg~=SZ?g~cw*5KGY2Ek?+SRw8W=NQ; z?*qm6jxZ;_O7eYd^nINF0CF*4`aZ#5F<|=0wfl!-Ni6|iBgXf$+4rmJL#^MN!UM{_ z-*CNK$#0V2`x{q>*`$Xe^IKZ-ZwA0}0}WjHh)BK%Q+p~J`-;fyX~}<>GMO++{tHo- zL)rJZ4R|R%@QnmY{$rdWde# z7(=9OWc0u_%hp&>hY1te`%Km(@b@$Hr|&tescN}qoi?9jih?u%ysNG`=$DVBvlkdd zX8eE`5DZ-N#hP#6{brz?;f4o*gh7MtHm{Y8Yo)bG5CU3TYrtQzwp<&IYkh6Wm1T@s z+pMi+ErN2#j?!9f?ZfKY2ZALfMxvzXo~diGnSJbNC*;po*G>)Ow_m&57{7KA?k`7L z`XsDfimSgsA!&Ho$J%UlEvBV_(3g<$OxUxn*47pe#RR0RJ=1dSVQqdAzN{K0t*u>q z5$#bRwOsoHV3$aPMJHnm?lzbUBGrO6#HR%V9x`bksPzRs3i=hoDWPb8!BYYC7YrmI zMf(eAN)^^pFcQ~|qWuN%TZ2<>AXdbunbKzY|VY86=q_Ab^d{Wp`DSRwApA`02@Iob;=R@a{!p90|36aM4fFWUqDc-3RSE|M9^*oII#Rt`5Ki%`OKc?hnb4d%Oq?wpm zh*~XaNeE(oE$Pf>sgftv60CE1A=>Wf=$MkKw&s!pN=cnsvQy_6C>=9%$$6#ZtXgtP z&%>-z^0QikO)kM?OLR=>gKf>Fk1M5JMdd>2O9v`=lM)43v|UM8)Y4HzsBOU)piAee zrE#1Mrd!;ntEEZ27^T!LNHk1rrCxTUmKHJET`{E>%%$Hdr58i0i#MP}V-PZz$x4|q zVD@;vcx;)m>=vnKi?SA617)ps&by;c+7Y$BY)+Y_>|L}h{Abp(Wj4Ac+bqMfPakW_ za_L%le+^9#gMV3}p>0LVs2VwqtgQ9b zbW2vW{^);LQP{xpSIVcuOXGoVrF@=R4z-=yM|RxPTn-nM`{&)u-Qd({bzm-cE9I%W ziPM@wDKAvZeT)HCtKG`WjOAtJa8%e&!-~b0Z!)OmaJ*0L!`h*HITmgdg=|s2Bfi}2 zmrpmbjI@;3A^Q`pQb6Exo3x{9eZ`#>EjPen7V9a4v7$ZQvLAE}d{w(*ic&E~7mS=t zrDDEPF;lcDUrCSX*`i_{Z?}rgN=3QI)cvc9x_?$!si+fJ_n9l|)C!1qx?VTP&Mhhq z3Q*9$irH|xdBeTR25unQZXKEY(hX6}S~_dHqOnupUoXjfpOEBzHzH|Bze@7{myt@5 z{*>echa~x}c%=Q3d=ST25B8SiLt#jENj}^XiT)mzukCB>DXjl6-QkB%gW=sX&rXXGrpglcBd(VcO^FwS@HvJMAZ%`l9~t9SX@1u6+sY zol>LCr>~_uOxh*n{F-P;yibq7Cq^XR2aEsrJr8O#*v03;Fl=n%tvHf;tM{RXM^e95 zuO)t;cr|H8_;bF8K!i;#Icdg!@--R^Np}D(c{vM&jFG~UXbEjOiQW4#Y}-oT)Jb}r z;3GL4M`Cq&L#aZyzq}7KZ|%Rfzf9V<>b0beNn4ZNlfn|_a#{VjfzXiZFe{Fn4;G{t zj?Vj?dM&wGvXcCu6qfiK!%uFD8-|}uj%;Wc82H}kad!#TEM_-3)HmcBxS{*$Z zU8+H(7oNV>~>o`1X5=PsE2BUQ% zJ$FKb7(I)k4`Nm<1_Of_9RmIdbamDP)=N^D?_o~(E^avC@eslbbR8XtSV`QSvC)oW>M(u&gj*eg23sM5-D!-`DXioZgW zX*D6Tk}r$`e^IZc4^5w#z6cwFLl|xP4BW61)8_|i8|dZ=hziro(ks!_4A+>x5jXsY zs&Q4lhI3s*GTwv|(BjZu#yH$Cu58;TaCk9Le+oE*vR=JrYi3hy-4Uvx;D*77!&+o{ zXe%3f)IX0sg6LNe4Yf_NO*e!kwdX|BZPRfN}3?q$1W0Chd3in!T01qrHnEOufP=>|N|# z1O=4+EO7n+&UE{H`x4-M$#It0mjrRBLH-0zt^JVwgduDeM>%0X5sHFQ^P?_E36lK3 zhma;9IgpMZ{Uym~Fv^`-h*XAjQIgMMlsx+s(jp{`wr5WwVTAlR3TZIX>qvPh;Epiu zFZG(^CdWMH{HD`BccNd;S zct|ojU%~|#;4IE4{0$C+PEw^l45Bsl;m)~&;9?lWgsH>-Su9>GexKQyYjGkH^~t;X zgqF&0AB%H(#?#5D@c02V#z7$lI}oG$8|()cYn zZT$amGDtcngVe{l!}+0eA8M35c#Nbv-v!HBTAVsRjk*DziP`z3#rZi&%+E|Y@lL*T z>m|wTtdDp8OyvtWVtE9YythKV&hA{jcbmL;?A~>&>n>ME$>4ibcv!AhxRn~!*43Ic zxkXeO+X)>E9g$R52fzI3L!=0kw+WcVxL$M(#aPo%XEqqO{D+zsSSDbNbd7Vpj@c`4 z*k}@N*?8ufLZjevhU>z396I)Tn}T$i>rGb?hMjJD0m-=Kq^TjK==2~B*s(-|kM{=9 zm$^2&{Gjiy({IBqs*7zD%q)7*3>_~%a2;^H?fM4jkLl>gam$N48ANw|0a)nvBMOs2 z{e$Z_e9=X+-CQK?pOHEr~6(qzGe{C z=5pxiA&R>{c0Rp#vz<@(SigK8M?8C&yf=aARBZZ`ApnAHTKBXd z(|7_hrfEUx#QvGv4W^pn&Q;uQc2db}V8^6s;p8sz%NOot+;0Z=4er`Z6Pg;#>8)`> z;)4XE>DB#Skhz^}92qK2g%1UiECS^MspBZ4w#j!-g(gvy*bl5m*JnIkNj z*bx0}s4lZPb7GX}GLpB6$i%3E4&#+g-diE+g3QEBY~tL2t+9ncQBw#;O3g%z={`%Q zi>@1l-80uInLZ(nh3%7MVv+LMF(q>wE7;ov%N3k4+s95S(#Vqej*@w(f&52_0P z@?}N&<@eek?5>SL%+)qn-gg;=RBz9MEd0~B7Aso-=O5+kix^>+a&F( z$=h7LmeV(9WNsVuV{9Sh^b1ryXFLI^>N!*KSM>6n*&(e0T)Yr3JSJyZTXRmLlJlmh z36HGhI8o%QIQ$TslVj)OzmiiIs)U>aj1o%7IfASC zk~bnI=XAUHoHMwqkd&Ms%{gEHKhC}bK8m7^dp8LOEO z2?>PWgn(ed2B>@Kof0Gkc0);pkX{KPXL+&rhWaYlK(PTvgO%_9%u+fn28ghmNfFsXMLE}t1t^Z5Y|rf_#^+u~ zxGYLPxij~c+(~&ez*+>R_FM~rasvoR%FPXRDZpHUFrk-{n+@GejunUH?h|ae&q}%5 z+^OzydVjMD6DYBvxedAP$Y6I-*w+yDIa6VY4bJ^^ur2qrBljf2%X*2TB?@`q6&2q% z72U`VJ5$a@k`ZPYH0nOC>kNwnwf6m5A}-hhe; z><-J@4VHI1y-#o9W}pWfh|fDL<&|kf^z}Fv>sNGXx` zInj6RDe^!Shmi?;9yToH{VwHom|2(eMNmFRLwSlMcjouVzdpZ(uP@2(Y2@?#K?Ee^ z`Diehkz>q*kW)(~f4Y>9$v2jrxLWck$KL$q%ELeC{`Y3B8+*gEoy3kpEzQ zcK%Z!rCGK3{A8#1nH+{cU(V0N$1FZ{nO}hSl!W|3JZgZBB#%0`QIZD{b`8~8ut7zF#&o;%KuVho7Hp5^}zCTfwcgJfEFm^pEIx&^esT`#r}+} zgDF!S5QqzP3T}`Jup@vMCoB|7euUObAce;jjPNWNQNa3;qFBIs#I-D~d97zJ7%j>L zqn+O0ZWT%jEy|5@XMtZqSOIc}dbie|C|FcLEnoU$l+EOqic-NUsbHyzwnec4$%6%n z1^Il%O@V8(ML|YEKF6f3GAPIff*h$JTTeV%aiiP>1WG||!7F^lO@Zpt!jXbkTnJE+ z7qkJv^HM>Zj(}F&CSWr*Cld)4lBg$B+({s>qK#w}7-kEV_e7iWUs-t%*neV`hJw!3_qdMY zE{ie(gnm^1QEvqyve9wu79_3;)r-Jn39(h)oeYf(nZ zooJIyR%KvBg)YXauGKMW0D*~h6&BKsb#)0m%$*Gohy#H~WHk;1%2}oDP&eWIh)_Dv zqTC8PiE5sD8YkVO!3sJ_hKf{$z>E%cqqMe)THA#tnHQcoAod?|p!y%B($j;mP)d7B z>brU&S5G*-f9&H>Kf~iDbc05L_}Rklg+p00Tm9akT-dX4C@4Z_g?(I<&4dcC7l*;! zR5*Y&`U?jFWrm>iGI+5lx8bz(;f41UVlar>AcZ4b=%*8qp%3{V=p%tX66oh6D#}6O z3gAC0DE&-7G40@eW#0G5i~Ve6hGj&u-|k4WZf9;`^CVqzdM1c80@DW z3W=vHaQ}?}n0ixa)9fE3?;qjxK8It!V2t+r;dP`?ywjqLmpk`Q-ygNVKsQGFXShf# zATT4r$2d$RHZc;&A+#}?Di0Wq{fU_H&yx2i0{doWjP~!uYo<{Annk$_gw*|2`#;f* z(f&dgp#}m|&fnkGMHYtlRp5P3-jDvlxvw>2^qWPw8yG*||MP*-x-r^+(uMIi0yEaB zFK5=y0jR5sF*<;i3I~SB2d;N|pC8YS(Seb84-|_3v?vqg&I4l)1RTiKjnRQ|2Au;l z2~2bjL=aj&JaRx+m!Ta)bE5sg;PqRjWWuIk)IB{A`XMQ>A;)J7#(=a>3yL;Ge%kvi*gUJ ze{|q%kq=)fbK=x-cMh5RiQ^kQrQ{9b`?#YbN&lQ6A&*ud1a}jVy1@H5{;Ls2{|BK*# z0gbH-HG=mq-oOuIGzDB7EUG>{$Wy)N|8EdkvzBaZ$4l{-JBvpb-`!Ka7mZrC#uRG| zi`|q3pm?F^LNTgV!L#UZ_C!h*qi5r#-g|izGHX)|yUWPXi9DbrIK6*)zNZLmV@X-p zS(F)|KB+jecq7XZ#rGL1EuLFU7L4dD!c)%?44b`pl{gH}R=hzfUgb-iEB-876hG+n z?zk1%g2Gvp0APQzIH&kKzF@L=lMDT>Vy$UXjAr*Btp`-Rml*;kIPX8*QG9q{ab3wm z7@FbgB%llg%AblamCR!!8pS^w7)!blj2JHIO@-8a9tXyeG;}354J;XILKh@=mMkh+ zSMnA_#QNNl#V&l06OamH2{TW;k5=LUZf%P>VP*P2KkSZ@oPj0zCd9!&{C>$drLbnS zRkh>;7vi%7WPdPoCFew2$sbY)TKP7@69ZWzH zwR9w&dfLDr-Hy^RqOJ5EsdS8nkPoSp20FceJuWC$S(KT;8&8hBQw8YAPf043dqlubt}Vu6*}3Y^t^$*?CP??KuUjH z0cE{Ksq6-+tha_sKCRqjQRd2>Ww(?~EL*_(U1hGpnz9*X=&Z9pEq)N<&!IIaT+nsO z0E-fh=u67Bl{xi%3g6H_%8uT$7NsR zspkn^Udw(Ehr!v(ev`_6&=7JvTMm=Z`3dYSFR=6E&hj4RHtYw8?-}_iNjUHM5IQz zrYZX&NwgihMLIM{IwZMC#}C`kg2{)_F!{ZT4%<+|<<3KQ9|}0s!k1DWatVAWgn+b^ z@=zEF%q`)exnv3X!3nh44!nzp;>_03m~J$Tx?TJZ57Al ziX%?%KmO$FjA=BRiZ->m%{U-1R=!dhea{Nt#= zyyc($*-)W$xVLl|o90>OOpd@vNKp*BP95Fg&~@r)6uf`M`>%`O_QG8hynn;uqTdd~ z{UmsI-VXN&T)p6Z@mjbwaK{Dj-v__}{>L?N32+|>-hWb-z79hXa_8ZBhZi4P=&4Tm z|7_jxHoT{ovIMxkKm2n~bt+mmOod*`Qn|Czv$FdYrp$3X`Z9Q4T`9$6_hJz!M|D$D zfu#)ppMycq!_EBZ>3R4VwSLS;p&|HTjB0qPQyHzp@8dn2HAJX%C=0u^h;RlpxPkfm z%Zaxow9osm5Ae2(&IA4Hi=N`)GTurWY*AK%u^TG~RU-A&Y2Xcvc~*|3PxgmuymGYY zS2-GRDwn)B%yPX{Ihr@dm-tt}OGbgfU>- zcPq!rm7|^Be@C!QypGCocz-y)@?JbrvDj35vnZ?N&T4CQ@9J`J=&x~DeG`3Z93qoe z50k3LN!7P%L}hUv`XRY` zjnn&|p2k!IR=rgxGNf|#Hu6!HO~wS{{a~rGy1fP~k&+(}QMft_za^-4|3z?v*my|M<_s%xIBMei3AxivK|WUmm6 zn6G&U&t!IHlZoq^Q)aGfeid!C7OCbhjcYa=U3-nw`;tGKFOHKtYX{Z()+PYcYB8>s zPHW(eyxO}6NOWqEMFa;;-%gN?a281j#+{ml@pP9mT=H6UZ%P?8bTGb|$*N#mAE5V{UWptyvt!$g1G zLa8o7XM)Ww(3o!B3NXUw4P?2qZbO};?kL(^nPOa>YokhCO5IUVr9VTfby;o%_KQ*- z_$}86$eBfNT9gNX@wvLU>O(P*aw9N4?-K1}0@8^Ibtmz3SEX3@iy#b2vMr^`7uwPn z;~2E-z09=hF^o`ut5iQoqn&gkOoUwT=d_B8#Uz`f-XCv|6sKC0^>Sx@ME%nG@4?S& zVqATs!B72a0-9Bg?o9n!u$KH7<$R%jGrd2`Hb!%{7#Ivfi2Mu$ih9Et;*HE5oSO}6yLTNvX@}S(=u&&{$hSzuxq`@^> z*^o#;Mlu~wBcm-~wLau*z(}+qCqCPxhB`gbvlyBGfXqeO@}oFF=Iw@W8gJ%(k%o5+ zeK-8rcr(z`A7I>yHT+`2Y;Wu#N{!b`jo0YNVT3J8yxiG1vhlvg1lBoeywyP17~Duk zfc^}GjbUyGR{-IoQsY_;;ku$Z79|1rQX7jJzd>*1eKD@lRoEL3H-5wM!TuG$&Pp3g z=*BuXtk^By__5UZmWDOy{o*$)%0obVw(;+#`OxnfpmhyqH;Dv9P7|BF@pRBJoPJ_l zlSI#?5yU)pKtazZTB<)hk9QT5nMj<<6$XO%F94gdl$d z-x46==CSFqrh}RwMgeNVVU9*3+MBkEQqz8^DNmOH+lws9!@yY8)Yd!^*%IfRHdVVY z9w#6b-lo^_>{57}PW^k~Z8~qJ-E0wU%|24|)f(;O^;CG92Rp6ZY*cugN8{~|lD92N zlHA!mxjCYF8}AY}Pcisup5MGplMt{eOnuEu+^9S%O3leq^A=rw9VKBFqWX_jReY8HblOpOczTYee}5crv=p9ZsvI zC+%ieHiCysEmyZZ3@vXI<60;K@N{eGM?flxEfN)eZhQFYC6tgRTii0iOt&Rew6!dj zTB3B7Zlt`@vI;cgg_6w{C0XuldAud9~ zEwvi*q=}^%fq4`dUu*gJ$b3kFGf-PzcVYaRfRtBS&f?i6ueAL0?|J3OHD=mJZWe7v z{G=nJbip=IUO6(=Y3&|FdF4nL-WHT%5acnr^T^^Oj~_V#ejXR&j<`z0kGMcEh@B8hW?7WSL9PABN3CeKCO-jc zPDA=5rwGWXoyOB$dc9qx6aCXnw6(WrYaJ}L`shSyGo;))%4zKpAe2fLrN2GQjXS%2GQ0i0us?yQvH=hY+dd~?FmpzlUkqAsnH@PxiuTqT7_av#y<&a`K>ia zdx0A6aB0QK>RL8!JwiZ6&57r~ir9)#E0o8+Sjpj=oy-lA*<;b)JQ9X$igF~I6F3`Y+Wko~!a{27f#HyW>j z#($-w@9LtVH!29FeJsirp#I_LrMBs87wpj=4UyWq6O8=<#_NDKjLf<8)pm<$Ya1`M z-KHU>i2|V%YuBEVJKKWWmbRg1n)JOG*M{31w8Uv!MLnI55&r) zwnB{<5F>Hgs+?Bu<3cfpeVzu#+w;IX^4 zP6Syw@4rXEy&-u2vjpyK!TS=r-j|Z#eiE$0BDgbxRh$6#ieU9v4EL^J^~ASl2HdBD z)$2~UBDmiKYqw;$6N1&U0PbzU+IJwMci5L#5y+~#3%;iQu4DR>TR?!XS&1A$PV9Zoj*I9-GZz*HZFYr+s3(HaXBv^PFy-DSLacXloDl zMgI$Vp*;e~E(%JVMacxVMeR?tzr<%R+Ff%4?VHyW2Bt3hdknYcUPwDtjd4H2fBy9iSU05;q#!ql-~cIwD3B22XtbczP;#zmMK z?zCRh9V=-d!qg=YVJf<)*Nh<%rmlAvVH=4sH6E@2?qg(E%y!}}!6d`fLhgmUz>H85 zEk>DQv~J*uWs)wthwnC#NWDp{y{NIqw*CmEH&~SIjO6F=yWkY2t%vc$2nxPVno0i7 zy{=#aDchmZLgOe1V;_j0*`~3S9fW-vGQhM%xc6YOF(ZbzjVA2V(zq8B2r1x6nwf^B z_J$A)Py_y_m1_L!ONp4z3*>W58*F3K?gT*7m5*NGd}Aet@o@rR6fgh9kTQeuflFMp zngw1^0C{1!+Y?`%cysI|-3owXh*5|?tbd`WGbkH-KajwBU!F##QS1>E2SmGZ?tc&1 z@gJjco}2;WhK%h$!)fhvGjfAJ`aFH^M4I~}pY)j`lwzW;jM(*G0k;wEO%FDHfj8HY z#`t)WyucPKiT)^HZWaic%|DF@XZd0p%t6WHzYEFZUt01b7EtH-@_X$4+xfYCIm8k= zx_#agluV1VlQHlfVBb51=^@Zp8tKdbeUrZYf8kyNj3K-(n)NjuBMiE}^qLaN;u@OX z%cLPYkPM{^I(;0tovsg2CZ~Z(@HBmr)7m!@YMMSBFUy3|8!gJS#N707xTSEfgSlK{ zZaN!}>jQ-#`KGVtUV?`R=B8udV^H!OR><-7q`@kS=U~Yy(67#6Mi&nEG7c#VPS>+w za<0Z<3m7|396pbiOF{`2sqA7L!W2#a!YRy{4-WGfC9^G>4$YF6#^HIqxi@Fv-QA7R z8P{CK=#1;#8J*!vjLw)0MrZixIWCVgI>YX?_R9gIGiKwZOen>yVlFW{V=>%=P9Xrg zb9fM=GnSardB$Vhi>LDp8aL8vQ3OnMDV9nAs{m%?n3zHZFrxyl!E8NeJVy*RX$C~lN)$QJMr+$OVZ0m($y=$LDjTYy5) z98I>Qzqo7xrB3U0{UBRFC0+&##U~(JKpSKWcn*M>Og0>cW3J}PnQSK!ot_?H4sHnN`YPjU&G6@LMfI36fpii0qm?(2)Z9- zGN1AHshPiv+)LvRo%zekWYD$$&SuaMcQ%9WA~u79z-G{W8k@=aoXwzUr`2aT*bKr* zrq8`XDV7@?BsPQA!EJF0!F^%+JBZC7*N7%QkU@g`f)AFwK`D4krY_wSHm1qSU{Ick z4dm0H8n`3od>V9|SURe)#LA!#0G|=`JssMCG!8<9b1vmd+=u~tG%nkSx1 z8V!C3j0WGYG0JLv@EZJt)7n2BYk$FPa3Y1+K|iUwJX&cC-b>KkU78HRxIjT~GSFq^ z!L=g94TgR1Uu#kJFyUSS;3KDCe+boEJrnL#Q~n7?u_P}|xUWe#x7iymoO!?yX=CpJ z*PDc6EeZ%{w}C%uG@LtjM`@r6l+*$CE!xM zJ!Fq`7tX$zgtM;#N?ggTkZ|_L;1Zp}Ol0w-Z%H`&<0j$k+1v|4=|go)9DA;NTG=ZR zvC&PO=ZT|cO&tATCz9fQ^7xW|PIO5k`#FMs-&G2nFlbJqnI6a?c z9`05+3=|}%lN2*=FiA1fk9%>mKXW1_k>1LiIRjr>E01b3))JjL+aw<4`k5QR*-T@) zEuEL;nVX%~8@-{@nelk(FO+P7d^0mCXaW6f>muLGGJ+oHBHzp^lYADXkO|a=fNwg5 zkQfLQ$pmtZO~C78?#1)m%##qoy&d6_cRLd-pLJoBm?N#E=sf)IaH@ZVUa$0SBkVqk)^>59)=;={aK|7lM)2_Fx;YFVlerg9tyz@e z{zq!fTF^zLS(}N6hjfwVa-%RS#c91MO(-1#0cMf0n?<&5)~>DsR1&njs{jpd0#q;o zUO+(DvCu)Hki3Tp@S-WTW_?RuV4MCh?!ZTRw085XpG-X45zv#m`=Qs;kGIbFo|4@b zWj~P$y#;POoC;m-CQ_lU)p_{1mwWM|8afpOjfQ7vwkr=F!4a;H8g?9KdF=7 z&C6?Oy3;zK0a+n*J6>K8N{3pM1B|HyfYm#Nunxw`&F>| z>=CT}V+8By71t)dn0lMGMvez&#*Aunxp?V5wjoGy<+(unwLFDF=Bd zRiv%iE8*5Ug?ScFHBj)tBA6>(7vi=+%9sP7QD1GLJT1j?GJMB?4=#K#h2Jz`)#tj|1ba7gh4%81fxr9t+mkLkfiV zgV#gD@X}v|O%Lyn&u3ix_p&H8#D6%2xC`zJZDccixGD35Pvkz_GKWus9`zAjgu;wI z4&_7$b0G@F_j0&(=5}@X6UZ&$>$TiMjWPgnQa97u14$g)&tPpsgGZyY%vxsx3>Ytr4V3zvavmyJY5+-AZaF_n8Edop#frbUD~#fk3-GMf>)+0^$DF(0a- zBOdEg$wtJxDp`xt!1&mPaQmD>WOqo(y2%mS&3sgFFP>5nXh{g#QW*-Qca)e>kHF}F zkyywT5vRyvMVu!_&S*&i3e1{D{Oz>fQYjR7T9iiOBJwIY=qd7P;Kx1Cc)QxfMdV2C z#kq*2o*HohMRP8U0;bh3k^b(iM8*&+k)*9iU0Wc-Sc%-|v<@356koI`O^lTU1lk4n zJBVP>HQo}EA2w@?-r$*vGR{oh=OLK zmVlLT#>yoVD^Y#97iT5v2C$OF7TM^1B9<&sBitE?nnVmlg@S>o>3Xt+a|WWKoYvuX zq4*Dr(n1VG!E8r8<`m|lhtE6EQLD@hY~fxS1BqbZ3LWSuoDOT`3l!q0LvVGF$ml>v zwG%T98Z&waI_fx>c@6v3P+p_nr4Xm+=R+-+Ue=?2BItKra(dLSuAELC=($)hjo#Y$B}JSuu~9|l8n z^(k<^!vTOTPV0y=q4+OIGdF`m@H(gAp#;9eU0R3rY6*8NQW9ET}m@r)ct#=i(5(1nNiZ4NcmtU9gE>y(NYYm-edJ+?Y2_ zVxYvud_{I9ri0iytIHD26C>sir*%}BPy(e`hoBug6m8X;cfoZC)?2m+)?prSS%P&q z+LXi5W*zaEU>%9}=g8j#>#YrfbrimDL&Yof@=%_WJK}$g|10g5?rJcrjE$@9!QqdX z6GSk*1&KE=d}|F2dUJzd}gFQNV&{ zVgz0hP!toSA zs%b)N;tY@gdP5R?CcK8=E_%F2V{k0;DI>k3rICfQ(ccKG44r#gx}k{0bgnnb{-d6oARJZyJL-DYX7|uAG_D37{InfvKMKq_tWuKHii& zQa7b;Nj(Pivk(@CttQ}uCP2hgFg_?NjhB_w0>Tu!#1kiR#HBXS6Xz@XGEa;07SOzq z`eEuxoG*w*ajI)TCiOD_S-#Z|XapXYnZUdCc9iSeF9}xPQE=#hju&T3x76OgIE(kB>1Hf0Lt?23Cc^*4m%v$TO+!wXat$9 z3SvQ}u!vvE9T_PZSut5@SaVOYx+y;(*7NxP1fQPiudyd0i|OwI1J5bO*afW3DU*@= zlB5_@+fz(`o->bSbYBDA$@FvS9Vi57uYmjXj`R+^(4P?>h5Q=?yqM85qZb0kz)$qd z=#|ln1#=I08a&5kY|e1tl-WWa(2?P|LclW!=*)O0a|VuVg3Tt3pJl?pvOj|~M%Y6$ z&Sd<6g7u;c=XIyex@61-Cm9KRxij^j*nKuwr${Z%+5_Zkso;hBW zGqGCW&TNbFt=y6ML}pqhj#^UZGxC|wW?s4y`OL!1qORmKt3m#GDf6hD+2pj2y;_Y? zjMGdR`S%DaWuBBXKhgc|ndd;hlRhoVcXCITUsgc&NKwcl8;LV^XJ?PRoILI)pP#k3 z3;E!zwYZ9Wla#el&e{NcneOE6SsA#)U6HbK<*XgLw>nQbGuc0@eh6Z|BxO0}tXA@J z6e_26y$QCgkL0X(2}~d<>$H@0QqCd)SU93W=i)=XS-%oc$`<9UzjSYVc0W>?? z2GBb$Wj`lpAJx6p`O3GG{j)!VnAzu~?C<34ugS|@%&k{RTf0kJ1v&dq-BU*`Z@q>< znwVQ}q7P~7NO|kcdPw`$dqin#puBaO4xxg5MzG%58*T#JGB^y@ja?#G#{~*jKVQh( z-9!0N?%1|@8+tp7Hh8KF+>1Q2HgAuhRC_7s5c2zNzxB_2n;Xt4Vvd(`Uhdf5ZM%1j zx)4C@z`TPO?NMIJ1^CR~zOcW#$OtZWQ?CP(68wJ&>Ym%G*^?~AHYWhC1`G8`0dQ|( znN0|9s);y}Erahv%X!%9ec7b$)udKD1RVk)pqAz3`b)L;da+fi|sEEjGA)WkE8aZB{>=r46yYG z-u{7Y`$=j0$G)To<-DGE@9P%2{m&f;NM=IU&A=TV>SSu&5WcK5dB=55>-gkJK09!o zG-5k;+>Y-C;V5`jj$v4~-jat;Boo*L@4?Xc6)vGfYH8v!oRUD_jY zE4REO9)0av7You3Z1QKEPW9ihbtJY_?kL+)4K@>)R%|vjE61s7s*8oCHS4PlHYJ%h~3R&XKc?LipwE)#L9?B+%VciMfQFGWecU z$NJ^G%Ka}xpoR9yX-#JF;?<={jht5{H-I|cSb3t3*P=|z`2_3O(sF(w2Be(d9XT+; zP)f9VH&nG#vh5ry?X)>|!fFA!45}JuQq@lXok3kxwG*vHH&yMlyQymDLZ+&n_iLi= zygy+l)>TcoiK%KQ=1xGzPlHYJ+liqyGdjo4rzwQr&TKt?b|Qf$tRvp}vz_T8b_UcvwLUV7(9q6tpM=q+~yY8OqpF0BPIM-jw9T%TF+G(9QjyO`;?e>(N z1$ahFxwGSQXOgF*P@U*Xf#BRdw%l4Nw?fJ-j?dkz2XN)-_}m5pa*OSk%QBFu{N=tH zpNmC{9Ia38I|;e3;_C?0N$x4h4d9l2P|f*aS)5ziNO>Odxqlnj@_HuZc{r{2^kCTX z`b%yAHw{lp&qG<9I8Mr&5T7?r#}J$sXv&NMxPrkvEub|B`8d#JIZm%bCoX>y1rwBiCi&z?#OH^yNYJ-W{)1Bfn)v(` zI&s31qmEa{PfE|vCZLpG5TF07?oA8z3b1x?1xH(OD|raYrAg@p_ps0ff$;^X1G#2{ z3*v1B1yVsqd_gk7y0D0QhYDJxg1Y#EO6IEx0rK$pN-Fp~zTji#fl^6PZ3P`W9lwy> zFFLJ`58mC=wtKL&yKnsNtKE?^YY61Kr%1ae#_#sK4EgRjY4^(b-Al~KK^5I^pWS8B z?)~w*6?2@O#L(_{rQL7D?|!*U99%0X#_vXRhf4=6)AkG(g7?g~?Ri+*vpjy!BHfE; zZQGtlpVejHsk!G>+nzJho)glZ_u}`wX-2QdIBQ6)CG4I*eASga1r!XDQVRTyTLN#2 zS1^Oc8SzmjO3K)H#g_n7cuWbaVB!%8tE`Au7VF-Wu*z4y>M9Lw2YCppFezQ_#zL!o z;?=A4(820Zn|hC=-WIP8CzvZ?ZR&k)+(M;ltfWT8tFu`^EsdE<)g(!k&ijj-(-7r*Z|z?_6dYh&#Dujtr^#V?aHg7^Jm+jl8`A8O9YPFG7qoRqeo zP-aN`uXXH4Gh}iGt5yjRB zHUKpxV$or_2rUi7K%+w{YH}1cP;h2a#|9TYKiF3Ewp8?*T!a=FN2_B(W#Civy;O8s zF8V_Eqv~8P`jvh90ef+Gx-pLM!9yyR(lY?e z*VQxWj?xPQOD`JfSQa9e1+p06R4R*hltoc+$_MJW;IgH-KJG!OEKV-N&^$-0V_gJu>eTN@~0f-FtiAbh;n%nUj5avfbW#cx3UjP$8s1s1VK7pk~c_7qMb%#mm8Wl{l%^Jr zt>T2vgw-5_ZPKC=^1)> zCebTq7udAb+JD z-h=>ujht*hj5`7j7tx1B^^!XdHynPeG8m{aJbSp&#nXobgt_i={)|E$Zy*QCJ1TD( zSUJkIQbFw|cT|Q}F0L%(YZNNO3~ZGv2+01}M5s^Y1FYi8p-yb&(=2O_q8@K0c27}r zzH*zSy}C8$Evf}HiYgnbu*!wjA5<2*XgCQ-TCBvVqo8S#ymc*l1XP}^{JrulQycS; zD=#>$0VANcDh%LPS$r)J%~6HHmVf|3y~bW8;VuVzl`m>hwY%I=HLWV5x;qR7R)<&l z8u>$r}YT2uv0@~23-BpTv9crs8^rada zObn|k6XhyY3p|RT{1seP2Nqi#RZRfCWta|R`YP-gTf<^Gsy-x7K^5&)r_lAcS9OZF zT2xW)sJ^PY5B56!0mUFFaqC%a;{am3dc+m7`BkCSlM&KXy$PY!Q~(_{MumqeI4`k@5+oZIbEr32O)g;L^vhF|0r)HO< zW+!>D%CV+cu0dBWFqRutcsDs}P#43S8vix_m1^FQYf#j|B5M*FLQoT}=6grYcPub? zlWH!?HR#(TB$@xQ!L^pbw%R^Y?NyFiZx#q(gFl%6+S{et5sq5a!k|V`$Qst(#XkKe z2iJxp`eLbezFdn+g=00MdrnHLeV9T@wVUPI$8>)n&2ZGFF%(p1)E3CK&yuGuUTuY= z_8{{n@oL|ZYM+;D+gNlio~tWP7Nqt^3Og#euA8my8mSIzijA=@xvnoo)2fQPA-t}s zL+32;VdZ>q-9%g6Y^lyJ)%nYH_fbf_2H^uha$STT9S!BW4N~1|xehH0S2#!AC@1F$0R>Gy~sRZA=RCf>pszO_|%S@)~t25|2br`4mu z1Z~#$lIwfw7;y3GB%k`FQvH0no+SYjf$F&WI0}s_zWz~L{bon~lk{n3t^V0Atkpj& z*JGH8i|13nC!rqcVsB=w)gO}F0B*hiNon=yZWC)S%JuC!hRKuC>%YcFqNDy>^1bh> zNofrj`wDz`SVMv+HDt;SDHJyAL*+Z8;7;;sD0DQSn+et_!!}gN4W$%H%did2gKZ5j zNDapv4M$m^E*ZArGpXT(qXG8DlwljruursC(i?uqYogR}$XHbZ$xJ~ zFp<%0yx!61!(vd89vj>^Y_P3yjMR8rd?RI@L}JBIBnnC6OsO#-zHz$lM};K5ky0a3 z1x>%k9Ct;>H|CI^Pvf%*^cFIhX}GaSas#+0zE9&RN8{&+_Ar?tsqrVdkxF$eYmTEG z)8r{N{_SY|lZ7C*sh~EIOb@Gm@b2%xf)e^b5t5pG<))D=HY-qMCYk~rO*2>kDw9of z<)&~7z{_NC(+XSDdZ}r(xokC|;xNiqlY^J7CRVOdwwm&7O;u7;InE7|n6{UOa(FW<57g>z4wajO$&bWiJ>KTEax)rv zfFKw7G(RCXKf=Bc&!;(AZbpL^evoyP>ZgvQ7GHCr++0A=th7KWD4}~x#ern6L1d&<>$t^e18_Q6sEi33fzGW>QiBtVs9!Bh^~#5=;KJcKBgrfd7EO;m{#f$ zbn77VksswFRI-`O!L9vlt)rw?o7_re$0P}35mu_zF11dVTPHJLjWA2A){Ro@2Dz2& z6))!C$kv)<@PeU_)&g5=t<-uzZdKip>tkB2??|n$$*spPM~(wzev@0zn~{Smna!gU zq@!cyqZkSTU5z0&0CRM?baat?bY7P@h_ORHn#G_zp8<>QC`N~PlUqLeGx?#d9o#0^ z+6GE(y`{FEa+?=HSxGWf&Di#wYnyEn9bs0=Z5Wc{Dg}Sj+L8pM zjZa&X)K)FG9Wuvd`fU5J-1d_igYYbKE^XEH3$rmSTZBa9K*>0e6&nH_7)+f(X!NI=qwWl zKgh?(81pRC-q+TCtJHp@jHQ!+xp3LqZ#PuHMgu4LwA-cj>2kYU?qP}5zENu5Ah)~a z9ta)Wo^NZfk=pmm?achRkn35d{cWlJRk{5?jI=pFw*Miu|0=gLW5cQ)Be8vO{>9xA ze(sd_kZz=v);yq>0IC_+G*C z8eVo0rmYk{-As|?H~?G8r;&-w)io&<2H$evq&io3Ymr_JhEFQOE8i?CxN<_S9t3 zoj=v~q&xq!gz_65rA6%_ci<$1>)~#NTaKv&1U=_)Z6wI`z!4`2=s2Y3{8*aFw-G#jh05S_k< zduenkL8t2iW3NzPI1cv)c!<-s2tjdU0D6}V69nMx6S&{uzJX6NI|ouA=3r5ydZHr? zD&mk^@Ou^bnSqKwY9@;cDP~;D`p4Je?IwcLL7HGgy@m@p<1Pn$?tsq_8h)T)_n3mQ z!=eG3>&tf@sBBxxjOD(x;eukqutW_JR8NcQP5PLz3$7IB1E9CcSIo}HHR)qUE%)O3 zn1OLUeZ?~GdGl={(8!FB;6A@hBQs9v8kzAeFnJ=-FH9p0?8`I}V1?8H{h*!z3<=D= zp54p~wFICkGIyaMaJd6~!9C7vu+AOFhF$P+C-c`N4w&U8alm|C;((QDi376W zRP6J|!Xv&$J0RO6aX>lu;t~f`T~T6BNF4Ac+y{_&ty>-l_(+#H;3NY40mp_y-Z4oW z=mCiXy&-X+#c7SU>JkT9@fD^^9C!;P4jcf`FiqmXk<4F{IB>czTgXnKLMfD>_OK|w zl8k{*!EMD}{61KlfwOJ#^|VRGz-P$|lF=XWg|RPW$-v#jRxyfAAVx@xZYP_N0IX8P zlmwoy!o4X7X+Idf9B~+dsk{Y#NI&`<1+6klMjT4^G4KM3{*%)hGe9?sh!#X8 zBoI}5%mA947{&6vMfr^c3K|C&0QV9qE9}Ql`VE|#x3Vvznc2Kewn^qVZfgn(j!UYN{BOFCw{b#d4jRZx|Tvaf>Mh;8&^QPSClGdmrjsn-|w&D=}Cf?Wi} zat>q3EB;ln%s!BRCM-wnT0J=+^2{LwwGq^u_pqWH+t+)+p}w7+0`@=#T+*3H zA;UR{%Mx-cjaBjmSP(5_213P0@D;iEoTtm;;`=@;k|bo!5bz)JDEJO}z-e93P3MWk z3Zb)aLgX&l5-XYj&E*+0qy_J-mu1WlY;R-+2|5dT53D407=#6aeFOKSTV@UUjWTP< zCFmgpV>S@m7aOvwXElQ@l<9tQ**#HJ!pv zqp+@AJ1c@hFHXb{8fpvb+;Z)#4U{uyJw{QWnOVscb_az`r?BSCnhqd}$bv0IsFY%% z$+cjMmRZU7McwyR^2O*Ve34lR@7IL)XJiiSy|*s7mUxK6$KP5Cg|pTpR2uKnH^yNoiG@yme8rphdL+v0P8cCQIgLEj`xd!Rb2Q<=C z4AL?qEsKowHX@zsMw%$@C5pL3QH@p3(nlqIT!AzOzOd0d48B_+QCJv58@2#w!y>z) z4O<6HVas*2AQYBB5KPqkn`mJ>AX-=+lpVH<=op!YGHY15NGPfa1yzY*D8*sa6oBAZ z?np5|GICHDx(O@?h5bm_z9($192E8kLeI7k>;J&Vl^Cp4%~U84MCvUH&CFA zdjDk#38}xZxuz zRC4QpkI+0$XbACULhQn4Q98+(%szol#V`=zx9}sy0WqJN7w%17#4i4ftq-Kc@Tb_;_Jn&L2{n^pH6LO)=Nj%sJ3H{!7uHYT+ksCQLt}RbKB?`2{T+Cl3J-mU z2R>(!hiQ)o2|8yXaWyAW9qq-MG@`GkN}aYj+nv^>p2>9H$eaUs?W=}B-*cMrirVKI z;(5+@aA-nCgkzfpu{`Ijsq%^N;6A*O5aA70^u4CU2Crcvh9VFWz`QUOsUI=im;=Md z9aPUmpi{B5k(v;g2Ls;`lQ3I{M*tX%KxSI{hF%CPYH#8$Vmn+Bwl%&5<*;435j)K6 zRdX+my*5(e6*dS{>y!Fa5g)*P3`TD-7DS5!0Qyw{Y zKL9UKsg8WrXRC1(;)IEe4az4`yEg)qY`<68x=?qB@k6qYs-#@7r#S* ztAIYLC!q&`77ycd0Qif#IT=4gfHv8vo!G|psEJ6|sPTyL7F zr0vJcZzM#^$rmGcECD^qnp6-|3&zJH{(YpojZu_Ax6J&*<+If@EryBAl#C!-ORa9fRnlL$St(( zcUcroLWAbq45xL)i$d|cyqh_9KeRGeC3IS+YcBYv06W>1<>weV)W6Ffv#5Qj6wEyf z_qS7+{|xds+p;;=b^QVMt$J`TUJ9a7NL^bt1^j7SHd!AG87F!O+_1|^LG*|&r6BrV zy%a>#F*(sOkSltQ)4DR2W!c#Kx)U-eBKncbia_+EdJ%|DLx4qYCJ-qd zGbL7%{eJ`93C&klwE$)$)DJ)5IGg$|T=3^3?^Pd>ON!I41vU z;@~iGp!*}=$Gk>f?+_1f5f83>&kg{Hp_5@^&@yl_L9K(Bv+hjH6E!C0T?5~FSeWTz zf(GjWqf$H%rPx3;Zz}kihf>Tnf>I1_=b;ocZs#p0UzB1uZs(;?a?C?fSk+HNa?C?B zjFN-eS@RAN)nW7^QloJmnmw!f5j(BqLFk->4z^OuLWVh=4!_rVxte#9`1}+Bb*;}k zO*k;z%aRgWhcxrO0Gkh?U1CzHn?I0B-F!;+E$ll|^uu>7ax2P@zMGeV#8MFQTS9)A zW};WZ36IsKGzR92!$v5;dRKt;ZUK<>=RXQGu?T2*Sk%5$*5?<(VMuJzP?U9cB*y%` zrW$YlQSQad`utaff3NZ8e*tXYTvpcSpXpN8=l`jf_1LRX)?;b>JGPJ0x(2l=gy&^F zb~J!@URKs)$LVD~HV6S`^0JN{sIgSgV~`?O=>|5E0CRt@#jO-e#dHZvhQIEVwEeKi(j)!6^D3 zRF^FnK;$XJZNRz!qiHT#sFW<2Mof|aY@lC2dNE`m^HifeYdh zX|-lp7Es$@0on$PdCjmaKu3==QANHLW+r%*w*ZX*&c@fo#ur`KSl9!aTnJkb=XIZm zBDQc4FJcSFg8stMCi)8}g2KYPT=c>J!We?V9JoZMBDL@lDq;)KD_XOf>d}QT_zPcv zt3x?SHVC5jvo%URIpASFIcC<3f5^u1*`w}f^~W%T$^B> zF&j=5tN|WyTLf$1U4k`o1KdY~HR_CDo%^w1jYhbbY{5Ejv0#nu4)>{GT`~f0Gu%6Z zb!n1dT?V`>M+(+8*9q2j55t`l1Yv-ODv`8HdcgH^3hPu)bt7z*;5u1=ED9AzZJ+p6 zUTS}evFaB%EGK-FZ>ocSR{cRu!%bf5_2hs5)o|BY)W;0}`>!Q`!Are?`45BtXp8!| z%iov$8U=6F(i%B z5C(@)xIee2x}J^20?|+gEdjKury8Q8AIPB31NvHjbrW#l;0F4`e#AZNSs-zgmpX`r z`V67Y_E$ImuTVF$P|(o*7yBoiVBApT!31926RuB8LSICN4BEcvQP?Lrn!J}F$BJ{Pc0Bnou~mn_4J`h-h-WW^;LDaEw?{`h=`R7O3*B^eZ0+w+f4noU8E5O4d* zV?Eg_(-uor;(bCaoOB z;lxn#Ug4X(N4*i*V(A7-40$`f(h03oHnBry)tg!P1YgoMi?Nl(ptuFT>K1Ivx{cne zebuM%PG?52L{JB^crW>q_F24-jCfe@%)(N<4h@G9ZxEEa>>65pkLM7u35J&4N(>2{ zmt`+AUd93ZK6JY5eW$SEHI@Ygp8PmejpCm4rL==;meD-%va?JD+5jm5{$aYp2q|&5 ze1NWp<>T~mC=gygQy&k5GL-jJ4|Oo%UXFXSG<7Urr;D}xahE!lRd-0S@}Dav{HhzYgkLp8 z7h~1!Jh>snDjIPz$}tjtRS+fos?99nSB3M0UxhWoFb@CE3BPJ3_*n%5g3_f9))Icz z16NA;RoSM5Uv+@#fF=AOO88aJQ^K!$i_pDdPWV;t8VNth(nEyd5}eizz43My}H&7lkheqf!^l!5L8;{vE(h(+eVwM-ot{y86#hz5W(80y4$C>$EJxS-61X@i8vaO!c zCB5jJt<`jF-RdPK&GFevbp&H-BRrGfR7_NSz_@zU%oUoNdj6N+j= z{HX&i>PUv|0DSA=J^=7(hONkq&B?vou^ngFj+@fSqK;zNK0)x4P9d%l*pR;wjha@g zf8rn)7B(fk8tVj|!WwUq7BvqldX-Jt;(JYB`nj4HNwz1RmNv1AUe??)5MHB7`tot5 zHGwP;mh=G{L-}?MEh}0>HJ4!`*3ji8ux+$BkUSruACyt8vV(@!Y{7bd4C<}PCa+yA zvInxnnuBrlL(w-0nB0LCUDM1`hQhr`KQGhI3!K%3baVjCO!Eq0%~wD~2x!n|3MwX| z^t(6`h~xSI9@mG#>9lVkj`P(K$4vvyxCwd=z#NH6heXFkLA*E;FK(XZ=WgKR9_RGp zsKo$z)tjjR#o_uf{L?jqx6ewg+r3B+k^B&ovo!`+<5 zOX(L!)n?o&_wCat6idIgpR@E^`x{~Yjls3_Th~uVylyyft{b4G5zRQU^jmi?#9J3kep9ZP ze(M%-dh6)W#VMP3@~wNCl5brGMN2YkWgU|XJDC@t-?6b&us(V(Tsqtd!TNZfV0|(g zDb~$Hy@S$r-D$WVoWh1~p6WC1eFCH1ibkZDI+j8|FcWTe46O(@b$`(49mjmpY=2;7 z3@xvA_w{4G|AFu8F|=aX-FH0meILH3`_uX^-jdEiTX{0`=?x!p_keAfjR#OB*gHBf zNXrLq1o*O(i1eNr9V3D;!;~K=G|uF}$2g~T(?l5ayBYTHox*wxTt7_wu%Xlket?#B zYrft}UZ6mKZXLe$y~t*)@8wI%P{&%-350Haf4H%5(|`{58shDGGr9@n#j$lkcP~SC zuP@&tV^JqEbg(_^m%%+E3XVdCj*ja!xLZSBS46jtpc*}+^&W=q3516V*5`ve z8S%&ruTLd_hJ-R0RSoNLq!0c2Qi7=CE$So|Uj?iNnZ=V`t%#38GdGw=Cm;3)IF6!1 zi2sN;6S(Ja)j=4sqe)ip8Lr0D$A`Yu02r<&ki}Sknm}Lp>Pr!64bX5kk$F+;bv+JW z#PqXn+J-0m2l;!`Mz|LQ>*l_2=wEN%Cs?=K1rCtEr^pu*zDelFYU_@Zj*$FbsmF<1 z3`5a_db{kXcmzgPTTWbiA%oGA{UNod@QxBPk*FQOg$i<-d@=EsM8CvIqDOuxLW-V= zlM*Kxk#w9EbtVE%!%2bh7?OJchuZlYx=Nf&KpIj=L?P|EybZzV?79bWcHNUw;)A~V zq3Se#!F=LVPV1IG1Y9t$h5&g=Vqp?;KW*?!Om!hIAt1>cPg8@Cmw3~JMeRuSWn$;R z#J^1&{AS4)lLjS?NxGlS`6UfDkR?qZ7;&036;FLZ5N9!ImS{_wD<#chEYg^aoPo=DFkr1tdM>F0SaEfHQjH7iaRM@|uj8qmaw@Q19sdRLQ$YTmlyr(Cr~P4#UPXH{&TCJeDka~| zDY8r9iE45Xs5S{Dg%;IczL*@AycGA^vW0WWvt3m0PksU<=#RG~ljB4w`4K5Oj$var zz^mbi{#0^C@(*bE;Rg6**Q&eZX9-AaYm#^4>8=qmxk?c98{i?DerBXb=moI-x|I9^ zBgC(JPsWVOGfU|f;N)-c_9(7y(eEVcu%nq(5x{WewWe{e9(38 zfTvtf@2)GCNk)L#uV_yR6m2Q9rIbL>wcJh?GLesvTHO0vbsKUwcY9NYzRy2>Evm}E^bfl0kqGt zrNPtXi>cS7-kdraseT#!~!UY}~(YPdyLy z{2`^D=R%z!t*2gcS{*0ovUN33zL?f4ZBUvYUwoN%je$PxmNY+&MV?pFMu<|{7%6Q8 z=ZzmtHJ!_%R2{epCEjd(fYNst}| zB8#N-D6W}}jKE3|I6$|dtHB`faC&08g2cpa=;@ER2xO!ynnE;8*`k!5E2U>MOzi4& zbsnPcPp{5EJB+SAPe0&_-bz49%=G8*?2?%2AN)&Vrhf;PFG%U%ahBOV=js1At%?4W zm>HPsNQ}lk=jwd!^562S+r#YNg0zl z4R)z{2BvrtophEyUF2g&wLm(HcOcgGaAN4 zko~zZV1nO(}m|O0hvC|;pv`9&54=iCEBvCma@DUYG8prvigD1Z|OR4b*X$Y z>n5Dy*$Pf^9eCCNgTnve>pS41DBAz`a^WCc6iZlraZRLXL^Ohe*nrSU&;SBbLKjg1 z^~H*>ZTD`=?X^e}0%?0WNuih!I-%w44O9@Yfdy2GVxfo>;s1SR_X_I&clm5~_nDbz zo|$>(ndfmD&G?z!}-E8Tst}Ei`{U&jO$a*`4Xm%UQ%(L z<(x0yg=;ja;abT#U6r!M2Itf|;UWq$l8ou%DffHs&kD*~25)5a$5ix~_RaKkI@6b`u!Z5p?H_vj z^aMTK)a2Vcj2Yr7xr2PC+>i8hXviI7)dj7*AECi7_8kT1FdjjI!SW>eC3ax995=M& zDe_B*3x<{-#Qj2jRel_L`m?GE1pu8>T4v zafEXS#t@>$<408iMkg{f7kPa6Yv93GUX}QtDTDwod(0_oE`|WM~i_)$yq=)jy&2 z!kYM#OUlvi<+Tww&(#>vtE)CXLz|UwmaFEDp7N|=os;iveAnhMoI)Cc_w={Aj5?~5jXTaj}VY$_&Dwt4iO$DG2g%i`IaHy zMZBlX%$FUj?7@Q1fK&3U#x0$WR5qSQzRgh8+kioEn6f7lt5(l$0#dblh-EAx!yVtN{>D>1j~TU%&u}vyJt(v0U^l0#Yve zt?^v+L6l4ML}S1yD}5YP>}k9{j%8&YO03UD9)~3TN!(!aeeN(cWF_hI^poaM!@4V; z)qMRVFo7NQg%=b8?5NlA`Z9|h_0<{r+X?Kb@3jsV)_>sjud&xZl=$dIHlqG>#2FmL zIP_WMeAb)lh1Nlb3G4XcA*w20K|pFkZ@YNT-s=G~du6=$Aq{xOdj}NIe!TY%v#5Er zE3Y>XIejE~$KduQoe^xz6;FAmL3!Q|p26wB-Us3tiUedCs<>asGv12-f4=p|cP;O& zH+hB~{Of%?;wu7Xb;IZy@ec;=#MQzF|;7 z$MU{m45N7w`V#S`DnTVl?_h0y3#*%0UXM z`P5;&02JT*PC(AE^Im;F#0c|q1f;IuZ-Kidul<+c*^<}P3;b6?$8690uQZ#8o#*Pm z2^1ce{M{qYc^uAibr>&-r~JMAdHw)$83m2AcRZJI1f=5oC*yu0Yp@KSLaKAZF9CC*e^KCKV8-dF{-QYM4n)CSfCTY)+p5E`h9}#unuyr}pn*R@=O_S-;BP5#(-iBwZ8G?iVmThnf0;30g24}Mb#0tUZY(mh*2cI)Zk&?M&G3bjpi|&$w zg}4oN1sC8p(j7z>DVomJ4sjSR5Y`xcJ$M2bRS*_;!Uo?XAcrm$B;oYWgFkbFdy(Id zd~mOspGv(i_zO_)qys(;H&CB0a27y8r=vZCXJTb8XhT3kUCqt+tQ&VZ;@)e~j zxX~sQ^xz9_WVx7!cNW|kaTec9M|T>sc&cD{bEgNnj+aB!xB<%uTMX=ONnVZ{ z)SsZkSb$76%OA<-nN1_d-J$YMf-%Cs0bXWQ4~O zWah;6Om!Cl*$>54zk-?bJ+FSnD%3P{YQJ$9 z+V}{Edt4Ks?O)4l0z-$CkSJQWh;v~Vu10Yf72;{_PHm{Bfhu?pwYV!-8%scjbqZm< zK=;sQ0_&5!Hq#^$Ykh!K0#=Eu8SgNH!0OkQd0w$`(sp1awcO+>ZI$O0V56Ve960ls zS%scQGCYr))g^65TU3gtJ@Y-ao;@6!Sn!Y{WuoxZ6Oah=tiqj~yRptSf$7Pf_o0&S z;63j%>M$<>>O5aYoTcr!n)wc+0I0w7{Groc3^chAH(x#H^h=2}{LI?ZZSX+1=5?Ei z>Bn05_FfTB>%87YzlTjO=<(%E`fd6>X5wh-JCM2`uQMe!FuQi2!orK;!0R<8{l{zfI}8KKoAmA8_aL;%gT5hFv-%za{(ra}^{vD7;iNeU^-W3t zjrqMb8Qx`PYr2AH&5(H7yUqKRuLIKWfWjR2|3Qlekc5o)P+Z7(f5UTNtp5f-9vZ4KevGc9Px@$el*x}ik$?=ViaY6D zF@8j(`zrs^<4v_GXnV*#xcNHB%Thq1EBzB%cMTg_~Jf1D1tP6(9dFMRB3Kt z3ADzQd|-)L&3$T6KhF7kIA;ll;1UewCGdhS5O6(=>ut`tum!GsTq|%L=bWX(aA6oP z{g88(wZWB#3u(%;a6x@2-_1EIa&cAQ`WBhg};+l*h_rV~L}<9mY~5m?%Fc z&tnclc~U(79D-33$WNgO;*QQ-8OxbujhA1dN?XhvhBCC!%41yJbq-@05SGYw^0(&T zx*(3Qo?r|iMz4R^9rC-t`Ux+;%dnaQ>t_+CF@USfbQrGz>kslDN=GpKWO#^wjH5kA zKtijaE)(fgoNySX@rsjSL^AXtA_kNSjZKre4C;C zXm!bZ!OY9WGinM}GhjGnV|42nHZ_BQ>_=ntwHTwbc=cLVPIHW|!*}hCNPnj~lzgBh zder!6s*WHa6;K_A`vsqc=c?0z?onQy&d`~by!uqc8Ty#3!#>6Kc@B3a}

    *F#(A#%pX2dNIT&+ED8iaaJwk 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

    WV(@LR93hu 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Ν2lnlQ6brmzklD>> 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 iDbP(w)9wR5O| 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 ljxJ{0I#Xh*~O`@BYP(gzyp+nYup)bU08cb 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

    B5n^;>h-yfq!ny_` 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%0Dylr{<9%^1VGZ6L75#+<8%?snvRL{Mh{yR<4 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ⓈS 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%0AR=^GFisr9@asZ0`n<3!((H&97CT7nK(Y_Lx~v3 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 Dllcer literal 0 HcmV?d00001 diff --git a/.dart_tool/pub/bin/sdk-version b/.dart_tool/pub/bin/sdk-version new file mode 100644 index 000000000..860487ca1 --- /dev/null +++ b/.dart_tool/pub/bin/sdk-version @@ -0,0 +1 @@ +2.7.1 diff --git a/.packages b/.packages new file mode 100644 index 000000000..2eb435347 --- /dev/null +++ b/.packages @@ -0,0 +1,29 @@ +# Generated by pub on 2020-02-12 11:39:05.309375. +args:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/args-1.5.2/lib/ +charcode:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/charcode-1.1.3/lib/ +collection:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/collection-1.14.12/lib/ +csv:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/csv-4.0.3/lib/ +dshell:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/dshell-1.6.1/lib/ +equatable:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/equatable-1.1.0/lib/ +file:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/file-5.1.0/lib/ +file_utils:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/file_utils-0.1.4/lib/ +globbing:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/globbing-0.3.0/lib/ +intl:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/intl-0.16.1/lib/ +io:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/io-0.3.3/lib/ +logger:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/logger-0.8.3/lib/ +matcher:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.6/lib/ +meta:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/meta-1.1.8/lib/ +money2:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/money2-1.3.0/lib/ +path:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/ +pub_semver:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/pub_semver-1.4.3/lib/ +pubspec:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/pubspec-0.1.4/lib/ +quiver:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/quiver-2.1.2+1/lib/ +recase:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/recase-3.0.0/lib/ +source_span:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/source_span-1.6.0/lib/ +stack_trace:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/ +string_scanner:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.5/lib/ +term_glyph:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.1.0/lib/ +uri:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/uri-0.11.3+1/lib/ +utf:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/utf-0.9.0+5/lib/ +yaml:file:///home/rsutton/.pub-cache/hosted/pub.dartlang.org/yaml-2.2.0/lib/ +asterisk_java_installer:lib/ diff --git a/pom.xml b/pom.xml index dc84ea5b7..4c26b49c2 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 2.0.4-SNAPSHOT + 2.1.0 UTF-8 diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 000000000..4dce678ba --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,194 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + args: + dependency: "direct main" + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.2" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.3" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.14.12" + csv: + dependency: transitive + description: + name: csv + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.3" + dshell: + dependency: "direct main" + description: + name: dshell + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.1" + equatable: + dependency: transitive + description: + name: equatable + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0" + file_utils: + dependency: transitive + description: + name: file_utils + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" + globbing: + dependency: transitive + description: + name: globbing + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.3" + logger: + dependency: transitive + description: + name: logger + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.3" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.6" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.8" + money2: + dependency: transitive + description: + name: money2 + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + path: + dependency: "direct main" + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.4" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.3" + pubspec: + dependency: transitive + description: + name: pubspec + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2+1" + recase: + dependency: transitive + description: + name: recase + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.3" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + uri: + dependency: transitive + description: + name: uri + url: "https://pub.dartlang.org" + source: hosted + version: "0.11.3+1" + utf: + dependency: transitive + description: + name: utf + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.0+5" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" +sdks: + dart: ">=2.7.0 <3.0.0" diff --git a/triggerRelease.dart b/triggerRelease.dart old mode 100644 new mode 100755 From 16b1999559d65c2ca64783ccdc8c9573fa9285bd Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 11:44:08 +1100 Subject: [PATCH 313/802] add workflow --- .github/workflows/nexus.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/nexus.yml diff --git a/.github/workflows/nexus.yml b/.github/workflows/nexus.yml new file mode 100644 index 000000000..3cd1e8344 --- /dev/null +++ b/.github/workflows/nexus.yml @@ -0,0 +1,28 @@ +name: Release + +# Run workflow on tags +on: + push: + tags: + - '*' + +jobs: + release: + runs-on: ubuntu-18.04 + steps: + - name: Check out Git repository + uses: actions/checkout@v2 + + - name: Install Java and Maven + uses: actions/setup-java@v1 + with: + java-version: 1.8 + + - name: Release Maven package + uses: samuelmeuli/action-maven-publish@v1 + with: + gpg_private_key: ${{ secrets.gpg_private_key }} + gpg_passphrase: ${{ secrets.gpg_passphrase }} + nexus_username: ${{ secrets.nexus_username }} + nexus_password: ${{ secrets.nexus_password }} + From ec68ecf95511b9127adf0e1fdcd5fb0d5f4e1d6a Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 11:44:22 +1100 Subject: [PATCH 314/802] for version 2.2.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4c26b49c2..6215f50d3 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 2.1.0 + 2.2.0 UTF-8 From d5f24890af1f9658235c8826551105088e40da16 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 12:00:52 +1100 Subject: [PATCH 315/802] update repo info --- README.md | 50 ++++---------------------------------------------- 1 file changed, 4 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index db61ef3e5..43a6a0dff 100644 --- a/README.md +++ b/README.md @@ -44,65 +44,23 @@ Asterisk-Java is available from [here](https://github.com/asterisk-java/asterisk Maven Dependency ---------------- -Asterisk-Java 2.0.4 - - - - asterisk-java-mvn-repo - https://raw.githubusercontent.com/asterisk-java/asterisk-java/mvn-repo - - true - - - true - - - +Asterisk-Java 3.0.19 org.asteriskjava asterisk-java - 2.0.4 + 3.0.19 -Asterisk-Java 2.0.3 - - - - asterisk-java-mvn-repo - https://raw.githubusercontent.com/asterisk-java/asterisk-java/mvn-repo - - true - - - true - - - +Asterisk-Java 2.2.0 org.asteriskjava asterisk-java - 2.0.3 + 2.2.0 -Asterisk-Java 2.0 - - - org.asteriskjava - asterisk-java - 2.0.2 - - -Asterisk-Java 1.0 - - - org.asteriskjava - asterisk-java - 1.0.0-final - - INSTALLATION FROM SOURCE ------------------------ From 8d2a517b179ed8ce5fda4e062314eb3f7f7b0eec Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 12:04:00 +1100 Subject: [PATCH 316/802] update version info --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 43a6a0dff..51d5db15e 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Asterisk-Java is available from [here](https://github.com/asterisk-java/asterisk Maven Dependency ---------------- -Asterisk-Java 3.0.19 +Asterisk-Java 3.0.19 (Java 1.8 and Asterisk Version 10 thru 16) org.asteriskjava @@ -52,7 +52,7 @@ Asterisk-Java 3.0.19 3.0.19 -Asterisk-Java 2.2.0 +Asterisk-Java 2.2.0 (Java 1.7 and Asterisk < Version 10) org.asteriskjava From 44aee1b44afbb1e4dc518ad8ea32126291318c32 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 12:05:44 +1100 Subject: [PATCH 317/802] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 51d5db15e..7ff4fdacb 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Asterisk-Java is available from [here](https://github.com/asterisk-java/asterisk Maven Dependency ---------------- -Asterisk-Java 3.0.19 (Java 1.8 and Asterisk Version 10 thru 16) +Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 16) (master) org.asteriskjava @@ -52,7 +52,7 @@ Asterisk-Java 3.0.19 (Java 1.8 and Asterisk Version 10 thru 16) 3.0.19 -Asterisk-Java 2.2.0 (Java 1.7 and Asterisk < Version 10) +Asterisk-Java 2.x (Java 1.7 and Asterisk < Version 10) (branch 2.0.4) org.asteriskjava From c90f24935134444ad648d63637edbf28a75ec82c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 12:07:44 +1100 Subject: [PATCH 318/802] update readme --- .gitignore | 2 ++ README.md | 30 +++++------------------------- 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 647fe6c60..aee1dd39d 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ classes build/ /.settings/ /.metadata/ +/.packages +/.dart_tool/ diff --git a/README.md b/README.md index b048bbf07..7ff4fdacb 100644 --- a/README.md +++ b/README.md @@ -43,44 +43,24 @@ Asterisk-Java is available from [here](https://github.com/asterisk-java/asterisk Maven Dependency ---------------- -Asterisk-Java 2.0.3 - - - - asterisk-java-mvn-repo - https://raw.githubusercontent.com/asterisk-java/asterisk-java/mvn-repo - - true - - - true - - - - - org.asteriskjava - asterisk-java - 2.0.3 - - - -Asterisk-Java 2.0 +Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 16) (master) org.asteriskjava asterisk-java - 2.0.2 + 3.0.19 -Asterisk-Java 1.0 +Asterisk-Java 2.x (Java 1.7 and Asterisk < Version 10) (branch 2.0.4) org.asteriskjava asterisk-java - 1.0.0-final + 2.2.0 + INSTALLATION FROM SOURCE ------------------------ From 0492fa2c94fcc9ced2165caea86a5fb04304abe2 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 12 Feb 2020 13:49:56 +1100 Subject: [PATCH 319/802] fixing build --- pom.xml | 7 ++++--- settings.xml | 5 ----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index b0f3390d9..c703ea677 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.0.20-SNAPSHOT + 3.0.20-SNAPSHOT UTF-8 @@ -86,7 +86,7 @@ https://oss.sonatype.org/service/local/staging/deploy/maven2 - + @@ -130,8 +130,9 @@ + org.apache.maven.plugins maven-surefire-plugin - 2.18 + 3.0.0-M4 maven-assembly-plugin diff --git a/settings.xml b/settings.xml index 17620bd4c..7480a1434 100644 --- a/settings.xml +++ b/settings.xml @@ -21,11 +21,6 @@ true - - github - GitHub OWNER Apache Maven Packages - https://maven.pkg.github.com/asterisk-java/asterisk-java - From 34a6289300d90b5063ed3d19789ef2e8db016733 Mon Sep 17 00:00:00 2001 From: Marcelo Bernardes Pinto Date: Sun, 16 Feb 2020 03:41:19 -0300 Subject: [PATCH 320/802] - Removed the incall attribute in specialized class, because alread exist in super class. (#322) --- .../manager/event/QueueMemberStatusEvent.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java index 4619cd2b6..12c35b67e 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java @@ -31,7 +31,6 @@ public class QueueMemberStatusEvent extends QueueMemberEvent private String ringinuse; private String iface; - private Integer incall; /** * @param source @@ -66,16 +65,4 @@ public void setRinginuse(String ringinuse) { this.ringinuse = ringinuse; } - - public Integer getIncall() - { - return incall; - } - - public void setIncall(Integer incall) - { - this.incall = incall; - } - - } From 3ad4869ceb24a19da843f0ba1d8b947e6e5919f4 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 17 Feb 2020 15:04:22 +1100 Subject: [PATCH 321/802] for version 3.0.21-SNAPSHOT --- .dart_tool/pub/bin/.gitignore | 1 - .dart_tool/pub/bin/dshell/.gitignore | 3 --- pom.xml | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 .dart_tool/pub/bin/.gitignore delete mode 100644 .dart_tool/pub/bin/dshell/.gitignore diff --git a/.dart_tool/pub/bin/.gitignore b/.dart_tool/pub/bin/.gitignore deleted file mode 100644 index 35623abbf..000000000 --- a/.dart_tool/pub/bin/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/sdk-version diff --git a/.dart_tool/pub/bin/dshell/.gitignore b/.dart_tool/pub/bin/dshell/.gitignore deleted file mode 100644 index b650a938e..000000000 --- a/.dart_tool/pub/bin/dshell/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/dshell.dart.snapshot.dart2 -/dshell_complete.dart.snapshot.dart2 -/dshell_install.dart.snapshot.dart2 diff --git a/pom.xml b/pom.xml index c703ea677..441014b33 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.0.20-SNAPSHOT + 3.0.21-SNAPSHOT UTF-8 From 0f0d33c0cea30dd649fa2d65e816fbc3af7c8139 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 17 Feb 2020 15:10:58 +1100 Subject: [PATCH 322/802] for version 3.0.22-SNAPSHOT --- pom.xml | 2 +- pubspec.lock | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 pubspec.lock diff --git a/pom.xml b/pom.xml index 56c4af1af..4567e9419 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.0.21-SNAPSHOT + 3.0.22-SNAPSHOT UTF-8 diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 000000000..4d600c6ee --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,229 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + args: + dependency: "direct main" + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.2" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.3" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.14.12" + csv: + dependency: transitive + description: + name: csv + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.3" + dshell: + dependency: "direct main" + description: + name: dshell + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.2" + equatable: + dependency: transitive + description: + name: equatable + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0" + file_utils: + dependency: transitive + description: + name: file_utils + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" + globbing: + dependency: transitive + description: + name: globbing + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.3" + logger: + dependency: transitive + description: + name: logger + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.3" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.6" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.8" + mockito: + dependency: transitive + description: + name: mockito + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.1" + money2: + dependency: transitive + description: + name: money2 + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + path: + dependency: "direct main" + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.4" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.3" + pubspec: + dependency: transitive + description: + name: pubspec + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2+1" + recase: + dependency: transitive + description: + name: recase + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.3" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.14" + uri: + dependency: transitive + description: + name: uri + url: "https://pub.dartlang.org" + source: hosted + version: "0.11.3+1" + utf: + dependency: transitive + description: + name: utf + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.0+5" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" +sdks: + dart: ">=2.7.0 <3.0.0" From b075718d1f5797a36f81ee927ff4fabab5f667c2 Mon Sep 17 00:00:00 2001 From: Stefan Erichsen Date: Mon, 24 Feb 2020 10:41:59 +0100 Subject: [PATCH 323/802] added missing events for Asterisk 16.6.2 --- .../manager/AbstractManagerEventListener.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 4cde7dcc6..73131349a 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -14,7 +14,11 @@ import org.asteriskjava.manager.event.AgentsEvent; import org.asteriskjava.manager.event.AlarmClearEvent; import org.asteriskjava.manager.event.AlarmEvent; +import org.asteriskjava.manager.event.BridgeCreateEvent; +import org.asteriskjava.manager.event.BridgeDestroyEvent; +import org.asteriskjava.manager.event.BridgeEnterEvent; import org.asteriskjava.manager.event.BridgeEvent; +import org.asteriskjava.manager.event.BridgeLeaveEvent; import org.asteriskjava.manager.event.CdrEvent; import org.asteriskjava.manager.event.ChanSpyStartEvent; import org.asteriskjava.manager.event.ChanSpyStopEvent; @@ -25,7 +29,9 @@ import org.asteriskjava.manager.event.DahdiShowChannelsCompleteEvent; import org.asteriskjava.manager.event.DahdiShowChannelsEvent; import org.asteriskjava.manager.event.DbGetResponseEvent; +import org.asteriskjava.manager.event.DeviceStateChangeEvent; import org.asteriskjava.manager.event.DialEvent; +import org.asteriskjava.manager.event.DialStateEvent; import org.asteriskjava.manager.event.DisconnectEvent; import org.asteriskjava.manager.event.DndStateEvent; import org.asteriskjava.manager.event.DongleCENDEvent; @@ -52,6 +58,7 @@ import org.asteriskjava.manager.event.MessageWaitingEvent; import org.asteriskjava.manager.event.NewCallerIdEvent; import org.asteriskjava.manager.event.NewChannelEvent; +import org.asteriskjava.manager.event.NewConnectedLineEvent; import org.asteriskjava.manager.event.NewExtenEvent; import org.asteriskjava.manager.event.NewStateEvent; import org.asteriskjava.manager.event.OriginateResponseEvent; @@ -77,12 +84,15 @@ import org.asteriskjava.manager.event.RegistryEvent; import org.asteriskjava.manager.event.ReloadEvent; import org.asteriskjava.manager.event.RenameEvent; +import org.asteriskjava.manager.event.RtcpReceivedEvent; +import org.asteriskjava.manager.event.RtcpSentEvent; import org.asteriskjava.manager.event.ShutdownEvent; import org.asteriskjava.manager.event.SoftHangupRequestEvent; import org.asteriskjava.manager.event.StatusCompleteEvent; import org.asteriskjava.manager.event.StatusEvent; import org.asteriskjava.manager.event.UnparkedCallEvent; import org.asteriskjava.manager.event.UserEvent; +import org.asteriskjava.manager.event.VarSetEvent; import org.asteriskjava.manager.event.ZapShowChannelsCompleteEvent; import org.asteriskjava.manager.event.ZapShowChannelsEvent; import org.asteriskjava.util.Log; @@ -476,6 +486,46 @@ protected void handleEvent(CoreShowChannelsCompleteEvent event) { } + protected void handleEvent(DialStateEvent event) + { + } + + protected void handleEvent(VarSetEvent event) + { + } + + protected void handleEvent(DeviceStateChangeEvent event) + { + } + + protected void handleEvent(NewConnectedLineEvent event) + { + } + + protected void handleEvent(BridgeCreateEvent event) + { + } + + protected void handleEvent(BridgeEnterEvent event) + { + } + + protected void handleEvent(BridgeDestroyEvent event) + { + } + + protected void handleEvent(BridgeLeaveEvent event) + { + } + + protected void handleEvent(RtcpSentEvent event) + { + } + + protected void handleEvent(RtcpReceivedEvent event) + { + } + /** * Dispatches to the appropriate handleEvent(...) method. * From 544f00f37ffda84dfc26896f7821f1f8ad7ccc86 Mon Sep 17 00:00:00 2001 From: Stefan Erichsen Date: Mon, 24 Feb 2020 11:13:13 +0100 Subject: [PATCH 324/802] added missing events for Asterisk 16.6.2 --- .../manager/AbstractManagerEventListener.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 73131349a..bc4a0b56d 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -14,6 +14,7 @@ import org.asteriskjava.manager.event.AgentsEvent; import org.asteriskjava.manager.event.AlarmClearEvent; import org.asteriskjava.manager.event.AlarmEvent; +import org.asteriskjava.manager.event.BlindTransferEvent; import org.asteriskjava.manager.event.BridgeCreateEvent; import org.asteriskjava.manager.event.BridgeDestroyEvent; import org.asteriskjava.manager.event.BridgeEnterEvent; @@ -30,6 +31,8 @@ import org.asteriskjava.manager.event.DahdiShowChannelsEvent; import org.asteriskjava.manager.event.DbGetResponseEvent; import org.asteriskjava.manager.event.DeviceStateChangeEvent; +import org.asteriskjava.manager.event.DialBeginEvent; +import org.asteriskjava.manager.event.DialEndEvent; import org.asteriskjava.manager.event.DialEvent; import org.asteriskjava.manager.event.DialStateEvent; import org.asteriskjava.manager.event.DisconnectEvent; @@ -56,6 +59,8 @@ import org.asteriskjava.manager.event.MeetMeMuteEvent; import org.asteriskjava.manager.event.MeetMeTalkingEvent; import org.asteriskjava.manager.event.MessageWaitingEvent; +import org.asteriskjava.manager.event.MusicOnHoldStartEvent; +import org.asteriskjava.manager.event.MusicOnHoldStopEvent; import org.asteriskjava.manager.event.NewCallerIdEvent; import org.asteriskjava.manager.event.NewChannelEvent; import org.asteriskjava.manager.event.NewConnectedLineEvent; @@ -90,6 +95,7 @@ import org.asteriskjava.manager.event.SoftHangupRequestEvent; import org.asteriskjava.manager.event.StatusCompleteEvent; import org.asteriskjava.manager.event.StatusEvent; +import org.asteriskjava.manager.event.UnholdEvent; import org.asteriskjava.manager.event.UnparkedCallEvent; import org.asteriskjava.manager.event.UserEvent; import org.asteriskjava.manager.event.VarSetEvent; @@ -210,10 +216,34 @@ protected void handleEvent(SoftHangupRequestEvent event) { } - protected void handleEvent(DialEvent event) + protected void handleEvent(MusicOnHoldStartEvent event) + { + } + + protected void handleEvent(MusicOnHoldStopEvent event) + { + } + + protected void handleEvent(UnholdEvent event) + { + } + + protected void handleEvent(BlindTransferEvent event) + { + } + + protected void handleEvent(DialEvent event) + { + } + + protected void handleEvent(DialBeginEvent event) { } + protected void handleEvent(DialEndEvent event) + { + } + protected void handleEvent(HangupRequestEvent event) { } From 0fa77f867830f9497585b7ff571e641fbd7777a2 Mon Sep 17 00:00:00 2001 From: Stefan Erichsen Date: Mon, 24 Feb 2020 11:14:16 +0100 Subject: [PATCH 325/802] made AbstractManagerEventListener work again --- .../manager/AbstractManagerEventListener.java | 202 +++++++++--------- .../AbstractManagerEventListenerTest.java | 4 +- 2 files changed, 103 insertions(+), 103 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index bc4a0b56d..87a4bf774 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -142,8 +142,8 @@ * // and finally log off and disconnect * managerConnection.logoff(); * } - * - * protected void handleEvent(StatusEvent event) + * + * public void handleEvent(StatusEvent event) * { * System.out.println(event.getChannel() + ":" + event.getState()); * } @@ -164,395 +164,395 @@ public abstract class AbstractManagerEventListener implements ManagerEventListen { Log logger = LogFactory.getLog(AbstractManagerEventListener.class); - protected void handleEvent(AgentCallbackLoginEvent event) + public void handleEvent(AgentCallbackLoginEvent event) { } - protected void handleEvent(AgentCallbackLogoffEvent event) + public void handleEvent(AgentCallbackLogoffEvent event) { } - protected void handleEvent(AgentCalledEvent event) + public void handleEvent(AgentCalledEvent event) { } - protected void handleEvent(AgentLoginEvent event) + public void handleEvent(AgentLoginEvent event) { } - protected void handleEvent(AgentLogoffEvent event) + public void handleEvent(AgentLogoffEvent event) { } - protected void handleEvent(AlarmClearEvent event) + public void handleEvent(AlarmClearEvent event) { } - protected void handleEvent(AlarmEvent event) + public void handleEvent(AlarmEvent event) { } - protected void handleEvent(CdrEvent event) + public void handleEvent(CdrEvent event) { } - protected void handleEvent(ChanSpyStartEvent event) + public void handleEvent(ChanSpyStartEvent event) { } - protected void handleEvent(ChanSpyStopEvent event) + public void handleEvent(ChanSpyStopEvent event) { } - protected void handleEvent(ConnectEvent event) + public void handleEvent(ConnectEvent event) { } - protected void handleEvent(DAHDIChannelEvent event) + public void handleEvent(DAHDIChannelEvent event) { } - protected void handleEvent(SoftHangupRequestEvent event) + public void handleEvent(SoftHangupRequestEvent event) { } - protected void handleEvent(MusicOnHoldStartEvent event) + public void handleEvent(MusicOnHoldStartEvent event) { } - protected void handleEvent(MusicOnHoldStopEvent event) + public void handleEvent(MusicOnHoldStopEvent event) { } - protected void handleEvent(UnholdEvent event) + public void handleEvent(UnholdEvent event) { } - protected void handleEvent(BlindTransferEvent event) + public void handleEvent(BlindTransferEvent event) { } - protected void handleEvent(DialEvent event) + public void handleEvent(DialEvent event) { } - protected void handleEvent(DialBeginEvent event) + public void handleEvent(DialBeginEvent event) { } - protected void handleEvent(DialEndEvent event) + public void handleEvent(DialEndEvent event) { } - protected void handleEvent(HangupRequestEvent event) + public void handleEvent(HangupRequestEvent event) { } - protected void handleEvent(DisconnectEvent event) + public void handleEvent(DisconnectEvent event) { } - protected void handleEvent(DndStateEvent event) + public void handleEvent(DndStateEvent event) { } - protected void handleEvent(ExtensionStatusEvent event) + public void handleEvent(ExtensionStatusEvent event) { } - protected void handleEvent(HoldedCallEvent event) + public void handleEvent(HoldedCallEvent event) { } - protected void handleEvent(HoldEvent event) + public void handleEvent(HoldEvent event) { } - protected void handleEvent(LogChannelEvent event) + public void handleEvent(LogChannelEvent event) { } - protected void handleEvent(MessageWaitingEvent event) + public void handleEvent(MessageWaitingEvent event) { } - protected void handleEvent(NewExtenEvent event) + public void handleEvent(NewExtenEvent event) { } - protected void handleEvent(PeerStatusEvent event) + public void handleEvent(PeerStatusEvent event) { } - protected void handleEvent(ProtocolIdentifierReceivedEvent event) + public void handleEvent(ProtocolIdentifierReceivedEvent event) { } - protected void handleEvent(QueueEvent event) + public void handleEvent(QueueEvent event) { } - protected void handleEvent(RegistryEntryEvent event) + public void handleEvent(RegistryEntryEvent event) { } - protected void handleEvent(RegistryEvent event) + public void handleEvent(RegistryEvent event) { } - protected void handleEvent(ReloadEvent event) + public void handleEvent(ReloadEvent event) { } - protected void handleEvent(RenameEvent event) + public void handleEvent(RenameEvent event) { } - protected void handleEvent(ShutdownEvent event) + public void handleEvent(ShutdownEvent event) { } - protected void handleEvent(UserEvent event) + public void handleEvent(UserEvent event) { } - protected void handleEvent(AgentCompleteEvent event) + public void handleEvent(AgentCompleteEvent event) { } - protected void handleEvent(AgentConnectEvent event) + public void handleEvent(AgentConnectEvent event) { } - protected void handleEvent(AgentDumpEvent event) + public void handleEvent(AgentDumpEvent event) { } - protected void handleEvent(FaxReceivedEvent event) + public void handleEvent(FaxReceivedEvent event) { } - protected void handleEvent(NewCallerIdEvent event) + public void handleEvent(NewCallerIdEvent event) { } - protected void handleEvent(HangupEvent event) + public void handleEvent(HangupEvent event) { } - protected void handleEvent(NewChannelEvent event) + public void handleEvent(NewChannelEvent event) { } - protected void handleEvent(NewStateEvent event) + public void handleEvent(NewStateEvent event) { } - protected void handleEvent(MeetMeJoinEvent event) + public void handleEvent(MeetMeJoinEvent event) { } - protected void handleEvent(MeetMeLeaveEvent event) + public void handleEvent(MeetMeLeaveEvent event) { } - protected void handleEvent(MeetMeMuteEvent event) + public void handleEvent(MeetMeMuteEvent event) { } - protected void handleEvent(MeetMeTalkingEvent event) + public void handleEvent(MeetMeTalkingEvent event) { } - protected void handleEvent(ParkedCallGiveUpEvent event) + public void handleEvent(ParkedCallGiveUpEvent event) { } - protected void handleEvent(ParkedCallTimeOutEvent event) + public void handleEvent(ParkedCallTimeOutEvent event) { } - protected void handleEvent(UnparkedCallEvent event) + public void handleEvent(UnparkedCallEvent event) { } - protected void handleEvent(QueueMemberAddedEvent event) + public void handleEvent(QueueMemberAddedEvent event) { } - protected void handleEvent(QueueMemberPausedEvent event) + public void handleEvent(QueueMemberPausedEvent event) { } - protected void handleEvent(QueueMemberRemovedEvent event) + public void handleEvent(QueueMemberRemovedEvent event) { } - protected void handleEvent(AgentsCompleteEvent event) + public void handleEvent(AgentsCompleteEvent event) { } - protected void handleEvent(AgentsEvent event) + public void handleEvent(AgentsEvent event) { } - protected void handleEvent(DbGetResponseEvent event) + public void handleEvent(DbGetResponseEvent event) { } - protected void handleEvent(DongleNewSMSBase64Event event) + public void handleEvent(DongleNewSMSBase64Event event) { } - protected void handleEvent(DongleStatusEvent event) + public void handleEvent(DongleStatusEvent event) { } - protected void handleEvent(DongleCENDEvent event) + public void handleEvent(DongleCENDEvent event) { } - protected void handleEvent(DongleCallStateChangeEvent event) + public void handleEvent(DongleCallStateChangeEvent event) { } - protected void handleEvent(DongleNewSMSEvent event) + public void handleEvent(DongleNewSMSEvent event) { } - protected void handleEvent(DongleNewCMGREvent event) + public void handleEvent(DongleNewCMGREvent event) { } - protected void handleEvent(DongleDeviceEntryEvent event) + public void handleEvent(DongleDeviceEntryEvent event) { } - protected void handleEvent(JoinEvent event) + public void handleEvent(JoinEvent event) { } - protected void handleEvent(LeaveEvent event) + public void handleEvent(LeaveEvent event) { } - protected void handleEvent(BridgeEvent event) + public void handleEvent(BridgeEvent event) { } - protected void handleEvent(OriginateResponseEvent event) + public void handleEvent(OriginateResponseEvent event) { } - protected void handleEvent(ParkedCallEvent event) + public void handleEvent(ParkedCallEvent event) { } - protected void handleEvent(ParkedCallsCompleteEvent event) + public void handleEvent(ParkedCallsCompleteEvent event) { } - protected void handleEvent(PeerEntryEvent event) + public void handleEvent(PeerEntryEvent event) { } - protected void handleEvent(PeerlistCompleteEvent event) + public void handleEvent(PeerlistCompleteEvent event) { } - protected void handleEvent(QueueEntryEvent event) + public void handleEvent(QueueEntryEvent event) { } - protected void handleEvent(QueueMemberEvent event) + public void handleEvent(QueueMemberEvent event) { } - protected void handleEvent(QueueMemberStatusEvent event) + public void handleEvent(QueueMemberStatusEvent event) { } - protected void handleEvent(QueueParamsEvent event) + public void handleEvent(QueueParamsEvent event) { } - protected void handleEvent(QueueStatusCompleteEvent event) + public void handleEvent(QueueStatusCompleteEvent event) { } - protected void handleEvent(RegistrationsCompleteEvent event) + public void handleEvent(RegistrationsCompleteEvent event) { } - protected void handleEvent(StatusCompleteEvent event) + public void handleEvent(StatusCompleteEvent event) { } - protected void handleEvent(StatusEvent event) + public void handleEvent(StatusEvent event) { } - protected void handleEvent(ZapShowChannelsCompleteEvent event) + public void handleEvent(ZapShowChannelsCompleteEvent event) { } - protected void handleEvent(DahdiShowChannelsCompleteEvent event) + public void handleEvent(DahdiShowChannelsCompleteEvent event) { } - protected void handleEvent(ZapShowChannelsEvent event) + public void handleEvent(ZapShowChannelsEvent event) { } - protected void handleEvent(DahdiShowChannelsEvent event) + public void handleEvent(DahdiShowChannelsEvent event) { } - protected void handleEvent(CoreShowChannelEvent event) + public void handleEvent(CoreShowChannelEvent event) { } - protected void handleEvent(CoreShowChannelsCompleteEvent event) + public void handleEvent(CoreShowChannelsCompleteEvent event) { } - protected void handleEvent(DialStateEvent event) + public void handleEvent(DialStateEvent event) { } - protected void handleEvent(VarSetEvent event) + public void handleEvent(VarSetEvent event) { } - protected void handleEvent(DeviceStateChangeEvent event) + public void handleEvent(DeviceStateChangeEvent event) { } - protected void handleEvent(NewConnectedLineEvent event) + public void handleEvent(NewConnectedLineEvent event) { } - protected void handleEvent(BridgeCreateEvent event) + public void handleEvent(BridgeCreateEvent event) { } - protected void handleEvent(BridgeEnterEvent event) + public void handleEvent(BridgeEnterEvent event) { } - protected void handleEvent(BridgeDestroyEvent event) + public void handleEvent(BridgeDestroyEvent event) { } - protected void handleEvent(BridgeLeaveEvent event) + public void handleEvent(BridgeLeaveEvent event) { } - protected void handleEvent(RtcpSentEvent event) + public void handleEvent(RtcpSentEvent event) { } - protected void handleEvent(RtcpReceivedEvent event) + public void handleEvent(RtcpReceivedEvent event) { } @@ -570,7 +570,7 @@ public void onManagerEvent(ManagerEvent event) try { - Method method = this.getClass().getDeclaredMethod("handleEvent", new Class[]{event.getClass()}); + Method method = this.getClass().getMethod("handleEvent", new Class[]{event.getClass()}); if (method != null) { method.invoke(this, event); diff --git a/src/test/java/org/asteriskjava/manager/AbstractManagerEventListenerTest.java b/src/test/java/org/asteriskjava/manager/AbstractManagerEventListenerTest.java index 9a3d72f07..6050bd106 100644 --- a/src/test/java/org/asteriskjava/manager/AbstractManagerEventListenerTest.java +++ b/src/test/java/org/asteriskjava/manager/AbstractManagerEventListenerTest.java @@ -37,12 +37,12 @@ private static class EventListener extends AbstractManagerEventListener { public boolean leaveEventHandled; @Override - protected void handleEvent(JoinEvent event) { + public void handleEvent(JoinEvent event) { this.joinEventHandled = true; } @Override - protected void handleEvent(LeaveEvent event) { + public void handleEvent(LeaveEvent event) { this.leaveEventHandled = true; } } From 8bf2bfd82a2723ec25ed0f78c937be80304fcb07 Mon Sep 17 00:00:00 2001 From: Stefan Erichsen Date: Mon, 24 Feb 2020 11:15:23 +0100 Subject: [PATCH 326/802] formatting --- .../manager/AbstractManagerEventListener.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 87a4bf774..f672986f9 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -113,32 +113,32 @@ * Kindly donated by Steve Prior. *

    * Example based on HelloEvents from the tutorial: - * + * *

      * public class HelloEvents extends AbstractManagerEventListener
      * {
      *     private ManagerConnection managerConnection;
    - * 
    + *
      *     public HelloEvents(String machine, String userid, String password) throws IOException
      *     {
      *         ManagerConnectionFactory factory = new ManagerConnectionFactory(machine, userid, password);
      *         this.managerConnection = factory.createManagerConnection();
      *     }
    - * 
    + *
      *     public void run() throws Exception
      *     {
      *         // register for events
      *         managerConnection.addEventListener(this);
    - * 
    + *
      *         // connect to Asterisk and log in
      *         managerConnection.login();
    - * 
    + *
      *         // request channel state
      *         managerConnection.sendAction(new StatusAction());
    - * 
    + *
      *         // wait 10 seconds for events to come in
      *         Thread.sleep(10000);
    - * 
    + *
      *         // and finally log off and disconnect
      *         managerConnection.logoff();
      *     }
    @@ -147,7 +147,7 @@
      *     {
      *         System.out.println(event.getChannel() + ":" + event.getState());
      *     }
    - * 
    + *
      *     public static void main(String[] args) throws Exception
      *     {
      *         HelloEvents helloEvents;
    @@ -156,7 +156,7 @@
      *     }
      * }
      * 
    - * + * * @author srt * @since 0.3 */ @@ -558,7 +558,7 @@ public void handleEvent(RtcpReceivedEvent event) /** * Dispatches to the appropriate handleEvent(...) method. - * + * * @param event the event to handle */ @Override From 02f28a56fe6c10c005a1f7af3cfb8bfd89705057 Mon Sep 17 00:00:00 2001 From: Stefan Erichsen Date: Mon, 24 Feb 2020 11:58:46 +0100 Subject: [PATCH 327/802] actually added methods for *all* events --- .../manager/AbstractManagerEventListener.java | 640 ++++++++++++++---- 1 file changed, 510 insertions(+), 130 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index f672986f9..3542ea02d 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -10,20 +10,44 @@ import org.asteriskjava.manager.event.AgentDumpEvent; import org.asteriskjava.manager.event.AgentLoginEvent; import org.asteriskjava.manager.event.AgentLogoffEvent; +import org.asteriskjava.manager.event.AgentRingNoAnswerEvent; import org.asteriskjava.manager.event.AgentsCompleteEvent; import org.asteriskjava.manager.event.AgentsEvent; +import org.asteriskjava.manager.event.AgiExecEndEvent; +import org.asteriskjava.manager.event.AgiExecEvent; +import org.asteriskjava.manager.event.AgiExecStartEvent; import org.asteriskjava.manager.event.AlarmClearEvent; import org.asteriskjava.manager.event.AlarmEvent; +import org.asteriskjava.manager.event.AntennaLevelEvent; +import org.asteriskjava.manager.event.AsyncAgiEvent; +import org.asteriskjava.manager.event.AttendedTransferEvent; import org.asteriskjava.manager.event.BlindTransferEvent; import org.asteriskjava.manager.event.BridgeCreateEvent; import org.asteriskjava.manager.event.BridgeDestroyEvent; import org.asteriskjava.manager.event.BridgeEnterEvent; import org.asteriskjava.manager.event.BridgeEvent; +import org.asteriskjava.manager.event.BridgeExecEvent; import org.asteriskjava.manager.event.BridgeLeaveEvent; +import org.asteriskjava.manager.event.BridgeMergeEvent; import org.asteriskjava.manager.event.CdrEvent; +import org.asteriskjava.manager.event.CelEvent; +import org.asteriskjava.manager.event.ChallengeResponseFailedEvent; +import org.asteriskjava.manager.event.ChallengeSentEvent; import org.asteriskjava.manager.event.ChanSpyStartEvent; import org.asteriskjava.manager.event.ChanSpyStopEvent; +import org.asteriskjava.manager.event.ChannelReloadEvent; +import org.asteriskjava.manager.event.ChannelUpdateEvent; +import org.asteriskjava.manager.event.ConfbridgeEndEvent; +import org.asteriskjava.manager.event.ConfbridgeJoinEvent; +import org.asteriskjava.manager.event.ConfbridgeLeaveEvent; +import org.asteriskjava.manager.event.ConfbridgeListCompleteEvent; +import org.asteriskjava.manager.event.ConfbridgeListEvent; +import org.asteriskjava.manager.event.ConfbridgeListRoomsCompleteEvent; +import org.asteriskjava.manager.event.ConfbridgeListRoomsEvent; +import org.asteriskjava.manager.event.ConfbridgeStartEvent; +import org.asteriskjava.manager.event.ConfbridgeTalkingEvent; import org.asteriskjava.manager.event.ConnectEvent; +import org.asteriskjava.manager.event.ContactStatusEvent; import org.asteriskjava.manager.event.CoreShowChannelEvent; import org.asteriskjava.manager.event.CoreShowChannelsCompleteEvent; import org.asteriskjava.manager.event.DAHDIChannelEvent; @@ -43,24 +67,49 @@ import org.asteriskjava.manager.event.DongleNewCMGREvent; import org.asteriskjava.manager.event.DongleNewSMSBase64Event; import org.asteriskjava.manager.event.DongleNewSMSEvent; +import org.asteriskjava.manager.event.DongleShowDevicesCompleteEvent; import org.asteriskjava.manager.event.DongleStatusEvent; +import org.asteriskjava.manager.event.DtmfBeginEvent; +import org.asteriskjava.manager.event.DtmfEndEvent; +import org.asteriskjava.manager.event.DtmfEvent; +import org.asteriskjava.manager.event.EndpointList; +import org.asteriskjava.manager.event.EndpointListComplete; import org.asteriskjava.manager.event.ExtensionStatusEvent; +import org.asteriskjava.manager.event.FaxDocumentStatusEvent; import org.asteriskjava.manager.event.FaxReceivedEvent; +import org.asteriskjava.manager.event.FaxStatusEvent; +import org.asteriskjava.manager.event.FullyBootedEvent; import org.asteriskjava.manager.event.HangupEvent; import org.asteriskjava.manager.event.HangupRequestEvent; import org.asteriskjava.manager.event.HoldEvent; import org.asteriskjava.manager.event.HoldedCallEvent; +import org.asteriskjava.manager.event.InvalidPasswordEvent; +import org.asteriskjava.manager.event.JabberEventEvent; +import org.asteriskjava.manager.event.JitterBufStatsEvent; import org.asteriskjava.manager.event.JoinEvent; import org.asteriskjava.manager.event.LeaveEvent; +import org.asteriskjava.manager.event.LinkEvent; +import org.asteriskjava.manager.event.ListDialplanEvent; +import org.asteriskjava.manager.event.LocalBridgeEvent; +import org.asteriskjava.manager.event.LocalOptimizationBeginEvent; +import org.asteriskjava.manager.event.LocalOptimizationEndEvent; import org.asteriskjava.manager.event.LogChannelEvent; import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.MasqueradeEvent; +import org.asteriskjava.manager.event.MeetMeEndEvent; import org.asteriskjava.manager.event.MeetMeJoinEvent; import org.asteriskjava.manager.event.MeetMeLeaveEvent; import org.asteriskjava.manager.event.MeetMeMuteEvent; import org.asteriskjava.manager.event.MeetMeTalkingEvent; +import org.asteriskjava.manager.event.MeetMeTalkingRequestEvent; import org.asteriskjava.manager.event.MessageWaitingEvent; +import org.asteriskjava.manager.event.ModuleLoadReportEvent; +import org.asteriskjava.manager.event.MonitorStartEvent; +import org.asteriskjava.manager.event.MonitorStopEvent; +import org.asteriskjava.manager.event.MusicOnHoldEvent; import org.asteriskjava.manager.event.MusicOnHoldStartEvent; import org.asteriskjava.manager.event.MusicOnHoldStopEvent; +import org.asteriskjava.manager.event.NewAccountCodeEvent; import org.asteriskjava.manager.event.NewCallerIdEvent; import org.asteriskjava.manager.event.NewChannelEvent; import org.asteriskjava.manager.event.NewConnectedLineEvent; @@ -68,37 +117,64 @@ import org.asteriskjava.manager.event.NewStateEvent; import org.asteriskjava.manager.event.OriginateResponseEvent; import org.asteriskjava.manager.event.ParkedCallEvent; -import org.asteriskjava.manager.event.ParkedCallGiveUpEvent; -import org.asteriskjava.manager.event.ParkedCallTimeOutEvent; import org.asteriskjava.manager.event.ParkedCallsCompleteEvent; +import org.asteriskjava.manager.event.PausedEvent; import org.asteriskjava.manager.event.PeerEntryEvent; import org.asteriskjava.manager.event.PeerStatusEvent; import org.asteriskjava.manager.event.PeerlistCompleteEvent; +import org.asteriskjava.manager.event.PeersEvent; +import org.asteriskjava.manager.event.PickupEvent; +import org.asteriskjava.manager.event.PriEventEvent; import org.asteriskjava.manager.event.ProtocolIdentifierReceivedEvent; +import org.asteriskjava.manager.event.QueueCallerAbandonEvent; +import org.asteriskjava.manager.event.QueueCallerJoinEvent; +import org.asteriskjava.manager.event.QueueCallerLeaveEvent; import org.asteriskjava.manager.event.QueueEntryEvent; import org.asteriskjava.manager.event.QueueEvent; import org.asteriskjava.manager.event.QueueMemberAddedEvent; import org.asteriskjava.manager.event.QueueMemberEvent; import org.asteriskjava.manager.event.QueueMemberPausedEvent; +import org.asteriskjava.manager.event.QueueMemberPenaltyEvent; import org.asteriskjava.manager.event.QueueMemberRemovedEvent; -import org.asteriskjava.manager.event.QueueMemberStatusEvent; import org.asteriskjava.manager.event.QueueParamsEvent; import org.asteriskjava.manager.event.QueueStatusCompleteEvent; +import org.asteriskjava.manager.event.QueueSummaryCompleteEvent; +import org.asteriskjava.manager.event.QueueSummaryEvent; +import org.asteriskjava.manager.event.ReceiveFaxEvent; import org.asteriskjava.manager.event.RegistrationsCompleteEvent; import org.asteriskjava.manager.event.RegistryEntryEvent; import org.asteriskjava.manager.event.RegistryEvent; import org.asteriskjava.manager.event.ReloadEvent; import org.asteriskjava.manager.event.RenameEvent; +import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.manager.event.RtcpReceivedEvent; import org.asteriskjava.manager.event.RtcpSentEvent; +import org.asteriskjava.manager.event.RtpReceiverStatEvent; +import org.asteriskjava.manager.event.RtpSenderStatEvent; +import org.asteriskjava.manager.event.SendFaxEvent; +import org.asteriskjava.manager.event.SendFaxStatusEvent; +import org.asteriskjava.manager.event.ShowDialplanCompleteEvent; import org.asteriskjava.manager.event.ShutdownEvent; +import org.asteriskjava.manager.event.SkypeAccountStatusEvent; +import org.asteriskjava.manager.event.SkypeBuddyEntryEvent; +import org.asteriskjava.manager.event.SkypeBuddyListCompleteEvent; +import org.asteriskjava.manager.event.SkypeBuddyStatusEvent; +import org.asteriskjava.manager.event.SkypeChatMessageEvent; +import org.asteriskjava.manager.event.SkypeLicenseEvent; +import org.asteriskjava.manager.event.SkypeLicenseListCompleteEvent; import org.asteriskjava.manager.event.SoftHangupRequestEvent; import org.asteriskjava.manager.event.StatusCompleteEvent; import org.asteriskjava.manager.event.StatusEvent; +import org.asteriskjava.manager.event.SuccessfulAuthEvent; +import org.asteriskjava.manager.event.T38FaxStatusEvent; +import org.asteriskjava.manager.event.TransferEvent; import org.asteriskjava.manager.event.UnholdEvent; -import org.asteriskjava.manager.event.UnparkedCallEvent; +import org.asteriskjava.manager.event.UnlinkEvent; +import org.asteriskjava.manager.event.UnpausedEvent; import org.asteriskjava.manager.event.UserEvent; import org.asteriskjava.manager.event.VarSetEvent; +import org.asteriskjava.manager.event.VoicemailUserEntryCompleteEvent; +import org.asteriskjava.manager.event.VoicemailUserEntryEvent; import org.asteriskjava.manager.event.ZapShowChannelsCompleteEvent; import org.asteriskjava.manager.event.ZapShowChannelsEvent; import org.asteriskjava.util.Log; @@ -164,397 +240,701 @@ public abstract class AbstractManagerEventListener implements ManagerEventListen { Log logger = LogFactory.getLog(AbstractManagerEventListener.class); - public void handleEvent(AgentCallbackLoginEvent event) + public void handleEvent(AgentCompleteEvent event) { } - public void handleEvent(AgentCallbackLogoffEvent event) + public void handleEvent(AgentConnectEvent event) { } - public void handleEvent(AgentCalledEvent event) + public void handleEvent(AgentDumpEvent event) { } - public void handleEvent(AgentLoginEvent event) + public void handleEvent(AgentRingNoAnswerEvent event) { } - public void handleEvent(AgentLogoffEvent event) + public void handleEvent(AttendedTransferEvent event) { } - public void handleEvent(AlarmClearEvent event) + public void handleEvent(BlindTransferEvent event) { } - public void handleEvent(AlarmEvent event) + public void handleEvent(BridgeCreateEvent event) + { + } + + public void handleEvent(BridgeDestroyEvent event) + { + } + + public void handleEvent(BridgeEnterEvent event) + { + } + + public void handleEvent(BridgeLeaveEvent event) + { + } + + public void handleEvent(HangupEvent event) + { + } + + public void handleEvent(NewChannelEvent event) + { + } + + public void handleEvent(NewStateEvent event) + { + } + + public void handleEvent(ConfbridgeEndEvent event) + { + } + + public void handleEvent(ConfbridgeJoinEvent event) + { + } + + public void handleEvent(ConfbridgeLeaveEvent event) + { + } + + public void handleEvent(ConfbridgeStartEvent event) + { + } + + public void handleEvent(ConfbridgeTalkingEvent event) + { + } + + public void handleEvent(AntennaLevelEvent event) + { + } + + public void handleEvent(HangupRequestEvent event) + { + } + + public void handleEvent(NewCallerIdEvent event) { } - public void handleEvent(CdrEvent event) + public void handleEvent(SoftHangupRequestEvent event) { } - public void handleEvent(ChanSpyStartEvent event) + public void handleEvent(FaxDocumentStatusEvent event) { } - public void handleEvent(ChanSpyStopEvent event) + public void handleEvent(FaxReceivedEvent event) { } - public void handleEvent(ConnectEvent event) + public void handleEvent(FaxStatusEvent event) { } - public void handleEvent(DAHDIChannelEvent event) + public void handleEvent(SendFaxEvent event) { } - public void handleEvent(SoftHangupRequestEvent event) + public void handleEvent(SendFaxStatusEvent event) { } - public void handleEvent(MusicOnHoldStartEvent event) - { - } + public void handleEvent(T38FaxStatusEvent event) + { + } - public void handleEvent(MusicOnHoldStopEvent event) - { - } + public void handleEvent(HoldEvent event) + { + } public void handleEvent(UnholdEvent event) - { - } + { + } + + public void handleEvent(MeetMeJoinEvent event) + { + } + + public void handleEvent(MeetMeLeaveEvent event) + { + } + + public void handleEvent(MeetMeMuteEvent event) + { + } + + public void handleEvent(MeetMeTalkingEvent event) + { + } + + public void handleEvent(MeetMeTalkingRequestEvent event) + { + } + + public void handleEvent(MonitorStartEvent event) + { + } + + public void handleEvent(MonitorStopEvent event) + { + } + + public void handleEvent(ParkedCallEvent event) + { + } + + public void handleEvent(QueueMemberAddedEvent event) + { + } + + public void handleEvent(QueueMemberPausedEvent event) + { + } + + public void handleEvent(QueueMemberRemovedEvent event) + { + } + + public void handleEvent(RtcpReceivedEvent event) + { + } + + public void handleEvent(RtcpSentEvent event) + { + } + + public void handleEvent(RtpReceiverStatEvent event) + { + } + + public void handleEvent(RtpSenderStatEvent event) + { + } + + public void handleEvent(AgentCallbackLoginEvent event) + { + } + + public void handleEvent(AgentCallbackLogoffEvent event) + { + } + + public void handleEvent(AgentCalledEvent event) + { + } + + public void handleEvent(AgentLoginEvent event) + { + } + + public void handleEvent(AgentLogoffEvent event) + { + } + + public void handleEvent(AgiExecEvent event) + { + } + + public void handleEvent(AgiExecEndEvent event) + { + } + + public void handleEvent(AgiExecStartEvent event) + { + } + + public void handleEvent(AlarmClearEvent event) + { + } + + public void handleEvent(AlarmEvent event) + { + } + + public void handleEvent(BridgeEvent event) + { + } + + public void handleEvent(LinkEvent event) + { + } + + public void handleEvent(UnlinkEvent event) + { + } + + public void handleEvent(BridgeExecEvent event) + { + } + + public void handleEvent(BridgeMergeEvent event) + { + } + + public void handleEvent(CdrEvent event) + { + } + + public void handleEvent(CelEvent event) + { + } + + public void handleEvent(ChallengeResponseFailedEvent event) + { + } + + public void handleEvent(ChallengeSentEvent event) + { + } + + public void handleEvent(ChannelReloadEvent event) + { + } + + public void handleEvent(ChannelUpdateEvent event) + { + } + + public void handleEvent(ChanSpyStartEvent event) + { + } + + public void handleEvent(ChanSpyStopEvent event) + { + } + + public void handleEvent(ConnectEvent event) + { + } + + public void handleEvent(ContactStatusEvent event) + { + } + + public void handleEvent(DAHDIChannelEvent event) + { + } - public void handleEvent(BlindTransferEvent event) - { - } + public void handleEvent(DeviceStateChangeEvent event) + { + } public void handleEvent(DialEvent event) - { - } + { + } public void handleEvent(DialBeginEvent event) { } public void handleEvent(DialEndEvent event) - { - } + { + } - public void handleEvent(HangupRequestEvent event) + public void handleEvent(DialStateEvent event) { } - public void handleEvent(DisconnectEvent event) + public void handleEvent(DisconnectEvent event) { } - public void handleEvent(DndStateEvent event) + public void handleEvent(DndStateEvent event) { } - public void handleEvent(ExtensionStatusEvent event) + public void handleEvent(DongleCallStateChangeEvent event) { } - public void handleEvent(HoldedCallEvent event) + public void handleEvent(DongleCENDEvent event) { } - public void handleEvent(HoldEvent event) + public void handleEvent(DongleNewCMGREvent event) { } - public void handleEvent(LogChannelEvent event) + public void handleEvent(DongleNewSMSBase64Event event) { } - public void handleEvent(MessageWaitingEvent event) + public void handleEvent(DongleNewSMSEvent event) { } - public void handleEvent(NewExtenEvent event) + public void handleEvent(DongleStatusEvent event) { } - public void handleEvent(PeerStatusEvent event) + public void handleEvent(DtmfEvent event) { } - public void handleEvent(ProtocolIdentifierReceivedEvent event) + public void handleEvent(DtmfBeginEvent event) { } - public void handleEvent(QueueEvent event) + public void handleEvent(DtmfEndEvent event) { } - public void handleEvent(RegistryEntryEvent event) + public void handleEvent(ExtensionStatusEvent event) { } - public void handleEvent(RegistryEvent event) + public void handleEvent(FullyBootedEvent event) { } - public void handleEvent(ReloadEvent event) + public void handleEvent(HoldedCallEvent event) { } - public void handleEvent(RenameEvent event) + public void handleEvent(InvalidPasswordEvent event) { } - public void handleEvent(ShutdownEvent event) + public void handleEvent(JabberEventEvent event) { } - public void handleEvent(UserEvent event) + public void handleEvent(JitterBufStatsEvent event) { } - public void handleEvent(AgentCompleteEvent event) + public void handleEvent(LocalBridgeEvent event) { } - public void handleEvent(AgentConnectEvent event) + public void handleEvent(LocalOptimizationBeginEvent event) { } - public void handleEvent(AgentDumpEvent event) + public void handleEvent(LocalOptimizationEndEvent event) { } - public void handleEvent(FaxReceivedEvent event) + public void handleEvent(LogChannelEvent event) { } - public void handleEvent(NewCallerIdEvent event) + public void handleEvent(MasqueradeEvent event) { } - public void handleEvent(HangupEvent event) + public void handleEvent(MeetMeEndEvent event) { } - public void handleEvent(NewChannelEvent event) + public void handleEvent(MessageWaitingEvent event) { } - public void handleEvent(NewStateEvent event) + public void handleEvent(ModuleLoadReportEvent event) { } - public void handleEvent(MeetMeJoinEvent event) + public void handleEvent(MusicOnHoldEvent event) { } - public void handleEvent(MeetMeLeaveEvent event) + public void handleEvent(MusicOnHoldStartEvent event) { } - public void handleEvent(MeetMeMuteEvent event) + public void handleEvent(MusicOnHoldStopEvent event) { } - public void handleEvent(MeetMeTalkingEvent event) + public void handleEvent(NewAccountCodeEvent event) { } - public void handleEvent(ParkedCallGiveUpEvent event) + public void handleEvent(NewConnectedLineEvent event) { } - public void handleEvent(ParkedCallTimeOutEvent event) + public void handleEvent(NewExtenEvent event) { } - public void handleEvent(UnparkedCallEvent event) + public void handleEvent(PeerStatusEvent event) { } - public void handleEvent(QueueMemberAddedEvent event) + public void handleEvent(PickupEvent event) { } - public void handleEvent(QueueMemberPausedEvent event) + public void handleEvent(PriEventEvent event) { } - public void handleEvent(QueueMemberRemovedEvent event) + public void handleEvent(ProtocolIdentifierReceivedEvent event) { } - public void handleEvent(AgentsCompleteEvent event) + public void handleEvent(QueueEvent event) { } - public void handleEvent(AgentsEvent event) + public void handleEvent(JoinEvent event) { } - public void handleEvent(DbGetResponseEvent event) + public void handleEvent(LeaveEvent event) { } - public void handleEvent(DongleNewSMSBase64Event event) + public void handleEvent(QueueCallerAbandonEvent event) { } - public void handleEvent(DongleStatusEvent event) + public void handleEvent(QueueCallerJoinEvent event) { } - public void handleEvent(DongleCENDEvent event) + public void handleEvent(QueueCallerLeaveEvent event) { } - public void handleEvent(DongleCallStateChangeEvent event) + public void handleEvent(QueueMemberPenaltyEvent event) { } - public void handleEvent(DongleNewSMSEvent event) + public void handleEvent(ReceiveFaxEvent event) { } - public void handleEvent(DongleNewCMGREvent event) + public void handleEvent(RegistryEvent event) { } - public void handleEvent(DongleDeviceEntryEvent event) + public void handleEvent(ReloadEvent event) { } - public void handleEvent(JoinEvent event) + public void handleEvent(RenameEvent event) { } - public void handleEvent(LeaveEvent event) + public void handleEvent(ResponseEvent event) { } - public void handleEvent(BridgeEvent event) + public void handleEvent(AgentsCompleteEvent event) { } - public void handleEvent(OriginateResponseEvent event) + public void handleEvent(AgentsEvent event) { } - public void handleEvent(ParkedCallEvent event) + public void handleEvent(AsyncAgiEvent event) { } - public void handleEvent(ParkedCallsCompleteEvent event) + public void handleEvent(ConfbridgeListCompleteEvent event) { } - public void handleEvent(PeerEntryEvent event) + public void handleEvent(ConfbridgeListEvent event) { } - public void handleEvent(PeerlistCompleteEvent event) + public void handleEvent(ConfbridgeListRoomsCompleteEvent event) { } - public void handleEvent(QueueEntryEvent event) + public void handleEvent(ConfbridgeListRoomsEvent event) { } - public void handleEvent(QueueMemberEvent event) + public void handleEvent(CoreShowChannelEvent event) { } - public void handleEvent(QueueMemberStatusEvent event) + public void handleEvent(CoreShowChannelsCompleteEvent event) { } - public void handleEvent(QueueParamsEvent event) + public void handleEvent(DahdiShowChannelsCompleteEvent event) { } - public void handleEvent(QueueStatusCompleteEvent event) + public void handleEvent(DahdiShowChannelsEvent event) { } - public void handleEvent(RegistrationsCompleteEvent event) + public void handleEvent(DbGetResponseEvent event) { } - public void handleEvent(StatusCompleteEvent event) + public void handleEvent(DongleDeviceEntryEvent event) { } - public void handleEvent(StatusEvent event) + public void handleEvent(DongleShowDevicesCompleteEvent event) { } - public void handleEvent(ZapShowChannelsCompleteEvent event) + public void handleEvent(EndpointList event) { } - public void handleEvent(DahdiShowChannelsCompleteEvent event) + public void handleEvent(EndpointListComplete event) { } - public void handleEvent(ZapShowChannelsEvent event) + public void handleEvent(ListDialplanEvent event) { } - public void handleEvent(DahdiShowChannelsEvent event) + public void handleEvent(OriginateResponseEvent event) { } - public void handleEvent(CoreShowChannelEvent event) + public void handleEvent(ParkedCallsCompleteEvent event) { } - public void handleEvent(CoreShowChannelsCompleteEvent event) + public void handleEvent(PeerEntryEvent event) { } - public void handleEvent(DialStateEvent event) - { - } + public void handleEvent(PeerlistCompleteEvent event) + { + } - public void handleEvent(VarSetEvent event) - { - } + public void handleEvent(PeersEvent event) + { + } - public void handleEvent(DeviceStateChangeEvent event) - { - } + public void handleEvent(QueueEntryEvent event) + { + } - public void handleEvent(NewConnectedLineEvent event) - { - } + public void handleEvent(QueueMemberEvent event) + { + } - public void handleEvent(BridgeCreateEvent event) - { - } + public void handleEvent(QueueParamsEvent event) + { + } - public void handleEvent(BridgeEnterEvent event) - { - } + public void handleEvent(QueueStatusCompleteEvent event) + { + } - public void handleEvent(BridgeDestroyEvent event) - { - } + public void handleEvent(QueueSummaryCompleteEvent event) + { + } - public void handleEvent(BridgeLeaveEvent event) - { - } + public void handleEvent(QueueSummaryEvent event) + { + } - public void handleEvent(RtcpSentEvent event) - { - } + public void handleEvent(RegistrationsCompleteEvent event) + { + } - public void handleEvent(RtcpReceivedEvent event) - { - } + public void handleEvent(RegistryEntryEvent event) + { + } + + public void handleEvent(ShowDialplanCompleteEvent event) + { + } + + public void handleEvent(SkypeBuddyEntryEvent event) + { + } + + public void handleEvent(SkypeBuddyListCompleteEvent event) + { + } + + public void handleEvent(SkypeLicenseEvent event) + { + } + + public void handleEvent(SkypeLicenseListCompleteEvent event) + { + } + + public void handleEvent(StatusCompleteEvent event) + { + } + + public void handleEvent(StatusEvent event) + { + } + + public void handleEvent(VoicemailUserEntryCompleteEvent event) + { + } + + public void handleEvent(VoicemailUserEntryEvent event) + { + } + + public void handleEvent(ZapShowChannelsCompleteEvent event) + { + } + + public void handleEvent(ZapShowChannelsEvent event) + { + } + + public void handleEvent(ShutdownEvent event) + { + } + + public void handleEvent(SkypeAccountStatusEvent event) + { + } + + public void handleEvent(SkypeBuddyStatusEvent event) + { + } + + public void handleEvent(SkypeChatMessageEvent event) + { + } + + public void handleEvent(SuccessfulAuthEvent event) + { + } + + public void handleEvent(TransferEvent event) + { + } + + public void handleEvent(UserEvent event) + { + } + + public void handleEvent(PausedEvent event) + { + } + + public void handleEvent(UnpausedEvent event) + { + } + + public void handleEvent(VarSetEvent event) + { + } /** * Dispatches to the appropriate handleEvent(...) method. From 37aed0b993b6c53c15bbee86f4e77acacc13b3d2 Mon Sep 17 00:00:00 2001 From: Stefan Erichsen Date: Mon, 24 Feb 2020 12:04:14 +0100 Subject: [PATCH 328/802] formatting, made logger a constant --- .../manager/AbstractManagerEventListener.java | 1152 ++++++----------- 1 file changed, 398 insertions(+), 754 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 3542ea02d..3e5bcb677 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -1,185 +1,11 @@ package org.asteriskjava.manager; -import java.lang.reflect.Method; - -import org.asteriskjava.manager.event.AgentCallbackLoginEvent; -import org.asteriskjava.manager.event.AgentCallbackLogoffEvent; -import org.asteriskjava.manager.event.AgentCalledEvent; -import org.asteriskjava.manager.event.AgentCompleteEvent; -import org.asteriskjava.manager.event.AgentConnectEvent; -import org.asteriskjava.manager.event.AgentDumpEvent; -import org.asteriskjava.manager.event.AgentLoginEvent; -import org.asteriskjava.manager.event.AgentLogoffEvent; -import org.asteriskjava.manager.event.AgentRingNoAnswerEvent; -import org.asteriskjava.manager.event.AgentsCompleteEvent; -import org.asteriskjava.manager.event.AgentsEvent; -import org.asteriskjava.manager.event.AgiExecEndEvent; -import org.asteriskjava.manager.event.AgiExecEvent; -import org.asteriskjava.manager.event.AgiExecStartEvent; -import org.asteriskjava.manager.event.AlarmClearEvent; -import org.asteriskjava.manager.event.AlarmEvent; -import org.asteriskjava.manager.event.AntennaLevelEvent; -import org.asteriskjava.manager.event.AsyncAgiEvent; -import org.asteriskjava.manager.event.AttendedTransferEvent; -import org.asteriskjava.manager.event.BlindTransferEvent; -import org.asteriskjava.manager.event.BridgeCreateEvent; -import org.asteriskjava.manager.event.BridgeDestroyEvent; -import org.asteriskjava.manager.event.BridgeEnterEvent; -import org.asteriskjava.manager.event.BridgeEvent; -import org.asteriskjava.manager.event.BridgeExecEvent; -import org.asteriskjava.manager.event.BridgeLeaveEvent; -import org.asteriskjava.manager.event.BridgeMergeEvent; -import org.asteriskjava.manager.event.CdrEvent; -import org.asteriskjava.manager.event.CelEvent; -import org.asteriskjava.manager.event.ChallengeResponseFailedEvent; -import org.asteriskjava.manager.event.ChallengeSentEvent; -import org.asteriskjava.manager.event.ChanSpyStartEvent; -import org.asteriskjava.manager.event.ChanSpyStopEvent; -import org.asteriskjava.manager.event.ChannelReloadEvent; -import org.asteriskjava.manager.event.ChannelUpdateEvent; -import org.asteriskjava.manager.event.ConfbridgeEndEvent; -import org.asteriskjava.manager.event.ConfbridgeJoinEvent; -import org.asteriskjava.manager.event.ConfbridgeLeaveEvent; -import org.asteriskjava.manager.event.ConfbridgeListCompleteEvent; -import org.asteriskjava.manager.event.ConfbridgeListEvent; -import org.asteriskjava.manager.event.ConfbridgeListRoomsCompleteEvent; -import org.asteriskjava.manager.event.ConfbridgeListRoomsEvent; -import org.asteriskjava.manager.event.ConfbridgeStartEvent; -import org.asteriskjava.manager.event.ConfbridgeTalkingEvent; -import org.asteriskjava.manager.event.ConnectEvent; -import org.asteriskjava.manager.event.ContactStatusEvent; -import org.asteriskjava.manager.event.CoreShowChannelEvent; -import org.asteriskjava.manager.event.CoreShowChannelsCompleteEvent; -import org.asteriskjava.manager.event.DAHDIChannelEvent; -import org.asteriskjava.manager.event.DahdiShowChannelsCompleteEvent; -import org.asteriskjava.manager.event.DahdiShowChannelsEvent; -import org.asteriskjava.manager.event.DbGetResponseEvent; -import org.asteriskjava.manager.event.DeviceStateChangeEvent; -import org.asteriskjava.manager.event.DialBeginEvent; -import org.asteriskjava.manager.event.DialEndEvent; -import org.asteriskjava.manager.event.DialEvent; -import org.asteriskjava.manager.event.DialStateEvent; -import org.asteriskjava.manager.event.DisconnectEvent; -import org.asteriskjava.manager.event.DndStateEvent; -import org.asteriskjava.manager.event.DongleCENDEvent; -import org.asteriskjava.manager.event.DongleCallStateChangeEvent; -import org.asteriskjava.manager.event.DongleDeviceEntryEvent; -import org.asteriskjava.manager.event.DongleNewCMGREvent; -import org.asteriskjava.manager.event.DongleNewSMSBase64Event; -import org.asteriskjava.manager.event.DongleNewSMSEvent; -import org.asteriskjava.manager.event.DongleShowDevicesCompleteEvent; -import org.asteriskjava.manager.event.DongleStatusEvent; -import org.asteriskjava.manager.event.DtmfBeginEvent; -import org.asteriskjava.manager.event.DtmfEndEvent; -import org.asteriskjava.manager.event.DtmfEvent; -import org.asteriskjava.manager.event.EndpointList; -import org.asteriskjava.manager.event.EndpointListComplete; -import org.asteriskjava.manager.event.ExtensionStatusEvent; -import org.asteriskjava.manager.event.FaxDocumentStatusEvent; -import org.asteriskjava.manager.event.FaxReceivedEvent; -import org.asteriskjava.manager.event.FaxStatusEvent; -import org.asteriskjava.manager.event.FullyBootedEvent; -import org.asteriskjava.manager.event.HangupEvent; -import org.asteriskjava.manager.event.HangupRequestEvent; -import org.asteriskjava.manager.event.HoldEvent; -import org.asteriskjava.manager.event.HoldedCallEvent; -import org.asteriskjava.manager.event.InvalidPasswordEvent; -import org.asteriskjava.manager.event.JabberEventEvent; -import org.asteriskjava.manager.event.JitterBufStatsEvent; -import org.asteriskjava.manager.event.JoinEvent; -import org.asteriskjava.manager.event.LeaveEvent; -import org.asteriskjava.manager.event.LinkEvent; -import org.asteriskjava.manager.event.ListDialplanEvent; -import org.asteriskjava.manager.event.LocalBridgeEvent; -import org.asteriskjava.manager.event.LocalOptimizationBeginEvent; -import org.asteriskjava.manager.event.LocalOptimizationEndEvent; -import org.asteriskjava.manager.event.LogChannelEvent; -import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.MasqueradeEvent; -import org.asteriskjava.manager.event.MeetMeEndEvent; -import org.asteriskjava.manager.event.MeetMeJoinEvent; -import org.asteriskjava.manager.event.MeetMeLeaveEvent; -import org.asteriskjava.manager.event.MeetMeMuteEvent; -import org.asteriskjava.manager.event.MeetMeTalkingEvent; -import org.asteriskjava.manager.event.MeetMeTalkingRequestEvent; -import org.asteriskjava.manager.event.MessageWaitingEvent; -import org.asteriskjava.manager.event.ModuleLoadReportEvent; -import org.asteriskjava.manager.event.MonitorStartEvent; -import org.asteriskjava.manager.event.MonitorStopEvent; -import org.asteriskjava.manager.event.MusicOnHoldEvent; -import org.asteriskjava.manager.event.MusicOnHoldStartEvent; -import org.asteriskjava.manager.event.MusicOnHoldStopEvent; -import org.asteriskjava.manager.event.NewAccountCodeEvent; -import org.asteriskjava.manager.event.NewCallerIdEvent; -import org.asteriskjava.manager.event.NewChannelEvent; -import org.asteriskjava.manager.event.NewConnectedLineEvent; -import org.asteriskjava.manager.event.NewExtenEvent; -import org.asteriskjava.manager.event.NewStateEvent; -import org.asteriskjava.manager.event.OriginateResponseEvent; -import org.asteriskjava.manager.event.ParkedCallEvent; -import org.asteriskjava.manager.event.ParkedCallsCompleteEvent; -import org.asteriskjava.manager.event.PausedEvent; -import org.asteriskjava.manager.event.PeerEntryEvent; -import org.asteriskjava.manager.event.PeerStatusEvent; -import org.asteriskjava.manager.event.PeerlistCompleteEvent; -import org.asteriskjava.manager.event.PeersEvent; -import org.asteriskjava.manager.event.PickupEvent; -import org.asteriskjava.manager.event.PriEventEvent; -import org.asteriskjava.manager.event.ProtocolIdentifierReceivedEvent; -import org.asteriskjava.manager.event.QueueCallerAbandonEvent; -import org.asteriskjava.manager.event.QueueCallerJoinEvent; -import org.asteriskjava.manager.event.QueueCallerLeaveEvent; -import org.asteriskjava.manager.event.QueueEntryEvent; -import org.asteriskjava.manager.event.QueueEvent; -import org.asteriskjava.manager.event.QueueMemberAddedEvent; -import org.asteriskjava.manager.event.QueueMemberEvent; -import org.asteriskjava.manager.event.QueueMemberPausedEvent; -import org.asteriskjava.manager.event.QueueMemberPenaltyEvent; -import org.asteriskjava.manager.event.QueueMemberRemovedEvent; -import org.asteriskjava.manager.event.QueueParamsEvent; -import org.asteriskjava.manager.event.QueueStatusCompleteEvent; -import org.asteriskjava.manager.event.QueueSummaryCompleteEvent; -import org.asteriskjava.manager.event.QueueSummaryEvent; -import org.asteriskjava.manager.event.ReceiveFaxEvent; -import org.asteriskjava.manager.event.RegistrationsCompleteEvent; -import org.asteriskjava.manager.event.RegistryEntryEvent; -import org.asteriskjava.manager.event.RegistryEvent; -import org.asteriskjava.manager.event.ReloadEvent; -import org.asteriskjava.manager.event.RenameEvent; -import org.asteriskjava.manager.event.ResponseEvent; -import org.asteriskjava.manager.event.RtcpReceivedEvent; -import org.asteriskjava.manager.event.RtcpSentEvent; -import org.asteriskjava.manager.event.RtpReceiverStatEvent; -import org.asteriskjava.manager.event.RtpSenderStatEvent; -import org.asteriskjava.manager.event.SendFaxEvent; -import org.asteriskjava.manager.event.SendFaxStatusEvent; -import org.asteriskjava.manager.event.ShowDialplanCompleteEvent; -import org.asteriskjava.manager.event.ShutdownEvent; -import org.asteriskjava.manager.event.SkypeAccountStatusEvent; -import org.asteriskjava.manager.event.SkypeBuddyEntryEvent; -import org.asteriskjava.manager.event.SkypeBuddyListCompleteEvent; -import org.asteriskjava.manager.event.SkypeBuddyStatusEvent; -import org.asteriskjava.manager.event.SkypeChatMessageEvent; -import org.asteriskjava.manager.event.SkypeLicenseEvent; -import org.asteriskjava.manager.event.SkypeLicenseListCompleteEvent; -import org.asteriskjava.manager.event.SoftHangupRequestEvent; -import org.asteriskjava.manager.event.StatusCompleteEvent; -import org.asteriskjava.manager.event.StatusEvent; -import org.asteriskjava.manager.event.SuccessfulAuthEvent; -import org.asteriskjava.manager.event.T38FaxStatusEvent; -import org.asteriskjava.manager.event.TransferEvent; -import org.asteriskjava.manager.event.UnholdEvent; -import org.asteriskjava.manager.event.UnlinkEvent; -import org.asteriskjava.manager.event.UnpausedEvent; -import org.asteriskjava.manager.event.UserEvent; -import org.asteriskjava.manager.event.VarSetEvent; -import org.asteriskjava.manager.event.VoicemailUserEntryCompleteEvent; -import org.asteriskjava.manager.event.VoicemailUserEntryEvent; -import org.asteriskjava.manager.event.ZapShowChannelsCompleteEvent; -import org.asteriskjava.manager.event.ZapShowChannelsEvent; +import org.asteriskjava.manager.event.*; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.lang.reflect.Method; + /** * Utility class that provides a protected handler method for each concrete * manager event. Makes life easier by removing the need to code endless @@ -236,734 +62,552 @@ * @author srt * @since 0.3 */ -public abstract class AbstractManagerEventListener implements ManagerEventListener -{ - Log logger = LogFactory.getLog(AbstractManagerEventListener.class); +public abstract class AbstractManagerEventListener implements ManagerEventListener { + + private static final Log LOGGER = LogFactory.getLog(AbstractManagerEventListener.class); + + public void handleEvent(AgentCompleteEvent event) { + } + + public void handleEvent(AgentConnectEvent event) { + } + + public void handleEvent(AgentDumpEvent event) { + } + + public void handleEvent(AgentRingNoAnswerEvent event) { + } + + public void handleEvent(AttendedTransferEvent event) { + } + + public void handleEvent(BlindTransferEvent event) { + } + + public void handleEvent(BridgeCreateEvent event) { + } + + public void handleEvent(BridgeDestroyEvent event) { + } + + public void handleEvent(BridgeEnterEvent event) { + } + + public void handleEvent(BridgeLeaveEvent event) { + } + + public void handleEvent(HangupEvent event) { + } + + public void handleEvent(NewChannelEvent event) { + } + + public void handleEvent(NewStateEvent event) { + } + + public void handleEvent(ConfbridgeEndEvent event) { + } + + public void handleEvent(ConfbridgeJoinEvent event) { + } + + public void handleEvent(ConfbridgeLeaveEvent event) { + } + + public void handleEvent(ConfbridgeStartEvent event) { + } + + public void handleEvent(ConfbridgeTalkingEvent event) { + } + + public void handleEvent(AntennaLevelEvent event) { + } + + public void handleEvent(HangupRequestEvent event) { + } + + public void handleEvent(NewCallerIdEvent event) { + } + + public void handleEvent(SoftHangupRequestEvent event) { + } + + public void handleEvent(FaxDocumentStatusEvent event) { + } + + public void handleEvent(FaxReceivedEvent event) { + } - public void handleEvent(AgentCompleteEvent event) - { - } + public void handleEvent(FaxStatusEvent event) { + } - public void handleEvent(AgentConnectEvent event) - { - } + public void handleEvent(SendFaxEvent event) { + } - public void handleEvent(AgentDumpEvent event) - { - } + public void handleEvent(SendFaxStatusEvent event) { + } - public void handleEvent(AgentRingNoAnswerEvent event) - { - } + public void handleEvent(T38FaxStatusEvent event) { + } - public void handleEvent(AttendedTransferEvent event) - { - } + public void handleEvent(HoldEvent event) { + } - public void handleEvent(BlindTransferEvent event) - { - } + public void handleEvent(UnholdEvent event) { + } - public void handleEvent(BridgeCreateEvent event) - { - } + public void handleEvent(MeetMeJoinEvent event) { + } - public void handleEvent(BridgeDestroyEvent event) - { - } + public void handleEvent(MeetMeLeaveEvent event) { + } - public void handleEvent(BridgeEnterEvent event) - { - } + public void handleEvent(MeetMeMuteEvent event) { + } - public void handleEvent(BridgeLeaveEvent event) - { - } + public void handleEvent(MeetMeTalkingEvent event) { + } - public void handleEvent(HangupEvent event) - { - } + public void handleEvent(MeetMeTalkingRequestEvent event) { + } - public void handleEvent(NewChannelEvent event) - { - } + public void handleEvent(MonitorStartEvent event) { + } - public void handleEvent(NewStateEvent event) - { - } + public void handleEvent(MonitorStopEvent event) { + } - public void handleEvent(ConfbridgeEndEvent event) - { - } + public void handleEvent(ParkedCallEvent event) { + } - public void handleEvent(ConfbridgeJoinEvent event) - { - } + public void handleEvent(QueueMemberAddedEvent event) { + } - public void handleEvent(ConfbridgeLeaveEvent event) - { - } + public void handleEvent(QueueMemberPausedEvent event) { + } - public void handleEvent(ConfbridgeStartEvent event) - { - } + public void handleEvent(QueueMemberRemovedEvent event) { + } - public void handleEvent(ConfbridgeTalkingEvent event) - { - } + public void handleEvent(RtcpReceivedEvent event) { + } - public void handleEvent(AntennaLevelEvent event) - { - } + public void handleEvent(RtcpSentEvent event) { + } - public void handleEvent(HangupRequestEvent event) - { - } + public void handleEvent(RtpReceiverStatEvent event) { + } - public void handleEvent(NewCallerIdEvent event) - { - } + public void handleEvent(RtpSenderStatEvent event) { + } - public void handleEvent(SoftHangupRequestEvent event) - { - } + public void handleEvent(AgentCallbackLoginEvent event) { + } - public void handleEvent(FaxDocumentStatusEvent event) - { - } + public void handleEvent(AgentCallbackLogoffEvent event) { + } - public void handleEvent(FaxReceivedEvent event) - { - } + public void handleEvent(AgentCalledEvent event) { + } - public void handleEvent(FaxStatusEvent event) - { - } + public void handleEvent(AgentLoginEvent event) { + } - public void handleEvent(SendFaxEvent event) - { - } + public void handleEvent(AgentLogoffEvent event) { + } - public void handleEvent(SendFaxStatusEvent event) - { - } + public void handleEvent(AgiExecEvent event) { + } - public void handleEvent(T38FaxStatusEvent event) - { - } + public void handleEvent(AgiExecEndEvent event) { + } - public void handleEvent(HoldEvent event) - { - } + public void handleEvent(AgiExecStartEvent event) { + } - public void handleEvent(UnholdEvent event) - { - } + public void handleEvent(AlarmClearEvent event) { + } - public void handleEvent(MeetMeJoinEvent event) - { - } + public void handleEvent(AlarmEvent event) { + } - public void handleEvent(MeetMeLeaveEvent event) - { - } + public void handleEvent(BridgeEvent event) { + } - public void handleEvent(MeetMeMuteEvent event) - { - } + public void handleEvent(LinkEvent event) { + } - public void handleEvent(MeetMeTalkingEvent event) - { - } + public void handleEvent(UnlinkEvent event) { + } - public void handleEvent(MeetMeTalkingRequestEvent event) - { - } + public void handleEvent(BridgeExecEvent event) { + } - public void handleEvent(MonitorStartEvent event) - { - } + public void handleEvent(BridgeMergeEvent event) { + } - public void handleEvent(MonitorStopEvent event) - { - } + public void handleEvent(CdrEvent event) { + } - public void handleEvent(ParkedCallEvent event) - { - } + public void handleEvent(CelEvent event) { + } - public void handleEvent(QueueMemberAddedEvent event) - { - } + public void handleEvent(ChallengeResponseFailedEvent event) { + } - public void handleEvent(QueueMemberPausedEvent event) - { - } + public void handleEvent(ChallengeSentEvent event) { + } - public void handleEvent(QueueMemberRemovedEvent event) - { - } + public void handleEvent(ChannelReloadEvent event) { + } - public void handleEvent(RtcpReceivedEvent event) - { - } + public void handleEvent(ChannelUpdateEvent event) { + } - public void handleEvent(RtcpSentEvent event) - { - } + public void handleEvent(ChanSpyStartEvent event) { + } - public void handleEvent(RtpReceiverStatEvent event) - { - } + public void handleEvent(ChanSpyStopEvent event) { + } - public void handleEvent(RtpSenderStatEvent event) - { - } + public void handleEvent(ConnectEvent event) { + } - public void handleEvent(AgentCallbackLoginEvent event) - { - } + public void handleEvent(ContactStatusEvent event) { + } - public void handleEvent(AgentCallbackLogoffEvent event) - { - } + public void handleEvent(DAHDIChannelEvent event) { + } - public void handleEvent(AgentCalledEvent event) - { - } + public void handleEvent(DeviceStateChangeEvent event) { + } - public void handleEvent(AgentLoginEvent event) - { - } + public void handleEvent(DialEvent event) { + } - public void handleEvent(AgentLogoffEvent event) - { - } + public void handleEvent(DialBeginEvent event) { + } - public void handleEvent(AgiExecEvent event) - { - } + public void handleEvent(DialEndEvent event) { + } - public void handleEvent(AgiExecEndEvent event) - { - } + public void handleEvent(DialStateEvent event) { + } - public void handleEvent(AgiExecStartEvent event) - { - } + public void handleEvent(DisconnectEvent event) { + } - public void handleEvent(AlarmClearEvent event) - { - } + public void handleEvent(DndStateEvent event) { + } - public void handleEvent(AlarmEvent event) - { - } + public void handleEvent(DongleCallStateChangeEvent event) { + } - public void handleEvent(BridgeEvent event) - { - } + public void handleEvent(DongleCENDEvent event) { + } - public void handleEvent(LinkEvent event) - { - } + public void handleEvent(DongleNewCMGREvent event) { + } - public void handleEvent(UnlinkEvent event) - { - } + public void handleEvent(DongleNewSMSBase64Event event) { + } - public void handleEvent(BridgeExecEvent event) - { - } + public void handleEvent(DongleNewSMSEvent event) { + } - public void handleEvent(BridgeMergeEvent event) - { - } + public void handleEvent(DongleStatusEvent event) { + } - public void handleEvent(CdrEvent event) - { - } + public void handleEvent(DtmfEvent event) { + } - public void handleEvent(CelEvent event) - { - } + public void handleEvent(DtmfBeginEvent event) { + } - public void handleEvent(ChallengeResponseFailedEvent event) - { - } + public void handleEvent(DtmfEndEvent event) { + } - public void handleEvent(ChallengeSentEvent event) - { - } + public void handleEvent(ExtensionStatusEvent event) { + } - public void handleEvent(ChannelReloadEvent event) - { - } + public void handleEvent(FullyBootedEvent event) { + } - public void handleEvent(ChannelUpdateEvent event) - { - } + public void handleEvent(HoldedCallEvent event) { + } - public void handleEvent(ChanSpyStartEvent event) - { - } + public void handleEvent(InvalidPasswordEvent event) { + } - public void handleEvent(ChanSpyStopEvent event) - { - } + public void handleEvent(JabberEventEvent event) { + } - public void handleEvent(ConnectEvent event) - { - } + public void handleEvent(JitterBufStatsEvent event) { + } - public void handleEvent(ContactStatusEvent event) - { - } + public void handleEvent(LocalBridgeEvent event) { + } - public void handleEvent(DAHDIChannelEvent event) - { - } + public void handleEvent(LocalOptimizationBeginEvent event) { + } - public void handleEvent(DeviceStateChangeEvent event) - { - } + public void handleEvent(LocalOptimizationEndEvent event) { + } - public void handleEvent(DialEvent event) - { - } + public void handleEvent(LogChannelEvent event) { + } - public void handleEvent(DialBeginEvent event) - { - } + public void handleEvent(MasqueradeEvent event) { + } - public void handleEvent(DialEndEvent event) - { - } + public void handleEvent(MeetMeEndEvent event) { + } - public void handleEvent(DialStateEvent event) - { - } + public void handleEvent(MessageWaitingEvent event) { + } - public void handleEvent(DisconnectEvent event) - { - } + public void handleEvent(ModuleLoadReportEvent event) { + } - public void handleEvent(DndStateEvent event) - { - } + public void handleEvent(MusicOnHoldEvent event) { + } - public void handleEvent(DongleCallStateChangeEvent event) - { - } + public void handleEvent(MusicOnHoldStartEvent event) { + } - public void handleEvent(DongleCENDEvent event) - { - } + public void handleEvent(MusicOnHoldStopEvent event) { + } - public void handleEvent(DongleNewCMGREvent event) - { - } + public void handleEvent(NewAccountCodeEvent event) { + } - public void handleEvent(DongleNewSMSBase64Event event) - { - } + public void handleEvent(NewConnectedLineEvent event) { + } - public void handleEvent(DongleNewSMSEvent event) - { - } + public void handleEvent(NewExtenEvent event) { + } - public void handleEvent(DongleStatusEvent event) - { - } + public void handleEvent(PeerStatusEvent event) { + } - public void handleEvent(DtmfEvent event) - { - } + public void handleEvent(PickupEvent event) { + } - public void handleEvent(DtmfBeginEvent event) - { - } + public void handleEvent(PriEventEvent event) { + } - public void handleEvent(DtmfEndEvent event) - { - } + public void handleEvent(ProtocolIdentifierReceivedEvent event) { + } - public void handleEvent(ExtensionStatusEvent event) - { - } + public void handleEvent(QueueEvent event) { + } - public void handleEvent(FullyBootedEvent event) - { - } + public void handleEvent(JoinEvent event) { + } - public void handleEvent(HoldedCallEvent event) - { - } + public void handleEvent(LeaveEvent event) { + } - public void handleEvent(InvalidPasswordEvent event) - { - } + public void handleEvent(QueueCallerAbandonEvent event) { + } - public void handleEvent(JabberEventEvent event) - { - } + public void handleEvent(QueueCallerJoinEvent event) { + } - public void handleEvent(JitterBufStatsEvent event) - { - } + public void handleEvent(QueueCallerLeaveEvent event) { + } - public void handleEvent(LocalBridgeEvent event) - { - } + public void handleEvent(QueueMemberPenaltyEvent event) { + } - public void handleEvent(LocalOptimizationBeginEvent event) - { - } + public void handleEvent(ReceiveFaxEvent event) { + } - public void handleEvent(LocalOptimizationEndEvent event) - { - } + public void handleEvent(RegistryEvent event) { + } - public void handleEvent(LogChannelEvent event) - { - } + public void handleEvent(ReloadEvent event) { + } - public void handleEvent(MasqueradeEvent event) - { - } + public void handleEvent(RenameEvent event) { + } - public void handleEvent(MeetMeEndEvent event) - { - } + public void handleEvent(ResponseEvent event) { + } - public void handleEvent(MessageWaitingEvent event) - { - } + public void handleEvent(AgentsCompleteEvent event) { + } - public void handleEvent(ModuleLoadReportEvent event) - { - } + public void handleEvent(AgentsEvent event) { + } - public void handleEvent(MusicOnHoldEvent event) - { - } + public void handleEvent(AsyncAgiEvent event) { + } - public void handleEvent(MusicOnHoldStartEvent event) - { - } + public void handleEvent(ConfbridgeListCompleteEvent event) { + } - public void handleEvent(MusicOnHoldStopEvent event) - { - } + public void handleEvent(ConfbridgeListEvent event) { + } - public void handleEvent(NewAccountCodeEvent event) - { - } + public void handleEvent(ConfbridgeListRoomsCompleteEvent event) { + } - public void handleEvent(NewConnectedLineEvent event) - { - } + public void handleEvent(ConfbridgeListRoomsEvent event) { + } - public void handleEvent(NewExtenEvent event) - { - } + public void handleEvent(CoreShowChannelEvent event) { + } - public void handleEvent(PeerStatusEvent event) - { - } + public void handleEvent(CoreShowChannelsCompleteEvent event) { + } - public void handleEvent(PickupEvent event) - { - } + public void handleEvent(DahdiShowChannelsCompleteEvent event) { + } - public void handleEvent(PriEventEvent event) - { - } + public void handleEvent(DahdiShowChannelsEvent event) { + } - public void handleEvent(ProtocolIdentifierReceivedEvent event) - { - } + public void handleEvent(DbGetResponseEvent event) { + } - public void handleEvent(QueueEvent event) - { - } + public void handleEvent(DongleDeviceEntryEvent event) { + } - public void handleEvent(JoinEvent event) - { - } + public void handleEvent(DongleShowDevicesCompleteEvent event) { + } - public void handleEvent(LeaveEvent event) - { - } + public void handleEvent(EndpointList event) { + } - public void handleEvent(QueueCallerAbandonEvent event) - { - } + public void handleEvent(EndpointListComplete event) { + } - public void handleEvent(QueueCallerJoinEvent event) - { - } + public void handleEvent(ListDialplanEvent event) { + } - public void handleEvent(QueueCallerLeaveEvent event) - { - } + public void handleEvent(OriginateResponseEvent event) { + } - public void handleEvent(QueueMemberPenaltyEvent event) - { - } + public void handleEvent(ParkedCallsCompleteEvent event) { + } - public void handleEvent(ReceiveFaxEvent event) - { - } + public void handleEvent(PeerEntryEvent event) { + } - public void handleEvent(RegistryEvent event) - { - } + public void handleEvent(PeerlistCompleteEvent event) { + } - public void handleEvent(ReloadEvent event) - { - } + public void handleEvent(PeersEvent event) { + } - public void handleEvent(RenameEvent event) - { - } + public void handleEvent(QueueEntryEvent event) { + } - public void handleEvent(ResponseEvent event) - { - } + public void handleEvent(QueueMemberEvent event) { + } - public void handleEvent(AgentsCompleteEvent event) - { - } + public void handleEvent(QueueParamsEvent event) { + } - public void handleEvent(AgentsEvent event) - { - } + public void handleEvent(QueueStatusCompleteEvent event) { + } - public void handleEvent(AsyncAgiEvent event) - { - } + public void handleEvent(QueueSummaryCompleteEvent event) { + } - public void handleEvent(ConfbridgeListCompleteEvent event) - { - } + public void handleEvent(QueueSummaryEvent event) { + } - public void handleEvent(ConfbridgeListEvent event) - { - } + public void handleEvent(RegistrationsCompleteEvent event) { + } - public void handleEvent(ConfbridgeListRoomsCompleteEvent event) - { - } + public void handleEvent(RegistryEntryEvent event) { + } - public void handleEvent(ConfbridgeListRoomsEvent event) - { - } + public void handleEvent(ShowDialplanCompleteEvent event) { + } - public void handleEvent(CoreShowChannelEvent event) - { - } + public void handleEvent(SkypeBuddyEntryEvent event) { + } - public void handleEvent(CoreShowChannelsCompleteEvent event) - { - } + public void handleEvent(SkypeBuddyListCompleteEvent event) { + } - public void handleEvent(DahdiShowChannelsCompleteEvent event) - { - } + public void handleEvent(SkypeLicenseEvent event) { + } - public void handleEvent(DahdiShowChannelsEvent event) - { - } + public void handleEvent(SkypeLicenseListCompleteEvent event) { + } - public void handleEvent(DbGetResponseEvent event) - { - } + public void handleEvent(StatusCompleteEvent event) { + } - public void handleEvent(DongleDeviceEntryEvent event) - { - } + public void handleEvent(StatusEvent event) { + } - public void handleEvent(DongleShowDevicesCompleteEvent event) - { - } + public void handleEvent(VoicemailUserEntryCompleteEvent event) { + } - public void handleEvent(EndpointList event) - { - } + public void handleEvent(VoicemailUserEntryEvent event) { + } - public void handleEvent(EndpointListComplete event) - { - } + public void handleEvent(ZapShowChannelsCompleteEvent event) { + } - public void handleEvent(ListDialplanEvent event) - { - } + public void handleEvent(ZapShowChannelsEvent event) { + } - public void handleEvent(OriginateResponseEvent event) - { - } + public void handleEvent(ShutdownEvent event) { + } - public void handleEvent(ParkedCallsCompleteEvent event) - { - } + public void handleEvent(SkypeAccountStatusEvent event) { + } - public void handleEvent(PeerEntryEvent event) - { - } + public void handleEvent(SkypeBuddyStatusEvent event) { + } - public void handleEvent(PeerlistCompleteEvent event) - { - } + public void handleEvent(SkypeChatMessageEvent event) { + } - public void handleEvent(PeersEvent event) - { - } + public void handleEvent(SuccessfulAuthEvent event) { + } - public void handleEvent(QueueEntryEvent event) - { - } + public void handleEvent(TransferEvent event) { + } - public void handleEvent(QueueMemberEvent event) - { - } + public void handleEvent(UserEvent event) { + } - public void handleEvent(QueueParamsEvent event) - { - } + public void handleEvent(PausedEvent event) { + } - public void handleEvent(QueueStatusCompleteEvent event) - { - } + public void handleEvent(UnpausedEvent event) { + } - public void handleEvent(QueueSummaryCompleteEvent event) - { - } + public void handleEvent(VarSetEvent event) { + } - public void handleEvent(QueueSummaryEvent event) - { - } - - public void handleEvent(RegistrationsCompleteEvent event) - { - } + /** + * Dispatches to the appropriate handleEvent(...) method. + * + * @param event the event to handle + */ + @Override + public void onManagerEvent(ManagerEvent event) { - public void handleEvent(RegistryEntryEvent event) - { - } + // if this turns out to be slow, we could consider caching the reflection lookup + try { + Method method = this.getClass().getMethod("handleEvent", event.getClass()); + if (method != null) { + method.invoke(this, event); + return; + } + } catch (Exception e) { + LOGGER.error(e, e); + } - public void handleEvent(ShowDialplanCompleteEvent event) - { - } - - public void handleEvent(SkypeBuddyEntryEvent event) - { - } - - public void handleEvent(SkypeBuddyListCompleteEvent event) - { - } - - public void handleEvent(SkypeLicenseEvent event) - { - } - - public void handleEvent(SkypeLicenseListCompleteEvent event) - { - } - - public void handleEvent(StatusCompleteEvent event) - { - } - - public void handleEvent(StatusEvent event) - { - } - - public void handleEvent(VoicemailUserEntryCompleteEvent event) - { - } - - public void handleEvent(VoicemailUserEntryEvent event) - { - } - - public void handleEvent(ZapShowChannelsCompleteEvent event) - { - } - - public void handleEvent(ZapShowChannelsEvent event) - { - } - - public void handleEvent(ShutdownEvent event) - { - } - - public void handleEvent(SkypeAccountStatusEvent event) - { - } - - public void handleEvent(SkypeBuddyStatusEvent event) - { - } - - public void handleEvent(SkypeChatMessageEvent event) - { - } - - public void handleEvent(SuccessfulAuthEvent event) - { - } - - public void handleEvent(TransferEvent event) - { - } - - public void handleEvent(UserEvent event) - { - } - - public void handleEvent(PausedEvent event) - { - } - - public void handleEvent(UnpausedEvent event) - { - } - - public void handleEvent(VarSetEvent event) - { - } - - /** - * Dispatches to the appropriate handleEvent(...) method. - * - * @param event the event to handle - */ - @Override - public void onManagerEvent(ManagerEvent event) - { - - // if this turns out to be slow, we could consider caching the reflection lookup - - try - { - - Method method = this.getClass().getMethod("handleEvent", new Class[]{event.getClass()}); - if (method != null) - { - method.invoke(this, event); - return; - } - } - catch (Exception e) - { - logger.error(e, e); - } - - logger.error("The event " + event.getClass() - + " couldn't be mapped to a method in AbstractManagerEventListener.java, someone should add it!"); - - } + LOGGER.error("The event " + event.getClass() + + " couldn't be mapped to a method in AbstractManagerEventListener.java, someone should add it!"); + } } From 8004b68d5bbd105e2c906d174f5171ee4db2d986 Mon Sep 17 00:00:00 2001 From: Stefan Erichsen Date: Mon, 24 Feb 2020 12:07:07 +0100 Subject: [PATCH 329/802] formatting, tabs -> spaces --- .../AbstractManagerEventListenerTest.java | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/test/java/org/asteriskjava/manager/AbstractManagerEventListenerTest.java b/src/test/java/org/asteriskjava/manager/AbstractManagerEventListenerTest.java index 6050bd106..38a1e0cdb 100644 --- a/src/test/java/org/asteriskjava/manager/AbstractManagerEventListenerTest.java +++ b/src/test/java/org/asteriskjava/manager/AbstractManagerEventListenerTest.java @@ -1,49 +1,49 @@ package org.asteriskjava.manager; -import static org.junit.Assert.assertTrue; - import org.asteriskjava.manager.event.JoinEvent; import org.asteriskjava.manager.event.LeaveEvent; import org.junit.Test; +import static org.junit.Assert.assertTrue; + public class AbstractManagerEventListenerTest { - @Test - public void shouldHandleJoinEvent() { - //given - EventListener listener = new EventListener(); + @Test + public void shouldHandleJoinEvent() { + //given + EventListener listener = new EventListener(); - //when - listener.onManagerEvent(new JoinEvent(this)); + //when + listener.onManagerEvent(new JoinEvent(this)); - //then - assertTrue(listener.joinEventHandled); - } + //then + assertTrue(listener.joinEventHandled); + } - @Test - public void shouldHandleLeaveEvent() { - //given - EventListener listener = new EventListener(); + @Test + public void shouldHandleLeaveEvent() { + //given + EventListener listener = new EventListener(); - //when - listener.onManagerEvent(new LeaveEvent(this)); + //when + listener.onManagerEvent(new LeaveEvent(this)); - //then - assertTrue(listener.leaveEventHandled); - } + //then + assertTrue(listener.leaveEventHandled); + } - private static class EventListener extends AbstractManagerEventListener { - public boolean joinEventHandled; - public boolean leaveEventHandled; + private static class EventListener extends AbstractManagerEventListener { + public boolean joinEventHandled; + public boolean leaveEventHandled; - @Override - public void handleEvent(JoinEvent event) { - this.joinEventHandled = true; - } + @Override + public void handleEvent(JoinEvent event) { + this.joinEventHandled = true; + } - @Override + @Override public void handleEvent(LeaveEvent event) { - this.leaveEventHandled = true; - } - } + this.leaveEventHandled = true; + } + } } \ No newline at end of file From a2e6e13791e4999f1e4b7a1c1615ab7aba039952 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 25 Feb 2020 13:32:28 +1100 Subject: [PATCH 330/802] change to using org.reflections to load event handlers --- pom.xml | 5 ++++ .../manager/internal/EventBuilderImpl.java | 28 ++++++++++--------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index 4567e9419..f673cd29b 100644 --- a/pom.xml +++ b/pom.xml @@ -185,6 +185,11 @@ 1.1.2 test + + org.reflections + reflections + 0.9.12 + diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index 89edec986..bfff1b375 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -35,7 +35,7 @@ import org.asteriskjava.manager.event.UserEvent; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -import org.asteriskjava.util.ReflectionUtil; +import org.reflections.Reflections; /** * Default implementation of the EventBuilder interface. @@ -52,8 +52,8 @@ class EventBuilderImpl extends AbstractBuilder implements EventBuilder private static final Log logger = LogFactory.getLog(EventBuilderImpl.class); - private final static Set> knownManagerEventClasses = ReflectionUtil - .loadClasses("org.asteriskjava.manager.event", ManagerEvent.class); + private final static Set> knownManagerEventClasses = new Reflections( + "org.asteriskjava.manager.event").getSubTypesOf(ManagerEvent.class); EventBuilderImpl() { @@ -68,7 +68,10 @@ private void registerBuiltinEventClasses() { for (Class< ? extends ManagerEvent> managerEventClass : knownManagerEventClasses) { - registerEventClass(managerEventClass); + if (!Modifier.isAbstract(managerEventClass.getModifiers())) + { + registerEventClass(managerEventClass); + } } } @@ -107,12 +110,11 @@ public final void registerEventClass(String eventType, Class< ? extends ManagerE { Constructor< ? > defaultConstructor; - if (!ManagerEvent.class.isAssignableFrom(clazz)) + if (Modifier.isAbstract(clazz.getModifiers())) { - throw new IllegalArgumentException(clazz + " is not a ManagerEvent"); + throw new IllegalArgumentException(clazz + " is abstract"); } - - if ((clazz.getModifiers() & Modifier.ABSTRACT) != 0) + if (clazz.isInterface()) { throw new IllegalArgumentException(clazz + " is abstract"); } @@ -120,17 +122,17 @@ public final void registerEventClass(String eventType, Class< ? extends ManagerE try { defaultConstructor = clazz.getConstructor(Object.class); + + if (!Modifier.isPublic(defaultConstructor.getModifiers())) + { + throw new IllegalArgumentException(clazz + " has no public default constructor"); + } } catch (NoSuchMethodException ex) { throw new IllegalArgumentException(clazz + " has no usable constructor"); } - if ((defaultConstructor.getModifiers() & Modifier.PUBLIC) == 0) - { - throw new IllegalArgumentException(clazz + " has no public default constructor"); - } - registeredEventClasses.put(eventType.toLowerCase(Locale.US), clazz); logger.debug("Registered event type '" + eventType + "' (" + clazz + ")"); From 4be1d20c10d69d66600980564042d68c8ce86fd2 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 25 Feb 2020 13:33:00 +1100 Subject: [PATCH 331/802] for version 3.0.23-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f673cd29b..66de763e1 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.0.22-SNAPSHOT + 3.0.23-SNAPSHOT UTF-8 From e9681dafe9edc1b61d14f0df292d1c7f0be3991c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 26 Feb 2020 10:42:48 +1100 Subject: [PATCH 332/802] for version 3.1.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 66de763e1..ae242b34d 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.0.23-SNAPSHOT + 3.1.0 UTF-8 From 966e72c3ca1845df19fcff6c12c2afd84ddc53e8 Mon Sep 17 00:00:00 2001 From: rndbit <> Date: Mon, 16 Mar 2020 13:44:42 +1030 Subject: [PATCH 333/802] Add asynchronous method sendEventGeneratingAction --- .../manager/DefaultManagerConnection.java | 8 ++ .../manager/ManagerConnection.java | 14 ++ .../SendEventGeneratingActionCallback.java | 31 +++++ .../internal/ManagerConnectionImpl.java | 124 ++++++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/SendEventGeneratingActionCallback.java diff --git a/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java b/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java index 032ee340d..18b65fc4c 100644 --- a/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java @@ -350,6 +350,14 @@ public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, lo return impl.sendEventGeneratingAction(action, timeout); } + @Override + public void sendEventGeneratingAction(EventGeneratingAction action, + SendEventGeneratingActionCallback callback) + throws IOException, IllegalArgumentException, IllegalStateException + { + impl.sendEventGeneratingAction(action, callback); + } + public void addEventListener(final ManagerEventListener listener) { impl.addEventListener(listener); diff --git a/src/main/java/org/asteriskjava/manager/ManagerConnection.java b/src/main/java/org/asteriskjava/manager/ManagerConnection.java index 442f9a2e2..bc50e8f0b 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/ManagerConnection.java @@ -403,6 +403,20 @@ ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long timeout) throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException; + /** + * Asynchronously sends an {@link EventGeneratingAction} to the Asterisk + * server. This is similar to + * {@link #sendEventGeneratingAction(EventGeneratingAction, long)} except it + * does NOT block to wait for the completion. Instead after the action + * completes or fails the result is provided to the optional callback via + * {@link SendEventGeneratingActionCallback#onResponse(ResponseEvents)}. + * + * @see #sendEventGeneratingAction(EventGeneratingAction, long) + */ + void sendEventGeneratingAction( + EventGeneratingAction action, + SendEventGeneratingActionCallback callback) + throws IOException, IllegalArgumentException, IllegalStateException; /** * Registers an event listener that is called whenever an * {@link org.asteriskjava.manager.event.ManagerEvent} is receiced from the diff --git a/src/main/java/org/asteriskjava/manager/SendEventGeneratingActionCallback.java b/src/main/java/org/asteriskjava/manager/SendEventGeneratingActionCallback.java new file mode 100644 index 000000000..09feda162 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/SendEventGeneratingActionCallback.java @@ -0,0 +1,31 @@ +package org.asteriskjava.manager; + +import org.asteriskjava.manager.response.ManagerError; +import org.asteriskjava.manager.response.ManagerResponse; + +/** + * Callback interface to send + * {@link org.asteriskjava.manager.action.EventGeneratingAction} asynchronously. + * + * @see org.asteriskjava.manager.ManagerConnection#sendEventGeneratingAction(org.asteriskjava.manager.action.EventGeneratingAction, SendEventGeneratingActionCallback) + * + * Initial response is passed to one of {@link #onResponse(ManagerResponse)} or + * {@link #onErrorResponse(ManagerResponse)}. but not both. + */ +public interface SendEventGeneratingActionCallback +{ + /** + * Called to notify that + * {@link ManagerConnection#sendEventGeneratingAction(org.asteriskjava.manager.action.EventGeneratingAction, SendEventGeneratingActionCallback)} + * is done. + *

    + * If connection is lost before action is completed then + * {@link ResponseEvents#getResponse()} can be null or list of events might + * be lacking some events including end event. The + * {@link ResponseEvents#getResponse()} can also be {@link ManagerError} + * + * @param responseEvents + * the response at whatever state it was when action ended. + */ + public void onResponse(ResponseEvents responseEvents); +} \ No newline at end of file diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 875500214..6b991fc90 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -51,6 +51,7 @@ import org.asteriskjava.manager.ManagerEventListener; import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.SendActionCallback; +import org.asteriskjava.manager.SendEventGeneratingActionCallback; import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.manager.action.ChallengeAction; import org.asteriskjava.manager.action.CommandAction; @@ -1117,6 +1118,56 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas return responseEvents; } + public void sendEventGeneratingAction( + EventGeneratingAction action, + SendEventGeneratingActionCallback callback) + throws IOException, IllegalArgumentException, IllegalStateException + { + if (action == null) + { + throw new IllegalArgumentException("Unable to send action: action is null."); + } + else if (action.getActionCompleteEventClass() == null) + { + throw new IllegalArgumentException( + "Unable to send action: actionCompleteEventClass for " + action.getClass().getName() + " is null."); + } + else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClass())) + { + throw new IllegalArgumentException( + "Unable to send action: actionCompleteEventClass (" + action.getActionCompleteEventClass().getName() + + ") for " + action.getClass().getName() + " is not a ResponseEvent."); + } + + if (state != CONNECTED) + { + throw new IllegalStateException( + "Actions may only be sent when in state " + "CONNECTED but connection is in state " + state); + } + + final String internalActionId = createInternalActionId(); + + if (callback != null) + { + AsyncEventGeneratingResponseHandler responseEventHandler = new AsyncEventGeneratingResponseHandler( + action.getActionCompleteEventClass(), callback); + + // register response handler... + synchronized (this.responseListeners) + { + this.responseListeners.put(internalActionId, responseEventHandler); + } + + // ...and event handler. + synchronized (this.responseEventListeners) + { + this.responseEventListeners.put(internalActionId, responseEventHandler); + } + } + + writer.sendAction(action, internalActionId); + } + /** * Creates a new unique internal action id based on the hash code of this * connection and a sequence. @@ -1691,6 +1742,79 @@ public void onResponse(ManagerResponse response) } } + private class AsyncEventGeneratingResponseHandler + implements SendActionCallback, ManagerEventListener + { + private final Class actionCompleteEventClass; + private final SendEventGeneratingActionCallback callback; + + private final ResponseEventsImpl events; + + public AsyncEventGeneratingResponseHandler( + Class actionCompleteEventClass, + SendEventGeneratingActionCallback callback) + { + this.actionCompleteEventClass = actionCompleteEventClass; + this.callback = callback; + + this.events = new ResponseEventsImpl(); + } + + @Override + public void onManagerEvent(ManagerEvent event) + { + if (event instanceof DisconnectEvent) + { + callback.onResponse(events); + return; + } + + // should always be a ResponseEvent, anyway... + if (false == (event instanceof ResponseEvent)) + { + return; + } + + ResponseEvent responseEvent = (ResponseEvent)event; + events.addEvent(responseEvent); + + if (actionCompleteEventClass.isAssignableFrom(event.getClass())) + { + events.setComplete(true); + String internalActionId = responseEvent.getInternalActionId(); + synchronized (responseEventListeners) + { + responseEventListeners.remove(internalActionId); + } + callback.onResponse(events); + } + } + + @Override + public void onResponse(ManagerResponse response) + { + // If disconnected + if (response == null) + { + callback.onResponse(events); + return; + } + + events.setRepsonse(response); + if (response instanceof ManagerError) + { + events.setComplete(true); + } + + // finished? + if (events.isComplete()) + { + // invoke callback + callback.onResponse(events); + } + } + } + @Override public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) { From b9c8ae6ef584294ecfbd48f6f80173e7c6b8abe4 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 24 Mar 2020 16:43:41 +1100 Subject: [PATCH 334/802] add pjsip show contacts action and events --- .../action/PJSipShowContactsAction.java | 62 +++++ .../manager/event/ContactList.java | 263 ++++++++++++++++++ .../manager/event/ContactListComplete.java | 89 ++++++ .../manager/event/ContactStatusEnum.java | 7 + .../manager/event/ManagerEvent.java | 2 +- .../manager/event/ResponseEvent.java | 20 +- .../manager/internal/AbstractBuilder.java | 117 +++++--- .../manager/internal/ResponseEventsImpl.java | 6 + 8 files changed, 524 insertions(+), 42 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java create mode 100644 src/main/java/org/asteriskjava/manager/event/ContactList.java create mode 100644 src/main/java/org/asteriskjava/manager/event/ContactListComplete.java create mode 100644 src/main/java/org/asteriskjava/manager/event/ContactStatusEnum.java diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java new file mode 100644 index 000000000..c4948961c --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java @@ -0,0 +1,62 @@ +/* + * 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.manager.action; + +import org.asteriskjava.manager.event.ContactListComplete; +import org.asteriskjava.manager.event.ResponseEvent; + +/** + * Retrieves a list of all defined SIP peers. + *

    + * For each peer that is found a PeerEntryEvent is sent by Asterisk containing + * the details. When all peers have been reported a PeerlistCompleteEvent is + * sent. + *

    + * Available since Asterisk 1.2 Permission required: write=system + * + * @author srt + * @version $Id$ + * @see org.asteriskjava.manager.event.PeerEntryEvent + * @see org.asteriskjava.manager.event.PeerlistCompleteEvent + * @since 0.2 + */ +public class PJSipShowContactsAction extends AbstractManagerAction implements EventGeneratingAction +{ + /** + * Serial version identifier. + */ + private static final long serialVersionUID = 921037572305993779L; + + /** + * Creates a new SipPeersAction. + */ + public PJSipShowContactsAction() + { + + } + + @Override + public String getAction() + { + return "PJSIPShowContacts"; + } + + public Class< ? extends ResponseEvent> getActionCompleteEventClass() + { + return ContactListComplete.class; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/ContactList.java b/src/main/java/org/asteriskjava/manager/event/ContactList.java new file mode 100644 index 000000000..02d0f622b --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/ContactList.java @@ -0,0 +1,263 @@ +/* + * 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.manager.event; + +/** + * A ContactListCompleteEvent is triggered after the details of all peers has + * been reported in response to an PJSipShowContactsAction. + *

    + * Available since Asterisk 16? + * + * @author srt + * @version $Id$ + * @since 3.0 + */ +public class ContactList extends ResponseEvent +{ + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -1177773673509373296L; + + Double qualifyTimeout; + String callid; + String regserver; + Long roundtripusec; + Long expirationtime; + String authenticatequalify; + String objectname; + String useragent; + String uri; + String viaaddr; + Long qualifyfrequency; + String path; + String endpoint; + String viaport; + String outboundproxy; + + String objecttype; + String pruneonboot; + ContactStatusEnum status; + + /** + * Creates a new instance. + * + * @param source + */ + public ContactList(Object source) + { + super(source); + } + + public double getQualifyTimeout() + { + return qualifyTimeout; + } + + public void setQualifyTimeout(double qualifyTimeout) + { + this.qualifyTimeout = qualifyTimeout; + } + + public String getCallid() + { + return callid; + } + + public void setCallid(String callid) + { + this.callid = callid; + } + + public String getRegserver() + { + return regserver; + } + + public void setRegserver(String regserver) + { + this.regserver = regserver; + } + + public long getRoundtripusec() + { + return roundtripusec; + } + + public void setRoundtripusec(long roundtripusec) + { + this.roundtripusec = roundtripusec; + } + + public long getExpirationtime() + { + return expirationtime; + } + + public void setExpirationtime(long expirationtime) + { + this.expirationtime = expirationtime; + } + + public String getAuthenticatequalify() + { + return authenticatequalify; + } + + public void setAuthenticatequalify(String authenticatequalify) + { + this.authenticatequalify = authenticatequalify; + } + + public String getObjectname() + { + return objectname; + } + + public void setObjectname(String objectname) + { + this.objectname = objectname; + } + + public String getUseragent() + { + return useragent; + } + + public void setUseragent(String useragent) + { + this.useragent = useragent; + } + + public String getUri() + { + return uri; + } + + public void setUri(String uri) + { + this.uri = uri; + } + + public String getViaaddr() + { + return viaaddr; + } + + public void setViaaddr(String viaaddr) + { + this.viaaddr = viaaddr; + } + + public long getQualifyfrequency() + { + return qualifyfrequency; + } + + public void setQualifyfrequency(Long qualifyfrequency) + { + this.qualifyfrequency = qualifyfrequency; + } + + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + public String getEndpoint() + { + return endpoint; + } + + public void setEndpoint(String endpoint) + { + this.endpoint = endpoint; + } + + public String getViaport() + { + return viaport; + } + + public void setViaport(String viaport) + { + this.viaport = viaport; + } + + public String getOutboundproxy() + { + return outboundproxy; + } + + public void setOutboundproxy(String outboundproxy) + { + this.outboundproxy = outboundproxy; + } + + public String getObjecttype() + { + return objecttype; + } + + public void setObjecttype(String objecttype) + { + this.objecttype = objecttype; + } + + public String getPruneonboot() + { + return pruneonboot; + } + + public void setPruneonboot(String pruneonboot) + { + this.pruneonboot = pruneonboot; + } + + public ContactStatusEnum getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = ContactStatusEnum.UNKNOWN; + + if (status != null && status.length() > 0) + { + this.status = ContactStatusEnum.valueOf(status.toUpperCase()); + } + + } + + @Override + public String toString() + { + return "ContactList [qualifyTimeout=" + qualifyTimeout + ", callid=" + callid + ", regserver=" + regserver + + ", roundtripusec=" + roundtripusec + ", expirationtime=" + expirationtime + ", authenticatequalify=" + + authenticatequalify + ", objectname=" + objectname + ", useragent=" + useragent + ", uri=" + uri + + ", viaaddr=" + viaaddr + ", qualifyfrequency=" + qualifyfrequency + ", path=" + path + ", endpoint=" + + endpoint + ", viaport=" + viaport + ", outboundproxy=" + outboundproxy + ", actionId=" + actionId + + ", objecttype=" + objecttype + ", pruneonboot=" + pruneonboot + ", status=" + status + "]\n"; + } + +} diff --git a/src/main/java/org/asteriskjava/manager/event/ContactListComplete.java b/src/main/java/org/asteriskjava/manager/event/ContactListComplete.java new file mode 100644 index 000000000..08cea4cdb --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/ContactListComplete.java @@ -0,0 +1,89 @@ +/* + * 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.manager.event; + +/** + * A PeerlistCompleteEvent is triggered after the details of all peers has been + * reported in response to an SIPPeersAction or SIPShowPeerAction. + *

    + * Available since Asterisk 1.2 + * + * @see org.asteriskjava.manager.event.PeerEntryEvent + * @see org.asteriskjava.manager.action.SipPeersAction + * @see org.asteriskjava.manager.action.SipShowPeerAction + * @author srt + * @version $Id$ + * @since 0.2 + */ +public class ContactListComplete extends ResponseEvent +{ + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -1177773673509373296L; + private Integer listItems; + private String eventList; + + /** + * Creates a new instance. + * + * @param source + */ + public ContactListComplete(Object source) + { + super(source); + } + + /** + * Returns the number of PeerEvents that have been reported. + * + * @return the number of PeerEvents that have been reported. + */ + public Integer getListItems() + { + return listItems; + } + + /** + * Sets the number of PeerEvents that have been reported. + * + * @param listItems the number of PeerEvents that have been reported. + */ + public void setListItems(Integer listItems) + { + this.listItems = listItems; + } + + /** + * Returns always "Complete". + *

    + * Available since Asterisk 1.6. + * + * @return always returns "Complete" confirming that all PeerEntry events + * have been sent. + * @since 1.0.0 + */ + public String getEventList() + { + return eventList; + } + + public void setEventList(String eventList) + { + this.eventList = eventList; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/ContactStatusEnum.java b/src/main/java/org/asteriskjava/manager/event/ContactStatusEnum.java new file mode 100644 index 000000000..c7d421529 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/ContactStatusEnum.java @@ -0,0 +1,7 @@ +package org.asteriskjava.manager.event; + +public enum ContactStatusEnum +{ + REACHABLE, UNREACHABLE, NONQUALIFIED, UNKNOWN + +} diff --git a/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java b/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java index 3fa1af486..58e7f654b 100644 --- a/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java @@ -31,7 +31,7 @@ * server.
    * Events contain data pertaining to an event generated from within the Asterisk * core or an extension module.
    - * There is one conrete subclass of ManagerEvent per each supported Asterisk + * There is one concrete subclass of ManagerEvent per each supported Asterisk * Event. * * @author srt diff --git a/src/main/java/org/asteriskjava/manager/event/ResponseEvent.java b/src/main/java/org/asteriskjava/manager/event/ResponseEvent.java index f979e0d61..13184eaa7 100644 --- a/src/main/java/org/asteriskjava/manager/event/ResponseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ResponseEvent.java @@ -17,7 +17,8 @@ package org.asteriskjava.manager.event; /** - * Abstract base class for events triggered in response to a ManagerAction.

    + * Abstract base class for events triggered in response to a ManagerAction. + *

    * All ResponseEvents contain an additional action id property that links the * event to the action that caused it. * @@ -27,8 +28,8 @@ */ public abstract class ResponseEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; - private String actionId; + private static final long serialVersionUID = 1L; + protected String actionId; private String internalActionId; public ResponseEvent(Object source) @@ -37,9 +38,9 @@ public ResponseEvent(Object source) } /** - * Returns the user provided action id of the ManagerAction that caused - * this event. If the application did not set an action id this method - * returns null. + * Returns the user provided action id of the ManagerAction that caused this + * event. If the application did not set an action id this method returns + * null. * * @return the action id of the ManagerAction that caused this event or * null if none was set. @@ -54,7 +55,7 @@ public final String getActionId() * Sets the action id of the ManagerAction that caused this event. * * @param actionId the action id of the ManagerAction that caused this - * event. + * event. */ public final void setActionId(String actionId) { @@ -63,7 +64,8 @@ public final void setActionId(String actionId) /** * Returns the internal action id of the ManagerAction that caused this - * event.

    + * event. + *

    * Warning: This method is internal to Asterisk-Java and should never be * used in application code. * @@ -80,7 +82,7 @@ public final String getInternalActionId() * Sets the internal action id of the ManagerAction that caused this event. * * @param internalActionId the internal action id of the ManagerAction that - * caused this event. + * caused this event. * @since 0.2 */ public final void setInternalActionId(String internalActionId) diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index 58406dc82..fe36148b9 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -22,7 +22,6 @@ abstract class AbstractBuilder { protected final Log logger = LogFactory.getLog(getClass()); - @SuppressWarnings("unchecked") protected void setAttributes(Object target, Map attributes, Set ignoredAttributes) { Map setters; @@ -96,40 +95,19 @@ else if ("class".equals(setterName)) } else if (dataType.isAssignableFrom(String.class)) { - value = entry.getValue(); - if (AstUtil.isNull(value)) - { - - value = null; - } - if (value instanceof List) - { - StringBuilder strBuff = new StringBuilder(); - for (String tmp : (List) value) - { - if (tmp != null && tmp.length() != 0) - { - strBuff.append(tmp).append('\n'); - } - } - value = strBuff.toString(); - } + value = parseString(entry); } else if (dataType.isAssignableFrom(Map.class)) { - if (entry.getValue() instanceof List) - { - List list = (List) entry.getValue(); - value = buildMap(list.toArray(new String[list.size()])); - } - else if (entry.getValue() instanceof String) - { - value = buildMap((String) entry.getValue()); - } - else - { - value = null; - } + value = parseMap(entry); + } + else if (dataType.isAssignableFrom(double.class) || dataType.isAssignableFrom(Double.class)) + { + value = parseDouble(entry); + } + else if (dataType.isAssignableFrom(long.class) || dataType.isAssignableFrom(Long.class)) + { + value = parseLong(entry); } else { @@ -159,6 +137,81 @@ else if (entry.getValue() instanceof String) } } + @SuppressWarnings("unchecked") + private Map parseMap(Map.Entry entry) + { + Map value; + if (entry.getValue() instanceof List) + { + List list = (List) entry.getValue(); + value = buildMap(list.toArray(new String[list.size()])); + } + else if (entry.getValue() instanceof String) + { + value = buildMap((String) entry.getValue()); + } + else + { + value = null; + } + return value; + } + + @SuppressWarnings("unchecked") + private Object parseString(Map.Entry entry) + { + Object value; + value = entry.getValue(); + if (AstUtil.isNull(value)) + { + + value = null; + } + if (value instanceof List) + { + StringBuilder strBuff = new StringBuilder(); + for (String tmp : (List) value) + { + if (tmp != null && tmp.length() != 0) + { + strBuff.append(tmp).append('\n'); + } + } + value = strBuff.toString(); + } + return value; + } + + private Double parseDouble(Map.Entry entry) + { + Double value; + String stringValue = (String) entry.getValue(); + if (stringValue != null && stringValue.length() > 0) + { + value = Double.parseDouble(stringValue); + } + else + { + value = null; + } + return value; + } + + private Long parseLong(Map.Entry entry) + { + Long value; + String stringValue = (String) entry.getValue(); + if (stringValue != null && stringValue.length() > 0) + { + value = Long.parseLong(stringValue); + } + else + { + value = null; + } + return value; + } + private Map buildMap(String... lines) { if (lines == null) diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java index 8d056cc2c..664b64547 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java @@ -114,4 +114,10 @@ public void countDown() { latch.countDown(); } + + @Override + public String toString() + { + return "ResponseEventsImpl [response=" + response + ",\nevents=" + events + ",\ncomplete=" + complete + "]"; + } } From 3fedf00419e7ea11cf0f00501e669725200e19d8 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 24 Mar 2020 16:44:30 +1100 Subject: [PATCH 335/802] for version 3.1.1-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ae242b34d..86699e344 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.1.0 + 3.1.1-SNAPSHOT UTF-8 From df4bd3f8383f4b9f4d5dcb1cecbcd770ece1d452 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 25 Mar 2020 15:30:34 +1100 Subject: [PATCH 336/802] for version 3.1.2-SNAPSHOT --- pom.xml | 2 +- .../manager/event/BlindTransferEvent.java | 575 +++++++++--------- .../manager/event/QueueMemberStatusEvent.java | 11 + .../manager/internal/AbstractBuilder.java | 70 +-- 4 files changed, 339 insertions(+), 319 deletions(-) diff --git a/pom.xml b/pom.xml index 86699e344..76eaba400 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.1.1-SNAPSHOT + 3.1.2-SNAPSHOT UTF-8 diff --git a/src/main/java/org/asteriskjava/manager/event/BlindTransferEvent.java b/src/main/java/org/asteriskjava/manager/event/BlindTransferEvent.java index 91a2a6040..c5da2e206 100644 --- a/src/main/java/org/asteriskjava/manager/event/BlindTransferEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BlindTransferEvent.java @@ -5,289 +5,289 @@ */ public class BlindTransferEvent extends AbstractBridgeEvent { - /** - * - */ - private static final long serialVersionUID = 1L; - private String transfererUniqueId; - private String transfererConnectedLineNum; - private String transfererConnectedLineName; - private String transfererCallerIdName; - private String transfererCallerIdNum; - private String transfererChannel; - private String transfererChannelState; - private String transfererChannelStateDesc; - private Integer transfererPriority; - private String transfererContext; - - private String transfereeUniqueId; - private String transfereeConnectedLineNum; - private String transfereeConnectedLineName; - private String transfereeCallerIdName; - private String transfereeCallerIdNum; - private String transfereeChannel; - private String transfereeChannelState; - private String transfereeChannelStateDesc; - private Integer transfereePriority; - private String transfereeContext; - private String transfereeExten; - - private String extension; - private String isexternal; - private String result; - - private String transfereeLinkedId; - private String transfererAccountCode; - private String transfererExten; - private String transfererLanguage; - private String transfererLinkedId; + /** + * + */ + private static final long serialVersionUID = 1L; + private String transfererUniqueId; + private String transfererConnectedLineNum; + private String transfererConnectedLineName; + private String transfererCallerIdName; + private String transfererCallerIdNum; + private String transfererChannel; + private String transfererChannelState; + private String transfererChannelStateDesc; + private Integer transfererPriority; + private String transfererContext; + + private String transfereeUniqueId; + private String transfereeConnectedLineNum; + private String transfereeConnectedLineName; + private String transfereeCallerIdName; + private String transfereeCallerIdNum; + private String transfereeChannel; + private String transfereeChannelState; + private String transfereeChannelStateDesc; + private Integer transfereePriority; + private String transfereeContext; + private String transfereeExten; + + private String extension; + private String isexternal; + private String result; + + private String transfereeLinkedId; + private String transfererAccountCode; + private String transfererExten; + private String transfererLanguage; + private String transfererLinkedId; private String transfereeLanguage; + private String transfereeaccountcode; - - public BlindTransferEvent(Object source) - { - super(source); - } - - public String getTransfererUniqueId() - { - return transfererUniqueId; - } - - public void setTransfererUniqueId(String transfererUniqueId) - { - this.transfererUniqueId = transfererUniqueId; - } - - public String getTransfererConnectedLineNum() - { - return transfererConnectedLineNum; - } - - public void setTransfererConnectedLineNum(String transfererConnectedLineNum) - { - this.transfererConnectedLineNum = transfererConnectedLineNum; - } - - public String getTransfererConnectedLineName() - { - return transfererConnectedLineName; - } - - public void setTransfererConnectedLineName(String transfererConnectedLineName) - { - this.transfererConnectedLineName = transfererConnectedLineName; - } - - public String getTransfererCallerIdName() - { - return transfererCallerIdName; - } - - public void setTransfererCallerIdName(String transfererCallerIdName) - { - this.transfererCallerIdName = transfererCallerIdName; - } - - public String getTransfererCallerIdNum() - { - return transfererCallerIdNum; - } - - public void setTransfererCallerIdNum(String transfererCallerIdNum) - { - this.transfererCallerIdNum = transfererCallerIdNum; - } - - public String getTransfererChannel() - { - return transfererChannel; - } - - public void setTransfererChannel(String transfererChannel) - { - this.transfererChannel = transfererChannel; - } - - public String getTransfererChannelState() - { - return transfererChannelState; - } - - public void setTransfererChannelState(String transfererChannelState) - { - this.transfererChannelState = transfererChannelState; - } - - public String getTransfererChannelStateDesc() - { - return transfererChannelStateDesc; - } - - public void setTransfererChannelStateDesc(String transfererChannelStateDesc) - { - this.transfererChannelStateDesc = transfererChannelStateDesc; - } - - public Integer getTransfererPriority() - { - return transfererPriority; - } - - public void setTransfererPriority(Integer transfererPriority) - { - this.transfererPriority = transfererPriority; - } - - public String getTransfererContext() - { - return transfererContext; - } - - public void setTransfererContext(String transfererContext) - { - this.transfererContext = transfererContext; - } - - public String getTransfereeUniqueId() - { - return transfereeUniqueId; - } - - public void setTransfereeUniqueId(String transfereeUniqueId) - { - this.transfereeUniqueId = transfereeUniqueId; - } - - public String getTransfereeConnectedLineNum() - { - return transfereeConnectedLineNum; - } - - public void setTransfereeConnectedLineNum(String transfereeConnectedLineNum) - { - this.transfereeConnectedLineNum = transfereeConnectedLineNum; - } - - public String getTransfereeConnectedLineName() - { - return transfereeConnectedLineName; - } - - public void setTransfereeConnectedLineName(String transfereeConnectedLineName) - { - this.transfereeConnectedLineName = transfereeConnectedLineName; - } - - public String getTransfereeCallerIdName() - { - return transfereeCallerIdName; - } - - public void setTransfereeCallerIdName(String transfereeCallerIdName) - { - this.transfereeCallerIdName = transfereeCallerIdName; - } - - public String getTransfereeCallerIdNum() - { - return transfereeCallerIdNum; - } - - public void setTransfereeCallerIdNum(String transfereeCallerIdNum) - { - this.transfereeCallerIdNum = transfereeCallerIdNum; - } - - public String getTransfereeChannel() - { - return transfereeChannel; - } - - public void setTransfereeChannel(String transfereeChannel) - { - this.transfereeChannel = transfereeChannel; - } - - public String getTransfereeChannelState() - { - return transfereeChannelState; - } - - public void setTransfereeChannelState(String transfereeChannelState) - { - this.transfereeChannelState = transfereeChannelState; - } - - public String getTransfereeChannelStateDesc() - { - return transfereeChannelStateDesc; - } - - public void setTransfereeChannelStateDesc(String transfereeChannelStateDesc) - { - this.transfereeChannelStateDesc = transfereeChannelStateDesc; - } - - public Integer getTransfereePriority() - { - return transfereePriority; - } - - public void setTransfereePriority(Integer transfereePriority) - { - this.transfereePriority = transfereePriority; - } - - public String getTransfereeContext() - { - return transfereeContext; - } - - public void setTransfereeContext(String transfereeContext) - { - this.transfereeContext = transfereeContext; - } - - public String getExtension() - { - return extension; - } - - public void setExtension(String extension) - { - this.extension = extension; - } - - public String getIsexternal() - { - return isexternal; - } - - public void setIsexternal(String isexternal) - { - this.isexternal = isexternal; - } - - public String getResult() - { - return result; - } - - public void setResult(String result) - { - this.result = result; - } - - public String getTransfereeExten() - { - return transfereeExten; - } - - public void setTransfereeExten(String transfereeExten) - { - this.transfereeExten = transfereeExten; - } + public BlindTransferEvent(Object source) + { + super(source); + } + + public String getTransfererUniqueId() + { + return transfererUniqueId; + } + + public void setTransfererUniqueId(String transfererUniqueId) + { + this.transfererUniqueId = transfererUniqueId; + } + + public String getTransfererConnectedLineNum() + { + return transfererConnectedLineNum; + } + + public void setTransfererConnectedLineNum(String transfererConnectedLineNum) + { + this.transfererConnectedLineNum = transfererConnectedLineNum; + } + + public String getTransfererConnectedLineName() + { + return transfererConnectedLineName; + } + + public void setTransfererConnectedLineName(String transfererConnectedLineName) + { + this.transfererConnectedLineName = transfererConnectedLineName; + } + + public String getTransfererCallerIdName() + { + return transfererCallerIdName; + } + + public void setTransfererCallerIdName(String transfererCallerIdName) + { + this.transfererCallerIdName = transfererCallerIdName; + } + + public String getTransfererCallerIdNum() + { + return transfererCallerIdNum; + } + + public void setTransfererCallerIdNum(String transfererCallerIdNum) + { + this.transfererCallerIdNum = transfererCallerIdNum; + } + + public String getTransfererChannel() + { + return transfererChannel; + } + + public void setTransfererChannel(String transfererChannel) + { + this.transfererChannel = transfererChannel; + } + + public String getTransfererChannelState() + { + return transfererChannelState; + } + + public void setTransfererChannelState(String transfererChannelState) + { + this.transfererChannelState = transfererChannelState; + } + + public String getTransfererChannelStateDesc() + { + return transfererChannelStateDesc; + } + + public void setTransfererChannelStateDesc(String transfererChannelStateDesc) + { + this.transfererChannelStateDesc = transfererChannelStateDesc; + } + + public Integer getTransfererPriority() + { + return transfererPriority; + } + + public void setTransfererPriority(Integer transfererPriority) + { + this.transfererPriority = transfererPriority; + } + + public String getTransfererContext() + { + return transfererContext; + } + + public void setTransfererContext(String transfererContext) + { + this.transfererContext = transfererContext; + } + + public String getTransfereeUniqueId() + { + return transfereeUniqueId; + } + + public void setTransfereeUniqueId(String transfereeUniqueId) + { + this.transfereeUniqueId = transfereeUniqueId; + } + + public String getTransfereeConnectedLineNum() + { + return transfereeConnectedLineNum; + } + + public void setTransfereeConnectedLineNum(String transfereeConnectedLineNum) + { + this.transfereeConnectedLineNum = transfereeConnectedLineNum; + } + + public String getTransfereeConnectedLineName() + { + return transfereeConnectedLineName; + } + + public void setTransfereeConnectedLineName(String transfereeConnectedLineName) + { + this.transfereeConnectedLineName = transfereeConnectedLineName; + } + + public String getTransfereeCallerIdName() + { + return transfereeCallerIdName; + } + + public void setTransfereeCallerIdName(String transfereeCallerIdName) + { + this.transfereeCallerIdName = transfereeCallerIdName; + } + + public String getTransfereeCallerIdNum() + { + return transfereeCallerIdNum; + } + + public void setTransfereeCallerIdNum(String transfereeCallerIdNum) + { + this.transfereeCallerIdNum = transfereeCallerIdNum; + } + + public String getTransfereeChannel() + { + return transfereeChannel; + } + + public void setTransfereeChannel(String transfereeChannel) + { + this.transfereeChannel = transfereeChannel; + } + + public String getTransfereeChannelState() + { + return transfereeChannelState; + } + + public void setTransfereeChannelState(String transfereeChannelState) + { + this.transfereeChannelState = transfereeChannelState; + } + + public String getTransfereeChannelStateDesc() + { + return transfereeChannelStateDesc; + } + + public void setTransfereeChannelStateDesc(String transfereeChannelStateDesc) + { + this.transfereeChannelStateDesc = transfereeChannelStateDesc; + } + + public Integer getTransfereePriority() + { + return transfereePriority; + } + + public void setTransfereePriority(Integer transfereePriority) + { + this.transfereePriority = transfereePriority; + } + + public String getTransfereeContext() + { + return transfereeContext; + } + + public void setTransfereeContext(String transfereeContext) + { + this.transfereeContext = transfereeContext; + } + + public String getExtension() + { + return extension; + } + + public void setExtension(String extension) + { + this.extension = extension; + } + + public String getIsexternal() + { + return isexternal; + } + + public void setIsexternal(String isexternal) + { + this.isexternal = isexternal; + } + + public String getResult() + { + return result; + } + + public void setResult(String result) + { + this.result = result; + } + + public String getTransfereeExten() + { + return transfereeExten; + } + + public void setTransfereeExten(String transfereeExten) + { + this.transfereeExten = transfereeExten; + } public String getTransfereeLinkedId() { @@ -348,6 +348,15 @@ public void setTransfereeLanguage(String transfereeLanguage) { this.transfereeLanguage = transfereeLanguage; } - - + + public void setTransfereeaccountcode(String transfereeaccountcode) + { + this.transfereeaccountcode = transfereeaccountcode; + } + + public String getTransfereeaccountcode() + { + return transfereeaccountcode; + } + } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java index a57865cdc..f70dd6b67 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java @@ -30,6 +30,7 @@ public class QueueMemberStatusEvent extends QueueMemberEvent private static final long serialVersionUID = -2293926744791895763L; private String ringinuse; + private Integer wrapuptime; /** * @param source @@ -54,4 +55,14 @@ public void setRinginuse(String ringinuse) { this.ringinuse = ringinuse; } + + public Integer getWrapuptime() + { + return wrapuptime; + } + + public void setWrapuptime(Integer wrapuptime) + { + this.wrapuptime = wrapuptime; + } } diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index fe36148b9..531e41a18 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -87,52 +87,52 @@ else if ("class".equals(setterName)) continue; } - dataType = setter.getParameterTypes()[0]; - - if (dataType == Boolean.class) - { - value = AstUtil.isTrue(entry.getValue()); - } - else if (dataType.isAssignableFrom(String.class)) - { - value = parseString(entry); - } - else if (dataType.isAssignableFrom(Map.class)) - { - value = parseMap(entry); - } - else if (dataType.isAssignableFrom(double.class) || dataType.isAssignableFrom(Double.class)) - { - value = parseDouble(entry); - } - else if (dataType.isAssignableFrom(long.class) || dataType.isAssignableFrom(Long.class)) - { - value = parseLong(entry); - } - else + try { - try + dataType = setter.getParameterTypes()[0]; + + if (dataType == Boolean.class) { - Constructor< ? > constructor = dataType.getConstructor(String.class); - value = constructor.newInstance(entry.getValue()); + value = AstUtil.isTrue(entry.getValue()); } - catch (Exception e) + else if (dataType.isAssignableFrom(String.class)) { - logger.error("Unable to convert value: Called the constructor of " + dataType + " with value '" - + entry.getValue() + "' for the attribute '" + entry.getKey() + "'\n of event type " - + target.getClass().getName() + " with resulting error: " + e.getMessage(), e); - continue; + value = parseString(entry); + } + else if (dataType.isAssignableFrom(Map.class)) + { + value = parseMap(entry); + } + else if (dataType.isAssignableFrom(double.class) || dataType.isAssignableFrom(Double.class)) + { + value = parseDouble(entry); + } + else if (dataType.isAssignableFrom(long.class) || dataType.isAssignableFrom(Long.class)) + { + value = parseLong(entry); + } + else + { + try + { + Constructor< ? > constructor = dataType.getConstructor(String.class); + value = constructor.newInstance(entry.getValue()); + } + catch (Exception e) + { + logger.error("Unable to convert value: Called the constructor of " + dataType + " with value '" + + entry.getValue() + "' for the attribute '" + entry.getKey() + "'\n of event type " + + target.getClass().getName() + " with resulting error: " + e.getMessage(), e); + continue; + } } - } - try - { setter.invoke(target, value); } catch (Exception e) { logger.error("Unable to set property '" + entry.getKey() + "' to '" + entry.getValue() + "' on " - + target.getClass().getName(), e); + + target.getClass().getName() + " " + e.getMessage(), e); } } } From e1adc5c987e0ff4d07a23816e348ef7f361b20d2 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 26 Mar 2020 10:28:16 +1100 Subject: [PATCH 337/802] fix for string value --- .../java/org/asteriskjava/manager/event/ContactList.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/ContactList.java b/src/main/java/org/asteriskjava/manager/event/ContactList.java index 02d0f622b..752597af6 100644 --- a/src/main/java/org/asteriskjava/manager/event/ContactList.java +++ b/src/main/java/org/asteriskjava/manager/event/ContactList.java @@ -36,7 +36,10 @@ public class ContactList extends ResponseEvent Double qualifyTimeout; String callid; String regserver; - Long roundtripusec; + + // roundtripusec when it contains a value is a long, but when it doesn't + // asterisk reports "N/A" + String roundtripusec; Long expirationtime; String authenticatequalify; String objectname; @@ -93,12 +96,12 @@ public void setRegserver(String regserver) this.regserver = regserver; } - public long getRoundtripusec() + public String getRoundtripusec() { return roundtripusec; } - public void setRoundtripusec(long roundtripusec) + public void setRoundtripusec(String roundtripusec) { this.roundtripusec = roundtripusec; } From 1e26949b8fcaff9d88dd0a432ba4d098fc11406d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 26 Mar 2020 10:28:53 +1100 Subject: [PATCH 338/802] for version 3.1.3-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 76eaba400..d8cb0d258 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.1.2-SNAPSHOT + 3.1.3-SNAPSHOT UTF-8 From 43115f8c4ed03700d3c1210f44417d339d5c076d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 6 Apr 2020 09:11:32 +1000 Subject: [PATCH 339/802] fix to pass channel vars through --- .../pbx/internal/core/AsteriskPBX.java | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index bf3557ef0..3d0a28d03 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -868,13 +868,13 @@ public ChannelProxy getProxyById(String id) } public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, AgiChannelActivityAction action, - ActivityCallback iCallback) + ActivityCallback iCallback, Map channelVarsToSet) { final CompletionAdaptor completion = new CompletionAdaptor<>(); - final DialToAgiActivityImpl dialer = new DialToAgiActivityImpl(endPoint, callerID, null, false, completion, null, - action); + final DialToAgiActivityImpl dialer = new DialToAgiActivityImpl(endPoint, callerID, null, false, completion, + channelVarsToSet, action); dialer.startActivity(false); @@ -948,26 +948,29 @@ public boolean createAgiEntryPoint() throws IOException, AuthenticationFailedExc } - public boolean checkDialplanExists(String dialPlan, String context) throws IOException, TimeoutException { - String command; + public boolean checkDialplanExists(String dialPlan, String context) throws IOException, TimeoutException + { + String command; - if (getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) { - // TODO: Use ShowDialplanAction instead of CommandAction? - command = "dialplan show " + context; - } - else - { - command = "show dialplan " + context; - } + if (getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) + { + // TODO: Use ShowDialplanAction instead of CommandAction? + command = "dialplan show " + context; + } + else + { + command = "show dialplan " + context; + } - CommandAction action = new CommandAction(command); - CommandResponse response = (CommandResponse) sendAction(action, 30000); + CommandAction action = new CommandAction(command); + CommandResponse response = (CommandResponse) sendAction(action, 30000); - return response.getResult().stream().anyMatch(line -> line.contains(dialPlan)); - } + return response.getResult().stream().anyMatch(line -> line.contains(dialPlan)); + } public boolean checkDialplanExists(AsteriskSettings profile) - throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException { + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException + { return checkDialplanExists(ACTIVITY_AGI, profile.getManagementContext()); } @@ -983,8 +986,9 @@ public String addAsteriskExtension(String extNumber, int priority, String comman List line = response.getResult(); String tmp = "Extension '" + extNumber + "," + priority + ","; - if (line.stream().anyMatch(answer -> answer.substring(0, tmp.length()).compareToIgnoreCase(tmp) == 0)) { - return "OK"; + if (line.stream().anyMatch(answer -> answer.substring(0, tmp.length()).compareToIgnoreCase(tmp) == 0)) + { + return "OK"; } throw new Exception("InitiateAction.AddExtentionFailed" + ext); From 2b2ddd256805c1c9debc71f0e91568385f8a5811 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 6 Apr 2020 09:30:42 +1000 Subject: [PATCH 340/802] for version 3.1.4-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d8cb0d258..ef72686f1 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.1.3-SNAPSHOT + 3.1.4-SNAPSHOT UTF-8 From acb034b3bd37720fee706c67a276f44a9bab663d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 6 Apr 2020 09:32:39 +1000 Subject: [PATCH 341/802] for version 3.2.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ef72686f1..99a5dc67f 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.1.4-SNAPSHOT + 3.2.0 UTF-8 From 41e85c8b519e79619f0b829068f958808cfc0638 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 6 Apr 2020 12:18:16 +1000 Subject: [PATCH 342/802] add dial options to blind transfer activity --- .../examples/activities/BlindTransfer.java | 27 ++++++++++--------- src/main/java/org/asteriskjava/pbx/PBX.java | 4 +-- .../agi/AgiChannelActivityBlindTransfer.java | 6 +++-- .../activity/BlindTransferActivityImpl.java | 10 ++++--- .../pbx/internal/core/AsteriskPBX.java | 15 ++++++----- 5 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java index 8948437de..e70fb5328 100644 --- a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java +++ b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java @@ -28,19 +28,20 @@ public class BlindTransfer static public void main(String[] args) throws IOException, AuthenticationFailedException, TimeoutException { - /** - * Initialise the PBX Factory. You need to implement your own AsteriskSettings class. - */ + /** + * Initialise the PBX Factory. You need to implement your own + * AsteriskSettings class. + */ PBXFactory.init(new ExamplesAsteriskSettings()); - + /** - * Activities utilise an agi entry point in your dial plan. - * You can create your own entry point in dialplan or have - * asterisk-java add it automatically + * Activities utilise an agi entry point in your dial plan. You can + * create your own entry point in dialplan or have asterisk-java add it + * automatically */ AsteriskPBX asteriskPbx = (AsteriskPBX) PBXFactory.getActivePBX(); asteriskPbx.createAgiEntryPoint(); - + // We are all configured lets try and do a blind transfer. blindTransfer(); } @@ -48,9 +49,10 @@ static public void main(String[] args) throws IOException, AuthenticationFailedE static private void blindTransfer() { PBX pbx = PBXFactory.getActivePBX(); - + // The trunk MUST match the section header (e.g. [default]) that appears - // in your /etc/asterisk/sip.d file (assuming you are using a SIP trunk). + // in your /etc/asterisk/sip.d file (assuming you are using a SIP + // trunk). // The trunk is used to select which SIP trunk to dial through. Trunk trunk = pbx.buildTrunk("default"); @@ -85,11 +87,12 @@ public void progress(DialActivity activity, ActivityStatusEnum status, String me { @Override - public void progress(BlindTransferActivity activity, ActivityStatusEnum status, String message) + public void progress(BlindTransferActivity activity, ActivityStatusEnum status, + String message) { // if success the blind transfer completed. } - }); + }, ""); } if (status == ActivityStatusEnum.FAILURE) System.out.println("Oops something bad happened when we dialed."); diff --git a/src/main/java/org/asteriskjava/pbx/PBX.java b/src/main/java/org/asteriskjava/pbx/PBX.java index d46a275cc..1986bb1e4 100644 --- a/src/main/java/org/asteriskjava/pbx/PBX.java +++ b/src/main/java/org/asteriskjava/pbx/PBX.java @@ -52,7 +52,7 @@ public interface PBX * @param ActivityCallback */ BlindTransferActivity blindTransfer(final Call call, OperandChannel channelToTransfer, final EndPoint transferTarget, - final CallerID toCallerID, boolean autoAnswer, long timeout); + final CallerID toCallerID, boolean autoAnswer, long timeout, String dialOptions); /** * The BlindTransferActivity is used by the AsteriksPBX to transfer a live @@ -73,7 +73,7 @@ BlindTransferActivity blindTransfer(final Call call, OperandChannel channelToTra * is reached the Blind Transfer will be cancelled. */ void blindTransfer(Call call, OperandChannel channelToTransfer, final EndPoint transferTarget, final CallerID toCallerID, - boolean autoAnswer, long timeout, ActivityCallback callback); + boolean autoAnswer, long timeout, ActivityCallback callback, String dialOptions); /** * Sends a DTMF tone to given channel. Not returning until the tone has been diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java index 156433cd2..c942c52aa 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java @@ -15,12 +15,14 @@ public class AgiChannelActivityBlindTransfer implements AgiChannelActivityAction private String sipHeader; int timeout = 30; private String callerId; + private String dialOptions; - public AgiChannelActivityBlindTransfer(String fullyQualifiedName, String sipHeader, String callerId) + public AgiChannelActivityBlindTransfer(String fullyQualifiedName, String sipHeader, String callerId, String dialOptions) { this.target = fullyQualifiedName; this.sipHeader = sipHeader; this.callerId = callerId; + this.dialOptions = dialOptions; if (sipHeader == null) { this.sipHeader = ""; @@ -34,7 +36,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I channel.setVariable("__SIPADDHEADER", sipHeader); channel.setCallerId(callerId); ichannel.setCurrentActivityAction(new AgiChannelActivityHold()); - channel.dial(target, timeout, ""); + channel.dial(target, timeout, dialOptions); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index 058a619ee..a224c4ec6 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -65,6 +65,8 @@ public class BlindTransferActivityImpl extends ActivityHelper listener) + final ActivityCallback listener, String dialOptions) { super("BlindTransferActivity", listener); @@ -88,6 +90,7 @@ public BlindTransferActivityImpl(Call call, final Call.OperandChannel channelToT this._toCallerID = toCallerID; this._autoAnswer = autoAnswer; this._timeout = timeout; + this.dialOptions = dialOptions; actualChannelToTransfer = _call.getOperandChannel(this._channelToTransfer); @@ -95,7 +98,7 @@ public BlindTransferActivityImpl(Call call, final Call.OperandChannel channelToT } public BlindTransferActivityImpl(Channel agentChannel, EndPoint transferTarget, CallerID toCallerID, boolean autoAnswer, - int timeout, ActivityCallback iCallback) throws PBXException + int timeout, ActivityCallback iCallback, String dialOptions) throws PBXException { super("BlindTransferActivity", iCallback); @@ -104,6 +107,7 @@ public BlindTransferActivityImpl(Channel agentChannel, EndPoint transferTarget, this._autoAnswer = autoAnswer; this._timeout = timeout; actualChannelToTransfer = agentChannel; + this.dialOptions = dialOptions; _channelToTransfer = OperandChannel.ORIGINATING_PARTY; this._call = new CallImpl(agentChannel, CallDirection.OUTBOUND); this.startActivity(true); @@ -150,7 +154,7 @@ public boolean doActivity() throws PBXException sipHeader = PBXFactory.getActiveProfile().getAutoAnswer(); } actualChannelToTransfer.setCurrentActivityAction(new AgiChannelActivityBlindTransfer( - this._transferTarget.getFullyQualifiedName(), sipHeader, _toCallerID.getNumber())); + this._transferTarget.getFullyQualifiedName(), sipHeader, _toCallerID.getNumber(), dialOptions)); // TODO: At one point we were adding the /n option to the end of the // channel to get around diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 3d0a28d03..f5b2418f5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -130,12 +130,12 @@ public boolean isBridgeSupported() @Override public BlindTransferActivity blindTransfer(Call call, Call.OperandChannel channelToTransfer, EndPoint transferTarget, - CallerID toCallerID, boolean autoAnswer, long timeout) + CallerID toCallerID, boolean autoAnswer, long timeout, String dialOptions) { final CompletionAdaptor completion = new CompletionAdaptor<>(); final BlindTransferActivityImpl transfer = new BlindTransferActivityImpl(call, channelToTransfer, transferTarget, - toCallerID, autoAnswer, timeout, completion); + toCallerID, autoAnswer, timeout, completion, dialOptions); completion.waitForCompletion(timeout + 2, TimeUnit.SECONDS); @@ -145,16 +145,19 @@ public BlindTransferActivity blindTransfer(Call call, Call.OperandChannel channe @Override public void blindTransfer(Call call, Call.OperandChannel channelToTransfer, EndPoint transferTarget, CallerID toCallerID, - boolean autoAnswer, long timeout, ActivityCallback listener) + boolean autoAnswer, long timeout, ActivityCallback listener, String dialOptions) { - new BlindTransferActivityImpl(call, channelToTransfer, transferTarget, toCallerID, autoAnswer, timeout, listener); + new BlindTransferActivityImpl(call, channelToTransfer, transferTarget, toCallerID, autoAnswer, timeout, listener, + dialOptions); } public BlindTransferActivity blindTransfer(Channel agentChannel, EndPoint transferTarget, CallerID toCallerID, - boolean autoAnswer, int timeout, ActivityCallback iCallback) throws PBXException + boolean autoAnswer, int timeout, ActivityCallback iCallback, String dialOptions) + throws PBXException { - return new BlindTransferActivityImpl(agentChannel, transferTarget, toCallerID, autoAnswer, timeout, iCallback); + return new BlindTransferActivityImpl(agentChannel, transferTarget, toCallerID, autoAnswer, timeout, iCallback, + dialOptions); } From 5a3b920596f073d953cebc9527a9d10de71c7bbc Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 6 Apr 2020 12:26:59 +1000 Subject: [PATCH 343/802] for version 3.2.1-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 99a5dc67f..80a9888ab 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.2.0 + 3.2.1-SNAPSHOT UTF-8 From 477b56f19d87f172320a9f2895783a112b456d6c Mon Sep 17 00:00:00 2001 From: rndbit <> Date: Tue, 7 Apr 2020 22:04:55 +0930 Subject: [PATCH 344/802] upon disconnect clear response listeners, unblock synchronous calls - was keeping waiting synchronous calls sendAction and sendEventGenerationAction. even after reconnect the synchronous calls could continue to wait. changed to release those calls when connection is lost, without waiting for timeout to expire - when disconnecting while response listeners were waiting was keeping those listeners forever (memory leaking) due to response or event likely getting missed during loss of connection --- .../internal/ManagerConnectionImpl.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 875500214..9615bce65 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1314,6 +1314,7 @@ public void dispatchEvent(ManagerEvent event) } if (event instanceof DisconnectEvent) { + cleanupActionListeners((DisconnectEvent)event); // When we receive get disconnected while we are connected start // a new reconnect thread and set the state to RECONNECTING. synchronized (this) @@ -1534,6 +1535,70 @@ private void reconnect() } } + /** + * Notify pending {@link #responseListeners} and + * {@link #responseEventListeners} so the synchronous ones can unblock, + * clears those listener collections. + * + * @param event + */ + private void cleanupActionListeners(DisconnectEvent event) + { + HashMap oldResponseListeners = null; + + synchronized (responseListeners) + { + // Store remaining response listeners to be notified outside of synchronized + oldResponseListeners = new HashMap(responseListeners); + responseListeners.clear(); + } + + // Clear pending responseListeners that will not receive their responses + for (SendActionCallback responseListener: oldResponseListeners.values()) + { + // Allows to unblock waiting sendAction() calls + try + { + responseListener.onResponse(null); + } + catch (Exception ex) + { + logger.warn("Exception notifying responseListener.onResponse(null)", ex); + } + } + + HashMap oldResponseEventListeners = null; + synchronized (responseEventListeners) + { + // Store remaining responseEventListeners to be notified outside of synchronized + oldResponseEventListeners = new HashMap(responseEventListeners); + responseEventListeners.clear(); + } + + // Remove those already cleaned up via oldResponseListeners + // TODO or should all be notified? + for (String discardedInternalActionId: oldResponseListeners.keySet()) + { + oldResponseEventListeners.remove(discardedInternalActionId); + } + + // Notify remaining responseEventListeners. + // These could be EventGeneratingAction handlers that have received a + // response but have not yet received the end event. + for (ManagerEventListener responseEventListener: oldResponseEventListeners.values()) + { + try + { + // Allows to unblock waiting sendAction() calls + responseEventListener.onManagerEvent(event); + } + catch (Exception ex) + { + logger.warn("Exception notifying responseListener.onManagerEvent(DisconnectEvent)", ex); + } + } + } + private void cleanup() { disconnect(); @@ -1622,7 +1687,10 @@ public DefaultSendActionCallback(ResponseHandlerResult result) public void onResponse(ManagerResponse response) { + // null response happens when connection is lost + if (response != null) { result.setResponse(response); + } result.countDown(); } } @@ -1651,6 +1719,16 @@ public ResponseEventHandler(ResponseEventsImpl events, Class< ? > actionComplete public void onManagerEvent(ManagerEvent event) { + if (event instanceof DisconnectEvent) + { + // Set flag that must not wait for the response + events.setComplete(true); + // unblock potentially waiting synchronous call to + // sendEventGeneratingAction(EventGeneratingAction action, long timeout) + events.countDown(); + return; + } + // should always be a ResponseEvent, anyway... if (event instanceof ResponseEvent) { @@ -1675,6 +1753,17 @@ public void onManagerEvent(ManagerEvent event) public void onResponse(ManagerResponse response) { + // If disconnected + if (response == null) + { + // Set flag that must not wait for the response + events.setComplete(true); + // unblock potentially waiting synchronous call to + // sendEventGeneratingAction(EventGeneratingAction action, long timeout) + events.countDown(); + return; + } + events.setRepsonse(response); if (response instanceof ManagerError) { From ff862470c56be56b9ac3caa7d48cc3bc686015ab Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 23 Apr 2020 16:50:42 +1000 Subject: [PATCH 345/802] add comment about passing option --- .../org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java index ba5141771..617a90ab7 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java @@ -28,7 +28,12 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I { try { - + // TODO: this should probably pass the 'F' option to allow the + // bridgee + // to go back to dialplan. + // I'm not currently prepared to do it as it is called from a number + // of places, and + // I can't currently see it causing problems. channel.bridge(target.getChannelName(), ""); channel.hangup(); } From 0ef62635f732aeb77049cf733e1852117ba8ce2d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 28 Apr 2020 16:00:49 +1000 Subject: [PATCH 346/802] allow passing of dial options --- .../examples/activities/BlindTransfer.java | 4 +- .../examples/activities/Dial.java | 7 +- .../examples/activities/Hold.java | 3 +- src/main/java/org/asteriskjava/pbx/PBX.java | 4 +- .../pbx/agi/AgiChannelActivityDial.java | 93 ++++++++++--------- .../internal/activity/DialActivityImpl.java | 7 +- .../pbx/internal/core/AsteriskPBX.java | 14 +-- .../pbx/internal/managerAPI/Dial.java | 4 +- 8 files changed, 75 insertions(+), 61 deletions(-) diff --git a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java index e70fb5328..fb4de37e9 100644 --- a/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java +++ b/src/main/java/org/asteriskjava/examples/activities/BlindTransfer.java @@ -48,6 +48,8 @@ static public void main(String[] args) throws IOException, AuthenticationFailedE static private void blindTransfer() { + String dialOptions = ""; + PBX pbx = PBXFactory.getActivePBX(); // The trunk MUST match the section header (e.g. [default]) that appears @@ -97,7 +99,7 @@ public void progress(BlindTransferActivity activity, ActivityStatusEnum status, if (status == ActivityStatusEnum.FAILURE) System.out.println("Oops something bad happened when we dialed."); } - }); + }, dialOptions); } diff --git a/src/main/java/org/asteriskjava/examples/activities/Dial.java b/src/main/java/org/asteriskjava/examples/activities/Dial.java index 3cbdae526..edfe26690 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Dial.java +++ b/src/main/java/org/asteriskjava/examples/activities/Dial.java @@ -34,6 +34,8 @@ static private void syncDial() { try { + String dialOptions = ""; + PBX pbx = PBXFactory.getActivePBX(); // The trunk MUST match the section header (e.g. [default]) that @@ -56,7 +58,7 @@ static private void syncDial() // Trunk is currently ignored so set to null // The call is dialed and only returns when the call comes up (it // doesn't wait for the remote end to answer). - DialActivity dial = pbx.dial(from, fromCallerID, to, toCallerID); + DialActivity dial = pbx.dial(from, fromCallerID, to, toCallerID, dialOptions); Call call = dial.getNewCall(); @@ -73,6 +75,7 @@ static private void syncDial() static private void asyncDial() { + String dialOptions = ""; PBX pbx = PBXFactory.getActivePBX(); // We are going to dial from extension 100 @@ -112,7 +115,7 @@ public void progress(DialActivity activity, ActivityStatusEnum status, String me if (status == ActivityStatusEnum.FAILURE) System.out.println("Oops something bad happened when we dialed."); } - }); + }, dialOptions); } diff --git a/src/main/java/org/asteriskjava/examples/activities/Hold.java b/src/main/java/org/asteriskjava/examples/activities/Hold.java index af792962e..3034785d8 100644 --- a/src/main/java/org/asteriskjava/examples/activities/Hold.java +++ b/src/main/java/org/asteriskjava/examples/activities/Hold.java @@ -27,6 +27,7 @@ static public void main(String[] args) static private void hold() { + String dialOptions = ""; PBX pbx = PBXFactory.getActivePBX(); // We are going to dial from extension 100 @@ -64,7 +65,7 @@ public void progress(DialActivity activity, ActivityStatusEnum status, String me if (status == ActivityStatusEnum.FAILURE) System.out.println("Oops something bad happened when we dialed."); } - }); + }, dialOptions); } diff --git a/src/main/java/org/asteriskjava/pbx/PBX.java b/src/main/java/org/asteriskjava/pbx/PBX.java index 1986bb1e4..9b355e702 100644 --- a/src/main/java/org/asteriskjava/pbx/PBX.java +++ b/src/main/java/org/asteriskjava/pbx/PBX.java @@ -100,7 +100,7 @@ void blindTransfer(Call call, OperandChannel channelToTransfer, final EndPoint t * * @return Call - the call resulting from dialing the number. */ - DialActivity dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID); + DialActivity dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID, String dialOptions); /** * Dials the given phone number using the specified trunk. Not returning @@ -110,7 +110,7 @@ void blindTransfer(Call call, OperandChannel channelToTransfer, final EndPoint t * @return Call the call resulting from dialing the number. */ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID, - ActivityCallback callback); + ActivityCallback callback, String dialOptions); /** * Hangs up the given channel. Not returning until the call is hungup. diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java index e33a76c1b..bbfdeaeca 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java @@ -10,49 +10,52 @@ public class AgiChannelActivityDial implements AgiChannelActivityAction { - CountDownLatch latch = new CountDownLatch(1); - private String target; - private String sipHeader; - - public AgiChannelActivityDial(String target) - { - this.target = target; - } - - public AgiChannelActivityDial(String fullyQualifiedName, String sipHeader) - { - target = fullyQualifiedName; - this.sipHeader = sipHeader; - } - - @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { - if (sipHeader != null) - { - channel.setVariable("__SIPADDHEADER", sipHeader); - } - // setting the activity to hold, means that when the call falls out of - // the dial it'll go to hold. - - // also if some other code sets and activity and then redirects, we - // won't over write it on the way out (if we did it after the dial - // command) - ichannel.setCurrentActivityAction(new AgiChannelActivityHold()); - channel.dial(target, 30, ""); - - } - - @Override - public boolean isDisconnect() - { - return false; - } - - @Override - public void cancel() - { - latch.countDown(); - - } + CountDownLatch latch = new CountDownLatch(1); + private String target; + private String sipHeader; + private String dialOptions; + + public AgiChannelActivityDial(String target, String dialOptions) + { + this.target = target; + this.dialOptions = dialOptions; + } + + public AgiChannelActivityDial(String fullyQualifiedName, String sipHeader, String dialOptions) + { + target = fullyQualifiedName; + this.sipHeader = sipHeader; + this.dialOptions = dialOptions; + } + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + if (sipHeader != null) + { + channel.setVariable("__SIPADDHEADER", sipHeader); + } + // setting the activity to hold, means that when the call falls out of + // the dial it'll go to hold. + + // also if some other code sets and activity and then redirects, we + // won't over write it on the way out (if we did it after the dial + // command) + ichannel.setCurrentActivityAction(new AgiChannelActivityHold()); + channel.dial(target, 30, dialOptions); + + } + + @Override + public boolean isDisconnect() + { + return false; + } + + @Override + public void cancel() + { + latch.countDown(); + + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java index b43a2ad4d..b3e11d2bb 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java @@ -54,9 +54,11 @@ public class DialActivityImpl extends ActivityHelper implements Di private Map channelVarsToSet; + private String dialOptions; + public DialActivityImpl(final EndPoint originating, final EndPoint accepting, final CallerID toCallerID, final boolean hideToCallerID, final ActivityCallback listener, - Map channelVarsToSet) + Map channelVarsToSet, String dialOptions) { super("Dial", listener); this._originating = originating; @@ -65,6 +67,7 @@ public DialActivityImpl(final EndPoint originating, final EndPoint accepting, fi this.hideToCallerId = hideToCallerID; this.cancelledByOperator = false; this.channelVarsToSet = channelVarsToSet; + this.dialOptions = dialOptions; this.startActivity(false); } @@ -84,7 +87,7 @@ public boolean doActivity() throws PBXException final AsteriskSettings profile = PBXFactory.getActiveProfile(); final OriginateResult[] resultChannels = nr.dial(this, this._originating, this._accepting, - profile.getManagementContext(), this.toCallerID, this.hideToCallerId, channelVarsToSet); + profile.getManagementContext(), this.toCallerID, this.hideToCallerId, channelVarsToSet, dialOptions); if ((resultChannels[0] == null) || (resultChannels[1] == null)) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index f5b2418f5..b610d5a12 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -255,11 +255,12 @@ public void conference(final Channel channelOne, final Channel channelTwo, final } @Override - public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID) + public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID, + String dialOptions) { final CompletionAdaptor completion = new CompletionAdaptor<>(); - final DialActivityImpl dialer = new DialActivityImpl(from, to, toCallerID, false, completion, null); + final DialActivityImpl dialer = new DialActivityImpl(from, to, toCallerID, false, completion, null, dialOptions); completion.waitForCompletion(3, TimeUnit.MINUTES); @@ -273,17 +274,18 @@ public DialLocalToAgiActivity dialLocalToAgi(final EndPoint from, final CallerID } public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID, - final ActivityCallback callback, Map channelVarsToSet) + final ActivityCallback callback, Map channelVarsToSet, String dialOptions) { - final DialActivityImpl dialer = new DialActivityImpl(from, to, toCallerID, false, callback, channelVarsToSet); + final DialActivityImpl dialer = new DialActivityImpl(from, to, toCallerID, false, callback, channelVarsToSet, + dialOptions); return dialer; } @Override public void dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID, - final ActivityCallback callback) + final ActivityCallback callback, String dialOptions) { - new DialActivityImpl(from, to, toCallerID, false, callback, null); + new DialActivityImpl(from, to, toCallerID, false, callback, null, dialOptions); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java index 8bb06f666..d4d4c1e84 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java @@ -55,7 +55,7 @@ public Dial(final String descriptiveName) */ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint localHandset, final EndPoint targetEndPoint, final String dialContext, final CallerID callerID, final boolean hideCallerId, - Map channelVarsToSet) throws PBXException + Map channelVarsToSet, String dialOptions) throws PBXException { final PBX pbx = PBXFactory.getActivePBX(); @@ -98,7 +98,7 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint this._latch = new CountDownLatch(1); trcResult.getChannel().setCurrentActivityAction( - new AgiChannelActivityDial(targetEndPoint.getFullyQualifiedName())); + new AgiChannelActivityDial(targetEndPoint.getFullyQualifiedName(), dialOptions)); this._latch.await(30, TimeUnit.SECONDS); From c6df951fe1e6978f1ca174d7fa5a527844f163ff Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 29 Apr 2020 11:56:04 +1000 Subject: [PATCH 347/802] for version 3.2.2-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 80a9888ab..e46b2b262 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.2.1-SNAPSHOT + 3.2.2-SNAPSHOT UTF-8 From a3c4726b1d5a9458778757e042b5e52c0b353252 Mon Sep 17 00:00:00 2001 From: discardedwutu Date: Fri, 8 May 2020 17:57:19 -0500 Subject: [PATCH 348/802] Make channels entering holding bridges not create backwards compatibility BridgeEvent --- .../internal/backwardsCompatibility/bridge/BridgeState.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index ab6bfffb2..2f02ffe0d 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -48,6 +48,11 @@ ManagerEvent addMember(BridgeEnterEvent event) { List remaining = null; + if (event.getBridgeTechnology().equals("holding_bridge")) { + /* channels in a holding bridge aren't bridged to one another */ + return null; + } + synchronized (members) { if (members.put(event.getChannel(), event) == null && members.size() == 2) From e27e8813919f79b47771b7a2415772e0f9594893 Mon Sep 17 00:00:00 2001 From: discardedwutu Date: Fri, 8 May 2020 18:14:32 -0500 Subject: [PATCH 349/802] Fix accidental tab instead of spaces --- .../internal/backwardsCompatibility/bridge/BridgeState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 2f02ffe0d..3ce231023 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -49,7 +49,7 @@ ManagerEvent addMember(BridgeEnterEvent event) List remaining = null; if (event.getBridgeTechnology().equals("holding_bridge")) { - /* channels in a holding bridge aren't bridged to one another */ + /* channels in a holding bridge aren't bridged to one another */ return null; } From 3fc842e8707fe8cd4614d85fb78d71987018b23b Mon Sep 17 00:00:00 2001 From: discardedwutu Date: Mon, 11 May 2020 17:06:26 -0500 Subject: [PATCH 350/802] Didn't notice before that a similar thing would happen in a holding bridge if channels in the bridge dropped from 3 to 2. --- .../internal/backwardsCompatibility/bridge/BridgeState.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 3ce231023..beb0dd439 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -86,6 +86,11 @@ ManagerEvent removeMember(BridgeLeaveEvent event) { List remaining = new LinkedList<>(); + if (event.getBridgeTechnology().equals("holding_bridge")) { + /* channels in a holding bridge aren't bridged to one another */ + return null; + } + synchronized (members) { remaining.addAll(members.values()); From 1ccb4457d403e1eaa41280dcae2bb24e550ca9fa Mon Sep 17 00:00:00 2001 From: discardedwutu Date: Tue, 12 May 2020 10:26:28 -0500 Subject: [PATCH 351/802] Small change - define "holding_bridge" as a static variable and use that as the subject of the equals action just in case we end up with a NULL value for BridgeTechnology header --- .../internal/backwardsCompatibility/bridge/BridgeState.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index beb0dd439..edb572117 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -26,6 +26,7 @@ class BridgeState private final Log logger = LogFactory.getLog(getClass()); private static final BridgeEnterEventComparator BRIDGE_ENTER_EVENT_COMPARATOR = new BridgeEnterEventComparator(); + private static final String HOLDING_BRIDGE_TECH = "holding_bridge"; private final Map members = new HashMap<>(); @@ -48,7 +49,7 @@ ManagerEvent addMember(BridgeEnterEvent event) { List remaining = null; - if (event.getBridgeTechnology().equals("holding_bridge")) { + if (HOLDING_BRIDGE_TECH.equals(event.getBridgeTechnology())) { /* channels in a holding bridge aren't bridged to one another */ return null; } @@ -86,7 +87,7 @@ ManagerEvent removeMember(BridgeLeaveEvent event) { List remaining = new LinkedList<>(); - if (event.getBridgeTechnology().equals("holding_bridge")) { + if (HOLDING_BRIDGE_TECH.equals(event.getBridgeTechnology())) { /* channels in a holding bridge aren't bridged to one another */ return null; } From a87b0d8e418442fe2edd869f4f5bace5d8341253 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 14 May 2020 11:50:13 +1000 Subject: [PATCH 352/802] add error message when streaming invalid file --- .../fastagi/internal/AgiChannelImpl.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java index 541f3c011..93d04794d 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java @@ -255,17 +255,29 @@ public void setPriority(String priority) throws AgiException public void streamFile(String file) throws AgiException { + checkFile(file); sendCommand(new StreamFileCommand(file)); } + private void checkFile(String file) + { + if (file == null || file.length() == 0) + { + logger.error( + "Call to streamFile with empty file, this will result in AGI setting AGISTATUS = FAILURE and returning -1"); + } + } + public char streamFile(String file, String escapeDigits) throws AgiException { + checkFile(file); sendCommand(new StreamFileCommand(file, escapeDigits)); return lastReply.getResultCodeAsChar(); } public char streamFile(String file, String escapeDigits, int offset) throws AgiException { + checkFile(file); sendCommand(new StreamFileCommand(file, escapeDigits, offset)); return lastReply.getResultCodeAsChar(); } From 1bd3e8821b06ab576288732546f43349552dad2c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 15 May 2020 13:01:23 +1000 Subject: [PATCH 353/802] spread reconnect attempts --- .../internal/ManagerConnectionImpl.java | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 4ecefa456..c29d0e893 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1048,10 +1048,8 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas return responseEvents; } - public void sendEventGeneratingAction( - EventGeneratingAction action, - SendEventGeneratingActionCallback callback) - throws IOException, IllegalArgumentException, IllegalStateException + public void sendEventGeneratingAction(EventGeneratingAction action, SendEventGeneratingActionCallback callback) + throws IOException, IllegalArgumentException, IllegalStateException { if (action == null) { @@ -1295,7 +1293,7 @@ public void dispatchEvent(ManagerEvent event) } if (event instanceof DisconnectEvent) { - cleanupActionListeners((DisconnectEvent)event); + cleanupActionListeners((DisconnectEvent) event); // When we receive get disconnected while we are connected start // a new reconnect thread and set the state to RECONNECTING. synchronized (this) @@ -1397,7 +1395,7 @@ private boolean isSupportedProtocolIdentifier(final String identifier) return true; } } - + // Other cases if ("OpenPBX Call Manager/1.0".equals(identifier)) return true; @@ -1405,7 +1403,7 @@ private boolean isSupportedProtocolIdentifier(final String identifier) return true; if (identifier.startsWith("Asterisk Call Manager Proxy/")) return true; - + return false; } @@ -1519,6 +1517,17 @@ private void reconnect() } logger.warn("Exception while trying to reconnect: " + message); + try + { + // Where multiple connections are present, spread out + // their reconnect attempts and prevent hard loop. + long randomSleep = (long) (Math.random() * 100); + TimeUnit.MILLISECONDS.sleep(50 + randomSleep); + } + catch (InterruptedException e1) + { + logger.error(e1); + } } numTries++; } @@ -1537,13 +1546,14 @@ private void cleanupActionListeners(DisconnectEvent event) synchronized (responseListeners) { - // Store remaining response listeners to be notified outside of synchronized + // Store remaining response listeners to be notified outside of + // synchronized oldResponseListeners = new HashMap(responseListeners); responseListeners.clear(); } // Clear pending responseListeners that will not receive their responses - for (SendActionCallback responseListener: oldResponseListeners.values()) + for (SendActionCallback responseListener : oldResponseListeners.values()) { // Allows to unblock waiting sendAction() calls try @@ -1559,14 +1569,15 @@ private void cleanupActionListeners(DisconnectEvent event) HashMap oldResponseEventListeners = null; synchronized (responseEventListeners) { - // Store remaining responseEventListeners to be notified outside of synchronized + // Store remaining responseEventListeners to be notified outside of + // synchronized oldResponseEventListeners = new HashMap(responseEventListeners); responseEventListeners.clear(); } // Remove those already cleaned up via oldResponseListeners // TODO or should all be notified? - for (String discardedInternalActionId: oldResponseListeners.keySet()) + for (String discardedInternalActionId : oldResponseListeners.keySet()) { oldResponseEventListeners.remove(discardedInternalActionId); } @@ -1574,7 +1585,7 @@ private void cleanupActionListeners(DisconnectEvent event) // Notify remaining responseEventListeners. // These could be EventGeneratingAction handlers that have received a // response but have not yet received the end event. - for (ManagerEventListener responseEventListener: oldResponseEventListeners.values()) + for (ManagerEventListener responseEventListener : oldResponseEventListeners.values()) { try { @@ -1677,8 +1688,9 @@ public DefaultSendActionCallback(ResponseHandlerResult result) public void onResponse(ManagerResponse response) { // null response happens when connection is lost - if (response != null) { - result.setResponse(response); + if (response != null) + { + result.setResponse(response); } result.countDown(); } @@ -1713,7 +1725,8 @@ public void onManagerEvent(ManagerEvent event) // Set flag that must not wait for the response events.setComplete(true); // unblock potentially waiting synchronous call to - // sendEventGeneratingAction(EventGeneratingAction action, long timeout) + // sendEventGeneratingAction(EventGeneratingAction action, long + // timeout) events.countDown(); return; } @@ -1748,7 +1761,8 @@ public void onResponse(ManagerResponse response) // Set flag that must not wait for the response events.setComplete(true); // unblock potentially waiting synchronous call to - // sendEventGeneratingAction(EventGeneratingAction action, long timeout) + // sendEventGeneratingAction(EventGeneratingAction action, long + // timeout) events.countDown(); return; } @@ -1769,16 +1783,14 @@ public void onResponse(ManagerResponse response) } } - private class AsyncEventGeneratingResponseHandler - implements SendActionCallback, ManagerEventListener + private class AsyncEventGeneratingResponseHandler implements SendActionCallback, ManagerEventListener { - private final Class actionCompleteEventClass; + private final Class< ? extends ResponseEvent> actionCompleteEventClass; private final SendEventGeneratingActionCallback callback; private final ResponseEventsImpl events; - public AsyncEventGeneratingResponseHandler( - Class actionCompleteEventClass, + public AsyncEventGeneratingResponseHandler(Class< ? extends ResponseEvent> actionCompleteEventClass, SendEventGeneratingActionCallback callback) { this.actionCompleteEventClass = actionCompleteEventClass; @@ -1802,7 +1814,7 @@ public void onManagerEvent(ManagerEvent event) return; } - ResponseEvent responseEvent = (ResponseEvent)event; + ResponseEvent responseEvent = (ResponseEvent) event; events.addEvent(responseEvent); if (actionCompleteEventClass.isAssignableFrom(event.getClass())) From d79381e65c8d08466466b3f3458ef2b416b8351d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 15 May 2020 13:01:56 +1000 Subject: [PATCH 354/802] for version 3.3.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e46b2b262..fabb03ebc 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.2.2-SNAPSHOT + 3.3.0 UTF-8 From a5834beb96d2e9d93209fcf960db5c9fee3af3c4 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 25 May 2020 14:55:37 +1000 Subject: [PATCH 355/802] hand int types --- .../manager/internal/AbstractBuilder.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index 531e41a18..867c977a3 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -111,6 +111,10 @@ else if (dataType.isAssignableFrom(long.class) || dataType.isAssignableFrom(Long { value = parseLong(entry); } + else if (dataType.isAssignableFrom(int.class) || dataType.isAssignableFrom(Integer.class)) + { + value = parseInteger(entry); + } else { try @@ -137,6 +141,21 @@ else if (dataType.isAssignableFrom(long.class) || dataType.isAssignableFrom(Long } } + private Integer parseInteger(Entry entry) + { + Integer value; + String stringValue = (String) entry.getValue(); + if (stringValue != null && stringValue.length() > 0) + { + value = Integer.parseInt(stringValue); + } + else + { + value = null; + } + return value; + } + @SuppressWarnings("unchecked") private Map parseMap(Map.Entry entry) { From 781af0fc020f68f35c430f415d00115821ac5b0e Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 25 May 2020 14:56:46 +1000 Subject: [PATCH 356/802] add and update confbridge actions and events --- .../action/ConfbridgeListRoomsAction.java | 11 +- .../manager/event/ConfbridgeListEvent.java | 124 +++++++++++++++++- .../event/ConfbridgeListRoomsEvent.java | 11 ++ .../wrap/actions/ConfbridgeKickAction.java | 35 +++++ 4 files changed, 173 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeKickAction.java diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeListRoomsAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeListRoomsAction.java index 551ecf3bd..f44916009 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeListRoomsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeListRoomsAction.java @@ -4,8 +4,9 @@ import org.asteriskjava.manager.event.ResponseEvent; /** - * Lists data about all active conferences. ConfbridgeListRoomsEvent will follow as separate events, - * followed by a final event called ConfbridgeListRoomsComplete. + * Lists data about all active conferences. ConfbridgeListRoomsEvent will follow + * as separate events, followed by a final event called + * ConfbridgeListRoomsComplete. * * @since 1.0.0 */ @@ -13,6 +14,10 @@ public class ConfbridgeListRoomsAction extends AbstractManagerAction implements { private static final long serialVersionUID = 1L; + /** + * note this requires the "reporting" WRITE permission + */ + @Override public String getAction() { @@ -20,7 +25,7 @@ public String getAction() } @Override - public Class getActionCompleteEventClass() + public Class< ? extends ResponseEvent> getActionCompleteEventClass() { return ConfbridgeListRoomsCompleteEvent.class; } diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListEvent.java index 4046c17bd..380aa8c46 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListEvent.java @@ -17,6 +17,16 @@ public class ConfbridgeListEvent extends ResponseEvent private Boolean admin; private Boolean markedUser; private String channel; + private String linkedid; + private String waiting; + private String language; + private String talking; + private String muted; + private String uniqueid; + private int answeredtime; + private String waitmarked; + private String endmarked; + private String accountcode; public ConfbridgeListEvent(Object source) { @@ -41,12 +51,14 @@ public void setConference(String conference) public String getConference() { return conference; - } + } /** - * Sets the role of the caller in the list admin = yes or no of the conference. + * Sets the role of the caller in the list admin = yes or no of the + * conference. * - * @param admin = yes or no the role of the caller in the list of the conference. + * @param admin = yes or no the role of the caller in the list of the + * conference. */ public void setAdmin(Boolean admin) { @@ -54,9 +66,11 @@ public void setAdmin(Boolean admin) } /** - * Returns the role of the caller in the list admin = yes or no of the conference. + * Returns the role of the caller in the list admin = yes or no of the + * conference. * - * @return the role of the caller in the list admin = yes or no of the conference. + * @return the role of the caller in the list admin = yes or no of the + * conference. */ public Boolean getAdmin() { @@ -88,4 +102,104 @@ public String getChannel() { return channel; } + + public String getLinkedid() + { + return linkedid; + } + + public void setLinkedid(String linkedid) + { + this.linkedid = linkedid; + } + + public String getWaiting() + { + return waiting; + } + + public void setWaiting(String waiting) + { + this.waiting = waiting; + } + + public String getLanguage() + { + return language; + } + + public void setLanguage(String language) + { + this.language = language; + } + + public String getTalking() + { + return talking; + } + + public void setTalking(String talking) + { + this.talking = talking; + } + + public String getMuted() + { + return muted; + } + + public void setMuted(String muted) + { + this.muted = muted; + } + + public String getUniqueid() + { + return uniqueid; + } + + public void setUniqueid(String uniqueid) + { + this.uniqueid = uniqueid; + } + + public int getAnsweredtime() + { + return answeredtime; + } + + public void setAnsweredtime(int answeredtime) + { + this.answeredtime = answeredtime; + } + + public String getWaitmarked() + { + return waitmarked; + } + + public void setWaitmarked(String waitmarked) + { + this.waitmarked = waitmarked; + } + + public String getEndmarked() + { + return endmarked; + } + + public void setEndmarked(String endmarked) + { + this.endmarked = endmarked; + } + + public String getAccountcode() + { + return accountcode; + } + + public void setAccountcode(String accountcode) + { + this.accountcode = accountcode; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsEvent.java index 342ab684a..d748b6df7 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsEvent.java @@ -11,6 +11,7 @@ public class ConfbridgeListRoomsEvent extends ResponseEvent private Integer parties; private Integer marked; private Boolean locked; + private String muted; public ConfbridgeListRoomsEvent(Object source) { @@ -82,4 +83,14 @@ public Boolean getLocked() { return locked; } + + public String getMuted() + { + return muted; + } + + public void setMuted(String muted) + { + this.muted = muted; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeKickAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeKickAction.java new file mode 100644 index 000000000..ae82454b6 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeKickAction.java @@ -0,0 +1,35 @@ +package org.asteriskjava.pbx.asterisk.wrap.actions; + +public class ConfbridgeKickAction extends AbstractManagerAction +{ + + private final String channel; + private String room; + + public ConfbridgeKickAction(final String room, String channel) + { + this.channel = channel; + this.room = room; + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() + { + final org.asteriskjava.manager.action.ConfbridgeKickAction action = new org.asteriskjava.manager.action.ConfbridgeKickAction(); + action.setActionId(this.getActionId()); + action.setChannel(channel); + action.setConference(room); + + return action; + } + + public String getChannel() + { + return channel; + } + + public String getRoom() + { + return room; + } +} From 58e65f3dc3ca4ab737b77e3f0a5e4737ec037817 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 25 May 2020 14:57:18 +1000 Subject: [PATCH 357/802] for version 3.4.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fabb03ebc..9711852cf 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.3.0 + 3.4.0 UTF-8 From a34b78001d59d8c2f1cfb273a35d2c7f188211cd Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 25 May 2020 14:58:58 +1000 Subject: [PATCH 358/802] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ff4fdacb..bc0083bea 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 16) (master) org.asteriskjava asterisk-java - 3.0.19 + 3.4.0 Asterisk-Java 2.x (Java 1.7 and Asterisk < Version 10) (branch 2.0.4) From 9025fec25aeed41de281fcc144114233efab8604 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 25 May 2020 15:18:49 +1000 Subject: [PATCH 359/802] improve logging --- .../org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java index 722953b9b..9c6b6fc5b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java @@ -194,13 +194,14 @@ public void setOwner(RoomOwner newOwner) public void removeOwner(RoomOwner toRemove) { - if (owner == toRemove) + if (owner == toRemove || owner == null) { owner = null; } else { - logger.error("Tring to remove the owner, but it's not the current owner"); + logger.error( + "Tring to remove the owner, but it's not the current owner. Owner=" + owner + " caller=" + toRemove); } } From a97bbc42620ad1c18352530b673534cc6999cf50 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 4 Jun 2020 13:14:53 +1000 Subject: [PATCH 360/802] add outcome for failed blindtransferactivity --- .../pbx/activities/BlindTransferActivity.java | 87 ++++++++++--------- .../agi/AgiChannelActivityBlindTransfer.java | 12 ++- .../pbx/agi/BlindTransferResultListener.java | 8 ++ .../activity/BlindTransferActivityImpl.java | 20 ++++- 4 files changed, 80 insertions(+), 47 deletions(-) create mode 100644 src/main/java/org/asteriskjava/pbx/agi/BlindTransferResultListener.java diff --git a/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java b/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java index e18527f6e..6e5e56451 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java @@ -9,56 +9,57 @@ public interface BlindTransferActivity extends Activity { - /** - * A bridged call is a successful transfer all other options are a failed - * transfer. - * - * @author bsutton - * - */ - enum CompletionCause - { - // The call was bridged. - BRIDGED("Connected") - // The call hungup - , HANGUP("Transfer Failed, Caller Hungup or Destination Busy") - // A timeout occur during the transfer - // which essentially means the transferTarget didn't answer the phone - , TIMEOUT("Transfer Failed, Timeout") - // The cancel method was called. - , CANCELLED("Transfer Cancelled"); + /** + * A bridged call is a successful transfer all other options are a failed + * transfer. + * + * @author bsutton + */ + enum CompletionCause + { + // The call was bridged. + BRIDGED("Connected") + // The call hungup + , HANGUP("Transfer Failed, Caller Hungup or Destination Busy") + // A timeout occur during the transfer + // which essentially means the transferTarget didn't answer the phone + , TIMEOUT("Transfer Failed, Timeout") + // The cancel method was called. + , CANCELLED("Transfer Cancelled") + // Failed + , FAILED("Transfer Failed"); - String message; - - CompletionCause(String message) - { - this.message = message; - } - - public String getMessage() - { - return message; - } - } + String message; - Channel getChannelToTransfer(); + CompletionCause(String message) + { + this.message = message; + } - CallerID getTransferTargetCallerID(); + public String getMessage() + { + return message; + } + } - EndPoint getTransferTarget(); + Channel getChannelToTransfer(); - Channel getTransferTargetChannel(); + CallerID getTransferTargetCallerID(); - CompletionCause getCompletionCause(); + EndPoint getTransferTarget(); - void cancel(); + Channel getTransferTargetChannel(); - /** - * The call created as a result of the blind transfer being answered. - * - * @return - * @throws PBXException - */ - Call getNewCall() throws PBXException; + CompletionCause getCompletionCause(); + + void cancel(); + + /** + * The call created as a result of the blind transfer being answered. + * + * @return + * @throws PBXException + */ + Call getNewCall() throws PBXException; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java index c942c52aa..8497cb85a 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java @@ -16,8 +16,10 @@ public class AgiChannelActivityBlindTransfer implements AgiChannelActivityAction int timeout = 30; private String callerId; private String dialOptions; + private BlindTransferResultListener listener; - public AgiChannelActivityBlindTransfer(String fullyQualifiedName, String sipHeader, String callerId, String dialOptions) + public AgiChannelActivityBlindTransfer(String fullyQualifiedName, String sipHeader, String callerId, String dialOptions, + BlindTransferResultListener listener) { this.target = fullyQualifiedName; this.sipHeader = sipHeader; @@ -27,6 +29,7 @@ public AgiChannelActivityBlindTransfer(String fullyQualifiedName, String sipHead { this.sipHeader = ""; } + this.listener = listener; } @Override @@ -37,7 +40,12 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I channel.setCallerId(callerId); ichannel.setCurrentActivityAction(new AgiChannelActivityHold()); channel.dial(target, timeout, dialOptions); - + String status = channel.getVariable("DIALSTATUS"); + boolean success = "ANSWER".equalsIgnoreCase(status); + if (listener != null) + { + listener.result(status, success); + } } @Override diff --git a/src/main/java/org/asteriskjava/pbx/agi/BlindTransferResultListener.java b/src/main/java/org/asteriskjava/pbx/agi/BlindTransferResultListener.java new file mode 100644 index 000000000..b053979c0 --- /dev/null +++ b/src/main/java/org/asteriskjava/pbx/agi/BlindTransferResultListener.java @@ -0,0 +1,8 @@ +package org.asteriskjava.pbx.agi; + +public interface BlindTransferResultListener +{ + + void result(String status, boolean success); + +} diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index a224c4ec6..cbe35dd19 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -18,6 +18,7 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.activities.BlindTransferActivity; import org.asteriskjava.pbx.agi.AgiChannelActivityBlindTransfer; +import org.asteriskjava.pbx.agi.BlindTransferResultListener; import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; import org.asteriskjava.pbx.asterisk.wrap.events.DialEvent; import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; @@ -153,8 +154,23 @@ public boolean doActivity() throws PBXException { sipHeader = PBXFactory.getActiveProfile().getAutoAnswer(); } - actualChannelToTransfer.setCurrentActivityAction(new AgiChannelActivityBlindTransfer( - this._transferTarget.getFullyQualifiedName(), sipHeader, _toCallerID.getNumber(), dialOptions)); + BlindTransferResultListener listener = new BlindTransferResultListener() + { + + @Override + public void result(String status, boolean success) + { + if (_completionCause == null) + { + _completionCause = CompletionCause.FAILED; + } + _latch.countDown(); + + } + }; + actualChannelToTransfer.setCurrentActivityAction( + new AgiChannelActivityBlindTransfer(this._transferTarget.getFullyQualifiedName(), sipHeader, + _toCallerID.getNumber(), dialOptions, listener)); // TODO: At one point we were adding the /n option to the end of the // channel to get around From 585a2b6a200877d7e7fa2d04457c42a68908ecad Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 9 Jun 2020 09:58:25 +1000 Subject: [PATCH 361/802] for version 3.5.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9711852cf..61dff1825 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.4.0 + 3.5.0 UTF-8 From 4548dc91d5a0d5c5185f31c09b4110876830f69e Mon Sep 17 00:00:00 2001 From: AhmadHamdanMontyMobile <67693580+AhmadHamdanMontyMobile@users.noreply.github.com> Date: Thu, 2 Jul 2020 02:51:35 +0300 Subject: [PATCH 362/802] Added Asterisk cert 13&16 version check support (#335) * Added Asterisk cert 13&16 version check support * Update AsteriskVersion.java --- src/main/java/org/asteriskjava/AsteriskVersion.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 5e7dd4f83..d815aaad4 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -36,8 +36,10 @@ public class AsteriskVersion implements Comparable, Serializabl private final String versionString; private final Pattern patterns[]; + private static final String VERSION_PATTERN_CERTIFIED_16 = "^\\s*Asterisk certified/(GIT-)?16[-. ].*"; private static final String VERSION_PATTERN_CERTIFIED_13 = "^\\s*Asterisk certified/((SVN-branch|GIT)-)?13[-. ].*"; + /** * Represents the Asterisk 1.0 series. */ @@ -96,7 +98,7 @@ public class AsteriskVersion implements Comparable, Serializabl * @since 1.0.0 */ public static final AsteriskVersion ASTERISK_13 = new AsteriskVersion(1300, "Asterisk 13", VERSION_PATTERN_13, - VERSION_PATTERN_CERTIFIED_13); + VERSION_PATTERN_CERTIFIED_13); /** * Represents the Asterisk 14 series. @@ -117,13 +119,14 @@ public class AsteriskVersion implements Comparable, Serializabl * * @since 2.1.0 */ - public static final AsteriskVersion ASTERISK_16 = new AsteriskVersion(1600, "Asterisk 16", VERSION_PATTERN_16); + public static final AsteriskVersion ASTERISK_16 = new AsteriskVersion(1600, "Asterisk 16", VERSION_PATTERN_16, + VERSION_PATTERN_CERTIFIED_16); private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ASTERISK_16, ASTERISK_15, ASTERISK_14, ASTERISK_13, ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6}; - // current debian stable version, as of 03/07/2018 - public static final AsteriskVersion DEFAULT_VERSION = ASTERISK_13; + // current debian stable version, as of 09/10/2018 + public static final AsteriskVersion DEFAULT_VERSION = ASTERISK_16; /** * Serial version identifier. From fc8bcd2d33fd6d768895a5de1e97c30a3f662582 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 2 Jul 2020 13:39:51 +1000 Subject: [PATCH 363/802] add extra logging and move some logging levels up --- .../internal/AgiConnectionHandler.java | 14 ++++-- .../org/asteriskjava/pbx/agi/ActivityAgi.java | 2 +- .../pbx/internal/core/ChannelProxy.java | 7 ++- .../managerAPI/OriginateBaseClass.java | 45 ++++++++++++------- 4 files changed, 44 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java index 5d5a0e6aa..f5554fe90 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java @@ -169,10 +169,11 @@ else if (script != null) private void runScript(AgiScript script, AgiRequest request, AgiChannel channel) { + String channelName = channel.getName(); String threadName; threadName = Thread.currentThread().getName(); - logger.debug("Begin AgiScript " + getScriptName(script) + " on " + threadName); + logger.debug("Begin AgiScript " + describeAgiCall(threadName, channelName)); try { script.service(request, channel); @@ -180,15 +181,20 @@ private void runScript(AgiScript script, AgiRequest request, AgiChannel channel) } catch (AgiException e) { - logger.error("AgiException running AgiScript " + getScriptName(script) + " on " + threadName, e); + logger.error("AgiException running AgiScript " + describeAgiCall(threadName, channelName), e); setStatusVariable(channel, AJ_AGISTATUS_FAILED); } catch (Exception e) { - logger.error("Exception running AgiScript " + getScriptName(script) + " on " + threadName, e); + logger.error("Exception running AgiScript " + describeAgiCall(threadName, channelName), e); setStatusVariable(channel, AJ_AGISTATUS_FAILED); } - logger.debug("End AgiScript " + getScriptName(script) + " on " + threadName); + logger.debug("End AgiScript " + describeAgiCall(threadName, channelName)); + } + + private String describeAgiCall(String threadName, String channelName) + { + return getScriptName(script) + " on " + threadName + " on " + channelName; } protected String getScriptName(AgiScript script) diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index c2ddf7198..7e051271f 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -76,7 +76,7 @@ public void service() throws AgiException } - logger.info("Channel " + channelName + " arrived in agi"); + logger.warn("Channel " + channelName + " arrived in agi"); channelProxy.setIsInAgi(true); channelProxy.addHangupListener(new ChannelHangupListener() diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index 4662d6932..f13772762 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -370,7 +370,7 @@ public void setIsInAgi(boolean b) hasReachedAgi.countDown(); } isInAgi = b; - logger.debug("Setting is in agi to " + b + " for channel " + this); + logger.warn("Setting is in agi to " + b + " for channel " + this); } @@ -385,7 +385,10 @@ public boolean isInAgi() @Override public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException { - return hasReachedAgi.await(timeout, timeunit); + logger.warn("Waiting for channel to reach agi " + this); + boolean tmp = hasReachedAgi.await(timeout, timeunit); + logger.warn("Result of waiting for channel to reach agi " + this + " " + tmp); + return tmp; } @Override diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index a93d66d0d..984f0ea2a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -4,6 +4,7 @@ import java.util.HashSet; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import org.asteriskjava.live.ManagerCommunicationException; @@ -77,6 +78,8 @@ public abstract class OriginateBaseClass extends EventListenerBaseClass private String channelId; + private final AtomicInteger managerEventsSeen = new AtomicInteger(); + protected OriginateBaseClass(final NewChannelListener listener, final Channel monitor, final Channel monitor2) { super("NewOrginateClass", PBXFactory.getActivePBX()); @@ -102,7 +105,7 @@ protected OriginateBaseClass(final NewChannelListener listener, final Channel mo OriginateResult originate(final EndPoint local, final EndPoint target, final HashMap myVars, final CallerID callerID, final Integer timeout, final boolean hideCallerId, final String context) { - OriginateBaseClass.logger.debug("originate called"); + OriginateBaseClass.logger.warn("originate called"); this.originateSeen = false; this.channelSeen = false; @@ -113,7 +116,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has return null; } - OriginateBaseClass.logger.debug("originate connection endPoint \n" + local + " to endPoint " + target //$NON-NLS-2$ + OriginateBaseClass.logger.warn("originate connection endPoint \n" + local + " to endPoint " + target //$NON-NLS-2$ + " vars " + myVars); ManagerResponse response = null; @@ -182,7 +185,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has this.startListener(); response = pbx.sendAction(originate, localTimeout); - OriginateBaseClass.logger.debug("Originate.sendAction completed"); + OriginateBaseClass.logger.warn("Originate.sendAction completed"); if (response.getResponse().compareToIgnoreCase("Success") != 0) { OriginateBaseClass.logger @@ -192,7 +195,10 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has // wait the set timeout +1 second to allow for // asterisk to start the originate - originateLatch.await(localTimeout + 1000, TimeUnit.MILLISECONDS); + if (!originateLatch.await(localTimeout + 1000, TimeUnit.MILLISECONDS)) + { + logger.error("Originate Latch timed out"); + } } catch (final InterruptedException e) { @@ -211,7 +217,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has { this.result.setSuccess(true); this.result.setChannelData(this.newChannel); - OriginateBaseClass.logger.debug("new channel ok: " + this.newChannel); + OriginateBaseClass.logger.warn("new channel ok: " + this.newChannel); } else { @@ -221,7 +227,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has { try { - logger.info("Hanging up"); + logger.warn("Hanging up"); pbx.hangup(this.newChannel); } catch (IllegalArgumentException | IllegalStateException | PBXException e) @@ -231,12 +237,15 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has } } } + + logger.warn("Manager Events seen " + managerEventsSeen.get()); + return this.result; } void abort(final String reason) { - OriginateBaseClass.logger.debug("Aborting originate "); + OriginateBaseClass.logger.warn("Aborting originate "); this.originateSuccess = false; this.result.setAbortReason(reason); this.hungup = true; @@ -288,6 +297,7 @@ void abort(final String reason) synchronized public void onManagerEvent(final ManagerEvent event) { + managerEventsSeen.getAndIncrement(); if (event instanceof HangupEvent) { final HangupEvent hangupEvt = (HangupEvent) event; @@ -305,7 +315,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) this.hungup = true; if (this.newChannel != null) { - OriginateBaseClass.logger.debug("hanging up " + this.newChannel); + OriginateBaseClass.logger.warn("hanging up " + this.newChannel); this.result.setChannelHungup(true); PBX pbx = PBXFactory.getActivePBX(); @@ -320,7 +330,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) } } - OriginateBaseClass.logger.debug("notify channel 1 hungup"); + OriginateBaseClass.logger.warn("notify channel 1 hungup"); originateLatch.countDown(); } if ((this.monitorChannel2 != null) && (hangupChannel.isSame(this.monitorChannel2))) @@ -329,7 +339,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) this.hungup = true; if (this.newChannel != null) { - OriginateBaseClass.logger.debug("Hanging up channel " + this.newChannel); + OriginateBaseClass.logger.warn("Hanging up channel " + this.newChannel); this.result.setChannelHungup(true); PBX pbx = PBXFactory.getActivePBX(); @@ -343,7 +353,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) } } - OriginateBaseClass.logger.debug("Notify channel 2 (" + this.monitorChannel2 + ") hungup");//$NON-NLS-2$ + OriginateBaseClass.logger.warn("Notify channel 2 (" + this.monitorChannel2 + ") hungup");//$NON-NLS-2$ originateLatch.countDown(); } @@ -362,7 +372,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) if (this.originateID.compareToIgnoreCase(response.getActionId()) == 0) { this.originateSuccess = response.isSuccess(); - OriginateBaseClass.logger.debug("OriginateResponse: matched actionId, success=" + this.originateSuccess + OriginateBaseClass.logger.warn("OriginateResponse: matched actionId, success=" + this.originateSuccess + " channelSeen=" + this.channelSeen); this.originateSeen = true; @@ -383,7 +393,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) // notify. if (this.channelSeen) { - OriginateBaseClass.logger.info("notify originate response event " + this.originateSuccess); + OriginateBaseClass.logger.warn("notify originate response event " + this.originateSuccess); originateLatch.countDown(); } else @@ -406,7 +416,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) { final Channel channel = newState.getChannel(); - OriginateBaseClass.logger.debug("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-2$ + OriginateBaseClass.logger.warn("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-2$ + " state =" + newState.getChannelStateDesc() + " state =" + newState.getChannelState()); //$NON-NLS-2$ handleId(channel); @@ -428,7 +438,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) { OriginateBaseClass.logger - .debug("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ + .warn("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ + " channel2 =" + bridgeEvent.getChannel2()); handleId(channel); @@ -444,6 +454,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) String forward = ((DialEndEvent) event).getForward(); if (forward != null && forward.length() > 0) { + logger.warn("DialEndEvent"); originateLatch.countDown(); } } @@ -458,7 +469,7 @@ private void handleId(Channel channel) this.newChannel = channel; this.channelSeen = true; - OriginateBaseClass.logger.info("new channel name " + channel); + OriginateBaseClass.logger.warn("new channel name " + channel); if (this.listener != null) { /* @@ -470,7 +481,7 @@ private void handleId(Channel channel) if (this.originateSeen) { - OriginateBaseClass.logger.debug("notifying success 362"); + OriginateBaseClass.logger.warn("notifying success 362"); originateLatch.countDown(); } } From 28a7e436df4760567a3efad2ef42a0b54ebf7de0 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 2 Jul 2020 13:40:26 +1000 Subject: [PATCH 364/802] for version 3.5.1-SNAPSHOT --- pom.xml | 2 +- .../manager/action/ExecAction.java | 99 +++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/asteriskjava/manager/action/ExecAction.java diff --git a/pom.xml b/pom.xml index 61dff1825..9855dd3bf 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.5.0 + 3.5.1-SNAPSHOT UTF-8 diff --git a/src/main/java/org/asteriskjava/manager/action/ExecAction.java b/src/main/java/org/asteriskjava/manager/action/ExecAction.java new file mode 100644 index 000000000..3a80a702a --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/ExecAction.java @@ -0,0 +1,99 @@ +/* + * 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.manager.action; + +import org.asteriskjava.manager.ExpectedResponse; +import org.asteriskjava.manager.response.CommandResponse; + +/** + * The CommandAction sends a command line interface (CLI) command to the + * asterisk server. + *

    + * For a list of supported commands type help on Asterisk's command + * line. + *

    + * In response to a CommandAction you will receive a CommandResponse that + * contains the CLI output. + *

    + * Example: + * + *

    + * CommandAction commandAction = new CommandAction("iax2 show peers");
    + * CommandResponse response = (CommandResponse) c.sendAction(commandAction);
    + * for (String line : response.getResult())
    + * {
    + *     System.out.println(line);
    + * }
    + * 
    + * + * Where c is an instance of + * {@link org.asteriskjava.manager.ManagerConnection}. + * + * @author srt + * @version $Id$ + * @see org.asteriskjava.manager.response.CommandResponse + */ +@ExpectedResponse(CommandResponse.class) +public class ExecAction extends AbstractManagerAction +{ + static final long serialVersionUID = 4753117770471622025L; + protected String command; + + /** + * Creates a new CommandAction. + */ + public ExecAction() + { + + } + + /** + * Creates a new CommandAction with the given command. + * + * @param command the CLI command to execute. + * @since 0.2 + */ + public ExecAction(String command) + { + this.command = command; + } + + /** + * Returns the name of this action, i.e. "Command". + */ + @Override + public String getAction() + { + return "exec"; + } + + /** + * Returns the command. + */ + public String getCommand() + { + return command; + } + + /** + * Sets the CLI command to send to the Asterisk server. + */ + public void setCommand(String command) + { + this.command = command; + } +} From 97e98892224607a5e1000d319f9d4e9a7782e879 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 8 Jul 2020 16:30:38 +1000 Subject: [PATCH 365/802] add checks for badly behaved event handlers and recover. --- .../core/CoherentManagerEventQueue.java | 109 +++++++++--------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index 84fb33e2b..217b85be7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -39,15 +39,13 @@ class CoherentManagerEventQueue implements ManagerEventListener, Runnable private final ListenerManager listeners = new ListenerManager(); - private boolean _stop = false; - private final Thread _th; - private final BlockingQueue> _eventQueue = new LinkedBlockingQueue<>(); + private volatile boolean _stop = false; - private int _queueMaxSize; + private static final int QUEUE_SIZE = 1000; + private final BlockingQueue> _eventQueue = new LinkedBlockingQueue<>( + QUEUE_SIZE); - private long _queueSum; - - private long _queueCount; + long suppressQueueSizeErrorUntil = 0; private HashSet> globalEvents = new HashSet<>(); @@ -56,10 +54,10 @@ public CoherentManagerEventQueue(String name, ManagerConnection connection) connection.addEventListener(this); - this._th = new Thread(this); - this._th.setName("EventQueue: " + name);//$NON-NLS-1$ - this._th.setDaemon(true); - this._th.start(); + Thread _th = new Thread(this); + _th.setName("EventQueue: " + name);//$NON-NLS-1$ + _th.setDaemon(true); + _th.start(); } /** @@ -89,65 +87,65 @@ public void onManagerEvent(final org.asteriskjava.manager.event.ManagerEvent eve if (wanted) { - // We don't support all events. this._eventQueue.add(new EventLifeMonitor<>(event)); - final int queueSize = this._eventQueue.size(); - if (this._queueMaxSize < queueSize) + if (_eventQueue.remainingCapacity() < QUEUE_SIZE / 10 + && suppressQueueSizeErrorUntil < System.currentTimeMillis()) { - this._queueMaxSize = queueSize; + suppressQueueSizeErrorUntil = System.currentTimeMillis() + 1000; + logger.error("EventQueue more than 90% full"); } - this._queueSum += queueSize; - this._queueCount++; - if (CoherentManagerEventQueue.logger.isDebugEnabled()) - { - if (this._eventQueue.size() > ((this._queueMaxSize + (this._queueSum / this._queueCount)) / 2)) - { - CoherentManagerEventQueue.logger.debug("queue gtr max avg: size=" + queueSize + " max:" //$NON-NLS-1$ //$NON-NLS-2$ - + this._queueMaxSize + " avg:" + (this._queueSum / this._queueCount)); //$NON-NLS-1$ - } - } } } @Override public void run() { - - while (!this._stop) + try { - try + while (!this._stop) { - final EventLifeMonitor elm = this._eventQueue.poll(2, - TimeUnit.SECONDS); - if (elm != null) + try { - // A poison queue event means its time to shutdown. - if (elm.getEvent().getClass() == PoisonQueueEvent.class) - break; - - final ManagerEvent iEvent = CoherentEventFactory.build(elm.getEvent()); - if (iEvent != null) + final EventLifeMonitor elm = this._eventQueue.poll(2, + TimeUnit.SECONDS); + if (elm != null) { - dispatchEvent(iEvent); - elm.assessAge(); + // A poison queue event means its time to shutdown. + if (elm.getEvent().getClass() == PoisonQueueEvent.class) + { + logger.warn("Got Poison event"); + break; + } + + final ManagerEvent iEvent = CoherentEventFactory.build(elm.getEvent()); + if (iEvent != null) + { + dispatchEvent(iEvent); + elm.assessAge(); + } } } - } - catch (final Exception e) - { - /** - * If an exception is thrown whilst we are shutting down then we - * don't care. If it is thrown when we aren't shutting down then - * we have a problem and we need to log it. - */ - if (!this._stop) + catch (final Exception e) { - CoherentManagerEventQueue.logger.error(e, e); + /** + * If an exception is thrown whilst we are shutting down + * then we don't care. If it is thrown when we aren't + * shutting down then we have a problem and we need to log + * it. + */ + if (!this._stop) + { + CoherentManagerEventQueue.logger.error(e, e); + } } - } + } + } + finally + { + logger.warn("Shutting down!"); } } @@ -177,8 +175,8 @@ public void stop() } } - // TODO: make this multi threaded - private final ExecutorService executors = Executors.newFixedThreadPool(1); + // + private final ExecutorService executors = Executors.newCachedThreadPool(); /** * Events are sent here from the CoherentManagerEventQueue after being @@ -222,9 +220,12 @@ public void dispatchEvent(final ManagerEvent event) } } - latch.await(); + if (!latch.await(2, TimeUnit.SECONDS)) + { + logger.error("Timeout waiting for event to be processed " + event); + } - if (totalTime.timeTaken() > 500) + if (totalTime.timeTaken() > 100) { logger.warn("Too long to process event " + event + " time taken: " + totalTime.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$ } From 24f98eabaa7982534e8386aab34f1279cef1d4d3 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 8 Jul 2020 16:37:30 +1000 Subject: [PATCH 366/802] for version 3.5.2-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9855dd3bf..a35f5cc0f 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.5.1-SNAPSHOT + 3.5.2-SNAPSHOT UTF-8 From 35a2a59eef495cc61c920be03d350724203a0cbf Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Jul 2020 10:33:07 +1000 Subject: [PATCH 367/802] make agi available to AgiChannelActivity isDisconnect callback method --- .../internal/AgiConnectionHandler.java | 5 +- .../pbx/AgiChannelActivityAction.java | 7 +-- .../org/asteriskjava/pbx/agi/ActivityAgi.java | 2 +- .../agi/AgiChannelActivityBlindTransfer.java | 2 +- .../pbx/agi/AgiChannelActivityBridge.java | 2 +- .../pbx/agi/AgiChannelActivityDial.java | 2 +- .../pbx/agi/AgiChannelActivityHangup.java | 2 +- .../pbx/agi/AgiChannelActivityHold.java | 2 +- .../agi/AgiChannelActivityHoldForBridge.java | 2 +- .../pbx/agi/AgiChannelActivityMeetme.java | 2 +- .../agi/AgiChannelActivityPlayMessage.java | 2 +- .../pbx/agi/AgiChannelActivityQueue.java | 2 +- ...giChannelActivityTransientHoldSilence.java | 2 +- .../pbx/agi/AgiChannelActivityVoicemail.java | 52 +++++++++---------- 14 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java index f5554fe90..f465f998d 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java @@ -189,7 +189,10 @@ private void runScript(AgiScript script, AgiRequest request, AgiChannel channel) logger.error("Exception running AgiScript " + describeAgiCall(threadName, channelName), e); setStatusVariable(channel, AJ_AGISTATUS_FAILED); } - logger.debug("End AgiScript " + describeAgiCall(threadName, channelName)); + finally + { + logger.debug("End AgiScript " + describeAgiCall(threadName, channelName)); + } } private String describeAgiCall(String threadName, String channelName) diff --git a/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java b/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java index 8e150d008..6ecebf799 100644 --- a/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java +++ b/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java @@ -2,14 +2,15 @@ import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.pbx.agi.ActivityAgi; public interface AgiChannelActivityAction { - void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException; + void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException; - boolean isDisconnect(); + boolean isDisconnect(ActivityAgi activityAgi); - void cancel(); + void cancel(); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index 7e051271f..a3e68c57c 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -112,7 +112,7 @@ public void channelHangup(Channel channel, Integer cause, String causeText) boolean isAlive = true; RateLimiter rateLimiter = new RateLimiter(2); - while (!action.isDisconnect() && isAlive) + while (!action.isDisconnect(this) && isAlive) { action.execute(this.channel, channelProxy); diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java index 8497cb85a..888865843 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java @@ -49,7 +49,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect() + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java index 617a90ab7..afa8c805e 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java @@ -48,7 +48,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect() + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java index bbfdeaeca..e4d2924d6 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java @@ -47,7 +47,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect() + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java index dbc2bc240..300067bab 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java @@ -33,7 +33,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect() + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java index 308a224f3..a6a02aa56 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java @@ -65,7 +65,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect() + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java index 1be5c4506..973fd7a7f 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java @@ -40,7 +40,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect() + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java index 7746b2568..b9f32b9ef 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java @@ -62,7 +62,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect() + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java index 5e4318828..867e48dd8 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java @@ -50,7 +50,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect() + public boolean isDisconnect(ActivityAgi activityAgi) { return hangup; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java index 327c68314..ef61c40b0 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java @@ -60,7 +60,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect() + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java index a488030bc..fe3bcd433 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java @@ -54,7 +54,7 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect() + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java index 560b35c48..228c47501 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java @@ -8,30 +8,30 @@ public class AgiChannelActivityVoicemail implements AgiChannelActivityAction { - public AgiChannelActivityVoicemail(String mailbox) - { - // TODO Auto-generated constructor stub - } - - @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { - // TODO Auto-generated method stub - - } - - @Override - public boolean isDisconnect() - { - // TODO Auto-generated method stub - return false; - } - - @Override - public void cancel() - { - // TODO Auto-generated method stub - - } - // Logger logger = LogManager.getLogger(); + public AgiChannelActivityVoicemail(String mailbox) + { + // TODO Auto-generated constructor stub + } + + @Override + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException + { + // TODO Auto-generated method stub + + } + + @Override + public boolean isDisconnect(ActivityAgi activityAgi) + { + // TODO Auto-generated method stub + return false; + } + + @Override + public void cancel() + { + // TODO Auto-generated method stub + + } + // Logger logger = LogManager.getLogger(); } From fc1df25cee96442b07976604e71e64acbf20adec Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Jul 2020 10:33:51 +1000 Subject: [PATCH 368/802] for version 3.6.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a35f5cc0f..692f83b52 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.5.2-SNAPSHOT + 3.6.0 UTF-8 From 10279d492d8137a25575aba00f5c0a1b6ed6ab2d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Jul 2020 14:06:43 +1000 Subject: [PATCH 369/802] Update README.md change version to 3.6.0 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc0083bea..c1eb5bdf4 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 16) (master) org.asteriskjava asterisk-java - 3.4.0 + 3.6.0 Asterisk-Java 2.x (Java 1.7 and Asterisk < Version 10) (branch 2.0.4) From 87595c2a03f8993930e0658596e6126d1ae9e3bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Ba=C5=84kowski?= Date: Thu, 16 Jul 2020 16:44:00 +0200 Subject: [PATCH 370/802] Fixing possibility of adding duplicate entries to list of AsteriskQueueEntryImpl. --- .../live/internal/AsteriskQueueImpl.java | 31 ++++++++------ .../live/internal/QueueManager.java | 40 ++++++------------- 2 files changed, 32 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java index 989f72531..173da9ed7 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java @@ -354,20 +354,16 @@ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date date { AsteriskQueueEntryImpl qe = new AsteriskQueueEntryImpl(server, this, channel, reportedPosition, dateReceived); - long delay = serviceLevel * 1000L; - if (delay > 0) - { - ServiceLevelTimerTask timerTask = new ServiceLevelTimerTask(qe); - timer.schedule(timerTask, delay); - synchronized (serviceLevelTimerTasks) - { - serviceLevelTimerTasks.put(qe, timerTask); - } - } - synchronized (entries) { - entries.add(qe); // at the end of the list + if (getEntry(channel.getName()) != null) + { + logger.debug("Ignored duplicate queue entry during population in queue " + name + " for channel " + + channel.getName()); + return; + } + + entries.add(qe); // at the end of the list // Keep the lock ! // This will fire PCE on the newly created queue entry @@ -375,6 +371,17 @@ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date date shift(); } + long delay = serviceLevel * 1000L; + if (delay > 0) + { + ServiceLevelTimerTask timerTask = new ServiceLevelTimerTask(qe); + timer.schedule(timerTask, delay); + synchronized (serviceLevelTimerTasks) + { + serviceLevelTimerTasks.put(qe, timerTask); + } + } + // Set the channel property ony here as queue entries and channels // maintain a reciprocal reference. // That way property change on channel and new entry event on queue will be diff --git a/src/main/java/org/asteriskjava/live/internal/QueueManager.java b/src/main/java/org/asteriskjava/live/internal/QueueManager.java index ce41982bc..f390c88fc 100644 --- a/src/main/java/org/asteriskjava/live/internal/QueueManager.java +++ b/src/main/java/org/asteriskjava/live/internal/QueueManager.java @@ -47,7 +47,7 @@ /** * Manages queue events on behalf of an AsteriskServer. - * + * * @author srt * @version $Id$ */ @@ -117,7 +117,7 @@ else if (event instanceof QueueEntryEvent) /** * Method to ask for a Queue data update - * + * * @author Octavio Luna * @param queue * @throws ManagerCommunicationException @@ -182,7 +182,7 @@ void disconnected() /** * Gets (a copy of) the list of the queues. - * + * * @return a copy of the list of the queues. */ Collection getQueues() @@ -227,7 +227,7 @@ public List getQueuesUpdatedAfter(Date date) /** * Adds a queue to the internal map, keyed by name. - * + * * @param queue the AsteriskQueueImpl to be added */ private void addQueue(AsteriskQueueImpl queue) @@ -240,7 +240,7 @@ private void addQueue(AsteriskQueueImpl queue) /** * Called during initialization to populate the list of queues. - * + * * @param event the event received */ private void handleQueueParamsEvent(QueueParamsEvent event) @@ -294,7 +294,7 @@ private void handleQueueParamsEvent(QueueParamsEvent event) /** * Called during initialization to populate the members of the queues. - * + * * @param event the QueueMemberEvent received */ private void handleQueueMemberEvent(QueueMemberEvent event) @@ -335,7 +335,7 @@ private void manageQueueMemberChange(AsteriskQueueImpl queue, AsteriskQueueMembe /** * Called during initialization to populate entries of the queues. Currently * does the same as handleJoinEvent() - * + * * @param event - the QueueEntryEvent received */ private void handleQueueEntryEvent(QueueEntryEvent event) @@ -354,13 +354,6 @@ private void handleQueueEntryEvent(QueueEntryEvent event) return; } - if (queue.getEntry(event.getChannel()) != null) - { - logger.debug("Ignored duplicate queue entry during population in queue " + event.getQueue() + " for channel " - + event.getChannel()); - return; - } - // Asterisk gives us an initial position but doesn't tell us when he // shifts the others // We won't use this data for ordering until there is a appropriate @@ -375,7 +368,7 @@ private void handleQueueEntryEvent(QueueEntryEvent event) /** * Called from AsteriskServerImpl whenever a new entry appears in a queue. - * + * * @param event the JoinEvent received */ void handleJoinEvent(JoinEvent event) @@ -394,13 +387,6 @@ void handleJoinEvent(JoinEvent event) return; } - if (queue.getEntry(event.getChannel()) != null) - { - logger.error( - "Ignored duplicate queue entry in queue " + event.getQueue() + " for channel " + event.getChannel()); - return; - } - // Asterisk gives us an initial position but doesn't tell us when he // shifts the others // We won't use this data for ordering until there is a appropriate @@ -415,7 +401,7 @@ void handleJoinEvent(JoinEvent event) /** * Called from AsteriskServerImpl whenever an enty leaves a queue. - * + * * @param event - the LeaveEvent received */ void handleLeaveEvent(LeaveEvent event) @@ -448,7 +434,7 @@ void handleLeaveEvent(LeaveEvent event) /** * Challange a QueueMemberStatusEvent. Called from AsteriskServerImpl * whenever a member state changes. - * + * * @param event that was triggered by Asterisk server. */ void handleQueueMemberStatusEvent(QueueMemberStatusEvent event) @@ -514,7 +500,7 @@ void handleQueueMemberPenaltyEvent(QueueMemberPenaltyEvent event) /** * Retrieves a queue by its name. - * + * * @param queueName name of the queue. * @return the requested queue or null if there is no queue * with the given name. @@ -562,7 +548,7 @@ private void refreshQueuesIfForced() /** * Challange a QueueMemberAddedEvent. - * + * * @param event - the generated QueueMemberAddedEvent. */ public void handleQueueMemberAddedEvent(QueueMemberAddedEvent event) @@ -587,7 +573,7 @@ public void handleQueueMemberAddedEvent(QueueMemberAddedEvent event) /** * Challange a QueueMemberRemovedEvent. - * + * * @param event - the generated QueueMemberRemovedEvent. */ public void handleQueueMemberRemovedEvent(QueueMemberRemovedEvent event) From 8329036ae4f577b166fec4c1e6ee9845ce91f181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Ba=C5=84kowski?= Date: Tue, 28 Jul 2020 10:48:10 +0200 Subject: [PATCH 371/802] Added a debug level check (#337). --- .../org/asteriskjava/live/internal/AsteriskQueueImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java index 173da9ed7..13f53c2ab 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java @@ -358,8 +358,11 @@ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date date { if (getEntry(channel.getName()) != null) { - logger.debug("Ignored duplicate queue entry during population in queue " + name + " for channel " - + channel.getName()); + if (logger.isDebugEnabled()) + { + logger.debug("Ignored duplicate queue entry during population in queue " + name + " for channel " + + channel.getName()); + } return; } From 5b5550eaa1f32903c278d68b01f0c54be6161bad Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Aug 2020 17:22:53 +1000 Subject: [PATCH 372/802] clean up some warnings for spot bugs --- .../manager/AbstractManagerEventListener.java | 981 +++++++++++------- .../internal/ManagerConnectionImpl.java | 22 +- .../internal/ProtocolIdentifierWrapper.java | 4 +- .../manager/internal/ResponseEventsImpl.java | 5 +- ...giChannelActivityTransientHoldSilence.java | 5 +- .../internal/activity/ParkActivityImpl.java | 5 +- .../pbx/internal/managerAPI/Dial.java | 5 +- 7 files changed, 611 insertions(+), 416 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 3e5bcb677..79bc4190a 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -1,11 +1,11 @@ package org.asteriskjava.manager; +import java.lang.reflect.Method; + import org.asteriskjava.manager.event.*; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -import java.lang.reflect.Method; - /** * Utility class that provides a protected handler method for each concrete * manager event. Makes life easier by removing the need to code endless @@ -62,552 +62,735 @@ * @author srt * @since 0.3 */ -public abstract class AbstractManagerEventListener implements ManagerEventListener { - - private static final Log LOGGER = LogFactory.getLog(AbstractManagerEventListener.class); - - public void handleEvent(AgentCompleteEvent event) { - } - - public void handleEvent(AgentConnectEvent event) { - } - - public void handleEvent(AgentDumpEvent event) { - } - - public void handleEvent(AgentRingNoAnswerEvent event) { - } - - public void handleEvent(AttendedTransferEvent event) { - } - - public void handleEvent(BlindTransferEvent event) { - } - - public void handleEvent(BridgeCreateEvent event) { - } - - public void handleEvent(BridgeDestroyEvent event) { - } - - public void handleEvent(BridgeEnterEvent event) { - } - - public void handleEvent(BridgeLeaveEvent event) { - } - - public void handleEvent(HangupEvent event) { - } - - public void handleEvent(NewChannelEvent event) { - } - - public void handleEvent(NewStateEvent event) { - } - - public void handleEvent(ConfbridgeEndEvent event) { - } - - public void handleEvent(ConfbridgeJoinEvent event) { - } - - public void handleEvent(ConfbridgeLeaveEvent event) { - } - - public void handleEvent(ConfbridgeStartEvent event) { - } - - public void handleEvent(ConfbridgeTalkingEvent event) { - } - - public void handleEvent(AntennaLevelEvent event) { - } - - public void handleEvent(HangupRequestEvent event) { - } - - public void handleEvent(NewCallerIdEvent event) { - } - - public void handleEvent(SoftHangupRequestEvent event) { - } - - public void handleEvent(FaxDocumentStatusEvent event) { - } - - public void handleEvent(FaxReceivedEvent event) { - } - - public void handleEvent(FaxStatusEvent event) { - } - - public void handleEvent(SendFaxEvent event) { - } +public abstract class AbstractManagerEventListener implements ManagerEventListener +{ - public void handleEvent(SendFaxStatusEvent event) { - } + private static final Log LOGGER = LogFactory.getLog(AbstractManagerEventListener.class); - public void handleEvent(T38FaxStatusEvent event) { - } + public void handleEvent(AgentCompleteEvent event) + { + } - public void handleEvent(HoldEvent event) { - } + public void handleEvent(AgentConnectEvent event) + { + } - public void handleEvent(UnholdEvent event) { - } + public void handleEvent(AgentDumpEvent event) + { + } - public void handleEvent(MeetMeJoinEvent event) { - } + public void handleEvent(AgentRingNoAnswerEvent event) + { + } - public void handleEvent(MeetMeLeaveEvent event) { - } + public void handleEvent(AttendedTransferEvent event) + { + } - public void handleEvent(MeetMeMuteEvent event) { - } + public void handleEvent(BlindTransferEvent event) + { + } - public void handleEvent(MeetMeTalkingEvent event) { - } + public void handleEvent(BridgeCreateEvent event) + { + } - public void handleEvent(MeetMeTalkingRequestEvent event) { - } + public void handleEvent(BridgeDestroyEvent event) + { + } - public void handleEvent(MonitorStartEvent event) { - } + public void handleEvent(BridgeEnterEvent event) + { + } - public void handleEvent(MonitorStopEvent event) { - } + public void handleEvent(BridgeLeaveEvent event) + { + } - public void handleEvent(ParkedCallEvent event) { - } + public void handleEvent(HangupEvent event) + { + } - public void handleEvent(QueueMemberAddedEvent event) { - } + public void handleEvent(NewChannelEvent event) + { + } - public void handleEvent(QueueMemberPausedEvent event) { - } + public void handleEvent(NewStateEvent event) + { + } - public void handleEvent(QueueMemberRemovedEvent event) { - } + public void handleEvent(ConfbridgeEndEvent event) + { + } - public void handleEvent(RtcpReceivedEvent event) { - } + public void handleEvent(ConfbridgeJoinEvent event) + { + } - public void handleEvent(RtcpSentEvent event) { - } + public void handleEvent(ConfbridgeLeaveEvent event) + { + } - public void handleEvent(RtpReceiverStatEvent event) { - } + public void handleEvent(ConfbridgeStartEvent event) + { + } - public void handleEvent(RtpSenderStatEvent event) { - } + public void handleEvent(ConfbridgeTalkingEvent event) + { + } - public void handleEvent(AgentCallbackLoginEvent event) { - } + public void handleEvent(AntennaLevelEvent event) + { + } - public void handleEvent(AgentCallbackLogoffEvent event) { - } + public void handleEvent(HangupRequestEvent event) + { + } - public void handleEvent(AgentCalledEvent event) { - } + public void handleEvent(NewCallerIdEvent event) + { + } - public void handleEvent(AgentLoginEvent event) { - } + public void handleEvent(SoftHangupRequestEvent event) + { + } - public void handleEvent(AgentLogoffEvent event) { - } + public void handleEvent(FaxDocumentStatusEvent event) + { + } - public void handleEvent(AgiExecEvent event) { - } + public void handleEvent(FaxReceivedEvent event) + { + } - public void handleEvent(AgiExecEndEvent event) { - } + public void handleEvent(FaxStatusEvent event) + { + } - public void handleEvent(AgiExecStartEvent event) { - } + public void handleEvent(SendFaxEvent event) + { + } - public void handleEvent(AlarmClearEvent event) { - } + public void handleEvent(SendFaxStatusEvent event) + { + } - public void handleEvent(AlarmEvent event) { - } + public void handleEvent(T38FaxStatusEvent event) + { + } - public void handleEvent(BridgeEvent event) { - } + public void handleEvent(HoldEvent event) + { + } - public void handleEvent(LinkEvent event) { - } + public void handleEvent(UnholdEvent event) + { + } - public void handleEvent(UnlinkEvent event) { - } + public void handleEvent(MeetMeJoinEvent event) + { + } - public void handleEvent(BridgeExecEvent event) { - } + public void handleEvent(MeetMeLeaveEvent event) + { + } - public void handleEvent(BridgeMergeEvent event) { - } + public void handleEvent(MeetMeMuteEvent event) + { + } - public void handleEvent(CdrEvent event) { - } + public void handleEvent(MeetMeTalkingEvent event) + { + } - public void handleEvent(CelEvent event) { - } + public void handleEvent(MeetMeTalkingRequestEvent event) + { + } - public void handleEvent(ChallengeResponseFailedEvent event) { - } + public void handleEvent(MonitorStartEvent event) + { + } - public void handleEvent(ChallengeSentEvent event) { - } + public void handleEvent(MonitorStopEvent event) + { + } - public void handleEvent(ChannelReloadEvent event) { - } + public void handleEvent(ParkedCallEvent event) + { + } - public void handleEvent(ChannelUpdateEvent event) { - } + public void handleEvent(QueueMemberAddedEvent event) + { + } - public void handleEvent(ChanSpyStartEvent event) { - } + public void handleEvent(QueueMemberPausedEvent event) + { + } - public void handleEvent(ChanSpyStopEvent event) { - } + public void handleEvent(QueueMemberRemovedEvent event) + { + } - public void handleEvent(ConnectEvent event) { - } + public void handleEvent(RtcpReceivedEvent event) + { + } - public void handleEvent(ContactStatusEvent event) { - } + public void handleEvent(RtcpSentEvent event) + { + } - public void handleEvent(DAHDIChannelEvent event) { - } + public void handleEvent(RtpReceiverStatEvent event) + { + } - public void handleEvent(DeviceStateChangeEvent event) { - } + public void handleEvent(RtpSenderStatEvent event) + { + } - public void handleEvent(DialEvent event) { - } + public void handleEvent(AgentCallbackLoginEvent event) + { + } - public void handleEvent(DialBeginEvent event) { - } + public void handleEvent(AgentCallbackLogoffEvent event) + { + } - public void handleEvent(DialEndEvent event) { - } + public void handleEvent(AgentCalledEvent event) + { + } - public void handleEvent(DialStateEvent event) { - } + public void handleEvent(AgentLoginEvent event) + { + } - public void handleEvent(DisconnectEvent event) { - } + public void handleEvent(AgentLogoffEvent event) + { + } - public void handleEvent(DndStateEvent event) { - } + public void handleEvent(AgiExecEvent event) + { + } - public void handleEvent(DongleCallStateChangeEvent event) { - } + public void handleEvent(AgiExecEndEvent event) + { + } - public void handleEvent(DongleCENDEvent event) { - } + public void handleEvent(AgiExecStartEvent event) + { + } - public void handleEvent(DongleNewCMGREvent event) { - } + public void handleEvent(AlarmClearEvent event) + { + } - public void handleEvent(DongleNewSMSBase64Event event) { - } + public void handleEvent(AlarmEvent event) + { + } - public void handleEvent(DongleNewSMSEvent event) { - } + public void handleEvent(BridgeEvent event) + { + } - public void handleEvent(DongleStatusEvent event) { - } + @SuppressWarnings("deprecation") + public void handleEvent(LinkEvent event) + { + } + + @SuppressWarnings("deprecation") + public void handleEvent(UnlinkEvent event) + { + } - public void handleEvent(DtmfEvent event) { - } + public void handleEvent(BridgeExecEvent event) + { + } - public void handleEvent(DtmfBeginEvent event) { - } + public void handleEvent(BridgeMergeEvent event) + { + } - public void handleEvent(DtmfEndEvent event) { - } + public void handleEvent(CdrEvent event) + { + } - public void handleEvent(ExtensionStatusEvent event) { - } + public void handleEvent(CelEvent event) + { + } - public void handleEvent(FullyBootedEvent event) { - } + public void handleEvent(ChallengeResponseFailedEvent event) + { + } - public void handleEvent(HoldedCallEvent event) { - } + public void handleEvent(ChallengeSentEvent event) + { + } - public void handleEvent(InvalidPasswordEvent event) { - } + public void handleEvent(ChannelReloadEvent event) + { + } - public void handleEvent(JabberEventEvent event) { - } + public void handleEvent(ChannelUpdateEvent event) + { + } - public void handleEvent(JitterBufStatsEvent event) { - } + public void handleEvent(ChanSpyStartEvent event) + { + } - public void handleEvent(LocalBridgeEvent event) { - } + public void handleEvent(ChanSpyStopEvent event) + { + } - public void handleEvent(LocalOptimizationBeginEvent event) { - } + public void handleEvent(ConnectEvent event) + { + } - public void handleEvent(LocalOptimizationEndEvent event) { - } + public void handleEvent(ContactStatusEvent event) + { + } - public void handleEvent(LogChannelEvent event) { - } + public void handleEvent(DAHDIChannelEvent event) + { + } - public void handleEvent(MasqueradeEvent event) { - } + public void handleEvent(DeviceStateChangeEvent event) + { + } - public void handleEvent(MeetMeEndEvent event) { - } + public void handleEvent(DialEvent event) + { + } - public void handleEvent(MessageWaitingEvent event) { - } + public void handleEvent(DialBeginEvent event) + { + } - public void handleEvent(ModuleLoadReportEvent event) { - } + public void handleEvent(DialEndEvent event) + { + } - public void handleEvent(MusicOnHoldEvent event) { - } + public void handleEvent(DialStateEvent event) + { + } - public void handleEvent(MusicOnHoldStartEvent event) { - } + public void handleEvent(DisconnectEvent event) + { + } - public void handleEvent(MusicOnHoldStopEvent event) { - } + public void handleEvent(DndStateEvent event) + { + } - public void handleEvent(NewAccountCodeEvent event) { - } + public void handleEvent(DongleCallStateChangeEvent event) + { + } - public void handleEvent(NewConnectedLineEvent event) { - } + public void handleEvent(DongleCENDEvent event) + { + } - public void handleEvent(NewExtenEvent event) { - } + public void handleEvent(DongleNewCMGREvent event) + { + } - public void handleEvent(PeerStatusEvent event) { - } + public void handleEvent(DongleNewSMSBase64Event event) + { + } - public void handleEvent(PickupEvent event) { - } + public void handleEvent(DongleNewSMSEvent event) + { + } - public void handleEvent(PriEventEvent event) { - } + public void handleEvent(DongleStatusEvent event) + { + } - public void handleEvent(ProtocolIdentifierReceivedEvent event) { - } + public void handleEvent(DtmfEvent event) + { + } - public void handleEvent(QueueEvent event) { - } + public void handleEvent(DtmfBeginEvent event) + { + } - public void handleEvent(JoinEvent event) { - } + public void handleEvent(DtmfEndEvent event) + { + } - public void handleEvent(LeaveEvent event) { - } + public void handleEvent(ExtensionStatusEvent event) + { + } - public void handleEvent(QueueCallerAbandonEvent event) { - } + public void handleEvent(FullyBootedEvent event) + { + } - public void handleEvent(QueueCallerJoinEvent event) { - } + public void handleEvent(HoldedCallEvent event) + { + } - public void handleEvent(QueueCallerLeaveEvent event) { - } + public void handleEvent(InvalidPasswordEvent event) + { + } - public void handleEvent(QueueMemberPenaltyEvent event) { - } + public void handleEvent(JabberEventEvent event) + { + } - public void handleEvent(ReceiveFaxEvent event) { - } + public void handleEvent(JitterBufStatsEvent event) + { + } - public void handleEvent(RegistryEvent event) { - } + public void handleEvent(LocalBridgeEvent event) + { + } - public void handleEvent(ReloadEvent event) { - } + public void handleEvent(LocalOptimizationBeginEvent event) + { + } - public void handleEvent(RenameEvent event) { - } + public void handleEvent(LocalOptimizationEndEvent event) + { + } - public void handleEvent(ResponseEvent event) { - } + public void handleEvent(LogChannelEvent event) + { + } - public void handleEvent(AgentsCompleteEvent event) { - } + public void handleEvent(MasqueradeEvent event) + { + } - public void handleEvent(AgentsEvent event) { - } + public void handleEvent(MeetMeEndEvent event) + { + } - public void handleEvent(AsyncAgiEvent event) { - } + public void handleEvent(MessageWaitingEvent event) + { + } - public void handleEvent(ConfbridgeListCompleteEvent event) { - } + public void handleEvent(ModuleLoadReportEvent event) + { + } - public void handleEvent(ConfbridgeListEvent event) { - } + public void handleEvent(MusicOnHoldEvent event) + { + } - public void handleEvent(ConfbridgeListRoomsCompleteEvent event) { - } + public void handleEvent(MusicOnHoldStartEvent event) + { + } - public void handleEvent(ConfbridgeListRoomsEvent event) { - } + public void handleEvent(MusicOnHoldStopEvent event) + { + } - public void handleEvent(CoreShowChannelEvent event) { - } + public void handleEvent(NewAccountCodeEvent event) + { + } - public void handleEvent(CoreShowChannelsCompleteEvent event) { - } + public void handleEvent(NewConnectedLineEvent event) + { + } - public void handleEvent(DahdiShowChannelsCompleteEvent event) { - } + public void handleEvent(NewExtenEvent event) + { + } - public void handleEvent(DahdiShowChannelsEvent event) { - } + public void handleEvent(PeerStatusEvent event) + { + } - public void handleEvent(DbGetResponseEvent event) { - } + public void handleEvent(PickupEvent event) + { + } - public void handleEvent(DongleDeviceEntryEvent event) { - } + public void handleEvent(PriEventEvent event) + { + } - public void handleEvent(DongleShowDevicesCompleteEvent event) { - } + public void handleEvent(ProtocolIdentifierReceivedEvent event) + { + } - public void handleEvent(EndpointList event) { - } + public void handleEvent(QueueEvent event) + { + } - public void handleEvent(EndpointListComplete event) { - } + public void handleEvent(JoinEvent event) + { + } - public void handleEvent(ListDialplanEvent event) { - } + public void handleEvent(LeaveEvent event) + { + } - public void handleEvent(OriginateResponseEvent event) { - } + public void handleEvent(QueueCallerAbandonEvent event) + { + } - public void handleEvent(ParkedCallsCompleteEvent event) { - } + public void handleEvent(QueueCallerJoinEvent event) + { + } - public void handleEvent(PeerEntryEvent event) { - } + public void handleEvent(QueueCallerLeaveEvent event) + { + } - public void handleEvent(PeerlistCompleteEvent event) { - } + public void handleEvent(QueueMemberPenaltyEvent event) + { + } - public void handleEvent(PeersEvent event) { - } + public void handleEvent(ReceiveFaxEvent event) + { + } - public void handleEvent(QueueEntryEvent event) { - } + public void handleEvent(RegistryEvent event) + { + } - public void handleEvent(QueueMemberEvent event) { - } + public void handleEvent(ReloadEvent event) + { + } - public void handleEvent(QueueParamsEvent event) { - } + public void handleEvent(RenameEvent event) + { + } - public void handleEvent(QueueStatusCompleteEvent event) { - } + public void handleEvent(ResponseEvent event) + { + } - public void handleEvent(QueueSummaryCompleteEvent event) { - } + public void handleEvent(AgentsCompleteEvent event) + { + } - public void handleEvent(QueueSummaryEvent event) { - } + public void handleEvent(AgentsEvent event) + { + } - public void handleEvent(RegistrationsCompleteEvent event) { - } + public void handleEvent(AsyncAgiEvent event) + { + } - public void handleEvent(RegistryEntryEvent event) { - } + public void handleEvent(ConfbridgeListCompleteEvent event) + { + } - public void handleEvent(ShowDialplanCompleteEvent event) { - } + public void handleEvent(ConfbridgeListEvent event) + { + } - public void handleEvent(SkypeBuddyEntryEvent event) { - } + public void handleEvent(ConfbridgeListRoomsCompleteEvent event) + { + } - public void handleEvent(SkypeBuddyListCompleteEvent event) { - } + public void handleEvent(ConfbridgeListRoomsEvent event) + { + } - public void handleEvent(SkypeLicenseEvent event) { - } + public void handleEvent(CoreShowChannelEvent event) + { + } - public void handleEvent(SkypeLicenseListCompleteEvent event) { - } + public void handleEvent(CoreShowChannelsCompleteEvent event) + { + } - public void handleEvent(StatusCompleteEvent event) { - } + public void handleEvent(DahdiShowChannelsCompleteEvent event) + { + } - public void handleEvent(StatusEvent event) { - } + public void handleEvent(DahdiShowChannelsEvent event) + { + } - public void handleEvent(VoicemailUserEntryCompleteEvent event) { - } + public void handleEvent(DbGetResponseEvent event) + { + } - public void handleEvent(VoicemailUserEntryEvent event) { - } + public void handleEvent(DongleDeviceEntryEvent event) + { + } - public void handleEvent(ZapShowChannelsCompleteEvent event) { - } + public void handleEvent(DongleShowDevicesCompleteEvent event) + { + } - public void handleEvent(ZapShowChannelsEvent event) { - } + public void handleEvent(EndpointList event) + { + } - public void handleEvent(ShutdownEvent event) { - } + public void handleEvent(EndpointListComplete event) + { + } - public void handleEvent(SkypeAccountStatusEvent event) { - } + public void handleEvent(ListDialplanEvent event) + { + } - public void handleEvent(SkypeBuddyStatusEvent event) { - } + public void handleEvent(OriginateResponseEvent event) + { + } - public void handleEvent(SkypeChatMessageEvent event) { - } + public void handleEvent(ParkedCallsCompleteEvent event) + { + } - public void handleEvent(SuccessfulAuthEvent event) { - } + public void handleEvent(PeerEntryEvent event) + { + } - public void handleEvent(TransferEvent event) { - } + public void handleEvent(PeerlistCompleteEvent event) + { + } - public void handleEvent(UserEvent event) { - } + public void handleEvent(PeersEvent event) + { + } - public void handleEvent(PausedEvent event) { - } + public void handleEvent(QueueEntryEvent event) + { + } - public void handleEvent(UnpausedEvent event) { - } + public void handleEvent(QueueMemberEvent event) + { + } - public void handleEvent(VarSetEvent event) { - } + public void handleEvent(QueueParamsEvent event) + { + } - /** - * Dispatches to the appropriate handleEvent(...) method. - * - * @param event the event to handle - */ - @Override - public void onManagerEvent(ManagerEvent event) { + public void handleEvent(QueueStatusCompleteEvent event) + { + } - // if this turns out to be slow, we could consider caching the reflection lookup - try { - Method method = this.getClass().getMethod("handleEvent", event.getClass()); - if (method != null) { - method.invoke(this, event); - return; - } - } catch (Exception e) { - LOGGER.error(e, e); - } + public void handleEvent(QueueSummaryCompleteEvent event) + { + } - LOGGER.error("The event " + event.getClass() - + " couldn't be mapped to a method in AbstractManagerEventListener.java, someone should add it!"); - } + public void handleEvent(QueueSummaryEvent event) + { + } + + public void handleEvent(RegistrationsCompleteEvent event) + { + } + + public void handleEvent(RegistryEntryEvent event) + { + } + + public void handleEvent(ShowDialplanCompleteEvent event) + { + } + + public void handleEvent(SkypeBuddyEntryEvent event) + { + } + + public void handleEvent(SkypeBuddyListCompleteEvent event) + { + } + + public void handleEvent(SkypeLicenseEvent event) + { + } + + public void handleEvent(SkypeLicenseListCompleteEvent event) + { + } + + public void handleEvent(StatusCompleteEvent event) + { + } + + public void handleEvent(StatusEvent event) + { + } + + public void handleEvent(VoicemailUserEntryCompleteEvent event) + { + } + + public void handleEvent(VoicemailUserEntryEvent event) + { + } + + public void handleEvent(ZapShowChannelsCompleteEvent event) + { + } + + public void handleEvent(ZapShowChannelsEvent event) + { + } + + public void handleEvent(ShutdownEvent event) + { + } + + public void handleEvent(SkypeAccountStatusEvent event) + { + } + + public void handleEvent(SkypeBuddyStatusEvent event) + { + } + + public void handleEvent(SkypeChatMessageEvent event) + { + } + + public void handleEvent(SuccessfulAuthEvent event) + { + } + + public void handleEvent(TransferEvent event) + { + } + + public void handleEvent(UserEvent event) + { + } + + public void handleEvent(PausedEvent event) + { + } + + public void handleEvent(UnpausedEvent event) + { + } + + public void handleEvent(VarSetEvent event) + { + } + + /** + * Dispatches to the appropriate handleEvent(...) method. + * + * @param event the event to handle + */ + @Override + public void onManagerEvent(ManagerEvent event) + { + + // if this turns out to be slow, we could consider caching the + // reflection lookup + try + { + Method method = this.getClass().getMethod("handleEvent", event.getClass()); + if (method != null) + { + method.invoke(this, event); + return; + } + } + catch (Exception e) + { + LOGGER.error(e, e); + } + + LOGGER.error("The event " + event.getClass() + + " couldn't be mapped to a method in AbstractManagerEventListener.java, someone should add it!"); + } } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index c29d0e893..ab6ce80bc 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -96,14 +96,15 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher // NOTE: identifier is AMI_VERSION, defined in include/asterisk/manager.h // AMI version consists of MAJOR.BREAKING.NON-BREAKING. private static final String[] SUPPORTED_AMI_VERSIONS = { - "2.6", // Asterisk 13 - "2.7", // Asterisk 13.2 - "2.8", // Asterisk >13.5 - "2.9", // Asterisk >13.3 - "3.1", // Asterisk =14.3 - "3.2", // Asterisk 14.4.0 - "4.0", // Asterisk 15 - "5.0", // Asterisk 16 + + "2.6", // Asterisk 13 + "2.7", // Asterisk 13.2 + "2.8", // Asterisk >13.5 + "2.9", // Asterisk >13.3 + "3.1", // Asterisk =14.3 + "3.2", // Asterisk 14.4.0 + "4.0", // Asterisk 15 + "5.0", // Asterisk 16 }; private static final AtomicLong idCounter = new AtomicLong(0); @@ -1654,11 +1655,12 @@ private void countDown() /** * @param millis - milliseconds to wait + * @return * @throws InterruptedException */ - private void await(long millis) throws InterruptedException + private boolean await(long millis) throws InterruptedException { - latch.await(millis, TimeUnit.MILLISECONDS); + return latch.await(millis, TimeUnit.MILLISECONDS); } } diff --git a/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java b/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java index 74c1d6d9d..8a4ab08e3 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java +++ b/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java @@ -14,9 +14,9 @@ void reset() latch = new CountDownLatch(1); } - void await(long timeout) throws InterruptedException + boolean await(long timeout) throws InterruptedException { - latch.await(timeout, TimeUnit.MILLISECONDS); + return latch.await(timeout, TimeUnit.MILLISECONDS); } String getValue() diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java index 664b64547..0d69efd80 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java @@ -103,11 +103,12 @@ public void setComplete(boolean complete) /** * @param timeout - milliseconds + * @return * @throws InterruptedException */ - public void await(long timeout) throws InterruptedException + public boolean await(long timeout) throws InterruptedException { - latch.await(timeout, TimeUnit.MILLISECONDS); + return latch.await(timeout, TimeUnit.MILLISECONDS); } public void countDown() diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java index fe3bcd433..74b74b935 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java @@ -39,7 +39,10 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } else { - latch.await(10, TimeUnit.SECONDS); + if (!latch.await(10, TimeUnit.SECONDS)) + { + logger.warn("Exiting with timeout"); + } } } catch (AgiHangupException e) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java index 5d4343a72..6289ae212 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java @@ -136,7 +136,10 @@ public boolean doActivity() throws PBXException { if (success) { - this._latch.await(2, TimeUnit.SECONDS); + if (!this._latch.await(2, TimeUnit.SECONDS)) + { + logger.warn("Timeout, continuing"); + } } if (this._parkingLot == null) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java index d4d4c1e84..fb1e903ac 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java @@ -100,7 +100,10 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint trcResult.getChannel().setCurrentActivityAction( new AgiChannelActivityDial(targetEndPoint.getFullyQualifiedName(), dialOptions)); - this._latch.await(30, TimeUnit.SECONDS); + if (!this._latch.await(30, TimeUnit.SECONDS)) + { + logger.warn("Timeout waiting for channel. " + trcResult.getChannel()); + } } } From 07dafb56eb17ee22197ccf758cb9e08c0a9e2ab5 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 7 Aug 2020 17:25:03 +1000 Subject: [PATCH 373/802] for version 3.6.1-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 692f83b52..f7c88468a 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.6.0 + 3.6.1-SNAPSHOT UTF-8 From 1154beb79132f3a4087aa0b2467bf1bb3cb93f12 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 9 Sep 2020 15:29:57 +1000 Subject: [PATCH 374/802] for version 3.7.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f7c88468a..793159cf3 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.6.1-SNAPSHOT + 3.7.0 UTF-8 From 8de3e4e0a57ff978559b5a5ca189c3b6e4349eb0 Mon Sep 17 00:00:00 2001 From: patryk Date: Fri, 11 Sep 2020 13:38:06 +0200 Subject: [PATCH 375/802] Added two missing queue actions: QueueChangePriorityCallerAction changes priority of caller. QueueMemberRingInUseAction changes ringinuse value of member. Added AsteriskVersion 17. Resolves errors From AgiExecStartEvent and AgiExecEndEvent (No setters to linkedid and language); --- .../org/asteriskjava/AsteriskVersion.java | 10 +- .../QueueChangePriorityCallerAction.java | 104 +++++++++++++++ .../action/QueueMemberRingInUseAction.java | 118 ++++++++++++++++++ .../manager/event/AgiExecEndEvent.java | 22 +++- .../manager/event/AgiExecStartEvent.java | 22 +++- .../internal/ManagerConnectionImpl.java | 3 +- 6 files changed, 275 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/action/QueueChangePriorityCallerAction.java create mode 100644 src/main/java/org/asteriskjava/manager/action/QueueMemberRingInUseAction.java diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index d815aaad4..bdcf1a0f1 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -28,6 +28,7 @@ */ public class AsteriskVersion implements Comparable, Serializable { + private static final String VERSION_PATTERN_17 = "^\\s*Asterisk (GIT-)?17[-. ].*"; private static final String VERSION_PATTERN_16 = "^\\s*Asterisk (GIT-)?16[-. ].*"; private static final String VERSION_PATTERN_15 = "^\\s*Asterisk (GIT-)?15[-. ].*"; private static final String VERSION_PATTERN_14 = "^\\s*Asterisk (GIT-)?14[-. ].*"; @@ -122,7 +123,14 @@ public class AsteriskVersion implements Comparable, Serializabl public static final AsteriskVersion ASTERISK_16 = new AsteriskVersion(1600, "Asterisk 16", VERSION_PATTERN_16, VERSION_PATTERN_CERTIFIED_16); - private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ASTERISK_16, ASTERISK_15, ASTERISK_14, + /** + * Represents the Asterisk 17 series. + * + * @since 3.7.0 + */ + public static final AsteriskVersion ASTERISK_17 = new AsteriskVersion(1700, "Asterisk 17", VERSION_PATTERN_17); + + private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ASTERISK_17, ASTERISK_16, ASTERISK_15, ASTERISK_14, ASTERISK_13, ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6}; // current debian stable version, as of 09/10/2018 diff --git a/src/main/java/org/asteriskjava/manager/action/QueueChangePriorityCallerAction.java b/src/main/java/org/asteriskjava/manager/action/QueueChangePriorityCallerAction.java new file mode 100644 index 000000000..1f94cbdd2 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/QueueChangePriorityCallerAction.java @@ -0,0 +1,104 @@ +package org.asteriskjava.manager.action; + +/** + * The QueueChangePriorityCallerAction requests to change priority of caller. + * Priority cannot be less than 0. + */ + +public class QueueChangePriorityCallerAction extends AbstractManagerAction { + + /** + * Serializable version identifier + */ + + private final static long serialVersionUID = -1554562185648L; + + private String queue; + private String caller; + private Integer priority; + + /** + * Creates a new empty QueueChangePriorityCallerAction. + */ + + public QueueChangePriorityCallerAction() { + } + + /** + * Creates a new QueueChangePriorityCAllerAction with all required parameters. + * @param queue name of queue. + * @param caller caller channel name. + * @param priority priority value to set. + */ + + public QueueChangePriorityCallerAction(String queue, String caller, Integer priority) { + this.queue = queue; + this.caller = caller; + this.priority = priority; + } + + /** + * Returns the name of this action, i.e. "QueueChangePriorityCaller" + * @return String, name of action + */ + + @Override + public String getAction() { + return "QueueChangePriorityCaller"; + } + + /** + * Returns the queue that caller is inside. + * + * @return queue name + */ + + public String getQueue() { + return queue; + } + + /** + * Sets the queue filter. + * @param queue queue name + */ + + public void setQueue(String queue) { + this.queue = queue; + } + + /** + * Returns the caller to change priority. + * @return String caller name + */ + + public String getCaller() { + return caller; + } + + /** + * Sets the caller to change priority. If not sets then nothing changes. + * @param caller caller name + */ + + public void setCaller(String caller) { + this.caller = caller; + } + + /** + * Returns priority to set to given caller. + * @return integer priority value + */ + + public Integer getPriority() { + return priority; + } + + /** + * Sets priority to given caller. If nothing sets then nothing changes. + * @param priority priority value + */ + + public void setPriority(Integer priority) { + this.priority = priority; + } +} diff --git a/src/main/java/org/asteriskjava/manager/action/QueueMemberRingInUseAction.java b/src/main/java/org/asteriskjava/manager/action/QueueMemberRingInUseAction.java new file mode 100644 index 000000000..26278dc17 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/QueueMemberRingInUseAction.java @@ -0,0 +1,118 @@ +package org.asteriskjava.manager.action; + +/** + * The QueueMemberRingInUseAction requests to change RingInUse value of queue member. + */ + +public class QueueMemberRingInUseAction extends AbstractManagerAction { + + /** + * Serializable version identifier + */ + + private final static long serialVersionUID = -1554562185640L; + + /** + * Queue name where member is located; + */ + + private String queue; + + /** + * RingInUse value. + */ + + private Boolean ringInUse; + + /** + * Interface where need to change RingInUse value; + */ + + private String iface; + + /** + * Creates a new empty QueueMemberRingInUseAction. + */ + + public QueueMemberRingInUseAction() { + } + + /** + * Creates a new QueueMemberRingInUseAction with mandatory properties queue, ringInUse and iface. + * + * @param queue queueName. + * @param ringInUse value to set. + * @param iface interface where to set ringInUse. + */ + + public QueueMemberRingInUseAction(String queue, Boolean ringInUse, String iface) { + this.queue = queue; + this.ringInUse = ringInUse; + this.iface = iface; + } + + @Override + public String getAction() { + return "QueueMemberRingInUse"; + } + + /** + * Returns queue name where interface is located. + * + * @return queue name; + */ + + public String getQueue() { + return queue; + } + + /** + * Sets queue name where interface is located. + * + * @param queue queue name; + */ + + public void setQueue(String queue) { + this.queue = queue; + } + + /** + * Returns RingInUse value of selected interface. + * + * @return ringInUse value; + */ + + public Boolean getRingInUse() { + return ringInUse; + } + + /** + * Sets RingInUse to selected interface. + * + * @param ringInUse value. + */ + + public void setRingInUse(Boolean ringInUse) { + this.ringInUse = ringInUse; + } + + /** + * Returns interface value eg. SIP/203. + * + * @return interface value. + */ + + public String getInterface() { + return iface; + } + + /** + * Sets interface value where RingInUse changes. + * + * @param iface name + */ + + public void setInterface(String iface) { + this.iface = iface; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/AgiExecEndEvent.java b/src/main/java/org/asteriskjava/manager/event/AgiExecEndEvent.java index 7d757b7b5..2981876c4 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgiExecEndEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgiExecEndEvent.java @@ -6,13 +6,33 @@ public class AgiExecEndEvent extends AgiExecEvent { /** - * + * */ private static final long serialVersionUID = 1L; + private String linkedid; + + private String language; + public AgiExecEndEvent(Object source) { super(source); setSubEvent(SUB_EVENT_END); } + + public String getLinkedid() { + return linkedid; + } + + public void setLinkedid(String linkedid) { + this.linkedid = linkedid; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgiExecStartEvent.java b/src/main/java/org/asteriskjava/manager/event/AgiExecStartEvent.java index a2d483cc3..525c1692c 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgiExecStartEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgiExecStartEvent.java @@ -6,13 +6,33 @@ public class AgiExecStartEvent extends AgiExecEvent { /** - * + * */ private static final long serialVersionUID = 1L; + private String linkedid; + + private String language; + public AgiExecStartEvent(Object source) { super(source); setSubEvent(SUB_EVENT_START); } + + public String getLinkedid() { + return linkedid; + } + + public void setLinkedid(String linkedid) { + this.linkedid = linkedid; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index ab6ce80bc..d5f6ac50f 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -96,7 +96,7 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher // NOTE: identifier is AMI_VERSION, defined in include/asterisk/manager.h // AMI version consists of MAJOR.BREAKING.NON-BREAKING. private static final String[] SUPPORTED_AMI_VERSIONS = { - + "2.6", // Asterisk 13 "2.7", // Asterisk 13.2 "2.8", // Asterisk >13.5 @@ -105,6 +105,7 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher "3.2", // Asterisk 14.4.0 "4.0", // Asterisk 15 "5.0", // Asterisk 16 + "6.0", // Asterisk 17 }; private static final AtomicLong idCounter = new AtomicLong(0); From 8fd77b51446e671e403b6d32bab7b8581ad47fe4 Mon Sep 17 00:00:00 2001 From: patryk Date: Fri, 11 Sep 2020 13:56:30 +0200 Subject: [PATCH 376/802] Added recordfile to CdrEvent as was in issues. --- .../asteriskjava/manager/event/CdrEvent.java | 124 ++++++++++-------- 1 file changed, 72 insertions(+), 52 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/CdrEvent.java b/src/main/java/org/asteriskjava/manager/event/CdrEvent.java index 817a5aa47..da30ae41e 100644 --- a/src/main/java/org/asteriskjava/manager/event/CdrEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/CdrEvent.java @@ -26,7 +26,7 @@ * To enable CdrEvents you have to add enabled = yes to the general section in * cdr_manager.conf.

    * This event is implemented in cdr/cdr_manager.c - * + * * @author srt * @version $Id$ */ @@ -36,18 +36,18 @@ public class CdrEvent extends ManagerEvent * Serializable version identifier */ private static final long serialVersionUID = 2541424315212201670L; - + public static final String DISPOSITION_NO_ANSWER = "NO ANSWER"; public static final String DISPOSITION_FAILED = "FAILED"; public static final String DISPOSITION_BUSY = "BUSY"; public static final String DISPOSITION_ANSWERED = "ANSWERED"; public static final String DISPOSITION_UNKNOWN = "UNKNOWN"; - + public static final String AMA_FLAG_OMIT = "OMIT"; public static final String AMA_FLAG_BILLING = "BILLING"; public static final String AMA_FLAG_DOCUMENTATION = "DOCUMENTATION"; public static final String AMA_FLAG_UNKNOWN = "Unknown"; - + private String accountCode; private String src; private String destination; @@ -66,6 +66,7 @@ public class CdrEvent extends ManagerEvent private String amaFlags; private String uniqueId; private String userField; + private String recordfile; /** * @param source @@ -78,7 +79,7 @@ public CdrEvent(Object source) /** * Returns the account number that is usually used to identify the party to bill for the call.

    * Corresponds to CDR field accountcode. - * + * * @return the account number. */ public String getAccountCode() @@ -88,7 +89,7 @@ public String getAccountCode() /** * Sets the account number. - * + * * @param accountCode the account number. */ public void setAccountCode(String accountCode) @@ -99,7 +100,7 @@ public void setAccountCode(String accountCode) /** * Returns the Caller*ID number.

    * Corresponds to CDR field src. - * + * * @return the Caller*ID number. */ public String getSrc() @@ -109,7 +110,7 @@ public String getSrc() /** * Sets the Caller*ID number. - * + * * @param source the Caller*ID number. */ public void setSrc(String source) @@ -120,7 +121,7 @@ public void setSrc(String source) /** * Returns the destination extension.

    * Corresponds to CDR field dst. - * + * * @return the destination extension. */ public String getDestination() @@ -130,7 +131,7 @@ public String getDestination() /** * Sets the destination extension. - * + * * @param destination the destination extension. */ public void setDestination(String destination) @@ -141,7 +142,7 @@ public void setDestination(String destination) /** * Returns the destination context.

    * Corresponds to CDR field dcontext. - * + * * @return the destination context. */ public String getDestinationContext() @@ -151,7 +152,7 @@ public String getDestinationContext() /** * Sets the destination context. - * + * * @param destinationContext the destination context. */ public void setDestinationContext(String destinationContext) @@ -162,7 +163,7 @@ public void setDestinationContext(String destinationContext) /** * Returns the Caller*ID with text.

    * Corresponds to CDR field clid. - * + * * @return the Caller*ID with text */ public String getCallerId() @@ -172,7 +173,7 @@ public String getCallerId() /** * Sets the Caller*ID with text. - * + * * @param callerId the Caller*ID with text. */ public void setCallerId(String callerId) @@ -183,7 +184,7 @@ public void setCallerId(String callerId) /** * Returns the name of the channel, for example "SIP/1310-asfe".

    * Corresponds to CDR field channel. - * + * * @return the name of the channel. */ public String getChannel() @@ -193,7 +194,7 @@ public String getChannel() /** * Sets the name of the channel. - * + * * @param channel the name of the channel. */ public void setChannel(String channel) @@ -204,7 +205,7 @@ public void setChannel(String channel) /** * Returns the name of the destination channel if appropriate.

    * Corresponds to CDR field dstchannel. - * + * * @return the name of the destination channel or null if not available. */ public String getDestinationChannel() @@ -214,7 +215,7 @@ public String getDestinationChannel() /** * Sets the name of the destination channel. - * + * * @param destinationChannel the name of the destination channel. */ public void setDestinationChannel(String destinationChannel) @@ -225,7 +226,7 @@ public void setDestinationChannel(String destinationChannel) /** * Returns the last application if appropriate, for example "VoiceMail".

    * Corresponds to CDR field lastapp. - * + * * @return the last application or null if not avaialble. */ public String getLastApplication() @@ -235,7 +236,7 @@ public String getLastApplication() /** * Sets the last application. - * + * * @param lastApplication the last application. */ public void setLastApplication(String lastApplication) @@ -246,7 +247,7 @@ public void setLastApplication(String lastApplication) /** * Returns the last application's data (arguments), for example "s1234".

    * Corresponds to CDR field lastdata. - * + * * @return the last application's data or null if not avaialble. */ public String getLastData() @@ -256,7 +257,7 @@ public String getLastData() /** * Set the last application's data. - * + * * @param lastData the last application's data. */ public void setLastData(String lastData) @@ -267,7 +268,7 @@ public void setLastData(String lastData) /** * Returns when the call has started.

    * This corresponds to CDR field start. - * + * * @return A string of the format "%Y-%m-%d %T" (strftime(3)) representing the date/time the * call has started, for example "2006-05-19 11:54:48". */ @@ -275,12 +276,12 @@ public String getStartTime() { return startTime; } - + /** * Returns the start time as Date object.

    - * This method asumes that the Asterisk server's timezone equals the default + * This method asumes that the Asterisk server's timezone equals the default * timezone of your JVM. - * + * * @return the start time as Date object. * @since 0.3 */ @@ -288,10 +289,10 @@ public Date getStartTimeAsDate() { return DateUtil.parseDateTime(startTime); } - + /** * Returns the start time as Date object. - * + * * @param tz the timezone of the Asterisk server. * @return the start time as Date object. * @since 0.3 @@ -303,7 +304,7 @@ public Date getStartTimeAsDate(TimeZone tz) /** * Sets the date/time when the call has started. - * + * * @param startTime the date/time when the call has started. */ public void setStartTime(String startTime) @@ -314,7 +315,7 @@ public void setStartTime(String startTime) /** * Returns when the call was answered.

    * This corresponds to CDR field answered. - * + * * @return A string of the format "%Y-%m-%d %T" (strftime(3)) representing the date/time the * call was answered, for example "2006-05-19 11:55:01" */ @@ -325,9 +326,9 @@ public String getAnswerTime() /** * Returns the answer time as Date object.

    - * This method asumes that the Asterisk server's timezone equals the default + * This method asumes that the Asterisk server's timezone equals the default * timezone of your JVM. - * + * * @return the answer time as Date object. * @since 0.3 */ @@ -338,7 +339,7 @@ public Date getAnswerTimeAsDate() /** * Returns the answer time as Date object. - * + * * @param tz the timezone of the Asterisk server. * @return the answer time as Date object. * @since 0.3 @@ -350,7 +351,7 @@ public Date getAnswerTimeAsDate(TimeZone tz) /** * Sets the date/time when the call was answered. - * + * * @param answerTime the date/time when the call was answered. */ public void setAnswerTime(String answerTime) @@ -361,7 +362,7 @@ public void setAnswerTime(String answerTime) /** * Returns when the call has ended.

    * This corresponds to CDR field end. - * + * * @return A string of the format "%Y-%m-%d %T" (strftime(3)) representing the date/time the * call has ended, for example "2006-05-19 11:58:21" */ @@ -372,9 +373,9 @@ public String getEndTime() /** * Returns the end time as Date object.

    - * This method asumes that the Asterisk server's timezone equals the default + * This method asumes that the Asterisk server's timezone equals the default * timezone of your JVM. - * + * * @return the end time as Date object. * @since 0.3 */ @@ -382,10 +383,10 @@ public Date getEndTimeAsDate() { return DateUtil.parseDateTime(endTime); } - + /** * Returns the end time as Date object. - * + * * @param tz the timezone of the Asterisk server. * @return the end time as Date object. * @since 0.3 @@ -397,7 +398,7 @@ public Date getEndTimeAsDate(TimeZone tz) /** * Sets the date/time when the call has ended. - * + * * @param endTime the date/time when the call has ended. */ public void setEndTime(String endTime) @@ -408,7 +409,7 @@ public void setEndTime(String endTime) /** * Returns the total time (in seconds) the caller spent in the system from dial to hangup.

    * Corresponds to CDR field duration. - * + * * @return the total time in system in seconds. */ public Integer getDuration() @@ -418,7 +419,7 @@ public Integer getDuration() /** * Sets the total time in system. - * + * * @param duration total time in system in seconds. */ public void setDuration(Integer duration) @@ -429,7 +430,7 @@ public void setDuration(Integer duration) /** * Returns the total time (in seconds) the call was up from answer to hangup.

    * Corresponds to CDR field billsec. - * + * * @return the total time in call in seconds. */ public Integer getBillableSeconds() @@ -439,7 +440,7 @@ public Integer getBillableSeconds() /** * Sets the total time in call. - * + * * @param billableSeconds the total time in call in seconds. */ public void setBillableSeconds(Integer billableSeconds) @@ -458,7 +459,7 @@ public void setBillableSeconds(Integer billableSeconds) *

  • {@link #DISPOSITION_UNKNOWN} * * Corresponds to CDR field disposition. - * + * * @return the disposition. */ public String getDisposition() @@ -468,7 +469,7 @@ public String getDisposition() /** * Sets the disposition. - * + * * @param disposition the disposition. */ public void setDisposition(String disposition) @@ -486,7 +487,7 @@ public void setDisposition(String disposition) *
  • {@link #AMA_FLAG_UNKNOWN} * * Corresponds to CDR field amaflags. - * + * * @return the AMA flags. */ public String getAmaFlags() @@ -496,7 +497,7 @@ public String getAmaFlags() /** * Sets the AMA (Automated Message Accounting) flags. - * + * * @param amaFlags the AMA (Automated Message Accounting) flags. */ public void setAmaFlags(String amaFlags) @@ -506,7 +507,7 @@ public void setAmaFlags(String amaFlags) /** * Returns the unique id of the channel. - * + * * @return the unique id of the channel. */ public String getUniqueId() @@ -516,7 +517,7 @@ public String getUniqueId() /** * Sets the unique id of the channel. - * + * * @param uniqueId the unique id of the channel. */ public void setUniqueId(String uniqueId) @@ -527,7 +528,7 @@ public void setUniqueId(String uniqueId) /** * Returns the user-defined field as set by Set(CDR(userfield)=Value).

    * Corresponds to CDR field userfield. - * + * * @return the user-defined field. */ public String getUserField() @@ -537,11 +538,30 @@ public String getUserField() /** * Sets the user-defined field. - * + * * @param userField the user-defined field */ public void setUserField(String userField) { this.userField = userField; } + + /** + * Returns record filename. + * @return record filename. + */ + + public String getRecordfile() { + return recordfile; + } + + /** + * Sets record filename. + * + * @param recordfile record filename. + */ + + public void setRecordfile(String recordfile) { + this.recordfile = recordfile; + } } From 54e3fd29cccc0115c76c1be648348896992cdd87 Mon Sep 17 00:00:00 2001 From: patryk Date: Fri, 11 Sep 2020 14:02:04 +0200 Subject: [PATCH 377/802] Added BridgeVideoSource to BridgeLeaveEvent. --- .../asteriskjava/manager/event/BridgeLeaveEvent.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java index 293888c8e..6da790b72 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java @@ -6,13 +6,14 @@ public class BridgeLeaveEvent extends AbstractBridgeEvent { /** - * + * */ private static final long serialVersionUID = 1L; private String uniqueId; private String channel; private String language; private String linkedId; + private String bridgevideosourcemode; public BridgeLeaveEvent(Object source) { @@ -59,4 +60,12 @@ public void setLinkedId(String linkedId) this.linkedId = linkedId; } + public String getBridgevideosourcemode () + { + return this.bridgevideosourcemode; + } + + public void setBridgevideosourcemode (String bridgevideosourcemode) { + this.bridgevideosourcemode = bridgevideosourcemode; + } } From 20cdafc4493e466557d01e3efc65a708040698d2 Mon Sep 17 00:00:00 2001 From: patryk Date: Fri, 11 Sep 2020 14:07:54 +0200 Subject: [PATCH 378/802] c --- src/main/java/org/asteriskjava/Cli.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/Cli.java b/src/main/java/org/asteriskjava/Cli.java index 82e49fcbd..bf905817b 100644 --- a/src/main/java/org/asteriskjava/Cli.java +++ b/src/main/java/org/asteriskjava/Cli.java @@ -23,7 +23,7 @@ *

    Displays the version of Asterisk-Java
    *
  • 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 mp`@OGFgmTN9-l*nvP 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

    * If no option is given a FastAGI server is started on the default port. - * + * * @since 1.0.0 */ public class Cli From b4b2c864cddeb9785a110e7429db13a80a56c082 Mon Sep 17 00:00:00 2001 From: patryk Date: Fri, 11 Sep 2020 14:09:26 +0200 Subject: [PATCH 379/802] Removed unnecessary variable. --- .../org/asteriskjava/manager/event/BridgeLeaveEvent.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java index 6da790b72..386c26e4d 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java @@ -13,7 +13,6 @@ public class BridgeLeaveEvent extends AbstractBridgeEvent private String channel; private String language; private String linkedId; - private String bridgevideosourcemode; public BridgeLeaveEvent(Object source) { @@ -60,12 +59,5 @@ public void setLinkedId(String linkedId) this.linkedId = linkedId; } - public String getBridgevideosourcemode () - { - return this.bridgevideosourcemode; - } - public void setBridgevideosourcemode (String bridgevideosourcemode) { - this.bridgevideosourcemode = bridgevideosourcemode; - } } From 933f97a2a2106d3832355587a8726399862a1720 Mon Sep 17 00:00:00 2001 From: patryk Date: Fri, 11 Sep 2020 15:52:09 +0200 Subject: [PATCH 380/802] Queue events implementation that allow to get entries in real time (Its usable with RealTime Queues, etc.). --- .../live/internal/AsteriskServerImpl.java | 51 +++------------- .../live/internal/QueueManager.java | 61 +++++++++++++++++++ 2 files changed, 71 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java index f05b33e40..1241934d3 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java @@ -65,46 +65,7 @@ import org.asteriskjava.manager.action.OriginateAction; import org.asteriskjava.manager.action.SetVarAction; import org.asteriskjava.manager.action.SipPeersAction; -import org.asteriskjava.manager.event.AbstractMeetMeEvent; -import org.asteriskjava.manager.event.AgentCallbackLoginEvent; -import org.asteriskjava.manager.event.AgentCallbackLogoffEvent; -import org.asteriskjava.manager.event.AgentCalledEvent; -import org.asteriskjava.manager.event.AgentCompleteEvent; -import org.asteriskjava.manager.event.AgentConnectEvent; -import org.asteriskjava.manager.event.AgentLoginEvent; -import org.asteriskjava.manager.event.AgentLogoffEvent; -import org.asteriskjava.manager.event.AgentsEvent; -import org.asteriskjava.manager.event.BridgeEvent; -import org.asteriskjava.manager.event.CdrEvent; -import org.asteriskjava.manager.event.ConnectEvent; -import org.asteriskjava.manager.event.DbGetResponseEvent; -import org.asteriskjava.manager.event.DialEvent; -import org.asteriskjava.manager.event.DisconnectEvent; -import org.asteriskjava.manager.event.DtmfEvent; -import org.asteriskjava.manager.event.HangupEvent; -import org.asteriskjava.manager.event.JoinEvent; -import org.asteriskjava.manager.event.LeaveEvent; -import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.MonitorStartEvent; -import org.asteriskjava.manager.event.MonitorStopEvent; -import org.asteriskjava.manager.event.NewCallerIdEvent; -import org.asteriskjava.manager.event.NewChannelEvent; -import org.asteriskjava.manager.event.NewExtenEvent; -import org.asteriskjava.manager.event.NewStateEvent; -import org.asteriskjava.manager.event.OriginateResponseEvent; -import org.asteriskjava.manager.event.ParkedCallEvent; -import org.asteriskjava.manager.event.ParkedCallGiveUpEvent; -import org.asteriskjava.manager.event.ParkedCallTimeOutEvent; -import org.asteriskjava.manager.event.PeerEntryEvent; -import org.asteriskjava.manager.event.QueueMemberAddedEvent; -import org.asteriskjava.manager.event.QueueMemberPausedEvent; -import org.asteriskjava.manager.event.QueueMemberPenaltyEvent; -import org.asteriskjava.manager.event.QueueMemberRemovedEvent; -import org.asteriskjava.manager.event.QueueMemberStatusEvent; -import org.asteriskjava.manager.event.RenameEvent; -import org.asteriskjava.manager.event.ResponseEvent; -import org.asteriskjava.manager.event.UnparkedCallEvent; -import org.asteriskjava.manager.event.VarSetEvent; +import org.asteriskjava.manager.event.*; import org.asteriskjava.manager.response.CommandResponse; import org.asteriskjava.manager.response.GetConfigResponse; import org.asteriskjava.manager.response.MailboxCountResponse; @@ -1140,6 +1101,14 @@ else if (event instanceof QueueMemberPausedEvent) { queueManager.handleQueueMemberPausedEvent((QueueMemberPausedEvent) event); } + else if (event instanceof QueueCallerJoinEvent) + { + queueManager.handleJoinEvent((QueueCallerJoinEvent) event); + } + else if (event instanceof QueueCallerLeaveEvent) + { + queueManager.handleLeaveEvent((QueueCallerLeaveEvent) event); + } // >>>>>> AJ 94 // Handle meetMeEvents else if (event instanceof AbstractMeetMeEvent) @@ -1191,7 +1160,7 @@ else if (event instanceof AgentLogoffEvent) /** * dispatch the event to the chainListener if they exist. - * + * * @param event */ private void fireChainListeners(ManagerEvent event) diff --git a/src/main/java/org/asteriskjava/live/internal/QueueManager.java b/src/main/java/org/asteriskjava/live/internal/QueueManager.java index f390c88fc..40b464348 100644 --- a/src/main/java/org/asteriskjava/live/internal/QueueManager.java +++ b/src/main/java/org/asteriskjava/live/internal/QueueManager.java @@ -34,6 +34,8 @@ import org.asteriskjava.manager.event.JoinEvent; import org.asteriskjava.manager.event.LeaveEvent; import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.QueueCallerJoinEvent; +import org.asteriskjava.manager.event.QueueCallerLeaveEvent; import org.asteriskjava.manager.event.QueueEntryEvent; import org.asteriskjava.manager.event.QueueMemberAddedEvent; import org.asteriskjava.manager.event.QueueMemberEvent; @@ -366,6 +368,37 @@ private void handleQueueEntryEvent(QueueEntryEvent event) queue.createNewEntry(channel, reportedPosition, event.getDateReceived()); } + /** + * + * Called from AsteriskServerImpl whenever a new entry appears in a queue. + * + * + * + * @param event the JoinEvent received + * + + */ + void handleJoinEvent(QueueCallerJoinEvent event) { + final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); + final AsteriskChannelImpl channel = channelManager.getChannelImplByName(event.getChannel()); + + if (queue == null) { + logger.error("Ignored JoinEvent for unknown queue " + event.getQueue()); + return; + } + if (channel == null) { + logger.error("Ignored JoinEvent for unknown channel " + event.getChannel()); + return; + } + + // Asterisk gives us an initial position but doesn't tell us when he + // shifts the others + // We won't use this data for ordering until there is a appropriate + // event in AMI. + // (and refreshing the whole queue is too intensive and suffers + // incoherencies + // due to asynchronous shift that leaves holes if requested too fast) + int reportedPosition = event.getPosition(); + + queue.createNewEntry(channel, reportedPosition, event.getDateReceived()); + } + /** * Called from AsteriskServerImpl whenever a new entry appears in a queue. * @@ -399,6 +432,34 @@ void handleJoinEvent(JoinEvent event) queue.createNewEntry(channel, reportedPosition, event.getDateReceived()); } + /** + * Called from AsteriskServerImpl whenever an enty leaves a queue. + * + * @param event - the LeaveEvent received + */ + void handleLeaveEvent(QueueCallerLeaveEvent event) { + final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); + final AsteriskChannelImpl channel = channelManager.getChannelImplByName(event.getChannel()); + + if (queue == null) { + logger.error("Ignored LeaveEvent for unknown queue " + event.getQueue()); + return; + } + if (channel == null) { + logger.error("Ignored LeaveEvent for unknown channel " + event.getChannel()); + return; + } + + final AsteriskQueueEntryImpl existingQueueEntry = queue.getEntry(event.getChannel()); + if (existingQueueEntry == null) { + logger.error("Ignored leave event for non existing queue entry in queue " + event.getQueue() + " for channel " + + event.getChannel()); + return; + } + + queue.removeEntry(existingQueueEntry, event.getDateReceived()); + } + /** * Called from AsteriskServerImpl whenever an enty leaves a queue. * From 52b0347ef266e91e3a476ade63ef9dcd7377af1c Mon Sep 17 00:00:00 2001 From: patryk Date: Mon, 14 Sep 2020 09:07:35 +0200 Subject: [PATCH 381/802] QueueSummaryCompleteEvent missing params implementation. --- .../event/QueueSummaryCompleteEvent.java | 76 +++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueSummaryCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueSummaryCompleteEvent.java index ed1dd6843..65025a813 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueSummaryCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueSummaryCompleteEvent.java @@ -5,22 +5,70 @@ /** * A QueueSummaryCompleteEvent is triggered after the summary for all requested * queues has been reported in response to a QueueSummaryAction. - * - * @see QueueSummaryAction - * @see QueueSummaryEvent + * * @author srt * @version $Id$ + * @see QueueSummaryAction + * @see QueueSummaryEvent * @since 0.3 */ -public class QueueSummaryCompleteEvent extends ResponseEvent -{ - /** - * Serial version identifier. - */ - private static final long serialVersionUID = -5044247858568827143L; - - public QueueSummaryCompleteEvent(Object source) - { - super(source); - } +public class QueueSummaryCompleteEvent extends ResponseEvent { + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -5044247858568827143L; + + /** + * ?? + */ + private String eventList; + + /** + * The number of listed items from queueSummaryAction. + */ + private Integer listItems; + + public QueueSummaryCompleteEvent(Object source) { + super(source); + } + + /** + * Returns eventList variable. + * + * @return String value. + */ + + public String getEventlist() { + return eventList; + } + + /** + * Sets eventList variable. + * + * @param eventList variable + */ + + public void setEventlist(String eventList) { + this.eventList = eventList; + } + + /** + * Returns the number of listed items. + * + * @return listItems size. + */ + + public Integer getListitems() { + return listItems; + } + + /** + * Sets the returnItems value. + * + * @param listItems variable. + */ + + public void setListitems(Integer listItems) { + this.listItems = listItems; + } } From aa33baf66b14b158068afe61d792b544e0f69b95 Mon Sep 17 00:00:00 2001 From: patryk Date: Mon, 14 Sep 2020 11:16:40 +0200 Subject: [PATCH 382/802] Added RequestBadFormatEvent, triggered when asterisk was restarted and action was produced in the same time. --- .../manager/event/RequestBadFormatEvent.java | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java diff --git a/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java b/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java new file mode 100644 index 000000000..8f8b0072c --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java @@ -0,0 +1,117 @@ +package org.asteriskjava.manager.event; + +/** + * A RequestBadFormatEvent is triggered when bad format of request. + */ + +public class RequestBadFormatEvent extends ManagerEvent { + + /** + * Serializable version identifier. + */ + private final static long serialVersionUID = 12534663L; + + private String severity; + + private Integer eventversion; + + private String sessiontv; + + private String eventtv; + + private String sessionid; + + private String localaddress; + + private String accountid; + + private String requesttype; + + private String service; + + private String remoteaddress; + + public RequestBadFormatEvent(Object source) { + super(source); + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public Integer getEventversion() { + return eventversion; + } + + public void setEventversion(Integer eventversion) { + this.eventversion = eventversion; + } + + public String getSessiontv() { + return sessiontv; + } + + public void setSessiontv(String sessiontv) { + this.sessiontv = sessiontv; + } + + public String getEventtv() { + return eventtv; + } + + public void setEventtv(String eventtv) { + this.eventtv = eventtv; + } + + public String getSessionid() { + return sessionid; + } + + public void setSessionid(String sessionid) { + this.sessionid = sessionid; + } + + public String getLocaladdress() { + return localaddress; + } + + public void setLocaladdress(String localaddress) { + this.localaddress = localaddress; + } + + public String getAccountid() { + return accountid; + } + + public void setAccountid(String accountid) { + this.accountid = accountid; + } + + public String getRequesttype() { + return requesttype; + } + + public void setRequesttype(String requesttype) { + this.requesttype = requesttype; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public String getRemoteaddress() { + return remoteaddress; + } + + public void setRemoteaddress(String remoteaddress) { + this.remoteaddress = remoteaddress; + } +} From 62fbe0fd91e40c6e739c7ae3ce353b5d23328051 Mon Sep 17 00:00:00 2001 From: patryk Date: Mon, 14 Sep 2020 11:16:40 +0200 Subject: [PATCH 383/802] Added RequestBadFormatEvent, triggered when asterisk was restarted and action was produced in the same time, etc. --- .../manager/event/RequestBadFormatEvent.java | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java diff --git a/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java b/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java new file mode 100644 index 000000000..8f8b0072c --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java @@ -0,0 +1,117 @@ +package org.asteriskjava.manager.event; + +/** + * A RequestBadFormatEvent is triggered when bad format of request. + */ + +public class RequestBadFormatEvent extends ManagerEvent { + + /** + * Serializable version identifier. + */ + private final static long serialVersionUID = 12534663L; + + private String severity; + + private Integer eventversion; + + private String sessiontv; + + private String eventtv; + + private String sessionid; + + private String localaddress; + + private String accountid; + + private String requesttype; + + private String service; + + private String remoteaddress; + + public RequestBadFormatEvent(Object source) { + super(source); + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public Integer getEventversion() { + return eventversion; + } + + public void setEventversion(Integer eventversion) { + this.eventversion = eventversion; + } + + public String getSessiontv() { + return sessiontv; + } + + public void setSessiontv(String sessiontv) { + this.sessiontv = sessiontv; + } + + public String getEventtv() { + return eventtv; + } + + public void setEventtv(String eventtv) { + this.eventtv = eventtv; + } + + public String getSessionid() { + return sessionid; + } + + public void setSessionid(String sessionid) { + this.sessionid = sessionid; + } + + public String getLocaladdress() { + return localaddress; + } + + public void setLocaladdress(String localaddress) { + this.localaddress = localaddress; + } + + public String getAccountid() { + return accountid; + } + + public void setAccountid(String accountid) { + this.accountid = accountid; + } + + public String getRequesttype() { + return requesttype; + } + + public void setRequesttype(String requesttype) { + this.requesttype = requesttype; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public String getRemoteaddress() { + return remoteaddress; + } + + public void setRemoteaddress(String remoteaddress) { + this.remoteaddress = remoteaddress; + } +} From bdc3fe9de9096e9f79f64357dfce97fc9277c21a Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 17 Sep 2020 13:16:15 +1000 Subject: [PATCH 384/802] for version 3.8.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 793159cf3..3408fe084 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.7.0 + 3.8.0 UTF-8 From efa5bed153ccb639673e76c3eff65b4b635833e2 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 1 Oct 2020 14:56:50 +1000 Subject: [PATCH 385/802] catch and log execptions on manager reader thread --- .../internal/ManagerConnectionImpl.java | 72 ++++++++++++------- .../manager/internal/ManagerReaderImpl.java | 14 +++- 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index d5f6ac50f..5d2bd9137 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -97,7 +97,7 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher // AMI version consists of MAJOR.BREAKING.NON-BREAKING. private static final String[] SUPPORTED_AMI_VERSIONS = { - "2.6", // Asterisk 13 + "2.6", // Asterisk 13 "2.7", // Asterisk 13.2 "2.8", // Asterisk >13.5 "2.9", // Asterisk >13.3 @@ -105,7 +105,7 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher "3.2", // Asterisk 14.4.0 "4.0", // Asterisk 15 "5.0", // Asterisk 16 - "6.0", // Asterisk 17 + "6.0", // Asterisk 17 }; private static final AtomicLong idCounter = new AtomicLong(0); @@ -113,7 +113,7 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher /** * Instance logger. */ - private final Log logger = LogFactory.getLog(getClass()); + private final static Log logger = LogFactory.getLog(ManagerConnectionImpl.class); private final long id; @@ -834,39 +834,49 @@ public ManagerResponse sendAction(ManagerAction action, long timeout) throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException { ResponseHandlerResult result = new ResponseHandlerResult(); - SendActionCallback callbackHandler = new DefaultSendActionCallback(result); + try + { + SendActionCallback callbackHandler = new DefaultSendActionCallback(result); - sendAction(action, callbackHandler); + sendAction(action, callbackHandler); - // definitely return null for the response of user events - if (action instanceof UserEventAction) - { - return null; - } + // definitely return null for the response of user events + if (action instanceof UserEventAction) + { + return null; + } - // only wait if we did not yet receive the response. - // Responses may be returned really fast. - if (result.getResponse() == null) - { - try + // only wait if we did not yet receive the response. + // Responses may be returned really fast. + if (result.getResponse() == null) { - result.await(timeout); + try + { + result.await(timeout); + } + catch (InterruptedException ex) + { + logger.warn("Interrupted while waiting for result"); + Thread.currentThread().interrupt(); + } } - catch (InterruptedException ex) + + // still no response? + if (result.getResponse() == null) { - logger.warn("Interrupted while waiting for result"); - Thread.currentThread().interrupt(); + throw new TimeoutException("Timeout waiting for response to " + action.getAction() + + (action.getActionId() == null + ? "" + : " (actionId: " + action.getActionId() + "), Timeout=" + timeout + " Action=" + + action.getAction())); + } + return result.getResponse(); } - - // still no response? - if (result.getResponse() == null) + finally { - throw new TimeoutException("Timeout waiting for response to " + action.getAction() - + (action.getActionId() == null ? "" : " (actionId: " + action.getActionId() + ")")); + result.dispose(); } - - return result.getResponse(); } public void sendAction(ManagerAction action, SendActionCallback callback) @@ -1634,6 +1644,7 @@ private static class ResponseHandlerResult implements Serializable private static final long serialVersionUID = 7831097958568769220L; private ManagerResponse response; private final CountDownLatch latch = new CountDownLatch(1); + private volatile boolean disposed = false; public ResponseHandlerResult() { @@ -1647,6 +1658,15 @@ public ManagerResponse getResponse() public void setResponse(ManagerResponse response) { this.response = response; + if (disposed) + { + logger.error("Response arrived after Disposal and assumably Timeout " + response); + } + } + + public void dispose() + { + disposed = true; } private void countDown() diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java index 3535a24d9..f41e533f4 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java @@ -197,8 +197,7 @@ public void run() int isFromAtStart = line.indexOf("From "); int isToAtStart = line.indexOf("To "); - int delimiterIndex = isFromAtStart == 0 || isToAtStart == 0 - ? line.indexOf(" ") : line.indexOf(":"); + int delimiterIndex = isFromAtStart == 0 || isToAtStart == 0 ? line.indexOf(" ") : line.indexOf(":"); // end of workaround for Astersik bug 13319 int delimiterLength = 1; @@ -279,6 +278,17 @@ else if (buffer.containsKey("response")) this.dead = true; logger.info("Terminating reader thread: " + e.getMessage()); } + catch (Exception e) + { + if (this.terminationException == null) + { + // wrap in IOException to avoid changing the external API of + // asteriskjava + this.terminationException = new IOException(e); + } + logger.error("Manager reader exiting due to unexpected Exception..."); + logger.error(e, e); + } finally { this.dead = true; From 41c7f42f03a7a85a7ac3de956f9294fa4d717325 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 1 Oct 2020 14:57:26 +1000 Subject: [PATCH 386/802] for version 3.8.1-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3408fe084..34e0ca07b 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.8.0 + 3.8.1-SNAPSHOT UTF-8 From a1fec9c307bb18612c1204f47e043cfdb6108f71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Oct 2020 07:40:46 +0000 Subject: [PATCH 387/802] Bump junit from 4.12 to 4.13.1 Bumps [junit](https://github.com/junit-team/junit4) from 4.12 to 4.13.1. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.12.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.12...r4.13.1) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 34e0ca07b..929574442 100644 --- a/pom.xml +++ b/pom.xml @@ -164,7 +164,7 @@ junit junit - 4.12 + 4.13.1 test From aa275afa2a48df0d54a7bd272858ab30df67a3a3 Mon Sep 17 00:00:00 2001 From: ssether Date: Thu, 8 Oct 2020 16:32:28 -0500 Subject: [PATCH 388/802] Adding PJSIPShowEndpoint --- .../manager/AbstractManagerEventListener.java | 16 + .../action/PJSipShowContactsAction.java | 12 +- .../action/PJSipShowEndpointAction.java | 80 ++ .../action/PJSipShowEndpointsAction.java | 4 +- .../asteriskjava/manager/event/AorDetail.java | 157 +++ .../manager/event/AuthDetail.java | 121 ++ .../manager/event/ContactStatusDetail.java | 171 +++ .../manager/event/EndpointDetail.java | 1148 +++++++++++++++++ .../manager/event/EndpointDetailComplete.java | 87 ++ .../manager/event/EndpointListComplete.java | 18 +- .../manager/event/TransportDetail.java | 314 +++++ .../manager/internal/AbstractBuilder.java | 6 +- .../internal/ManagerConnectionImpl.java | 2 + .../manager/internal/ResponseEventsImpl.java | 2 +- .../java/org/asteriskjava/util/AstUtil.java | 28 + 15 files changed, 2146 insertions(+), 20 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java create mode 100644 src/main/java/org/asteriskjava/manager/event/AorDetail.java create mode 100644 src/main/java/org/asteriskjava/manager/event/AuthDetail.java create mode 100644 src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java create mode 100644 src/main/java/org/asteriskjava/manager/event/EndpointDetail.java create mode 100644 src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java create mode 100644 src/main/java/org/asteriskjava/manager/event/TransportDetail.java diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 79bc4190a..4a28bb58e 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -764,7 +764,23 @@ public void handleEvent(UnpausedEvent event) public void handleEvent(VarSetEvent event) { } + + public void handleEvent(EndpointDetail event) + { + } + + public void handleEvent(AorDetail event) + { + } + public void handleEvent(ContactStatusDetail event) + { + } + + public void handleEvent(EndpointDetailComplete event) + { + } + /** * Dispatches to the appropriate handleEvent(...) method. * diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java index c4948961c..b902e2825 100644 --- a/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java @@ -20,18 +20,18 @@ import org.asteriskjava.manager.event.ResponseEvent; /** - * Retrieves a list of all defined SIP peers. + * Retrieves a list of all defined PJSIP contacts. *

    - * For each peer that is found a PeerEntryEvent is sent by Asterisk containing - * the details. When all peers have been reported a PeerlistCompleteEvent is + * For each contact that is found a ContactList is sent by Asterisk containing + * the details. When all contact have been reported a ContactListComplete is * sent. *

    - * Available since Asterisk 1.2 Permission required: write=system + * Available since Asterisk 16 Permission required: write=system * * @author srt * @version $Id$ - * @see org.asteriskjava.manager.event.PeerEntryEvent - * @see org.asteriskjava.manager.event.PeerlistCompleteEvent + * @see org.asteriskjava.manager.event.ContactList + * @see org.asteriskjava.manager.event.ContactListComplete * @since 0.2 */ public class PJSipShowContactsAction extends AbstractManagerAction implements EventGeneratingAction diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java new file mode 100644 index 000000000..186a27c12 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java @@ -0,0 +1,80 @@ +/* + * 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.manager.action; + +import org.asteriskjava.manager.event.EndpointDetailComplete; +import org.asteriskjava.manager.event.ResponseEvent; + +/** + * Retrieves details about a given endpoint. + *

    + * For the given endpoint, the call will return several events, including + * EndpointDetail, AorDetail, AuthDetail, TransportDetail, ContactStatusDetail,and IdentifyDetail. + * + * Some events may appear multiple times. + * + * When all events have been reported a EndpointDetailComplete is + * sent. + *

    + * Available since Asterisk 12 Permission required: write=system + * + * @author Steve Sether + * @version $Id$ + * @see org.asteriskjava.manager.event.ContactStatusDetail + * @see org.asteriskjava.manager.event.AorDetail + * @see org.asteriskjava.manager.event.EndpointDetail + * @see org.asteriskjava.manager.event.TransportDetail + * @see org.asteriskjava.manager.event.AuthDetail + * @see org.asteriskjava.manager.event.EndpointDetailComplete + * @since 12 + */ +public class PJSipShowEndpointAction extends AbstractManagerAction implements EventGeneratingAction +{ + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -5508189961610900058L; + private String endpoint; + + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + /** + * Creates a new SipPeersAction. + */ + public PJSipShowEndpointAction() + { + + } + + @Override + public String getAction() + { + return "PJSIPShowEndpoint"; + } + + public Class< ? extends ResponseEvent> getActionCompleteEventClass() + { + return EndpointDetailComplete.class; + } +} diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java index f33aa8eaf..d1acaa3f5 100644 --- a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java @@ -26,13 +26,13 @@ * the details. When all peers have been reported a PeerlistCompleteEvent is * sent. *

    - * Available since Asterisk 1.2 Permission required: write=system + * Available since Asterisk 12 Permission required: write=system * * @author srt * @version $Id$ * @see org.asteriskjava.manager.event.PeerEntryEvent * @see org.asteriskjava.manager.event.PeerlistCompleteEvent - * @since 0.2 + * @since 12 */ public class PJSipShowEndpointsAction extends AbstractManagerAction implements EventGeneratingAction { diff --git a/src/main/java/org/asteriskjava/manager/event/AorDetail.java b/src/main/java/org/asteriskjava/manager/event/AorDetail.java new file mode 100644 index 000000000..e6ebac3d5 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/AorDetail.java @@ -0,0 +1,157 @@ +package org.asteriskjava.manager.event; + +import org.asteriskjava.util.AstUtil; + +/** + * A ContactStatusDetail event is triggered in response to a + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, + * and contains information about a PJSIP Contact + *

    + * + * @author Steve Sether + * @version $Id$ + * @since 12 + */ + +public class AorDetail extends ResponseEvent { + + /** + * Serial version identifier. + */ + private static final long serialVersionUID = 2634171854313358591L; + public AorDetail(Object source) { + super(source); + } + + + private String objectType; + private String objectName; + private int minimumExpiration; + private int defaultExpiration; + private Float qualifyTimeout; + private String mailboxes; + private Boolean supportPath; + private String voicemailExtension; + private int maxContacts; + private Boolean authenticateQualify; + private String contacts; + private int maximumExpiration; + private int qualifyFrequency; + private Boolean removeExisting; + private String outboundProxy; + private int totalContacts; + private int contactsRegistered; + private String endpointName; + public String getObjectType() { + return objectType; + } + public void setObjectType(String objectType) { + this.objectType = objectType; + } + public String getObjectName() { + return objectName; + } + public void setObjectName(String objectName) { + this.objectName = objectName; + } + public int getMinimumExpiration() { + return minimumExpiration; + } + public void setMinimumExpiration(int minimumExpiration) { + this.minimumExpiration = minimumExpiration; + } + public int getDefaultExpiration() { + return defaultExpiration; + } + public void setDefaultExpiration(int defaultExpiration) { + this.defaultExpiration = defaultExpiration; + } + public Float getQualifyTimeout() { + return qualifyTimeout; + } + public void setQualifyTimeout(Float qualifyTimeout) { + this.qualifyTimeout = qualifyTimeout; + } + public String getMailboxes() { + return mailboxes; + } + public void setMailboxes(String mailboxes) { + this.mailboxes = mailboxes; + } + public Boolean isSupportPath() { + return supportPath; + } + public void setSupportPath(Boolean supportPath) { + this.supportPath = supportPath; + } + public String getVoicemailExtension() { + return voicemailExtension; + } + public void setVoicemailExtension(String voicemailExtension) { + this.voicemailExtension = voicemailExtension; + } + public int getMaxContacts() { + return maxContacts; + } + public void setMaxContacts(int maxContacts) { + this.maxContacts = maxContacts; + } + public Boolean isAuthenticateQualify() { + return authenticateQualify; + } + public void setAuthenticateQualify(Boolean authenticateQualify) { + this.authenticateQualify = authenticateQualify; + } + public String getContacts() { + return contacts; + } + public void setContacts(String contacts) { + this.contacts = contacts; + } + public int getMaximumExpiration() { + return maximumExpiration; + } + public void setMaximumExpiration(int maximumExpiration) { + this.maximumExpiration = maximumExpiration; + } + public int getQualifyFrequency() { + return qualifyFrequency; + } + public void setQualifyFrequency(int qualifyFrequency) { + this.qualifyFrequency = qualifyFrequency; + } + public Boolean isRemoveExisting() { + return removeExisting; + } + public void setRemoveExisting(Boolean removeExisting) { + this.removeExisting = removeExisting; + } + public String getOutboundProxy() { + return outboundProxy; + } + public void setOutboundProxy(String outboundProxy) { + this.outboundProxy = outboundProxy; + } + public int getTotalContacts() { + return totalContacts; + } + public void setTotalContacts(int totalContacts) { + this.totalContacts = totalContacts; + } + public int getContactsRegistered() { + return contactsRegistered; + } + public void setContactsRegistered(int contactsRegistered) { + this.contactsRegistered = contactsRegistered; + } + public String getEndpointName() { + return endpointName; + } + public void setEndpointName(String endpointName) { + this.endpointName = endpointName; + } + + + + +} diff --git a/src/main/java/org/asteriskjava/manager/event/AuthDetail.java b/src/main/java/org/asteriskjava/manager/event/AuthDetail.java new file mode 100644 index 000000000..298e89d69 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/AuthDetail.java @@ -0,0 +1,121 @@ +package org.asteriskjava.manager.event; + + +/** + * A AuthDetail event is triggered in response to a + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, + * and contains information about a PJSIP Contact + *

    + * + * @author Steve Sether + * @version $Id$ + * @since 12 + */ + +public class AuthDetail extends ResponseEvent { + + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -4998727723768836212L; + + private String event; + private String objectType; + private String objectName; + private String username; + private String password; + private String md5Cred; + private String realm; + private int nonceLifetime; + private String authType; + private String EndpointName; + + public AuthDetail(Object source) { + super(source); + } + + public String getEvent() { + return event; + } + + public void setEvent(String event) { + this.event = event; + } + + public String getObjectType() { + return objectType; + } + + public void setObjectType(String objectType) { + this.objectType = objectType; + } + + public String getObjectName() { + return objectName; + } + + public void setObjectName(String objectName) { + this.objectName = objectName; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getMd5Cred() { + return md5Cred; + } + + public void setMd5Cred(String md5Cred) { + this.md5Cred = md5Cred; + } + + public String getRealm() { + return realm; + } + + public void setRealm(String realm) { + this.realm = realm; + } + + public int getNonceLifetime() { + return nonceLifetime; + } + + public void setNonceLifetime(int nonceLifetime) { + this.nonceLifetime = nonceLifetime; + } + + public String getAuthType() { + return authType; + } + + public void setAuthType(String authType) { + this.authType = authType; + } + + public String getEndpointName() { + return EndpointName; + } + + public void setEndpointName(String endpointName) { + EndpointName = endpointName; + } + + + + + +} diff --git a/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java new file mode 100644 index 000000000..bf451bd1a --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java @@ -0,0 +1,171 @@ +package org.asteriskjava.manager.event; + +import org.asteriskjava.util.AstUtil; + +/** + * A ContactStatusDetail event is triggered in response to a + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, + * and contains information about a PJSIP Contact + *

    + * + * @author Steve Sether + * @version $Id$ + * @since 12 + */ + +public class ContactStatusDetail extends ResponseEvent { + + /** + * Serial version identifier. + */ + private static final long serialVersionUID = 987290433601178780L; + private String aor; + private String uri; + private String userAgent; + private long regExpire; + private String viaAddress; + private String callID; + private String status; + // roundtripusec when it contains a value is a long, but when it doesn't + // asterisk reports "N/A" + private String roundtripUsec; + private String endpointName; + private String id; + private Boolean authenticateQualify; + private String outboundProxy; + private String path; + private int qualifyFrequency; + private Float qualifyTimeout; + + public String getAor() { + return aor; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public void setAor(String aor) { + this.aor = aor; + } + + public String getUri() { + return uri; + } + + public void setUri(String uri) { + this.uri = uri; + } + + public String getUserAgent() { + return userAgent; + } + + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + + public long getRegExpire() { + return regExpire; + } + + public void setRegExpire(long regExpire) { + this.regExpire = regExpire; + } + + public String getViaAddress() { + return viaAddress; + } + + public void setViaAddress(String viaAddress) { + this.viaAddress = viaAddress; + } + + public String getCallID() { + return callID; + } + + public void setCallID(String callID) { + this.callID = callID; + } + + public String getEndpointName() { + return endpointName; + } + + public void setEndpointName(String endpointName) { + this.endpointName = endpointName; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Boolean isAuthenticateQualify() { + return authenticateQualify; + } + + public void setAuthenticateQualify(Boolean authenticateQualify) { + this.authenticateQualify = authenticateQualify; + } + + public String getOutboundProxy() { + return outboundProxy; + } + + public void setOutboundProxy(String outboundProxy) { + this.outboundProxy = outboundProxy; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public int getQualifyFrequency() { + return qualifyFrequency; + } + + public void setQualifyFrequency(int qualifyFrequency) { + this.qualifyFrequency = qualifyFrequency; + } + + public Float getQualifyTimeout() { + return qualifyTimeout; + } + + public void setQualifyTimeout(Float qualifyTimeout) { + this.qualifyTimeout = qualifyTimeout; + } + + public void setQualifyTimeout(String qualifyTimeout) { + this.qualifyTimeout = Float.parseFloat(qualifyTimeout); + } + + public ContactStatusDetail(Object source) { + super(source); + } + + public String getRoundtripUsec() { + return roundtripUsec; + } + + public void setRoundtripUsec(String roundtripUsec) { + this.roundtripUsec = roundtripUsec; + } + + + + +} diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java b/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java new file mode 100644 index 000000000..b83d1a07f --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java @@ -0,0 +1,1148 @@ +package org.asteriskjava.manager.event; + +import org.asteriskjava.util.AstUtil; + +/** + * A EndpointDetail event is triggered in response to a + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, + * and contains information about a PJSIP endpoint + *

    + * + * @author Steve Sether + * @version $Id$ + * @since 12 + */ + +public class EndpointDetail extends ResponseEvent { + + /** + * Serial version identifier. + */ + private static final long serialVersionUID = 77481930059189731L; + private Integer listItems; + private String eventList; + + public Integer getListItems() { + return listItems; + } + + public void setListItems(Integer listItems) { + this.listItems = listItems; + } + + public String getEventList() { + return eventList; + } + + public void setEventList(String eventList) { + this.eventList = eventList; + } + + private String objectName; + private String objectType; + private Boolean rpidImmediate; + private Boolean webrtc; + private Boolean ignorel83WithoutSdp; + private int deviceStateBusyAt; + private int t38UdptlMaxdatagram; + private int dtlsRekey; + private String namedPickupGroup; + private String directMediaMethod; + private Boolean sendRpid; + private String pickupGroup; + private String sdpSession; + private String dtlsVerify; + private String messageContext; + private String mailboxes; + private String recordOnFeature; + private String dtlsPrivateKey; + private String dtlsFingerprint; + private String fromDomain; + private int timersSessExpires; + private String namedCallGroup; + private String dtlsCipher; + private Boolean mediaEncryptionOptimistic; + private Boolean suppressQ850ReasonHeaders; + private String aors; + private String identifyBy; + private String calleridPrivacy; + private String mwiSubscribeReplacesUnsolicited; + private String cosAudio; + private Boolean followEarlyMediaFork; + private String context; + private Boolean rtpSymmetric; + private String transport; + private String mohSuggest; + private Boolean t38Udptl; + private Boolean faxDetect; + private String tosVideo; + private Boolean srtpTag32; + private Boolean referBlindProgress; + private int maxAudioStreams; + private Boolean bundle; + private Boolean useAvpf; + private String callGroup; + private Boolean sendConnectedLine; + private int faxDetectTimeout; + private String sdpOwner; + private Boolean forceRport; + private String calleridTag; + private int rtpTimeoutHold; + private Boolean usePtime; + private String mediaAddress; + private String voicemailExtension; + private int rtpTimeout; + private String setVar; + private String contactAcl; + private Boolean preferredCodecOnly; + private Boolean forceAvp; + private String recordOffFeature; + private String fromUser; + private Boolean sendDiversion; + private Boolean t38UdptlIpv6; + private String toneZone; + private String language; + private Boolean allowSubscribe; + private Boolean rtpIpv6; + private String callerid; + private Boolean mohPassthrough; + private String cosVideo; + private String dtlsAutoGenerateCert; + private Boolean asymmetricRtpCodec; + private Boolean iceSupport; + private Boolean aggregateMwi; + private Boolean oneTouchRecording; + private String mwiFromUser; + private String accountcode; + private String allow; + private Boolean rewriteContact; + private Boolean userEqPhone; + private String rtpEngine; + private String subscribeContext; + private Boolean notifyEarlyInuseRinging; + private String incomingMwiMailbox; + private String auth; + private String directMediaGlareMitigation; + private Boolean trustIdInbound; + private Boolean bindRtpToMediaAddress; + private Boolean disableDirectMediaOnNat; + private Boolean mediaEncryption; + private Boolean mediaUseReceivedTransport; + private Boolean allowOverlap; + private String dtmfMode; + private String outboundAuth; + private String tosAudio; + private String dtlsCertFile; + private String dtlsCaPath; + private String dtlsSetup; + private String connectedLineMethod; + private Boolean g726NonStandard; + private String _100rel; + private String timers; + private Boolean directMedia; + private String acl; + private int timersMinSe; + private Boolean trustIdOutbound; + private int subMinExpiry; + private Boolean rtcpMux; + private int maxVideoStreams; + private Boolean acceptMultipleSdpAnswers; + private Boolean trustConnectedLine; + private Boolean sendPai; + private int rtpKeepalive; + private String t38UdptlEc; + private Boolean t38UdptlNat; + private Boolean allowTransfer; + private String dtlsCaFile; + private String outboundProxy; + private Boolean inbandProgress; + private String deviceState; + private String activeChannels; + private Boolean ignore183withoutsdp; + + public int getMaxVideoStreams() { + return maxVideoStreams; + } + + public void setMaxVideoStreams(int maxVideoStreams) { + this.maxVideoStreams = maxVideoStreams; + } + + public String getObjectName() { + return objectName; + } + + public void setObjectName(String objectName) { + this.objectName = objectName; + } + + public String getObjectType() { + return objectType; + } + + public void setObjectType(String objectType) { + this.objectType = objectType; + } + + public Boolean isRpidImmediate() { + return rpidImmediate; + } + + public void setRpidImmediate(Boolean rpidImmediate) { + this.rpidImmediate = rpidImmediate; + } + + public Boolean isWebrtc() { + return webrtc; + } + + public void setWebrtc(Boolean webrtc) { + this.webrtc = webrtc; + } + + public Boolean isIgnorel83WithoutSdp() { + return ignorel83WithoutSdp; + } + + public void setIgnorel83WithoutSdp(Boolean ignorel83WithoutSdp) { + this.ignorel83WithoutSdp = ignorel83WithoutSdp; + } + + public int getDeviceStateBusyAt() { + return deviceStateBusyAt; + } + + public void setDeviceStateBusyAt(int deviceStateBusyAt) { + this.deviceStateBusyAt = deviceStateBusyAt; + } + + public int getT38UdptlMaxdatagram() { + return t38UdptlMaxdatagram; + } + + public void setT38UdptlMaxdatagram(int t38UdptlMaxdatagram) { + this.t38UdptlMaxdatagram = t38UdptlMaxdatagram; + } + + public int getDtlsRekey() { + return dtlsRekey; + } + + public void setDtlsRekey(int dtlsRekey) { + this.dtlsRekey = dtlsRekey; + } + + public String getNamedPickupGroup() { + return namedPickupGroup; + } + + public void setNamedPickupGroup(String namedPickupGroup) { + this.namedPickupGroup = namedPickupGroup; + } + + public String getDirectMediaMethod() { + return directMediaMethod; + } + + public void setDirectMediaMethod(String directMediaMethod) { + this.directMediaMethod = directMediaMethod; + } + + public Boolean isSendRpid() { + return sendRpid; + } + + public void setSendRpid(Boolean sendRpid) { + this.sendRpid = sendRpid; + } + + public String getPickupGroup() { + return pickupGroup; + } + + public void setPickupGroup(String pickupGroup) { + this.pickupGroup = pickupGroup; + } + + public String getSdpSession() { + return sdpSession; + } + + public void setSdpSession(String sdpSession) { + this.sdpSession = sdpSession; + } + + public String getDtlsVerify() { + return dtlsVerify; + } + + public void setDtlsVerify(String dtlsVerify) { + this.dtlsVerify = dtlsVerify; + } + + public String getMessageContext() { + return messageContext; + } + + public void setMessageContext(String messageContext) { + this.messageContext = messageContext; + } + + public String getMailboxes() { + return mailboxes; + } + + public void setMailboxes(String mailboxes) { + this.mailboxes = mailboxes; + } + + public String getRecordOnFeature() { + return recordOnFeature; + } + + public void setRecordOnFeature(String recordOnFeature) { + this.recordOnFeature = recordOnFeature; + } + + public String getDtlsPrivateKey() { + return dtlsPrivateKey; + } + + public void setDtlsPrivateKey(String dtlsPrivateKey) { + this.dtlsPrivateKey = dtlsPrivateKey; + } + + public String getDtlsFingerprint() { + return dtlsFingerprint; + } + + public void setDtlsFingerprint(String dtlsFingerprint) { + this.dtlsFingerprint = dtlsFingerprint; + } + + public String getFromDomain() { + return fromDomain; + } + + public void setFromDomain(String fromDomain) { + this.fromDomain = fromDomain; + } + + public int getTimersSessExpires() { + return timersSessExpires; + } + + public void setTimersSessExpires(int timersSessExpires) { + this.timersSessExpires = timersSessExpires; + } + + public String getNamedCallGroup() { + return namedCallGroup; + } + + public void setNamedCallGroup(String namedCallGroup) { + this.namedCallGroup = namedCallGroup; + } + + public String getDtlsCipher() { + return dtlsCipher; + } + + public void setDtlsCipher(String dtlsCipher) { + this.dtlsCipher = dtlsCipher; + } + + public Boolean isMediaEncryptionOptimistic() { + return mediaEncryptionOptimistic; + } + + public void setMediaEncryptionOptimistic(Boolean mediaEncryptionOptimistic) { + this.mediaEncryptionOptimistic = mediaEncryptionOptimistic; + } + + public Boolean isSuppressQ850ReasonHeaders() { + return suppressQ850ReasonHeaders; + } + + public void setSuppressQ850ReasonHeaders(Boolean suppressQ850ReasonHeaders) { + this.suppressQ850ReasonHeaders = suppressQ850ReasonHeaders; + } + + public String getAors() { + return aors; + } + + public void setAors(String aors) { + this.aors = aors; + } + + public String getIdentifyBy() { + return identifyBy; + } + + public void setIdentifyBy(String identifyBy) { + this.identifyBy = identifyBy; + } + + public String getCalleridPrivacy() { + return calleridPrivacy; + } + + public void setCalleridPrivacy(String calleridPrivacy) { + this.calleridPrivacy = calleridPrivacy; + } + + public String getMwiSubscribeReplacesUnsolicited() { + return mwiSubscribeReplacesUnsolicited; + } + + public void setMwiSubscribeReplacesUnsolicited(String mwiSubscribeReplacesUnsolicited) { + this.mwiSubscribeReplacesUnsolicited = mwiSubscribeReplacesUnsolicited; + } + + public Boolean isFollowEarlyMediaFork() { + return followEarlyMediaFork; + } + + public void setFollowEarlyMediaFork(Boolean followEarlyMediaFork) { + this.followEarlyMediaFork = followEarlyMediaFork; + } + + public String getContext() { + return context; + } + + public void setContext(String context) { + this.context = context; + } + + public Boolean isRtpSymmetric() { + return rtpSymmetric; + } + + public void setRtpSymmetric(Boolean rtpSymmetric) { + this.rtpSymmetric = rtpSymmetric; + } + + public String getTransport() { + return transport; + } + + public void setTransport(String transport) { + this.transport = transport; + } + + public String getMohSuggest() { + return mohSuggest; + } + + public void setMohSuggest(String mohSuggest) { + this.mohSuggest = mohSuggest; + } + + public Boolean isT38Udptl() { + return t38Udptl; + } + + public void setT38Udptl(Boolean t38Udptl) { + this.t38Udptl = t38Udptl; + } + + public Boolean isFaxDetect() { + return faxDetect; + } + + public void setFaxDetect(Boolean faxDetect) { + this.faxDetect = faxDetect; + } + + public Boolean getSrtpTag32() { + return srtpTag32; + } + + public void setSrtpTag32(Boolean srtpTag32) { + this.srtpTag32 = srtpTag32; + } + + public Boolean isReferBlindProgress() { + return referBlindProgress; + } + + public void setReferBlindProgress(Boolean referBlindProgress) { + this.referBlindProgress = referBlindProgress; + } + + public int getMaxAudioStreams() { + return maxAudioStreams; + } + + public void setMaxAudioStreams(int maxAudioStreams) { + this.maxAudioStreams = maxAudioStreams; + } + + public Boolean isBundle() { + return bundle; + } + + public void setBundle(Boolean bundle) { + this.bundle = bundle; + } + + + public Boolean isUseAvpf() { + return useAvpf; + } + + public void setUseAvpf(Boolean useAvpf) { + this.useAvpf = useAvpf; + } + + + public String getCallGroup() { + return callGroup; + } + + public void setCallGroup(String callGroup) { + this.callGroup = callGroup; + } + + public Boolean isSendConnectedLine() { + return sendConnectedLine; + } + + public void setSendConnectedLine(Boolean sendConnectedLine) { + this.sendConnectedLine = sendConnectedLine; + } + + + public int getFaxDetectTimeout() { + return faxDetectTimeout; + } + + public void setFaxDetectTimeout(int faxDetectTimeout) { + this.faxDetectTimeout = faxDetectTimeout; + } + + public String getSdpOwner() { + return sdpOwner; + } + + public void setSdpOwner(String sdpOwner) { + this.sdpOwner = sdpOwner; + } + + public Boolean isForceRport() { + return forceRport; + } + + public void setForceRport(Boolean forceRport) { + this.forceRport = forceRport; + } + + + public String getCalleridTag() { + return calleridTag; + } + + public void setCalleridTag(String calleridTag) { + this.calleridTag = calleridTag; + } + + public int getRtpTimeoutHold() { + return rtpTimeoutHold; + } + + public void setRtpTimeoutHold(int rtpTimeoutHold) { + this.rtpTimeoutHold = rtpTimeoutHold; + } + + public Boolean isUsePtime() { + return usePtime; + } + + public void setUsePtime(Boolean usePtime) { + this.usePtime = usePtime; + } + + + public String getMediaAddress() { + return mediaAddress; + } + + public void setMediaAddress(String mediaAddress) { + this.mediaAddress = mediaAddress; + } + + public String getVoicemailExtension() { + return voicemailExtension; + } + + public void setVoicemailExtension(String voicemailExtension) { + this.voicemailExtension = voicemailExtension; + } + + public int getRtpTimeout() { + return rtpTimeout; + } + + public void setRtpTimeout(int rtpTimeout) { + this.rtpTimeout = rtpTimeout; + } + + public String getSetVar() { + return setVar; + } + + public void setSetVar(String setVar) { + this.setVar = setVar; + } + + public String getContactAcl() { + return contactAcl; + } + + public void setContactAcl(String contactAcl) { + this.contactAcl = contactAcl; + } + + public Boolean isPreferredCodecOnly() { + return preferredCodecOnly; + } + + public void setPreferredCodecOnly(Boolean preferredCodecOnly) { + this.preferredCodecOnly = preferredCodecOnly; + } + + public Boolean isForceAvp() { + return forceAvp; + } + + public void setForceAvp(Boolean forceAvp) { + this.forceAvp = forceAvp; + } + + + public String getRecordOffFeature() { + return recordOffFeature; + } + + public void setRecordOffFeature(String recordOffFeature) { + this.recordOffFeature = recordOffFeature; + } + + public String getFromUser() { + return fromUser; + } + + public void setFromUser(String fromUser) { + this.fromUser = fromUser; + } + + public Boolean isSendDiversion() { + return sendDiversion; + } + + public void setSendDiversion(Boolean sendDiversion) { + this.sendDiversion = sendDiversion; + } + + + public Boolean isT38UdptlIpv6() { + return t38UdptlIpv6; + } + + public void setT38UdptlIpv6(Boolean t38UdptlIpv6) { + this.t38UdptlIpv6 = t38UdptlIpv6; + } + + + public String getToneZone() { + return toneZone; + } + + public void setToneZone(String toneZone) { + this.toneZone = toneZone; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public Boolean isAllowSubscribe() { + return allowSubscribe; + } + + public void setAllowSubscribe(Boolean allowSubscribe) { + this.allowSubscribe = allowSubscribe; + } + + public Boolean isRtpIpv6() { + return rtpIpv6; + } + + public void setRtpIpv6(Boolean rtpIpv6) { + this.rtpIpv6 = rtpIpv6; + } + + + public String getCallerid() { + return callerid; + } + + public void setCallerid(String callerid) { + this.callerid = callerid; + } + + public Boolean isMohPassthrough() { + return mohPassthrough; + } + + public void setMohPassthrough(Boolean mohPassthrough) { + this.mohPassthrough = mohPassthrough; + } + + public String getCosAudio() { + return cosAudio; + } + + public void setCosAudio(String cosAudio) { + this.cosAudio = cosAudio; + } + + public String getCosVideo() { + return cosVideo; + } + + public void setCosVideo(String cosVideo) { + this.cosVideo = cosVideo; + } + + public String getDtlsAutoGenerateCert() { + return dtlsAutoGenerateCert; + } + + public void setDtlsAutoGenerateCert(String dtlsAutoGenerateCert) { + this.dtlsAutoGenerateCert = dtlsAutoGenerateCert; + } + + public Boolean isAsymmetricRtpCodec() { + return asymmetricRtpCodec; + } + + public void setAsymmetricRtpCodec(Boolean asymmetricRtpCodec) { + this.asymmetricRtpCodec = asymmetricRtpCodec; + } + + + public Boolean isIceSupport() { + return iceSupport; + } + + public void setIceSupport(Boolean iceSupport) { + this.iceSupport = iceSupport; + } + + + public Boolean isAggregateMwi() { + return aggregateMwi; + } + + public void setAggregateMwi(Boolean aggregateMwi) { + this.aggregateMwi = aggregateMwi; + } + + + public Boolean isOneTouchRecording() { + return oneTouchRecording; + } + + public void setOneTouchRecording(Boolean oneTouchRecording) { + this.oneTouchRecording = oneTouchRecording; + } + + + public String getMwiFromUser() { + return mwiFromUser; + } + + public void setMwiFromUser(String mwiFromUser) { + this.mwiFromUser = mwiFromUser; + } + + public String getAccountcode() { + return accountcode; + } + + public void setAccountcode(String accountcode) { + this.accountcode = accountcode; + } + + public String getAllow() { + return allow; + } + + public void setAllow(String allow) { + this.allow = allow; + } + + public Boolean isRewriteContact() { + return rewriteContact; + } + + public void setRewriteContact(Boolean rewriteContact) { + this.rewriteContact = rewriteContact; + } + + public Boolean isUserEqPhone() { + return userEqPhone; + } + + public void setUserEqPhone(Boolean userEqPhone) { + this.userEqPhone = userEqPhone; + } + + public String getRtpEngine() { + return rtpEngine; + } + + public void setRtpEngine(String rtpEngine) { + this.rtpEngine = rtpEngine; + } + + public String getSubscribeContext() { + return subscribeContext; + } + + public void setSubscribeContext(String subscribeContext) { + this.subscribeContext = subscribeContext; + } + + public Boolean isNotifyEarlyInuseRinging() { + return notifyEarlyInuseRinging; + } + + public void setNotifyEarlyInuseRinging(Boolean notifyEarlyInuseRinging) { + this.notifyEarlyInuseRinging = notifyEarlyInuseRinging; + } + + public String getIncomingMwiMailbox() { + return incomingMwiMailbox; + } + + public void setIncomingMwiMailbox(String incomingMwiMailbox) { + this.incomingMwiMailbox = incomingMwiMailbox; + } + + public String getAuth() { + return auth; + } + + public void setAuth(String auth) { + this.auth = auth; + } + + public String getDirectMediaGlareMitigation() { + return directMediaGlareMitigation; + } + + public void setDirectMediaGlareMitigation(String directMediaGlareMitigation) { + this.directMediaGlareMitigation = directMediaGlareMitigation; + } + + public Boolean isTrustIdInbound() { + return trustIdInbound; + } + + public void setTrustIdInbound(Boolean trustIdInbound) { + this.trustIdInbound = trustIdInbound; + } + + public Boolean isBindRtpToMediaAddress() { + return bindRtpToMediaAddress; + } + + public void setBindRtpToMediaAddress(Boolean bindRtpToMediaAddress) { + this.bindRtpToMediaAddress = bindRtpToMediaAddress; + } + + public Boolean isDisableDirectMediaOnNat() { + return disableDirectMediaOnNat; + } + + public void setDisableDirectMediaOnNat(Boolean disableDirectMediaOnNat) { + this.disableDirectMediaOnNat = disableDirectMediaOnNat; + } + + public Boolean isMediaEncryption() { + return mediaEncryption; + } + + public void setMediaEncryption(Boolean mediaEncryption) { + this.mediaEncryption = mediaEncryption; + } + + public Boolean isMediaUseReceivedTransport() { + return mediaUseReceivedTransport; + } + + public void setMediaUseReceivedTransport(Boolean mediaUseReceivedTransport) { + this.mediaUseReceivedTransport = mediaUseReceivedTransport; + } + + public Boolean isAllowOverlap() { + return allowOverlap; + } + + public void setAllowOverlap(Boolean allowOverlap) { + this.allowOverlap = allowOverlap; + } + + public String getDtmfMode() { + return dtmfMode; + } + + public void setDtmfMode(String dtmfMode) { + this.dtmfMode = dtmfMode; + } + + public String getOutboundAuth() { + return outboundAuth; + } + + public void setOutboundAuth(String outboundAuth) { + this.outboundAuth = outboundAuth; + } + + public String getTosVideo() { + return tosVideo; + } + + public void setTosVideo(String tosVideo) { + this.tosVideo = tosVideo; + } + + public String getTosAudio() { + return tosAudio; + } + + public void setTosAudio(String tosAudio) { + this.tosAudio = tosAudio; + } + + public String getDtlsCertFile() { + return dtlsCertFile; + } + + public void setDtlsCertFile(String dtlsCertFile) { + this.dtlsCertFile = dtlsCertFile; + } + + public String getDtlsCaPath() { + return dtlsCaPath; + } + + public void setDtlsCaPath(String dtlsCaPath) { + this.dtlsCaPath = dtlsCaPath; + } + + public String getDtlsSetup() { + return dtlsSetup; + } + + public void setDtlsSetup(String dtlsSetup) { + this.dtlsSetup = dtlsSetup; + } + + public String getConnectedLineMethod() { + return connectedLineMethod; + } + + public void setConnectedLineMethod(String connectedLineMethod) { + this.connectedLineMethod = connectedLineMethod; + } + + public Boolean isG726NonStandard() { + return g726NonStandard; + } + + public void setG726NonStandard(Boolean g726NonStandard) { + this.g726NonStandard = g726NonStandard; + } + + public String get100rel() { + return _100rel; + } + + public void set100rel(String _100rel) { + this._100rel = _100rel; + } + + public String getTimers() { + return timers; + } + + public void setTimers(String timers) { + this.timers = timers; + } + + public Boolean isDirectMedia() { + return directMedia; + } + + public void setDirectMedia(Boolean directMedia) { + this.directMedia = directMedia; + } + + public String getAcl() { + return acl; + } + + public void setAcl(String acl) { + this.acl = acl; + } + + public int getTimersMinSe() { + return timersMinSe; + } + + public void setTimersMinSe(int timersMinSe) { + this.timersMinSe = timersMinSe; + } + + public Boolean isTrustIdOutbound() { + return trustIdOutbound; + } + + public void setTrustIdOutbound(Boolean trustIdOutbound) { + this.trustIdOutbound = trustIdOutbound; + } + + public int getSubMinExpiry() { + return subMinExpiry; + } + + public void setSubMinExpiry(int subMinExpiry) { + this.subMinExpiry = subMinExpiry; + } + + public Boolean isRtcpMux() { + return rtcpMux; + } + + public void setRtcpMux(Boolean rtcpMux) { + this.rtcpMux = rtcpMux; + } + + public Boolean isAcceptMultipleSdpAnswers() { + return acceptMultipleSdpAnswers; + } + + public void setAcceptMultipleSdpAnswers(Boolean acceptMultipleSdpAnswers) { + this.acceptMultipleSdpAnswers = acceptMultipleSdpAnswers; + } + + public Boolean isTrustConnectedLine() { + return trustConnectedLine; + } + + public void setTrustConnectedLine(Boolean trustConnectedLine) { + this.trustConnectedLine = trustConnectedLine; + } + + public Boolean isSendPai() { + return sendPai; + } + + public void setSendPai(Boolean sendPai) { + this.sendPai = sendPai; + } + + public int getRtpKeepalive() { + return rtpKeepalive; + } + + public void setRtpKeepalive(int rtpKeepalive) { + this.rtpKeepalive = rtpKeepalive; + } + + public String getT38UdptlEc() { + return t38UdptlEc; + } + + public void setT38UdptlEc(String t38UdptlEc) { + this.t38UdptlEc = t38UdptlEc; + } + + public Boolean isT38UdptlNat() { + return t38UdptlNat; + } + + public void setT38UdptlNat(Boolean t38UdptlNat) { + this.t38UdptlNat = t38UdptlNat; + } + + public Boolean isAllowTransfer() { + return allowTransfer; + } + + public void setAllowTransfer(Boolean allowTransfer) { + this.allowTransfer = allowTransfer; + } + + public String getDtlsCaFile() { + return dtlsCaFile; + } + + public void setDtlsCaFile(String dtlsCaFile) { + this.dtlsCaFile = dtlsCaFile; + } + + public String getOutboundProxy() { + return outboundProxy; + } + + public void setOutboundProxy(String outboundProxy) { + this.outboundProxy = outboundProxy; + } + + public Boolean isInbandProgress() { + return inbandProgress; + } + + public void setInbandProgress(Boolean inbandProgress) { + this.inbandProgress = inbandProgress; + } + + public String getDeviceState() { + return deviceState; + } + + public void setDeviceState(String deviceState) { + this.deviceState = deviceState; + } + + public String getActiveChannels() { + return activeChannels; + } + + public void setActiveChannels(String activeChannels) { + this.activeChannels = activeChannels; + } + + public EndpointDetail(Object source) { + super(source); + } + + public Boolean getIgnore183withoutsdp() { + return ignore183withoutsdp; + } + + public void setIgnore183withoutsdp(Boolean ignore183withoutsdp) { + this.ignore183withoutsdp = ignore183withoutsdp; + } + +} diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java b/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java new file mode 100644 index 000000000..015f87ca4 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java @@ -0,0 +1,87 @@ +/* + * 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.manager.event; + +/** + * A EndpointDetailComplete event is triggered after the details of an endpoint has been + * reported in response to a PJSIPShowEndpoint + *

    + * Available since Asterisk 12 + * + * @see org.asteriskjava.manager.event.PJSIpShowEndpoint + * @author Steve Sether + * @version $Id$ + * @since 12 + */ +public class EndpointDetailComplete extends ResponseEvent +{ + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -1177773673509373296L; + private Integer listItems; + private String eventList; + + /** + * Creates a new instance. + * + * @param source + */ + public EndpointDetailComplete(Object source) + { + super(source); + } + + /** + * Returns the number of EndpointDetail events that have been reported. + * + * @return the number of EndpointDetail events that have been reported. + */ + public Integer getListItems() + { + return listItems; + } + + /** + * Sets the number of EndpointDetail events that have been reported. + * + * @param listItems the number of EndpointDetail events that have been reported. + */ + public void setListItems(Integer listItems) + { + this.listItems = listItems; + } + + /** + * Returns always "Complete". + *

    + * Available since Asterisk 12. + * + * @return always returns "Complete" confirming that all EndpointDetail events have + * been sent. + * @since 12 + */ + public String getEventList() + { + return eventList; + } + + public void setEventList(String eventList) + { + this.eventList = eventList; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java b/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java index e1a1a5dd1..a11532edf 100644 --- a/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java +++ b/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java @@ -17,17 +17,15 @@ package org.asteriskjava.manager.event; /** - * A PeerlistCompleteEvent is triggered after the details of all peers has been - * reported in response to an SIPPeersAction or SIPShowPeerAction. + * A EndpointListComplete event is triggered after the details of all end points have been + * reported in response to a PJSIPShowEndpoints event. *

    - * Available since Asterisk 1.2 + * Available since Asterisk 12 * - * @see org.asteriskjava.manager.event.PeerEntryEvent - * @see org.asteriskjava.manager.action.SipPeersAction - * @see org.asteriskjava.manager.action.SipShowPeerAction + * @see org.asteriskjava.manager.event.PJSipShowEndpoints * @author srt * @version $Id$ - * @since 0.2 + * @since 12 */ public class EndpointListComplete extends ResponseEvent { @@ -49,9 +47,9 @@ public EndpointListComplete(Object source) } /** - * Returns the number of PeerEvents that have been reported. + * Returns the number of Endpoints that have been reported. * - * @return the number of PeerEvents that have been reported. + * @return the number of Endpoints that have been reported. */ public Integer getListItems() { @@ -59,7 +57,7 @@ public Integer getListItems() } /** - * Sets the number of PeerEvents that have been reported. + * Sets the number of Endpoints that have been reported. * * @param listItems the number of PeerEvents that have been reported. */ diff --git a/src/main/java/org/asteriskjava/manager/event/TransportDetail.java b/src/main/java/org/asteriskjava/manager/event/TransportDetail.java new file mode 100644 index 000000000..9153484c9 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/TransportDetail.java @@ -0,0 +1,314 @@ +package org.asteriskjava.manager.event; + +import org.asteriskjava.util.AstUtil; + +/** + * A TransportDetail event is triggered in response to a + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint} + *

    + * + * @author Steve Sether + * @version $Id$ + * @since 12 + */ + +public class TransportDetail extends ResponseEvent { + + /** + * + */ + private static final long serialVersionUID = 8558130768089350575L; + private String Event; + private String objectType; + private String pbjectName; + private String protocol; + private String bind; + private int asycOperations; + private String caListFile; + private String caListPath; + private String certFile; + private String privKeyFile; + private String password; + private String externalSignalingAddress; + private int externalSignalingPort; + private String externalMediaAddress; + private String domain; + private String verifyServer; + private String verifyClient; + private Boolean requireClientCert; + private String method; + private String cipher; + private String localNet; + private String tos; + private int cos; + private int websocketWriteTimeout; + private String endpointName; + + + /** + * Serial version identifier. + */ + public TransportDetail(Object source) { + super(source); + } + + + public String getEvent() { + return Event; + } + + + public void setEvent(String event) { + Event = event; + } + + + public String getObjectType() { + return objectType; + } + + + public void setObjectType(String objectType) { + this.objectType = objectType; + } + + + public String getPbjectName() { + return pbjectName; + } + + + public void setPbjectName(String pbjectName) { + this.pbjectName = pbjectName; + } + + + public String getProtocol() { + return protocol; + } + + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + + public String getBind() { + return bind; + } + + + public void setBind(String bind) { + this.bind = bind; + } + + + public int getAsycOperations() { + return asycOperations; + } + + + public void setAsycOperations(int asycOperations) { + this.asycOperations = asycOperations; + } + + + public String getCaListFile() { + return caListFile; + } + + + public void setCaListFile(String caListFile) { + this.caListFile = caListFile; + } + + + public String getCaListPath() { + return caListPath; + } + + + public void setCaListPath(String caListPath) { + this.caListPath = caListPath; + } + + + public String getCertFile() { + return certFile; + } + + + public void setCertFile(String certFile) { + this.certFile = certFile; + } + + + public String getPrivKeyFile() { + return privKeyFile; + } + + + public void setPrivKeyFile(String privKeyFile) { + this.privKeyFile = privKeyFile; + } + + + public String getPassword() { + return password; + } + + + public void setPassword(String password) { + this.password = password; + } + + + public String getExternalSignalingAddress() { + return externalSignalingAddress; + } + + + public void setExternalSignalingAddress(String externalSignalingAddress) { + this.externalSignalingAddress = externalSignalingAddress; + } + + + public int getExternalSignalingPort() { + return externalSignalingPort; + } + + + public void setExternalSignalingPort(int externalSignalingPort) { + this.externalSignalingPort = externalSignalingPort; + } + + + public String getExternalMediaAddress() { + return externalMediaAddress; + } + + + public void setExternalMediaAddress(String externalMediaAddress) { + this.externalMediaAddress = externalMediaAddress; + } + + + public String getDomain() { + return domain; + } + + + public void setDomain(String domain) { + this.domain = domain; + } + + + public String getVerifyServer() { + return verifyServer; + } + + + public void setVerifyServer(String verifyServer) { + this.verifyServer = verifyServer; + } + + + public String getVerifyClient() { + return verifyClient; + } + + + public void setVerifyClient(String verifyClient) { + this.verifyClient = verifyClient; + } + + + public Boolean getRequireClientCert() { + return requireClientCert; + } + + + public void setRequireClientCert(Boolean requireClientCert) { + this.requireClientCert = requireClientCert; + } + + + public String getMethod() { + return method; + } + + + public void setMethod(String method) { + this.method = method; + } + + + public String getCipher() { + return cipher; + } + + + public void setCipher(String cipher) { + this.cipher = cipher; + } + + + public String getLocalNet() { + return localNet; + } + + + public void setLocalNet(String localNet) { + this.localNet = localNet; + } + + + public String getTos() { + return tos; + } + + + public void setTos(String tos) { + this.tos = tos; + } + + + public int getCos() { + return cos; + } + + + public void setCos(int cos) { + this.cos = cos; + } + + + public int getWebsocketWriteTimeout() { + return websocketWriteTimeout; + } + + + public void setWebsocketWriteTimeout(int websocketWriteTimeout) { + this.websocketWriteTimeout = websocketWriteTimeout; + } + + + public String getEndpointName() { + return endpointName; + } + + + public void setEndpointName(String endpointName) { + this.endpointName = endpointName; + } + + + public static long getSerialversionuid() { + return serialVersionUID; + } + + + + + +} diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index 867c977a3..26f11e8cf 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -120,7 +120,11 @@ else if (dataType.isAssignableFrom(int.class) || dataType.isAssignableFrom(Integ try { Constructor< ? > constructor = dataType.getConstructor(String.class); - value = constructor.newInstance(entry.getValue()); + // Asterisk sometimes uses yes/no instead of True/False for boolean. java.lang.Boolean(String) doesn't handle this. + if (dataType.isAssignableFrom(Boolean.class)) { + value = constructor.newInstance(AstUtil.convertAsteriskBooleanStringToStandardBooleanString((String)entry.getValue())); + } + else value = constructor.newInstance(entry.getValue()); } catch (Exception e) { diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 5d2bd9137..8984bb584 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1032,6 +1032,8 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas // still no response or not all events received and timed out? if (responseEvents.getResponse() == null || !responseEvents.isComplete()) { + System.out.println("response:" +responseEvents.getResponse()); + System.out.println("complete:"+responseEvents.isComplete()); throw new EventTimeoutException( "Timeout waiting for response or response events to " + action.getAction() + (action.getActionId() == null ? "" : " (actionId: " + action.getActionId() + ")"), diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java index 0d69efd80..f1ca7814d 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java @@ -91,7 +91,7 @@ public void addEvent(ResponseEvent event) } /** - * Indicats if all events have been received. + * Indicates if all events have been received. * * @param complete true if all events have been received, * false otherwise. diff --git a/src/main/java/org/asteriskjava/util/AstUtil.java b/src/main/java/org/asteriskjava/util/AstUtil.java index 1aa348dc7..314721662 100644 --- a/src/main/java/org/asteriskjava/util/AstUtil.java +++ b/src/main/java/org/asteriskjava/util/AstUtil.java @@ -199,4 +199,32 @@ public static boolean isNull(Object s) return NULL_LITERALS.contains(((String) s).toLowerCase(Locale.US)); } + /** + * Converts a non-standard Asterisk boolean String value into something the Boolean class + * String constructor recognizes. + * + * Asterisk can return various strings that represent truth values. + * This method converts them into standard True/False, or null if null. + * + * @param value + * @return true if the String is "true" or "yes" (case insensitive). + * false if the String is "false" or "no" (case insensitive). + * @throws IllegalArgumentException if the String is null, or any other value not listed above. + */ + + public static String convertAsteriskBooleanStringToStandardBooleanString(String value) { + if (value == null) return null; + switch (value.toLowerCase()) + { + case "true": + case "yes": + return "True"; + case "false": + case "no": + return "False"; + default: + throw new IllegalArgumentException("value of:" + value + " was not recognized as a boolean"); + } + + } } From 6d3236949ab374f2f3023b48c7801057db0e17bb Mon Sep 17 00:00:00 2001 From: ssether Date: Fri, 16 Oct 2020 13:42:02 -0500 Subject: [PATCH 389/802] Removed debug code --- .../asteriskjava/manager/internal/ManagerConnectionImpl.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 8984bb584..5d2bd9137 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1032,8 +1032,6 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas // still no response or not all events received and timed out? if (responseEvents.getResponse() == null || !responseEvents.isComplete()) { - System.out.println("response:" +responseEvents.getResponse()); - System.out.println("complete:"+responseEvents.isComplete()); throw new EventTimeoutException( "Timeout waiting for response or response events to " + action.getAction() + (action.getActionId() == null ? "" : " (actionId: " + action.getActionId() + ")"), From 440886beb12bc5c4ad7a64a1b073f64db77c066c Mon Sep 17 00:00:00 2001 From: ssether Date: Fri, 16 Oct 2020 13:57:17 -0500 Subject: [PATCH 390/802] Fix indentation --- .../asteriskjava/manager/action/PJSipShowEndpointAction.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java index 186a27c12..221c682ed 100644 --- a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java @@ -48,10 +48,10 @@ public class PJSipShowEndpointAction extends AbstractManagerAction implements Ev * Serial version identifier. */ private static final long serialVersionUID = -5508189961610900058L; - private String endpoint; + private String endpoint; - public String getEndpoint() { + public String getEndpoint() { return endpoint; } From 7890da9310d193ab0caf61c4d92d17a4d1f32bd4 Mon Sep 17 00:00:00 2001 From: ssether Date: Fri, 16 Oct 2020 13:59:30 -0500 Subject: [PATCH 391/802] Spelling --- .../asteriskjava/manager/action/PJSipShowEndpointAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java index 221c682ed..60b6bedb4 100644 --- a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java @@ -27,7 +27,7 @@ * * Some events may appear multiple times. * - * When all events have been reported a EndpointDetailComplete is + * When all events have been reported an EndpointDetailComplete is * sent. *

    * Available since Asterisk 12 Permission required: write=system From 1bce306ecda92d29bd0355d6c15e5bac0e3be938 Mon Sep 17 00:00:00 2001 From: ssether Date: Fri, 16 Oct 2020 14:06:56 -0500 Subject: [PATCH 392/802] Indentation, grammar --- .../org/asteriskjava/manager/event/AuthDetail.java | 2 +- .../manager/event/ContactStatusDetail.java | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/AuthDetail.java b/src/main/java/org/asteriskjava/manager/event/AuthDetail.java index 298e89d69..fd0c174ad 100644 --- a/src/main/java/org/asteriskjava/manager/event/AuthDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/AuthDetail.java @@ -2,7 +2,7 @@ /** - * A AuthDetail event is triggered in response to a + * An AuthDetail event is triggered in response to a * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, * and contains information about a PJSIP Contact *

    diff --git a/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java index bf451bd1a..b57f35e5c 100644 --- a/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java @@ -26,8 +26,8 @@ public class ContactStatusDetail extends ResponseEvent { private String viaAddress; private String callID; private String status; - // roundtripusec when it contains a value is a long, but when it doesn't - // asterisk reports "N/A" + // roundtripusec when it contains a value is a long, but when it doesn't + // asterisk reports "N/A" private String roundtripUsec; private String endpointName; private String id; @@ -40,6 +40,10 @@ public class ContactStatusDetail extends ResponseEvent { public String getAor() { return aor; } + + public void setAor(String aor) { + this.aor = aor; + } public String getStatus() { return status; @@ -49,10 +53,6 @@ public void setStatus(String status) { this.status = status; } - public void setAor(String aor) { - this.aor = aor; - } - public String getUri() { return uri; } From f1a5232f2d7f28f2b60cdffe205b0f03c55c09ae Mon Sep 17 00:00:00 2001 From: ssether Date: Fri, 16 Oct 2020 14:17:58 -0500 Subject: [PATCH 393/802] Grammar --- .../org/asteriskjava/manager/event/EndpointDetailComplete.java | 2 +- .../org/asteriskjava/manager/event/EndpointListComplete.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java b/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java index 015f87ca4..43f0cf1f0 100644 --- a/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java +++ b/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java @@ -17,7 +17,7 @@ package org.asteriskjava.manager.event; /** - * A EndpointDetailComplete event is triggered after the details of an endpoint has been + * An EndpointDetailComplete event is triggered after the details of an endpoint has been * reported in response to a PJSIPShowEndpoint *

    * Available since Asterisk 12 diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java b/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java index a11532edf..5337b94e1 100644 --- a/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java +++ b/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java @@ -17,7 +17,7 @@ package org.asteriskjava.manager.event; /** - * A EndpointListComplete event is triggered after the details of all end points have been + * An EndpointListComplete event is triggered after the details of all end points have been * reported in response to a PJSIPShowEndpoints event. *

    * Available since Asterisk 12 From 5bd8100a49fc15d28eae21f0ded321c767e121f7 Mon Sep 17 00:00:00 2001 From: ssether Date: Fri, 16 Oct 2020 14:28:30 -0500 Subject: [PATCH 394/802] Fixed documentation on null. --- src/main/java/org/asteriskjava/util/AstUtil.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/util/AstUtil.java b/src/main/java/org/asteriskjava/util/AstUtil.java index 314721662..b2736e103 100644 --- a/src/main/java/org/asteriskjava/util/AstUtil.java +++ b/src/main/java/org/asteriskjava/util/AstUtil.java @@ -209,7 +209,8 @@ public static boolean isNull(Object s) * @param value * @return true if the String is "true" or "yes" (case insensitive). * false if the String is "false" or "no" (case insensitive). - * @throws IllegalArgumentException if the String is null, or any other value not listed above. + * null if the String is null. + * @throws IllegalArgumentException if any other value not listed above. */ public static String convertAsteriskBooleanStringToStandardBooleanString(String value) { From 3e25e52c80b3814f1711fda7e5894ea7811d3e32 Mon Sep 17 00:00:00 2001 From: ssether Date: Fri, 16 Oct 2020 14:35:14 -0500 Subject: [PATCH 395/802] Remove extra spacing --- .../manager/event/TransportDetail.java | 60 +------------------ 1 file changed, 2 insertions(+), 58 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/TransportDetail.java b/src/main/java/org/asteriskjava/manager/event/TransportDetail.java index 9153484c9..e54670630 100644 --- a/src/main/java/org/asteriskjava/manager/event/TransportDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/TransportDetail.java @@ -15,8 +15,8 @@ public class TransportDetail extends ResponseEvent { /** - * - */ + * Serial version identifier. + */ private static final long serialVersionUID = 8558130768089350575L; private String Event; private String objectType; @@ -52,263 +52,207 @@ public TransportDetail(Object source) { super(source); } - public String getEvent() { return Event; } - public void setEvent(String event) { Event = event; } - public String getObjectType() { return objectType; } - public void setObjectType(String objectType) { this.objectType = objectType; } - public String getPbjectName() { return pbjectName; } - public void setPbjectName(String pbjectName) { this.pbjectName = pbjectName; } - public String getProtocol() { return protocol; } - public void setProtocol(String protocol) { this.protocol = protocol; } - public String getBind() { return bind; } - public void setBind(String bind) { this.bind = bind; } - public int getAsycOperations() { return asycOperations; } - public void setAsycOperations(int asycOperations) { this.asycOperations = asycOperations; } - public String getCaListFile() { return caListFile; } - public void setCaListFile(String caListFile) { this.caListFile = caListFile; } - public String getCaListPath() { return caListPath; } - public void setCaListPath(String caListPath) { this.caListPath = caListPath; } - public String getCertFile() { return certFile; } - public void setCertFile(String certFile) { this.certFile = certFile; } - public String getPrivKeyFile() { return privKeyFile; } - public void setPrivKeyFile(String privKeyFile) { this.privKeyFile = privKeyFile; } - public String getPassword() { return password; } - public void setPassword(String password) { this.password = password; } - public String getExternalSignalingAddress() { return externalSignalingAddress; } - public void setExternalSignalingAddress(String externalSignalingAddress) { this.externalSignalingAddress = externalSignalingAddress; } - public int getExternalSignalingPort() { return externalSignalingPort; } - public void setExternalSignalingPort(int externalSignalingPort) { this.externalSignalingPort = externalSignalingPort; } - public String getExternalMediaAddress() { return externalMediaAddress; } - public void setExternalMediaAddress(String externalMediaAddress) { this.externalMediaAddress = externalMediaAddress; } - public String getDomain() { return domain; } - public void setDomain(String domain) { this.domain = domain; } - public String getVerifyServer() { return verifyServer; } - public void setVerifyServer(String verifyServer) { this.verifyServer = verifyServer; } - public String getVerifyClient() { return verifyClient; } - public void setVerifyClient(String verifyClient) { this.verifyClient = verifyClient; } - public Boolean getRequireClientCert() { return requireClientCert; } - public void setRequireClientCert(Boolean requireClientCert) { this.requireClientCert = requireClientCert; } - public String getMethod() { return method; } - public void setMethod(String method) { this.method = method; } - public String getCipher() { return cipher; } - public void setCipher(String cipher) { this.cipher = cipher; } - public String getLocalNet() { return localNet; } - public void setLocalNet(String localNet) { this.localNet = localNet; } - public String getTos() { return tos; } - public void setTos(String tos) { this.tos = tos; } - public int getCos() { return cos; } - public void setCos(int cos) { this.cos = cos; } - public int getWebsocketWriteTimeout() { return websocketWriteTimeout; } - public void setWebsocketWriteTimeout(int websocketWriteTimeout) { this.websocketWriteTimeout = websocketWriteTimeout; } - public String getEndpointName() { return endpointName; } - public void setEndpointName(String endpointName) { this.endpointName = endpointName; } - public static long getSerialversionuid() { return serialVersionUID; } - - - - - } From 2c1f2ed7d310613f2a24fe7dbf3c3d7f3154c1b9 Mon Sep 17 00:00:00 2001 From: ssether Date: Fri, 16 Oct 2020 14:35:49 -0500 Subject: [PATCH 396/802] Remove unused import --- .../java/org/asteriskjava/manager/event/TransportDetail.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/event/TransportDetail.java b/src/main/java/org/asteriskjava/manager/event/TransportDetail.java index e54670630..2db7b20d6 100644 --- a/src/main/java/org/asteriskjava/manager/event/TransportDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/TransportDetail.java @@ -1,6 +1,5 @@ package org.asteriskjava.manager.event; -import org.asteriskjava.util.AstUtil; /** * A TransportDetail event is triggered in response to a From 336680152dfd22a2f49f826f91ea73380ed8baa8 Mon Sep 17 00:00:00 2001 From: ssether Date: Thu, 8 Oct 2020 16:32:28 -0500 Subject: [PATCH 397/802] Adding PJSIPShowEndpoint --- .../manager/AbstractManagerEventListener.java | 16 + .../action/PJSipShowContactsAction.java | 12 +- .../action/PJSipShowEndpointAction.java | 80 ++ .../action/PJSipShowEndpointsAction.java | 4 +- .../asteriskjava/manager/event/AorDetail.java | 157 +++ .../manager/event/AuthDetail.java | 121 ++ .../manager/event/ContactStatusDetail.java | 171 +++ .../manager/event/EndpointDetail.java | 1148 +++++++++++++++++ .../manager/event/EndpointDetailComplete.java | 87 ++ .../manager/event/EndpointListComplete.java | 18 +- .../manager/event/TransportDetail.java | 257 ++++ .../manager/internal/AbstractBuilder.java | 6 +- .../manager/internal/ResponseEventsImpl.java | 2 +- .../java/org/asteriskjava/util/AstUtil.java | 29 + 14 files changed, 2088 insertions(+), 20 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java create mode 100644 src/main/java/org/asteriskjava/manager/event/AorDetail.java create mode 100644 src/main/java/org/asteriskjava/manager/event/AuthDetail.java create mode 100644 src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java create mode 100644 src/main/java/org/asteriskjava/manager/event/EndpointDetail.java create mode 100644 src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java create mode 100644 src/main/java/org/asteriskjava/manager/event/TransportDetail.java diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 79bc4190a..4a28bb58e 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -764,7 +764,23 @@ public void handleEvent(UnpausedEvent event) public void handleEvent(VarSetEvent event) { } + + public void handleEvent(EndpointDetail event) + { + } + + public void handleEvent(AorDetail event) + { + } + public void handleEvent(ContactStatusDetail event) + { + } + + public void handleEvent(EndpointDetailComplete event) + { + } + /** * Dispatches to the appropriate handleEvent(...) method. * diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java index c4948961c..b902e2825 100644 --- a/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java @@ -20,18 +20,18 @@ import org.asteriskjava.manager.event.ResponseEvent; /** - * Retrieves a list of all defined SIP peers. + * Retrieves a list of all defined PJSIP contacts. *

    - * For each peer that is found a PeerEntryEvent is sent by Asterisk containing - * the details. When all peers have been reported a PeerlistCompleteEvent is + * For each contact that is found a ContactList is sent by Asterisk containing + * the details. When all contact have been reported a ContactListComplete is * sent. *

    - * Available since Asterisk 1.2 Permission required: write=system + * Available since Asterisk 16 Permission required: write=system * * @author srt * @version $Id$ - * @see org.asteriskjava.manager.event.PeerEntryEvent - * @see org.asteriskjava.manager.event.PeerlistCompleteEvent + * @see org.asteriskjava.manager.event.ContactList + * @see org.asteriskjava.manager.event.ContactListComplete * @since 0.2 */ public class PJSipShowContactsAction extends AbstractManagerAction implements EventGeneratingAction diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java new file mode 100644 index 000000000..60b6bedb4 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java @@ -0,0 +1,80 @@ +/* + * 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.manager.action; + +import org.asteriskjava.manager.event.EndpointDetailComplete; +import org.asteriskjava.manager.event.ResponseEvent; + +/** + * Retrieves details about a given endpoint. + *

    + * For the given endpoint, the call will return several events, including + * EndpointDetail, AorDetail, AuthDetail, TransportDetail, ContactStatusDetail,and IdentifyDetail. + * + * Some events may appear multiple times. + * + * When all events have been reported an EndpointDetailComplete is + * sent. + *

    + * Available since Asterisk 12 Permission required: write=system + * + * @author Steve Sether + * @version $Id$ + * @see org.asteriskjava.manager.event.ContactStatusDetail + * @see org.asteriskjava.manager.event.AorDetail + * @see org.asteriskjava.manager.event.EndpointDetail + * @see org.asteriskjava.manager.event.TransportDetail + * @see org.asteriskjava.manager.event.AuthDetail + * @see org.asteriskjava.manager.event.EndpointDetailComplete + * @since 12 + */ +public class PJSipShowEndpointAction extends AbstractManagerAction implements EventGeneratingAction +{ + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -5508189961610900058L; + private String endpoint; + + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + /** + * Creates a new SipPeersAction. + */ + public PJSipShowEndpointAction() + { + + } + + @Override + public String getAction() + { + return "PJSIPShowEndpoint"; + } + + public Class< ? extends ResponseEvent> getActionCompleteEventClass() + { + return EndpointDetailComplete.class; + } +} diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java index f33aa8eaf..d1acaa3f5 100644 --- a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java @@ -26,13 +26,13 @@ * the details. When all peers have been reported a PeerlistCompleteEvent is * sent. *

    - * Available since Asterisk 1.2 Permission required: write=system + * Available since Asterisk 12 Permission required: write=system * * @author srt * @version $Id$ * @see org.asteriskjava.manager.event.PeerEntryEvent * @see org.asteriskjava.manager.event.PeerlistCompleteEvent - * @since 0.2 + * @since 12 */ public class PJSipShowEndpointsAction extends AbstractManagerAction implements EventGeneratingAction { diff --git a/src/main/java/org/asteriskjava/manager/event/AorDetail.java b/src/main/java/org/asteriskjava/manager/event/AorDetail.java new file mode 100644 index 000000000..e6ebac3d5 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/AorDetail.java @@ -0,0 +1,157 @@ +package org.asteriskjava.manager.event; + +import org.asteriskjava.util.AstUtil; + +/** + * A ContactStatusDetail event is triggered in response to a + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, + * and contains information about a PJSIP Contact + *

    + * + * @author Steve Sether + * @version $Id$ + * @since 12 + */ + +public class AorDetail extends ResponseEvent { + + /** + * Serial version identifier. + */ + private static final long serialVersionUID = 2634171854313358591L; + public AorDetail(Object source) { + super(source); + } + + + private String objectType; + private String objectName; + private int minimumExpiration; + private int defaultExpiration; + private Float qualifyTimeout; + private String mailboxes; + private Boolean supportPath; + private String voicemailExtension; + private int maxContacts; + private Boolean authenticateQualify; + private String contacts; + private int maximumExpiration; + private int qualifyFrequency; + private Boolean removeExisting; + private String outboundProxy; + private int totalContacts; + private int contactsRegistered; + private String endpointName; + public String getObjectType() { + return objectType; + } + public void setObjectType(String objectType) { + this.objectType = objectType; + } + public String getObjectName() { + return objectName; + } + public void setObjectName(String objectName) { + this.objectName = objectName; + } + public int getMinimumExpiration() { + return minimumExpiration; + } + public void setMinimumExpiration(int minimumExpiration) { + this.minimumExpiration = minimumExpiration; + } + public int getDefaultExpiration() { + return defaultExpiration; + } + public void setDefaultExpiration(int defaultExpiration) { + this.defaultExpiration = defaultExpiration; + } + public Float getQualifyTimeout() { + return qualifyTimeout; + } + public void setQualifyTimeout(Float qualifyTimeout) { + this.qualifyTimeout = qualifyTimeout; + } + public String getMailboxes() { + return mailboxes; + } + public void setMailboxes(String mailboxes) { + this.mailboxes = mailboxes; + } + public Boolean isSupportPath() { + return supportPath; + } + public void setSupportPath(Boolean supportPath) { + this.supportPath = supportPath; + } + public String getVoicemailExtension() { + return voicemailExtension; + } + public void setVoicemailExtension(String voicemailExtension) { + this.voicemailExtension = voicemailExtension; + } + public int getMaxContacts() { + return maxContacts; + } + public void setMaxContacts(int maxContacts) { + this.maxContacts = maxContacts; + } + public Boolean isAuthenticateQualify() { + return authenticateQualify; + } + public void setAuthenticateQualify(Boolean authenticateQualify) { + this.authenticateQualify = authenticateQualify; + } + public String getContacts() { + return contacts; + } + public void setContacts(String contacts) { + this.contacts = contacts; + } + public int getMaximumExpiration() { + return maximumExpiration; + } + public void setMaximumExpiration(int maximumExpiration) { + this.maximumExpiration = maximumExpiration; + } + public int getQualifyFrequency() { + return qualifyFrequency; + } + public void setQualifyFrequency(int qualifyFrequency) { + this.qualifyFrequency = qualifyFrequency; + } + public Boolean isRemoveExisting() { + return removeExisting; + } + public void setRemoveExisting(Boolean removeExisting) { + this.removeExisting = removeExisting; + } + public String getOutboundProxy() { + return outboundProxy; + } + public void setOutboundProxy(String outboundProxy) { + this.outboundProxy = outboundProxy; + } + public int getTotalContacts() { + return totalContacts; + } + public void setTotalContacts(int totalContacts) { + this.totalContacts = totalContacts; + } + public int getContactsRegistered() { + return contactsRegistered; + } + public void setContactsRegistered(int contactsRegistered) { + this.contactsRegistered = contactsRegistered; + } + public String getEndpointName() { + return endpointName; + } + public void setEndpointName(String endpointName) { + this.endpointName = endpointName; + } + + + + +} diff --git a/src/main/java/org/asteriskjava/manager/event/AuthDetail.java b/src/main/java/org/asteriskjava/manager/event/AuthDetail.java new file mode 100644 index 000000000..fd0c174ad --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/AuthDetail.java @@ -0,0 +1,121 @@ +package org.asteriskjava.manager.event; + + +/** + * An AuthDetail event is triggered in response to a + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, + * and contains information about a PJSIP Contact + *

    + * + * @author Steve Sether + * @version $Id$ + * @since 12 + */ + +public class AuthDetail extends ResponseEvent { + + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -4998727723768836212L; + + private String event; + private String objectType; + private String objectName; + private String username; + private String password; + private String md5Cred; + private String realm; + private int nonceLifetime; + private String authType; + private String EndpointName; + + public AuthDetail(Object source) { + super(source); + } + + public String getEvent() { + return event; + } + + public void setEvent(String event) { + this.event = event; + } + + public String getObjectType() { + return objectType; + } + + public void setObjectType(String objectType) { + this.objectType = objectType; + } + + public String getObjectName() { + return objectName; + } + + public void setObjectName(String objectName) { + this.objectName = objectName; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getMd5Cred() { + return md5Cred; + } + + public void setMd5Cred(String md5Cred) { + this.md5Cred = md5Cred; + } + + public String getRealm() { + return realm; + } + + public void setRealm(String realm) { + this.realm = realm; + } + + public int getNonceLifetime() { + return nonceLifetime; + } + + public void setNonceLifetime(int nonceLifetime) { + this.nonceLifetime = nonceLifetime; + } + + public String getAuthType() { + return authType; + } + + public void setAuthType(String authType) { + this.authType = authType; + } + + public String getEndpointName() { + return EndpointName; + } + + public void setEndpointName(String endpointName) { + EndpointName = endpointName; + } + + + + + +} diff --git a/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java new file mode 100644 index 000000000..b57f35e5c --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java @@ -0,0 +1,171 @@ +package org.asteriskjava.manager.event; + +import org.asteriskjava.util.AstUtil; + +/** + * A ContactStatusDetail event is triggered in response to a + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, + * and contains information about a PJSIP Contact + *

    + * + * @author Steve Sether + * @version $Id$ + * @since 12 + */ + +public class ContactStatusDetail extends ResponseEvent { + + /** + * Serial version identifier. + */ + private static final long serialVersionUID = 987290433601178780L; + private String aor; + private String uri; + private String userAgent; + private long regExpire; + private String viaAddress; + private String callID; + private String status; + // roundtripusec when it contains a value is a long, but when it doesn't + // asterisk reports "N/A" + private String roundtripUsec; + private String endpointName; + private String id; + private Boolean authenticateQualify; + private String outboundProxy; + private String path; + private int qualifyFrequency; + private Float qualifyTimeout; + + public String getAor() { + return aor; + } + + public void setAor(String aor) { + this.aor = aor; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getUri() { + return uri; + } + + public void setUri(String uri) { + this.uri = uri; + } + + public String getUserAgent() { + return userAgent; + } + + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + + public long getRegExpire() { + return regExpire; + } + + public void setRegExpire(long regExpire) { + this.regExpire = regExpire; + } + + public String getViaAddress() { + return viaAddress; + } + + public void setViaAddress(String viaAddress) { + this.viaAddress = viaAddress; + } + + public String getCallID() { + return callID; + } + + public void setCallID(String callID) { + this.callID = callID; + } + + public String getEndpointName() { + return endpointName; + } + + public void setEndpointName(String endpointName) { + this.endpointName = endpointName; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Boolean isAuthenticateQualify() { + return authenticateQualify; + } + + public void setAuthenticateQualify(Boolean authenticateQualify) { + this.authenticateQualify = authenticateQualify; + } + + public String getOutboundProxy() { + return outboundProxy; + } + + public void setOutboundProxy(String outboundProxy) { + this.outboundProxy = outboundProxy; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public int getQualifyFrequency() { + return qualifyFrequency; + } + + public void setQualifyFrequency(int qualifyFrequency) { + this.qualifyFrequency = qualifyFrequency; + } + + public Float getQualifyTimeout() { + return qualifyTimeout; + } + + public void setQualifyTimeout(Float qualifyTimeout) { + this.qualifyTimeout = qualifyTimeout; + } + + public void setQualifyTimeout(String qualifyTimeout) { + this.qualifyTimeout = Float.parseFloat(qualifyTimeout); + } + + public ContactStatusDetail(Object source) { + super(source); + } + + public String getRoundtripUsec() { + return roundtripUsec; + } + + public void setRoundtripUsec(String roundtripUsec) { + this.roundtripUsec = roundtripUsec; + } + + + + +} diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java b/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java new file mode 100644 index 000000000..b83d1a07f --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java @@ -0,0 +1,1148 @@ +package org.asteriskjava.manager.event; + +import org.asteriskjava.util.AstUtil; + +/** + * A EndpointDetail event is triggered in response to a + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, + * and contains information about a PJSIP endpoint + *

    + * + * @author Steve Sether + * @version $Id$ + * @since 12 + */ + +public class EndpointDetail extends ResponseEvent { + + /** + * Serial version identifier. + */ + private static final long serialVersionUID = 77481930059189731L; + private Integer listItems; + private String eventList; + + public Integer getListItems() { + return listItems; + } + + public void setListItems(Integer listItems) { + this.listItems = listItems; + } + + public String getEventList() { + return eventList; + } + + public void setEventList(String eventList) { + this.eventList = eventList; + } + + private String objectName; + private String objectType; + private Boolean rpidImmediate; + private Boolean webrtc; + private Boolean ignorel83WithoutSdp; + private int deviceStateBusyAt; + private int t38UdptlMaxdatagram; + private int dtlsRekey; + private String namedPickupGroup; + private String directMediaMethod; + private Boolean sendRpid; + private String pickupGroup; + private String sdpSession; + private String dtlsVerify; + private String messageContext; + private String mailboxes; + private String recordOnFeature; + private String dtlsPrivateKey; + private String dtlsFingerprint; + private String fromDomain; + private int timersSessExpires; + private String namedCallGroup; + private String dtlsCipher; + private Boolean mediaEncryptionOptimistic; + private Boolean suppressQ850ReasonHeaders; + private String aors; + private String identifyBy; + private String calleridPrivacy; + private String mwiSubscribeReplacesUnsolicited; + private String cosAudio; + private Boolean followEarlyMediaFork; + private String context; + private Boolean rtpSymmetric; + private String transport; + private String mohSuggest; + private Boolean t38Udptl; + private Boolean faxDetect; + private String tosVideo; + private Boolean srtpTag32; + private Boolean referBlindProgress; + private int maxAudioStreams; + private Boolean bundle; + private Boolean useAvpf; + private String callGroup; + private Boolean sendConnectedLine; + private int faxDetectTimeout; + private String sdpOwner; + private Boolean forceRport; + private String calleridTag; + private int rtpTimeoutHold; + private Boolean usePtime; + private String mediaAddress; + private String voicemailExtension; + private int rtpTimeout; + private String setVar; + private String contactAcl; + private Boolean preferredCodecOnly; + private Boolean forceAvp; + private String recordOffFeature; + private String fromUser; + private Boolean sendDiversion; + private Boolean t38UdptlIpv6; + private String toneZone; + private String language; + private Boolean allowSubscribe; + private Boolean rtpIpv6; + private String callerid; + private Boolean mohPassthrough; + private String cosVideo; + private String dtlsAutoGenerateCert; + private Boolean asymmetricRtpCodec; + private Boolean iceSupport; + private Boolean aggregateMwi; + private Boolean oneTouchRecording; + private String mwiFromUser; + private String accountcode; + private String allow; + private Boolean rewriteContact; + private Boolean userEqPhone; + private String rtpEngine; + private String subscribeContext; + private Boolean notifyEarlyInuseRinging; + private String incomingMwiMailbox; + private String auth; + private String directMediaGlareMitigation; + private Boolean trustIdInbound; + private Boolean bindRtpToMediaAddress; + private Boolean disableDirectMediaOnNat; + private Boolean mediaEncryption; + private Boolean mediaUseReceivedTransport; + private Boolean allowOverlap; + private String dtmfMode; + private String outboundAuth; + private String tosAudio; + private String dtlsCertFile; + private String dtlsCaPath; + private String dtlsSetup; + private String connectedLineMethod; + private Boolean g726NonStandard; + private String _100rel; + private String timers; + private Boolean directMedia; + private String acl; + private int timersMinSe; + private Boolean trustIdOutbound; + private int subMinExpiry; + private Boolean rtcpMux; + private int maxVideoStreams; + private Boolean acceptMultipleSdpAnswers; + private Boolean trustConnectedLine; + private Boolean sendPai; + private int rtpKeepalive; + private String t38UdptlEc; + private Boolean t38UdptlNat; + private Boolean allowTransfer; + private String dtlsCaFile; + private String outboundProxy; + private Boolean inbandProgress; + private String deviceState; + private String activeChannels; + private Boolean ignore183withoutsdp; + + public int getMaxVideoStreams() { + return maxVideoStreams; + } + + public void setMaxVideoStreams(int maxVideoStreams) { + this.maxVideoStreams = maxVideoStreams; + } + + public String getObjectName() { + return objectName; + } + + public void setObjectName(String objectName) { + this.objectName = objectName; + } + + public String getObjectType() { + return objectType; + } + + public void setObjectType(String objectType) { + this.objectType = objectType; + } + + public Boolean isRpidImmediate() { + return rpidImmediate; + } + + public void setRpidImmediate(Boolean rpidImmediate) { + this.rpidImmediate = rpidImmediate; + } + + public Boolean isWebrtc() { + return webrtc; + } + + public void setWebrtc(Boolean webrtc) { + this.webrtc = webrtc; + } + + public Boolean isIgnorel83WithoutSdp() { + return ignorel83WithoutSdp; + } + + public void setIgnorel83WithoutSdp(Boolean ignorel83WithoutSdp) { + this.ignorel83WithoutSdp = ignorel83WithoutSdp; + } + + public int getDeviceStateBusyAt() { + return deviceStateBusyAt; + } + + public void setDeviceStateBusyAt(int deviceStateBusyAt) { + this.deviceStateBusyAt = deviceStateBusyAt; + } + + public int getT38UdptlMaxdatagram() { + return t38UdptlMaxdatagram; + } + + public void setT38UdptlMaxdatagram(int t38UdptlMaxdatagram) { + this.t38UdptlMaxdatagram = t38UdptlMaxdatagram; + } + + public int getDtlsRekey() { + return dtlsRekey; + } + + public void setDtlsRekey(int dtlsRekey) { + this.dtlsRekey = dtlsRekey; + } + + public String getNamedPickupGroup() { + return namedPickupGroup; + } + + public void setNamedPickupGroup(String namedPickupGroup) { + this.namedPickupGroup = namedPickupGroup; + } + + public String getDirectMediaMethod() { + return directMediaMethod; + } + + public void setDirectMediaMethod(String directMediaMethod) { + this.directMediaMethod = directMediaMethod; + } + + public Boolean isSendRpid() { + return sendRpid; + } + + public void setSendRpid(Boolean sendRpid) { + this.sendRpid = sendRpid; + } + + public String getPickupGroup() { + return pickupGroup; + } + + public void setPickupGroup(String pickupGroup) { + this.pickupGroup = pickupGroup; + } + + public String getSdpSession() { + return sdpSession; + } + + public void setSdpSession(String sdpSession) { + this.sdpSession = sdpSession; + } + + public String getDtlsVerify() { + return dtlsVerify; + } + + public void setDtlsVerify(String dtlsVerify) { + this.dtlsVerify = dtlsVerify; + } + + public String getMessageContext() { + return messageContext; + } + + public void setMessageContext(String messageContext) { + this.messageContext = messageContext; + } + + public String getMailboxes() { + return mailboxes; + } + + public void setMailboxes(String mailboxes) { + this.mailboxes = mailboxes; + } + + public String getRecordOnFeature() { + return recordOnFeature; + } + + public void setRecordOnFeature(String recordOnFeature) { + this.recordOnFeature = recordOnFeature; + } + + public String getDtlsPrivateKey() { + return dtlsPrivateKey; + } + + public void setDtlsPrivateKey(String dtlsPrivateKey) { + this.dtlsPrivateKey = dtlsPrivateKey; + } + + public String getDtlsFingerprint() { + return dtlsFingerprint; + } + + public void setDtlsFingerprint(String dtlsFingerprint) { + this.dtlsFingerprint = dtlsFingerprint; + } + + public String getFromDomain() { + return fromDomain; + } + + public void setFromDomain(String fromDomain) { + this.fromDomain = fromDomain; + } + + public int getTimersSessExpires() { + return timersSessExpires; + } + + public void setTimersSessExpires(int timersSessExpires) { + this.timersSessExpires = timersSessExpires; + } + + public String getNamedCallGroup() { + return namedCallGroup; + } + + public void setNamedCallGroup(String namedCallGroup) { + this.namedCallGroup = namedCallGroup; + } + + public String getDtlsCipher() { + return dtlsCipher; + } + + public void setDtlsCipher(String dtlsCipher) { + this.dtlsCipher = dtlsCipher; + } + + public Boolean isMediaEncryptionOptimistic() { + return mediaEncryptionOptimistic; + } + + public void setMediaEncryptionOptimistic(Boolean mediaEncryptionOptimistic) { + this.mediaEncryptionOptimistic = mediaEncryptionOptimistic; + } + + public Boolean isSuppressQ850ReasonHeaders() { + return suppressQ850ReasonHeaders; + } + + public void setSuppressQ850ReasonHeaders(Boolean suppressQ850ReasonHeaders) { + this.suppressQ850ReasonHeaders = suppressQ850ReasonHeaders; + } + + public String getAors() { + return aors; + } + + public void setAors(String aors) { + this.aors = aors; + } + + public String getIdentifyBy() { + return identifyBy; + } + + public void setIdentifyBy(String identifyBy) { + this.identifyBy = identifyBy; + } + + public String getCalleridPrivacy() { + return calleridPrivacy; + } + + public void setCalleridPrivacy(String calleridPrivacy) { + this.calleridPrivacy = calleridPrivacy; + } + + public String getMwiSubscribeReplacesUnsolicited() { + return mwiSubscribeReplacesUnsolicited; + } + + public void setMwiSubscribeReplacesUnsolicited(String mwiSubscribeReplacesUnsolicited) { + this.mwiSubscribeReplacesUnsolicited = mwiSubscribeReplacesUnsolicited; + } + + public Boolean isFollowEarlyMediaFork() { + return followEarlyMediaFork; + } + + public void setFollowEarlyMediaFork(Boolean followEarlyMediaFork) { + this.followEarlyMediaFork = followEarlyMediaFork; + } + + public String getContext() { + return context; + } + + public void setContext(String context) { + this.context = context; + } + + public Boolean isRtpSymmetric() { + return rtpSymmetric; + } + + public void setRtpSymmetric(Boolean rtpSymmetric) { + this.rtpSymmetric = rtpSymmetric; + } + + public String getTransport() { + return transport; + } + + public void setTransport(String transport) { + this.transport = transport; + } + + public String getMohSuggest() { + return mohSuggest; + } + + public void setMohSuggest(String mohSuggest) { + this.mohSuggest = mohSuggest; + } + + public Boolean isT38Udptl() { + return t38Udptl; + } + + public void setT38Udptl(Boolean t38Udptl) { + this.t38Udptl = t38Udptl; + } + + public Boolean isFaxDetect() { + return faxDetect; + } + + public void setFaxDetect(Boolean faxDetect) { + this.faxDetect = faxDetect; + } + + public Boolean getSrtpTag32() { + return srtpTag32; + } + + public void setSrtpTag32(Boolean srtpTag32) { + this.srtpTag32 = srtpTag32; + } + + public Boolean isReferBlindProgress() { + return referBlindProgress; + } + + public void setReferBlindProgress(Boolean referBlindProgress) { + this.referBlindProgress = referBlindProgress; + } + + public int getMaxAudioStreams() { + return maxAudioStreams; + } + + public void setMaxAudioStreams(int maxAudioStreams) { + this.maxAudioStreams = maxAudioStreams; + } + + public Boolean isBundle() { + return bundle; + } + + public void setBundle(Boolean bundle) { + this.bundle = bundle; + } + + + public Boolean isUseAvpf() { + return useAvpf; + } + + public void setUseAvpf(Boolean useAvpf) { + this.useAvpf = useAvpf; + } + + + public String getCallGroup() { + return callGroup; + } + + public void setCallGroup(String callGroup) { + this.callGroup = callGroup; + } + + public Boolean isSendConnectedLine() { + return sendConnectedLine; + } + + public void setSendConnectedLine(Boolean sendConnectedLine) { + this.sendConnectedLine = sendConnectedLine; + } + + + public int getFaxDetectTimeout() { + return faxDetectTimeout; + } + + public void setFaxDetectTimeout(int faxDetectTimeout) { + this.faxDetectTimeout = faxDetectTimeout; + } + + public String getSdpOwner() { + return sdpOwner; + } + + public void setSdpOwner(String sdpOwner) { + this.sdpOwner = sdpOwner; + } + + public Boolean isForceRport() { + return forceRport; + } + + public void setForceRport(Boolean forceRport) { + this.forceRport = forceRport; + } + + + public String getCalleridTag() { + return calleridTag; + } + + public void setCalleridTag(String calleridTag) { + this.calleridTag = calleridTag; + } + + public int getRtpTimeoutHold() { + return rtpTimeoutHold; + } + + public void setRtpTimeoutHold(int rtpTimeoutHold) { + this.rtpTimeoutHold = rtpTimeoutHold; + } + + public Boolean isUsePtime() { + return usePtime; + } + + public void setUsePtime(Boolean usePtime) { + this.usePtime = usePtime; + } + + + public String getMediaAddress() { + return mediaAddress; + } + + public void setMediaAddress(String mediaAddress) { + this.mediaAddress = mediaAddress; + } + + public String getVoicemailExtension() { + return voicemailExtension; + } + + public void setVoicemailExtension(String voicemailExtension) { + this.voicemailExtension = voicemailExtension; + } + + public int getRtpTimeout() { + return rtpTimeout; + } + + public void setRtpTimeout(int rtpTimeout) { + this.rtpTimeout = rtpTimeout; + } + + public String getSetVar() { + return setVar; + } + + public void setSetVar(String setVar) { + this.setVar = setVar; + } + + public String getContactAcl() { + return contactAcl; + } + + public void setContactAcl(String contactAcl) { + this.contactAcl = contactAcl; + } + + public Boolean isPreferredCodecOnly() { + return preferredCodecOnly; + } + + public void setPreferredCodecOnly(Boolean preferredCodecOnly) { + this.preferredCodecOnly = preferredCodecOnly; + } + + public Boolean isForceAvp() { + return forceAvp; + } + + public void setForceAvp(Boolean forceAvp) { + this.forceAvp = forceAvp; + } + + + public String getRecordOffFeature() { + return recordOffFeature; + } + + public void setRecordOffFeature(String recordOffFeature) { + this.recordOffFeature = recordOffFeature; + } + + public String getFromUser() { + return fromUser; + } + + public void setFromUser(String fromUser) { + this.fromUser = fromUser; + } + + public Boolean isSendDiversion() { + return sendDiversion; + } + + public void setSendDiversion(Boolean sendDiversion) { + this.sendDiversion = sendDiversion; + } + + + public Boolean isT38UdptlIpv6() { + return t38UdptlIpv6; + } + + public void setT38UdptlIpv6(Boolean t38UdptlIpv6) { + this.t38UdptlIpv6 = t38UdptlIpv6; + } + + + public String getToneZone() { + return toneZone; + } + + public void setToneZone(String toneZone) { + this.toneZone = toneZone; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public Boolean isAllowSubscribe() { + return allowSubscribe; + } + + public void setAllowSubscribe(Boolean allowSubscribe) { + this.allowSubscribe = allowSubscribe; + } + + public Boolean isRtpIpv6() { + return rtpIpv6; + } + + public void setRtpIpv6(Boolean rtpIpv6) { + this.rtpIpv6 = rtpIpv6; + } + + + public String getCallerid() { + return callerid; + } + + public void setCallerid(String callerid) { + this.callerid = callerid; + } + + public Boolean isMohPassthrough() { + return mohPassthrough; + } + + public void setMohPassthrough(Boolean mohPassthrough) { + this.mohPassthrough = mohPassthrough; + } + + public String getCosAudio() { + return cosAudio; + } + + public void setCosAudio(String cosAudio) { + this.cosAudio = cosAudio; + } + + public String getCosVideo() { + return cosVideo; + } + + public void setCosVideo(String cosVideo) { + this.cosVideo = cosVideo; + } + + public String getDtlsAutoGenerateCert() { + return dtlsAutoGenerateCert; + } + + public void setDtlsAutoGenerateCert(String dtlsAutoGenerateCert) { + this.dtlsAutoGenerateCert = dtlsAutoGenerateCert; + } + + public Boolean isAsymmetricRtpCodec() { + return asymmetricRtpCodec; + } + + public void setAsymmetricRtpCodec(Boolean asymmetricRtpCodec) { + this.asymmetricRtpCodec = asymmetricRtpCodec; + } + + + public Boolean isIceSupport() { + return iceSupport; + } + + public void setIceSupport(Boolean iceSupport) { + this.iceSupport = iceSupport; + } + + + public Boolean isAggregateMwi() { + return aggregateMwi; + } + + public void setAggregateMwi(Boolean aggregateMwi) { + this.aggregateMwi = aggregateMwi; + } + + + public Boolean isOneTouchRecording() { + return oneTouchRecording; + } + + public void setOneTouchRecording(Boolean oneTouchRecording) { + this.oneTouchRecording = oneTouchRecording; + } + + + public String getMwiFromUser() { + return mwiFromUser; + } + + public void setMwiFromUser(String mwiFromUser) { + this.mwiFromUser = mwiFromUser; + } + + public String getAccountcode() { + return accountcode; + } + + public void setAccountcode(String accountcode) { + this.accountcode = accountcode; + } + + public String getAllow() { + return allow; + } + + public void setAllow(String allow) { + this.allow = allow; + } + + public Boolean isRewriteContact() { + return rewriteContact; + } + + public void setRewriteContact(Boolean rewriteContact) { + this.rewriteContact = rewriteContact; + } + + public Boolean isUserEqPhone() { + return userEqPhone; + } + + public void setUserEqPhone(Boolean userEqPhone) { + this.userEqPhone = userEqPhone; + } + + public String getRtpEngine() { + return rtpEngine; + } + + public void setRtpEngine(String rtpEngine) { + this.rtpEngine = rtpEngine; + } + + public String getSubscribeContext() { + return subscribeContext; + } + + public void setSubscribeContext(String subscribeContext) { + this.subscribeContext = subscribeContext; + } + + public Boolean isNotifyEarlyInuseRinging() { + return notifyEarlyInuseRinging; + } + + public void setNotifyEarlyInuseRinging(Boolean notifyEarlyInuseRinging) { + this.notifyEarlyInuseRinging = notifyEarlyInuseRinging; + } + + public String getIncomingMwiMailbox() { + return incomingMwiMailbox; + } + + public void setIncomingMwiMailbox(String incomingMwiMailbox) { + this.incomingMwiMailbox = incomingMwiMailbox; + } + + public String getAuth() { + return auth; + } + + public void setAuth(String auth) { + this.auth = auth; + } + + public String getDirectMediaGlareMitigation() { + return directMediaGlareMitigation; + } + + public void setDirectMediaGlareMitigation(String directMediaGlareMitigation) { + this.directMediaGlareMitigation = directMediaGlareMitigation; + } + + public Boolean isTrustIdInbound() { + return trustIdInbound; + } + + public void setTrustIdInbound(Boolean trustIdInbound) { + this.trustIdInbound = trustIdInbound; + } + + public Boolean isBindRtpToMediaAddress() { + return bindRtpToMediaAddress; + } + + public void setBindRtpToMediaAddress(Boolean bindRtpToMediaAddress) { + this.bindRtpToMediaAddress = bindRtpToMediaAddress; + } + + public Boolean isDisableDirectMediaOnNat() { + return disableDirectMediaOnNat; + } + + public void setDisableDirectMediaOnNat(Boolean disableDirectMediaOnNat) { + this.disableDirectMediaOnNat = disableDirectMediaOnNat; + } + + public Boolean isMediaEncryption() { + return mediaEncryption; + } + + public void setMediaEncryption(Boolean mediaEncryption) { + this.mediaEncryption = mediaEncryption; + } + + public Boolean isMediaUseReceivedTransport() { + return mediaUseReceivedTransport; + } + + public void setMediaUseReceivedTransport(Boolean mediaUseReceivedTransport) { + this.mediaUseReceivedTransport = mediaUseReceivedTransport; + } + + public Boolean isAllowOverlap() { + return allowOverlap; + } + + public void setAllowOverlap(Boolean allowOverlap) { + this.allowOverlap = allowOverlap; + } + + public String getDtmfMode() { + return dtmfMode; + } + + public void setDtmfMode(String dtmfMode) { + this.dtmfMode = dtmfMode; + } + + public String getOutboundAuth() { + return outboundAuth; + } + + public void setOutboundAuth(String outboundAuth) { + this.outboundAuth = outboundAuth; + } + + public String getTosVideo() { + return tosVideo; + } + + public void setTosVideo(String tosVideo) { + this.tosVideo = tosVideo; + } + + public String getTosAudio() { + return tosAudio; + } + + public void setTosAudio(String tosAudio) { + this.tosAudio = tosAudio; + } + + public String getDtlsCertFile() { + return dtlsCertFile; + } + + public void setDtlsCertFile(String dtlsCertFile) { + this.dtlsCertFile = dtlsCertFile; + } + + public String getDtlsCaPath() { + return dtlsCaPath; + } + + public void setDtlsCaPath(String dtlsCaPath) { + this.dtlsCaPath = dtlsCaPath; + } + + public String getDtlsSetup() { + return dtlsSetup; + } + + public void setDtlsSetup(String dtlsSetup) { + this.dtlsSetup = dtlsSetup; + } + + public String getConnectedLineMethod() { + return connectedLineMethod; + } + + public void setConnectedLineMethod(String connectedLineMethod) { + this.connectedLineMethod = connectedLineMethod; + } + + public Boolean isG726NonStandard() { + return g726NonStandard; + } + + public void setG726NonStandard(Boolean g726NonStandard) { + this.g726NonStandard = g726NonStandard; + } + + public String get100rel() { + return _100rel; + } + + public void set100rel(String _100rel) { + this._100rel = _100rel; + } + + public String getTimers() { + return timers; + } + + public void setTimers(String timers) { + this.timers = timers; + } + + public Boolean isDirectMedia() { + return directMedia; + } + + public void setDirectMedia(Boolean directMedia) { + this.directMedia = directMedia; + } + + public String getAcl() { + return acl; + } + + public void setAcl(String acl) { + this.acl = acl; + } + + public int getTimersMinSe() { + return timersMinSe; + } + + public void setTimersMinSe(int timersMinSe) { + this.timersMinSe = timersMinSe; + } + + public Boolean isTrustIdOutbound() { + return trustIdOutbound; + } + + public void setTrustIdOutbound(Boolean trustIdOutbound) { + this.trustIdOutbound = trustIdOutbound; + } + + public int getSubMinExpiry() { + return subMinExpiry; + } + + public void setSubMinExpiry(int subMinExpiry) { + this.subMinExpiry = subMinExpiry; + } + + public Boolean isRtcpMux() { + return rtcpMux; + } + + public void setRtcpMux(Boolean rtcpMux) { + this.rtcpMux = rtcpMux; + } + + public Boolean isAcceptMultipleSdpAnswers() { + return acceptMultipleSdpAnswers; + } + + public void setAcceptMultipleSdpAnswers(Boolean acceptMultipleSdpAnswers) { + this.acceptMultipleSdpAnswers = acceptMultipleSdpAnswers; + } + + public Boolean isTrustConnectedLine() { + return trustConnectedLine; + } + + public void setTrustConnectedLine(Boolean trustConnectedLine) { + this.trustConnectedLine = trustConnectedLine; + } + + public Boolean isSendPai() { + return sendPai; + } + + public void setSendPai(Boolean sendPai) { + this.sendPai = sendPai; + } + + public int getRtpKeepalive() { + return rtpKeepalive; + } + + public void setRtpKeepalive(int rtpKeepalive) { + this.rtpKeepalive = rtpKeepalive; + } + + public String getT38UdptlEc() { + return t38UdptlEc; + } + + public void setT38UdptlEc(String t38UdptlEc) { + this.t38UdptlEc = t38UdptlEc; + } + + public Boolean isT38UdptlNat() { + return t38UdptlNat; + } + + public void setT38UdptlNat(Boolean t38UdptlNat) { + this.t38UdptlNat = t38UdptlNat; + } + + public Boolean isAllowTransfer() { + return allowTransfer; + } + + public void setAllowTransfer(Boolean allowTransfer) { + this.allowTransfer = allowTransfer; + } + + public String getDtlsCaFile() { + return dtlsCaFile; + } + + public void setDtlsCaFile(String dtlsCaFile) { + this.dtlsCaFile = dtlsCaFile; + } + + public String getOutboundProxy() { + return outboundProxy; + } + + public void setOutboundProxy(String outboundProxy) { + this.outboundProxy = outboundProxy; + } + + public Boolean isInbandProgress() { + return inbandProgress; + } + + public void setInbandProgress(Boolean inbandProgress) { + this.inbandProgress = inbandProgress; + } + + public String getDeviceState() { + return deviceState; + } + + public void setDeviceState(String deviceState) { + this.deviceState = deviceState; + } + + public String getActiveChannels() { + return activeChannels; + } + + public void setActiveChannels(String activeChannels) { + this.activeChannels = activeChannels; + } + + public EndpointDetail(Object source) { + super(source); + } + + public Boolean getIgnore183withoutsdp() { + return ignore183withoutsdp; + } + + public void setIgnore183withoutsdp(Boolean ignore183withoutsdp) { + this.ignore183withoutsdp = ignore183withoutsdp; + } + +} diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java b/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java new file mode 100644 index 000000000..43f0cf1f0 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java @@ -0,0 +1,87 @@ +/* + * 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.manager.event; + +/** + * An EndpointDetailComplete event is triggered after the details of an endpoint has been + * reported in response to a PJSIPShowEndpoint + *

    + * Available since Asterisk 12 + * + * @see org.asteriskjava.manager.event.PJSIpShowEndpoint + * @author Steve Sether + * @version $Id$ + * @since 12 + */ +public class EndpointDetailComplete extends ResponseEvent +{ + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -1177773673509373296L; + private Integer listItems; + private String eventList; + + /** + * Creates a new instance. + * + * @param source + */ + public EndpointDetailComplete(Object source) + { + super(source); + } + + /** + * Returns the number of EndpointDetail events that have been reported. + * + * @return the number of EndpointDetail events that have been reported. + */ + public Integer getListItems() + { + return listItems; + } + + /** + * Sets the number of EndpointDetail events that have been reported. + * + * @param listItems the number of EndpointDetail events that have been reported. + */ + public void setListItems(Integer listItems) + { + this.listItems = listItems; + } + + /** + * Returns always "Complete". + *

    + * Available since Asterisk 12. + * + * @return always returns "Complete" confirming that all EndpointDetail events have + * been sent. + * @since 12 + */ + public String getEventList() + { + return eventList; + } + + public void setEventList(String eventList) + { + this.eventList = eventList; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java b/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java index e1a1a5dd1..5337b94e1 100644 --- a/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java +++ b/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java @@ -17,17 +17,15 @@ package org.asteriskjava.manager.event; /** - * A PeerlistCompleteEvent is triggered after the details of all peers has been - * reported in response to an SIPPeersAction or SIPShowPeerAction. + * An EndpointListComplete event is triggered after the details of all end points have been + * reported in response to a PJSIPShowEndpoints event. *

    - * Available since Asterisk 1.2 + * Available since Asterisk 12 * - * @see org.asteriskjava.manager.event.PeerEntryEvent - * @see org.asteriskjava.manager.action.SipPeersAction - * @see org.asteriskjava.manager.action.SipShowPeerAction + * @see org.asteriskjava.manager.event.PJSipShowEndpoints * @author srt * @version $Id$ - * @since 0.2 + * @since 12 */ public class EndpointListComplete extends ResponseEvent { @@ -49,9 +47,9 @@ public EndpointListComplete(Object source) } /** - * Returns the number of PeerEvents that have been reported. + * Returns the number of Endpoints that have been reported. * - * @return the number of PeerEvents that have been reported. + * @return the number of Endpoints that have been reported. */ public Integer getListItems() { @@ -59,7 +57,7 @@ public Integer getListItems() } /** - * Sets the number of PeerEvents that have been reported. + * Sets the number of Endpoints that have been reported. * * @param listItems the number of PeerEvents that have been reported. */ diff --git a/src/main/java/org/asteriskjava/manager/event/TransportDetail.java b/src/main/java/org/asteriskjava/manager/event/TransportDetail.java new file mode 100644 index 000000000..2db7b20d6 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/TransportDetail.java @@ -0,0 +1,257 @@ +package org.asteriskjava.manager.event; + + +/** + * A TransportDetail event is triggered in response to a + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint} + *

    + * + * @author Steve Sether + * @version $Id$ + * @since 12 + */ + +public class TransportDetail extends ResponseEvent { + + /** + * Serial version identifier. + */ + private static final long serialVersionUID = 8558130768089350575L; + private String Event; + private String objectType; + private String pbjectName; + private String protocol; + private String bind; + private int asycOperations; + private String caListFile; + private String caListPath; + private String certFile; + private String privKeyFile; + private String password; + private String externalSignalingAddress; + private int externalSignalingPort; + private String externalMediaAddress; + private String domain; + private String verifyServer; + private String verifyClient; + private Boolean requireClientCert; + private String method; + private String cipher; + private String localNet; + private String tos; + private int cos; + private int websocketWriteTimeout; + private String endpointName; + + + /** + * Serial version identifier. + */ + public TransportDetail(Object source) { + super(source); + } + + public String getEvent() { + return Event; + } + + public void setEvent(String event) { + Event = event; + } + + public String getObjectType() { + return objectType; + } + + public void setObjectType(String objectType) { + this.objectType = objectType; + } + + public String getPbjectName() { + return pbjectName; + } + + public void setPbjectName(String pbjectName) { + this.pbjectName = pbjectName; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getBind() { + return bind; + } + + public void setBind(String bind) { + this.bind = bind; + } + + public int getAsycOperations() { + return asycOperations; + } + + public void setAsycOperations(int asycOperations) { + this.asycOperations = asycOperations; + } + + public String getCaListFile() { + return caListFile; + } + + public void setCaListFile(String caListFile) { + this.caListFile = caListFile; + } + + public String getCaListPath() { + return caListPath; + } + + public void setCaListPath(String caListPath) { + this.caListPath = caListPath; + } + + public String getCertFile() { + return certFile; + } + + public void setCertFile(String certFile) { + this.certFile = certFile; + } + + public String getPrivKeyFile() { + return privKeyFile; + } + + public void setPrivKeyFile(String privKeyFile) { + this.privKeyFile = privKeyFile; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getExternalSignalingAddress() { + return externalSignalingAddress; + } + + public void setExternalSignalingAddress(String externalSignalingAddress) { + this.externalSignalingAddress = externalSignalingAddress; + } + + public int getExternalSignalingPort() { + return externalSignalingPort; + } + + public void setExternalSignalingPort(int externalSignalingPort) { + this.externalSignalingPort = externalSignalingPort; + } + + public String getExternalMediaAddress() { + return externalMediaAddress; + } + + public void setExternalMediaAddress(String externalMediaAddress) { + this.externalMediaAddress = externalMediaAddress; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + public String getVerifyServer() { + return verifyServer; + } + + public void setVerifyServer(String verifyServer) { + this.verifyServer = verifyServer; + } + + public String getVerifyClient() { + return verifyClient; + } + + public void setVerifyClient(String verifyClient) { + this.verifyClient = verifyClient; + } + + public Boolean getRequireClientCert() { + return requireClientCert; + } + + public void setRequireClientCert(Boolean requireClientCert) { + this.requireClientCert = requireClientCert; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public String getCipher() { + return cipher; + } + + public void setCipher(String cipher) { + this.cipher = cipher; + } + + public String getLocalNet() { + return localNet; + } + + public void setLocalNet(String localNet) { + this.localNet = localNet; + } + + public String getTos() { + return tos; + } + + public void setTos(String tos) { + this.tos = tos; + } + + public int getCos() { + return cos; + } + + public void setCos(int cos) { + this.cos = cos; + } + + public int getWebsocketWriteTimeout() { + return websocketWriteTimeout; + } + + public void setWebsocketWriteTimeout(int websocketWriteTimeout) { + this.websocketWriteTimeout = websocketWriteTimeout; + } + + public String getEndpointName() { + return endpointName; + } + + public void setEndpointName(String endpointName) { + this.endpointName = endpointName; + } + + public static long getSerialversionuid() { + return serialVersionUID; + } +} diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index 867c977a3..26f11e8cf 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -120,7 +120,11 @@ else if (dataType.isAssignableFrom(int.class) || dataType.isAssignableFrom(Integ try { Constructor< ? > constructor = dataType.getConstructor(String.class); - value = constructor.newInstance(entry.getValue()); + // Asterisk sometimes uses yes/no instead of True/False for boolean. java.lang.Boolean(String) doesn't handle this. + if (dataType.isAssignableFrom(Boolean.class)) { + value = constructor.newInstance(AstUtil.convertAsteriskBooleanStringToStandardBooleanString((String)entry.getValue())); + } + else value = constructor.newInstance(entry.getValue()); } catch (Exception e) { diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java index 0d69efd80..f1ca7814d 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java @@ -91,7 +91,7 @@ public void addEvent(ResponseEvent event) } /** - * Indicats if all events have been received. + * Indicates if all events have been received. * * @param complete true if all events have been received, * false otherwise. diff --git a/src/main/java/org/asteriskjava/util/AstUtil.java b/src/main/java/org/asteriskjava/util/AstUtil.java index 1aa348dc7..b2736e103 100644 --- a/src/main/java/org/asteriskjava/util/AstUtil.java +++ b/src/main/java/org/asteriskjava/util/AstUtil.java @@ -199,4 +199,33 @@ public static boolean isNull(Object s) return NULL_LITERALS.contains(((String) s).toLowerCase(Locale.US)); } + /** + * Converts a non-standard Asterisk boolean String value into something the Boolean class + * String constructor recognizes. + * + * Asterisk can return various strings that represent truth values. + * This method converts them into standard True/False, or null if null. + * + * @param value + * @return true if the String is "true" or "yes" (case insensitive). + * false if the String is "false" or "no" (case insensitive). + * null if the String is null. + * @throws IllegalArgumentException if any other value not listed above. + */ + + public static String convertAsteriskBooleanStringToStandardBooleanString(String value) { + if (value == null) return null; + switch (value.toLowerCase()) + { + case "true": + case "yes": + return "True"; + case "false": + case "no": + return "False"; + default: + throw new IllegalArgumentException("value of:" + value + " was not recognized as a boolean"); + } + + } } From 88ff69b7bde6df2afc6ab6e6651b7d8e2647e6ed Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 9 Dec 2020 11:08:37 +1100 Subject: [PATCH 398/802] fix for npe --- .../pbx/internal/activity/BlindTransferActivityImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index cbe35dd19..efa537e3c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -154,6 +154,9 @@ public boolean doActivity() throws PBXException { sipHeader = PBXFactory.getActiveProfile().getAutoAnswer(); } + + this._latch = new CountDownLatch(1); + BlindTransferResultListener listener = new BlindTransferResultListener() { @@ -177,7 +180,6 @@ public void result(String status, boolean success) // secondary transfer options. Need to review if this is still // required. // TODO control the caller id. - this._latch = new CountDownLatch(1); success = this._latch.await(this._timeout, TimeUnit.SECONDS); if (!success) From 83a1a503fee402a241f4d8e2f216cc9d0b3939b4 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 9 Dec 2020 16:49:16 +1100 Subject: [PATCH 399/802] for version 3.9.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 929574442..cc9cec258 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.8.1-SNAPSHOT + 3.9.0 UTF-8 From ba8ed6a56055f04d2c4abc99061ccdc932c7393c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 16 Dec 2020 11:26:56 +1100 Subject: [PATCH 400/802] fix npe, reduce logging levels --- .../org/asteriskjava/pbx/agi/ActivityAgi.java | 2 +- .../pbx/internal/core/ChannelProxy.java | 6 ++--- .../pbx/internal/managerAPI/DialToAgi.java | 9 +++++++- .../managerAPI/OriginateBaseClass.java | 22 +++++++++---------- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index a3e68c57c..a32853bdb 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -76,7 +76,7 @@ public void service() throws AgiException } - logger.warn("Channel " + channelName + " arrived in agi"); + logger.info("Channel " + channelName + " arrived in agi"); channelProxy.setIsInAgi(true); channelProxy.addHangupListener(new ChannelHangupListener() diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index f13772762..f502d3f78 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -370,7 +370,7 @@ public void setIsInAgi(boolean b) hasReachedAgi.countDown(); } isInAgi = b; - logger.warn("Setting is in agi to " + b + " for channel " + this); + logger.info("Setting is in agi to " + b + " for channel " + this); } @@ -385,9 +385,9 @@ public boolean isInAgi() @Override public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException { - logger.warn("Waiting for channel to reach agi " + this); + logger.info("Waiting for channel to reach agi " + this); boolean tmp = hasReachedAgi.await(timeout, timeunit); - logger.warn("Result of waiting for channel to reach agi " + this + " " + tmp); + logger.info("Result of waiting for channel to reach agi " + this + " " + tmp); return tmp; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index ce437a63c..b83e73177 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -140,7 +140,14 @@ public ListenerPriority getPriority() public void abort() { - originator.abort("user abort"); + if (originator != null) + { + originator.abort("user abort"); + } + else + { + logger.error("Call to abort, but it doesn't look like the Dial had started yet"); + } } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 984f0ea2a..2c65e3c33 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -105,7 +105,7 @@ protected OriginateBaseClass(final NewChannelListener listener, final Channel mo OriginateResult originate(final EndPoint local, final EndPoint target, final HashMap myVars, final CallerID callerID, final Integer timeout, final boolean hideCallerId, final String context) { - OriginateBaseClass.logger.warn("originate called"); + OriginateBaseClass.logger.info("originate called"); this.originateSeen = false; this.channelSeen = false; @@ -116,7 +116,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has return null; } - OriginateBaseClass.logger.warn("originate connection endPoint \n" + local + " to endPoint " + target //$NON-NLS-2$ + OriginateBaseClass.logger.info("originate connection endPoint \n" + local + " to endPoint " + target //$NON-NLS-2$ + " vars " + myVars); ManagerResponse response = null; @@ -185,7 +185,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has this.startListener(); response = pbx.sendAction(originate, localTimeout); - OriginateBaseClass.logger.warn("Originate.sendAction completed"); + OriginateBaseClass.logger.info("Originate.sendAction completed"); if (response.getResponse().compareToIgnoreCase("Success") != 0) { OriginateBaseClass.logger @@ -217,7 +217,7 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has { this.result.setSuccess(true); this.result.setChannelData(this.newChannel); - OriginateBaseClass.logger.warn("new channel ok: " + this.newChannel); + OriginateBaseClass.logger.info("new channel ok: " + this.newChannel); } else { @@ -238,8 +238,6 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has } } - logger.warn("Manager Events seen " + managerEventsSeen.get()); - return this.result; } @@ -372,7 +370,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) if (this.originateID.compareToIgnoreCase(response.getActionId()) == 0) { this.originateSuccess = response.isSuccess(); - OriginateBaseClass.logger.warn("OriginateResponse: matched actionId, success=" + this.originateSuccess + OriginateBaseClass.logger.info("OriginateResponse: matched actionId, success=" + this.originateSuccess + " channelSeen=" + this.channelSeen); this.originateSeen = true; @@ -393,7 +391,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) // notify. if (this.channelSeen) { - OriginateBaseClass.logger.warn("notify originate response event " + this.originateSuccess); + OriginateBaseClass.logger.info("notify originate response event " + this.originateSuccess); originateLatch.countDown(); } else @@ -416,7 +414,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) { final Channel channel = newState.getChannel(); - OriginateBaseClass.logger.warn("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-2$ + OriginateBaseClass.logger.info("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-2$ + " state =" + newState.getChannelStateDesc() + " state =" + newState.getChannelState()); //$NON-NLS-2$ handleId(channel); @@ -438,7 +436,7 @@ synchronized public void onManagerEvent(final ManagerEvent event) { OriginateBaseClass.logger - .warn("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ + .info("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ + " channel2 =" + bridgeEvent.getChannel2()); handleId(channel); @@ -469,7 +467,7 @@ private void handleId(Channel channel) this.newChannel = channel; this.channelSeen = true; - OriginateBaseClass.logger.warn("new channel name " + channel); + OriginateBaseClass.logger.info("new channel name " + channel); if (this.listener != null) { /* @@ -481,7 +479,7 @@ private void handleId(Channel channel) if (this.originateSeen) { - OriginateBaseClass.logger.warn("notifying success 362"); + OriginateBaseClass.logger.info("notifying success 362"); originateLatch.countDown(); } } From aca95a757809582aa4e56d7d3a3b44f23b699a1c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 16 Dec 2020 11:28:53 +1100 Subject: [PATCH 401/802] for version 3.10.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cc9cec258..a7f0972ac 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.9.0 + 3.10.0 UTF-8 From de89b0a615bcc3c39e384040bdc044946c4625f7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 29 Jan 2021 14:31:09 +1100 Subject: [PATCH 402/802] simplify response handling code --- .../internal/ManagerConnectionImpl.java | 114 +++++------------- .../org/asteriskjava/pbx/util/LogTime.java | 3 +- 2 files changed, 30 insertions(+), 87 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 5d2bd9137..84ca799b9 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -70,6 +70,7 @@ import org.asteriskjava.manager.response.CoreSettingsResponse; import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; +import org.asteriskjava.pbx.util.LogTime; import org.asteriskjava.util.DateUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -833,11 +834,11 @@ public ManagerResponse sendAction(ManagerAction action) public ManagerResponse sendAction(ManagerAction action, long timeout) throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException { - ResponseHandlerResult result = new ResponseHandlerResult(); + + DefaultSendActionCallback callbackHandler = new DefaultSendActionCallback(); + ManagerResponse response = null; try { - SendActionCallback callbackHandler = new DefaultSendActionCallback(result); - sendAction(action, callbackHandler); // definitely return null for the response of user events @@ -845,38 +846,31 @@ public ManagerResponse sendAction(ManagerAction action, long timeout) { return null; } - - // only wait if we did not yet receive the response. - // Responses may be returned really fast. - if (result.getResponse() == null) + try { - try - { - result.await(timeout); - } - catch (InterruptedException ex) + response = callbackHandler.waitForResponse(timeout); + + // no response? + if (response == null) { - logger.warn("Interrupted while waiting for result"); - Thread.currentThread().interrupt(); + throw new TimeoutException("Timeout waiting for response to " + action.getAction() + + (action.getActionId() == null + ? "" + : " (actionId: " + action.getActionId() + "), Timeout=" + timeout + " Action=" + + action.getAction())); } } - - // still no response? - if (result.getResponse() == null) + catch (InterruptedException ex) { - throw new TimeoutException("Timeout waiting for response to " + action.getAction() - + (action.getActionId() == null - ? "" - : " (actionId: " + action.getActionId() + "), Timeout=" + timeout + " Action=" - + action.getAction())); - + logger.warn("Interrupted while waiting for result"); + Thread.currentThread().interrupt(); } - return result.getResponse(); } finally { - result.dispose(); + callbackHandler.dispose(); } + return response; } public void sendAction(ManagerAction action, SendActionCallback callback) @@ -1636,87 +1630,37 @@ public String toString() /** * A simple data object to store a ManagerResult. */ - private static class ResponseHandlerResult implements Serializable + private static class DefaultSendActionCallback implements SendActionCallback, Serializable { - /** - * Serializable version identifier. - */ private static final long serialVersionUID = 7831097958568769220L; private ManagerResponse response; private final CountDownLatch latch = new CountDownLatch(1); private volatile boolean disposed = false; + private LogTime timer = new LogTime(); - public ResponseHandlerResult() - { - } - - public ManagerResponse getResponse() + private ManagerResponse waitForResponse(long timeout) throws InterruptedException { + latch.await(timeout, TimeUnit.MILLISECONDS); return this.response; } - public void setResponse(ManagerResponse response) + @Override + public void onResponse(ManagerResponse response) { this.response = response; if (disposed) { - logger.error("Response arrived after Disposal and assumably Timeout " + response); + logger.error("Response arrived after Disposal and assumably Timeout " + response + " elapsed: " + + timer.timeTaken() + "(MS)"); } - } - - public void dispose() - { - disposed = true; - } - - private void countDown() - { latch.countDown(); } - /** - * @param millis - milliseconds to wait - * @return - * @throws InterruptedException - */ - private boolean await(long millis) throws InterruptedException + private void dispose() { - return latch.await(millis, TimeUnit.MILLISECONDS); - } - - } - - /** - * A simple response handler that stores the received response in a - * ResponseHandlerResult for further processing. - */ - private static class DefaultSendActionCallback implements SendActionCallback, Serializable - { - /** - * Serializable version identifier. - */ - private static final long serialVersionUID = 2926598671855316803L; - private final ResponseHandlerResult result; - - /** - * Creates a new instance. - * - * @param result the result to store the response in - */ - public DefaultSendActionCallback(ResponseHandlerResult result) - { - this.result = result; + disposed = true; } - public void onResponse(ManagerResponse response) - { - // null response happens when connection is lost - if (response != null) - { - result.setResponse(response); - } - result.countDown(); - } } /** diff --git a/src/main/java/org/asteriskjava/pbx/util/LogTime.java b/src/main/java/org/asteriskjava/pbx/util/LogTime.java index fd2261e4c..98880e42b 100644 --- a/src/main/java/org/asteriskjava/pbx/util/LogTime.java +++ b/src/main/java/org/asteriskjava/pbx/util/LogTime.java @@ -13,8 +13,7 @@ public class LogTime public long timeTaken() { - // returns the time taken from construction til now in milliseconds - // Date dStartTime = new Date(); + // returns the time taken from construction until now in milliseconds return System.currentTimeMillis() - this.dStartTime; From 25681990af688feac648fa79a8e506319b810a89 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 29 Jan 2021 17:23:05 +1100 Subject: [PATCH 403/802] update version number in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c1eb5bdf4..8b4908a97 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 16) (master) org.asteriskjava asterisk-java - 3.6.0 + 3.11.0 Asterisk-Java 2.x (Java 1.7 and Asterisk < Version 10) (branch 2.0.4) From 8e7c0ef2bb17457af6319b322f6159dfd6466d97 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 29 Jan 2021 17:25:44 +1100 Subject: [PATCH 404/802] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b4908a97..625aa24db 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ To compile and run do: SYSTEM REQUIREMENTS ------------------- -Asterisk-Java needs a Java Virtual Machine of at least version 1.7 ([Java SE 7.0](http://www.oracle.com/technetwork/java/javase/downloads/index.html)). If you want to build the jar from source, you will +Asterisk-Java needs a Java Virtual Machine of at least version 1.8 ([Java SE 8.0](http://www.oracle.com/technetwork/java/javase/downloads/index.html)). If you want to build the jar from source, you will also need [Maven](http://maven.apache.org/). LEGAL From 6ebbc5d00eb462184a54b8635128d708a6006662 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 1 Feb 2021 16:02:15 +1100 Subject: [PATCH 405/802] add lock diagnostics --- .../asteriskjava/config/ConfigFileImpl.java | 7 +- .../asteriskjava/fastagi/AsyncAgiServer.java | 91 +++-- .../ResourceBundleMappingStrategy.java | 5 +- .../live/internal/AgentManager.java | 42 +-- .../live/internal/AsteriskAgentImpl.java | 16 +- .../live/internal/AsteriskChannelImpl.java | 249 +++++++------ .../live/internal/AsteriskQueueEntryImpl.java | 49 +-- .../live/internal/AsteriskQueueImpl.java | 351 +++++++++--------- .../internal/AsteriskQueueMemberImpl.java | 89 +++-- .../live/internal/AsteriskServerImpl.java | 231 +++++++----- .../live/internal/ChannelManager.java | 84 +++-- .../live/internal/MeetMeManager.java | 10 +- .../live/internal/MeetMeRoomImpl.java | 24 +- .../live/internal/MeetMeUserImpl.java | 21 +- .../live/internal/QueueManager.java | 135 +++---- .../org/asteriskjava/manager/PingThread.java | 28 +- .../internal/ManagerConnectionImpl.java | 36 +- .../manager/internal/ManagerWriterImpl.java | 43 ++- .../manager/internal/ResponseEventsImpl.java | 4 +- .../bridge/BridgeState.java | 14 +- .../java/org/asteriskjava/pbx/CallImpl.java | 32 -- .../activity/BlindTransferActivityImpl.java | 71 ++-- .../internal/activity/ParkActivityImpl.java | 17 +- .../internal/activity/SplitActivityImpl.java | 15 +- .../pbx/internal/asterisk/MeetmeRoom.java | 115 +++--- .../internal/asterisk/MeetmeRoomControl.java | 156 ++++---- .../pbx/internal/core/AsteriskPBX.java | 6 +- .../pbx/internal/core/CallTracker.java | 18 +- .../core/CoherentManagerEventQueue.java | 18 +- .../pbx/internal/core/LiveChannelManager.java | 4 +- .../asteriskjava/pbx/internal/core/Peer.java | 18 +- .../pbx/internal/core/PeerMonitor.java | 83 +++-- .../managerAPI/OriginateBaseClass.java | 254 ++++++------- .../java/org/asteriskjava/util/Locker.java | 238 ++++++++++++ .../internal/streamreader/FastScannerNl.java | 32 +- 35 files changed, 1537 insertions(+), 1069 deletions(-) create mode 100644 src/main/java/org/asteriskjava/util/Locker.java diff --git a/src/main/java/org/asteriskjava/config/ConfigFileImpl.java b/src/main/java/org/asteriskjava/config/ConfigFileImpl.java index 2810f5e20..a14c11ce6 100644 --- a/src/main/java/org/asteriskjava/config/ConfigFileImpl.java +++ b/src/main/java/org/asteriskjava/config/ConfigFileImpl.java @@ -21,6 +21,9 @@ import java.util.Map; import java.util.TreeMap; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; + /** * An Asterisk configuration file read from the filesystem. * @@ -50,7 +53,7 @@ public Map> getCategories() c = new TreeMap<>(); - synchronized (categories) + try (LockCloser closer = Locker.lock(categories)) { for (Category category : categories.values()) { @@ -126,7 +129,7 @@ public List getValues(String categoryName, String key) protected Category getCategory(String name) { - synchronized (categories) + try (LockCloser closer = Locker.lock(categories)) { return categories.get(name); } diff --git a/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java b/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java index 335ad2c42..69b1c93ab 100644 --- a/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java @@ -11,11 +11,14 @@ import org.asteriskjava.manager.event.AsyncAgiEvent; import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.event.RenameEvent; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; /** - * AGI server for AGI over the Manager API (AsyncAGI).

    + * AGI server for AGI over the Manager API (AsyncAGI). + *

    * AsyncAGI is available since Asterisk 1.6. * * @since 1.0.0 @@ -26,8 +29,10 @@ public class AsyncAgiServer extends AbstractAgiServer implements ManagerEventLis private final Map connectionHandlers; /** - * Creates a new AsyncAgiServer with a {@link DefaultAgiChannelFactory}.

    - * Note that you must set a {@link org.asteriskjava.fastagi.MappingStrategy} before using it. + * Creates a new AsyncAgiServer with a {@link DefaultAgiChannelFactory}. + *

    + * Note that you must set a {@link org.asteriskjava.fastagi.MappingStrategy} + * before using it. * * @see #setMappingStrategy(MappingStrategy) */ @@ -37,10 +42,13 @@ public AsyncAgiServer() } /** - * Creates a new AsyncAgiServer with a custom {@link AgiChannelFactory}.

    - * Note that you must set a {@link org.asteriskjava.fastagi.MappingStrategy} before using it. + * Creates a new AsyncAgiServer with a custom {@link AgiChannelFactory}. + *

    + * Note that you must set a {@link org.asteriskjava.fastagi.MappingStrategy} + * before using it. * - * @param agiChannelFactory The factory to use for creating new AgiChannel instances. + * @param agiChannelFactory The factory to use for creating new AgiChannel + * instances. * @see #setMappingStrategy(MappingStrategy) * @since 1.0.0 */ @@ -51,13 +59,15 @@ public AsyncAgiServer(AgiChannelFactory agiChannelFactory) } /** - * Creates a new AsyncAgiServer with the given MappingStrategy.

    - * 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 null. + * Creates a new AsyncAgiServer with the given MappingStrategy. + *

    + * 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 null. * - * @param mappingStrategy the MappingStrategy to use to determine which AGI script to run - * for a certain request. + * @param mappingStrategy the MappingStrategy to use to determine which AGI + * script to run for a certain request. */ public AsyncAgiServer(MappingStrategy mappingStrategy) { @@ -66,14 +76,17 @@ public AsyncAgiServer(MappingStrategy mappingStrategy) } /** - * Creates a new AsyncAgiServer with the given MappingStrategy.

    - * 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 null. + * Creates a new AsyncAgiServer with the given MappingStrategy. + *

    + * 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 null. * - * @param mappingStrategy the MappingStrategy to use to determine which AGI script to run - * for a certain request. - * @param agiChannelFactory The factory to use for creating new AgiChannel instances. + * @param mappingStrategy the MappingStrategy to use to determine which AGI + * script to run for a certain request. + * @param agiChannelFactory The factory to use for creating new AgiChannel + * instances. */ public AsyncAgiServer(MappingStrategy mappingStrategy, AgiChannelFactory agiChannelFactory) { @@ -82,12 +95,15 @@ public AsyncAgiServer(MappingStrategy mappingStrategy, AgiChannelFactory agiChan } /** - * Creates a new AsyncAgiServer that will execute the given AGI script for every - * request.

    - * Internally this constructor uses a {@link org.asteriskjava.fastagi.StaticMappingStrategy}. + * Creates a new AsyncAgiServer that will execute the given AGI script for + * every request. + *

    + * Internally this constructor uses a + * {@link org.asteriskjava.fastagi.StaticMappingStrategy}. * - * @param agiScript the AGI script to execute. - * @param agiChannelFactory The factory to use for creating new AgiChannel instances. + * @param agiScript the AGI script to execute. + * @param agiChannelFactory The factory to use for creating new AgiChannel + * instances. */ public AsyncAgiServer(AgiScript agiScript, AgiChannelFactory agiChannelFactory) { @@ -96,9 +112,11 @@ public AsyncAgiServer(AgiScript agiScript, AgiChannelFactory agiChannelFactory) } /** - * Creates a new AsyncAgiServer that will execute the given AGI script for every - * request.

    - * Internally this constructor uses a {@link org.asteriskjava.fastagi.StaticMappingStrategy}. + * Creates a new AsyncAgiServer that will execute the given AGI script for + * every request. + *

    + * Internally this constructor uses a + * {@link org.asteriskjava.fastagi.StaticMappingStrategy}. * * @param agiScript the AGI script to execute. */ @@ -108,7 +126,6 @@ public AsyncAgiServer(AgiScript agiScript) logger.debug("use default AgiChannelFactory"); } - public void onManagerEvent(ManagerEvent event) { if (event instanceof AsyncAgiEvent) @@ -132,7 +149,8 @@ private void handleAsyncAgiEvent(AsyncAgiEvent asyncAgiEvent) if (asyncAgiEvent.isStart()) { - connectionHandler = new AsyncAgiConnectionHandler(getMappingStrategy(), asyncAgiEvent, this.getAgiChannelFactory()); + connectionHandler = new AsyncAgiConnectionHandler(getMappingStrategy(), asyncAgiEvent, + this.getAgiChannelFactory()); setConnectionHandler(connection, channelName, connectionHandler); try { @@ -141,7 +159,8 @@ private void handleAsyncAgiEvent(AsyncAgiEvent asyncAgiEvent) catch (RejectedExecutionException e) { logger.warn("Execution was rejected by pool. Try to increase the pool size."); - // release resources if execution was rejected due to the pool size + // release resources if execution was rejected due to the pool + // size connectionHandler.release(); } } @@ -150,7 +169,8 @@ private void handleAsyncAgiEvent(AsyncAgiEvent asyncAgiEvent) connectionHandler = getConnectionHandler(connection, channelName); if (connectionHandler == null) { - logger.info("No AsyncAgiConnectionHandler registered for channel " + channelName + ": Ignoring AsyncAgiEvent"); + logger.info( + "No AsyncAgiConnectionHandler registered for channel " + channelName + ": Ignoring AsyncAgiEvent"); return; } @@ -188,15 +208,16 @@ private void handleRenameEvent(RenameEvent renameEvent) private AsyncAgiConnectionHandler getConnectionHandler(ManagerConnection connection, String channelName) { - synchronized (connectionHandlers) + try (LockCloser closer = Locker.lock(connectionHandlers)) { return connectionHandlers.get(calculateHashKey(connection, channelName)); } } - private void setConnectionHandler(ManagerConnection connection, String channelName, AsyncAgiConnectionHandler connectionHandler) + private void setConnectionHandler(ManagerConnection connection, String channelName, + AsyncAgiConnectionHandler connectionHandler) { - synchronized (connectionHandlers) + try (LockCloser closer = Locker.lock(connectionHandlers)) { connectionHandlers.put(calculateHashKey(connection, channelName), connectionHandler); } @@ -204,7 +225,7 @@ private void setConnectionHandler(ManagerConnection connection, String channelNa private void removeConnectionHandler(ManagerConnection connection, String channelName) { - synchronized (connectionHandlers) + try (LockCloser closer = Locker.lock(connectionHandlers)) { connectionHandlers.remove(calculateHashKey(connection, channelName)); } diff --git a/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java b/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java index ac387c9a1..3da8617b7 100644 --- a/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java +++ b/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java @@ -23,6 +23,9 @@ import java.util.MissingResourceException; import java.util.ResourceBundle; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; + /** * A MappingStrategy that is configured via a resource bundle. *

    @@ -113,7 +116,7 @@ public ResourceBundleMappingStrategy(String resourceBundleName, boolean shareIns public void setResourceBundleName(String resourceBundleName) { this.resourceBundleName = resourceBundleName; - synchronized (this) + try (LockCloser closer = Locker.lock(this)) { this.mappings = null; this.instances = null; diff --git a/src/main/java/org/asteriskjava/live/internal/AgentManager.java b/src/main/java/org/asteriskjava/live/internal/AgentManager.java index 51bc073f5..b7a878256 100644 --- a/src/main/java/org/asteriskjava/live/internal/AgentManager.java +++ b/src/main/java/org/asteriskjava/live/internal/AgentManager.java @@ -35,6 +35,8 @@ import org.asteriskjava.manager.event.AgentLogoffEvent; import org.asteriskjava.manager.event.AgentsEvent; import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -77,7 +79,7 @@ public class AgentManager * AgentsAction. * * @throws ManagerCommunicationException if communication with Asterisk - * server fails. + * server fails. */ void initialize() throws ManagerCommunicationException { @@ -89,7 +91,7 @@ void initialize() throws ManagerCommunicationException { if (event instanceof AgentsEvent) { - logger.info( event ); + logger.info(event); handleAgentsEvent((AgentsEvent) event); } } @@ -97,7 +99,7 @@ void initialize() throws ManagerCommunicationException void disconnected() { - synchronized (agents) + try (LockCloser closer = Locker.lock(agents)) { agents.clear(); } @@ -110,8 +112,8 @@ void disconnected() */ void handleAgentsEvent(AgentsEvent event) { - AsteriskAgentImpl agent = new AsteriskAgentImpl(server, - event.getName(), "Agent/" + event.getAgent(), AgentState.valueOf(event.getStatus())); + AsteriskAgentImpl agent = new AsteriskAgentImpl(server, event.getName(), "Agent/" + event.getAgent(), + AgentState.valueOf(event.getStatus())); logger.info("Adding agent " + agent.getName() + "(" + agent.getAgentId() + ")"); addAgent(agent); @@ -124,7 +126,7 @@ void handleAgentsEvent(AgentsEvent event) */ private void addAgent(AsteriskAgentImpl agent) { - synchronized (agents) + try (LockCloser closer = Locker.lock(agents)) { agents.put(agent.getAgentId(), agent); } @@ -139,7 +141,7 @@ private void addAgent(AsteriskAgentImpl agent) */ AsteriskAgentImpl getAgentByAgentId(String agentId) { - synchronized (agents) + try (LockCloser closer = Locker.lock(agents)) { return agents.get(agentId); } @@ -170,7 +172,7 @@ void handleAgentCalledEvent(AgentCalledEvent event) private void updateAgentState(AsteriskAgentImpl agent, AgentState newState) { logger.info("Set state of agent " + agent.getAgentId() + " to " + newState); - synchronized (agent) + try (LockCloser closer = Locker.lock(agent)) { agent.updateState(newState); } @@ -186,7 +188,7 @@ private void updateAgentState(AsteriskAgentImpl agent, AgentState newState) */ private void updateRingingAgents(String channelCalling, AsteriskAgentImpl agent) { - synchronized (ringingAgents) + try (LockCloser closer = Locker.lock(ringingAgents)) { if (ringingAgents.containsKey(channelCalling)) { @@ -211,7 +213,7 @@ void handleAgentConnectEvent(AgentConnectEvent event) } agent.updateState(AgentState.AGENT_ONCALL); } - + /** * Change state if agent logs in. * @@ -222,10 +224,10 @@ void handleAgentLoginEvent(AgentLoginEvent event) AsteriskAgentImpl agent = getAgentByAgentId("Agent/" + event.getAgent()); if (agent == null) { - synchronized (agents) + try (LockCloser closer = Locker.lock(agents)) { - logger.error("Ignored AgentLoginEvent for unknown agent " - + event.getAgent() + ". Agents: " + agents.values().toString()); + logger.error("Ignored AgentLoginEvent for unknown agent " + event.getAgent() + ". Agents: " + + agents.values().toString()); } return; @@ -243,8 +245,7 @@ void handleAgentLogoffEvent(AgentLogoffEvent event) AsteriskAgentImpl agent = getAgentByAgentId("Agent/" + event.getAgent()); if (agent == null) { - logger.error("Ignored AgentLogoffEvent for unknown agent " - + event.getAgent() + ". Agents: " + logger.error("Ignored AgentLogoffEvent for unknown agent " + event.getAgent() + ". Agents: " + agents.values().toString()); return; } @@ -261,10 +262,10 @@ void handleAgentCallbackLoginEvent(AgentCallbackLoginEvent event) AsteriskAgentImpl agent = getAgentByAgentId("Agent/" + event.getAgent()); if (agent == null) { - synchronized (agents) + try (LockCloser closer = Locker.lock(agents)) { - logger.error("Ignored AgentCallbackLoginEvent for unknown agent " - + event.getAgent() + ". Agents: " + agents.values().toString()); + logger.error("Ignored AgentCallbackLoginEvent for unknown agent " + event.getAgent() + ". Agents: " + + agents.values().toString()); } return; @@ -282,8 +283,7 @@ void handleAgentCallbackLogoffEvent(AgentCallbackLogoffEvent event) AsteriskAgentImpl agent = getAgentByAgentId("Agent/" + event.getAgent()); if (agent == null) { - logger.error("Ignored AgentCallbackLogoffEvent for unknown agent " - + event.getAgent() + ". Agents: " + logger.error("Ignored AgentCallbackLogoffEvent for unknown agent " + event.getAgent() + ". Agents: " + agents.values().toString()); return; } @@ -300,7 +300,7 @@ Collection getAgents() { Collection copy; - synchronized (agents) + try (LockCloser closer = Locker.lock(agents)) { copy = new ArrayList(agents.values()); } diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java index 1d38c3f67..b89a0ba7c 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java @@ -18,6 +18,8 @@ import org.asteriskjava.live.AgentState; import org.asteriskjava.live.AsteriskAgent; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; /** * Default implementation of the AsteriskAgent interface. @@ -58,11 +60,15 @@ public AgentState getState() return state; } - synchronized void updateState(AgentState state) + void updateState(AgentState state) { - final AgentState oldState = this.state; - this.state = state; - firePropertyChange(PROPERTY_STATE, oldState, this.state); + + try (LockCloser closer = Locker.lock(this)) + { + final AgentState oldState = this.state; + this.state = state; + firePropertyChange(PROPERTY_STATE, oldState, this.state); + } } @Override @@ -79,4 +85,4 @@ public String toString() return sb.toString(); } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java index 770d4001a..f4c96e50e 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java @@ -50,6 +50,8 @@ import org.asteriskjava.manager.action.UnpauseMonitorAction; import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.MixMonitorDirection; /** @@ -274,7 +276,7 @@ public ChannelState getState() public boolean wasInState(ChannelState state) { - synchronized (stateHistory) + try (LockCloser closer = Locker.lock(stateHistory)) { for (ChannelStateHistoryEntry historyEntry : stateHistory) { @@ -300,26 +302,30 @@ public boolean wasBusy() * @param date when the state change occurred. * @param state the new state of this channel. */ - synchronized void stateChanged(Date date, ChannelState state) + void stateChanged(Date date, ChannelState state) { - final ChannelStateHistoryEntry historyEntry; - final ChannelState oldState = this.state; - - if (oldState == state) + try (LockCloser closer = Locker.lock(this)) { - return; - } + final ChannelStateHistoryEntry historyEntry; + final ChannelState oldState = this.state; - // System.err.println(id + " state change: " + oldState + " => " + state - // + " (" + name + ")"); - historyEntry = new ChannelStateHistoryEntry(date, state); - synchronized (stateHistory) - { - stateHistory.add(historyEntry); - } + if (oldState == state) + { + return; + } + + // System.err.println(id + " state change: " + oldState + " => " + + // state + // + " (" + name + ")"); + historyEntry = new ChannelStateHistoryEntry(date, state); + try (LockCloser closer2 = Locker.lock(stateHistory)) + { + stateHistory.add(historyEntry); + } - this.state = state; - firePropertyChange(PROPERTY_STATE, oldState, state); + this.state = state; + firePropertyChange(PROPERTY_STATE, oldState, state); + } } public String getAccount() @@ -344,7 +350,7 @@ public Extension getCurrentExtension() { final Extension extension; - synchronized (extensionHistory) + try (LockCloser closer = Locker.lock(extensionHistory)) { if (extensionHistory.isEmpty()) { @@ -363,7 +369,7 @@ public Extension getFirstExtension() { final Extension extension; - synchronized (extensionHistory) + try (LockCloser closer = Locker.lock(extensionHistory)) { if (extensionHistory.isEmpty()) { @@ -382,7 +388,7 @@ public List getExtensionHistory() { final List copy; - synchronized (extensionHistory) + try (LockCloser closer = Locker.lock(extensionHistory)) { copy = new ArrayList<>(extensionHistory); } @@ -403,7 +409,7 @@ void extensionVisited(Date date, Extension extension) historyEntry = new ExtensionHistoryEntry(date, extension); - synchronized (extensionHistory) + try (LockCloser closer = Locker.lock(extensionHistory)) { extensionHistory.add(historyEntry); } @@ -452,13 +458,16 @@ void callDetailRecordReceived(Date date, CallDetailRecordImpl callDetailRecord) * @param hangupCause cause for hangup * @param hangupCauseText textual representation of hangup cause */ - synchronized void hungup(Date dateOfRemoval, HangupCause hangupCause, String hangupCauseText) + void hungup(Date dateOfRemoval, HangupCause hangupCause, String hangupCauseText) { - this.dateOfRemoval = dateOfRemoval; - this.hangupCause = hangupCause; - this.hangupCauseText = hangupCauseText; - // update state and fire PropertyChangeEvent - stateChanged(dateOfRemoval, ChannelState.HUNGUP); + try (LockCloser closer = Locker.lock(this)) + { + this.dateOfRemoval = dateOfRemoval; + this.hangupCause = hangupCause; + this.hangupCauseText = hangupCauseText; + // update state and fire PropertyChangeEvent + stateChanged(dateOfRemoval, ChannelState.HUNGUP); + } } /** @@ -470,7 +479,7 @@ public List getDialedChannels() { final List copy; - synchronized (dialedChannels) + try (LockCloser closer = Locker.lock(dialedChannels)) { copy = new ArrayList<>(dialedChannels); } @@ -482,7 +491,7 @@ public List getDialedChannels() public AsteriskChannel getDialedChannel() { - synchronized (dialedChannels) + try (LockCloser closer = Locker.lock(dialedChannels)) { for (AsteriskChannel channel : dialedChannels) { @@ -497,7 +506,7 @@ public List getDialedChannelHistory() { final List copy; - synchronized (dialedChannelHistory) + try (LockCloser closer = Locker.lock(dialedChannelHistory)) { copy = new ArrayList<>(dialedChannelHistory); } @@ -505,33 +514,36 @@ public List getDialedChannelHistory() return copy; } - synchronized void channelDialed(Date date, AsteriskChannel dialedChannel) + void channelDialed(Date date, AsteriskChannel dialedChannel) { - final AsteriskChannel oldDialedChannel; - synchronized (dialedChannels) + try (LockCloser closer = Locker.lock(this)) { - if (dialedChannels.isEmpty()) - oldDialedChannel = null; - else - oldDialedChannel = dialedChannels.get(dialedChannels.size() - 1); - dialedChannels.add(dialedChannel); - } - final DialedChannelHistoryEntry historyEntry; + final AsteriskChannel oldDialedChannel; + try (LockCloser closer2 = Locker.lock(dialedChannels)) + { + if (dialedChannels.isEmpty()) + oldDialedChannel = null; + else + oldDialedChannel = dialedChannels.get(dialedChannels.size() - 1); + dialedChannels.add(dialedChannel); + } + final DialedChannelHistoryEntry historyEntry; - historyEntry = new DialedChannelHistoryEntry(date, dialedChannel); - synchronized (dialedChannelHistory) - { - dialedChannelHistory.add(historyEntry); - } + historyEntry = new DialedChannelHistoryEntry(date, dialedChannel); + try (LockCloser closer3 = Locker.lock(dialedChannelHistory)) + { + dialedChannelHistory.add(historyEntry); + } - firePropertyChange(PROPERTY_DIALED_CHANNEL, oldDialedChannel, dialedChannel); + firePropertyChange(PROPERTY_DIALED_CHANNEL, oldDialedChannel, dialedChannel); + } } /* dialed channels */ public AsteriskChannel getDialingChannel() { - synchronized (dialingChannels) + try (LockCloser closer = Locker.lock(dialingChannels)) { if (dialingChannels.isEmpty()) return null; @@ -539,31 +551,34 @@ public AsteriskChannel getDialingChannel() } } - synchronized void channelDialing(Date date, AsteriskChannel dialingChannel) + void channelDialing(Date date, AsteriskChannel dialingChannel) { - final AsteriskChannel oldDialingChannel; - synchronized (this.dialingChannels) + try (LockCloser closer = Locker.lock(this)) { - if (this.dialingChannels.isEmpty()) + final AsteriskChannel oldDialingChannel; + try (LockCloser closer2 = Locker.lock(this.dialingChannels)) { - oldDialingChannel = null; - this.dialingChannels.add(dialingChannel); - } - else - { - oldDialingChannel = this.dialingChannels.get(0); - this.dialingChannels.set(0, dialingChannel); + if (this.dialingChannels.isEmpty()) + { + oldDialingChannel = null; + this.dialingChannels.add(dialingChannel); + } + else + { + oldDialingChannel = this.dialingChannels.get(0); + this.dialingChannels.set(0, dialingChannel); + } } - } - firePropertyChange(PROPERTY_DIALING_CHANNEL, oldDialingChannel, dialingChannel); + firePropertyChange(PROPERTY_DIALING_CHANNEL, oldDialingChannel, dialingChannel); + } } /* linked channels */ public AsteriskChannel getLinkedChannel() { - synchronized (linkedChannels) + try (LockCloser closer = Locker.lock(linkedChannels)) { if (linkedChannels.isEmpty()) return null; @@ -575,7 +590,7 @@ public List getLinkedChannelHistory() { final List copy; - synchronized (linkedChannelHistory) + try (LockCloser closer = Locker.lock(linkedChannelHistory)) { copy = new ArrayList<>(linkedChannelHistory); } @@ -594,71 +609,77 @@ public boolean wasLinked() * @param date the date this channel was linked. * @param linkedChannel the channel this channel is bridged with. */ - synchronized void channelLinked(Date date, AsteriskChannel linkedChannel) + void channelLinked(Date date, AsteriskChannel linkedChannel) { - final AsteriskChannel oldLinkedChannel; - synchronized (this.linkedChannels) + try (LockCloser closer = Locker.lock(this)) { - if (this.linkedChannels.isEmpty()) + final AsteriskChannel oldLinkedChannel; + try (LockCloser closer2 = Locker.lock(this.linkedChannels)) { - oldLinkedChannel = null; - this.linkedChannels.add(linkedChannel); - } - else - { - oldLinkedChannel = this.linkedChannels.get(0); - this.linkedChannels.set(0, linkedChannel); + if (this.linkedChannels.isEmpty()) + { + oldLinkedChannel = null; + this.linkedChannels.add(linkedChannel); + } + else + { + oldLinkedChannel = this.linkedChannels.get(0); + this.linkedChannels.set(0, linkedChannel); + } } - } - final LinkedChannelHistoryEntry historyEntry; + final LinkedChannelHistoryEntry historyEntry; - historyEntry = new LinkedChannelHistoryEntry(date, linkedChannel); - synchronized (linkedChannelHistory) - { - linkedChannelHistory.add(historyEntry); + historyEntry = new LinkedChannelHistoryEntry(date, linkedChannel); + try (LockCloser closer3 = Locker.lock(linkedChannelHistory)) + { + linkedChannelHistory.add(historyEntry); + } + this.wasLinked = true; + firePropertyChange(PROPERTY_LINKED_CHANNEL, oldLinkedChannel, linkedChannel); } - this.wasLinked = true; - firePropertyChange(PROPERTY_LINKED_CHANNEL, oldLinkedChannel, linkedChannel); } - synchronized void channelUnlinked(Date date) + void channelUnlinked(Date date) { - final AsteriskChannel oldLinkedChannel; - - synchronized (this.linkedChannels) + try (LockCloser closer = Locker.lock(this)) { - if (this.linkedChannels.isEmpty()) - { - oldLinkedChannel = null; - } - else + final AsteriskChannel oldLinkedChannel; + + try (LockCloser closer2 = Locker.lock(this.linkedChannels)) { - oldLinkedChannel = this.linkedChannels.get(0); + if (this.linkedChannels.isEmpty()) + { + oldLinkedChannel = null; + } + else + { + oldLinkedChannel = this.linkedChannels.get(0); + } + linkedChannels.clear(); } - linkedChannels.clear(); - } - final LinkedChannelHistoryEntry historyEntry; + final LinkedChannelHistoryEntry historyEntry; - synchronized (linkedChannelHistory) - { - if (linkedChannelHistory.isEmpty()) + try (LockCloser closer3 = Locker.lock(linkedChannelHistory)) { - historyEntry = null; + if (linkedChannelHistory.isEmpty()) + { + historyEntry = null; + } + else + { + historyEntry = linkedChannelHistory.get(linkedChannelHistory.size() - 1); + } } - else + + if (historyEntry != null) { - historyEntry = linkedChannelHistory.get(linkedChannelHistory.size() - 1); + historyEntry.setDateUnlinked(date); } - } - if (historyEntry != null) - { - historyEntry.setDateUnlinked(date); + firePropertyChange(PROPERTY_LINKED_CHANNEL, oldLinkedChannel, null); } - - firePropertyChange(PROPERTY_LINKED_CHANNEL, oldLinkedChannel, null); } /* MeetMe user */ @@ -732,7 +753,7 @@ public void redirectBothLegs(String context, String exten, int priority) { ManagerResponse response; - synchronized (linkedChannels) + try (LockCloser closer = Locker.lock(linkedChannels)) { if (linkedChannels.isEmpty()) { @@ -756,7 +777,7 @@ public String getVariable(String variable) throws ManagerCommunicationException, ManagerResponse response; String value; - synchronized (variables) + try (LockCloser closer = Locker.lock(variables)) { value = variables.get(variable); @@ -790,7 +811,7 @@ public void setVariable(String variable, String value) throws ManagerCommunicati { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } - synchronized (variables) + try (LockCloser closer = Locker.lock(variables)) { variables.put(variable, value); } @@ -940,7 +961,7 @@ void setParkedAt(Extension parkedAt, String parkingLot) void updateVariable(String name, String value) { - synchronized (variables) + try (LockCloser closer = Locker.lock(variables)) { // final String oldValue = variables.get(name); variables.put(name, value); @@ -950,7 +971,7 @@ void updateVariable(String name, String value) public Map getVariables() { - synchronized (variables) + try (LockCloser closer = Locker.lock(variables)) { return new HashMap<>(variables); } @@ -1018,7 +1039,7 @@ public String toString() sb = new StringBuilder("AsteriskChannel["); - synchronized (this) + try (LockCloser closer = Locker.lock(this)) { sb.append("id='").append(getId()).append("',"); sb.append("name='").append(getName()).append("',"); @@ -1037,7 +1058,7 @@ public String toString() else { sb.append("dialedChannel=AsteriskChannel["); - synchronized (dialedChannels) + try (LockCloser closer = Locker.lock(dialedChannels)) { for (AsteriskChannel dialedChannel : dialedChannels) { @@ -1057,7 +1078,7 @@ public String toString() sb.append("id='").append(dialingChannel.get(0).getId()).append("',"); sb.append("name='").append(dialingChannel.get(0).getName()).append("'],"); } - synchronized (linkedChannel) + try (LockCloser closer = Locker.lock(linkedChannel)) { if (linkedChannel.isEmpty()) { diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java index 4ab3d0f90..94236f0bb 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java @@ -4,6 +4,8 @@ import org.asteriskjava.live.AsteriskQueueEntry; import org.asteriskjava.live.QueueEntryState; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; /** * Default implementation of the AsteriskQueueEntry interface. @@ -20,15 +22,18 @@ class AsteriskQueueEntryImpl extends AbstractLiveObject implements AsteriskQueue private QueueEntryState state; // the position as given by asterisk in the queue entry or join event. - // we cannot work reliably with it because asterisk doesn't tell us when it shifts the entries. + // we cannot work reliably with it because asterisk doesn't tell us when it + // shifts the entries. private int reportedPosition; - // The position of this entry in our representation of the queue. Will be set - // and maintained by the respective queue when the entry is added/removed/shifted + // The position of this entry in our representation of the queue. Will be + // set + // and maintained by the respective queue when the entry is + // added/removed/shifted private int position = POSITION_UNDETERMINED; - AsteriskQueueEntryImpl(AsteriskServerImpl server, AsteriskQueueImpl queue, - AsteriskChannelImpl channel, int reportedPosition, Date dateJoined) + AsteriskQueueEntryImpl(AsteriskServerImpl server, AsteriskQueueImpl queue, AsteriskChannelImpl channel, + int reportedPosition, Date dateJoined) { super(server); this.queue = queue; @@ -64,14 +69,15 @@ public Date getDateLeft() } /** - * Sets the status to {@link QueueEntryState#LEFT} and dateLeft to the given date. + * Sets the status to {@link QueueEntryState#LEFT} and dateLeft to the given + * date. * * @param dateLeft the date this member left the queue. */ void left(Date dateLeft) { QueueEntryState oldState; - synchronized (this) + try (LockCloser closer = Locker.lock(this)) { oldState = this.state; this.dateLeft = dateLeft; @@ -87,8 +93,8 @@ public QueueEntryState getState() /** * Gets the position as reported by Asterisk when the entry was created. - * Currently we don't update this property as the entry shifts through the queue, - * see getPosition() instead. + * Currently we don't update this property as the entry shifts through the + * queue, see getPosition() instead. * * @return the position of the entry in the respective queue, starting at 1 */ @@ -98,16 +104,15 @@ public int getReportedPosition() } /** - * Gets the position in the queue based on the queue's internal list - *
    - * As Asterisk doesn't send events when it shifts entries in the queue - * we'll base our positions on our internal queue entries ordered list. - * It should be coherent as entries are always added at the end of the queue - * and we don't mind if it is different from asterisk's view as long as the - * relative order stays the same. Most of the time the position will be the same - * but right after asterisk removes an entry it could differ as the shift occurs - * asynchronously in asterisk queues. As a consequence we might have temporary holes - * in the asterisk numbering. + * Gets the position in the queue based on the queue's internal list
    + * As Asterisk doesn't send events when it shifts entries in the queue we'll + * base our positions on our internal queue entries ordered list. It should + * be coherent as entries are always added at the end of the queue and we + * don't mind if it is different from asterisk's view as long as the + * relative order stays the same. Most of the time the position will be the + * same but right after asterisk removes an entry it could differ as the + * shift occurs asynchronously in asterisk queues. As a consequence we might + * have temporary holes in the asterisk numbering. * * @return the position of the entry in the respective queue, starting at 1 */ @@ -133,12 +138,12 @@ void setReportedPosition(int reportedPosition) @Override public String toString() { - StringBuilder sb; + StringBuilder sb; int systemHashcode; sb = new StringBuilder("AsteriskQueueEntry["); - synchronized (this) + try (LockCloser closer = Locker.lock(this)) { sb.append("dateJoined=").append(getDateJoined()).append(","); sb.append("postition=").append(getPosition()).append(","); @@ -148,7 +153,7 @@ public String toString() if (channel != null) { sb.append("channel=AsteriskChannel["); - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { sb.append("id='").append(channel.getId()).append("',"); sb.append("name='").append(channel.getName()).append("'],"); diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java index 13f53c2ab..e632974b5 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java @@ -30,6 +30,8 @@ import org.asteriskjava.live.AsteriskQueueListener; import org.asteriskjava.live.AsteriskQueueMember; import org.asteriskjava.util.AstUtil; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -84,10 +86,9 @@ public void run() private final List listeners; private final Map serviceLevelTimerTasks; - AsteriskQueueImpl(AsteriskServerImpl server, String name, Integer max, - String strategy, Integer serviceLevel, Integer weight, - Integer calls, Integer holdTime, Integer talkTime, - Integer completed, Integer abandoned, Double serviceLevelPerf) + AsteriskQueueImpl(AsteriskServerImpl server, String name, Integer max, String strategy, Integer serviceLevel, + Integer weight, Integer calls, Integer holdTime, Integer talkTime, Integer completed, Integer abandoned, + Double serviceLevelPerf) { super(server); this.name = name; @@ -131,18 +132,18 @@ public String getStrategy() } /** - * * @param max * @return true if value updated, false otherwise */ boolean setMax(Integer max) { - if(!AstUtil.isEqual(this.max, max)){ - this.max = max; - stampLastUpdate(); - return true; - } - return false; + if (!AstUtil.isEqual(this.max, max)) + { + this.max = max; + stampLastUpdate(); + return true; + } + return false; } public Integer getServiceLevel() @@ -151,140 +152,153 @@ public Integer getServiceLevel() } /** - * * @param serviceLevel * @return */ boolean setServiceLevel(Integer serviceLevel) { - if(!AstUtil.isEqual(this.serviceLevel, serviceLevel)){ - this.serviceLevel = serviceLevel; - stampLastUpdate(); - return true; - } - return false; + if (!AstUtil.isEqual(this.serviceLevel, serviceLevel)) + { + this.serviceLevel = serviceLevel; + stampLastUpdate(); + return true; + } + return false; } @Override - public Integer getCalls() { - return calls; - } + public Integer getCalls() + { + return calls; + } /** - * * @param calls - * @return true if value updated, false otherwise + * @return true if value updated, false otherwise */ - boolean setCalls(Integer calls) { - if(!AstUtil.isEqual(this.calls, calls)){ - this.calls = calls; - stampLastUpdate(); - return true; - } - return false; - } + boolean setCalls(Integer calls) + { + if (!AstUtil.isEqual(this.calls, calls)) + { + this.calls = calls; + stampLastUpdate(); + return true; + } + return false; + } @Override - public Integer getWaiting() { - return calls; + public Integer getWaiting() + { + return calls; } @Override - public Integer getHoldTime() { - return holdTime; - } + public Integer getHoldTime() + { + return holdTime; + } /** - * * @param holdTime * @return true if value updated, false otherwise */ - boolean setHoldTime(Integer holdTime) { - if(!AstUtil.isEqual(this.holdTime, holdTime)){ - this.holdTime = holdTime; - stampLastUpdate(); - return true; - } - return false; - } + boolean setHoldTime(Integer holdTime) + { + if (!AstUtil.isEqual(this.holdTime, holdTime)) + { + this.holdTime = holdTime; + stampLastUpdate(); + return true; + } + return false; + } @Override - public Integer getTalkTime() { - return talkTime; - } + public Integer getTalkTime() + { + return talkTime; + } /** - * * @param talkTime * @return true if value updated, false otherwise */ - boolean setTalkTime(Integer talkTime) { - if(!AstUtil.isEqual(this.talkTime, talkTime)){ - this.talkTime = talkTime; - stampLastUpdate(); - return true; - } - return false; - } + boolean setTalkTime(Integer talkTime) + { + if (!AstUtil.isEqual(this.talkTime, talkTime)) + { + this.talkTime = talkTime; + stampLastUpdate(); + return true; + } + return false; + } @Override - public Integer getCompleted() { - return completed; - } + public Integer getCompleted() + { + return completed; + } /** - * * @param completed - * @return true if value updated, false otherwise + * @return true if value updated, false otherwise */ - boolean setCompleted(Integer completed) { - if(!AstUtil.isEqual(this.completed, completed)){ - this.completed = completed; - stampLastUpdate(); - return true; - } - return false; - } + boolean setCompleted(Integer completed) + { + if (!AstUtil.isEqual(this.completed, completed)) + { + this.completed = completed; + stampLastUpdate(); + return true; + } + return false; + } @Override - public Integer getAbandoned() { - return abandoned; - } + public Integer getAbandoned() + { + return abandoned; + } /** - * * @param abandoned * @return true if value updated, false otherwise */ - boolean setAbandoned(Integer abandoned) { - if(!AstUtil.isEqual(this.abandoned, abandoned)){ - this.abandoned = abandoned; - stampLastUpdate(); - return true; - } - - return false; - } - - @Override - public Double getServiceLevelPerf() { - return serviceLevelPerf; - } - - /** - * - * @param serviceLevelPerf - * @return true if value updated, false otherwise - */ - boolean setServiceLevelPerf(Double serviceLevelPerf) { - if(!AstUtil.isEqual(this.serviceLevelPerf, serviceLevelPerf)){ - this.serviceLevelPerf = serviceLevelPerf; - stampLastUpdate(); - return true; - } - return false; - } + boolean setAbandoned(Integer abandoned) + { + if (!AstUtil.isEqual(this.abandoned, abandoned)) + { + this.abandoned = abandoned; + stampLastUpdate(); + return true; + } + + return false; + } + + @Override + public Double getServiceLevelPerf() + { + return serviceLevelPerf; + } + + /** + * @param serviceLevelPerf + * @return true if value updated, false otherwise + */ + boolean setServiceLevelPerf(Double serviceLevelPerf) + { + if (!AstUtil.isEqual(this.serviceLevelPerf, serviceLevelPerf)) + { + this.serviceLevelPerf = serviceLevelPerf; + stampLastUpdate(); + return true; + } + return false; + } public Integer getWeight() { @@ -292,37 +306,37 @@ public Integer getWeight() } /** - * * @param weight * @return true if value updated, false otherwise */ boolean setWeight(Integer weight) { - if(!AstUtil.isEqual(this.weight, weight)){ - this.weight = weight; - stampLastUpdate(); - return true; - } - return false; + if (!AstUtil.isEqual(this.weight, weight)) + { + this.weight = weight; + stampLastUpdate(); + return true; + } + return false; } public List getEntries() { - synchronized (entries) + try (LockCloser closer = Locker.lock(entries)) { return new ArrayList(entries); } } /** - * Shifts the position of the queue entries if needed - * (and fire PCE on queue entries if appropriate). + * Shifts the position of the queue entries if needed (and fire PCE on queue + * entries if appropriate). */ private void shift() { int currentPos = 1; // Asterisk starts at 1 - synchronized (entries) + try (LockCloser closer = Locker.lock(entries)) { for (AsteriskQueueEntryImpl qe : entries) { @@ -337,7 +351,8 @@ private void shift() } /** - * Creates a new AsteriskQueueEntry, adds it to this queue.

    + * Creates a new AsteriskQueueEntry, adds it to this queue. + *

    * Fires: *

      *
    • PCE on channel
    • @@ -346,27 +361,28 @@ private void shift() *
    • NewQueueEntry on server
    • *
    * - * @param channel the channel that joined the queue - * @param reportedPosition the position as given by Asterisk (currently not used) - * @param dateReceived the date the hannel joined the queue + * @param channel the channel that joined the queue + * @param reportedPosition the position as given by Asterisk (currently not + * used) + * @param dateReceived the date the hannel joined the queue */ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date dateReceived) { AsteriskQueueEntryImpl qe = new AsteriskQueueEntryImpl(server, this, channel, reportedPosition, dateReceived); - synchronized (entries) + try (LockCloser closer = Locker.lock(entries)) { - if (getEntry(channel.getName()) != null) - { - if (logger.isDebugEnabled()) - { - logger.debug("Ignored duplicate queue entry during population in queue " + name + " for channel " - + channel.getName()); - } - return; - } + if (getEntry(channel.getName()) != null) + { + if (logger.isDebugEnabled()) + { + logger.debug("Ignored duplicate queue entry during population in queue " + name + " for channel " + + channel.getName()); + } + return; + } - entries.add(qe); // at the end of the list + entries.add(qe); // at the end of the list // Keep the lock ! // This will fire PCE on the newly created queue entry @@ -374,20 +390,21 @@ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date date shift(); } - long delay = serviceLevel * 1000L; - if (delay > 0) - { - ServiceLevelTimerTask timerTask = new ServiceLevelTimerTask(qe); - timer.schedule(timerTask, delay); - synchronized (serviceLevelTimerTasks) - { - serviceLevelTimerTasks.put(qe, timerTask); - } - } + long delay = serviceLevel * 1000L; + if (delay > 0) + { + ServiceLevelTimerTask timerTask = new ServiceLevelTimerTask(qe); + timer.schedule(timerTask, delay); + try (LockCloser closer = Locker.lock(serviceLevelTimerTasks)) + { + serviceLevelTimerTasks.put(qe, timerTask); + } + } // Set the channel property ony here as queue entries and channels // maintain a reciprocal reference. - // That way property change on channel and new entry event on queue will be + // That way property change on channel and new entry event on queue will + // be // lanched when BOTH channel and queue are correctly set. channel.setQueueEntry(qe); fireNewEntry(qe); @@ -395,7 +412,8 @@ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date date } /** - * Removes the given queue entry from the queue.

    + * Removes the given queue entry from the queue. + *

    * Fires if needed: *

      *
    • PCE on channel
    • @@ -403,12 +421,12 @@ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date date *
    • PCE on other queue entries if shifted
    • *
    * - * @param entry an existing entry object. + * @param entry an existing entry object. * @param dateReceived the remove event was received. */ void removeEntry(AsteriskQueueEntryImpl entry, Date dateReceived) { - synchronized (serviceLevelTimerTasks) + try (LockCloser closer = Locker.lock(serviceLevelTimerTasks)) { if (serviceLevelTimerTasks.containsKey(entry)) { @@ -419,7 +437,7 @@ void removeEntry(AsteriskQueueEntryImpl entry, Date dateReceived) } boolean changed; - synchronized (entries) + try (LockCloser closer = Locker.lock(entries)) { changed = entries.remove(entry); @@ -457,11 +475,11 @@ public String toString() sb.append("abandoned='").append(getAbandoned()).append("',"); sb.append("serviceLevelPerf='").append(getServiceLevelPerf()).append("',"); - synchronized (entries) + try (LockCloser closer = Locker.lock(entries)) { sb.append("entries='").append(entries.toString()).append("',"); } - synchronized (members) + try (LockCloser closer = Locker.lock(members)) { sb.append("members='").append(members.toString()).append("',"); } @@ -473,7 +491,7 @@ public String toString() public void addAsteriskQueueListener(AsteriskQueueListener listener) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { listeners.add(listener); } @@ -481,7 +499,7 @@ public void addAsteriskQueueListener(AsteriskQueueListener listener) public void removeAsteriskQueueListener(AsteriskQueueListener listener) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { listeners.remove(listener); } @@ -494,7 +512,7 @@ public void removeAsteriskQueueListener(AsteriskQueueListener listener) */ void fireNewEntry(AsteriskQueueEntryImpl entry) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { for (AsteriskQueueListener listener : listeners) { @@ -517,7 +535,7 @@ void fireNewEntry(AsteriskQueueEntryImpl entry) */ void fireEntryLeave(AsteriskQueueEntryImpl entry) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { for (AsteriskQueueListener listener : listeners) { @@ -534,13 +552,14 @@ void fireEntryLeave(AsteriskQueueEntryImpl entry) } /** - * Notifies all registered listener that a member has been added to the queue. + * Notifies all registered listener that a member has been added to the + * queue. * * @param member added to the queue */ void fireMemberAdded(AsteriskQueueMemberImpl member) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { for (AsteriskQueueListener listener : listeners) { @@ -557,13 +576,14 @@ void fireMemberAdded(AsteriskQueueMemberImpl member) } /** - * Notifies all registered listener that a member has been removed from the queue. + * Notifies all registered listener that a member has been removed from the + * queue. * * @param member that has been removed. */ void fireMemberRemoved(AsteriskQueueMemberImpl member) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { for (AsteriskQueueListener listener : listeners) { @@ -587,7 +607,7 @@ void fireMemberRemoved(AsteriskQueueMemberImpl member) public Collection getMembers() { List listOfMembers = new ArrayList<>(members.size()); - synchronized (members) + try (LockCloser closer = Locker.lock(members)) { listOfMembers.addAll(members.values()); } @@ -602,7 +622,7 @@ public Collection getMembers() */ AsteriskQueueMemberImpl getMember(String location) { - synchronized (members) + try (LockCloser closer = Locker.lock(members)) { if (members.containsKey(location)) { @@ -619,7 +639,7 @@ AsteriskQueueMemberImpl getMember(String location) */ void addMember(AsteriskQueueMemberImpl member) { - synchronized (members) + try (LockCloser closer = Locker.lock(members)) { // Check if member already exists if (members.containsValue(member)) @@ -643,7 +663,7 @@ void addMember(AsteriskQueueMemberImpl member) AsteriskQueueMemberImpl getMemberByLocation(String location) { AsteriskQueueMemberImpl member; - synchronized (members) + try (LockCloser closer = Locker.lock(members)) { member = members.get(location); } @@ -661,7 +681,7 @@ AsteriskQueueMemberImpl getMemberByLocation(String location) */ void fireMemberStateChanged(AsteriskQueueMemberImpl member) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { for (AsteriskQueueListener listener : listeners) { @@ -685,7 +705,7 @@ void fireMemberStateChanged(AsteriskQueueMemberImpl member) */ AsteriskQueueEntryImpl getEntry(String channelName) { - synchronized (entries) + try (LockCloser closer = Locker.lock(entries)) { for (AsteriskQueueEntryImpl entry : entries) { @@ -698,7 +718,6 @@ AsteriskQueueEntryImpl getEntry(String channelName) return null; } - /** * Removes a member from this queue. * @@ -706,7 +725,7 @@ AsteriskQueueEntryImpl getEntry(String channelName) */ public void removeMember(AsteriskQueueMemberImpl member) { - synchronized (members) + try (LockCloser closer = Locker.lock(members)) { // Check if member exists if (!members.containsValue(member)) @@ -714,8 +733,7 @@ public void removeMember(AsteriskQueueMemberImpl member) return; } // If so, remove the member. - logger.info("Remove member from the queue " + getName() + ": " - + member.toString()); + logger.info("Remove member from the queue " + getName() + ": " + member.toString()); members.remove(member.getLocation()); } @@ -724,7 +742,7 @@ public void removeMember(AsteriskQueueMemberImpl member) void fireServiceLevelExceeded(AsteriskQueueEntry entry) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { for (AsteriskQueueListener listener : listeners) { @@ -751,7 +769,7 @@ AsteriskQueueEntryImpl getEntry(int position) // positions in asterisk start at 1, but list starts at 0 position--; AsteriskQueueEntryImpl foundEntry = null; - synchronized (entries) + try (LockCloser closer = Locker.lock(entries)) { try { @@ -760,7 +778,8 @@ AsteriskQueueEntryImpl getEntry(int position) catch (IndexOutOfBoundsException e) { // For consistency with the above method, - // swallow. We might indeed request the 1st one from time to time + // swallow. We might indeed request the 1st one from time to + // time } // NOPMD } return foundEntry; diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java index 0831b6290..e4b846c1a 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java @@ -27,6 +27,8 @@ import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.AstUtil; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; /** * Default implementation of a queue member. @@ -212,64 +214,79 @@ public String toString() return sb.toString(); } - synchronized boolean stateChanged(QueueMemberState state) + boolean stateChanged(QueueMemberState state) { - if (!AstUtil.isEqual(this.state, state)) + try (LockCloser closer = Locker.lock(this)) { - QueueMemberState oldState = this.state; - this.state = state; - firePropertyChange(PROPERTY_STATE, oldState, state); - return true; + if (!AstUtil.isEqual(this.state, state)) + { + QueueMemberState oldState = this.state; + this.state = state; + firePropertyChange(PROPERTY_STATE, oldState, state); + return true; + } + return false; } - return false; } - synchronized boolean penaltyChanged(Integer penalty) + boolean penaltyChanged(Integer penalty) { - if (!AstUtil.isEqual(this.penalty, penalty)) + try (LockCloser closer = Locker.lock(this)) { - Integer oldPenalty = this.penalty; - this.penalty = penalty; - firePropertyChange(PROPERTY_PENALTY, oldPenalty, penalty); - return true; - } + if (!AstUtil.isEqual(this.penalty, penalty)) + { + Integer oldPenalty = this.penalty; + this.penalty = penalty; + firePropertyChange(PROPERTY_PENALTY, oldPenalty, penalty); + return true; + } - return false; + return false; + } } - synchronized boolean pausedChanged(boolean paused) + boolean pausedChanged(boolean paused) { - if (!AstUtil.isEqual(this.paused, paused)) + try (LockCloser closer = Locker.lock(this)) { - boolean oldPaused = this.paused; - this.paused = paused; - firePropertyChange(PROPERTY_PAUSED, oldPaused, paused); - return true; + if (!AstUtil.isEqual(this.paused, paused)) + { + boolean oldPaused = this.paused; + this.paused = paused; + firePropertyChange(PROPERTY_PAUSED, oldPaused, paused); + return true; + } + return false; } - return false; } - synchronized boolean callsTakenChanged(Integer callsTaken) + boolean callsTakenChanged(Integer callsTaken) { - if (!AstUtil.isEqual(this.callsTaken, callsTaken)) + try (LockCloser closer = Locker.lock(this)) { - Integer oldcallsTaken = this.callsTaken; - this.callsTaken = callsTaken; - firePropertyChange(PROPERTY_CALLSTAKEN, oldcallsTaken, callsTaken); - return true; + if (!AstUtil.isEqual(this.callsTaken, callsTaken)) + { + Integer oldcallsTaken = this.callsTaken; + this.callsTaken = callsTaken; + firePropertyChange(PROPERTY_CALLSTAKEN, oldcallsTaken, callsTaken); + return true; + } + return false; } - return false; } - synchronized boolean lastCallChanged(Long lastCall) + boolean lastCallChanged(Long lastCall) { - if (!AstUtil.isEqual(this.lastCall, lastCall)) + try (LockCloser closer = Locker.lock(this)) { - Long oldlastCall = this.lastCall; - this.lastCall = lastCall; - firePropertyChange(PROPERTY_LASTCALL, oldlastCall, lastCall); - return true; + if (!AstUtil.isEqual(this.lastCall, lastCall)) + { + Long oldlastCall = this.lastCall; + this.lastCall = lastCall; + firePropertyChange(PROPERTY_LASTCALL, oldlastCall, lastCall); + return true; + } + return false; } - return false; } } diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java index 1241934d3..9c84a3f70 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java @@ -65,7 +65,48 @@ import org.asteriskjava.manager.action.OriginateAction; import org.asteriskjava.manager.action.SetVarAction; import org.asteriskjava.manager.action.SipPeersAction; -import org.asteriskjava.manager.event.*; +import org.asteriskjava.manager.event.AbstractMeetMeEvent; +import org.asteriskjava.manager.event.AgentCallbackLoginEvent; +import org.asteriskjava.manager.event.AgentCallbackLogoffEvent; +import org.asteriskjava.manager.event.AgentCalledEvent; +import org.asteriskjava.manager.event.AgentCompleteEvent; +import org.asteriskjava.manager.event.AgentConnectEvent; +import org.asteriskjava.manager.event.AgentLoginEvent; +import org.asteriskjava.manager.event.AgentLogoffEvent; +import org.asteriskjava.manager.event.AgentsEvent; +import org.asteriskjava.manager.event.BridgeEvent; +import org.asteriskjava.manager.event.CdrEvent; +import org.asteriskjava.manager.event.ConnectEvent; +import org.asteriskjava.manager.event.DbGetResponseEvent; +import org.asteriskjava.manager.event.DialEvent; +import org.asteriskjava.manager.event.DisconnectEvent; +import org.asteriskjava.manager.event.DtmfEvent; +import org.asteriskjava.manager.event.HangupEvent; +import org.asteriskjava.manager.event.JoinEvent; +import org.asteriskjava.manager.event.LeaveEvent; +import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.MonitorStartEvent; +import org.asteriskjava.manager.event.MonitorStopEvent; +import org.asteriskjava.manager.event.NewCallerIdEvent; +import org.asteriskjava.manager.event.NewChannelEvent; +import org.asteriskjava.manager.event.NewExtenEvent; +import org.asteriskjava.manager.event.NewStateEvent; +import org.asteriskjava.manager.event.OriginateResponseEvent; +import org.asteriskjava.manager.event.ParkedCallEvent; +import org.asteriskjava.manager.event.ParkedCallGiveUpEvent; +import org.asteriskjava.manager.event.ParkedCallTimeOutEvent; +import org.asteriskjava.manager.event.PeerEntryEvent; +import org.asteriskjava.manager.event.QueueCallerJoinEvent; +import org.asteriskjava.manager.event.QueueCallerLeaveEvent; +import org.asteriskjava.manager.event.QueueMemberAddedEvent; +import org.asteriskjava.manager.event.QueueMemberPausedEvent; +import org.asteriskjava.manager.event.QueueMemberPenaltyEvent; +import org.asteriskjava.manager.event.QueueMemberRemovedEvent; +import org.asteriskjava.manager.event.QueueMemberStatusEvent; +import org.asteriskjava.manager.event.RenameEvent; +import org.asteriskjava.manager.event.ResponseEvent; +import org.asteriskjava.manager.event.UnparkedCallEvent; +import org.asteriskjava.manager.event.VarSetEvent; import org.asteriskjava.manager.response.CommandResponse; import org.asteriskjava.manager.response.GetConfigResponse; import org.asteriskjava.manager.response.MailboxCountResponse; @@ -74,6 +115,8 @@ import org.asteriskjava.manager.response.ModuleCheckResponse; import org.asteriskjava.util.AstUtil; import org.asteriskjava.util.DateUtil; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -230,59 +273,62 @@ public void initialize() throws ManagerCommunicationException initializeIfNeeded(); } - private synchronized void initializeIfNeeded() throws ManagerCommunicationException + private void initializeIfNeeded() throws ManagerCommunicationException { - if (initialized || initializing) + try (LockCloser closer = Locker.lock(this)) { - return; - } - if (asyncEventHandling && managerEventListenerProxy == null) - { - managerEventListenerProxy = new ManagerEventListenerProxy(this); - eventConnection.addEventListener(managerEventListenerProxy); - } - else if (!asyncEventHandling && eventListener == null) - { - eventListener = this; - eventConnection.addEventListener(eventListener); - } + if (initialized || initializing) + { + return; + } + if (asyncEventHandling && managerEventListenerProxy == null) + { + managerEventListenerProxy = new ManagerEventListenerProxy(this); + eventConnection.addEventListener(managerEventListenerProxy); + } + else if (!asyncEventHandling && eventListener == null) + { + eventListener = this; + eventConnection.addEventListener(eventListener); + } - initializing = true; + initializing = true; - if (eventConnection.getState() == ManagerConnectionState.INITIAL - || eventConnection.getState() == ManagerConnectionState.DISCONNECTED) - { - try + if (eventConnection.getState() == ManagerConnectionState.INITIAL + || eventConnection.getState() == ManagerConnectionState.DISCONNECTED) { - eventConnection.login(); + try + { + eventConnection.login(); + } + catch (Exception e) + { + throw new ManagerCommunicationException("Unable to login: " + e.getMessage(), e); + } } - catch (Exception e) + + channelManager.initialize(); + agentManager.initialize(); + meetMeManager.initialize(); + if (!skipQueues) { - throw new ManagerCommunicationException("Unable to login: " + e.getMessage(), e); + queueManager.initialize(); } - } - channelManager.initialize(); - agentManager.initialize(); - meetMeManager.initialize(); - if (!skipQueues) - { - queueManager.initialize(); - } - - if (asyncEventHandling && managerEventListenerProxy == null) - { - managerEventListenerProxy = new ManagerEventListenerProxy(this); - eventConnection.addEventListener(managerEventListenerProxy); - } - else if (!asyncEventHandling && eventListener == null) - { - eventListener = this; - eventConnection.addEventListener(eventListener); + if (asyncEventHandling && managerEventListenerProxy == null) + { + managerEventListenerProxy = new ManagerEventListenerProxy(this); + eventConnection.addEventListener(managerEventListenerProxy); + } + else if (!asyncEventHandling && eventListener == null) + { + eventListener = this; + eventConnection.addEventListener(eventListener); + } + logger.info("Initializing done"); + initializing = false; + initialized = true; } - logger.info("Initializing done"); - initializing = false; - initialized = true; } /* Implementation of the AsteriskServer interface */ @@ -457,7 +503,7 @@ public void originateAsync(OriginateAction originateAction, OriginateCallback cb callbackData = new OriginateCallbackData(originateAction, DateUtil.getDate(), cb); // register callback - synchronized (originateCallbacks) + try (LockCloser closer = Locker.lock(originateCallbacks)) { originateCallbacks.put(traceId, callbackData); } @@ -517,41 +563,44 @@ public List getQueuesUpdatedAfter(Date date) return queueManager.getQueuesUpdatedAfter(date); } - public synchronized String getVersion() throws ManagerCommunicationException + public String getVersion() throws ManagerCommunicationException { - final ManagerResponse response; - final String command; - - initializeIfNeeded(); - if (version == null) + try (LockCloser closer = Locker.lock(this)) { - if (eventConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) - { - command = SHOW_VERSION_1_6_COMMAND; - } - else - { - command = SHOW_VERSION_COMMAND; - } + final ManagerResponse response; + final String command; - response = sendAction(new CommandAction(command)); - if (response instanceof CommandResponse) + initializeIfNeeded(); + if (version == null) { - final List result; + if (eventConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) + { + command = SHOW_VERSION_1_6_COMMAND; + } + else + { + command = SHOW_VERSION_COMMAND; + } - result = ((CommandResponse) response).getResult(); - if (!result.isEmpty()) + response = sendAction(new CommandAction(command)); + if (response instanceof CommandResponse) { - version = result.get(0); + final List result; + + result = ((CommandResponse) response).getResult(); + if (!result.isEmpty()) + { + version = result.get(0); + } + } + else + { + logger.error("Response to CommandAction(\"" + command + "\") was not a CommandResponse but " + response); } } - else - { - logger.error("Response to CommandAction(\"" + command + "\") was not a CommandResponse but " + response); - } - } - return version; + return version; + } } public int[] getVersion(String file) throws ManagerCommunicationException @@ -616,7 +665,7 @@ public int[] getVersion(String file) throws ManagerCommunicationException } else { - synchronized (versions) + try (LockCloser closer = Locker.lock(versions)) { fileVersion = versions.get(file); } @@ -847,7 +896,7 @@ public ConfigFile getConfig(String filename) throws ManagerCommunicationExceptio public void addAsteriskServerListener(AsteriskServerListener listener) throws ManagerCommunicationException { initializeIfNeeded(); - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { if (!listeners.contains(listener)) { @@ -859,7 +908,7 @@ public void addAsteriskServerListener(AsteriskServerListener listener) throws Ma @Override public void removeAsteriskServerListener(AsteriskServerListener listener) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { listeners.remove(listener); } @@ -873,7 +922,7 @@ public boolean isAsteriskServerListening(AsteriskServerListener listener) public void addChainListener(ManagerEventListener chainListener) { - synchronized (this.chainListeners) + try (LockCloser closer = Locker.lock(this.chainListeners)) { if (!this.chainListeners.contains(chainListener)) this.chainListeners.add(chainListener); @@ -888,7 +937,7 @@ public void removeChainListener(ManagerEventListener chainListener) void fireNewAsteriskChannel(AsteriskChannel channel) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { for (AsteriskServerListener listener : listeners) { @@ -906,7 +955,7 @@ void fireNewAsteriskChannel(AsteriskChannel channel) void fireNewMeetMeUser(MeetMeUser user) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { for (AsteriskServerListener listener : listeners) { @@ -962,7 +1011,7 @@ ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws Ma ResponseEvents - sendEventGeneratingAction(EventGeneratingAction action, long timeout) throws ManagerCommunicationException + sendEventGeneratingAction(EventGeneratingAction action, long timeout) throws ManagerCommunicationException { // return connectionPool.sendEventGeneratingAction(action, timeout); try @@ -977,7 +1026,7 @@ ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws Ma OriginateCallbackData getOriginateCallbackDataByTraceId(String traceId) { - synchronized (originateCallbacks) + try (LockCloser closer = Locker.lock(originateCallbacks)) { return originateCallbacks.get(traceId); } @@ -1101,14 +1150,14 @@ else if (event instanceof QueueMemberPausedEvent) { queueManager.handleQueueMemberPausedEvent((QueueMemberPausedEvent) event); } - else if (event instanceof QueueCallerJoinEvent) - { - queueManager.handleJoinEvent((QueueCallerJoinEvent) event); - } - else if (event instanceof QueueCallerLeaveEvent) - { - queueManager.handleLeaveEvent((QueueCallerLeaveEvent) event); - } + else if (event instanceof QueueCallerJoinEvent) + { + queueManager.handleJoinEvent((QueueCallerJoinEvent) event); + } + else if (event instanceof QueueCallerLeaveEvent) + { + queueManager.handleLeaveEvent((QueueCallerLeaveEvent) event); + } // >>>>>> AJ 94 // Handle meetMeEvents else if (event instanceof AbstractMeetMeEvent) @@ -1165,7 +1214,7 @@ else if (event instanceof AgentLogoffEvent) */ private void fireChainListeners(ManagerEvent event) { - synchronized (this.chainListeners) + try (LockCloser closer = Locker.lock(this.chainListeners)) { for (ManagerEventListener listener : this.chainListeners) listener.onManagerEvent(event); @@ -1238,7 +1287,7 @@ private void handleOriginateEvent(OriginateResponseEvent originateEvent) return; } - synchronized (originateCallbacks) + try (LockCloser closer = Locker.lock(originateCallbacks)) { callbackData = originateCallbacks.get(traceId); if (callbackData == null) @@ -1414,7 +1463,7 @@ public Collection getAgents() throws ManagerCommunicationExceptio void fireNewAgent(AsteriskAgentImpl agent) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { for (AsteriskServerListener listener : listeners) { @@ -1432,7 +1481,7 @@ void fireNewAgent(AsteriskAgentImpl agent) void fireNewQueueEntry(AsteriskQueueEntry entry) { - synchronized (listeners) + try (LockCloser closer = Locker.lock(listeners)) { for (AsteriskServerListener listener : listeners) { diff --git a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java index cf97155f7..6a933bdd9 100644 --- a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java +++ b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java @@ -59,6 +59,8 @@ import org.asteriskjava.manager.event.VarSetEvent; import org.asteriskjava.util.DaemonThreadFactory; import org.asteriskjava.util.DateUtil; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -108,7 +110,7 @@ void initialize(List variables) throws ManagerCommunicationException ResponseEvents re; shutdown(); - + traceScheduledExecutorService = new ScheduledThreadPoolExecutor(1, new DaemonThreadFactory());// Executors.newSingleThreadScheduledExecutor StatusAction sa = new StatusAction(); @@ -122,28 +124,27 @@ void initialize(List variables) throws ManagerCommunicationException } } logger.debug("ChannelManager has been initialised"); - + } void disconnected() { - shutdown(); - logger.debug("ChannelManager has been disconnected from Asterisk."); - } - + shutdown(); + logger.debug("ChannelManager has been disconnected from Asterisk."); + } + private void shutdown() { if (traceScheduledExecutorService != null) { traceScheduledExecutorService.shutdown(); } - synchronized (channels) + try (LockCloser closer = Locker.lock(channels)) { channels.clear(); } - - } + } /** * Returns a collection of all active AsteriskChannels. @@ -154,7 +155,7 @@ Collection getChannels() { Collection copy; - synchronized (channels) + try (LockCloser closer = Locker.lock(channels)) { copy = new ArrayList<>(channels.size() + 2); for (AsteriskChannel channel : channels.values()) @@ -170,7 +171,7 @@ Collection getChannels() private void addChannel(AsteriskChannelImpl channel) { - synchronized (channels) + try (LockCloser closer = Locker.lock(channels)) { channels.put(channel.getId(), channel); } @@ -184,7 +185,7 @@ private void removeOldChannels() { Iterator i; - synchronized (channels) + try (LockCloser closer = Locker.lock(channels)) { i = channels.values().iterator(); while (i.hasNext()) @@ -315,7 +316,7 @@ void handleStatusEvent(StatusEvent event) extension = new Extension(event.getContext(), event.getExtension(), event.getPriority()); } - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.setCallerId(new CallerId(event.getCallerIdName(), event.getCallerIdNum())); channel.setAccount(event.getAccountCode()); @@ -332,7 +333,7 @@ void handleStatusEvent(StatusEvent event) { // the date used here is not correct! channel.channelLinked(event.getDateReceived(), linkedChannel); - synchronized (linkedChannel) + try (LockCloser closer2 = Locker.lock(linkedChannel)) { linkedChannel.channelLinked(event.getDateReceived(), channel); } @@ -367,7 +368,7 @@ AsteriskChannelImpl getChannelImplByName(String name) return null; } - synchronized (channels) + try (LockCloser closer = Locker.lock(channels)) { for (AsteriskChannelImpl tmp : channels.values()) { @@ -411,7 +412,7 @@ AsteriskChannelImpl getChannelImplByNameAndActive(String name) return null; } - synchronized (channels) + try (LockCloser closer = Locker.lock(channels)) { for (AsteriskChannelImpl tmp : channels.values()) { @@ -431,7 +432,7 @@ AsteriskChannelImpl getChannelImplById(String uniqueId) return null; } - synchronized (channels) + try (LockCloser closer = Locker.lock(channels)) { return channels.get(uniqueId); } @@ -500,7 +501,7 @@ void handleNewChannelEvent(NewChannelEvent event) else { // channel had already been created probably by a NewCallerIdEvent - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.nameChanged(event.getDateReceived(), event.getChannel()); channel.setCallerId(new CallerId(event.getCallerIdName(), event.getCallerIdNum())); @@ -524,7 +525,7 @@ void handleNewExtenEvent(NewExtenEvent event) extension = new Extension(event.getContext(), event.getExtension(), event.getPriority(), event.getApplication(), event.getAppData()); - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.extensionVisited(event.getDateReceived(), extension); } @@ -543,7 +544,7 @@ private void idChanged(AsteriskChannelImpl channel, AbstractChannelEvent event) } logger.info("Changing unique_id for '" + channel.getName() + "' from " + oldId + " to " + newId + " < " + event); - synchronized (channels) + try (LockCloser closer = Locker.lock(channels)) { channels.remove(oldId); channels.put(newId, channel); @@ -612,7 +613,7 @@ void handleNewStateEvent(NewStateEvent event) { logger.info("Renaming channel (following NewStateEvent) '" + channel.getName() + "' to '" + event.getChannel() + "'"); - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.nameChanged(event.getDateReceived(), event.getChannel()); } @@ -621,7 +622,7 @@ void handleNewStateEvent(NewStateEvent event) if (event.getChannelState() != null) { - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.stateChanged(event.getDateReceived(), ChannelState.valueOf(event.getChannelState())); } @@ -648,7 +649,7 @@ void handleNewCallerIdEvent(NewCallerIdEvent event) } } - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.setCallerId(new CallerId(event.getCallerIdName(), event.getCallerIdNum())); } @@ -670,7 +671,7 @@ void handleHangupEvent(HangupEvent event) cause = HangupCause.getByCode(event.getCause()); } - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.hungup(event.getDateReceived(), cause, event.getCauseTxt()); } @@ -709,11 +710,11 @@ void handleDialEvent(DialEvent event) logger.info(sourceChannel.getName() + " dialed " + destinationChannel.getName()); getTraceId(sourceChannel); getTraceId(destinationChannel); - synchronized (sourceChannel) + try (LockCloser closer = Locker.lock(sourceChannel)) { sourceChannel.channelDialed(event.getDateReceived(), destinationChannel); } - synchronized (destinationChannel) + try (LockCloser closer = Locker.lock(destinationChannel)) { destinationChannel.channelDialing(event.getDateReceived(), sourceChannel); } @@ -738,12 +739,12 @@ void handleBridgeEvent(BridgeEvent event) if (event.isLink()) { logger.info("Linking channels " + channel1.getName() + " and " + channel2.getName()); - synchronized (channel1) + try (LockCloser closer = Locker.lock(channel1)) { channel1.channelLinked(event.getDateReceived(), channel2); } - synchronized (channel2) + try (LockCloser closer = Locker.lock(channel2)) { channel2.channelLinked(event.getDateReceived(), channel1); } @@ -752,12 +753,12 @@ void handleBridgeEvent(BridgeEvent event) if (event.isUnlink()) { logger.info("Unlinking channels " + channel1.getName() + " and " + channel2.getName()); - synchronized (channel1) + try (LockCloser closer = Locker.lock(channel1)) { channel1.channelUnlinked(event.getDateReceived()); } - synchronized (channel2) + try (LockCloser closer = Locker.lock(channel2)) { channel2.channelUnlinked(event.getDateReceived()); } @@ -776,7 +777,7 @@ void handleRenameEvent(RenameEvent event) logger.info("Renaming channel '" + channel.getName() + "' to '" + event.getNewname() + "', uniqueId is " + event.getUniqueId()); - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.nameChanged(event.getDateReceived(), event.getNewname()); } @@ -796,7 +797,7 @@ void handleCdrEvent(CdrEvent event) cdr = new CallDetailRecordImpl(channel, destinationChannel, event); - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.callDetailRecordReceived(event.getDateReceived(), cdr); } @@ -832,9 +833,10 @@ void handleParkedCallEvent(ParkedCallEvent event) return; } - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { - Extension ext = new Extension(null, (event.getParkingSpace() != null) ? event.getParkingSpace() : event.getExten(), 1); + Extension ext = new Extension(null, + (event.getParkingSpace() != null) ? event.getParkingSpace() : event.getExten(), 1); String parkinglot = event.getParkingLot(); channel.setParkedAt(ext, parkinglot); logger.info("Channel " + channel.getName() + " is parked at " + channel.getParkedAt().getExtension()); @@ -861,7 +863,7 @@ void handleParkedCallGiveUpEvent(ParkedCallGiveUpEvent event) return; } - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.setParkedAt(null, null); } @@ -888,7 +890,7 @@ void handleParkedCallTimeOutEvent(ParkedCallTimeOutEvent event) return; } - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.setParkedAt(null, null); } @@ -915,7 +917,7 @@ void handleUnparkedCallEvent(UnparkedCallEvent event) return; } - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.setParkedAt(null, null); } @@ -936,7 +938,7 @@ void handleVarSetEvent(VarSetEvent event) return; } - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.updateVariable(event.getVariable(), event.getValue()); } @@ -972,7 +974,7 @@ void handleDtmfEvent(DtmfEvent event) dtmfDigit = event.getDigit().charAt(0); } - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { if (event.isReceived()) { @@ -1003,7 +1005,7 @@ void handleMonitorStartEvent(MonitorStartEvent event) return; } - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.setMonitored(true); } @@ -1028,7 +1030,7 @@ void handleMonitorStopEvent(MonitorStopEvent event) return; } - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { channel.setMonitored(false); } diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java b/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java index ffe49497f..a54e3f596 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java @@ -35,6 +35,8 @@ import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.DateUtil; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -66,7 +68,7 @@ class MeetMeManager void initialize() { - synchronized (rooms) + try (LockCloser closer = Locker.lock(rooms)) { for (MeetMeRoomImpl room : rooms.values()) { @@ -78,7 +80,7 @@ void initialize() void disconnected() { /* - * synchronized (rooms) { rooms.clear(); } + * try (LockCloser closer = Locker2.lock(rooms) { rooms.clear(); } */ } @@ -87,7 +89,7 @@ Collection getMeetMeRooms() final Collection result; result = new ArrayList<>(); - synchronized (rooms) + try (LockCloser closer = Locker.lock(rooms)) { for (MeetMeRoom room : rooms.values()) { @@ -380,7 +382,7 @@ MeetMeRoomImpl getOrCreateRoomImpl(String roomNumber) MeetMeRoomImpl room; boolean created = false; - synchronized (rooms) + try (LockCloser closer = Locker.lock(rooms)) { room = rooms.get(roomNumber); if (room == null) diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java b/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java index 026d155d7..eacf1f613 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java @@ -25,6 +25,8 @@ import org.asteriskjava.live.MeetMeRoom; import org.asteriskjava.live.MeetMeUser; import org.asteriskjava.manager.action.CommandAction; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; /** * Default implementation of the MeetMeRoom interface. @@ -36,7 +38,7 @@ class MeetMeRoomImpl extends AbstractLiveObject implements MeetMeRoom private static final String UNLOCK_COMMAND = "unlock"; private final String roomNumber; - + /** * Maps userNumber to user. */ @@ -56,7 +58,7 @@ public String getRoomNumber() public Collection getUsers() { - synchronized (users) + try (LockCloser closer = Locker.lock(users)) { return new ArrayList(users.values()); } @@ -64,7 +66,7 @@ public Collection getUsers() public boolean isEmpty() { - synchronized (users) + try (LockCloser closer = Locker.lock(users)) { return users.isEmpty(); } @@ -72,15 +74,15 @@ public boolean isEmpty() Collection getUserImpls() { - synchronized (users) + try (LockCloser closer = Locker.lock(users)) { return new ArrayList<>(users.values()); } } - + void addUser(MeetMeUserImpl user) { - synchronized (users) + try (LockCloser closer = Locker.lock(users)) { users.put(user.getUserNumber(), user); } @@ -88,7 +90,7 @@ void addUser(MeetMeUserImpl user) MeetMeUserImpl getUser(Integer userNumber) { - synchronized (users) + try (LockCloser closer = Locker.lock(users)) { return users.get(userNumber); } @@ -96,7 +98,7 @@ MeetMeUserImpl getUser(Integer userNumber) void removeUser(MeetMeUserImpl user) { - synchronized (users) + try (LockCloser closer = Locker.lock(users)) { users.remove(user.getUserNumber()); } @@ -127,14 +129,14 @@ private void sendMeetMeCommand(String command) throws ManagerCommunicationExcept } @Override - public String toString() + public String toString() { - StringBuilder sb; + StringBuilder sb; int systemHashcode; sb = new StringBuilder("MeetMeRoom["); - synchronized (this) + try (LockCloser closer = Locker.lock(this)) { sb.append("roomNumber='").append(getRoomNumber()).append("',"); systemHashcode = System.identityHashCode(this); diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java b/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java index 9b2b5f501..a8837b04c 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java @@ -22,6 +22,8 @@ import org.asteriskjava.live.MeetMeUser; import org.asteriskjava.live.MeetMeUserState; import org.asteriskjava.manager.action.CommandAction; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; class MeetMeUserImpl extends AbstractLiveObject implements MeetMeUser { @@ -40,8 +42,8 @@ class MeetMeUserImpl extends AbstractLiveObject implements MeetMeUser private boolean talking; private boolean muted; - MeetMeUserImpl(AsteriskServerImpl server, MeetMeRoomImpl room, Integer userNumber, - AsteriskChannelImpl channel, Date dateJoined) + MeetMeUserImpl(AsteriskServerImpl server, MeetMeRoomImpl room, Integer userNumber, AsteriskChannelImpl channel, + Date dateJoined) { super(server); this.room = room; @@ -77,14 +79,15 @@ public Date getDateLeft() } /** - * Sets the status to {@link MeetMeUserState#LEFT} and dateLeft to the given date. + * Sets the status to {@link MeetMeUserState#LEFT} and dateLeft to the given + * date. * * @param dateLeft the date this user left the room. */ void left(Date dateLeft) { MeetMeUserState oldState; - synchronized (this) + try (LockCloser closer = Locker.lock(this)) { oldState = this.state; this.dateLeft = dateLeft; @@ -152,16 +155,16 @@ private void sendMeetMeUserCommand(String command) throws ManagerCommunicationEx server.sendAction(new CommandAction(sb.toString())); } - + @Override - public String toString() + public String toString() { - StringBuilder sb; + StringBuilder sb; int systemHashcode; sb = new StringBuilder("MeetMeUser["); - synchronized (this) + try (LockCloser closer = Locker.lock(this)) { sb.append("dateJoined='").append(getDateJoined()).append("',"); sb.append("dateLeft='").append(getDateLeft()).append("',"); @@ -171,7 +174,7 @@ public String toString() systemHashcode = System.identityHashCode(this); } sb.append("channel=AsteriskChannel["); - synchronized (channel) + try (LockCloser closer = Locker.lock(channel)) { sb.append("id='").append(channel.getId()).append("',"); sb.append("name='").append(channel.getName()).append("'],"); diff --git a/src/main/java/org/asteriskjava/live/internal/QueueManager.java b/src/main/java/org/asteriskjava/live/internal/QueueManager.java index 40b464348..b17cb6ff0 100644 --- a/src/main/java/org/asteriskjava/live/internal/QueueManager.java +++ b/src/main/java/org/asteriskjava/live/internal/QueueManager.java @@ -44,6 +44,8 @@ import org.asteriskjava.manager.event.QueueMemberRemovedEvent; import org.asteriskjava.manager.event.QueueMemberStatusEvent; import org.asteriskjava.manager.event.QueueParamsEvent; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -172,7 +174,7 @@ else if (event instanceof QueueEntryEvent) void disconnected() { - synchronized (queuesLRU) + try (LockCloser closer = Locker.lock(queuesLRU)) { for (AsteriskQueueImpl queue : queuesLRU.values()) { @@ -193,7 +195,7 @@ Collection getQueues() Collection copy; - synchronized (queuesLRU) + try (LockCloser closer = Locker.lock(queuesLRU)) { copy = new ArrayList(queuesLRU.values()); } @@ -205,7 +207,7 @@ public List getQueuesUpdatedAfter(Date date) refreshQueuesIfForced(); List copy = new ArrayList<>(); - synchronized (queuesLRU) + try (LockCloser closer = Locker.lock(queuesLRU)) { List> list = new ArrayList<>(queuesLRU.entrySet()); ListIterator> iter = list.listIterator(list.size()); @@ -234,7 +236,7 @@ public List getQueuesUpdatedAfter(Date date) */ private void addQueue(AsteriskQueueImpl queue) { - synchronized (queuesLRU) + try (LockCloser closer = Locker.lock(queuesLRU)) { queuesLRU.put(queue.getName(), queue); } @@ -275,9 +277,9 @@ private void handleQueueParamsEvent(QueueParamsEvent event) // We should never reach that code as this method is only called for // initialization // So the queue should never be in the queues list - synchronized (queue) + try (LockCloser closer = Locker.lock(queue)) { - synchronized (queuesLRU) + try (LockCloser closer2 = Locker.lock(queuesLRU)) { if (queue.setMax(max) | queue.setServiceLevel(serviceLevel) | queue.setWeight(weight) @@ -368,36 +370,37 @@ private void handleQueueEntryEvent(QueueEntryEvent event) queue.createNewEntry(channel, reportedPosition, event.getDateReceived()); } - /** - * + * Called from AsteriskServerImpl whenever a new entry appears in a queue. - * + * - * + * @param event the JoinEvent received - * + - */ - void handleJoinEvent(QueueCallerJoinEvent event) { - final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); - final AsteriskChannelImpl channel = channelManager.getChannelImplByName(event.getChannel()); - - if (queue == null) { - logger.error("Ignored JoinEvent for unknown queue " + event.getQueue()); - return; - } - if (channel == null) { - logger.error("Ignored JoinEvent for unknown channel " + event.getChannel()); - return; - } - - // Asterisk gives us an initial position but doesn't tell us when he - // shifts the others - // We won't use this data for ordering until there is a appropriate - // event in AMI. - // (and refreshing the whole queue is too intensive and suffers - // incoherencies - // due to asynchronous shift that leaves holes if requested too fast) - int reportedPosition = event.getPosition(); - - queue.createNewEntry(channel, reportedPosition, event.getDateReceived()); - } + /** + * + * Called from AsteriskServerImpl whenever a new entry appears in a + * queue. + * + * @param event the JoinEvent received + + */ + void handleJoinEvent(QueueCallerJoinEvent event) + { + final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); + final AsteriskChannelImpl channel = channelManager.getChannelImplByName(event.getChannel()); + + if (queue == null) + { + logger.error("Ignored JoinEvent for unknown queue " + event.getQueue()); + return; + } + if (channel == null) + { + logger.error("Ignored JoinEvent for unknown channel " + event.getChannel()); + return; + } + + // Asterisk gives us an initial position but doesn't tell us when he + // shifts the others + // We won't use this data for ordering until there is a appropriate + // event in AMI. + // (and refreshing the whole queue is too intensive and suffers + // incoherencies + // due to asynchronous shift that leaves holes if requested too fast) + int reportedPosition = event.getPosition(); + + queue.createNewEntry(channel, reportedPosition, event.getDateReceived()); + } /** * Called from AsteriskServerImpl whenever a new entry appears in a queue. @@ -432,33 +435,37 @@ void handleJoinEvent(JoinEvent event) queue.createNewEntry(channel, reportedPosition, event.getDateReceived()); } - /** - * Called from AsteriskServerImpl whenever an enty leaves a queue. - * - * @param event - the LeaveEvent received - */ - void handleLeaveEvent(QueueCallerLeaveEvent event) { - final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); - final AsteriskChannelImpl channel = channelManager.getChannelImplByName(event.getChannel()); - - if (queue == null) { - logger.error("Ignored LeaveEvent for unknown queue " + event.getQueue()); - return; - } - if (channel == null) { - logger.error("Ignored LeaveEvent for unknown channel " + event.getChannel()); - return; - } - - final AsteriskQueueEntryImpl existingQueueEntry = queue.getEntry(event.getChannel()); - if (existingQueueEntry == null) { - logger.error("Ignored leave event for non existing queue entry in queue " + event.getQueue() + " for channel " - + event.getChannel()); - return; - } - - queue.removeEntry(existingQueueEntry, event.getDateReceived()); - } + /** + * Called from AsteriskServerImpl whenever an enty leaves a queue. + * + * @param event - the LeaveEvent received + */ + void handleLeaveEvent(QueueCallerLeaveEvent event) + { + final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); + final AsteriskChannelImpl channel = channelManager.getChannelImplByName(event.getChannel()); + + if (queue == null) + { + logger.error("Ignored LeaveEvent for unknown queue " + event.getQueue()); + return; + } + if (channel == null) + { + logger.error("Ignored LeaveEvent for unknown channel " + event.getChannel()); + return; + } + + final AsteriskQueueEntryImpl existingQueueEntry = queue.getEntry(event.getChannel()); + if (existingQueueEntry == null) + { + logger.error("Ignored leave event for non existing queue entry in queue " + event.getQueue() + " for channel " + + event.getChannel()); + return; + } + + queue.removeEntry(existingQueueEntry, event.getDateReceived()); + } /** * Called from AsteriskServerImpl whenever an enty leaves a queue. @@ -583,7 +590,7 @@ private AsteriskQueueImpl getInternalQueueByName(String queueName) { AsteriskQueueImpl queue; - synchronized (queuesLRU) + try (LockCloser closer = Locker.lock(queuesLRU)) { queue = queuesLRU.get(queueName); } diff --git a/src/main/java/org/asteriskjava/manager/PingThread.java b/src/main/java/org/asteriskjava/manager/PingThread.java index ee5edf9b4..b796afbf1 100644 --- a/src/main/java/org/asteriskjava/manager/PingThread.java +++ b/src/main/java/org/asteriskjava/manager/PingThread.java @@ -22,16 +22,17 @@ import org.asteriskjava.manager.action.PingAction; import org.asteriskjava.manager.response.ManagerResponse; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; /** - * A Thread that pings the Asterisk server at a given interval. - * You can use this to prevent the connection being shut down when there is no - * traffic. + * A Thread that pings the Asterisk server at a given interval. You can use this + * to prevent the connection being shut down when there is no traffic. *

    * Since 1.0.0 PingThread supports mutliple connections so do don't have to - * start multiple threads to keep several connections alive. + * start multiple threads to keep several connections alive. * * @author srt * @version $Id$ @@ -53,8 +54,8 @@ public class PingThread extends Thread private final Set connections; /** - * Creates a new PingThread. Use {@link #addConnection(ManagerConnection)} to add connections - * that will be pinged. + * Creates a new PingThread. Use {@link #addConnection(ManagerConnection)} + * to add connections that will be pinged. * * @since 1.0.0 */ @@ -80,8 +81,7 @@ public PingThread(ManagerConnection connection) } /** - * Adjusts how often a PingAction is sent. - *
    + * Adjusts how often a PingAction is sent.
    * Default is 20000ms, i.e. 20 seconds. * * @param interval the interval in milliseconds @@ -93,11 +93,9 @@ public void setInterval(long interval) /** * Sets the timeout to wait for the ManagerResponse before throwing an - * excpetion. - *
    + * excpetion.
    * If set to 0 the response will be ignored an no exception will be thrown - * at all. - *
    + * at all.
    * Default is 0. * * @param timeout the timeout in milliseconds or 0 to indicate no timeout. @@ -116,7 +114,7 @@ public void setTimeout(long timeout) */ public void addConnection(ManagerConnection connection) { - synchronized (connections) + try (LockCloser closer = Locker.lock(connections)) { connections.add(connection); } @@ -130,7 +128,7 @@ public void addConnection(ManagerConnection connection) */ public void removeConnection(ManagerConnection connection) { - synchronized (connections) + try (LockCloser closer = Locker.lock(connections)) { connections.remove(connection); } @@ -165,7 +163,7 @@ public void run() break; } - synchronized (connections) + try (LockCloser closer = Locker.lock(connections)) { for (ManagerConnection c : connections) { diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 84ca799b9..4efa0a879 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -72,6 +72,8 @@ import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.pbx.util.LogTime; import org.asteriskjava.util.DateUtil; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; import org.asteriskjava.util.SocketConnectionFacade; @@ -911,7 +913,7 @@ else if (state != CONNECTED) // in the response, thats fine. if (callback != null) { - synchronized (this.responseListeners) + try (LockCloser closer = Locker.lock(this.responseListeners)) { this.responseListeners.put(internalActionId, callback); } @@ -997,13 +999,13 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas try { // register response handler... - synchronized (this.responseListeners) + try (LockCloser closer = Locker.lock(this.responseListeners)) { this.responseListeners.put(internalActionId, responseEventHandler); } // ...and event handler. - synchronized (this.responseEventListeners) + try (LockCloser closer = Locker.lock(this.responseEventListeners)) { this.responseEventListeners.put(internalActionId, responseEventHandler); } @@ -1036,7 +1038,7 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas finally { // remove the event handler - synchronized (this.responseEventListeners) + try (LockCloser closer = Locker.lock(this.responseEventListeners)) { this.responseEventListeners.remove(internalActionId); } @@ -1044,7 +1046,7 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas // Note: The response handler should have already been removed // when the response was received, however we remove it here // just in case it was never received. - synchronized (this.responseListeners) + try (LockCloser closer = Locker.lock(this.responseListeners)) { this.responseListeners.remove(internalActionId); } @@ -1087,13 +1089,13 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas action.getActionCompleteEventClass(), callback); // register response handler... - synchronized (this.responseListeners) + try (LockCloser closer = Locker.lock(this.responseListeners)) { this.responseListeners.put(internalActionId, responseEventHandler); } // ...and event handler. - synchronized (this.responseEventListeners) + try (LockCloser closer = Locker.lock(this.responseEventListeners)) { this.responseEventListeners.put(internalActionId, responseEventHandler); } @@ -1125,7 +1127,7 @@ private String createInternalActionId() public void addEventListener(final ManagerEventListener listener) { - synchronized (this.eventListeners) + try (LockCloser closer = Locker.lock(this.eventListeners)) { // only add it if its not already there if (!this.eventListeners.contains(listener)) @@ -1137,7 +1139,7 @@ public void addEventListener(final ManagerEventListener listener) public void removeEventListener(final ManagerEventListener listener) { - synchronized (this.eventListeners) + try (LockCloser closer = Locker.lock(this.eventListeners)) { if (this.eventListeners.contains(listener)) { @@ -1196,7 +1198,7 @@ public void dispatchResponse(ManagerResponse response) if (internalActionId != null) { - synchronized (this.responseListeners) + try (LockCloser closer = Locker.lock(this.responseListeners)) { listener = responseListeners.get(internalActionId); if (listener != null) @@ -1267,7 +1269,7 @@ public void dispatchEvent(ManagerEvent event) internalActionId = responseEvent.getInternalActionId(); if (internalActionId != null) { - synchronized (responseEventListeners) + try (LockCloser closer = Locker.lock(responseEventListeners)) { ManagerEventListener listener; @@ -1302,7 +1304,7 @@ public void dispatchEvent(ManagerEvent event) cleanupActionListeners((DisconnectEvent) event); // When we receive get disconnected while we are connected start // a new reconnect thread and set the state to RECONNECTING. - synchronized (this) + try (LockCloser closer = Locker.lock(this)) { if (state == CONNECTED) { @@ -1373,7 +1375,7 @@ private void dispatchLegacyEventIfNeeded(ManagerEvent event) */ private void fireEvent(ManagerEvent event) { - synchronized (eventListeners) + try (LockCloser closer = Locker.lock(eventListeners)) { for (ManagerEventListener listener : eventListeners) { @@ -1475,7 +1477,7 @@ private void reconnect() try { - synchronized (this) + try (LockCloser closer = Locker.lock(this)) { if (state != RECONNECTING) { @@ -1550,7 +1552,7 @@ private void cleanupActionListeners(DisconnectEvent event) { HashMap oldResponseListeners = null; - synchronized (responseListeners) + try (LockCloser closer = Locker.lock(responseListeners)) { // Store remaining response listeners to be notified outside of // synchronized @@ -1573,7 +1575,7 @@ private void cleanupActionListeners(DisconnectEvent event) } HashMap oldResponseEventListeners = null; - synchronized (responseEventListeners) + try (LockCloser closer = Locker.lock(responseEventListeners)) { // Store remaining responseEventListeners to be notified outside of // synchronized @@ -1788,7 +1790,7 @@ public void onManagerEvent(ManagerEvent event) { events.setComplete(true); String internalActionId = responseEvent.getInternalActionId(); - synchronized (responseEventListeners) + try (LockCloser closer = Locker.lock(responseEventListeners)) { responseEventListeners.remove(internalActionId); } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java index 3e321b430..44f056dfc 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java @@ -20,9 +20,10 @@ import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.action.ManagerAction; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.SocketConnectionFacade; - /** * Default implementation of ManagerWriter interface. * @@ -34,11 +35,11 @@ public class ManagerWriterImpl implements ManagerWriter /** * Instance logger. */ - //private final Log logger = LogFactory.getLog(getClass()); + // private final Log logger = LogFactory.getLog(getClass()); /** - * The action builder utility to convert ManagerAction to a String suitable to be sent to the - * asterisk server. + * The action builder utility to convert ManagerAction to a String suitable + * to be sent to the asterisk server. */ private final ActionBuilder actionBuilder; @@ -57,26 +58,34 @@ public void setTargetVersion(AsteriskVersion version) actionBuilder.setTargetVersion(version); } - public synchronized void setSocket(final SocketConnectionFacade socket) + public void setSocket(final SocketConnectionFacade socket) { - this.socket = socket; + try (LockCloser closer = Locker.lock(this)) + { + this.socket = socket; + } } - public synchronized void sendAction(final ManagerAction action, final String internalActionId) throws IOException + public void sendAction(final ManagerAction action, final String internalActionId) throws IOException { - final String actionString; - - if (socket == null) + try (LockCloser closer = Locker.lock(this)) { - throw new IllegalStateException("Unable to send action: socket is null"); - } + final String actionString; + + if (socket == null) + { + throw new IllegalStateException("Unable to send action: socket is null"); + } - actionString = actionBuilder.buildAction(action, internalActionId); + actionString = actionBuilder.buildAction(action, internalActionId); - socket.write(actionString); - socket.flush(); + socket.write(actionString); + socket.flush(); - // TODO tracing - //logger.debug("Sent " + action.getAction() + " action with actionId '" + action.getActionId() + "':\n" + actionString); + // TODO tracing + // logger.debug("Sent " + action.getAction() + " action with + // actionId '" + // + action.getActionId() + "':\n" + actionString); + } } } diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java index f1ca7814d..2ad741aad 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java @@ -24,6 +24,8 @@ import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.manager.response.ManagerResponse; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; /** * Implementation of the ResponseEvents interface. @@ -84,7 +86,7 @@ public void setRepsonse(ManagerResponse response) */ public void addEvent(ResponseEvent event) { - synchronized (events) + try (LockCloser closer = Locker.lock(events)) { events.add(event); } diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index edb572117..70c9a756f 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -12,6 +12,8 @@ import org.asteriskjava.manager.event.BridgeEvent; import org.asteriskjava.manager.event.BridgeLeaveEvent; import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -32,7 +34,7 @@ class BridgeState ManagerEvent destroy() { - synchronized (members) + try (LockCloser closer = Locker.lock(members)) { members.clear(); } @@ -49,12 +51,13 @@ ManagerEvent addMember(BridgeEnterEvent event) { List remaining = null; - if (HOLDING_BRIDGE_TECH.equals(event.getBridgeTechnology())) { + if (HOLDING_BRIDGE_TECH.equals(event.getBridgeTechnology())) + { /* channels in a holding bridge aren't bridged to one another */ return null; } - synchronized (members) + try (LockCloser closer = Locker.lock(members)) { if (members.put(event.getChannel(), event) == null && members.size() == 2) { @@ -87,12 +90,13 @@ ManagerEvent removeMember(BridgeLeaveEvent event) { List remaining = new LinkedList<>(); - if (HOLDING_BRIDGE_TECH.equals(event.getBridgeTechnology())) { + if (HOLDING_BRIDGE_TECH.equals(event.getBridgeTechnology())) + { /* channels in a holding bridge aren't bridged to one another */ return null; } - synchronized (members) + try (LockCloser closer = Locker.lock(members)) { remaining.addAll(members.values()); diff --git a/src/main/java/org/asteriskjava/pbx/CallImpl.java b/src/main/java/org/asteriskjava/pbx/CallImpl.java index 9596b11f6..f88334549 100644 --- a/src/main/java/org/asteriskjava/pbx/CallImpl.java +++ b/src/main/java/org/asteriskjava/pbx/CallImpl.java @@ -447,25 +447,6 @@ private boolean isSameChannel(Channel lhs, Channel rhs) return lhs != null && rhs != null && lhs.isSame(rhs); } - // private int findChannel(iChannel channel) - // { - // int index = -1; - // - // synchronized (this.channelList) - // { - // for (int i = 0; i < this.channelList.size(); i++) - // { - // iChannel aChannel = this.channelList.get(i); - // if (aChannel.isSame(channel)) - // { - // index = i; - // break; - // } - // } - // } - // return index; - // } - private void notifyCallHangupListeners() { for (CallHangupListener listener : this._hangupListeners) @@ -722,19 +703,6 @@ public OWNER getOwner() return this._owner; } - // /** - // * Returns a shallow clone of the list of channels. - // */ - // @SuppressWarnings("unchecked") - // @Override - // public Collection getChannels() - // { - // synchronized (this.channelList) - // { - // return (Collection) this.channelList.clone(); - // } - // } - @Override public String toString() { diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index efa537e3c..d50db4248 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -26,6 +26,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -230,51 +232,54 @@ else if (_completionCause == CompletionCause.CANCELLED) } @Override - synchronized public void onManagerEvent(final ManagerEvent event) + public void onManagerEvent(final ManagerEvent event) { - if (event instanceof BridgeEvent) + try (LockCloser closer = Locker.lock(this)) { - BridgeEvent bridge = (BridgeEvent) event; - if (bridge.isLink()) + if (event instanceof BridgeEvent) { - if (bridge.getChannel1().isSame(_call.getOperandChannel(this._channelToTransfer))) + BridgeEvent bridge = (BridgeEvent) event; + if (bridge.isLink()) { - this._completionCause = CompletionCause.BRIDGED; - this._transferTargetChannel = bridge.getChannel2(); + if (bridge.getChannel1().isSame(_call.getOperandChannel(this._channelToTransfer))) + { + this._completionCause = CompletionCause.BRIDGED; + this._transferTargetChannel = bridge.getChannel2(); + this._latch.countDown(); + } + else if (bridge.getChannel2().isSame(_call.getOperandChannel(this._channelToTransfer))) + { + this._completionCause = CompletionCause.BRIDGED; + this._transferTargetChannel = bridge.getChannel1(); + this._latch.countDown(); + } + } + } + else if (event instanceof HangupEvent) + { + HangupEvent hangup = (HangupEvent) event; + if (hangup.getChannel().isSame(_call.getOperandChannel(this._channelToTransfer))) + { + this._completionCause = CompletionCause.HANGUP; this._latch.countDown(); } - else if (bridge.getChannel2().isSame(_call.getOperandChannel(this._channelToTransfer))) + if (hangup.getChannel().isSame(dialedChannel)) { - this._completionCause = CompletionCause.BRIDGED; - this._transferTargetChannel = bridge.getChannel1(); + this._completionCause = CompletionCause.HANGUP; this._latch.countDown(); } } - } - else if (event instanceof HangupEvent) - { - HangupEvent hangup = (HangupEvent) event; - if (hangup.getChannel().isSame(_call.getOperandChannel(this._channelToTransfer))) - { - this._completionCause = CompletionCause.HANGUP; - this._latch.countDown(); - } - if (hangup.getChannel().isSame(dialedChannel)) + else if (event instanceof DialEvent) { - this._completionCause = CompletionCause.HANGUP; - this._latch.countDown(); - } - } - else if (event instanceof DialEvent) - { - DialEvent dialEvent = (DialEvent) event; - if (dialEvent.getChannel() != null) - { - Channel operandChannel = _call.getOperandChannel(_channelToTransfer); - if (dialEvent.getChannel().isSame(operandChannel)) + DialEvent dialEvent = (DialEvent) event; + if (dialEvent.getChannel() != null) { - DialEvent de = (DialEvent) event; - dialedChannel = de.getDestination(); + Channel operandChannel = _call.getOperandChannel(_channelToTransfer); + if (dialEvent.getChannel().isSame(operandChannel)) + { + DialEvent de = (DialEvent) event; + dialedChannel = de.getDestination(); + } } } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java index 6289ae212..102732a97 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java @@ -22,6 +22,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ParkedCallEvent; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -176,15 +178,18 @@ public EndPoint getParkingLot() } @Override - synchronized public void onManagerEvent(final ManagerEvent event) + public void onManagerEvent(final ManagerEvent event) { - assert event instanceof ParkedCallEvent : "Unexpected event"; + try (LockCloser closer = Locker.lock(this)) + { + assert event instanceof ParkedCallEvent : "Unexpected event"; - final ParkedCallEvent parkedEvent = (ParkedCallEvent) event; - final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + final ParkedCallEvent parkedEvent = (ParkedCallEvent) event; + final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - this._parkingLot = pbx.buildEndPoint(TechType.LOCAL, parkedEvent.getExten()); - this._latch.countDown(); + this._parkingLot = pbx.buildEndPoint(TechType.LOCAL, parkedEvent.getExten()); + this._latch.countDown(); + } } @Override diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index 0396db628..1b02e2ea7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -24,6 +24,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.RenameEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelProxy; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -115,14 +117,17 @@ public boolean doActivity() throws PBXException final AtomicReference renameEventReceived = new AtomicReference<>(); @Override - synchronized public void onManagerEvent(final ManagerEvent event) + public void onManagerEvent(final ManagerEvent event) { - if (event instanceof RenameEvent) + try (LockCloser closer = Locker.lock(this)) { - RenameEvent rename = (RenameEvent) event; - if (rename.getChannel().isSame(channel1) || rename.getChannel().isSame(channel2)) + if (event instanceof RenameEvent) { - renameEventReceived.get().countDown(); + RenameEvent rename = (RenameEvent) event; + if (rename.getChannel().isSame(channel1) || rename.getChannel().isSame(channel2)) + { + renameEventReceived.get().countDown(); + } } } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java index 9c6b6fc5b..b3f5505f7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java @@ -4,6 +4,8 @@ import java.util.LinkedList; import org.asteriskjava.pbx.Channel; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -44,35 +46,44 @@ public MeetmeRoom(final int number) * returns true if the channel was added to the list of channels in this * meetme. if the channel is already in the meetme, returns false */ - synchronized public boolean addChannel(final Channel channel) + public boolean addChannel(final Channel channel) { - boolean newChannel = false; - if (!this.channels.contains(channel)) + try (LockCloser closer = Locker.lock(this)) { - this.channels.add(channel); - this.channelCount++; - newChannel = true; + boolean newChannel = false; + if (!this.channels.contains(channel)) + { + this.channels.add(channel); + this.channelCount++; + newChannel = true; + } + else + MeetmeRoom.logger.error("rejecting " + channel + " already in meetme."); //$NON-NLS-1$ //$NON-NLS-2$ + return newChannel; } - else - MeetmeRoom.logger.error("rejecting " + channel + " already in meetme."); //$NON-NLS-1$ //$NON-NLS-2$ - return newChannel; } - synchronized public int getChannelCount() + public int getChannelCount() { - return this.channelCount; + try (LockCloser closer = Locker.lock(this)) + { + return this.channelCount; + } } - synchronized public Channel[] getChannels() + public Channel[] getChannels() { - final Channel list[] = new Channel[this.channels.size()]; - - int cnt = 0; - for (final Channel channel : this.channels) + try (LockCloser closer = Locker.lock(this)) { - list[cnt++] = channel; + final Channel list[] = new Channel[this.channels.size()]; + + int cnt = 0; + for (final Channel channel : this.channels) + { + list[cnt++] = channel; + } + return list; } - return list; } public boolean getForceClose() @@ -100,43 +111,49 @@ public boolean isActive() return this.active; } - synchronized public void removeChannel(final Channel channel) + public void removeChannel(final Channel channel) { - final boolean channelCountInSync = this.channelCount == this.channels.size(); - final boolean removed = this.channels.remove(channel); - - if (!removed) + try (LockCloser closer = Locker.lock(this)) { - MeetmeRoom.logger.warn( - "An attempt to remove an non-existing channel " + channel + " from Meetme Room " + this.getRoomNumber()); //$NON-NLS-1$ //$NON-NLS-2$ - } + final boolean channelCountInSync = this.channelCount == this.channels.size(); + final boolean removed = this.channels.remove(channel); - if (channelCountInSync && removed) - { - this.channelCount--; - } + if (!removed) + { + MeetmeRoom.logger.warn("An attempt to remove an non-existing channel " + channel + " from Meetme Room " //$NON-NLS-1$ //$NON-NLS-2$ + + this.getRoomNumber()); + } - // If the channel count is not insync then we decrement the channel - // count even if the remove was for a non-existent channel. - // We do this as if the channel count is out of sync it means that we - // have polled asterisk (usually during startup) - // and our local count was out of sync with asterisk. Asterisk is the - // definitive source. If we then get a remove - // channel then its probably a channel that asterisk knows about but - // which we don't know about. - // In that case our channelCount will also have come from asterisk so - // decrementing it keeps us in sync with asterisk - // and eventually we will get back in sync (hopefully). - if (!channelCountInSync && removed) - { - this.channelCount--; - } + if (channelCountInSync && removed) + { + this.channelCount--; + } - if ((this.channels.size() < 2) && (this.channels.size() > 0)) - { - if (!this.channels.get(0).isLocal()) + // If the channel count is not insync then we decrement the channel + // count even if the remove was for a non-existent channel. + // We do this as if the channel count is out of sync it means that + // we + // have polled asterisk (usually during startup) + // and our local count was out of sync with asterisk. Asterisk is + // the + // definitive source. If we then get a remove + // channel then its probably a channel that asterisk knows about but + // which we don't know about. + // In that case our channelCount will also have come from asterisk + // so + // decrementing it keeps us in sync with asterisk + // and eventually we will get back in sync (hopefully). + if (!channelCountInSync && removed) + { + this.channelCount--; + } + + if ((this.channels.size() < 2) && (this.channels.size() > 0)) { - logger.warn("One channel left in the meet me room " + this.channels.get(0) + " room " + this.roomNumber); //$NON-NLS-1$ + if (!this.channels.get(0).isLocal()) + { + logger.warn("One channel left in the meet me room " + this.channels.get(0) + " room " + this.roomNumber); //$NON-NLS-1$ + } } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index b8610f026..8115b0c43 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -28,6 +28,8 @@ import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.CoherentManagerEventListener; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -103,62 +105,65 @@ private MeetmeRoomControl(PBX pbx, final int roomCount) throws NoMeetmeException * returns the next available meetme room, or null if no rooms are * available. */ - public synchronized MeetmeRoom findAvailableRoom(RoomOwner newOwner) + public MeetmeRoom findAvailableRoom(RoomOwner newOwner) { - int count = 0; - for (final MeetmeRoom room : this.rooms) + try (LockCloser closer = Locker.lock(this)) { - if (MeetmeRoomControl.logger.isDebugEnabled()) + int count = 0; + for (final MeetmeRoom room : this.rooms) { - MeetmeRoomControl.logger.debug("room " + room.getRoomNumber() + " count " + count); - } - if (room.getOwner() == null || !room.getOwner().isRoomStillRequired()) - { - /* - * new code to attempt to recover uncleared meetme rooms safely - */ - try + if (MeetmeRoomControl.logger.isDebugEnabled()) { - final Date lastUpdated = room.getLastUpdated(); - final long now = new Date().getTime(); - if (lastUpdated != null) - { - final long elapsedTime = now - lastUpdated.getTime(); - MeetmeRoomControl.logger - .error("room: " + room.getRoomNumber() + " count: " + count + " elapsed: " + elapsedTime); - if ((elapsedTime > 1800000) && (room.getChannelCount() < 2)) - { - MeetmeRoomControl.logger.error("clearing room"); //$NON-NLS-1$ - room.setInactive(); - } - } + MeetmeRoomControl.logger.debug("room " + room.getRoomNumber() + " count " + count); } - catch (final Exception e) + if (room.getOwner() == null || !room.getOwner().isRoomStillRequired()) { /* - * attempt to make this new change safe + * new code to attempt to recover uncleared meetme rooms + * safely */ - MeetmeRoomControl.logger.error(e, e); - } + try + { + final Date lastUpdated = room.getLastUpdated(); + final long now = new Date().getTime(); + if (lastUpdated != null) + { + final long elapsedTime = now - lastUpdated.getTime(); + MeetmeRoomControl.logger.error( + "room: " + room.getRoomNumber() + " count: " + count + " elapsed: " + elapsedTime); + if ((elapsedTime > 1800000) && (room.getChannelCount() < 2)) + { + MeetmeRoomControl.logger.error("clearing room"); //$NON-NLS-1$ + room.setInactive(); + } + } + } + catch (final Exception e) + { + /* + * attempt to make this new change safe + */ + MeetmeRoomControl.logger.error(e, e); + } - if (room.getChannelCount() == 0) + if (room.getChannelCount() == 0) + { + room.setInactive(); + room.setOwner(newOwner); + MeetmeRoomControl.logger.warn("Returning available room " + room.getRoomNumber()); + return room; + } + + } + else { - room.setInactive(); - room.setOwner(newOwner); - MeetmeRoomControl.logger.warn("Returning available room " + room.getRoomNumber()); - return room; + logger.warn("Meetme " + room.getRoomNumber() + " is still in use by " + room.getOwner()); } - - } - else - { - logger.warn("Meetme " + room.getRoomNumber() + " is still in use by " + room.getOwner()); + count++; } - count++; + MeetmeRoomControl.logger.error("no more available rooms"); + return null; } - MeetmeRoomControl.logger.error("no more available rooms"); - return null; - } /** @@ -168,23 +173,30 @@ public synchronized MeetmeRoom findAvailableRoom(RoomOwner newOwner) * @param roomNumber the meetme room number * @return */ - synchronized private MeetmeRoom findMeetmeRoom(final String roomNumber) + private MeetmeRoom findMeetmeRoom(final String roomNumber) { - MeetmeRoom foundRoom = null; - for (final MeetmeRoom room : this.rooms) + try (LockCloser closer = Locker.lock(this)) { - if (room.getRoomNumber().compareToIgnoreCase(roomNumber) == 0) + MeetmeRoom foundRoom = null; + for (final MeetmeRoom room : this.rooms) { - foundRoom = room; - break; + if (room.getRoomNumber().compareToIgnoreCase(roomNumber) == 0) + { + foundRoom = room; + break; + } } + return foundRoom; } - return foundRoom; + } - synchronized MeetmeRoom getRoom(final int room) + MeetmeRoom getRoom(final int room) { - return this.rooms[room]; + try (LockCloser closer = Locker.lock(this)) + { + return this.rooms[room]; + } } @Override @@ -340,30 +352,32 @@ private void configure(AsteriskPBX pbx) throws NoMeetmeException } } - private synchronized void parseMeetme(final String line) throws NoMeetmeException + private void parseMeetme(final String line) throws NoMeetmeException { - - if (line != null) + try (LockCloser closer = Locker.lock(this)) { - if (line.toLowerCase().startsWith("no such command 'meetme'")) //$NON-NLS-1$ + if (line != null) { - throw new NoMeetmeException("Asterisk is not configured correctly! Please enable the MeetMe app"); //$NON-NLS-1$ - } + if (line.toLowerCase().startsWith("no such command 'meetme'")) //$NON-NLS-1$ + { + throw new NoMeetmeException("Asterisk is not configured correctly! Please enable the MeetMe app"); //$NON-NLS-1$ + } - if ((!line.toLowerCase().startsWith("no active meetme conferences.")) //$NON-NLS-1$ - && (!line.toLowerCase().startsWith("conf num")) //$NON-NLS-1$ - && (!line.toLowerCase().startsWith("* total number")) //$NON-NLS-1$ - && (!line.toLowerCase().startsWith("no such conference")) //$NON-NLS-1$ - && (!line.toLowerCase().startsWith("no such command 'meetme")) //$NON-NLS-1$ - ) - { - // Update the stats on each meetme - final String roomNumber = line.substring(0, 10).trim(); - final String tmp = line.substring(11, 25).trim(); - final int channelCount = Integer.parseInt(tmp); + if ((!line.toLowerCase().startsWith("no active meetme conferences.")) //$NON-NLS-1$ + && (!line.toLowerCase().startsWith("conf num")) //$NON-NLS-1$ + && (!line.toLowerCase().startsWith("* total number")) //$NON-NLS-1$ + && (!line.toLowerCase().startsWith("no such conference")) //$NON-NLS-1$ + && (!line.toLowerCase().startsWith("no such command 'meetme")) //$NON-NLS-1$ + ) + { + // Update the stats on each meetme + final String roomNumber = line.substring(0, 10).trim(); + final String tmp = line.substring(11, 25).trim(); + final int channelCount = Integer.parseInt(tmp); - final int roomNo = Integer.valueOf(roomNumber); - setRoomCount(roomNumber, channelCount, roomNo); + final int roomNo = Integer.valueOf(roomNumber); + setRoomCount(roomNumber, channelCount, roomNo); + } } } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index b610d5a12..21ed8b6f5 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -68,6 +68,8 @@ import org.asteriskjava.pbx.internal.asterisk.MeetmeRoomControl; import org.asteriskjava.pbx.internal.asterisk.RoomOwner; import org.asteriskjava.pbx.internal.managerAPI.RedirectCall; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -574,7 +576,7 @@ public Channel registerChannel(final String channelName, final String uniqueIdPa public Channel internalRegisterChannel(final String channelName, final String uniqueID) throws InvalidChannelName { ChannelProxy proxy = null; - synchronized (this.liveChannels) + try (LockCloser closer = Locker.lock(this.liveChannels)) { String localUniqueID = (uniqueID == null ? ChannelImpl.UNKNOWN_UNIQUE_ID : uniqueID); @@ -606,7 +608,7 @@ private String cleanChannelName(final String name) public Channel registerHangupChannel(String channel, String uniqueId) throws InvalidChannelName { Channel newChannel = null; - synchronized (this.liveChannels) + try (LockCloser closer = Locker.lock(this.liveChannels)) { newChannel = this.findChannel(channel, uniqueId); if (newChannel == null) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java index 4dc529478..a6f7b97d9 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java @@ -7,6 +7,8 @@ import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ChannelHangupListener; import org.asteriskjava.pbx.asterisk.wrap.events.ChannelState; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -56,7 +58,7 @@ public class CallTracker implements ChannelHangupListener */ void mergeCalls(CallTracker rhs) { - synchronized (this._associatedChannels) + try (LockCloser closer = Locker.lock(this._associatedChannels)) { this._associatedChannels.addAll(rhs._associatedChannels); // not certain this is necessary but lets just tidy up a bit. @@ -80,7 +82,7 @@ public void setState(final ChannelState channelState) public int findChannel(Channel newChannel) { int index = -1; - synchronized (this._associatedChannels) + try (LockCloser closer = Locker.lock(this._associatedChannels)) { for (int i = 0; i < this._associatedChannels.size(); i++) @@ -104,7 +106,7 @@ public int findChannel(Channel newChannel) */ public void remove(Channel channel) { - synchronized (this._associatedChannels) + try (LockCloser closer = Locker.lock(this._associatedChannels)) { int index = findChannel(channel); if (index != -1) @@ -121,7 +123,7 @@ public void remove(Channel channel) public void startSweep() { - synchronized (this._associatedChannels) + try (LockCloser closer = Locker.lock(this._associatedChannels)) { for (final Channel channel : this._associatedChannels) { @@ -133,7 +135,7 @@ public void startSweep() public void endSweep() { final List toremove = new LinkedList<>(); - synchronized (this._associatedChannels) + try (LockCloser closer = Locker.lock(this._associatedChannels)) { for (final Channel channel : this._associatedChannels) { @@ -161,7 +163,7 @@ void dumpChannelList() if (logger.isDebugEnabled()) { logger.debug("CallTracker: dump channellist:" + this); //$NON-NLS-1$ - synchronized (this._associatedChannels) + try (LockCloser closer = Locker.lock(this._associatedChannels)) { for (final Channel channel : this._associatedChannels) { @@ -173,7 +175,7 @@ void dumpChannelList() public boolean hasEnded() { - synchronized (this._associatedChannels) + try (LockCloser closer = Locker.lock(this._associatedChannels)) { return this._associatedChannels.size() == 0; } @@ -183,7 +185,7 @@ public boolean hasEnded() public void channelHangup(Channel channel, Integer cause, String causeText) { remove(channel); - synchronized (this._associatedChannels) + try (LockCloser closer = Locker.lock(this._associatedChannels)) { if (this._associatedChannels.size() == 0) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index 217b85be7..d6686ff51 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -19,6 +19,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.internal.eventQueue.EventLifeMonitor; import org.asteriskjava.pbx.util.LogTime; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -76,7 +78,7 @@ public void onManagerEvent(final org.asteriskjava.manager.event.ManagerEvent eve * processing overhead of these events. */ // Only enqueue the events that are of interest to one of our listeners. - synchronized (this.globalEvents) + try (LockCloser closer = Locker.lock(this.globalEvents)) { Class< ? extends ManagerEvent> shadowEvent = CoherentEventFactory.getShadowEvent(event); if (this.globalEvents.contains(shadowEvent)) @@ -195,7 +197,7 @@ public void dispatchEvent(final ManagerEvent event) // iterate over them // The iteration may call some long running processes. final List listenerCopy; - synchronized (this.listeners) + try (LockCloser closer = Locker.lock(this.listeners)) { listenerCopy = this.listeners.getCopyAsList(); } @@ -281,10 +283,10 @@ public void run() */ public void addListener(final FilteredManagerListener listener) { - synchronized (this.listeners) + try (LockCloser closer = Locker.lock(this.listeners)) { this.listeners.addListener(listener); - synchronized (this.globalEvents) + try (LockCloser closer2 = Locker.lock(this.globalEvents)) { Collection> expandEvents = expandEvents(listener.requiredEvents()); this.globalEvents.addAll(expandEvents); @@ -321,14 +323,14 @@ public void removeListener(final FilteredManagerListener melf) { if (melf != null) { - synchronized (this.listeners) + try (LockCloser closer = Locker.lock(this.listeners)) { this.listeners.removeListener(melf); // When we remove a listener we must unfortunately // completely // recalculate the set of required events. - synchronized (this.globalEvents) + try (LockCloser closer2 = Locker.lock(this.globalEvents)) { this.globalEvents.clear(); Iterator itr = this.listeners.iterator(); @@ -352,9 +354,9 @@ public void removeListener(final FilteredManagerListener melf) */ public void transferListeners(CoherentManagerEventQueue eventQueue) { - synchronized (this.listeners) + try (LockCloser closer = Locker.lock(this.listeners)) { - synchronized (eventQueue.listeners) + try (LockCloser closer2 = Locker.lock(eventQueue.listeners)) { Iterator itr = eventQueue.listeners.iterator(); while (itr.hasNext()) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index 85d1fe98f..f09379616 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -21,6 +21,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvents; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -120,7 +122,7 @@ public ChannelProxy getChannelByEndPoint(EndPoint endPoint) public void add(ChannelProxy proxy) { - synchronized (this._liveChannels) + try (LockCloser closer = Locker.lock(this._liveChannels)) { ChannelProxy index = findProxy(proxy); if (index == null) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java index 0718943bf..8d3f0aecd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java @@ -8,6 +8,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; import org.asteriskjava.pbx.asterisk.wrap.events.NewStateEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -49,7 +51,7 @@ private CallTracker registerChannel(final Channel newChannel) { CallTracker associatedCall = null; boolean found = false; - synchronized (this.callList) + try (LockCloser closer = Locker.lock(this.callList)) { for (final CallTracker call : this.callList) { @@ -74,7 +76,7 @@ private CallTracker registerChannel(final Channel newChannel) private CallTracker createCallTracker(final Channel newChannel) { CallTracker newCall; - synchronized (this.callList) + try (LockCloser closer = Locker.lock(this.callList)) { newCall = new CallTracker(this, newChannel); this.callList.add(newCall); @@ -90,7 +92,7 @@ public boolean getDND() // public String getFullChannelName() // { // String channelName = null; - // synchronized (this.callList) + // try (LockCloser closer = Locker2.lock(this.callList) // { // if (this.callList.size() > 0) // { @@ -208,7 +210,7 @@ public void handleEvent(final StatusEvent b) private CallTracker findCall(Channel channel) { CallTracker result = null; - synchronized (this.callList) + try (LockCloser closer = Locker.lock(this.callList)) { for (CallTracker call : this.callList) { @@ -231,7 +233,7 @@ public void setDND(final boolean on) public void startSweep() { Peer.logger.debug("Starting sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ - synchronized (this.callList) + try (LockCloser closer = Locker.lock(this.callList)) { for (final CallTracker call : this.callList) { @@ -243,7 +245,7 @@ public void startSweep() public void endSweep() { Peer.logger.debug("Ending sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ - synchronized (this.callList) + try (LockCloser closer = Locker.lock(this.callList)) { for (final CallTracker call : this.callList) { @@ -259,7 +261,7 @@ public void endSweep() */ private void evaluateState() { - synchronized (this.callList) + try (LockCloser closer = Locker.lock(this.callList)) { // Get the highest prioirty state from the set of calls. PeerState newState = PeerState.NOTSET; @@ -300,7 +302,7 @@ private void dumpCallList() public void callEnded(CallTracker call) { boolean found = false; - synchronized (this.callList) + try (LockCloser closer = Locker.lock(this.callList)) { for (final CallTracker aCall : this.callList) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java index 387b1b3ee..7773365a0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java @@ -23,6 +23,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -124,39 +126,45 @@ public void addSipsToMonitor() } - synchronized public Peer registerPeer(final Channel newChannel) + public Peer registerPeer(final Channel newChannel) { final Peer peer = this.registerPeer(newChannel.getEndPoint()); return peer; } - synchronized public Peer registerPeer(final EndPoint endPoint) + public Peer registerPeer(final EndPoint endPoint) { if (endPoint.isLocal()) { return null; } - Peer peer = this.findPeer(endPoint); - if (peer == null) + try (LockCloser closer = Locker.lock(peerList)) { - peer = new Peer(endPoint); - this.peerList.add(peer); + Peer peer = this.findPeer(endPoint); + if (peer == null) + { + peer = new Peer(endPoint); + this.peerList.add(peer); + } + return peer; } - return peer; } - synchronized public Peer findPeer(final EndPoint peerEndPoint) + public Peer findPeer(final EndPoint peerEndPoint) { Peer found = null; - for (final Peer peer : this.peerList) + try (LockCloser closer = Locker.lock(peerList)) { - if (peer.getEndPoint().isSame(peerEndPoint)) + for (final Peer peer : this.peerList) { - found = peer; - break; + if (peer.getEndPoint().isSame(peerEndPoint)) + { + found = peer; + break; + } } } return found; @@ -165,9 +173,12 @@ synchronized public Peer findPeer(final EndPoint peerEndPoint) @SuppressWarnings("unchecked") public Iterator getIterator() { - final List clone = (LinkedList) this.peerList.clone(); - final List tmpList = clone; - return tmpList.iterator(); + try (LockCloser closer = Locker.lock(peerList)) + { + final List clone = (LinkedList) this.peerList.clone(); + final List tmpList = clone; + return tmpList.iterator(); + } } @@ -189,7 +200,7 @@ public Iterator getIterator() } @Override - synchronized public void onManagerEvent(final ManagerEvent event) + public void onManagerEvent(final ManagerEvent event) { /* * This function is called from the base class. Here we process events @@ -232,33 +243,45 @@ else if (event instanceof NewStateEvent) private void handleEvent(NewStateEvent event) { - for (Peer peer : this.peerList) + try (LockCloser closer = Locker.lock(peerList)) { - peer.handleEvent(event); + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } } } private void handleEvent(final NewChannelEvent event) { - for (Peer peer : this.peerList) + try (LockCloser closer = Locker.lock(peerList)) { - peer.handleEvent(event); + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } } } private void handleEvent(final MasqueradeEvent event) { - for (Peer peer : this.peerList) + try (LockCloser closer = Locker.lock(peerList)) { - peer.handleEvent(event); + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } } } private void handleEvent(final StatusEvent event) { - for (Peer peer : this.peerList) + try (LockCloser closer = Locker.lock(peerList)) { - peer.handleEvent(event); + for (Peer peer : this.peerList) + { + peer.handleEvent(event); + } } } @@ -288,12 +311,14 @@ private void handleEvent(final PeerStatusEvent event) * * @param event */ - private synchronized void handleEvent(final StatusCompleteEvent event) + private void handleEvent(final StatusCompleteEvent event) { - - for (final Peer peer : this.peerList) + try (LockCloser closer = Locker.lock(peerList)) { - peer.endSweep(); + for (final Peer peer : this.peerList) + { + peer.endSweep(); + } } PeerMonitor.logger.debug("Channel Mark and Sweep complete"); //$NON-NLS-1$ } @@ -350,7 +375,7 @@ public void startSweep() PeerMonitor.logger.debug("Starting channel mark and sweep"); //$NON-NLS-1$ // Mark every channel as 'clearing' - synchronized (PeerMonitor.class) + try (LockCloser closer = Locker.lock(peerList)) { for (final Peer peer : this.peerList) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 2c65e3c33..d97fcacf0 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -28,6 +28,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; +import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -292,168 +294,172 @@ void abort(final String reason) * time. */ @Override - synchronized public void onManagerEvent(final ManagerEvent event) + public void onManagerEvent(final ManagerEvent event) { - - managerEventsSeen.getAndIncrement(); - if (event instanceof HangupEvent) + try (LockCloser closer = Locker.lock(this)) { - final HangupEvent hangupEvt = (HangupEvent) event; - final Channel hangupChannel = hangupEvt.getChannel(); - - if (channelId.equals(hangupEvt.getUniqueId())) - { - this.originateSuccess = false; - OriginateBaseClass.logger.warn("Dest channel " + this.newChannel + " hungup"); - originateLatch.countDown(); - } - if ((this.monitorChannel1 != null) && (hangupChannel.isSame(this.monitorChannel1))) + managerEventsSeen.getAndIncrement(); + if (event instanceof HangupEvent) { - this.originateSuccess = false; - this.hungup = true; - if (this.newChannel != null) - { - OriginateBaseClass.logger.warn("hanging up " + this.newChannel); - this.result.setChannelHungup(true); + final HangupEvent hangupEvt = (HangupEvent) event; + final Channel hangupChannel = hangupEvt.getChannel(); - PBX pbx = PBXFactory.getActivePBX(); - try - { - logger.warn("Hanging up"); - pbx.hangup(this.newChannel); - } - catch (IllegalArgumentException | IllegalStateException | PBXException e) + if (channelId.equals(hangupEvt.getUniqueId())) + { + this.originateSuccess = false; + OriginateBaseClass.logger.warn("Dest channel " + this.newChannel + " hungup"); + originateLatch.countDown(); + } + if ((this.monitorChannel1 != null) && (hangupChannel.isSame(this.monitorChannel1))) + { + this.originateSuccess = false; + this.hungup = true; + if (this.newChannel != null) { - logger.error(e, e); + OriginateBaseClass.logger.warn("hanging up " + this.newChannel); + this.result.setChannelHungup(true); + + PBX pbx = PBXFactory.getActivePBX(); + try + { + logger.warn("Hanging up"); + pbx.hangup(this.newChannel); + } + catch (IllegalArgumentException | IllegalStateException | PBXException e) + { + logger.error(e, e); + } } + OriginateBaseClass.logger.warn("notify channel 1 hungup"); + originateLatch.countDown(); } - OriginateBaseClass.logger.warn("notify channel 1 hungup"); - originateLatch.countDown(); - } - if ((this.monitorChannel2 != null) && (hangupChannel.isSame(this.monitorChannel2))) - { - this.originateSuccess = false; - this.hungup = true; - if (this.newChannel != null) + if ((this.monitorChannel2 != null) && (hangupChannel.isSame(this.monitorChannel2))) { - OriginateBaseClass.logger.warn("Hanging up channel " + this.newChannel); - this.result.setChannelHungup(true); - - PBX pbx = PBXFactory.getActivePBX(); - try - { - pbx.hangup(this.newChannel); - } - catch (IllegalArgumentException | IllegalStateException | PBXException e) + this.originateSuccess = false; + this.hungup = true; + if (this.newChannel != null) { - logger.error(e, e); + OriginateBaseClass.logger.warn("Hanging up channel " + this.newChannel); + this.result.setChannelHungup(true); + + PBX pbx = PBXFactory.getActivePBX(); + try + { + pbx.hangup(this.newChannel); + } + catch (IllegalArgumentException | IllegalStateException | PBXException e) + { + logger.error(e, e); + } } + OriginateBaseClass.logger.warn("Notify channel 2 (" + this.monitorChannel2 + ") hungup");//$NON-NLS-2$ + originateLatch.countDown(); } - OriginateBaseClass.logger.warn("Notify channel 2 (" + this.monitorChannel2 + ") hungup");//$NON-NLS-2$ - originateLatch.countDown(); - } - } - if (event instanceof OriginateResponseEvent) - { - OriginateBaseClass.logger.debug("response : " + this.newChannel); - - final OriginateResponseEvent response = (OriginateResponseEvent) event; - OriginateBaseClass.logger.debug("OriginateResponseEvent: channel=" - + (response.isChannel() ? response.getChannel() : response.getEndPoint()) + " originateID:" - + this.originateID); - OriginateBaseClass.logger.debug("{" + response.getReason() + ":" + response.getResponse() + "}"); //$NON-NLS-2$ //$NON-NLS-3$ - if (this.originateID != null) + } + if (event instanceof OriginateResponseEvent) { - if (this.originateID.compareToIgnoreCase(response.getActionId()) == 0) + OriginateBaseClass.logger.debug("response : " + this.newChannel); + + final OriginateResponseEvent response = (OriginateResponseEvent) event; + OriginateBaseClass.logger.debug("OriginateResponseEvent: channel=" + + (response.isChannel() ? response.getChannel() : response.getEndPoint()) + " originateID:" + + this.originateID); + OriginateBaseClass.logger.debug("{" + response.getReason() + ":" + response.getResponse() + "}"); //$NON-NLS-2$ //$NON-NLS-3$ + if (this.originateID != null) { - this.originateSuccess = response.isSuccess(); - OriginateBaseClass.logger.info("OriginateResponse: matched actionId, success=" + this.originateSuccess - + " channelSeen=" + this.channelSeen); + if (this.originateID.compareToIgnoreCase(response.getActionId()) == 0) + { + this.originateSuccess = response.isSuccess(); + OriginateBaseClass.logger.info("OriginateResponse: matched actionId, success=" + + this.originateSuccess + " channelSeen=" + this.channelSeen); - this.originateSeen = true; + this.originateSeen = true; - if (originateSuccess) - { - if (newChannel == null) + if (originateSuccess) { - this.newChannel = response.getChannel(); - } - channelSeen = newChannel != null; - - // if we have also seen the channel then we can notify - // the - // originate() method - // that the call is up. Otherwise we will rely on the - // NewChannelEvent doing the - // notify. - if (this.channelSeen) - { - OriginateBaseClass.logger.info("notify originate response event " + this.originateSuccess); - originateLatch.countDown(); - } - else - { - logger.error("Originate Response didn't contain the channel"); + if (newChannel == null) + { + this.newChannel = response.getChannel(); + } + channelSeen = newChannel != null; + + // if we have also seen the channel then we can + // notify + // the + // originate() method + // that the call is up. Otherwise we will rely on + // the + // NewChannelEvent doing the + // notify. + if (this.channelSeen) + { + OriginateBaseClass.logger.info("notify originate response event " + this.originateSuccess); + originateLatch.countDown(); + } + else + { + logger.error("Originate Response didn't contain the channel"); + } } } } + else + { + OriginateBaseClass.logger.warn("actionid is null"); + } } - else - { - OriginateBaseClass.logger.warn("actionid is null"); - } - } - if (event instanceof NewChannelEvent) - { - final NewChannelEvent newState = (NewChannelEvent) event; - if (channelId.equalsIgnoreCase(newState.getChannel().getUniqueId())) + if (event instanceof NewChannelEvent) { - final Channel channel = newState.getChannel(); + final NewChannelEvent newState = (NewChannelEvent) event; + if (channelId.equalsIgnoreCase(newState.getChannel().getUniqueId())) + { + final Channel channel = newState.getChannel(); - OriginateBaseClass.logger.info("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-2$ - + " state =" + newState.getChannelStateDesc() + " state =" + newState.getChannelState()); //$NON-NLS-2$ + OriginateBaseClass.logger.info("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-2$ + + " state =" + newState.getChannelStateDesc() + " state =" + newState.getChannelState()); //$NON-NLS-2$ - handleId(channel); + handleId(channel); + } } - } - if (event instanceof BridgeEvent) - { - if (((BridgeEvent) event).isLink()) + if (event instanceof BridgeEvent) { - final BridgeEvent bridgeEvent = (BridgeEvent) event; - Channel channel = bridgeEvent.getChannel1(); - if (bridgeEvent.getChannel1().isLocal()) - { - channel = bridgeEvent.getChannel2(); - } - if (channelId.equalsIgnoreCase(bridgeEvent.getChannel1().getUniqueId()) - || channelId.equalsIgnoreCase(bridgeEvent.getChannel2().getUniqueId())) + if (((BridgeEvent) event).isLink()) { + final BridgeEvent bridgeEvent = (BridgeEvent) event; + Channel channel = bridgeEvent.getChannel1(); + if (bridgeEvent.getChannel1().isLocal()) + { + channel = bridgeEvent.getChannel2(); + } + if (channelId.equalsIgnoreCase(bridgeEvent.getChannel1().getUniqueId()) + || channelId.equalsIgnoreCase(bridgeEvent.getChannel2().getUniqueId())) + { - OriginateBaseClass.logger - .info("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ - + " channel2 =" + bridgeEvent.getChannel2()); + OriginateBaseClass.logger + .info("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ + + " channel2 =" + bridgeEvent.getChannel2()); - handleId(channel); + handleId(channel); + } } - } - } + } - if (event instanceof DialEndEvent) - { - if (channelId.equalsIgnoreCase(((DialEndEvent) event).getDestChannel().getUniqueId())) + if (event instanceof DialEndEvent) { - String forward = ((DialEndEvent) event).getForward(); - if (forward != null && forward.length() > 0) + if (channelId.equalsIgnoreCase(((DialEndEvent) event).getDestChannel().getUniqueId())) { - logger.warn("DialEndEvent"); - originateLatch.countDown(); + String forward = ((DialEndEvent) event).getForward(); + if (forward != null && forward.length() > 0) + { + logger.warn("DialEndEvent"); + originateLatch.countDown(); + } } } } diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java new file mode 100644 index 000000000..7888abd1c --- /dev/null +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -0,0 +1,238 @@ +package org.asteriskjava.util; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +public class Locker +{ + + private static final Log logger = LogFactory.getLog(Locker.class); + + private static volatile boolean diags = false; + private static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + + private static final Map lockObjectMap = new WeakHashMap<>(); + + private static final Object mapSync = new Object(); + + // keep references to LockStats so the WeakHashMap won't remove them between + // reporting intervals + private static final List keepList = new LinkedList<>(); + + public static LockCloser lock(final Object sync) + { + LockStats finalStats; + synchronized (mapSync) + { + LockStats stats = lockObjectMap.get(System.identityHashCode(sync)); + if (stats == null) + { + String name = getCaller(sync); + + stats = new LockStats(sync, name); + + lockObjectMap.put(System.identityHashCode(sync), stats); + if (diags) + { + keepList.add(stats); + } + } + finalStats = stats; + } + + try + { + if (diags) + { + return lockWithDiags(finalStats); + } + return simpleLock(finalStats); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + + } + + private static String getCaller(Object object) + { + Exception ex = new Exception(); + StackTraceElement[] trace = ex.getStackTrace(); + String name = object.getClass().getCanonicalName(); + for (StackTraceElement element : trace) + { + if (element.getFileName() != null && !element.getFileName().contains(Locker.class.getSimpleName())) + { + name = element.getFileName() + " " + element.getMethodName() + " " + element.getLineNumber() + " " + + element.getClassName(); + break; + } + } + + return name; + } + + public interface LockCloser extends AutoCloseable + { + public void close(); + } + + private static LockCloser simpleLock(LockStats stats) throws InterruptedException + { + Semaphore lock = stats.semaphore; + lock.acquire(); + + return new LockCloser() + { + + @Override + public void close() + { + lock.release(); + stats.lastUsed.set(System.currentTimeMillis()); + } + }; + } + + private static LockCloser lockWithDiags(LockStats stats) throws InterruptedException + { + + int offset = stats.requested.incrementAndGet(); + long waitStart = System.currentTimeMillis(); + stats.lastUsed.set(waitStart); + + Semaphore lock = stats.semaphore; + lock.acquire(); + stats.acquired.getAndIncrement(); + long acquiredAt = System.currentTimeMillis(); + + return new LockCloser() + { + + @Override + public void close() + { + lock.release(); + long holdTime = System.currentTimeMillis() - acquiredAt; + long waitTime = acquiredAt - waitStart; + stats.totalWaitTime.addAndGet(waitTime); + stats.totalHoldTime.addAndGet(holdTime); + stats.lastUsed.set(System.currentTimeMillis()); + + long waiters = stats.requested.get() - offset; + + stats.waited.addAndGet((int) waiters); + if (waiters > 0 && holdTime > 1) + { + // some threads waited + Exception trace = new Exception("Lock held for (" + holdTime + "MS), " + waiters + + " threads waited for some of that time! " + getCaller(stats.object)); + logger.warn(trace); + if (holdTime > stats.getAverageHoldTime() * 10.0) + { + logger.error(trace, trace); + } + } + + if (holdTime > stats.getAverageHoldTime() * 2.0) + { + // long hold! + Exception trace = new Exception("Lock hold of lock (" + holdTime + "MS), average is " + + stats.getAverageHoldTime() + " " + getCaller(stats.object)); + logger.warn(trace); + if (holdTime > stats.getAverageHoldTime() * 10.0) + { + logger.error(trace, trace); + } + } + } + }; + + } + + public static void enable() + { + diags = true; + executor.scheduleWithFixedDelay(() -> { + dumpStats(); + }, 1, 1, TimeUnit.MINUTES); + + } + + private static void dumpStats() + { + List stats = new LinkedList<>(); + + synchronized (mapSync) + { + stats.addAll(lockObjectMap.values()); + keepList.clear(); + } + + for (LockStats stat : stats) + { + if (stat.waited.get() > 0) + { + logger.warn(stat); + } + } + + logger.warn("Dump Lock Stats finished."); + } + + static class LockStats + { + + @Override + public String toString() + { + return "LockStats [totalWaitTime=" + totalWaitTime + ", totalHoldTime=" + totalHoldTime + ", waited=" + waited + + ", acquired=" + acquired + ", object=" + name + "]"; + } + + final Semaphore semaphore = new Semaphore(1, true); + + // this reference to object stops the WeakRefHashMap removing this + // LockStats from + // the map + final Object object; + + final String name; + + long created = System.currentTimeMillis(); + AtomicLong lastUsed = new AtomicLong(created); + + public AtomicLong totalWaitTime = new AtomicLong(); + public AtomicLong totalHoldTime = new AtomicLong(); + AtomicInteger requested = new AtomicInteger(); + AtomicInteger waited = new AtomicInteger(); + AtomicInteger acquired = new AtomicInteger(); + + LockStats(Object object, String name) + { + this.object = object; + this.name = name; + } + + double getAverageHoldTime() + { + double hold = totalHoldTime.get(); + double count = acquired.get(); + if (count < 10) + { + return 250.0; + } + return Math.max(hold / count, 10); + } + } + +} diff --git a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java index fab787e00..3370fe5d9 100644 --- a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java +++ b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java @@ -27,7 +27,7 @@ public class FastScannerNl implements FastScanner protected int end = 0; protected int start = 0; private boolean closed = false; - protected final Object sync = new Object(); + // protected final Object sync = new Object(); private boolean isFirst = true; @@ -147,25 +147,25 @@ protected String getLine(boolean endOfLine) public void close() { - synchronized (sync) + // synchronized (sync) + // { + if (closed) + return; + if (readableReference.get() instanceof Closeable) { - if (closed) - return; - if (readableReference.get() instanceof Closeable) + try { - try - { - ((Closeable) readableReference.get()).close(); - // closeFileWriter(); - } - catch (IOException ioe) - { - logger.error(ioe, ioe); - } + ((Closeable) readableReference.get()).close(); + // closeFileWriter(); + } + catch (IOException ioe) + { + logger.error(ioe, ioe); } - readableReference.set(null); - closed = true; } + readableReference.set(null); + closed = true; + // } } @SuppressWarnings("unused") From 2f872ab74b1347ffc29936fcd67e4dc2c8b27515 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 2 Feb 2021 15:20:39 +1100 Subject: [PATCH 406/802] add test for Locker and remove some unused code --- .../java/org/asteriskjava/util/Locker.java | 80 ++++++++++++------- .../org/asteriskjava/util/LockerTest.java | 52 ++++++++++++ 2 files changed, 101 insertions(+), 31 deletions(-) create mode 100644 src/test/java/org/asteriskjava/util/LockerTest.java diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index 7888abd1c..f4464ace8 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -9,7 +9,6 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; public class Locker { @@ -32,6 +31,7 @@ public static LockCloser lock(final Object sync) LockStats finalStats; synchronized (mapSync) { + // find or create the semaphore for locking LockStats stats = lockObjectMap.get(System.identityHashCode(sync)); if (stats == null) { @@ -63,6 +63,12 @@ public static LockCloser lock(final Object sync) } + /** + * determine the caller to Locker + * + * @param object + * @return + */ private static String getCaller(Object object) { Exception ex = new Exception(); @@ -98,7 +104,6 @@ private static LockCloser simpleLock(LockStats stats) throws InterruptedExceptio public void close() { lock.release(); - stats.lastUsed.set(System.currentTimeMillis()); } }; } @@ -108,7 +113,6 @@ private static LockCloser lockWithDiags(LockStats stats) throws InterruptedExcep int offset = stats.requested.incrementAndGet(); long waitStart = System.currentTimeMillis(); - stats.lastUsed.set(waitStart); Semaphore lock = stats.semaphore; lock.acquire(); @@ -121,36 +125,43 @@ private static LockCloser lockWithDiags(LockStats stats) throws InterruptedExcep @Override public void close() { + // ignore any wait that may have been caused by Locker code, so + // count the waiters before we release the lock + long waiters = stats.requested.get() - offset; + stats.waited.addAndGet((int) waiters); + + // release the lock lock.release(); - long holdTime = System.currentTimeMillis() - acquiredAt; - long waitTime = acquiredAt - waitStart; + + // count the time waiting and holding the lock + int holdTime = (int) (System.currentTimeMillis() - acquiredAt); + int waitTime = (int) (acquiredAt - waitStart); stats.totalWaitTime.addAndGet(waitTime); stats.totalHoldTime.addAndGet(holdTime); - stats.lastUsed.set(System.currentTimeMillis()); - long waiters = stats.requested.get() - offset; - - stats.waited.addAndGet((int) waiters); if (waiters > 0 && holdTime > 1) { // some threads waited - Exception trace = new Exception("Lock held for (" + holdTime + "MS), " + waiters - + " threads waited for some of that time! " + getCaller(stats.object)); - logger.warn(trace); + String message = "Lock held for (" + holdTime + "MS), " + waiters + + " threads waited for some of that time! " + getCaller(stats.object); + logger.warn(message); if (holdTime > stats.getAverageHoldTime() * 10.0) { + Exception trace = new Exception(message); logger.error(trace, trace); } } - if (holdTime > stats.getAverageHoldTime() * 2.0) + if (holdTime > stats.getAverageHoldTime() * 4.0) { // long hold! - Exception trace = new Exception("Lock hold of lock (" + holdTime + "MS), average is " - + stats.getAverageHoldTime() + " " + getCaller(stats.object)); - logger.warn(trace); + String message = "Lock hold of lock (" + holdTime + "MS), average is " + stats.getAverageHoldTime() + " " + + getCaller(stats.object); + + logger.warn(message); if (holdTime > stats.getAverageHoldTime() * 10.0) { + Exception trace = new Exception(message); logger.error(trace, trace); } } @@ -159,12 +170,22 @@ public void close() } + /** + * start dumping lock stats once per minute, can't be stopped once started. + */ public static void enable() { - diags = true; - executor.scheduleWithFixedDelay(() -> { - dumpStats(); - }, 1, 1, TimeUnit.MINUTES); + if (!diags) + { + diags = true; + executor.scheduleWithFixedDelay(() -> { + dumpStats(); + }, 1, 1, TimeUnit.MINUTES); + } + else + { + logger.warn("Already enabled"); + } } @@ -208,14 +229,11 @@ public String toString() final String name; - long created = System.currentTimeMillis(); - AtomicLong lastUsed = new AtomicLong(created); - - public AtomicLong totalWaitTime = new AtomicLong(); - public AtomicLong totalHoldTime = new AtomicLong(); - AtomicInteger requested = new AtomicInteger(); - AtomicInteger waited = new AtomicInteger(); - AtomicInteger acquired = new AtomicInteger(); + final AtomicInteger totalWaitTime = new AtomicInteger(); + final AtomicInteger totalHoldTime = new AtomicInteger(); + final AtomicInteger requested = new AtomicInteger(); + final AtomicInteger waited = new AtomicInteger(); + final AtomicInteger acquired = new AtomicInteger(); LockStats(Object object, String name) { @@ -225,13 +243,13 @@ public String toString() double getAverageHoldTime() { - double hold = totalHoldTime.get(); - double count = acquired.get(); + long hold = totalHoldTime.get(); + long count = acquired.get(); if (count < 10) { return 250.0; } - return Math.max(hold / count, 10); + return Math.max(hold / count, 50); } } diff --git a/src/test/java/org/asteriskjava/util/LockerTest.java b/src/test/java/org/asteriskjava/util/LockerTest.java new file mode 100644 index 000000000..7d36b5990 --- /dev/null +++ b/src/test/java/org/asteriskjava/util/LockerTest.java @@ -0,0 +1,52 @@ +package org.asteriskjava.util; + +import org.asteriskjava.util.Locker.LockCloser; +import org.junit.Test; + +public class LockerTest +{ + + private final Object sync = new Object(); + + @Test + public void test() + { + int seconds = 2; + + int a = 0; + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < seconds * 1000) + { + try (LockCloser closer = Locker.lock(sync)) + { + a++; + } + } + System.out.println(a / seconds + " Locker per second"); + + Locker.enable(); + a = 0; + start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < seconds * 1000) + { + try (LockCloser closer = Locker.lock(sync)) + { + a++; + } + } + System.out.println(a / seconds + " Locker With Diags per second"); + + a = 0; + start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < seconds * 1000) + { + synchronized (sync) + { + a++; + } + } + System.out.println(a / seconds + " Synchronized per second"); + + } + +} From 7d7c23ea640cf27bcbec99856a445217a17a6525 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 2 Feb 2021 15:27:47 +1100 Subject: [PATCH 407/802] increase tollerance --- src/main/java/org/asteriskjava/util/Locker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index f4464ace8..4e332b7bf 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -152,7 +152,7 @@ public void close() } } - if (holdTime > stats.getAverageHoldTime() * 4.0) + if (holdTime > stats.getAverageHoldTime() * 5.0) { // long hold! String message = "Lock hold of lock (" + holdTime + "MS), average is " + stats.getAverageHoldTime() + " " From a3927664dddb21b7e67306a31f9acdf60dfd4f20 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 2 Feb 2021 15:50:36 +1100 Subject: [PATCH 408/802] reduce logging --- src/main/java/org/asteriskjava/util/Locker.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index 4e332b7bf..bd3ab6bd0 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -139,27 +139,28 @@ public void close() stats.totalWaitTime.addAndGet(waitTime); stats.totalHoldTime.addAndGet(holdTime); - if (waiters > 0 && holdTime > 1) + long averageHoldTime = stats.getAverageHoldTime(); + if (waiters > 0 && holdTime > averageHoldTime * 2) { // some threads waited String message = "Lock held for (" + holdTime + "MS), " + waiters + " threads waited for some of that time! " + getCaller(stats.object); logger.warn(message); - if (holdTime > stats.getAverageHoldTime() * 10.0) + if (holdTime > averageHoldTime * 10.0) { Exception trace = new Exception(message); logger.error(trace, trace); } } - if (holdTime > stats.getAverageHoldTime() * 5.0) + if (holdTime > averageHoldTime * 5.0) { // long hold! String message = "Lock hold of lock (" + holdTime + "MS), average is " + stats.getAverageHoldTime() + " " + getCaller(stats.object); logger.warn(message); - if (holdTime > stats.getAverageHoldTime() * 10.0) + if (holdTime > averageHoldTime * 10.0) { Exception trace = new Exception(message); logger.error(trace, trace); @@ -241,13 +242,13 @@ public String toString() this.name = name; } - double getAverageHoldTime() + long getAverageHoldTime() { long hold = totalHoldTime.get(); long count = acquired.get(); if (count < 10) { - return 250.0; + return 250; } return Math.max(hold / count, 50); } From cb0477f81f737940d09698dc7d00afe6149fa70c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 3 Feb 2021 15:26:27 +1100 Subject: [PATCH 409/802] improve logging of blocking thread --- .../java/org/asteriskjava/util/Locker.java | 70 +++++++++++++++++-- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index bd3ab6bd0..065cddc79 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -9,6 +9,7 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; public class Locker { @@ -114,10 +115,18 @@ private static LockCloser lockWithDiags(LockStats stats) throws InterruptedExcep int offset = stats.requested.incrementAndGet(); long waitStart = System.currentTimeMillis(); + int ctr = 0; Semaphore lock = stats.semaphore; - lock.acquire(); + while (!lock.tryAcquire(500, TimeUnit.MILLISECONDS)) + { + ctr++; + dumpBlocker(stats, ctr); + } + stats.dumped = false; stats.acquired.getAndIncrement(); + long acquiredAt = System.currentTimeMillis(); + stats.threadHoldingLock.set(Thread.currentThread()); return new LockCloser() { @@ -130,6 +139,7 @@ public void close() long waiters = stats.requested.get() - offset; stats.waited.addAndGet((int) waiters); + boolean dumped = stats.dumped; // release the lock lock.release(); @@ -140,13 +150,13 @@ public void close() stats.totalHoldTime.addAndGet(holdTime); long averageHoldTime = stats.getAverageHoldTime(); - if (waiters > 0 && holdTime > averageHoldTime * 2) + if (waiters > 0 && holdTime > averageHoldTime * 2 || dumped) { // some threads waited String message = "Lock held for (" + holdTime + "MS), " + waiters + " threads waited for some of that time! " + getCaller(stats.object); logger.warn(message); - if (holdTime > averageHoldTime * 10.0) + if (holdTime > averageHoldTime * 10.0 || dumped) { Exception trace = new Exception(message); logger.error(trace, trace); @@ -171,6 +181,45 @@ public void close() } + private static void dumpBlocker(LockStats stats, int ctr) + { + synchronized (stats) + { + if (!stats.dumped) + { + + Thread thread = stats.threadHoldingLock.get(); + stats.dumped = true; + if (thread != null) + { + + StackTraceElement[] trace = thread.getStackTrace(); + + String dump = ""; + + int i = 0; + for (; i < trace.length; i++) + { + StackTraceElement ste = trace[i]; + dump += "\tat " + ste.toString(); + dump += '\n'; + } + logger.error("Waiting on lock... blocked by..."); + logger.error(dump); + } + else + { + logger.error("Thread hasn't been set"); + } + + } + else + { + logger.warn("Still waiting " + ctr); + } + } + } + /** * start dumping lock stats once per minute, can't be stopped once started. */ @@ -190,6 +239,8 @@ public static void enable() } + private static volatile boolean first = true; + private static void dumpStats() { List stats = new LinkedList<>(); @@ -200,15 +251,21 @@ private static void dumpStats() keepList.clear(); } + boolean activity = false; for (LockStats stat : stats) { - if (stat.waited.get() > 0) + if ((stat.waited.get() > 0 && stat.totalWaitTime.get() > stat.getAverageHoldTime()) || first) { + activity = true; logger.warn(stat); } } - logger.warn("Dump Lock Stats finished."); + if (first || activity) + { + logger.warn("Dump Lock Stats finished. Will dump every minute when there is contention..."); + first = false; + } } static class LockStats @@ -229,12 +286,13 @@ public String toString() final Object object; final String name; - + final AtomicReference threadHoldingLock = new AtomicReference<>(); final AtomicInteger totalWaitTime = new AtomicInteger(); final AtomicInteger totalHoldTime = new AtomicInteger(); final AtomicInteger requested = new AtomicInteger(); final AtomicInteger waited = new AtomicInteger(); final AtomicInteger acquired = new AtomicInteger(); + volatile boolean dumped = false; LockStats(Object object, String name) { From 75e505a1e03d4d9b82a92cf69a6cb5d11a2e7d06 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 4 Feb 2021 13:13:38 +1100 Subject: [PATCH 410/802] reduce timeout check to 250 ms --- src/main/java/org/asteriskjava/util/Locker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index 065cddc79..6f900d905 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -117,7 +117,7 @@ private static LockCloser lockWithDiags(LockStats stats) throws InterruptedExcep int ctr = 0; Semaphore lock = stats.semaphore; - while (!lock.tryAcquire(500, TimeUnit.MILLISECONDS)) + while (!lock.tryAcquire(250, TimeUnit.MILLISECONDS)) { ctr++; dumpBlocker(stats, ctr); From f5a7f65e612e4f5d5723f7e734db6f70180c0a43 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 9 Feb 2021 10:26:19 +1100 Subject: [PATCH 411/802] change Lockable and withLock --- .../asteriskjava/config/ConfigFileImpl.java | 10 +- .../fastagi/AbstractMappingStrategy.java | 3 +- .../asteriskjava/fastagi/AsyncAgiServer.java | 13 +- .../ResourceBundleMappingStrategy.java | 3 +- .../live/internal/AbstractLiveObject.java | 3 +- .../live/internal/AgentManager.java | 27 ++- .../live/internal/AsteriskAgentImpl.java | 3 +- .../live/internal/AsteriskChannelImpl.java | 107 +++++----- .../live/internal/AsteriskQueueEntryImpl.java | 7 +- .../live/internal/AsteriskQueueImpl.java | 66 +++---- .../internal/AsteriskQueueMemberImpl.java | 11 +- .../live/internal/AsteriskServerImpl.java | 52 ++--- .../live/internal/ChannelManager.java | 68 +++---- .../live/internal/MeetMeManager.java | 13 +- .../live/internal/MeetMeRoomImpl.java | 21 +- .../live/internal/MeetMeUserImpl.java | 7 +- .../live/internal/QueueManager.java | 19 +- .../org/asteriskjava/manager/PingThread.java | 13 +- .../internal/ManagerConnectionImpl.java | 53 ++--- .../manager/internal/ManagerWriterImpl.java | 8 +- .../manager/internal/ResponseEventsImpl.java | 8 +- .../bridge/BridgeState.java | 11 +- .../pbx/internal/activity/ActivityHelper.java | 3 +- .../activity/BlindTransferActivityImpl.java | 3 +- .../internal/activity/ParkActivityImpl.java | 3 +- .../internal/activity/SplitActivityImpl.java | 3 +- .../pbx/internal/asterisk/MeetmeRoom.java | 12 +- .../internal/asterisk/MeetmeRoomControl.java | 9 +- .../pbx/internal/core/AsteriskPBX.java | 5 +- .../pbx/internal/core/CallTracker.java | 20 +- .../core/CoherentManagerEventQueue.java | 20 +- .../pbx/internal/core/ListenerManager.java | 3 +- .../pbx/internal/core/LiveChannelManager.java | 9 +- .../asteriskjava/pbx/internal/core/Peer.java | 18 +- .../pbx/internal/core/PeerMonitor.java | 30 ++- .../managerAPI/EventListenerBaseClass.java | 3 +- .../managerAPI/OriginateBaseClass.java | 3 +- .../java/org/asteriskjava/util/Lockable.java | 129 ++++++++++++ .../org/asteriskjava/util/LockableList.java | 187 ++++++++++++++++++ .../org/asteriskjava/util/LockableMap.java | 148 ++++++++++++++ .../org/asteriskjava/util/LockableSet.java | 124 ++++++++++++ .../java/org/asteriskjava/util/Locker.java | 142 ++++--------- .../org/asteriskjava/util/LockerTest.java | 6 +- 43 files changed, 961 insertions(+), 445 deletions(-) create mode 100644 src/main/java/org/asteriskjava/util/Lockable.java create mode 100644 src/main/java/org/asteriskjava/util/LockableList.java create mode 100644 src/main/java/org/asteriskjava/util/LockableMap.java create mode 100644 src/main/java/org/asteriskjava/util/LockableSet.java diff --git a/src/main/java/org/asteriskjava/config/ConfigFileImpl.java b/src/main/java/org/asteriskjava/config/ConfigFileImpl.java index a14c11ce6..dc79a3cb0 100644 --- a/src/main/java/org/asteriskjava/config/ConfigFileImpl.java +++ b/src/main/java/org/asteriskjava/config/ConfigFileImpl.java @@ -21,7 +21,7 @@ import java.util.Map; import java.util.TreeMap; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableMap; import org.asteriskjava.util.Locker.LockCloser; /** @@ -34,12 +34,12 @@ public class ConfigFileImpl implements ConfigFile { private final String filename; - protected final Map categories; + protected final LockableMap categories; public ConfigFileImpl(String filename, Map categories) { this.filename = filename; - this.categories = categories; + this.categories = new LockableMap<>(categories); } public String getFilename() @@ -53,7 +53,7 @@ public Map> getCategories() c = new TreeMap<>(); - try (LockCloser closer = Locker.lock(categories)) + try (LockCloser closer = categories.withLock()) { for (Category category : categories.values()) { @@ -129,7 +129,7 @@ public List getValues(String categoryName, String key) protected Category getCategory(String name) { - try (LockCloser closer = Locker.lock(categories)) + try (LockCloser closer = categories.withLock()) { return categories.get(name); } diff --git a/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java b/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java index bcf043784..8055c696a 100644 --- a/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java +++ b/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; +import org.asteriskjava.util.Lockable; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -34,7 +35,7 @@ * @author srt * @since 0.3 */ -public abstract class AbstractMappingStrategy implements MappingStrategy +public abstract class AbstractMappingStrategy extends Lockable implements MappingStrategy { /** * Reference to Asterisk-Java's logging subsystem. diff --git a/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java b/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java index 69b1c93ab..f5baa1d9c 100644 --- a/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java @@ -1,7 +1,6 @@ package org.asteriskjava.fastagi; import java.util.HashMap; -import java.util.Map; import java.util.concurrent.RejectedExecutionException; import org.asteriskjava.fastagi.internal.AsyncAgiConnectionHandler; @@ -11,7 +10,7 @@ import org.asteriskjava.manager.event.AsyncAgiEvent; import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.event.RenameEvent; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableMap; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -26,7 +25,7 @@ public class AsyncAgiServer extends AbstractAgiServer implements ManagerEventListener { private final Log logger = LogFactory.getLog(getClass()); - private final Map connectionHandlers; + private final LockableMap connectionHandlers; /** * Creates a new AsyncAgiServer with a {@link DefaultAgiChannelFactory}. @@ -55,7 +54,7 @@ public AsyncAgiServer() public AsyncAgiServer(AgiChannelFactory agiChannelFactory) { super(agiChannelFactory); - this.connectionHandlers = new HashMap<>(); + this.connectionHandlers = new LockableMap<>(new HashMap<>()); } /** @@ -208,7 +207,7 @@ private void handleRenameEvent(RenameEvent renameEvent) private AsyncAgiConnectionHandler getConnectionHandler(ManagerConnection connection, String channelName) { - try (LockCloser closer = Locker.lock(connectionHandlers)) + try (LockCloser closer = connectionHandlers.withLock()) { return connectionHandlers.get(calculateHashKey(connection, channelName)); } @@ -217,7 +216,7 @@ private AsyncAgiConnectionHandler getConnectionHandler(ManagerConnection connect private void setConnectionHandler(ManagerConnection connection, String channelName, AsyncAgiConnectionHandler connectionHandler) { - try (LockCloser closer = Locker.lock(connectionHandlers)) + try (LockCloser closer = connectionHandlers.withLock()) { connectionHandlers.put(calculateHashKey(connection, channelName), connectionHandler); } @@ -225,7 +224,7 @@ private void setConnectionHandler(ManagerConnection connection, String channelNa private void removeConnectionHandler(ManagerConnection connection, String channelName) { - try (LockCloser closer = Locker.lock(connectionHandlers)) + try (LockCloser closer = connectionHandlers.withLock()) { connectionHandlers.remove(calculateHashKey(connection, channelName)); } diff --git a/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java b/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java index 3da8617b7..ea76dca6d 100644 --- a/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java +++ b/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java @@ -23,7 +23,6 @@ import java.util.MissingResourceException; import java.util.ResourceBundle; -import org.asteriskjava.util.Locker; import org.asteriskjava.util.Locker.LockCloser; /** @@ -116,7 +115,7 @@ public ResourceBundleMappingStrategy(String resourceBundleName, boolean shareIns public void setResourceBundleName(String resourceBundleName) { this.resourceBundleName = resourceBundleName; - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { this.mappings = null; this.instances = null; diff --git a/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java b/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java index 0ae501c3c..de2f2ecc5 100644 --- a/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java +++ b/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java @@ -21,6 +21,7 @@ import org.asteriskjava.live.AsteriskServer; import org.asteriskjava.live.LiveObject; +import org.asteriskjava.util.Lockable; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -30,7 +31,7 @@ * @author srt * @since 0.3 */ -abstract class AbstractLiveObject implements LiveObject +abstract class AbstractLiveObject extends Lockable implements LiveObject { private final Log logger = LogFactory.getLog(this.getClass()); private final PropertyChangeSupport changes; diff --git a/src/main/java/org/asteriskjava/live/internal/AgentManager.java b/src/main/java/org/asteriskjava/live/internal/AgentManager.java index b7a878256..8cd1744e2 100644 --- a/src/main/java/org/asteriskjava/live/internal/AgentManager.java +++ b/src/main/java/org/asteriskjava/live/internal/AgentManager.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.Map; import org.asteriskjava.live.AgentState; import org.asteriskjava.live.AsteriskAgent; @@ -35,7 +34,7 @@ import org.asteriskjava.manager.event.AgentLogoffEvent; import org.asteriskjava.manager.event.AgentsEvent; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableMap; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -59,19 +58,19 @@ public class AgentManager /** * A Map of agents by thier agentId. */ - private final Map agents; + private final LockableMap agents; /** * A Map of agent in state RINGING by the caller id. Needed to return agent * into idle state, if call was not conneted. */ - private final Map ringingAgents; + private final LockableMap ringingAgents; AgentManager(AsteriskServerImpl asteriskServerImpl) { this.server = asteriskServerImpl; - agents = new HashMap<>(); - ringingAgents = new HashMap<>(); + agents = new LockableMap<>(new HashMap<>()); + ringingAgents = new LockableMap<>(new HashMap<>()); } /** @@ -99,7 +98,7 @@ void initialize() throws ManagerCommunicationException void disconnected() { - try (LockCloser closer = Locker.lock(agents)) + try (LockCloser closer = agents.withLock()) { agents.clear(); } @@ -126,7 +125,7 @@ void handleAgentsEvent(AgentsEvent event) */ private void addAgent(AsteriskAgentImpl agent) { - try (LockCloser closer = Locker.lock(agents)) + try (LockCloser closer = agents.withLock()) { agents.put(agent.getAgentId(), agent); } @@ -141,7 +140,7 @@ private void addAgent(AsteriskAgentImpl agent) */ AsteriskAgentImpl getAgentByAgentId(String agentId) { - try (LockCloser closer = Locker.lock(agents)) + try (LockCloser closer = agents.withLock()) { return agents.get(agentId); } @@ -172,7 +171,7 @@ void handleAgentCalledEvent(AgentCalledEvent event) private void updateAgentState(AsteriskAgentImpl agent, AgentState newState) { logger.info("Set state of agent " + agent.getAgentId() + " to " + newState); - try (LockCloser closer = Locker.lock(agent)) + try (LockCloser closer = agent.withLock()) { agent.updateState(newState); } @@ -188,7 +187,7 @@ private void updateAgentState(AsteriskAgentImpl agent, AgentState newState) */ private void updateRingingAgents(String channelCalling, AsteriskAgentImpl agent) { - try (LockCloser closer = Locker.lock(ringingAgents)) + try (LockCloser closer = ringingAgents.withLock()) { if (ringingAgents.containsKey(channelCalling)) { @@ -224,7 +223,7 @@ void handleAgentLoginEvent(AgentLoginEvent event) AsteriskAgentImpl agent = getAgentByAgentId("Agent/" + event.getAgent()); if (agent == null) { - try (LockCloser closer = Locker.lock(agents)) + try (LockCloser closer = agents.withLock()) { logger.error("Ignored AgentLoginEvent for unknown agent " + event.getAgent() + ". Agents: " + agents.values().toString()); @@ -262,7 +261,7 @@ void handleAgentCallbackLoginEvent(AgentCallbackLoginEvent event) AsteriskAgentImpl agent = getAgentByAgentId("Agent/" + event.getAgent()); if (agent == null) { - try (LockCloser closer = Locker.lock(agents)) + try (LockCloser closer = agents.withLock()) { logger.error("Ignored AgentCallbackLoginEvent for unknown agent " + event.getAgent() + ". Agents: " + agents.values().toString()); @@ -300,7 +299,7 @@ Collection getAgents() { Collection copy; - try (LockCloser closer = Locker.lock(agents)) + try (LockCloser closer = agents.withLock()) { copy = new ArrayList(agents.values()); } diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java index b89a0ba7c..7906e3e1c 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java @@ -18,7 +18,6 @@ import org.asteriskjava.live.AgentState; import org.asteriskjava.live.AsteriskAgent; -import org.asteriskjava.util.Locker; import org.asteriskjava.util.Locker.LockCloser; /** @@ -63,7 +62,7 @@ public AgentState getState() void updateState(AgentState state) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { final AgentState oldState = this.state; this.state = state; diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java index f4c96e50e..a63664edc 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java @@ -50,7 +50,8 @@ import org.asteriskjava.manager.action.UnpauseMonitorAction; import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableList; +import org.asteriskjava.util.LockableMap; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.MixMonitorDirection; @@ -67,18 +68,18 @@ class AsteriskChannelImpl extends AbstractLiveObject implements AsteriskChannel * Date this channel has been created. */ private final Date dateOfCreation; - private final List extensionHistory; - private final List stateHistory; - private final List linkedChannelHistory; - private final List dialedChannelHistory; - private final List dialedChannels; - private final List dialingChannels; + private final LockableList extensionHistory; + private final LockableList stateHistory; + private final LockableList linkedChannelHistory; + private final LockableList dialedChannelHistory; + private final LockableList dialedChannels; + private final LockableList dialingChannels; /** * If this channel is bridged to another channel, the linkedChannels * contains the channel this channel is bridged with. */ - private final List linkedChannels; - private final Map variables; + private final LockableList linkedChannels; + private final LockableMap variables; /** * Unique id of this channel. */ @@ -183,14 +184,14 @@ class AsteriskChannelImpl extends AbstractLiveObject implements AsteriskChannel this.name = name; this.id = id; this.dateOfCreation = dateOfCreation; - this.extensionHistory = new ArrayList<>(); - this.stateHistory = new ArrayList<>(); - this.linkedChannelHistory = new ArrayList<>(); - this.dialedChannelHistory = new ArrayList<>(); - this.variables = new HashMap<>(); - this.dialedChannels = new ArrayList<>(); - this.dialingChannels = new ArrayList<>(); - this.linkedChannels = new ArrayList<>(); + this.extensionHistory = new LockableList<>(new ArrayList<>()); + this.stateHistory = new LockableList<>(new ArrayList<>()); + this.linkedChannelHistory = new LockableList<>(new ArrayList<>()); + this.dialedChannelHistory = new LockableList<>(new ArrayList<>()); + this.variables = new LockableMap<>(new HashMap<>()); + this.dialedChannels = new LockableList<>(new ArrayList<>()); + this.dialingChannels = new LockableList<>(new ArrayList<>()); + this.linkedChannels = new LockableList<>(new ArrayList<>()); } public String getId() @@ -276,7 +277,7 @@ public ChannelState getState() public boolean wasInState(ChannelState state) { - try (LockCloser closer = Locker.lock(stateHistory)) + try (LockCloser closer = stateHistory.withLock()) { for (ChannelStateHistoryEntry historyEntry : stateHistory) { @@ -304,7 +305,7 @@ public boolean wasBusy() */ void stateChanged(Date date, ChannelState state) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { final ChannelStateHistoryEntry historyEntry; final ChannelState oldState = this.state; @@ -318,7 +319,7 @@ void stateChanged(Date date, ChannelState state) // state // + " (" + name + ")"); historyEntry = new ChannelStateHistoryEntry(date, state); - try (LockCloser closer2 = Locker.lock(stateHistory)) + try (LockCloser closer2 = stateHistory.withLock()) { stateHistory.add(historyEntry); } @@ -350,7 +351,7 @@ public Extension getCurrentExtension() { final Extension extension; - try (LockCloser closer = Locker.lock(extensionHistory)) + try (LockCloser closer = extensionHistory.withLock()) { if (extensionHistory.isEmpty()) { @@ -369,7 +370,7 @@ public Extension getFirstExtension() { final Extension extension; - try (LockCloser closer = Locker.lock(extensionHistory)) + try (LockCloser closer = extensionHistory.withLock()) { if (extensionHistory.isEmpty()) { @@ -388,7 +389,7 @@ public List getExtensionHistory() { final List copy; - try (LockCloser closer = Locker.lock(extensionHistory)) + try (LockCloser closer = extensionHistory.withLock()) { copy = new ArrayList<>(extensionHistory); } @@ -409,7 +410,7 @@ void extensionVisited(Date date, Extension extension) historyEntry = new ExtensionHistoryEntry(date, extension); - try (LockCloser closer = Locker.lock(extensionHistory)) + try (LockCloser closer = extensionHistory.withLock()) { extensionHistory.add(historyEntry); } @@ -460,7 +461,7 @@ void callDetailRecordReceived(Date date, CallDetailRecordImpl callDetailRecord) */ void hungup(Date dateOfRemoval, HangupCause hangupCause, String hangupCauseText) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { this.dateOfRemoval = dateOfRemoval; this.hangupCause = hangupCause; @@ -479,7 +480,7 @@ public List getDialedChannels() { final List copy; - try (LockCloser closer = Locker.lock(dialedChannels)) + try (LockCloser closer = dialedChannels.withLock()) { copy = new ArrayList<>(dialedChannels); } @@ -491,7 +492,7 @@ public List getDialedChannels() public AsteriskChannel getDialedChannel() { - try (LockCloser closer = Locker.lock(dialedChannels)) + try (LockCloser closer = dialedChannels.withLock()) { for (AsteriskChannel channel : dialedChannels) { @@ -506,7 +507,7 @@ public List getDialedChannelHistory() { final List copy; - try (LockCloser closer = Locker.lock(dialedChannelHistory)) + try (LockCloser closer = dialedChannelHistory.withLock()) { copy = new ArrayList<>(dialedChannelHistory); } @@ -516,10 +517,10 @@ public List getDialedChannelHistory() void channelDialed(Date date, AsteriskChannel dialedChannel) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { final AsteriskChannel oldDialedChannel; - try (LockCloser closer2 = Locker.lock(dialedChannels)) + try (LockCloser closer2 = dialedChannels.withLock()) { if (dialedChannels.isEmpty()) oldDialedChannel = null; @@ -530,7 +531,7 @@ void channelDialed(Date date, AsteriskChannel dialedChannel) final DialedChannelHistoryEntry historyEntry; historyEntry = new DialedChannelHistoryEntry(date, dialedChannel); - try (LockCloser closer3 = Locker.lock(dialedChannelHistory)) + try (LockCloser closer3 = dialedChannelHistory.withLock()) { dialedChannelHistory.add(historyEntry); } @@ -543,7 +544,7 @@ void channelDialed(Date date, AsteriskChannel dialedChannel) public AsteriskChannel getDialingChannel() { - try (LockCloser closer = Locker.lock(dialingChannels)) + try (LockCloser closer = dialingChannels.withLock()) { if (dialingChannels.isEmpty()) return null; @@ -553,10 +554,10 @@ public AsteriskChannel getDialingChannel() void channelDialing(Date date, AsteriskChannel dialingChannel) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { final AsteriskChannel oldDialingChannel; - try (LockCloser closer2 = Locker.lock(this.dialingChannels)) + try (LockCloser closer2 = this.dialingChannels.withLock()) { if (this.dialingChannels.isEmpty()) { @@ -578,7 +579,7 @@ void channelDialing(Date date, AsteriskChannel dialingChannel) public AsteriskChannel getLinkedChannel() { - try (LockCloser closer = Locker.lock(linkedChannels)) + try (LockCloser closer = linkedChannels.withLock()) { if (linkedChannels.isEmpty()) return null; @@ -590,7 +591,7 @@ public List getLinkedChannelHistory() { final List copy; - try (LockCloser closer = Locker.lock(linkedChannelHistory)) + try (LockCloser closer = linkedChannelHistory.withLock()) { copy = new ArrayList<>(linkedChannelHistory); } @@ -611,10 +612,10 @@ public boolean wasLinked() */ void channelLinked(Date date, AsteriskChannel linkedChannel) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { final AsteriskChannel oldLinkedChannel; - try (LockCloser closer2 = Locker.lock(this.linkedChannels)) + try (LockCloser closer2 = this.linkedChannels.withLock()) { if (this.linkedChannels.isEmpty()) { @@ -631,7 +632,7 @@ void channelLinked(Date date, AsteriskChannel linkedChannel) final LinkedChannelHistoryEntry historyEntry; historyEntry = new LinkedChannelHistoryEntry(date, linkedChannel); - try (LockCloser closer3 = Locker.lock(linkedChannelHistory)) + try (LockCloser closer3 = linkedChannelHistory.withLock()) { linkedChannelHistory.add(historyEntry); } @@ -642,11 +643,11 @@ void channelLinked(Date date, AsteriskChannel linkedChannel) void channelUnlinked(Date date) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { final AsteriskChannel oldLinkedChannel; - try (LockCloser closer2 = Locker.lock(this.linkedChannels)) + try (LockCloser closer2 = this.linkedChannels.withLock()) { if (this.linkedChannels.isEmpty()) { @@ -661,7 +662,7 @@ void channelUnlinked(Date date) final LinkedChannelHistoryEntry historyEntry; - try (LockCloser closer3 = Locker.lock(linkedChannelHistory)) + try (LockCloser closer3 = linkedChannelHistory.withLock()) { if (linkedChannelHistory.isEmpty()) { @@ -753,7 +754,7 @@ public void redirectBothLegs(String context, String exten, int priority) { ManagerResponse response; - try (LockCloser closer = Locker.lock(linkedChannels)) + try (LockCloser closer = linkedChannels.withLock()) { if (linkedChannels.isEmpty()) { @@ -777,7 +778,7 @@ public String getVariable(String variable) throws ManagerCommunicationException, ManagerResponse response; String value; - try (LockCloser closer = Locker.lock(variables)) + try (LockCloser closer = variables.withLock()) { value = variables.get(variable); @@ -811,7 +812,7 @@ public void setVariable(String variable, String value) throws ManagerCommunicati { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } - try (LockCloser closer = Locker.lock(variables)) + try (LockCloser closer = variables.withLock()) { variables.put(variable, value); } @@ -961,7 +962,7 @@ void setParkedAt(Extension parkedAt, String parkingLot) void updateVariable(String name, String value) { - try (LockCloser closer = Locker.lock(variables)) + try (LockCloser closer = variables.withLock()) { // final String oldValue = variables.get(name); variables.put(name, value); @@ -971,7 +972,7 @@ void updateVariable(String name, String value) public Map getVariables() { - try (LockCloser closer = Locker.lock(variables)) + try (LockCloser closer = variables.withLock()) { return new HashMap<>(variables); } @@ -1033,13 +1034,12 @@ void setMonitored(boolean monitored) public String toString() { final StringBuilder sb; - final List dialedChannels; - final List dialingChannel; - final List linkedChannel; + final LockableList dialingChannel; + final LockableList linkedChannel; sb = new StringBuilder("AsteriskChannel["); - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { sb.append("id='").append(getId()).append("',"); sb.append("name='").append(getName()).append("',"); @@ -1047,7 +1047,6 @@ public String toString() sb.append("state='").append(getState()).append("',"); sb.append("account='").append(getAccount()).append("',"); sb.append("dateOfCreation=").append(getDateOfCreation()).append(","); - dialedChannels = getDialedChannels(); dialingChannel = this.dialingChannels; linkedChannel = this.linkedChannels; } @@ -1058,7 +1057,7 @@ public String toString() else { sb.append("dialedChannel=AsteriskChannel["); - try (LockCloser closer = Locker.lock(dialedChannels)) + try (LockCloser closer = dialedChannels.withLock()) { for (AsteriskChannel dialedChannel : dialedChannels) { @@ -1078,7 +1077,7 @@ public String toString() sb.append("id='").append(dialingChannel.get(0).getId()).append("',"); sb.append("name='").append(dialingChannel.get(0).getName()).append("'],"); } - try (LockCloser closer = Locker.lock(linkedChannel)) + try (LockCloser closer = linkedChannel.withLock()) { if (linkedChannel.isEmpty()) { diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java index 94236f0bb..3e46c8393 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java @@ -4,7 +4,6 @@ import org.asteriskjava.live.AsteriskQueueEntry; import org.asteriskjava.live.QueueEntryState; -import org.asteriskjava.util.Locker; import org.asteriskjava.util.Locker.LockCloser; /** @@ -77,7 +76,7 @@ public Date getDateLeft() void left(Date dateLeft) { QueueEntryState oldState; - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { oldState = this.state; this.dateLeft = dateLeft; @@ -143,7 +142,7 @@ public String toString() sb = new StringBuilder("AsteriskQueueEntry["); - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { sb.append("dateJoined=").append(getDateJoined()).append(","); sb.append("postition=").append(getPosition()).append(","); @@ -153,7 +152,7 @@ public String toString() if (channel != null) { sb.append("channel=AsteriskChannel["); - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { sb.append("id='").append(channel.getId()).append("',"); sb.append("name='").append(channel.getName()).append("'],"); diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java index e632974b5..b6fb29419 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java @@ -21,7 +21,6 @@ import java.util.Date; import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Timer; import java.util.TimerTask; @@ -30,7 +29,8 @@ import org.asteriskjava.live.AsteriskQueueListener; import org.asteriskjava.live.AsteriskQueueMember; import org.asteriskjava.util.AstUtil; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableList; +import org.asteriskjava.util.LockableMap; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -80,11 +80,11 @@ public void run() /****/ private Integer weight; - private final List entries; + private final LockableList entries; private final Timer timer; - private final Map members; - private final List listeners; - private final Map serviceLevelTimerTasks; + private final LockableMap members; + private final LockableList listeners; + private final LockableMap serviceLevelTimerTasks; AsteriskQueueImpl(AsteriskServerImpl server, String name, Integer max, String strategy, Integer serviceLevel, Integer weight, Integer calls, Integer holdTime, Integer talkTime, Integer completed, Integer abandoned, @@ -96,11 +96,11 @@ public void run() this.strategy = strategy; this.serviceLevel = serviceLevel; this.weight = weight; - entries = new ArrayList<>(25); - listeners = new ArrayList<>(); - members = new HashMap<>(); + entries = new LockableList<>(new ArrayList<>(25)); + listeners = new LockableList<>(new ArrayList<>()); + members = new LockableMap<>(new HashMap<>()); timer = new Timer("ServiceLevelTimer-" + name, true); - serviceLevelTimerTasks = new HashMap<>(); + serviceLevelTimerTasks = new LockableMap<>(new HashMap<>()); this.calls = calls; this.holdTime = holdTime; this.talkTime = talkTime; @@ -322,7 +322,7 @@ boolean setWeight(Integer weight) public List getEntries() { - try (LockCloser closer = Locker.lock(entries)) + try (LockCloser closer = entries.withLock()) { return new ArrayList(entries); } @@ -336,7 +336,7 @@ private void shift() { int currentPos = 1; // Asterisk starts at 1 - try (LockCloser closer = Locker.lock(entries)) + try (LockCloser closer = entries.withLock()) { for (AsteriskQueueEntryImpl qe : entries) { @@ -370,7 +370,7 @@ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date date { AsteriskQueueEntryImpl qe = new AsteriskQueueEntryImpl(server, this, channel, reportedPosition, dateReceived); - try (LockCloser closer = Locker.lock(entries)) + try (LockCloser closer = entries.withLock()) { if (getEntry(channel.getName()) != null) { @@ -395,7 +395,7 @@ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date date { ServiceLevelTimerTask timerTask = new ServiceLevelTimerTask(qe); timer.schedule(timerTask, delay); - try (LockCloser closer = Locker.lock(serviceLevelTimerTasks)) + try (LockCloser closer = serviceLevelTimerTasks.withLock()) { serviceLevelTimerTasks.put(qe, timerTask); } @@ -426,7 +426,7 @@ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date date */ void removeEntry(AsteriskQueueEntryImpl entry, Date dateReceived) { - try (LockCloser closer = Locker.lock(serviceLevelTimerTasks)) + try (LockCloser closer = serviceLevelTimerTasks.withLock()) { if (serviceLevelTimerTasks.containsKey(entry)) { @@ -437,7 +437,7 @@ void removeEntry(AsteriskQueueEntryImpl entry, Date dateReceived) } boolean changed; - try (LockCloser closer = Locker.lock(entries)) + try (LockCloser closer = entries.withLock()) { changed = entries.remove(entry); @@ -475,11 +475,11 @@ public String toString() sb.append("abandoned='").append(getAbandoned()).append("',"); sb.append("serviceLevelPerf='").append(getServiceLevelPerf()).append("',"); - try (LockCloser closer = Locker.lock(entries)) + try (LockCloser closer = entries.withLock()) { sb.append("entries='").append(entries.toString()).append("',"); } - try (LockCloser closer = Locker.lock(members)) + try (LockCloser closer = members.withLock()) { sb.append("members='").append(members.toString()).append("',"); } @@ -491,7 +491,7 @@ public String toString() public void addAsteriskQueueListener(AsteriskQueueListener listener) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { listeners.add(listener); } @@ -499,7 +499,7 @@ public void addAsteriskQueueListener(AsteriskQueueListener listener) public void removeAsteriskQueueListener(AsteriskQueueListener listener) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { listeners.remove(listener); } @@ -512,7 +512,7 @@ public void removeAsteriskQueueListener(AsteriskQueueListener listener) */ void fireNewEntry(AsteriskQueueEntryImpl entry) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { for (AsteriskQueueListener listener : listeners) { @@ -535,7 +535,7 @@ void fireNewEntry(AsteriskQueueEntryImpl entry) */ void fireEntryLeave(AsteriskQueueEntryImpl entry) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { for (AsteriskQueueListener listener : listeners) { @@ -559,7 +559,7 @@ void fireEntryLeave(AsteriskQueueEntryImpl entry) */ void fireMemberAdded(AsteriskQueueMemberImpl member) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { for (AsteriskQueueListener listener : listeners) { @@ -583,7 +583,7 @@ void fireMemberAdded(AsteriskQueueMemberImpl member) */ void fireMemberRemoved(AsteriskQueueMemberImpl member) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { for (AsteriskQueueListener listener : listeners) { @@ -607,7 +607,7 @@ void fireMemberRemoved(AsteriskQueueMemberImpl member) public Collection getMembers() { List listOfMembers = new ArrayList<>(members.size()); - try (LockCloser closer = Locker.lock(members)) + try (LockCloser closer = members.withLock()) { listOfMembers.addAll(members.values()); } @@ -622,7 +622,7 @@ public Collection getMembers() */ AsteriskQueueMemberImpl getMember(String location) { - try (LockCloser closer = Locker.lock(members)) + try (LockCloser closer = members.withLock()) { if (members.containsKey(location)) { @@ -639,7 +639,7 @@ AsteriskQueueMemberImpl getMember(String location) */ void addMember(AsteriskQueueMemberImpl member) { - try (LockCloser closer = Locker.lock(members)) + try (LockCloser closer = members.withLock()) { // Check if member already exists if (members.containsValue(member)) @@ -663,7 +663,7 @@ void addMember(AsteriskQueueMemberImpl member) AsteriskQueueMemberImpl getMemberByLocation(String location) { AsteriskQueueMemberImpl member; - try (LockCloser closer = Locker.lock(members)) + try (LockCloser closer = members.withLock()) { member = members.get(location); } @@ -681,7 +681,7 @@ AsteriskQueueMemberImpl getMemberByLocation(String location) */ void fireMemberStateChanged(AsteriskQueueMemberImpl member) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { for (AsteriskQueueListener listener : listeners) { @@ -705,7 +705,7 @@ void fireMemberStateChanged(AsteriskQueueMemberImpl member) */ AsteriskQueueEntryImpl getEntry(String channelName) { - try (LockCloser closer = Locker.lock(entries)) + try (LockCloser closer = entries.withLock()) { for (AsteriskQueueEntryImpl entry : entries) { @@ -725,7 +725,7 @@ AsteriskQueueEntryImpl getEntry(String channelName) */ public void removeMember(AsteriskQueueMemberImpl member) { - try (LockCloser closer = Locker.lock(members)) + try (LockCloser closer = members.withLock()) { // Check if member exists if (!members.containsValue(member)) @@ -742,7 +742,7 @@ public void removeMember(AsteriskQueueMemberImpl member) void fireServiceLevelExceeded(AsteriskQueueEntry entry) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { for (AsteriskQueueListener listener : listeners) { @@ -769,7 +769,7 @@ AsteriskQueueEntryImpl getEntry(int position) // positions in asterisk start at 1, but list starts at 0 position--; AsteriskQueueEntryImpl foundEntry = null; - try (LockCloser closer = Locker.lock(entries)) + try (LockCloser closer = entries.withLock()) { try { diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java index e4b846c1a..d760cb652 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java @@ -27,7 +27,6 @@ import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.AstUtil; -import org.asteriskjava.util.Locker; import org.asteriskjava.util.Locker.LockCloser; /** @@ -216,7 +215,7 @@ public String toString() boolean stateChanged(QueueMemberState state) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { if (!AstUtil.isEqual(this.state, state)) { @@ -231,7 +230,7 @@ boolean stateChanged(QueueMemberState state) boolean penaltyChanged(Integer penalty) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { if (!AstUtil.isEqual(this.penalty, penalty)) { @@ -247,7 +246,7 @@ boolean penaltyChanged(Integer penalty) boolean pausedChanged(boolean paused) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { if (!AstUtil.isEqual(this.paused, paused)) { @@ -262,7 +261,7 @@ boolean pausedChanged(boolean paused) boolean callsTakenChanged(Integer callsTaken) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { if (!AstUtil.isEqual(this.callsTaken, callsTaken)) { @@ -277,7 +276,7 @@ boolean callsTakenChanged(Integer callsTaken) boolean lastCallChanged(Long lastCall) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { if (!AstUtil.isEqual(this.lastCall, lastCall)) { diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java index 9c84a3f70..12c9f962e 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java @@ -25,7 +25,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -115,7 +114,10 @@ import org.asteriskjava.manager.response.ModuleCheckResponse; import org.asteriskjava.util.AstUtil; import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Lockable; +import org.asteriskjava.util.LockableList; +import org.asteriskjava.util.LockableMap; +import org.asteriskjava.util.LockableSet; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -126,7 +128,7 @@ * @author srt * @version $Id$ */ -public class AsteriskServerImpl implements AsteriskServer, ManagerEventListener +public class AsteriskServerImpl extends Lockable implements AsteriskServer, ManagerEventListener { private static final String ACTION_ID_PREFIX_ORIGINATE = "AJ_ORIGINATE_"; private static final String SHOW_VERSION_COMMAND = "show version"; @@ -150,7 +152,7 @@ public class AsteriskServerImpl implements AsteriskServer, ManagerEventListener private boolean initialized = false; private boolean initializing = false; - final Set listeners; + final LockableSet listeners; final ChannelManager channelManager; final MeetMeManager meetMeManager; @@ -172,12 +174,12 @@ public class AsteriskServerImpl implements AsteriskServer, ManagerEventListener *

    * Contains null until lazily initialized. */ - private Map versions; + private LockableMap versions; /** * Maps the traceId to the corresponding callback data. */ - private final Map originateCallbacks; + private final LockableMap originateCallbacks; private final AtomicLong idCounter; @@ -207,7 +209,7 @@ public class AsteriskServerImpl implements AsteriskServer, ManagerEventListener * events have been processed by the live ChannelManager before you receive * an event and as such the names will always match. */ - private List chainListeners = new ArrayList<>(); + private LockableList chainListeners = new LockableList<>(new ArrayList<>()); /** * Creates a new instance. @@ -215,8 +217,8 @@ public class AsteriskServerImpl implements AsteriskServer, ManagerEventListener public AsteriskServerImpl() { idCounter = new AtomicLong(); - listeners = new LinkedHashSet<>(); - originateCallbacks = new HashMap<>(); + listeners = new LockableSet<>(new LinkedHashSet<>()); + originateCallbacks = new LockableMap<>(new HashMap<>()); channelManager = new ChannelManager(this); agentManager = new AgentManager(this); meetMeManager = new MeetMeManager(this, channelManager); @@ -275,7 +277,7 @@ public void initialize() throws ManagerCommunicationException private void initializeIfNeeded() throws ManagerCommunicationException { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { if (initialized || initializing) { @@ -503,7 +505,7 @@ public void originateAsync(OriginateAction originateAction, OriginateCallback cb callbackData = new OriginateCallbackData(originateAction, DateUtil.getDate(), cb); // register callback - try (LockCloser closer = Locker.lock(originateCallbacks)) + try (LockCloser closer = originateCallbacks.withLock()) { originateCallbacks.put(traceId, callbackData); } @@ -565,7 +567,7 @@ public List getQueuesUpdatedAfter(Date date) public String getVersion() throws ManagerCommunicationException { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { final ManagerResponse response; final String command; @@ -612,10 +614,10 @@ public int[] getVersion(String file) throws ManagerCommunicationException initializeIfNeeded(); if (versions == null) { - Map map; + LockableMap map; ManagerResponse response; - map = new HashMap<>(); + map = new LockableMap<>(new HashMap<>()); try { final String command; @@ -665,7 +667,7 @@ public int[] getVersion(String file) throws ManagerCommunicationException } else { - try (LockCloser closer = Locker.lock(versions)) + try (LockCloser closer = versions.withLock()) { fileVersion = versions.get(file); } @@ -896,7 +898,7 @@ public ConfigFile getConfig(String filename) throws ManagerCommunicationExceptio public void addAsteriskServerListener(AsteriskServerListener listener) throws ManagerCommunicationException { initializeIfNeeded(); - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { if (!listeners.contains(listener)) { @@ -908,7 +910,7 @@ public void addAsteriskServerListener(AsteriskServerListener listener) throws Ma @Override public void removeAsteriskServerListener(AsteriskServerListener listener) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { listeners.remove(listener); } @@ -922,7 +924,7 @@ public boolean isAsteriskServerListening(AsteriskServerListener listener) public void addChainListener(ManagerEventListener chainListener) { - try (LockCloser closer = Locker.lock(this.chainListeners)) + try (LockCloser closer = this.chainListeners.withLock()) { if (!this.chainListeners.contains(chainListener)) this.chainListeners.add(chainListener); @@ -937,7 +939,7 @@ public void removeChainListener(ManagerEventListener chainListener) void fireNewAsteriskChannel(AsteriskChannel channel) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { for (AsteriskServerListener listener : listeners) { @@ -955,7 +957,7 @@ void fireNewAsteriskChannel(AsteriskChannel channel) void fireNewMeetMeUser(MeetMeUser user) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { for (AsteriskServerListener listener : listeners) { @@ -1026,7 +1028,7 @@ ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws Ma OriginateCallbackData getOriginateCallbackDataByTraceId(String traceId) { - try (LockCloser closer = Locker.lock(originateCallbacks)) + try (LockCloser closer = originateCallbacks.withLock()) { return originateCallbacks.get(traceId); } @@ -1214,7 +1216,7 @@ else if (event instanceof AgentLogoffEvent) */ private void fireChainListeners(ManagerEvent event) { - try (LockCloser closer = Locker.lock(this.chainListeners)) + try (LockCloser closer = this.chainListeners.withLock()) { for (ManagerEventListener listener : this.chainListeners) listener.onManagerEvent(event); @@ -1287,7 +1289,7 @@ private void handleOriginateEvent(OriginateResponseEvent originateEvent) return; } - try (LockCloser closer = Locker.lock(originateCallbacks)) + try (LockCloser closer = originateCallbacks.withLock()) { callbackData = originateCallbacks.get(traceId); if (callbackData == null) @@ -1463,7 +1465,7 @@ public Collection getAgents() throws ManagerCommunicationExceptio void fireNewAgent(AsteriskAgentImpl agent) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { for (AsteriskServerListener listener : listeners) { @@ -1481,7 +1483,7 @@ void fireNewAgent(AsteriskAgentImpl agent) void fireNewQueueEntry(AsteriskQueueEntry entry) { - try (LockCloser closer = Locker.lock(listeners)) + try (LockCloser closer = listeners.withLock()) { for (AsteriskServerListener listener : listeners) { diff --git a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java index 6a933bdd9..38978d63d 100644 --- a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java +++ b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java @@ -59,7 +59,7 @@ import org.asteriskjava.manager.event.VarSetEvent; import org.asteriskjava.util.DaemonThreadFactory; import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableMap; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -86,7 +86,7 @@ class ChannelManager /** * A map of all active channel by their unique id. */ - final Map channels = new LinkedHashMap<>(); + final LockableMap channels = new LockableMap<>(new LinkedHashMap<>()); ScheduledThreadPoolExecutor traceScheduledExecutorService; @@ -139,7 +139,7 @@ private void shutdown() { traceScheduledExecutorService.shutdown(); } - try (LockCloser closer = Locker.lock(channels)) + try (LockCloser closer = channels.withLock()) { channels.clear(); } @@ -155,7 +155,7 @@ Collection getChannels() { Collection copy; - try (LockCloser closer = Locker.lock(channels)) + try (LockCloser closer = channels.withLock()) { copy = new ArrayList<>(channels.size() + 2); for (AsteriskChannel channel : channels.values()) @@ -171,7 +171,7 @@ Collection getChannels() private void addChannel(AsteriskChannelImpl channel) { - try (LockCloser closer = Locker.lock(channels)) + try (LockCloser closer = channels.withLock()) { channels.put(channel.getId(), channel); } @@ -185,7 +185,7 @@ private void removeOldChannels() { Iterator i; - try (LockCloser closer = Locker.lock(channels)) + try (LockCloser closer = channels.withLock()) { i = channels.values().iterator(); while (i.hasNext()) @@ -316,7 +316,7 @@ void handleStatusEvent(StatusEvent event) extension = new Extension(event.getContext(), event.getExtension(), event.getPriority()); } - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.setCallerId(new CallerId(event.getCallerIdName(), event.getCallerIdNum())); channel.setAccount(event.getAccountCode()); @@ -333,7 +333,7 @@ void handleStatusEvent(StatusEvent event) { // the date used here is not correct! channel.channelLinked(event.getDateReceived(), linkedChannel); - try (LockCloser closer2 = Locker.lock(linkedChannel)) + try (LockCloser closer2 = linkedChannel.withLock()) { linkedChannel.channelLinked(event.getDateReceived(), channel); } @@ -368,7 +368,7 @@ AsteriskChannelImpl getChannelImplByName(String name) return null; } - try (LockCloser closer = Locker.lock(channels)) + try (LockCloser closer = channels.withLock()) { for (AsteriskChannelImpl tmp : channels.values()) { @@ -412,7 +412,7 @@ AsteriskChannelImpl getChannelImplByNameAndActive(String name) return null; } - try (LockCloser closer = Locker.lock(channels)) + try (LockCloser closer = channels.withLock()) { for (AsteriskChannelImpl tmp : channels.values()) { @@ -432,7 +432,7 @@ AsteriskChannelImpl getChannelImplById(String uniqueId) return null; } - try (LockCloser closer = Locker.lock(channels)) + try (LockCloser closer = channels.withLock()) { return channels.get(uniqueId); } @@ -501,7 +501,7 @@ void handleNewChannelEvent(NewChannelEvent event) else { // channel had already been created probably by a NewCallerIdEvent - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.nameChanged(event.getDateReceived(), event.getChannel()); channel.setCallerId(new CallerId(event.getCallerIdName(), event.getCallerIdNum())); @@ -525,7 +525,7 @@ void handleNewExtenEvent(NewExtenEvent event) extension = new Extension(event.getContext(), event.getExtension(), event.getPriority(), event.getApplication(), event.getAppData()); - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.extensionVisited(event.getDateReceived(), extension); } @@ -544,7 +544,7 @@ private void idChanged(AsteriskChannelImpl channel, AbstractChannelEvent event) } logger.info("Changing unique_id for '" + channel.getName() + "' from " + oldId + " to " + newId + " < " + event); - try (LockCloser closer = Locker.lock(channels)) + try (LockCloser closer = channels.withLock()) { channels.remove(oldId); channels.put(newId, channel); @@ -613,7 +613,7 @@ void handleNewStateEvent(NewStateEvent event) { logger.info("Renaming channel (following NewStateEvent) '" + channel.getName() + "' to '" + event.getChannel() + "'"); - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.nameChanged(event.getDateReceived(), event.getChannel()); } @@ -622,7 +622,7 @@ void handleNewStateEvent(NewStateEvent event) if (event.getChannelState() != null) { - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.stateChanged(event.getDateReceived(), ChannelState.valueOf(event.getChannelState())); } @@ -649,7 +649,7 @@ void handleNewCallerIdEvent(NewCallerIdEvent event) } } - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.setCallerId(new CallerId(event.getCallerIdName(), event.getCallerIdNum())); } @@ -671,7 +671,7 @@ void handleHangupEvent(HangupEvent event) cause = HangupCause.getByCode(event.getCause()); } - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.hungup(event.getDateReceived(), cause, event.getCauseTxt()); } @@ -710,11 +710,11 @@ void handleDialEvent(DialEvent event) logger.info(sourceChannel.getName() + " dialed " + destinationChannel.getName()); getTraceId(sourceChannel); getTraceId(destinationChannel); - try (LockCloser closer = Locker.lock(sourceChannel)) + try (LockCloser closer = sourceChannel.withLock()) { sourceChannel.channelDialed(event.getDateReceived(), destinationChannel); } - try (LockCloser closer = Locker.lock(destinationChannel)) + try (LockCloser closer = destinationChannel.withLock()) { destinationChannel.channelDialing(event.getDateReceived(), sourceChannel); } @@ -739,12 +739,12 @@ void handleBridgeEvent(BridgeEvent event) if (event.isLink()) { logger.info("Linking channels " + channel1.getName() + " and " + channel2.getName()); - try (LockCloser closer = Locker.lock(channel1)) + try (LockCloser closer = channel1.withLock()) { channel1.channelLinked(event.getDateReceived(), channel2); } - try (LockCloser closer = Locker.lock(channel2)) + try (LockCloser closer = channel2.withLock()) { channel2.channelLinked(event.getDateReceived(), channel1); } @@ -753,12 +753,12 @@ void handleBridgeEvent(BridgeEvent event) if (event.isUnlink()) { logger.info("Unlinking channels " + channel1.getName() + " and " + channel2.getName()); - try (LockCloser closer = Locker.lock(channel1)) + try (LockCloser closer = channel1.withLock()) { channel1.channelUnlinked(event.getDateReceived()); } - try (LockCloser closer = Locker.lock(channel2)) + try (LockCloser closer = channel2.withLock()) { channel2.channelUnlinked(event.getDateReceived()); } @@ -777,7 +777,7 @@ void handleRenameEvent(RenameEvent event) logger.info("Renaming channel '" + channel.getName() + "' to '" + event.getNewname() + "', uniqueId is " + event.getUniqueId()); - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.nameChanged(event.getDateReceived(), event.getNewname()); } @@ -797,7 +797,7 @@ void handleCdrEvent(CdrEvent event) cdr = new CallDetailRecordImpl(channel, destinationChannel, event); - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.callDetailRecordReceived(event.getDateReceived(), cdr); } @@ -833,7 +833,7 @@ void handleParkedCallEvent(ParkedCallEvent event) return; } - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { Extension ext = new Extension(null, (event.getParkingSpace() != null) ? event.getParkingSpace() : event.getExten(), 1); @@ -863,7 +863,7 @@ void handleParkedCallGiveUpEvent(ParkedCallGiveUpEvent event) return; } - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.setParkedAt(null, null); } @@ -890,7 +890,7 @@ void handleParkedCallTimeOutEvent(ParkedCallTimeOutEvent event) return; } - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.setParkedAt(null, null); } @@ -917,7 +917,7 @@ void handleUnparkedCallEvent(UnparkedCallEvent event) return; } - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.setParkedAt(null, null); } @@ -938,7 +938,7 @@ void handleVarSetEvent(VarSetEvent event) return; } - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.updateVariable(event.getVariable(), event.getValue()); } @@ -974,7 +974,7 @@ void handleDtmfEvent(DtmfEvent event) dtmfDigit = event.getDigit().charAt(0); } - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { if (event.isReceived()) { @@ -1005,7 +1005,7 @@ void handleMonitorStartEvent(MonitorStartEvent event) return; } - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.setMonitored(true); } @@ -1030,7 +1030,7 @@ void handleMonitorStopEvent(MonitorStopEvent event) return; } - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { channel.setMonitored(false); } diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java b/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java index a54e3f596..959268774 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java @@ -20,7 +20,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -35,7 +34,7 @@ import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableMap; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -57,18 +56,18 @@ class MeetMeManager /** * Maps room number to MeetMe room. */ - private final Map rooms; + private final LockableMap rooms; MeetMeManager(AsteriskServerImpl server, ChannelManager channelManager) { this.server = server; this.channelManager = channelManager; - this.rooms = new HashMap<>(); + this.rooms = new LockableMap<>(new HashMap<>()); } void initialize() { - try (LockCloser closer = Locker.lock(rooms)) + try (LockCloser closer = rooms.withLock()) { for (MeetMeRoomImpl room : rooms.values()) { @@ -89,7 +88,7 @@ Collection getMeetMeRooms() final Collection result; result = new ArrayList<>(); - try (LockCloser closer = Locker.lock(rooms)) + try (LockCloser closer = rooms.withLock()) { for (MeetMeRoom room : rooms.values()) { @@ -382,7 +381,7 @@ MeetMeRoomImpl getOrCreateRoomImpl(String roomNumber) MeetMeRoomImpl room; boolean created = false; - try (LockCloser closer = Locker.lock(rooms)) + try (LockCloser closer = rooms.withLock()) { room = rooms.get(roomNumber); if (room == null) diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java b/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java index eacf1f613..9bd50ca7a 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java @@ -19,13 +19,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.Map; import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.MeetMeRoom; import org.asteriskjava.live.MeetMeUser; import org.asteriskjava.manager.action.CommandAction; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableMap; import org.asteriskjava.util.Locker.LockCloser; /** @@ -42,13 +41,13 @@ class MeetMeRoomImpl extends AbstractLiveObject implements MeetMeRoom /** * Maps userNumber to user. */ - private final Map users; + private final LockableMap users; MeetMeRoomImpl(AsteriskServerImpl server, String roomNumber) { super(server); this.roomNumber = roomNumber; - this.users = new HashMap<>(20); + this.users = new LockableMap<>(new HashMap<>(20)); } public String getRoomNumber() @@ -58,7 +57,7 @@ public String getRoomNumber() public Collection getUsers() { - try (LockCloser closer = Locker.lock(users)) + try (LockCloser closer = users.withLock()) { return new ArrayList(users.values()); } @@ -66,7 +65,7 @@ public Collection getUsers() public boolean isEmpty() { - try (LockCloser closer = Locker.lock(users)) + try (LockCloser closer = users.withLock()) { return users.isEmpty(); } @@ -74,7 +73,7 @@ public boolean isEmpty() Collection getUserImpls() { - try (LockCloser closer = Locker.lock(users)) + try (LockCloser closer = users.withLock()) { return new ArrayList<>(users.values()); } @@ -82,7 +81,7 @@ Collection getUserImpls() void addUser(MeetMeUserImpl user) { - try (LockCloser closer = Locker.lock(users)) + try (LockCloser closer = users.withLock()) { users.put(user.getUserNumber(), user); } @@ -90,7 +89,7 @@ void addUser(MeetMeUserImpl user) MeetMeUserImpl getUser(Integer userNumber) { - try (LockCloser closer = Locker.lock(users)) + try (LockCloser closer = users.withLock()) { return users.get(userNumber); } @@ -98,7 +97,7 @@ MeetMeUserImpl getUser(Integer userNumber) void removeUser(MeetMeUserImpl user) { - try (LockCloser closer = Locker.lock(users)) + try (LockCloser closer = users.withLock()) { users.remove(user.getUserNumber()); } @@ -136,7 +135,7 @@ public String toString() sb = new StringBuilder("MeetMeRoom["); - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { sb.append("roomNumber='").append(getRoomNumber()).append("',"); systemHashcode = System.identityHashCode(this); diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java b/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java index a8837b04c..3c9d28bd9 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java @@ -22,7 +22,6 @@ import org.asteriskjava.live.MeetMeUser; import org.asteriskjava.live.MeetMeUserState; import org.asteriskjava.manager.action.CommandAction; -import org.asteriskjava.util.Locker; import org.asteriskjava.util.Locker.LockCloser; class MeetMeUserImpl extends AbstractLiveObject implements MeetMeUser @@ -87,7 +86,7 @@ public Date getDateLeft() void left(Date dateLeft) { MeetMeUserState oldState; - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { oldState = this.state; this.dateLeft = dateLeft; @@ -164,7 +163,7 @@ public String toString() sb = new StringBuilder("MeetMeUser["); - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { sb.append("dateJoined='").append(getDateJoined()).append("',"); sb.append("dateLeft='").append(getDateLeft()).append("',"); @@ -174,7 +173,7 @@ public String toString() systemHashcode = System.identityHashCode(this); } sb.append("channel=AsteriskChannel["); - try (LockCloser closer = Locker.lock(channel)) + try (LockCloser closer = channel.withLock()) { sb.append("id='").append(channel.getId()).append("',"); sb.append("name='").append(channel.getName()).append("'],"); diff --git a/src/main/java/org/asteriskjava/live/internal/QueueManager.java b/src/main/java/org/asteriskjava/live/internal/QueueManager.java index b17cb6ff0..471c08c14 100644 --- a/src/main/java/org/asteriskjava/live/internal/QueueManager.java +++ b/src/main/java/org/asteriskjava/live/internal/QueueManager.java @@ -22,7 +22,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.ListIterator; -import java.util.Map; import java.util.Map.Entry; import org.asteriskjava.live.AsteriskQueue; @@ -44,7 +43,7 @@ import org.asteriskjava.manager.event.QueueMemberRemovedEvent; import org.asteriskjava.manager.event.QueueMemberStatusEvent; import org.asteriskjava.manager.event.QueueParamsEvent; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableMap; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -69,7 +68,7 @@ class QueueManager * A map of ACD queues by there name. 101119 OLB: Modified to act as a LRU * Cache to optimize updates */ - private final Map queuesLRU = new LinkedHashMap<>(); + private final LockableMap queuesLRU = new LockableMap<>(new LinkedHashMap<>()); QueueManager(AsteriskServerImpl server, ChannelManager channelManager) { @@ -174,7 +173,7 @@ else if (event instanceof QueueEntryEvent) void disconnected() { - try (LockCloser closer = Locker.lock(queuesLRU)) + try (LockCloser closer = queuesLRU.withLock()) { for (AsteriskQueueImpl queue : queuesLRU.values()) { @@ -195,7 +194,7 @@ Collection getQueues() Collection copy; - try (LockCloser closer = Locker.lock(queuesLRU)) + try (LockCloser closer = queuesLRU.withLock()) { copy = new ArrayList(queuesLRU.values()); } @@ -207,7 +206,7 @@ public List getQueuesUpdatedAfter(Date date) refreshQueuesIfForced(); List copy = new ArrayList<>(); - try (LockCloser closer = Locker.lock(queuesLRU)) + try (LockCloser closer = queuesLRU.withLock()) { List> list = new ArrayList<>(queuesLRU.entrySet()); ListIterator> iter = list.listIterator(list.size()); @@ -236,7 +235,7 @@ public List getQueuesUpdatedAfter(Date date) */ private void addQueue(AsteriskQueueImpl queue) { - try (LockCloser closer = Locker.lock(queuesLRU)) + try (LockCloser closer = queuesLRU.withLock()) { queuesLRU.put(queue.getName(), queue); } @@ -277,9 +276,9 @@ private void handleQueueParamsEvent(QueueParamsEvent event) // We should never reach that code as this method is only called for // initialization // So the queue should never be in the queues list - try (LockCloser closer = Locker.lock(queue)) + try (LockCloser closer = queue.withLock()) { - try (LockCloser closer2 = Locker.lock(queuesLRU)) + try (LockCloser closer2 = queuesLRU.withLock()) { if (queue.setMax(max) | queue.setServiceLevel(serviceLevel) | queue.setWeight(weight) @@ -590,7 +589,7 @@ private AsteriskQueueImpl getInternalQueueByName(String queueName) { AsteriskQueueImpl queue; - try (LockCloser closer = Locker.lock(queuesLRU)) + try (LockCloser closer = queuesLRU.withLock()) { queue = queuesLRU.get(queueName); } diff --git a/src/main/java/org/asteriskjava/manager/PingThread.java b/src/main/java/org/asteriskjava/manager/PingThread.java index b796afbf1..d6ced68ad 100644 --- a/src/main/java/org/asteriskjava/manager/PingThread.java +++ b/src/main/java/org/asteriskjava/manager/PingThread.java @@ -17,12 +17,11 @@ package org.asteriskjava.manager; import java.util.HashSet; -import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import org.asteriskjava.manager.action.PingAction; import org.asteriskjava.manager.response.ManagerResponse; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableSet; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -51,7 +50,7 @@ public class PingThread extends Thread private long interval = DEFAULT_INTERVAL; private long timeout = DEFAULT_TIMEOUT; private volatile boolean die; - private final Set connections; + private final LockableSet connections; /** * Creates a new PingThread. Use {@link #addConnection(ManagerConnection)} @@ -62,7 +61,7 @@ public class PingThread extends Thread public PingThread() { super(); - this.connections = new HashSet<>(); + this.connections = new LockableSet<>(new HashSet<>()); this.die = false; long id = idCounter.getAndIncrement(); setName("Asterisk-Java Ping-" + id); @@ -114,7 +113,7 @@ public void setTimeout(long timeout) */ public void addConnection(ManagerConnection connection) { - try (LockCloser closer = Locker.lock(connections)) + try (LockCloser closer = connections.withLock()) { connections.add(connection); } @@ -128,7 +127,7 @@ public void addConnection(ManagerConnection connection) */ public void removeConnection(ManagerConnection connection) { - try (LockCloser closer = Locker.lock(connections)) + try (LockCloser closer = connections.withLock()) { connections.remove(connection); } @@ -163,7 +162,7 @@ public void run() break; } - try (LockCloser closer = Locker.lock(connections)) + try (LockCloser closer = connections.withLock()) { for (ManagerConnection c : connections) { diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 4efa0a879..0081a8081 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -34,7 +34,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; @@ -72,7 +71,9 @@ import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.pbx.util.LogTime; import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Lockable; +import org.asteriskjava.util.LockableList; +import org.asteriskjava.util.LockableMap; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -86,7 +87,7 @@ * @version $Id$ * @see org.asteriskjava.manager.ManagerConnectionFactory */ -public class ManagerConnectionImpl implements ManagerConnection, Dispatcher +public class ManagerConnectionImpl extends Lockable implements ManagerConnection, Dispatcher { private static final int RECONNECTION_INTERVAL_1 = 50; private static final int RECONNECTION_INTERVAL_2 = 5000; @@ -231,7 +232,7 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher * Key is the internalActionId of the Action sent and value the * corresponding ResponseListener. */ - private final Map responseListeners; + private final LockableMap responseListeners; /** * Contains the event handlers that handle ResponseEvents for the @@ -240,12 +241,12 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher * Key is the internalActionId of the Action sent and value the * corresponding EventHandler. */ - private final Map responseEventListeners; + private final LockableMap responseEventListeners; /** * Contains the event handlers that users registered. */ - private final List eventListeners; + private final LockableList eventListeners; protected ManagerConnectionState state = INITIAL; @@ -257,9 +258,9 @@ public class ManagerConnectionImpl implements ManagerConnection, Dispatcher public ManagerConnectionImpl() { this.id = idCounter.getAndIncrement(); - this.responseListeners = new HashMap<>(); - this.responseEventListeners = new HashMap<>(); - this.eventListeners = new ArrayList<>(); + this.responseListeners = new LockableMap<>(new HashMap<>()); + this.responseEventListeners = new LockableMap<>(new HashMap<>()); + this.eventListeners = new LockableList<>(new ArrayList<>()); this.protocolIdentifier = new ProtocolIdentifierWrapper(); } @@ -913,7 +914,7 @@ else if (state != CONNECTED) // in the response, thats fine. if (callback != null) { - try (LockCloser closer = Locker.lock(this.responseListeners)) + try (LockCloser closer = this.responseListeners.withLock()) { this.responseListeners.put(internalActionId, callback); } @@ -999,13 +1000,13 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas try { // register response handler... - try (LockCloser closer = Locker.lock(this.responseListeners)) + try (LockCloser closer = this.responseListeners.withLock()) { this.responseListeners.put(internalActionId, responseEventHandler); } // ...and event handler. - try (LockCloser closer = Locker.lock(this.responseEventListeners)) + try (LockCloser closer = this.responseEventListeners.withLock()) { this.responseEventListeners.put(internalActionId, responseEventHandler); } @@ -1038,7 +1039,7 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas finally { // remove the event handler - try (LockCloser closer = Locker.lock(this.responseEventListeners)) + try (LockCloser closer = this.responseEventListeners.withLock()) { this.responseEventListeners.remove(internalActionId); } @@ -1046,7 +1047,7 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas // Note: The response handler should have already been removed // when the response was received, however we remove it here // just in case it was never received. - try (LockCloser closer = Locker.lock(this.responseListeners)) + try (LockCloser closer = this.responseListeners.withLock()) { this.responseListeners.remove(internalActionId); } @@ -1089,13 +1090,13 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas action.getActionCompleteEventClass(), callback); // register response handler... - try (LockCloser closer = Locker.lock(this.responseListeners)) + try (LockCloser closer = this.responseListeners.withLock()) { this.responseListeners.put(internalActionId, responseEventHandler); } // ...and event handler. - try (LockCloser closer = Locker.lock(this.responseEventListeners)) + try (LockCloser closer = this.responseEventListeners.withLock()) { this.responseEventListeners.put(internalActionId, responseEventHandler); } @@ -1127,7 +1128,7 @@ private String createInternalActionId() public void addEventListener(final ManagerEventListener listener) { - try (LockCloser closer = Locker.lock(this.eventListeners)) + try (LockCloser closer = this.eventListeners.withLock()) { // only add it if its not already there if (!this.eventListeners.contains(listener)) @@ -1139,7 +1140,7 @@ public void addEventListener(final ManagerEventListener listener) public void removeEventListener(final ManagerEventListener listener) { - try (LockCloser closer = Locker.lock(this.eventListeners)) + try (LockCloser closer = this.eventListeners.withLock()) { if (this.eventListeners.contains(listener)) { @@ -1198,7 +1199,7 @@ public void dispatchResponse(ManagerResponse response) if (internalActionId != null) { - try (LockCloser closer = Locker.lock(this.responseListeners)) + try (LockCloser closer = this.responseListeners.withLock()) { listener = responseListeners.get(internalActionId); if (listener != null) @@ -1269,7 +1270,7 @@ public void dispatchEvent(ManagerEvent event) internalActionId = responseEvent.getInternalActionId(); if (internalActionId != null) { - try (LockCloser closer = Locker.lock(responseEventListeners)) + try (LockCloser closer = responseEventListeners.withLock()) { ManagerEventListener listener; @@ -1304,7 +1305,7 @@ public void dispatchEvent(ManagerEvent event) cleanupActionListeners((DisconnectEvent) event); // When we receive get disconnected while we are connected start // a new reconnect thread and set the state to RECONNECTING. - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { if (state == CONNECTED) { @@ -1375,7 +1376,7 @@ private void dispatchLegacyEventIfNeeded(ManagerEvent event) */ private void fireEvent(ManagerEvent event) { - try (LockCloser closer = Locker.lock(eventListeners)) + try (LockCloser closer = eventListeners.withLock()) { for (ManagerEventListener listener : eventListeners) { @@ -1477,7 +1478,7 @@ private void reconnect() try { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { if (state != RECONNECTING) { @@ -1552,7 +1553,7 @@ private void cleanupActionListeners(DisconnectEvent event) { HashMap oldResponseListeners = null; - try (LockCloser closer = Locker.lock(responseListeners)) + try (LockCloser closer = responseListeners.withLock()) { // Store remaining response listeners to be notified outside of // synchronized @@ -1575,7 +1576,7 @@ private void cleanupActionListeners(DisconnectEvent event) } HashMap oldResponseEventListeners = null; - try (LockCloser closer = Locker.lock(responseEventListeners)) + try (LockCloser closer = responseEventListeners.withLock()) { // Store remaining responseEventListeners to be notified outside of // synchronized @@ -1790,7 +1791,7 @@ public void onManagerEvent(ManagerEvent event) { events.setComplete(true); String internalActionId = responseEvent.getInternalActionId(); - try (LockCloser closer = Locker.lock(responseEventListeners)) + try (LockCloser closer = responseEventListeners.withLock()) { responseEventListeners.remove(internalActionId); } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java index 44f056dfc..a6732a2b9 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java @@ -20,7 +20,7 @@ import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.action.ManagerAction; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Lockable; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.SocketConnectionFacade; @@ -30,7 +30,7 @@ * @author srt * @version $Id$ */ -public class ManagerWriterImpl implements ManagerWriter +public class ManagerWriterImpl extends Lockable implements ManagerWriter { /** * Instance logger. @@ -60,7 +60,7 @@ public void setTargetVersion(AsteriskVersion version) public void setSocket(final SocketConnectionFacade socket) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { this.socket = socket; } @@ -68,7 +68,7 @@ public void setSocket(final SocketConnectionFacade socket) public void sendAction(final ManagerAction action, final String internalActionId) throws IOException { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { final String actionString; diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java index 2ad741aad..26afce8ef 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java @@ -24,7 +24,7 @@ import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.manager.response.ManagerResponse; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableList; import org.asteriskjava.util.Locker.LockCloser; /** @@ -37,7 +37,7 @@ public class ResponseEventsImpl implements ResponseEvents { private ManagerResponse response; - private final Collection events; + private final LockableList events; private boolean complete; private final CountDownLatch latch = new CountDownLatch(1); @@ -46,7 +46,7 @@ public class ResponseEventsImpl implements ResponseEvents */ public ResponseEventsImpl() { - this.events = new ArrayList<>(); + this.events = new LockableList<>(new ArrayList<>()); this.complete = false; } @@ -86,7 +86,7 @@ public void setRepsonse(ManagerResponse response) */ public void addEvent(ResponseEvent event) { - try (LockCloser closer = Locker.lock(events)) + try (LockCloser closer = events.withLock()) { events.add(event); } diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 70c9a756f..143eb54fd 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -6,13 +6,12 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Map; import org.asteriskjava.manager.event.BridgeEnterEvent; import org.asteriskjava.manager.event.BridgeEvent; import org.asteriskjava.manager.event.BridgeLeaveEvent; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableMap; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -30,11 +29,11 @@ class BridgeState private static final BridgeEnterEventComparator BRIDGE_ENTER_EVENT_COMPARATOR = new BridgeEnterEventComparator(); private static final String HOLDING_BRIDGE_TECH = "holding_bridge"; - private final Map members = new HashMap<>(); + private final LockableMap members = new LockableMap<>(new HashMap<>()); ManagerEvent destroy() { - try (LockCloser closer = Locker.lock(members)) + try (LockCloser closer = members.withLock()) { members.clear(); } @@ -57,7 +56,7 @@ ManagerEvent addMember(BridgeEnterEvent event) return null; } - try (LockCloser closer = Locker.lock(members)) + try (LockCloser closer = members.withLock()) { if (members.put(event.getChannel(), event) == null && members.size() == 2) { @@ -96,7 +95,7 @@ ManagerEvent removeMember(BridgeLeaveEvent event) return null; } - try (LockCloser closer = Locker.lock(members)) + try (LockCloser closer = members.withLock()) { remaining.addAll(members.values()); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java index b12d012e1..a9c86019a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java @@ -15,10 +15,11 @@ import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; +import org.asteriskjava.util.Lockable; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public abstract class ActivityHelper implements Runnable, Activity +public abstract class ActivityHelper extends Lockable implements Runnable, Activity { private static final Log logger = LogFactory.getLog(ActivityHelper.class); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index d50db4248..7689c8f77 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -26,7 +26,6 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.util.Locker; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -234,7 +233,7 @@ else if (_completionCause == CompletionCause.CANCELLED) @Override public void onManagerEvent(final ManagerEvent event) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { if (event instanceof BridgeEvent) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java index 102732a97..acd5d1d15 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java @@ -22,7 +22,6 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ParkedCallEvent; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.util.Locker; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -180,7 +179,7 @@ public EndPoint getParkingLot() @Override public void onManagerEvent(final ManagerEvent event) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { assert event instanceof ParkedCallEvent : "Unexpected event"; diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index 1b02e2ea7..5c845668a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -24,7 +24,6 @@ import org.asteriskjava.pbx.asterisk.wrap.events.RenameEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelProxy; -import org.asteriskjava.util.Locker; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -119,7 +118,7 @@ public boolean doActivity() throws PBXException @Override public void onManagerEvent(final ManagerEvent event) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { if (event instanceof RenameEvent) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java index b3f5505f7..d4adb3e89 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java @@ -4,7 +4,7 @@ import java.util.LinkedList; import org.asteriskjava.pbx.Channel; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Lockable; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -14,7 +14,7 @@ * a meetme room. The hangup function will hangup all known participants in * this meetme room. */ -public class MeetmeRoom +public class MeetmeRoom extends Lockable { /** * The asterisk room number. This will be value offset from the Meetme Base. @@ -48,7 +48,7 @@ public MeetmeRoom(final int number) */ public boolean addChannel(final Channel channel) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { boolean newChannel = false; if (!this.channels.contains(channel)) @@ -65,7 +65,7 @@ public boolean addChannel(final Channel channel) public int getChannelCount() { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { return this.channelCount; } @@ -73,7 +73,7 @@ public int getChannelCount() public Channel[] getChannels() { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { final Channel list[] = new Channel[this.channels.size()]; @@ -113,7 +113,7 @@ public boolean isActive() public void removeChannel(final Channel channel) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { final boolean channelCountInSync = this.channelCount == this.channels.size(); final boolean removed = this.channels.remove(channel); diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index 8115b0c43..3433596ce 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -28,7 +28,6 @@ import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.CoherentManagerEventListener; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; -import org.asteriskjava.util.Locker; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -107,7 +106,7 @@ private MeetmeRoomControl(PBX pbx, final int roomCount) throws NoMeetmeException */ public MeetmeRoom findAvailableRoom(RoomOwner newOwner) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { int count = 0; for (final MeetmeRoom room : this.rooms) @@ -175,7 +174,7 @@ public MeetmeRoom findAvailableRoom(RoomOwner newOwner) */ private MeetmeRoom findMeetmeRoom(final String roomNumber) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { MeetmeRoom foundRoom = null; for (final MeetmeRoom room : this.rooms) @@ -193,7 +192,7 @@ private MeetmeRoom findMeetmeRoom(final String roomNumber) MeetmeRoom getRoom(final int room) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { return this.rooms[room]; } @@ -354,7 +353,7 @@ private void configure(AsteriskPBX pbx) throws NoMeetmeException private void parseMeetme(final String line) throws NoMeetmeException { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { if (line != null) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 21ed8b6f5..1f7b5e660 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -68,7 +68,6 @@ import org.asteriskjava.pbx.internal.asterisk.MeetmeRoomControl; import org.asteriskjava.pbx.internal.asterisk.RoomOwner; import org.asteriskjava.pbx.internal.managerAPI.RedirectCall; -import org.asteriskjava.util.Locker; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -576,7 +575,7 @@ public Channel registerChannel(final String channelName, final String uniqueIdPa public Channel internalRegisterChannel(final String channelName, final String uniqueID) throws InvalidChannelName { ChannelProxy proxy = null; - try (LockCloser closer = Locker.lock(this.liveChannels)) + try (LockCloser closer = this.liveChannels.withLock()) { String localUniqueID = (uniqueID == null ? ChannelImpl.UNKNOWN_UNIQUE_ID : uniqueID); @@ -608,7 +607,7 @@ private String cleanChannelName(final String name) public Channel registerHangupChannel(String channel, String uniqueId) throws InvalidChannelName { Channel newChannel = null; - try (LockCloser closer = Locker.lock(this.liveChannels)) + try (LockCloser closer = this.liveChannels.withLock()) { newChannel = this.findChannel(channel, uniqueId); if (newChannel == null) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java index a6f7b97d9..c59d46d43 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java @@ -7,7 +7,7 @@ import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ChannelHangupListener; import org.asteriskjava.pbx.asterisk.wrap.events.ChannelState; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableList; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -30,7 +30,7 @@ public class CallTracker implements ChannelHangupListener /** * The list of channels associated with this call. */ - ArrayList _associatedChannels = new ArrayList<>(); + LockableList _associatedChannels = new LockableList<>(new ArrayList<>()); /** * The state of this call. @@ -58,7 +58,7 @@ public class CallTracker implements ChannelHangupListener */ void mergeCalls(CallTracker rhs) { - try (LockCloser closer = Locker.lock(this._associatedChannels)) + try (LockCloser closer = this._associatedChannels.withLock()) { this._associatedChannels.addAll(rhs._associatedChannels); // not certain this is necessary but lets just tidy up a bit. @@ -82,7 +82,7 @@ public void setState(final ChannelState channelState) public int findChannel(Channel newChannel) { int index = -1; - try (LockCloser closer = Locker.lock(this._associatedChannels)) + try (LockCloser closer = this._associatedChannels.withLock()) { for (int i = 0; i < this._associatedChannels.size(); i++) @@ -106,7 +106,7 @@ public int findChannel(Channel newChannel) */ public void remove(Channel channel) { - try (LockCloser closer = Locker.lock(this._associatedChannels)) + try (LockCloser closer = this._associatedChannels.withLock()) { int index = findChannel(channel); if (index != -1) @@ -123,7 +123,7 @@ public void remove(Channel channel) public void startSweep() { - try (LockCloser closer = Locker.lock(this._associatedChannels)) + try (LockCloser closer = this._associatedChannels.withLock()) { for (final Channel channel : this._associatedChannels) { @@ -135,7 +135,7 @@ public void startSweep() public void endSweep() { final List toremove = new LinkedList<>(); - try (LockCloser closer = Locker.lock(this._associatedChannels)) + try (LockCloser closer = this._associatedChannels.withLock()) { for (final Channel channel : this._associatedChannels) { @@ -163,7 +163,7 @@ void dumpChannelList() if (logger.isDebugEnabled()) { logger.debug("CallTracker: dump channellist:" + this); //$NON-NLS-1$ - try (LockCloser closer = Locker.lock(this._associatedChannels)) + try (LockCloser closer = this._associatedChannels.withLock()) { for (final Channel channel : this._associatedChannels) { @@ -175,7 +175,7 @@ void dumpChannelList() public boolean hasEnded() { - try (LockCloser closer = Locker.lock(this._associatedChannels)) + try (LockCloser closer = this._associatedChannels.withLock()) { return this._associatedChannels.size() == 0; } @@ -185,7 +185,7 @@ public boolean hasEnded() public void channelHangup(Channel channel, Integer cause, String causeText) { remove(channel); - try (LockCloser closer = Locker.lock(this._associatedChannels)) + try (LockCloser closer = this._associatedChannels.withLock()) { if (this._associatedChannels.size() == 0) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index d6686ff51..6379cab3a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -19,7 +19,7 @@ import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.internal.eventQueue.EventLifeMonitor; import org.asteriskjava.pbx.util.LogTime; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableSet; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -49,7 +49,7 @@ class CoherentManagerEventQueue implements ManagerEventListener, Runnable long suppressQueueSizeErrorUntil = 0; - private HashSet> globalEvents = new HashSet<>(); + private LockableSet> globalEvents = new LockableSet<>(new HashSet<>()); public CoherentManagerEventQueue(String name, ManagerConnection connection) { @@ -78,7 +78,7 @@ public void onManagerEvent(final org.asteriskjava.manager.event.ManagerEvent eve * processing overhead of these events. */ // Only enqueue the events that are of interest to one of our listeners. - try (LockCloser closer = Locker.lock(this.globalEvents)) + try (LockCloser closer = this.globalEvents.withLock()) { Class< ? extends ManagerEvent> shadowEvent = CoherentEventFactory.getShadowEvent(event); if (this.globalEvents.contains(shadowEvent)) @@ -197,7 +197,7 @@ public void dispatchEvent(final ManagerEvent event) // iterate over them // The iteration may call some long running processes. final List listenerCopy; - try (LockCloser closer = Locker.lock(this.listeners)) + try (LockCloser closer = this.listeners.withLock()) { listenerCopy = this.listeners.getCopyAsList(); } @@ -283,10 +283,10 @@ public void run() */ public void addListener(final FilteredManagerListener listener) { - try (LockCloser closer = Locker.lock(this.listeners)) + try (LockCloser closer = this.listeners.withLock()) { this.listeners.addListener(listener); - try (LockCloser closer2 = Locker.lock(this.globalEvents)) + try (LockCloser closer2 = this.globalEvents.withLock()) { Collection> expandEvents = expandEvents(listener.requiredEvents()); this.globalEvents.addAll(expandEvents); @@ -323,14 +323,14 @@ public void removeListener(final FilteredManagerListener melf) { if (melf != null) { - try (LockCloser closer = Locker.lock(this.listeners)) + try (LockCloser closer = this.listeners.withLock()) { this.listeners.removeListener(melf); // When we remove a listener we must unfortunately // completely // recalculate the set of required events. - try (LockCloser closer2 = Locker.lock(this.globalEvents)) + try (LockCloser closer2 = this.globalEvents.withLock()) { this.globalEvents.clear(); Iterator itr = this.listeners.iterator(); @@ -354,9 +354,9 @@ public void removeListener(final FilteredManagerListener melf) */ public void transferListeners(CoherentManagerEventQueue eventQueue) { - try (LockCloser closer = Locker.lock(this.listeners)) + try (LockCloser closer = this.listeners.withLock()) { - try (LockCloser closer2 = Locker.lock(eventQueue.listeners)) + try (LockCloser closer2 = eventQueue.listeners.withLock()) { Iterator itr = eventQueue.listeners.iterator(); while (itr.hasNext()) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java index 0bec0d1c0..cc61603ad 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java @@ -7,10 +7,11 @@ import java.util.TreeSet; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import org.asteriskjava.util.Lockable; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class ListenerManager +public class ListenerManager extends Lockable { private final TreeSet listeners = new TreeSet<>(new ListenerPriorityComparator()); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index f09379616..aed1043fb 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -21,7 +21,8 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvents; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.Lockable; +import org.asteriskjava.util.LockableList; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -59,7 +60,7 @@ * * @author bsutton */ -public class LiveChannelManager implements FilteredManagerListener +public class LiveChannelManager extends Lockable implements FilteredManagerListener { private static final Log logger = LogFactory.getLog(LiveChannelManager.class); @@ -68,7 +69,7 @@ public class LiveChannelManager implements FilteredManagerListener * channels and remove them as they hangup. The hash is keyed by the * channel's name. e.g. SIP/100-000000100 */ - private final List _liveChannels = new CopyOnWriteArrayList<>(); + private final LockableList _liveChannels = new LockableList<>(new CopyOnWriteArrayList<>()); public LiveChannelManager() { @@ -122,7 +123,7 @@ public ChannelProxy getChannelByEndPoint(EndPoint endPoint) public void add(ChannelProxy proxy) { - try (LockCloser closer = Locker.lock(this._liveChannels)) + try (LockCloser closer = _liveChannels.withLock()) { ChannelProxy index = findProxy(proxy); if (index == null) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java index 8d3f0aecd..671c8cf70 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java @@ -8,7 +8,7 @@ import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; import org.asteriskjava.pbx.asterisk.wrap.events.NewStateEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableList; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -32,7 +32,7 @@ public class Peer implements CallEndedListener * there would normally only be a single channel unless we are in the middle * of a transfer or the phone has two calls up. */ - private final LinkedList callList = new LinkedList<>(); + private final LockableList callList = new LockableList<>(new LinkedList<>()); private PeerState _state = PeerState.NOTSET; private boolean dnd = false; @@ -51,7 +51,7 @@ private CallTracker registerChannel(final Channel newChannel) { CallTracker associatedCall = null; boolean found = false; - try (LockCloser closer = Locker.lock(this.callList)) + try (LockCloser closer = this.callList.withLock()) { for (final CallTracker call : this.callList) { @@ -76,7 +76,7 @@ private CallTracker registerChannel(final Channel newChannel) private CallTracker createCallTracker(final Channel newChannel) { CallTracker newCall; - try (LockCloser closer = Locker.lock(this.callList)) + try (LockCloser closer = this.callList.withLock()) { newCall = new CallTracker(this, newChannel); this.callList.add(newCall); @@ -210,7 +210,7 @@ public void handleEvent(final StatusEvent b) private CallTracker findCall(Channel channel) { CallTracker result = null; - try (LockCloser closer = Locker.lock(this.callList)) + try (LockCloser closer = this.callList.withLock()) { for (CallTracker call : this.callList) { @@ -233,7 +233,7 @@ public void setDND(final boolean on) public void startSweep() { Peer.logger.debug("Starting sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ - try (LockCloser closer = Locker.lock(this.callList)) + try (LockCloser closer = this.callList.withLock()) { for (final CallTracker call : this.callList) { @@ -245,7 +245,7 @@ public void startSweep() public void endSweep() { Peer.logger.debug("Ending sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ - try (LockCloser closer = Locker.lock(this.callList)) + try (LockCloser closer = this.callList.withLock()) { for (final CallTracker call : this.callList) { @@ -261,7 +261,7 @@ public void endSweep() */ private void evaluateState() { - try (LockCloser closer = Locker.lock(this.callList)) + try (LockCloser closer = this.callList.withLock()) { // Get the highest prioirty state from the set of calls. PeerState newState = PeerState.NOTSET; @@ -302,7 +302,7 @@ private void dumpCallList() public void callEnded(CallTracker call) { boolean found = false; - try (LockCloser closer = Locker.lock(this.callList)) + try (LockCloser closer = this.callList.withLock()) { for (final CallTracker aCall : this.callList) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java index 7773365a0..a8639c637 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java @@ -23,7 +23,7 @@ import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; -import org.asteriskjava.util.Locker; +import org.asteriskjava.util.LockableList; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -36,7 +36,7 @@ public class PeerMonitor extends EventListenerBaseClass implements Runnable private static final Log logger = LogFactory.getLog(PeerMonitor.class); - LinkedList peerList = new LinkedList<>(); + LockableList peerList = new LockableList<>(new LinkedList<>()); boolean initSip = false; @@ -77,7 +77,7 @@ public static synchronized PeerMonitor getInstance() private PeerMonitor() { super("PeerMonitor", PBXFactory.getActivePBX()); //$NON-NLS-1$ - this.peerList = new LinkedList<>(); + this.peerList = new LockableList<>(new LinkedList<>()); this.startListener(); this.addSipsToMonitor(); try @@ -139,7 +139,7 @@ public Peer registerPeer(final EndPoint endPoint) return null; } - try (LockCloser closer = Locker.lock(peerList)) + try (LockCloser closer = peerList.withLock()) { Peer peer = this.findPeer(endPoint); if (peer == null) @@ -156,7 +156,7 @@ public Peer findPeer(final EndPoint peerEndPoint) { Peer found = null; - try (LockCloser closer = Locker.lock(peerList)) + try (LockCloser closer = peerList.withLock()) { for (final Peer peer : this.peerList) { @@ -170,14 +170,12 @@ public Peer findPeer(final EndPoint peerEndPoint) return found; } - @SuppressWarnings("unchecked") public Iterator getIterator() { - try (LockCloser closer = Locker.lock(peerList)) + try (LockCloser closer = peerList.withLock()) { - final List clone = (LinkedList) this.peerList.clone(); - final List tmpList = clone; - return tmpList.iterator(); + final List clone = new LinkedList(this.peerList); + return clone.iterator(); } } @@ -243,7 +241,7 @@ else if (event instanceof NewStateEvent) private void handleEvent(NewStateEvent event) { - try (LockCloser closer = Locker.lock(peerList)) + try (LockCloser closer = peerList.withLock()) { for (Peer peer : this.peerList) { @@ -254,7 +252,7 @@ private void handleEvent(NewStateEvent event) private void handleEvent(final NewChannelEvent event) { - try (LockCloser closer = Locker.lock(peerList)) + try (LockCloser closer = peerList.withLock()) { for (Peer peer : this.peerList) { @@ -265,7 +263,7 @@ private void handleEvent(final NewChannelEvent event) private void handleEvent(final MasqueradeEvent event) { - try (LockCloser closer = Locker.lock(peerList)) + try (LockCloser closer = peerList.withLock()) { for (Peer peer : this.peerList) { @@ -276,7 +274,7 @@ private void handleEvent(final MasqueradeEvent event) private void handleEvent(final StatusEvent event) { - try (LockCloser closer = Locker.lock(peerList)) + try (LockCloser closer = peerList.withLock()) { for (Peer peer : this.peerList) { @@ -313,7 +311,7 @@ private void handleEvent(final PeerStatusEvent event) */ private void handleEvent(final StatusCompleteEvent event) { - try (LockCloser closer = Locker.lock(peerList)) + try (LockCloser closer = peerList.withLock()) { for (final Peer peer : this.peerList) { @@ -375,7 +373,7 @@ public void startSweep() PeerMonitor.logger.debug("Starting channel mark and sweep"); //$NON-NLS-1$ // Mark every channel as 'clearing' - try (LockCloser closer = Locker.lock(peerList)) + try (LockCloser closer = peerList.withLock()) { for (final Peer peer : this.peerList) { diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java index d294e9cf7..6418b234e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java @@ -4,12 +4,13 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.FilteredManagerListener; +import org.asteriskjava.util.Lockable; /* * This is the basic abstract event listener class. It implements a thread * and queue. */ -public abstract class EventListenerBaseClass implements FilteredManagerListener, AutoCloseable +public abstract class EventListenerBaseClass extends Lockable implements FilteredManagerListener, AutoCloseable { private final String name; diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index d97fcacf0..9191bf7ca 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -28,7 +28,6 @@ import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.util.Locker; import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -296,7 +295,7 @@ void abort(final String reason) @Override public void onManagerEvent(final ManagerEvent event) { - try (LockCloser closer = Locker.lock(this)) + try (LockCloser closer = this.withLock()) { managerEventsSeen.getAndIncrement(); if (event instanceof HangupEvent) diff --git a/src/main/java/org/asteriskjava/util/Lockable.java b/src/main/java/org/asteriskjava/util/Lockable.java new file mode 100644 index 000000000..567ecb0e8 --- /dev/null +++ b/src/main/java/org/asteriskjava/util/Lockable.java @@ -0,0 +1,129 @@ +package org.asteriskjava.util; + +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +import org.asteriskjava.util.Locker.LockCloser; + +public class Lockable +{ + private final Semaphore semaphore = new Semaphore(1, true); + final private String lockName; + final AtomicReference threadHoldingLock = new AtomicReference<>(); + private final AtomicInteger totalWaitTime = new AtomicInteger(); + private final AtomicInteger totalHoldTime = new AtomicInteger(); + private final AtomicInteger requested = new AtomicInteger(); + private final AtomicInteger waited = new AtomicInteger(); + private final AtomicInteger acquired = new AtomicInteger(); + private volatile boolean dumped = false; + + private final static AtomicLong seed = new AtomicLong(); + private final long lockableId = seed.incrementAndGet(); + + public Lockable() + { + this.lockName = getCaller(); + } + + String getCaller() + { + Exception ex = new Exception(); + StackTraceElement[] trace = ex.getStackTrace(); + String name = this.getClass().getCanonicalName(); + for (StackTraceElement element : trace) + { + if (element.getFileName() != null && !element.getFileName().contains(Lockable.class.getSimpleName())) + { + name = element.getFileName() + " " + element.getMethodName() + " " + element.getLineNumber() + " " + + element.getClassName(); + break; + } + } + + return name; + } + + public String asString() + { + return "Lockable [totalWaitTime=" + totalWaitTime + ", totalHoldTime=" + totalHoldTime + ", waited=" + waited + + ", acquired=" + acquired + ", object=" + lockName + "]"; + } + + long getAverageHoldTime() + { + long hold = totalHoldTime.get(); + long count = acquired.get(); + if (count < 10) + { + return 250; + } + return Math.max(hold / count, 50); + } + + public LockCloser withLock() + { + return Locker.doWithLock(this); + } + + Semaphore getSemaphore() + { + return semaphore; + } + + void addTotalWaitTime(int time) + { + totalWaitTime.addAndGet(time); + } + + void addTotalHoldTime(int time) + { + totalHoldTime.addAndGet(time); + } + + int addRequested() + { + return requested.incrementAndGet(); + } + + void addWaited(int time) + { + waited.addAndGet(time); + } + + void addAcquired() + { + acquired.incrementAndGet(); + } + + boolean isDumped() + { + return dumped; + } + + void setDumped(boolean dumped) + { + this.dumped = dumped; + } + + public long getTotalWaitTime() + { + return totalWaitTime.longValue(); + } + + public int getWaited() + { + return waited.intValue(); + } + + public int getRequested() + { + return requested.intValue(); + } + + public Long getLockableId() + { + return lockableId; + } +} diff --git a/src/main/java/org/asteriskjava/util/LockableList.java b/src/main/java/org/asteriskjava/util/LockableList.java new file mode 100644 index 000000000..ab8dc252d --- /dev/null +++ b/src/main/java/org/asteriskjava/util/LockableList.java @@ -0,0 +1,187 @@ +package org.asteriskjava.util; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; +import java.util.stream.Stream; + +public class LockableList extends Lockable implements List +{ + final List list; + + public LockableList(List list) + { + if (list instanceof Lockable) + { + throw new RuntimeException("list is already lockable"); + } + this.list = list; + } + + public void forEach(Consumer< ? super S> action) + { + list.forEach(action); + } + + public int size() + { + return list.size(); + } + + public boolean isEmpty() + { + return list.isEmpty(); + } + + public boolean contains(Object o) + { + return list.contains(o); + } + + public Iterator iterator() + { + return list.iterator(); + } + + public Object[] toArray() + { + return list.toArray(); + } + + public T[] toArray(T[] a) + { + return list.toArray(a); + } + + public boolean add(S e) + { + return list.add(e); + } + + public boolean remove(Object o) + { + return list.remove(o); + } + + public boolean containsAll(Collection< ? > c) + { + return list.containsAll(c); + } + + public boolean addAll(Collection< ? extends S> c) + { + return list.addAll(c); + } + + public boolean addAll(int index, Collection< ? extends S> c) + { + return list.addAll(index, c); + } + + public boolean removeAll(Collection< ? > c) + { + return list.removeAll(c); + } + + public boolean retainAll(Collection< ? > c) + { + return list.retainAll(c); + } + + public void replaceAll(UnaryOperator operator) + { + list.replaceAll(operator); + } + + public boolean removeIf(Predicate< ? super S> filter) + { + return list.removeIf(filter); + } + + public void sort(Comparator< ? super S> c) + { + list.sort(c); + } + + public void clear() + { + list.clear(); + } + + public boolean equals(Object o) + { + return list.equals(o); + } + + public int hashCode() + { + return list.hashCode(); + } + + public S get(int index) + { + return list.get(index); + } + + public S set(int index, S element) + { + return list.set(index, element); + } + + public void add(int index, S element) + { + list.add(index, element); + } + + public Stream stream() + { + return list.stream(); + } + + public S remove(int index) + { + return list.remove(index); + } + + public Stream parallelStream() + { + return list.parallelStream(); + } + + public int indexOf(Object o) + { + return list.indexOf(o); + } + + public int lastIndexOf(Object o) + { + return list.lastIndexOf(o); + } + + public ListIterator listIterator() + { + return list.listIterator(); + } + + public ListIterator listIterator(int index) + { + return list.listIterator(index); + } + + public List subList(int fromIndex, int toIndex) + { + return list.subList(fromIndex, toIndex); + } + + public Spliterator spliterator() + { + return list.spliterator(); + } + +} diff --git a/src/main/java/org/asteriskjava/util/LockableMap.java b/src/main/java/org/asteriskjava/util/LockableMap.java new file mode 100644 index 000000000..b7316b040 --- /dev/null +++ b/src/main/java/org/asteriskjava/util/LockableMap.java @@ -0,0 +1,148 @@ +package org.asteriskjava.util; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; + +public class LockableMap extends Lockable implements Map +{ + final Map map; + + public LockableMap(Map map) + { + if (map instanceof Lockable) + { + throw new RuntimeException("map is already lockable"); + } + this.map = map; + } + + public int size() + { + return map.size(); + } + + public boolean isEmpty() + { + return map.isEmpty(); + } + + public boolean containsKey(Object key) + { + return map.containsKey(key); + } + + public boolean containsValue(Object value) + { + return map.containsValue(value); + } + + public P get(Object key) + { + return map.get(key); + } + + public P put(S key, P value) + { + return map.put(key, value); + } + + public P remove(Object key) + { + return map.remove(key); + } + + public void putAll(Map< ? extends S, ? extends P> m) + { + map.putAll(m); + } + + public void clear() + { + map.clear(); + } + + public Set keySet() + { + return map.keySet(); + } + + public Collection

    values() + { + return map.values(); + } + + public Set> entrySet() + { + return map.entrySet(); + } + + public boolean equals(Object o) + { + return map.equals(o); + } + + public int hashCode() + { + return map.hashCode(); + } + + public P getOrDefault(Object key, P defaultValue) + { + return map.getOrDefault(key, defaultValue); + } + + public void forEach(BiConsumer< ? super S, ? super P> action) + { + map.forEach(action); + } + + public void replaceAll(BiFunction< ? super S, ? super P, ? extends P> function) + { + map.replaceAll(function); + } + + public P putIfAbsent(S key, P value) + { + return map.putIfAbsent(key, value); + } + + public boolean remove(Object key, Object value) + { + return map.remove(key, value); + } + + public boolean replace(S key, P oldValue, P newValue) + { + return map.replace(key, oldValue, newValue); + } + + public P replace(S key, P value) + { + return map.replace(key, value); + } + + public P computeIfAbsent(S key, Function< ? super S, ? extends P> mappingFunction) + { + return map.computeIfAbsent(key, mappingFunction); + } + + public P computeIfPresent(S key, BiFunction< ? super S, ? super P, ? extends P> remappingFunction) + { + return map.computeIfPresent(key, remappingFunction); + } + + public P compute(S key, BiFunction< ? super S, ? super P, ? extends P> remappingFunction) + { + return map.compute(key, remappingFunction); + } + + public P merge(S key, P value, BiFunction< ? super P, ? super P, ? extends P> remappingFunction) + { + return map.merge(key, value, remappingFunction); + } + +} diff --git a/src/main/java/org/asteriskjava/util/LockableSet.java b/src/main/java/org/asteriskjava/util/LockableSet.java new file mode 100644 index 000000000..92a1c4421 --- /dev/null +++ b/src/main/java/org/asteriskjava/util/LockableSet.java @@ -0,0 +1,124 @@ +package org.asteriskjava.util; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Stream; + +public class LockableSet extends Lockable implements Set +{ + final Set set; + + public LockableSet(Set set) + { + if (set instanceof Lockable) + { + throw new RuntimeException("set is already lockable"); + } + this.set = set; + } + + public void forEach(Consumer< ? super S> action) + { + set.forEach(action); + } + + public int size() + { + return set.size(); + } + + public boolean isEmpty() + { + return set.isEmpty(); + } + + public boolean contains(Object o) + { + return set.contains(o); + } + + public Iterator iterator() + { + return set.iterator(); + } + + public Object[] toArray() + { + return set.toArray(); + } + + public T[] toArray(T[] a) + { + return set.toArray(a); + } + + public boolean add(S e) + { + return set.add(e); + } + + public boolean remove(Object o) + { + return set.remove(o); + } + + public boolean containsAll(Collection< ? > c) + { + return set.containsAll(c); + } + + public boolean addAll(Collection< ? extends S> c) + { + return set.addAll(c); + } + + public boolean retainAll(Collection< ? > c) + { + return set.retainAll(c); + } + + public boolean removeAll(Collection< ? > c) + { + return set.removeAll(c); + } + + public void clear() + { + set.clear(); + } + + public boolean equals(Object o) + { + return set.equals(o); + } + + public int hashCode() + { + return set.hashCode(); + } + + public Spliterator spliterator() + { + return set.spliterator(); + } + + public boolean removeIf(Predicate< ? super S> filter) + { + return set.removeIf(filter); + } + + public Stream stream() + { + return set.stream(); + } + + public Stream parallelStream() + { + return set.parallelStream(); + } + +} diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index 6f900d905..3585f70f1 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -1,15 +1,13 @@ package org.asteriskjava.util; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.WeakHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; public class Locker { @@ -19,43 +17,29 @@ public class Locker private static volatile boolean diags = false; private static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); - private static final Map lockObjectMap = new WeakHashMap<>(); - - private static final Object mapSync = new Object(); + private static final Object sync = new Object(); // keep references to LockStats so the WeakHashMap won't remove them between // reporting intervals - private static final List keepList = new LinkedList<>(); + private static final Map keepList = new HashMap<>(); - public static LockCloser lock(final Object sync) + public static LockCloser doWithLock(final Lockable lockable) { - LockStats finalStats; - synchronized (mapSync) + if (diags) { - // find or create the semaphore for locking - LockStats stats = lockObjectMap.get(System.identityHashCode(sync)); - if (stats == null) + synchronized (sync) { - String name = getCaller(sync); - - stats = new LockStats(sync, name); - - lockObjectMap.put(System.identityHashCode(sync), stats); - if (diags) - { - keepList.add(stats); - } + keepList.put(lockable.getLockableId(), lockable); } - finalStats = stats; } try { if (diags) { - return lockWithDiags(finalStats); + return lockWithDiags(lockable); } - return simpleLock(finalStats); + return simpleLock(lockable); } catch (Exception e) { @@ -67,14 +51,14 @@ public static LockCloser lock(final Object sync) /** * determine the caller to Locker * - * @param object + * @param semaphore * @return */ - private static String getCaller(Object object) + static String getCaller(Lockable lockable) { Exception ex = new Exception(); StackTraceElement[] trace = ex.getStackTrace(); - String name = object.getClass().getCanonicalName(); + String name = lockable.getClass().getCanonicalName(); for (StackTraceElement element : trace) { if (element.getFileName() != null && !element.getFileName().contains(Locker.class.getSimpleName())) @@ -93,9 +77,9 @@ public interface LockCloser extends AutoCloseable public void close(); } - private static LockCloser simpleLock(LockStats stats) throws InterruptedException + private static LockCloser simpleLock(Lockable stats) throws InterruptedException { - Semaphore lock = stats.semaphore; + Semaphore lock = stats.getSemaphore(); lock.acquire(); return new LockCloser() @@ -109,24 +93,24 @@ public void close() }; } - private static LockCloser lockWithDiags(LockStats stats) throws InterruptedException + private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedException { - int offset = stats.requested.incrementAndGet(); + int offset = lockable.addRequested(); long waitStart = System.currentTimeMillis(); int ctr = 0; - Semaphore lock = stats.semaphore; + Semaphore lock = lockable.getSemaphore(); while (!lock.tryAcquire(250, TimeUnit.MILLISECONDS)) { ctr++; - dumpBlocker(stats, ctr); + dumpBlocker(lockable, ctr); } - stats.dumped = false; - stats.acquired.getAndIncrement(); + lockable.setDumped(false); + lockable.addAcquired(); long acquiredAt = System.currentTimeMillis(); - stats.threadHoldingLock.set(Thread.currentThread()); + lockable.threadHoldingLock.set(Thread.currentThread()); return new LockCloser() { @@ -136,25 +120,25 @@ public void close() { // ignore any wait that may have been caused by Locker code, so // count the waiters before we release the lock - long waiters = stats.requested.get() - offset; - stats.waited.addAndGet((int) waiters); + long waiters = lockable.getRequested() - offset; + lockable.addWaited((int) waiters); - boolean dumped = stats.dumped; + boolean dumped = lockable.isDumped(); // release the lock lock.release(); // count the time waiting and holding the lock int holdTime = (int) (System.currentTimeMillis() - acquiredAt); int waitTime = (int) (acquiredAt - waitStart); - stats.totalWaitTime.addAndGet(waitTime); - stats.totalHoldTime.addAndGet(holdTime); + lockable.addTotalWaitTime(waitTime); + lockable.addTotalHoldTime(holdTime); - long averageHoldTime = stats.getAverageHoldTime(); + long averageHoldTime = lockable.getAverageHoldTime(); if (waiters > 0 && holdTime > averageHoldTime * 2 || dumped) { // some threads waited String message = "Lock held for (" + holdTime + "MS), " + waiters - + " threads waited for some of that time! " + getCaller(stats.object); + + " threads waited for some of that time! " + getCaller(lockable); logger.warn(message); if (holdTime > averageHoldTime * 10.0 || dumped) { @@ -166,8 +150,8 @@ public void close() if (holdTime > averageHoldTime * 5.0) { // long hold! - String message = "Lock hold of lock (" + holdTime + "MS), average is " + stats.getAverageHoldTime() + " " - + getCaller(stats.object); + String message = "Lock hold of lock (" + holdTime + "MS), average is " + lockable.getAverageHoldTime() + + " " + getCaller(lockable); logger.warn(message); if (holdTime > averageHoldTime * 10.0) @@ -181,15 +165,15 @@ public void close() } - private static void dumpBlocker(LockStats stats, int ctr) + private static void dumpBlocker(Lockable lockable, int ctr) { - synchronized (stats) + synchronized (lockable) { - if (!stats.dumped) + if (!lockable.isDumped()) { - Thread thread = stats.threadHoldingLock.get(); - stats.dumped = true; + Thread thread = lockable.threadHoldingLock.get(); + lockable.setDumped(true); if (thread != null) { @@ -243,21 +227,21 @@ public static void enable() private static void dumpStats() { - List stats = new LinkedList<>(); + List lockables = new LinkedList<>(); - synchronized (mapSync) + synchronized (sync) { - stats.addAll(lockObjectMap.values()); + lockables.addAll(keepList.values()); keepList.clear(); } boolean activity = false; - for (LockStats stat : stats) + for (Lockable lockable : lockables) { - if ((stat.waited.get() > 0 && stat.totalWaitTime.get() > stat.getAverageHoldTime()) || first) + if ((lockable.getWaited() > 0 && lockable.getTotalWaitTime() > lockable.getAverageHoldTime()) || first) { activity = true; - logger.warn(stat); + logger.warn(lockable.asString()); } } @@ -268,48 +252,4 @@ private static void dumpStats() } } - static class LockStats - { - - @Override - public String toString() - { - return "LockStats [totalWaitTime=" + totalWaitTime + ", totalHoldTime=" + totalHoldTime + ", waited=" + waited - + ", acquired=" + acquired + ", object=" + name + "]"; - } - - final Semaphore semaphore = new Semaphore(1, true); - - // this reference to object stops the WeakRefHashMap removing this - // LockStats from - // the map - final Object object; - - final String name; - final AtomicReference threadHoldingLock = new AtomicReference<>(); - final AtomicInteger totalWaitTime = new AtomicInteger(); - final AtomicInteger totalHoldTime = new AtomicInteger(); - final AtomicInteger requested = new AtomicInteger(); - final AtomicInteger waited = new AtomicInteger(); - final AtomicInteger acquired = new AtomicInteger(); - volatile boolean dumped = false; - - LockStats(Object object, String name) - { - this.object = object; - this.name = name; - } - - long getAverageHoldTime() - { - long hold = totalHoldTime.get(); - long count = acquired.get(); - if (count < 10) - { - return 250; - } - return Math.max(hold / count, 50); - } - } - } diff --git a/src/test/java/org/asteriskjava/util/LockerTest.java b/src/test/java/org/asteriskjava/util/LockerTest.java index 7d36b5990..0955433c4 100644 --- a/src/test/java/org/asteriskjava/util/LockerTest.java +++ b/src/test/java/org/asteriskjava/util/LockerTest.java @@ -6,7 +6,7 @@ public class LockerTest { - private final Object sync = new Object(); + private final Lockable sync = new Lockable(); @Test public void test() @@ -17,7 +17,7 @@ public void test() long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < seconds * 1000) { - try (LockCloser closer = Locker.lock(sync)) + try (LockCloser closer = sync.withLock()) { a++; } @@ -29,7 +29,7 @@ public void test() start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < seconds * 1000) { - try (LockCloser closer = Locker.lock(sync)) + try (LockCloser closer = sync.withLock()) { a++; } From 322c38e0f59574fa13e1fccc34958b63c44fc884 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 9 Feb 2021 11:15:08 +1100 Subject: [PATCH 412/802] some fixes --- .../java/org/asteriskjava/util/Locker.java | 51 +++++++----- .../org/asteriskjava/util/LockerTest.java | 82 ++++++++++++++++++- 2 files changed, 113 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index 3585f70f1..02ecca61f 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -15,6 +16,8 @@ public class Locker private static final Log logger = LogFactory.getLog(Locker.class); private static volatile boolean diags = false; + + private static ScheduledFuture< ? > future; private static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); private static final Object sync = new Object(); @@ -25,18 +28,14 @@ public class Locker public static LockCloser doWithLock(final Lockable lockable) { - if (diags) - { - synchronized (sync) - { - keepList.put(lockable.getLockableId(), lockable); - } - } - try { if (diags) { + synchronized (sync) + { + keepList.put(lockable.getLockableId(), lockable); + } return lockWithDiags(lockable); } return simpleLock(lockable); @@ -77,9 +76,9 @@ public interface LockCloser extends AutoCloseable public void close(); } - private static LockCloser simpleLock(Lockable stats) throws InterruptedException + private static LockCloser simpleLock(Lockable lockable) throws InterruptedException { - Semaphore lock = stats.getSemaphore(); + Semaphore lock = lockable.getSemaphore(); lock.acquire(); return new LockCloser() @@ -209,23 +208,37 @@ private static void dumpBlocker(Lockable lockable, int ctr) */ public static void enable() { - if (!diags) + synchronized (sync) { - diags = true; - executor.scheduleWithFixedDelay(() -> { - dumpStats(); - }, 1, 1, TimeUnit.MINUTES); + if (!diags) + { + diags = true; + future = executor.scheduleWithFixedDelay(() -> { + dumpStats(); + }, 1, 1, TimeUnit.MINUTES); + } + else + { + logger.warn("Already enabled"); + } } - else + } + + public static void disable() + { + synchronized (sync) { - logger.warn("Already enabled"); + if (diags) + { + diags = false; + future.cancel(false); + } } - } private static volatile boolean first = true; - private static void dumpStats() + static void dumpStats() { List lockables = new LinkedList<>(); diff --git a/src/test/java/org/asteriskjava/util/LockerTest.java b/src/test/java/org/asteriskjava/util/LockerTest.java index 0955433c4..e25485b19 100644 --- a/src/test/java/org/asteriskjava/util/LockerTest.java +++ b/src/test/java/org/asteriskjava/util/LockerTest.java @@ -1,5 +1,7 @@ package org.asteriskjava.util; +import java.util.concurrent.TimeUnit; + import org.asteriskjava.util.Locker.LockCloser; import org.junit.Test; @@ -9,8 +11,9 @@ public class LockerTest private final Lockable sync = new Lockable(); @Test - public void test() + public void test1() { + Locker.disable(); int seconds = 2; int a = 0; @@ -49,4 +52,81 @@ public void test() } + volatile boolean stop = false; + int concurrentCounter1 = 0; + int concurrentCounter2 = 0; + int concurrentCounter3 = 0; + + @Test + public void testConcurrency() throws InterruptedException + { + Lockable s1 = new Lockable(); + Lockable s2 = new Lockable(); + Lockable s3 = new Lockable(); + + int seconds = 2; + + Locker.enable(); + stop = false; + Runnable runable2 = () -> { + while (!stop) + { + try (LockCloser closer = s1.withLock()) + { + concurrentCounter2++; + } + } + }; + + new Thread(runable2).start(); + new Thread(runable2).start(); + TimeUnit.SECONDS.sleep(seconds); + stop = true; + TimeUnit.SECONDS.sleep(1); + System.out.println(concurrentCounter2 / seconds + " Locker per second with 2 threads and diags"); + + Locker.disable(); + stop = false; + + Runnable runable = () -> { + while (!stop) + { + try (LockCloser closer = s2.withLock()) + { + concurrentCounter1++; + } + } + }; + new Thread(runable).start(); + new Thread(runable).start(); + TimeUnit.SECONDS.sleep(seconds); + stop = true; + TimeUnit.SECONDS.sleep(1); + System.out.println(concurrentCounter1 / seconds + " Locker per second with 2 threads"); + + Locker.dumpStats(); + stop = false; + + Runnable runable3 = () -> { + while (!stop) + { + synchronized (s3) + { + concurrentCounter3++; + } + } + }; + new Thread(runable3).start(); + new Thread(runable3).start(); + TimeUnit.SECONDS.sleep(seconds); + stop = true; + TimeUnit.SECONDS.sleep(1); + System.out.println(concurrentCounter3 / seconds + " synchronized per second with 2 threads"); + + System.out.println("\nIt seems wrong that 2 threads with diags is faster,\n" + + "but the reality is that with the added overhead of diags there is less lock contention so it runs faster.\n" + + "If more threads are added the two tests produce near identicaly through put as contention is high for both cases then.\n"); + + } + } From 6b8853172d7339c96d9e3660004db055657bd4e2 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 9 Feb 2021 11:33:12 +1100 Subject: [PATCH 413/802] enable/disable improvements --- src/main/java/org/asteriskjava/util/Locker.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index 02ecca61f..9def21b3f 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -216,6 +216,7 @@ public static void enable() future = executor.scheduleWithFixedDelay(() -> { dumpStats(); }, 1, 1, TimeUnit.MINUTES); + logger.warn("Lock checking enabled"); } else { @@ -232,6 +233,12 @@ public static void disable() { diags = false; future.cancel(false); + dumpStats(); + logger.warn("Lock checking disabled"); + } + else + { + logger.warn("Lock checking is already disabled"); } } } From 16bc0ee7df81aee90c9b1ae3f5743a5a8357f909 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 9 Feb 2021 11:35:20 +1100 Subject: [PATCH 414/802] move synchronized methods to locker --- .../internal/ManagerConnectionImpl.java | 329 +++++++++--------- 1 file changed, 172 insertions(+), 157 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 0081a8081..8396088c6 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -471,30 +471,33 @@ public void setSocketReadTimeout(int socketReadTimeout) this.socketReadTimeout = socketReadTimeout; } - public synchronized void login() throws IOException, AuthenticationFailedException, TimeoutException + public void login() throws IOException, AuthenticationFailedException, TimeoutException { login(null); } - public synchronized void login(String eventMask) throws IOException, AuthenticationFailedException, TimeoutException + public void login(String eventMask) throws IOException, AuthenticationFailedException, TimeoutException { - if (state != INITIAL && state != DISCONNECTED) + try (LockCloser closer = this.withLock()) { - throw new IllegalStateException("Login may only be perfomed when in state " - + "INITIAL or DISCONNECTED, but connection is in state " + state); - } + if (state != INITIAL && state != DISCONNECTED) + { + throw new IllegalStateException("Login may only be perfomed when in state " + + "INITIAL or DISCONNECTED, but connection is in state " + state); + } - state = CONNECTING; - this.eventMask = eventMask; - try - { - doLogin(defaultResponseTimeout, eventMask); - } - finally - { - if (state != CONNECTED) + state = CONNECTING; + this.eventMask = eventMask; + try { - state = DISCONNECTED; + doLogin(defaultResponseTimeout, eventMask); + } + finally + { + if (state != CONNECTED) + { + state = DISCONNECTED; + } } } } @@ -527,119 +530,122 @@ public synchronized void login(String eventMask) throws IOException, Authenticat * @throws TimeoutException if a timeout occurs while waiting for the * protocol identifier. The connection is closed in this case. */ - protected synchronized void doLogin(long timeout, String eventMask) + protected void doLogin(long timeout, String eventMask) throws IOException, AuthenticationFailedException, TimeoutException { - ChallengeAction challengeAction; - ManagerResponse challengeResponse; - String challenge; - String key; - LoginAction loginAction; - ManagerResponse loginResponse; - - if (socket == null) + try (LockCloser closer = this.withLock()) { - connect(); - } + ChallengeAction challengeAction; + ManagerResponse challengeResponse; + String challenge; + String key; + LoginAction loginAction; + ManagerResponse loginResponse; - if (protocolIdentifier.getValue() == null) - { - try + if (socket == null) { - protocolIdentifier.await(timeout); + connect(); } - catch (InterruptedException e) // NOPMD + + if (protocolIdentifier.getValue() == null) { - Thread.currentThread().interrupt(); + try + { + protocolIdentifier.await(timeout); + } + catch (InterruptedException e) // NOPMD + { + Thread.currentThread().interrupt(); + } } - } - if (protocolIdentifier.getValue() == null) - { - disconnect(); - if (reader != null && reader.getTerminationException() != null) + if (protocolIdentifier.getValue() == null) { - throw reader.getTerminationException(); + disconnect(); + if (reader != null && reader.getTerminationException() != null) + { + throw reader.getTerminationException(); + } + throw new TimeoutException("Timeout waiting for protocol identifier"); } - throw new TimeoutException("Timeout waiting for protocol identifier"); - } - - challengeAction = new ChallengeAction("MD5"); - try - { - challengeResponse = sendAction(challengeAction); - } - catch (Exception e) - { - disconnect(); - throw new AuthenticationFailedException("Unable to send challenge action", e); - } - if (challengeResponse instanceof ChallengeResponse) - { - challenge = ((ChallengeResponse) challengeResponse).getChallenge(); - } - else - { - disconnect(); - throw new AuthenticationFailedException( - "Unable to get challenge from Asterisk. ChallengeAction returned: " + challengeResponse.getMessage()); - } + challengeAction = new ChallengeAction("MD5"); + try + { + challengeResponse = sendAction(challengeAction); + } + catch (Exception e) + { + disconnect(); + throw new AuthenticationFailedException("Unable to send challenge action", e); + } - try - { - MessageDigest md; + if (challengeResponse instanceof ChallengeResponse) + { + challenge = ((ChallengeResponse) challengeResponse).getChallenge(); + } + else + { + disconnect(); + throw new AuthenticationFailedException("Unable to get challenge from Asterisk. ChallengeAction returned: " + + challengeResponse.getMessage()); + } - md = MessageDigest.getInstance("MD5"); - if (challenge != null) + try { - md.update(challenge.getBytes(StandardCharsets.UTF_8)); + MessageDigest md; + + md = MessageDigest.getInstance("MD5"); + if (challenge != null) + { + md.update(challenge.getBytes(StandardCharsets.UTF_8)); + } + if (password != null) + { + md.update(password.getBytes(StandardCharsets.UTF_8)); + } + key = ManagerUtil.toHexString(md.digest()); } - if (password != null) + catch (NoSuchAlgorithmException ex) { - md.update(password.getBytes(StandardCharsets.UTF_8)); + disconnect(); + throw new AuthenticationFailedException("Unable to create login key using MD5 Message Digest", ex); } - key = ManagerUtil.toHexString(md.digest()); - } - catch (NoSuchAlgorithmException ex) - { - disconnect(); - throw new AuthenticationFailedException("Unable to create login key using MD5 Message Digest", ex); - } - loginAction = new LoginAction(username, "MD5", key, eventMask); - try - { - loginResponse = sendAction(loginAction); - } - catch (Exception e) - { - disconnect(); - throw new AuthenticationFailedException("Unable to send login action", e); - } + loginAction = new LoginAction(username, "MD5", key, eventMask); + try + { + loginResponse = sendAction(loginAction); + } + catch (Exception e) + { + disconnect(); + throw new AuthenticationFailedException("Unable to send login action", e); + } - if (loginResponse instanceof ManagerError) - { - disconnect(); - throw new AuthenticationFailedException(loginResponse.getMessage()); - } + if (loginResponse instanceof ManagerError) + { + disconnect(); + throw new AuthenticationFailedException(loginResponse.getMessage()); + } - logger.info("Successfully logged in"); + logger.info("Successfully logged in"); - version = determineVersion(); + version = determineVersion(); - state = CONNECTED; + state = CONNECTED; - writer.setTargetVersion(version); + writer.setTargetVersion(version); - logger.info("Determined Asterisk version: " + version); + logger.info("Determined Asterisk version: " + version); - // generate pseudo event indicating a successful login - ConnectEvent connectEvent = new ConnectEvent(this); - connectEvent.setProtocolIdentifier(getProtocolIdentifier()); - connectEvent.setDateReceived(DateUtil.getDate()); - // TODO could this cause a deadlock? - fireEvent(connectEvent); + // generate pseudo event indicating a successful login + ConnectEvent connectEvent = new ConnectEvent(this); + connectEvent.setProtocolIdentifier(getProtocolIdentifier()); + connectEvent.setDateReceived(DateUtil.getDate()); + // TODO could this cause a deadlock? + fireEvent(connectEvent); + } } protected AsteriskVersion determineVersion() throws IOException, TimeoutException @@ -736,40 +742,43 @@ protected AsteriskVersion determineVersionByCoreShowVersion() throws Exception return AsteriskVersion.getDetermineVersionFromString(coreLine); } - protected synchronized void connect() throws IOException + protected void connect() throws IOException { - logger.info("Connecting to " + hostname + ":" + port); - - if (reader == null) + try (LockCloser closer = this.withLock()) { - logger.debug("Creating reader for " + hostname + ":" + port); - reader = createReader(this, this); - } + logger.info("Connecting to " + hostname + ":" + port); - if (writer == null) - { - logger.debug("Creating writer"); - writer = createWriter(); - } + if (reader == null) + { + logger.debug("Creating reader for " + hostname + ":" + port); + reader = createReader(this, this); + } - logger.debug("Creating socket"); - socket = createSocket(); + if (writer == null) + { + logger.debug("Creating writer"); + writer = createWriter(); + } - logger.debug("Passing socket to reader"); - reader.setSocket(socket); + logger.debug("Creating socket"); + socket = createSocket(); - if (readerThread == null || !readerThread.isAlive() || reader.isDead()) - { - logger.debug("Creating and starting reader thread"); - readerThread = new Thread(reader); - readerThread - .setName("Asterisk-Java ManagerConnection-" + id + "-Reader-" + readerThreadCounter.getAndIncrement()); - readerThread.setDaemon(true); - readerThread.start(); - } + logger.debug("Passing socket to reader"); + reader.setSocket(socket); - logger.debug("Passing socket to writer"); - writer.setSocket(socket); + if (readerThread == null || !readerThread.isAlive() || reader.isDead()) + { + logger.debug("Creating and starting reader thread"); + readerThread = new Thread(reader); + readerThread.setName( + "Asterisk-Java ManagerConnection-" + id + "-Reader-" + readerThreadCounter.getAndIncrement()); + readerThread.setDaemon(true); + readerThread.start(); + } + + logger.debug("Passing socket to writer"); + writer.setSocket(socket); + } } protected SocketConnectionFacade createSocket() throws IOException @@ -777,50 +786,56 @@ protected SocketConnectionFacade createSocket() throws IOException return new SocketConnectionFacadeImpl(hostname, port, ssl, socketTimeout, socketReadTimeout, encoding); } - public synchronized void logoff() throws IllegalStateException + public void logoff() throws IllegalStateException { - if (state != CONNECTED && state != RECONNECTING) + try (LockCloser closer = this.withLock()) { - throw new IllegalStateException("Logoff may only be perfomed when in state " - + "CONNECTED or RECONNECTING, but connection is in state " + state); - } - - state = DISCONNECTING; - - if (socket != null) - { - try + if (state != CONNECTED && state != RECONNECTING) { - sendAction(new LogoffAction()); + throw new IllegalStateException("Logoff may only be perfomed when in state " + + "CONNECTED or RECONNECTING, but connection is in state " + state); } - catch (Exception e) + + state = DISCONNECTING; + + if (socket != null) { - logger.warn("Unable to send LogOff action", e); + try + { + sendAction(new LogoffAction()); + } + catch (Exception e) + { + logger.warn("Unable to send LogOff action", e); + } } + cleanup(); + state = DISCONNECTED; } - cleanup(); - state = DISCONNECTED; } /** * Closes the socket connection. */ - protected synchronized void disconnect() + protected void disconnect() { - if (socket != null) + try (LockCloser closer = this.withLock()) { - logger.info("Closing socket."); - try + if (socket != null) { - socket.close(); - } - catch (IOException ex) - { - logger.warn("Unable to close socket: " + ex.getMessage()); + logger.info("Closing socket."); + try + { + socket.close(); + } + catch (IOException ex) + { + logger.warn("Unable to close socket: " + ex.getMessage()); + } + socket = null; } - socket = null; + protocolIdentifier.reset(); } - protocolIdentifier.reset(); } public ManagerResponse sendAction(ManagerAction action) From b73fc9e26797f5fade11dc861d4ca4a848264ed6 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 9 Feb 2021 12:08:46 +1100 Subject: [PATCH 415/802] change to ReentrantLock to keep semantics of synchronized --- .../java/org/asteriskjava/util/Lockable.java | 10 +++++----- src/main/java/org/asteriskjava/util/Locker.java | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/Lockable.java b/src/main/java/org/asteriskjava/util/Lockable.java index 567ecb0e8..19bff3b94 100644 --- a/src/main/java/org/asteriskjava/util/Lockable.java +++ b/src/main/java/org/asteriskjava/util/Lockable.java @@ -1,15 +1,15 @@ package org.asteriskjava.util; -import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.ReentrantLock; import org.asteriskjava.util.Locker.LockCloser; public class Lockable { - private final Semaphore semaphore = new Semaphore(1, true); + private final ReentrantLock internalLock = new ReentrantLock(true); final private String lockName; final AtomicReference threadHoldingLock = new AtomicReference<>(); private final AtomicInteger totalWaitTime = new AtomicInteger(); @@ -48,7 +48,7 @@ String getCaller() public String asString() { return "Lockable [totalWaitTime=" + totalWaitTime + ", totalHoldTime=" + totalHoldTime + ", waited=" + waited - + ", acquired=" + acquired + ", object=" + lockName + "]"; + + ", acquired=" + acquired + ", object=" + lockName + ", id=" + lockableId + "]"; } long getAverageHoldTime() @@ -67,9 +67,9 @@ public LockCloser withLock() return Locker.doWithLock(this); } - Semaphore getSemaphore() + ReentrantLock getInternalLock() { - return semaphore; + return internalLock; } void addTotalWaitTime(int time) diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index 9def21b3f..54068aa94 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -7,8 +7,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; public class Locker { @@ -50,7 +50,7 @@ public static LockCloser doWithLock(final Lockable lockable) /** * determine the caller to Locker * - * @param semaphore + * @param lockable * @return */ static String getCaller(Lockable lockable) @@ -78,8 +78,8 @@ public interface LockCloser extends AutoCloseable private static LockCloser simpleLock(Lockable lockable) throws InterruptedException { - Semaphore lock = lockable.getSemaphore(); - lock.acquire(); + ReentrantLock lock = lockable.getInternalLock(); + lock.lock(); return new LockCloser() { @@ -87,7 +87,7 @@ private static LockCloser simpleLock(Lockable lockable) throws InterruptedExcept @Override public void close() { - lock.release(); + lock.unlock(); } }; } @@ -99,8 +99,8 @@ private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedExc long waitStart = System.currentTimeMillis(); int ctr = 0; - Semaphore lock = lockable.getSemaphore(); - while (!lock.tryAcquire(250, TimeUnit.MILLISECONDS)) + ReentrantLock lock = lockable.getInternalLock(); + while (!lock.tryLock(250, TimeUnit.MILLISECONDS)) { ctr++; dumpBlocker(lockable, ctr); @@ -124,7 +124,7 @@ public void close() boolean dumped = lockable.isDumped(); // release the lock - lock.release(); + lock.unlock(); // count the time waiting and holding the lock int holdTime = (int) (System.currentTimeMillis() - acquiredAt); From fb4e467985406b0f33356298615141c3b1f67ec3 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 9 Feb 2021 15:56:14 +1100 Subject: [PATCH 416/802] tidy up stack trace acquisition --- src/main/java/org/asteriskjava/util/Lockable.java | 3 +-- src/main/java/org/asteriskjava/util/Locker.java | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/Lockable.java b/src/main/java/org/asteriskjava/util/Lockable.java index 19bff3b94..413cc5557 100644 --- a/src/main/java/org/asteriskjava/util/Lockable.java +++ b/src/main/java/org/asteriskjava/util/Lockable.java @@ -29,8 +29,7 @@ public Lockable() String getCaller() { - Exception ex = new Exception(); - StackTraceElement[] trace = ex.getStackTrace(); + StackTraceElement[] trace = new Exception().getStackTrace(); String name = this.getClass().getCanonicalName(); for (StackTraceElement element : trace) { diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index 54068aa94..84dd75a5d 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -55,8 +55,7 @@ public static LockCloser doWithLock(final Lockable lockable) */ static String getCaller(Lockable lockable) { - Exception ex = new Exception(); - StackTraceElement[] trace = ex.getStackTrace(); + StackTraceElement[] trace = new Exception().getStackTrace(); String name = lockable.getClass().getCanonicalName(); for (StackTraceElement element : trace) { @@ -176,7 +175,7 @@ private static void dumpBlocker(Lockable lockable, int ctr) if (thread != null) { - StackTraceElement[] trace = thread.getStackTrace(); + StackTraceElement[] trace = new Exception().getStackTrace(); String dump = ""; From a52f195172891af93ed2debee09a39d734afa7bb Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 11 Feb 2021 11:49:19 +1100 Subject: [PATCH 417/802] reduce logging level and cleanup --- .../internal/asterisk/MeetmeRoomControl.java | 2 +- .../core/CoherentManagerConnection.java | 50 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index 3433596ce..85117ddf6 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -149,7 +149,7 @@ public MeetmeRoom findAvailableRoom(RoomOwner newOwner) { room.setInactive(); room.setOwner(newOwner); - MeetmeRoomControl.logger.warn("Returning available room " + room.getRoomNumber()); + MeetmeRoomControl.logger.info("Returning available room " + room.getRoomNumber()); return room; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java index 1a6393363..aeff22db8 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -119,7 +119,7 @@ public static synchronized void init() throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException, InterruptedException { if (self != null) - logger.warn("The CoherentManagerConnection has already been initialised"); //$NON-NLS-1$ + logger.warn("The CoherentManagerConnection has already been initialised"); else { self = new CoherentManagerConnection(); @@ -159,7 +159,7 @@ public static void reset() public static synchronized CoherentManagerConnection getInstance() { if (self == null) - throw new IllegalStateException("The CoherentManagerConnection has not been initialised"); //$NON-NLS-1$ + throw new IllegalStateException("The CoherentManagerConnection has not been initialised"); self.checkConnection(); @@ -195,17 +195,17 @@ public void setVariable(final Channel channel, final String variableName, final throw new PBXException("Channel: " + channel + " cannot be retrieved as it is still in transition."); response = sendAction(setVariable, 500); - if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0)) //$NON-NLS-1$ + if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0)) { // $NON-NLS-1$ - CoherentManagerConnection.logger.debug("set variable " + variableName + " to " + value //$NON-NLS-1$ //$NON-NLS-2$ - + " on " + channel); //$NON-NLS-1$ + CoherentManagerConnection.logger.debug("set variable " + variableName + " to " + value //$NON-NLS-2$ + + " on " + channel); } else { - throw new PBXException("failed to set variable '" + variableName + "' on channel " + channel + " to '" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - + value + "'" + (response != null ? " Error:" + response.getMessage() : "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + throw new PBXException("failed to set variable '" + variableName + "' on channel " + channel + " to '" //$NON-NLS-2$ //$NON-NLS-3$ + + value + "'" + (response != null ? " Error:" + response.getMessage() : "")); //$NON-NLS-2$ //$NON-NLS-3$ } } catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) @@ -239,16 +239,16 @@ public String getVariable(final Channel channel, final String variableName) ManagerResponse convertedResponse = sendAction(var, 500); if (convertedResponse != null) { - value = convertedResponse.getAttribute("value"); //$NON-NLS-1$ + value = convertedResponse.getAttribute("value"); if (value == null) value = ""; - CoherentManagerConnection.logger.debug("getVarAction returned name:" + variableName + " value:" + value); //$NON-NLS-1$ //$NON-NLS-2$ + CoherentManagerConnection.logger.debug("getVarAction returned name:" + variableName + " value:" + value); //$NON-NLS-2$ } } catch (final Exception e) { CoherentManagerConnection.logger.debug(e, e); - CoherentManagerConnection.logger.error("getVariable: " + e); //$NON-NLS-1$ + CoherentManagerConnection.logger.error("getVariable: " + e); } return value; } @@ -277,7 +277,7 @@ public void run() } } }; - background.setName("sendActionNoWait"); //$NON-NLS-1$ + background.setName("sendActionNoWait"); background.setDaemon(true); background.start(); } @@ -328,7 +328,7 @@ public static ManagerResponse sendAction(final ManagerAction action, final int t throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException { if (logger.isDebugEnabled()) - CoherentManagerConnection.logger.debug("Sending Action: " + action.toString()); //$NON-NLS-1$ + CoherentManagerConnection.logger.debug("Sending Action: " + action.toString()); CoherentManagerConnection.getInstance(); if ((CoherentManagerConnection.managerConnection != null) @@ -344,15 +344,15 @@ public static ManagerResponse sendAction(final ManagerAction action, final int t if (response != null) convertedResponse = CoherentEventFactory.build(response); - if ((convertedResponse != null) && (convertedResponse.getResponse().compareToIgnoreCase("Error") == 0))//$NON-NLS-1$ + if ((convertedResponse != null) && (convertedResponse.getResponse().compareToIgnoreCase("Error") == 0)) { - CoherentManagerConnection.logger.warn("Action '" + ajAction + "' failed, Response: " //$NON-NLS-1$ //$NON-NLS-2$ - + convertedResponse.getResponse() + " Message: " + convertedResponse.getMessage()); //$NON-NLS-1$ + CoherentManagerConnection.logger.warn("Action '" + ajAction + "' failed, Response: " + + convertedResponse.getResponse() + " Message: " + convertedResponse.getMessage()); } return convertedResponse; } - throw new IllegalStateException("not connected."); //$NON-NLS-1$ + throw new IllegalStateException("not connected."); } private void checkConnection() @@ -365,7 +365,7 @@ private void checkConnection() { if (trys == 3) { - CoherentManagerConnection.logger.warn("Awaiting Manager connection"); //$NON-NLS-1$ + CoherentManagerConnection.logger.warn("Awaiting Manager connection"); } try { @@ -398,7 +398,7 @@ private void configureConnection() // that it hasn't already) // and should have no duplicate events. Once drained the queue will be // garbage collected. - CoherentManagerEventQueue newRealtime = new CoherentManagerEventQueue("Realtime", //$NON-NLS-1$ + CoherentManagerEventQueue newRealtime = new CoherentManagerEventQueue("Realtime", CoherentManagerConnection.managerConnection); if (this.realtimeEventQueue != null) { @@ -407,7 +407,7 @@ private void configureConnection() } this.realtimeEventQueue = newRealtime; - CoherentManagerEventQueue newStandard = new CoherentManagerEventQueue("Standard", //$NON-NLS-1$ + CoherentManagerEventQueue newStandard = new CoherentManagerEventQueue("Standard", CoherentManagerConnection.managerConnection); if (this.eventQueue != null) { @@ -428,11 +428,11 @@ private void checkFeatures() throws IOException, TimeoutException boolean muteAudioFound = false; for (final String command : convertedResponse.getAttributes().keySet()) { - if (command.toLowerCase().contains("bridge")) //$NON-NLS-1$ + if (command.toLowerCase().contains("bridge")) { bridgeFound = true; } - if (command.toLowerCase().contains("muteaudio")) //$NON-NLS-1$ + if (command.toLowerCase().contains("muteaudio")) { muteAudioFound = true; } @@ -463,7 +463,7 @@ public void shutDown() } catch (final Exception e) { - CoherentManagerConnection.logger.debug("Manager logging off"); //$NON-NLS-1$ + CoherentManagerConnection.logger.debug("Manager logging off"); CoherentManagerConnection.logger.debug(e, e); } } @@ -508,7 +508,7 @@ public void addListener(FilteredManagerListener listener) @Override public String getName() { - return "CoherentManagerConnection"; //$NON-NLS-1$ + return "CoherentManagerConnection"; } @Override @@ -527,12 +527,12 @@ public void onManagerEvent(ManagerEvent event) // by notifying it of the connection. if (event instanceof ConnectEvent) { - logger.warn("****************** Asterisk manager connection acquired **************************"); //$NON-NLS-1$ + logger.warn("****************** Asterisk manager connection acquired **************************"); this._reconnectLatch.countDown(); } else if (event instanceof DisconnectEvent) { - logger.warn("****************** Asterisk manager connection lost **************************"); //$NON-NLS-1$ + logger.warn("****************** Asterisk manager connection lost **************************"); // new Thread(new Runnable() // { // public void run() From b305d6e3b33ecf0e26a5b189f50431408e965769 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 11 Feb 2021 11:49:40 +1100 Subject: [PATCH 418/802] switch to unfair lock to flush out locking bugs --- src/main/java/org/asteriskjava/util/Lockable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/util/Lockable.java b/src/main/java/org/asteriskjava/util/Lockable.java index 413cc5557..a8d25cb1f 100644 --- a/src/main/java/org/asteriskjava/util/Lockable.java +++ b/src/main/java/org/asteriskjava/util/Lockable.java @@ -9,7 +9,7 @@ public class Lockable { - private final ReentrantLock internalLock = new ReentrantLock(true); + private final ReentrantLock internalLock = new ReentrantLock(false); final private String lockName; final AtomicReference threadHoldingLock = new AtomicReference<>(); private final AtomicInteger totalWaitTime = new AtomicInteger(); From 8ca43ef0c43696c4fde90ca988814e23e7217974 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 11 Feb 2021 11:52:49 +1100 Subject: [PATCH 419/802] organize imports and incedental reformat --- .../org/asteriskjava/fastagi/AgiWriter.java | 1 - .../fastagi/DefaultAgiServer.java | 1 + .../manager/ManagerConnection.java | 1 + .../asteriskjava/manager/event/AorDetail.java | 351 ++- .../manager/event/ContactStatusDetail.java | 338 ++- .../manager/event/EndpointDetail.java | 2489 +++++++++-------- .../bridge/BridgeEnterEventComparator.java | 4 +- .../wrap/response/ManagerResponse.java | 1 + 8 files changed, 1759 insertions(+), 1427 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/AgiWriter.java b/src/main/java/org/asteriskjava/fastagi/AgiWriter.java index 0b4527f5a..412222167 100644 --- a/src/main/java/org/asteriskjava/fastagi/AgiWriter.java +++ b/src/main/java/org/asteriskjava/fastagi/AgiWriter.java @@ -16,7 +16,6 @@ */ package org.asteriskjava.fastagi; -import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.command.AgiCommand; /** diff --git a/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java b/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java index 7b4088a6b..77ac2e9de 100644 --- a/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.net.InetAddress; +import java.net.Socket; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.concurrent.RejectedExecutionException; diff --git a/src/main/java/org/asteriskjava/manager/ManagerConnection.java b/src/main/java/org/asteriskjava/manager/ManagerConnection.java index 2f768d1b4..82cac30c9 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/ManagerConnection.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.net.InetAddress; import java.nio.charset.Charset; + import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.action.EventGeneratingAction; import org.asteriskjava.manager.action.ManagerAction; diff --git a/src/main/java/org/asteriskjava/manager/event/AorDetail.java b/src/main/java/org/asteriskjava/manager/event/AorDetail.java index e6ebac3d5..ee6401364 100644 --- a/src/main/java/org/asteriskjava/manager/event/AorDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/AorDetail.java @@ -1,11 +1,9 @@ package org.asteriskjava.manager.event; -import org.asteriskjava.util.AstUtil; - /** * A ContactStatusDetail event is triggered in response to a - * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, - * and contains information about a PJSIP Contact + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, and contains + * information about a PJSIP Contact *

    * * @author Steve Sether @@ -13,145 +11,216 @@ * @since 12 */ -public class AorDetail extends ResponseEvent { +public class AorDetail extends ResponseEvent +{ /** * Serial version identifier. */ - private static final long serialVersionUID = 2634171854313358591L; - public AorDetail(Object source) { - super(source); - } - - - private String objectType; - private String objectName; - private int minimumExpiration; - private int defaultExpiration; - private Float qualifyTimeout; - private String mailboxes; - private Boolean supportPath; - private String voicemailExtension; - private int maxContacts; - private Boolean authenticateQualify; - private String contacts; - private int maximumExpiration; - private int qualifyFrequency; - private Boolean removeExisting; - private String outboundProxy; - private int totalContacts; - private int contactsRegistered; - private String endpointName; - public String getObjectType() { - return objectType; - } - public void setObjectType(String objectType) { - this.objectType = objectType; - } - public String getObjectName() { - return objectName; - } - public void setObjectName(String objectName) { - this.objectName = objectName; - } - public int getMinimumExpiration() { - return minimumExpiration; - } - public void setMinimumExpiration(int minimumExpiration) { - this.minimumExpiration = minimumExpiration; - } - public int getDefaultExpiration() { - return defaultExpiration; - } - public void setDefaultExpiration(int defaultExpiration) { - this.defaultExpiration = defaultExpiration; - } - public Float getQualifyTimeout() { - return qualifyTimeout; - } - public void setQualifyTimeout(Float qualifyTimeout) { - this.qualifyTimeout = qualifyTimeout; - } - public String getMailboxes() { - return mailboxes; - } - public void setMailboxes(String mailboxes) { - this.mailboxes = mailboxes; - } - public Boolean isSupportPath() { - return supportPath; - } - public void setSupportPath(Boolean supportPath) { - this.supportPath = supportPath; - } - public String getVoicemailExtension() { - return voicemailExtension; - } - public void setVoicemailExtension(String voicemailExtension) { - this.voicemailExtension = voicemailExtension; - } - public int getMaxContacts() { - return maxContacts; - } - public void setMaxContacts(int maxContacts) { - this.maxContacts = maxContacts; - } - public Boolean isAuthenticateQualify() { - return authenticateQualify; - } - public void setAuthenticateQualify(Boolean authenticateQualify) { - this.authenticateQualify = authenticateQualify; - } - public String getContacts() { - return contacts; - } - public void setContacts(String contacts) { - this.contacts = contacts; - } - public int getMaximumExpiration() { - return maximumExpiration; - } - public void setMaximumExpiration(int maximumExpiration) { - this.maximumExpiration = maximumExpiration; - } - public int getQualifyFrequency() { - return qualifyFrequency; - } - public void setQualifyFrequency(int qualifyFrequency) { - this.qualifyFrequency = qualifyFrequency; - } - public Boolean isRemoveExisting() { - return removeExisting; - } - public void setRemoveExisting(Boolean removeExisting) { - this.removeExisting = removeExisting; - } - public String getOutboundProxy() { - return outboundProxy; - } - public void setOutboundProxy(String outboundProxy) { - this.outboundProxy = outboundProxy; - } - public int getTotalContacts() { - return totalContacts; - } - public void setTotalContacts(int totalContacts) { - this.totalContacts = totalContacts; - } - public int getContactsRegistered() { - return contactsRegistered; - } - public void setContactsRegistered(int contactsRegistered) { - this.contactsRegistered = contactsRegistered; - } - public String getEndpointName() { - return endpointName; - } - public void setEndpointName(String endpointName) { - this.endpointName = endpointName; - } - - - - + private static final long serialVersionUID = 2634171854313358591L; + + public AorDetail(Object source) + { + super(source); + } + + private String objectType; + private String objectName; + private int minimumExpiration; + private int defaultExpiration; + private Float qualifyTimeout; + private String mailboxes; + private Boolean supportPath; + private String voicemailExtension; + private int maxContacts; + private Boolean authenticateQualify; + private String contacts; + private int maximumExpiration; + private int qualifyFrequency; + private Boolean removeExisting; + private String outboundProxy; + private int totalContacts; + private int contactsRegistered; + private String endpointName; + + public String getObjectType() + { + return objectType; + } + + public void setObjectType(String objectType) + { + this.objectType = objectType; + } + + public String getObjectName() + { + return objectName; + } + + public void setObjectName(String objectName) + { + this.objectName = objectName; + } + + public int getMinimumExpiration() + { + return minimumExpiration; + } + + public void setMinimumExpiration(int minimumExpiration) + { + this.minimumExpiration = minimumExpiration; + } + + public int getDefaultExpiration() + { + return defaultExpiration; + } + + public void setDefaultExpiration(int defaultExpiration) + { + this.defaultExpiration = defaultExpiration; + } + + public Float getQualifyTimeout() + { + return qualifyTimeout; + } + + public void setQualifyTimeout(Float qualifyTimeout) + { + this.qualifyTimeout = qualifyTimeout; + } + + public String getMailboxes() + { + return mailboxes; + } + + public void setMailboxes(String mailboxes) + { + this.mailboxes = mailboxes; + } + + public Boolean isSupportPath() + { + return supportPath; + } + + public void setSupportPath(Boolean supportPath) + { + this.supportPath = supportPath; + } + + public String getVoicemailExtension() + { + return voicemailExtension; + } + + public void setVoicemailExtension(String voicemailExtension) + { + this.voicemailExtension = voicemailExtension; + } + + public int getMaxContacts() + { + return maxContacts; + } + + public void setMaxContacts(int maxContacts) + { + this.maxContacts = maxContacts; + } + + public Boolean isAuthenticateQualify() + { + return authenticateQualify; + } + + public void setAuthenticateQualify(Boolean authenticateQualify) + { + this.authenticateQualify = authenticateQualify; + } + + public String getContacts() + { + return contacts; + } + + public void setContacts(String contacts) + { + this.contacts = contacts; + } + + public int getMaximumExpiration() + { + return maximumExpiration; + } + + public void setMaximumExpiration(int maximumExpiration) + { + this.maximumExpiration = maximumExpiration; + } + + public int getQualifyFrequency() + { + return qualifyFrequency; + } + + public void setQualifyFrequency(int qualifyFrequency) + { + this.qualifyFrequency = qualifyFrequency; + } + + public Boolean isRemoveExisting() + { + return removeExisting; + } + + public void setRemoveExisting(Boolean removeExisting) + { + this.removeExisting = removeExisting; + } + + public String getOutboundProxy() + { + return outboundProxy; + } + + public void setOutboundProxy(String outboundProxy) + { + this.outboundProxy = outboundProxy; + } + + public int getTotalContacts() + { + return totalContacts; + } + + public void setTotalContacts(int totalContacts) + { + this.totalContacts = totalContacts; + } + + public int getContactsRegistered() + { + return contactsRegistered; + } + + public void setContactsRegistered(int contactsRegistered) + { + this.contactsRegistered = contactsRegistered; + } + + public String getEndpointName() + { + return endpointName; + } + + public void setEndpointName(String endpointName) + { + this.endpointName = endpointName; + } + } diff --git a/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java index b57f35e5c..f95839392 100644 --- a/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java @@ -1,11 +1,9 @@ package org.asteriskjava.manager.event; -import org.asteriskjava.util.AstUtil; - /** * A ContactStatusDetail event is triggered in response to a - * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, - * and contains information about a PJSIP Contact + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, and contains + * information about a PJSIP Contact *

    * * @author Steve Sether @@ -13,159 +11,189 @@ * @since 12 */ -public class ContactStatusDetail extends ResponseEvent { +public class ContactStatusDetail extends ResponseEvent +{ /** * Serial version identifier. */ - private static final long serialVersionUID = 987290433601178780L; - private String aor; - private String uri; - private String userAgent; - private long regExpire; - private String viaAddress; - private String callID; - private String status; - // roundtripusec when it contains a value is a long, but when it doesn't - // asterisk reports "N/A" - private String roundtripUsec; - private String endpointName; - private String id; - private Boolean authenticateQualify; - private String outboundProxy; - private String path; - private int qualifyFrequency; - private Float qualifyTimeout; - - public String getAor() { - return aor; - } - - public void setAor(String aor) { - this.aor = aor; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getUri() { - return uri; - } - - public void setUri(String uri) { - this.uri = uri; - } - - public String getUserAgent() { - return userAgent; - } - - public void setUserAgent(String userAgent) { - this.userAgent = userAgent; - } - - public long getRegExpire() { - return regExpire; - } - - public void setRegExpire(long regExpire) { - this.regExpire = regExpire; - } - - public String getViaAddress() { - return viaAddress; - } - - public void setViaAddress(String viaAddress) { - this.viaAddress = viaAddress; - } - - public String getCallID() { - return callID; - } - - public void setCallID(String callID) { - this.callID = callID; - } - - public String getEndpointName() { - return endpointName; - } - - public void setEndpointName(String endpointName) { - this.endpointName = endpointName; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public Boolean isAuthenticateQualify() { - return authenticateQualify; - } - - public void setAuthenticateQualify(Boolean authenticateQualify) { - this.authenticateQualify = authenticateQualify; - } - - public String getOutboundProxy() { - return outboundProxy; - } - - public void setOutboundProxy(String outboundProxy) { - this.outboundProxy = outboundProxy; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public int getQualifyFrequency() { - return qualifyFrequency; - } - - public void setQualifyFrequency(int qualifyFrequency) { - this.qualifyFrequency = qualifyFrequency; - } - - public Float getQualifyTimeout() { - return qualifyTimeout; - } - - public void setQualifyTimeout(Float qualifyTimeout) { - this.qualifyTimeout = qualifyTimeout; - } - - public void setQualifyTimeout(String qualifyTimeout) { - this.qualifyTimeout = Float.parseFloat(qualifyTimeout); - } - - public ContactStatusDetail(Object source) { - super(source); - } - - public String getRoundtripUsec() { - return roundtripUsec; - } - - public void setRoundtripUsec(String roundtripUsec) { - this.roundtripUsec = roundtripUsec; - } - - - - + private static final long serialVersionUID = 987290433601178780L; + private String aor; + private String uri; + private String userAgent; + private long regExpire; + private String viaAddress; + private String callID; + private String status; + // roundtripusec when it contains a value is a long, but when it doesn't + // asterisk reports "N/A" + private String roundtripUsec; + private String endpointName; + private String id; + private Boolean authenticateQualify; + private String outboundProxy; + private String path; + private int qualifyFrequency; + private Float qualifyTimeout; + + public String getAor() + { + return aor; + } + + public void setAor(String aor) + { + this.aor = aor; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getUri() + { + return uri; + } + + public void setUri(String uri) + { + this.uri = uri; + } + + public String getUserAgent() + { + return userAgent; + } + + public void setUserAgent(String userAgent) + { + this.userAgent = userAgent; + } + + public long getRegExpire() + { + return regExpire; + } + + public void setRegExpire(long regExpire) + { + this.regExpire = regExpire; + } + + public String getViaAddress() + { + return viaAddress; + } + + public void setViaAddress(String viaAddress) + { + this.viaAddress = viaAddress; + } + + public String getCallID() + { + return callID; + } + + public void setCallID(String callID) + { + this.callID = callID; + } + + public String getEndpointName() + { + return endpointName; + } + + public void setEndpointName(String endpointName) + { + this.endpointName = endpointName; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public Boolean isAuthenticateQualify() + { + return authenticateQualify; + } + + public void setAuthenticateQualify(Boolean authenticateQualify) + { + this.authenticateQualify = authenticateQualify; + } + + public String getOutboundProxy() + { + return outboundProxy; + } + + public void setOutboundProxy(String outboundProxy) + { + this.outboundProxy = outboundProxy; + } + + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + public int getQualifyFrequency() + { + return qualifyFrequency; + } + + public void setQualifyFrequency(int qualifyFrequency) + { + this.qualifyFrequency = qualifyFrequency; + } + + public Float getQualifyTimeout() + { + return qualifyTimeout; + } + + public void setQualifyTimeout(Float qualifyTimeout) + { + this.qualifyTimeout = qualifyTimeout; + } + + public void setQualifyTimeout(String qualifyTimeout) + { + this.qualifyTimeout = Float.parseFloat(qualifyTimeout); + } + + public ContactStatusDetail(Object source) + { + super(source); + } + + public String getRoundtripUsec() + { + return roundtripUsec; + } + + public void setRoundtripUsec(String roundtripUsec) + { + this.roundtripUsec = roundtripUsec; + } + } diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java b/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java index b83d1a07f..b8b8cd53e 100644 --- a/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java @@ -1,11 +1,9 @@ package org.asteriskjava.manager.event; -import org.asteriskjava.util.AstUtil; - /** * A EndpointDetail event is triggered in response to a - * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, - * and contains information about a PJSIP endpoint + * {@link org.asteriskjava.manager.action.PJSipShowEndpoint}, and contains + * information about a PJSIP endpoint *

    * * @author Steve Sether @@ -13,1136 +11,1371 @@ * @since 12 */ -public class EndpointDetail extends ResponseEvent { +public class EndpointDetail extends ResponseEvent +{ /** * Serial version identifier. */ - private static final long serialVersionUID = 77481930059189731L; + private static final long serialVersionUID = 77481930059189731L; private Integer listItems; private String eventList; - - public Integer getListItems() { - return listItems; - } - - public void setListItems(Integer listItems) { - this.listItems = listItems; - } - - public String getEventList() { - return eventList; - } - - public void setEventList(String eventList) { - this.eventList = eventList; - } - - private String objectName; - private String objectType; - private Boolean rpidImmediate; - private Boolean webrtc; - private Boolean ignorel83WithoutSdp; - private int deviceStateBusyAt; - private int t38UdptlMaxdatagram; - private int dtlsRekey; - private String namedPickupGroup; - private String directMediaMethod; - private Boolean sendRpid; - private String pickupGroup; - private String sdpSession; - private String dtlsVerify; - private String messageContext; - private String mailboxes; - private String recordOnFeature; - private String dtlsPrivateKey; - private String dtlsFingerprint; - private String fromDomain; - private int timersSessExpires; - private String namedCallGroup; - private String dtlsCipher; - private Boolean mediaEncryptionOptimistic; - private Boolean suppressQ850ReasonHeaders; - private String aors; - private String identifyBy; - private String calleridPrivacy; - private String mwiSubscribeReplacesUnsolicited; - private String cosAudio; - private Boolean followEarlyMediaFork; - private String context; - private Boolean rtpSymmetric; - private String transport; - private String mohSuggest; - private Boolean t38Udptl; - private Boolean faxDetect; - private String tosVideo; - private Boolean srtpTag32; - private Boolean referBlindProgress; - private int maxAudioStreams; - private Boolean bundle; - private Boolean useAvpf; - private String callGroup; - private Boolean sendConnectedLine; - private int faxDetectTimeout; - private String sdpOwner; - private Boolean forceRport; - private String calleridTag; - private int rtpTimeoutHold; - private Boolean usePtime; - private String mediaAddress; - private String voicemailExtension; - private int rtpTimeout; - private String setVar; - private String contactAcl; - private Boolean preferredCodecOnly; - private Boolean forceAvp; - private String recordOffFeature; - private String fromUser; - private Boolean sendDiversion; - private Boolean t38UdptlIpv6; - private String toneZone; - private String language; - private Boolean allowSubscribe; - private Boolean rtpIpv6; - private String callerid; - private Boolean mohPassthrough; - private String cosVideo; - private String dtlsAutoGenerateCert; - private Boolean asymmetricRtpCodec; - private Boolean iceSupport; - private Boolean aggregateMwi; - private Boolean oneTouchRecording; - private String mwiFromUser; - private String accountcode; - private String allow; - private Boolean rewriteContact; - private Boolean userEqPhone; - private String rtpEngine; - private String subscribeContext; - private Boolean notifyEarlyInuseRinging; - private String incomingMwiMailbox; - private String auth; - private String directMediaGlareMitigation; - private Boolean trustIdInbound; - private Boolean bindRtpToMediaAddress; - private Boolean disableDirectMediaOnNat; - private Boolean mediaEncryption; - private Boolean mediaUseReceivedTransport; - private Boolean allowOverlap; - private String dtmfMode; - private String outboundAuth; - private String tosAudio; - private String dtlsCertFile; - private String dtlsCaPath; - private String dtlsSetup; - private String connectedLineMethod; - private Boolean g726NonStandard; - private String _100rel; - private String timers; - private Boolean directMedia; - private String acl; - private int timersMinSe; - private Boolean trustIdOutbound; - private int subMinExpiry; - private Boolean rtcpMux; - private int maxVideoStreams; - private Boolean acceptMultipleSdpAnswers; - private Boolean trustConnectedLine; - private Boolean sendPai; - private int rtpKeepalive; - private String t38UdptlEc; - private Boolean t38UdptlNat; - private Boolean allowTransfer; - private String dtlsCaFile; - private String outboundProxy; - private Boolean inbandProgress; - private String deviceState; - private String activeChannels; - private Boolean ignore183withoutsdp; - - public int getMaxVideoStreams() { - return maxVideoStreams; - } - - public void setMaxVideoStreams(int maxVideoStreams) { - this.maxVideoStreams = maxVideoStreams; - } - - public String getObjectName() { - return objectName; - } - - public void setObjectName(String objectName) { - this.objectName = objectName; - } - - public String getObjectType() { - return objectType; - } - - public void setObjectType(String objectType) { - this.objectType = objectType; - } - - public Boolean isRpidImmediate() { - return rpidImmediate; - } - - public void setRpidImmediate(Boolean rpidImmediate) { - this.rpidImmediate = rpidImmediate; - } - - public Boolean isWebrtc() { - return webrtc; - } - - public void setWebrtc(Boolean webrtc) { - this.webrtc = webrtc; - } - - public Boolean isIgnorel83WithoutSdp() { - return ignorel83WithoutSdp; - } - - public void setIgnorel83WithoutSdp(Boolean ignorel83WithoutSdp) { - this.ignorel83WithoutSdp = ignorel83WithoutSdp; - } - - public int getDeviceStateBusyAt() { - return deviceStateBusyAt; - } - - public void setDeviceStateBusyAt(int deviceStateBusyAt) { - this.deviceStateBusyAt = deviceStateBusyAt; - } - - public int getT38UdptlMaxdatagram() { - return t38UdptlMaxdatagram; - } - - public void setT38UdptlMaxdatagram(int t38UdptlMaxdatagram) { - this.t38UdptlMaxdatagram = t38UdptlMaxdatagram; - } - - public int getDtlsRekey() { - return dtlsRekey; - } - - public void setDtlsRekey(int dtlsRekey) { - this.dtlsRekey = dtlsRekey; - } - - public String getNamedPickupGroup() { - return namedPickupGroup; - } - - public void setNamedPickupGroup(String namedPickupGroup) { - this.namedPickupGroup = namedPickupGroup; - } - - public String getDirectMediaMethod() { - return directMediaMethod; - } - - public void setDirectMediaMethod(String directMediaMethod) { - this.directMediaMethod = directMediaMethod; - } - - public Boolean isSendRpid() { - return sendRpid; - } - - public void setSendRpid(Boolean sendRpid) { - this.sendRpid = sendRpid; - } - - public String getPickupGroup() { - return pickupGroup; - } - - public void setPickupGroup(String pickupGroup) { - this.pickupGroup = pickupGroup; - } - - public String getSdpSession() { - return sdpSession; - } - - public void setSdpSession(String sdpSession) { - this.sdpSession = sdpSession; - } - - public String getDtlsVerify() { - return dtlsVerify; - } - - public void setDtlsVerify(String dtlsVerify) { - this.dtlsVerify = dtlsVerify; - } - - public String getMessageContext() { - return messageContext; - } - - public void setMessageContext(String messageContext) { - this.messageContext = messageContext; - } - - public String getMailboxes() { - return mailboxes; - } - - public void setMailboxes(String mailboxes) { - this.mailboxes = mailboxes; - } - - public String getRecordOnFeature() { - return recordOnFeature; - } - - public void setRecordOnFeature(String recordOnFeature) { - this.recordOnFeature = recordOnFeature; - } - - public String getDtlsPrivateKey() { - return dtlsPrivateKey; - } - - public void setDtlsPrivateKey(String dtlsPrivateKey) { - this.dtlsPrivateKey = dtlsPrivateKey; - } - - public String getDtlsFingerprint() { - return dtlsFingerprint; - } - - public void setDtlsFingerprint(String dtlsFingerprint) { - this.dtlsFingerprint = dtlsFingerprint; - } - - public String getFromDomain() { - return fromDomain; - } - - public void setFromDomain(String fromDomain) { - this.fromDomain = fromDomain; - } - - public int getTimersSessExpires() { - return timersSessExpires; - } - - public void setTimersSessExpires(int timersSessExpires) { - this.timersSessExpires = timersSessExpires; - } - - public String getNamedCallGroup() { - return namedCallGroup; - } - - public void setNamedCallGroup(String namedCallGroup) { - this.namedCallGroup = namedCallGroup; - } - - public String getDtlsCipher() { - return dtlsCipher; - } - - public void setDtlsCipher(String dtlsCipher) { - this.dtlsCipher = dtlsCipher; - } - - public Boolean isMediaEncryptionOptimistic() { - return mediaEncryptionOptimistic; - } - - public void setMediaEncryptionOptimistic(Boolean mediaEncryptionOptimistic) { - this.mediaEncryptionOptimistic = mediaEncryptionOptimistic; - } - - public Boolean isSuppressQ850ReasonHeaders() { - return suppressQ850ReasonHeaders; - } - - public void setSuppressQ850ReasonHeaders(Boolean suppressQ850ReasonHeaders) { - this.suppressQ850ReasonHeaders = suppressQ850ReasonHeaders; - } - - public String getAors() { - return aors; - } - - public void setAors(String aors) { - this.aors = aors; - } - - public String getIdentifyBy() { - return identifyBy; - } - - public void setIdentifyBy(String identifyBy) { - this.identifyBy = identifyBy; - } - - public String getCalleridPrivacy() { - return calleridPrivacy; - } - - public void setCalleridPrivacy(String calleridPrivacy) { - this.calleridPrivacy = calleridPrivacy; - } - - public String getMwiSubscribeReplacesUnsolicited() { - return mwiSubscribeReplacesUnsolicited; - } - - public void setMwiSubscribeReplacesUnsolicited(String mwiSubscribeReplacesUnsolicited) { - this.mwiSubscribeReplacesUnsolicited = mwiSubscribeReplacesUnsolicited; - } - - public Boolean isFollowEarlyMediaFork() { - return followEarlyMediaFork; - } - - public void setFollowEarlyMediaFork(Boolean followEarlyMediaFork) { - this.followEarlyMediaFork = followEarlyMediaFork; - } - - public String getContext() { - return context; - } - - public void setContext(String context) { - this.context = context; - } - - public Boolean isRtpSymmetric() { - return rtpSymmetric; - } - - public void setRtpSymmetric(Boolean rtpSymmetric) { - this.rtpSymmetric = rtpSymmetric; - } - - public String getTransport() { - return transport; - } - - public void setTransport(String transport) { - this.transport = transport; - } - - public String getMohSuggest() { - return mohSuggest; - } - - public void setMohSuggest(String mohSuggest) { - this.mohSuggest = mohSuggest; - } - - public Boolean isT38Udptl() { - return t38Udptl; - } - - public void setT38Udptl(Boolean t38Udptl) { - this.t38Udptl = t38Udptl; - } - - public Boolean isFaxDetect() { - return faxDetect; - } - - public void setFaxDetect(Boolean faxDetect) { - this.faxDetect = faxDetect; - } - - public Boolean getSrtpTag32() { - return srtpTag32; - } - - public void setSrtpTag32(Boolean srtpTag32) { - this.srtpTag32 = srtpTag32; - } - - public Boolean isReferBlindProgress() { - return referBlindProgress; - } - - public void setReferBlindProgress(Boolean referBlindProgress) { - this.referBlindProgress = referBlindProgress; - } - - public int getMaxAudioStreams() { - return maxAudioStreams; - } - - public void setMaxAudioStreams(int maxAudioStreams) { - this.maxAudioStreams = maxAudioStreams; - } - - public Boolean isBundle() { - return bundle; - } - - public void setBundle(Boolean bundle) { - this.bundle = bundle; - } - - - public Boolean isUseAvpf() { - return useAvpf; - } - - public void setUseAvpf(Boolean useAvpf) { - this.useAvpf = useAvpf; - } - - - public String getCallGroup() { - return callGroup; - } - - public void setCallGroup(String callGroup) { - this.callGroup = callGroup; - } - - public Boolean isSendConnectedLine() { - return sendConnectedLine; - } - - public void setSendConnectedLine(Boolean sendConnectedLine) { - this.sendConnectedLine = sendConnectedLine; - } - - - public int getFaxDetectTimeout() { - return faxDetectTimeout; - } - - public void setFaxDetectTimeout(int faxDetectTimeout) { - this.faxDetectTimeout = faxDetectTimeout; - } - - public String getSdpOwner() { - return sdpOwner; - } - - public void setSdpOwner(String sdpOwner) { - this.sdpOwner = sdpOwner; - } - - public Boolean isForceRport() { - return forceRport; - } - - public void setForceRport(Boolean forceRport) { - this.forceRport = forceRport; - } - - - public String getCalleridTag() { - return calleridTag; - } - - public void setCalleridTag(String calleridTag) { - this.calleridTag = calleridTag; - } - - public int getRtpTimeoutHold() { - return rtpTimeoutHold; - } - - public void setRtpTimeoutHold(int rtpTimeoutHold) { - this.rtpTimeoutHold = rtpTimeoutHold; - } - - public Boolean isUsePtime() { - return usePtime; - } - - public void setUsePtime(Boolean usePtime) { - this.usePtime = usePtime; - } - - - public String getMediaAddress() { - return mediaAddress; - } - - public void setMediaAddress(String mediaAddress) { - this.mediaAddress = mediaAddress; - } - - public String getVoicemailExtension() { - return voicemailExtension; - } - - public void setVoicemailExtension(String voicemailExtension) { - this.voicemailExtension = voicemailExtension; - } - - public int getRtpTimeout() { - return rtpTimeout; - } - - public void setRtpTimeout(int rtpTimeout) { - this.rtpTimeout = rtpTimeout; - } - - public String getSetVar() { - return setVar; - } - - public void setSetVar(String setVar) { - this.setVar = setVar; - } - - public String getContactAcl() { - return contactAcl; - } - - public void setContactAcl(String contactAcl) { - this.contactAcl = contactAcl; - } - - public Boolean isPreferredCodecOnly() { - return preferredCodecOnly; - } - - public void setPreferredCodecOnly(Boolean preferredCodecOnly) { - this.preferredCodecOnly = preferredCodecOnly; - } - - public Boolean isForceAvp() { - return forceAvp; - } - - public void setForceAvp(Boolean forceAvp) { - this.forceAvp = forceAvp; - } - - - public String getRecordOffFeature() { - return recordOffFeature; - } - - public void setRecordOffFeature(String recordOffFeature) { - this.recordOffFeature = recordOffFeature; - } - - public String getFromUser() { - return fromUser; - } - - public void setFromUser(String fromUser) { - this.fromUser = fromUser; - } - - public Boolean isSendDiversion() { - return sendDiversion; - } - - public void setSendDiversion(Boolean sendDiversion) { - this.sendDiversion = sendDiversion; - } - - - public Boolean isT38UdptlIpv6() { - return t38UdptlIpv6; - } - - public void setT38UdptlIpv6(Boolean t38UdptlIpv6) { - this.t38UdptlIpv6 = t38UdptlIpv6; - } - - - public String getToneZone() { - return toneZone; - } - - public void setToneZone(String toneZone) { - this.toneZone = toneZone; - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - public Boolean isAllowSubscribe() { - return allowSubscribe; - } - - public void setAllowSubscribe(Boolean allowSubscribe) { - this.allowSubscribe = allowSubscribe; - } - - public Boolean isRtpIpv6() { - return rtpIpv6; - } - - public void setRtpIpv6(Boolean rtpIpv6) { - this.rtpIpv6 = rtpIpv6; - } - - - public String getCallerid() { - return callerid; - } - - public void setCallerid(String callerid) { - this.callerid = callerid; - } - - public Boolean isMohPassthrough() { - return mohPassthrough; - } - - public void setMohPassthrough(Boolean mohPassthrough) { - this.mohPassthrough = mohPassthrough; - } - - public String getCosAudio() { - return cosAudio; - } - - public void setCosAudio(String cosAudio) { - this.cosAudio = cosAudio; - } - - public String getCosVideo() { - return cosVideo; - } - - public void setCosVideo(String cosVideo) { - this.cosVideo = cosVideo; - } - - public String getDtlsAutoGenerateCert() { - return dtlsAutoGenerateCert; - } - - public void setDtlsAutoGenerateCert(String dtlsAutoGenerateCert) { - this.dtlsAutoGenerateCert = dtlsAutoGenerateCert; - } - - public Boolean isAsymmetricRtpCodec() { - return asymmetricRtpCodec; - } - - public void setAsymmetricRtpCodec(Boolean asymmetricRtpCodec) { - this.asymmetricRtpCodec = asymmetricRtpCodec; - } - - - public Boolean isIceSupport() { - return iceSupport; - } - - public void setIceSupport(Boolean iceSupport) { - this.iceSupport = iceSupport; - } - - - public Boolean isAggregateMwi() { - return aggregateMwi; - } - - public void setAggregateMwi(Boolean aggregateMwi) { - this.aggregateMwi = aggregateMwi; - } - - - public Boolean isOneTouchRecording() { - return oneTouchRecording; - } - - public void setOneTouchRecording(Boolean oneTouchRecording) { - this.oneTouchRecording = oneTouchRecording; - } - - - public String getMwiFromUser() { - return mwiFromUser; - } - - public void setMwiFromUser(String mwiFromUser) { - this.mwiFromUser = mwiFromUser; - } - - public String getAccountcode() { - return accountcode; - } - - public void setAccountcode(String accountcode) { - this.accountcode = accountcode; - } - - public String getAllow() { - return allow; - } - - public void setAllow(String allow) { - this.allow = allow; - } - - public Boolean isRewriteContact() { - return rewriteContact; - } - - public void setRewriteContact(Boolean rewriteContact) { - this.rewriteContact = rewriteContact; - } - - public Boolean isUserEqPhone() { - return userEqPhone; - } - - public void setUserEqPhone(Boolean userEqPhone) { - this.userEqPhone = userEqPhone; - } - - public String getRtpEngine() { - return rtpEngine; - } - - public void setRtpEngine(String rtpEngine) { - this.rtpEngine = rtpEngine; - } - - public String getSubscribeContext() { - return subscribeContext; - } - - public void setSubscribeContext(String subscribeContext) { - this.subscribeContext = subscribeContext; - } - - public Boolean isNotifyEarlyInuseRinging() { - return notifyEarlyInuseRinging; - } - - public void setNotifyEarlyInuseRinging(Boolean notifyEarlyInuseRinging) { - this.notifyEarlyInuseRinging = notifyEarlyInuseRinging; - } - - public String getIncomingMwiMailbox() { - return incomingMwiMailbox; - } - - public void setIncomingMwiMailbox(String incomingMwiMailbox) { - this.incomingMwiMailbox = incomingMwiMailbox; - } - - public String getAuth() { - return auth; - } - - public void setAuth(String auth) { - this.auth = auth; - } - - public String getDirectMediaGlareMitigation() { - return directMediaGlareMitigation; - } - - public void setDirectMediaGlareMitigation(String directMediaGlareMitigation) { - this.directMediaGlareMitigation = directMediaGlareMitigation; - } - - public Boolean isTrustIdInbound() { - return trustIdInbound; - } - - public void setTrustIdInbound(Boolean trustIdInbound) { - this.trustIdInbound = trustIdInbound; - } - - public Boolean isBindRtpToMediaAddress() { - return bindRtpToMediaAddress; - } - - public void setBindRtpToMediaAddress(Boolean bindRtpToMediaAddress) { - this.bindRtpToMediaAddress = bindRtpToMediaAddress; - } - - public Boolean isDisableDirectMediaOnNat() { - return disableDirectMediaOnNat; - } - - public void setDisableDirectMediaOnNat(Boolean disableDirectMediaOnNat) { - this.disableDirectMediaOnNat = disableDirectMediaOnNat; - } - - public Boolean isMediaEncryption() { - return mediaEncryption; - } - - public void setMediaEncryption(Boolean mediaEncryption) { - this.mediaEncryption = mediaEncryption; - } - - public Boolean isMediaUseReceivedTransport() { - return mediaUseReceivedTransport; - } - - public void setMediaUseReceivedTransport(Boolean mediaUseReceivedTransport) { - this.mediaUseReceivedTransport = mediaUseReceivedTransport; - } - - public Boolean isAllowOverlap() { - return allowOverlap; - } - - public void setAllowOverlap(Boolean allowOverlap) { - this.allowOverlap = allowOverlap; - } - - public String getDtmfMode() { - return dtmfMode; - } - - public void setDtmfMode(String dtmfMode) { - this.dtmfMode = dtmfMode; - } - - public String getOutboundAuth() { - return outboundAuth; - } - - public void setOutboundAuth(String outboundAuth) { - this.outboundAuth = outboundAuth; - } - - public String getTosVideo() { - return tosVideo; - } - - public void setTosVideo(String tosVideo) { - this.tosVideo = tosVideo; - } - - public String getTosAudio() { - return tosAudio; - } - - public void setTosAudio(String tosAudio) { - this.tosAudio = tosAudio; - } - - public String getDtlsCertFile() { - return dtlsCertFile; - } - - public void setDtlsCertFile(String dtlsCertFile) { - this.dtlsCertFile = dtlsCertFile; - } - - public String getDtlsCaPath() { - return dtlsCaPath; - } - - public void setDtlsCaPath(String dtlsCaPath) { - this.dtlsCaPath = dtlsCaPath; - } - - public String getDtlsSetup() { - return dtlsSetup; - } - - public void setDtlsSetup(String dtlsSetup) { - this.dtlsSetup = dtlsSetup; - } - - public String getConnectedLineMethod() { - return connectedLineMethod; - } - - public void setConnectedLineMethod(String connectedLineMethod) { - this.connectedLineMethod = connectedLineMethod; - } - - public Boolean isG726NonStandard() { - return g726NonStandard; - } - - public void setG726NonStandard(Boolean g726NonStandard) { - this.g726NonStandard = g726NonStandard; - } - - public String get100rel() { - return _100rel; - } - - public void set100rel(String _100rel) { - this._100rel = _100rel; - } - - public String getTimers() { - return timers; - } - - public void setTimers(String timers) { - this.timers = timers; - } - - public Boolean isDirectMedia() { - return directMedia; - } - - public void setDirectMedia(Boolean directMedia) { - this.directMedia = directMedia; - } - - public String getAcl() { - return acl; - } - - public void setAcl(String acl) { - this.acl = acl; - } - - public int getTimersMinSe() { - return timersMinSe; - } - - public void setTimersMinSe(int timersMinSe) { - this.timersMinSe = timersMinSe; - } - - public Boolean isTrustIdOutbound() { - return trustIdOutbound; - } - - public void setTrustIdOutbound(Boolean trustIdOutbound) { - this.trustIdOutbound = trustIdOutbound; - } - - public int getSubMinExpiry() { - return subMinExpiry; - } - - public void setSubMinExpiry(int subMinExpiry) { - this.subMinExpiry = subMinExpiry; - } - - public Boolean isRtcpMux() { - return rtcpMux; - } - - public void setRtcpMux(Boolean rtcpMux) { - this.rtcpMux = rtcpMux; - } - - public Boolean isAcceptMultipleSdpAnswers() { - return acceptMultipleSdpAnswers; - } - - public void setAcceptMultipleSdpAnswers(Boolean acceptMultipleSdpAnswers) { - this.acceptMultipleSdpAnswers = acceptMultipleSdpAnswers; - } - - public Boolean isTrustConnectedLine() { - return trustConnectedLine; - } - - public void setTrustConnectedLine(Boolean trustConnectedLine) { - this.trustConnectedLine = trustConnectedLine; - } - - public Boolean isSendPai() { - return sendPai; - } - - public void setSendPai(Boolean sendPai) { - this.sendPai = sendPai; - } - - public int getRtpKeepalive() { - return rtpKeepalive; - } - - public void setRtpKeepalive(int rtpKeepalive) { - this.rtpKeepalive = rtpKeepalive; - } - - public String getT38UdptlEc() { - return t38UdptlEc; - } - - public void setT38UdptlEc(String t38UdptlEc) { - this.t38UdptlEc = t38UdptlEc; - } - - public Boolean isT38UdptlNat() { - return t38UdptlNat; - } - - public void setT38UdptlNat(Boolean t38UdptlNat) { - this.t38UdptlNat = t38UdptlNat; - } - - public Boolean isAllowTransfer() { - return allowTransfer; - } - - public void setAllowTransfer(Boolean allowTransfer) { - this.allowTransfer = allowTransfer; - } - - public String getDtlsCaFile() { - return dtlsCaFile; - } - - public void setDtlsCaFile(String dtlsCaFile) { - this.dtlsCaFile = dtlsCaFile; - } - - public String getOutboundProxy() { - return outboundProxy; - } - - public void setOutboundProxy(String outboundProxy) { - this.outboundProxy = outboundProxy; - } - - public Boolean isInbandProgress() { - return inbandProgress; - } - - public void setInbandProgress(Boolean inbandProgress) { - this.inbandProgress = inbandProgress; - } - - public String getDeviceState() { - return deviceState; - } - - public void setDeviceState(String deviceState) { - this.deviceState = deviceState; - } - - public String getActiveChannels() { - return activeChannels; - } - - public void setActiveChannels(String activeChannels) { - this.activeChannels = activeChannels; - } - - public EndpointDetail(Object source) { - super(source); - } - - public Boolean getIgnore183withoutsdp() { - return ignore183withoutsdp; - } - public void setIgnore183withoutsdp(Boolean ignore183withoutsdp) { - this.ignore183withoutsdp = ignore183withoutsdp; - } + public Integer getListItems() + { + return listItems; + } + + public void setListItems(Integer listItems) + { + this.listItems = listItems; + } + + public String getEventList() + { + return eventList; + } + + public void setEventList(String eventList) + { + this.eventList = eventList; + } + + private String objectName; + private String objectType; + private Boolean rpidImmediate; + private Boolean webrtc; + private Boolean ignorel83WithoutSdp; + private int deviceStateBusyAt; + private int t38UdptlMaxdatagram; + private int dtlsRekey; + private String namedPickupGroup; + private String directMediaMethod; + private Boolean sendRpid; + private String pickupGroup; + private String sdpSession; + private String dtlsVerify; + private String messageContext; + private String mailboxes; + private String recordOnFeature; + private String dtlsPrivateKey; + private String dtlsFingerprint; + private String fromDomain; + private int timersSessExpires; + private String namedCallGroup; + private String dtlsCipher; + private Boolean mediaEncryptionOptimistic; + private Boolean suppressQ850ReasonHeaders; + private String aors; + private String identifyBy; + private String calleridPrivacy; + private String mwiSubscribeReplacesUnsolicited; + private String cosAudio; + private Boolean followEarlyMediaFork; + private String context; + private Boolean rtpSymmetric; + private String transport; + private String mohSuggest; + private Boolean t38Udptl; + private Boolean faxDetect; + private String tosVideo; + private Boolean srtpTag32; + private Boolean referBlindProgress; + private int maxAudioStreams; + private Boolean bundle; + private Boolean useAvpf; + private String callGroup; + private Boolean sendConnectedLine; + private int faxDetectTimeout; + private String sdpOwner; + private Boolean forceRport; + private String calleridTag; + private int rtpTimeoutHold; + private Boolean usePtime; + private String mediaAddress; + private String voicemailExtension; + private int rtpTimeout; + private String setVar; + private String contactAcl; + private Boolean preferredCodecOnly; + private Boolean forceAvp; + private String recordOffFeature; + private String fromUser; + private Boolean sendDiversion; + private Boolean t38UdptlIpv6; + private String toneZone; + private String language; + private Boolean allowSubscribe; + private Boolean rtpIpv6; + private String callerid; + private Boolean mohPassthrough; + private String cosVideo; + private String dtlsAutoGenerateCert; + private Boolean asymmetricRtpCodec; + private Boolean iceSupport; + private Boolean aggregateMwi; + private Boolean oneTouchRecording; + private String mwiFromUser; + private String accountcode; + private String allow; + private Boolean rewriteContact; + private Boolean userEqPhone; + private String rtpEngine; + private String subscribeContext; + private Boolean notifyEarlyInuseRinging; + private String incomingMwiMailbox; + private String auth; + private String directMediaGlareMitigation; + private Boolean trustIdInbound; + private Boolean bindRtpToMediaAddress; + private Boolean disableDirectMediaOnNat; + private Boolean mediaEncryption; + private Boolean mediaUseReceivedTransport; + private Boolean allowOverlap; + private String dtmfMode; + private String outboundAuth; + private String tosAudio; + private String dtlsCertFile; + private String dtlsCaPath; + private String dtlsSetup; + private String connectedLineMethod; + private Boolean g726NonStandard; + private String _100rel; + private String timers; + private Boolean directMedia; + private String acl; + private int timersMinSe; + private Boolean trustIdOutbound; + private int subMinExpiry; + private Boolean rtcpMux; + private int maxVideoStreams; + private Boolean acceptMultipleSdpAnswers; + private Boolean trustConnectedLine; + private Boolean sendPai; + private int rtpKeepalive; + private String t38UdptlEc; + private Boolean t38UdptlNat; + private Boolean allowTransfer; + private String dtlsCaFile; + private String outboundProxy; + private Boolean inbandProgress; + private String deviceState; + private String activeChannels; + private Boolean ignore183withoutsdp; + + public int getMaxVideoStreams() + { + return maxVideoStreams; + } + + public void setMaxVideoStreams(int maxVideoStreams) + { + this.maxVideoStreams = maxVideoStreams; + } + + public String getObjectName() + { + return objectName; + } + + public void setObjectName(String objectName) + { + this.objectName = objectName; + } + + public String getObjectType() + { + return objectType; + } + + public void setObjectType(String objectType) + { + this.objectType = objectType; + } + + public Boolean isRpidImmediate() + { + return rpidImmediate; + } + + public void setRpidImmediate(Boolean rpidImmediate) + { + this.rpidImmediate = rpidImmediate; + } + + public Boolean isWebrtc() + { + return webrtc; + } + + public void setWebrtc(Boolean webrtc) + { + this.webrtc = webrtc; + } + + public Boolean isIgnorel83WithoutSdp() + { + return ignorel83WithoutSdp; + } + + public void setIgnorel83WithoutSdp(Boolean ignorel83WithoutSdp) + { + this.ignorel83WithoutSdp = ignorel83WithoutSdp; + } + + public int getDeviceStateBusyAt() + { + return deviceStateBusyAt; + } + + public void setDeviceStateBusyAt(int deviceStateBusyAt) + { + this.deviceStateBusyAt = deviceStateBusyAt; + } + + public int getT38UdptlMaxdatagram() + { + return t38UdptlMaxdatagram; + } + + public void setT38UdptlMaxdatagram(int t38UdptlMaxdatagram) + { + this.t38UdptlMaxdatagram = t38UdptlMaxdatagram; + } + + public int getDtlsRekey() + { + return dtlsRekey; + } + + public void setDtlsRekey(int dtlsRekey) + { + this.dtlsRekey = dtlsRekey; + } + + public String getNamedPickupGroup() + { + return namedPickupGroup; + } + + public void setNamedPickupGroup(String namedPickupGroup) + { + this.namedPickupGroup = namedPickupGroup; + } + + public String getDirectMediaMethod() + { + return directMediaMethod; + } + + public void setDirectMediaMethod(String directMediaMethod) + { + this.directMediaMethod = directMediaMethod; + } + + public Boolean isSendRpid() + { + return sendRpid; + } + + public void setSendRpid(Boolean sendRpid) + { + this.sendRpid = sendRpid; + } + + public String getPickupGroup() + { + return pickupGroup; + } + + public void setPickupGroup(String pickupGroup) + { + this.pickupGroup = pickupGroup; + } + + public String getSdpSession() + { + return sdpSession; + } + + public void setSdpSession(String sdpSession) + { + this.sdpSession = sdpSession; + } + + public String getDtlsVerify() + { + return dtlsVerify; + } + + public void setDtlsVerify(String dtlsVerify) + { + this.dtlsVerify = dtlsVerify; + } + + public String getMessageContext() + { + return messageContext; + } + + public void setMessageContext(String messageContext) + { + this.messageContext = messageContext; + } + + public String getMailboxes() + { + return mailboxes; + } + + public void setMailboxes(String mailboxes) + { + this.mailboxes = mailboxes; + } + + public String getRecordOnFeature() + { + return recordOnFeature; + } + + public void setRecordOnFeature(String recordOnFeature) + { + this.recordOnFeature = recordOnFeature; + } + + public String getDtlsPrivateKey() + { + return dtlsPrivateKey; + } + + public void setDtlsPrivateKey(String dtlsPrivateKey) + { + this.dtlsPrivateKey = dtlsPrivateKey; + } + + public String getDtlsFingerprint() + { + return dtlsFingerprint; + } + + public void setDtlsFingerprint(String dtlsFingerprint) + { + this.dtlsFingerprint = dtlsFingerprint; + } + + public String getFromDomain() + { + return fromDomain; + } + + public void setFromDomain(String fromDomain) + { + this.fromDomain = fromDomain; + } + + public int getTimersSessExpires() + { + return timersSessExpires; + } + + public void setTimersSessExpires(int timersSessExpires) + { + this.timersSessExpires = timersSessExpires; + } + + public String getNamedCallGroup() + { + return namedCallGroup; + } + + public void setNamedCallGroup(String namedCallGroup) + { + this.namedCallGroup = namedCallGroup; + } + + public String getDtlsCipher() + { + return dtlsCipher; + } + + public void setDtlsCipher(String dtlsCipher) + { + this.dtlsCipher = dtlsCipher; + } + + public Boolean isMediaEncryptionOptimistic() + { + return mediaEncryptionOptimistic; + } + + public void setMediaEncryptionOptimistic(Boolean mediaEncryptionOptimistic) + { + this.mediaEncryptionOptimistic = mediaEncryptionOptimistic; + } + + public Boolean isSuppressQ850ReasonHeaders() + { + return suppressQ850ReasonHeaders; + } + + public void setSuppressQ850ReasonHeaders(Boolean suppressQ850ReasonHeaders) + { + this.suppressQ850ReasonHeaders = suppressQ850ReasonHeaders; + } + + public String getAors() + { + return aors; + } + + public void setAors(String aors) + { + this.aors = aors; + } + + public String getIdentifyBy() + { + return identifyBy; + } + + public void setIdentifyBy(String identifyBy) + { + this.identifyBy = identifyBy; + } + + public String getCalleridPrivacy() + { + return calleridPrivacy; + } + + public void setCalleridPrivacy(String calleridPrivacy) + { + this.calleridPrivacy = calleridPrivacy; + } + + public String getMwiSubscribeReplacesUnsolicited() + { + return mwiSubscribeReplacesUnsolicited; + } + + public void setMwiSubscribeReplacesUnsolicited(String mwiSubscribeReplacesUnsolicited) + { + this.mwiSubscribeReplacesUnsolicited = mwiSubscribeReplacesUnsolicited; + } + + public Boolean isFollowEarlyMediaFork() + { + return followEarlyMediaFork; + } + + public void setFollowEarlyMediaFork(Boolean followEarlyMediaFork) + { + this.followEarlyMediaFork = followEarlyMediaFork; + } + + public String getContext() + { + return context; + } + + public void setContext(String context) + { + this.context = context; + } + + public Boolean isRtpSymmetric() + { + return rtpSymmetric; + } + + public void setRtpSymmetric(Boolean rtpSymmetric) + { + this.rtpSymmetric = rtpSymmetric; + } + + public String getTransport() + { + return transport; + } + + public void setTransport(String transport) + { + this.transport = transport; + } + + public String getMohSuggest() + { + return mohSuggest; + } + + public void setMohSuggest(String mohSuggest) + { + this.mohSuggest = mohSuggest; + } + + public Boolean isT38Udptl() + { + return t38Udptl; + } + + public void setT38Udptl(Boolean t38Udptl) + { + this.t38Udptl = t38Udptl; + } + + public Boolean isFaxDetect() + { + return faxDetect; + } + + public void setFaxDetect(Boolean faxDetect) + { + this.faxDetect = faxDetect; + } + + public Boolean getSrtpTag32() + { + return srtpTag32; + } + + public void setSrtpTag32(Boolean srtpTag32) + { + this.srtpTag32 = srtpTag32; + } + + public Boolean isReferBlindProgress() + { + return referBlindProgress; + } + + public void setReferBlindProgress(Boolean referBlindProgress) + { + this.referBlindProgress = referBlindProgress; + } + + public int getMaxAudioStreams() + { + return maxAudioStreams; + } + + public void setMaxAudioStreams(int maxAudioStreams) + { + this.maxAudioStreams = maxAudioStreams; + } + + public Boolean isBundle() + { + return bundle; + } + + public void setBundle(Boolean bundle) + { + this.bundle = bundle; + } + + public Boolean isUseAvpf() + { + return useAvpf; + } + + public void setUseAvpf(Boolean useAvpf) + { + this.useAvpf = useAvpf; + } + + public String getCallGroup() + { + return callGroup; + } + + public void setCallGroup(String callGroup) + { + this.callGroup = callGroup; + } + + public Boolean isSendConnectedLine() + { + return sendConnectedLine; + } + + public void setSendConnectedLine(Boolean sendConnectedLine) + { + this.sendConnectedLine = sendConnectedLine; + } + + public int getFaxDetectTimeout() + { + return faxDetectTimeout; + } + + public void setFaxDetectTimeout(int faxDetectTimeout) + { + this.faxDetectTimeout = faxDetectTimeout; + } + + public String getSdpOwner() + { + return sdpOwner; + } + + public void setSdpOwner(String sdpOwner) + { + this.sdpOwner = sdpOwner; + } + + public Boolean isForceRport() + { + return forceRport; + } + + public void setForceRport(Boolean forceRport) + { + this.forceRport = forceRport; + } + + public String getCalleridTag() + { + return calleridTag; + } + + public void setCalleridTag(String calleridTag) + { + this.calleridTag = calleridTag; + } + + public int getRtpTimeoutHold() + { + return rtpTimeoutHold; + } + + public void setRtpTimeoutHold(int rtpTimeoutHold) + { + this.rtpTimeoutHold = rtpTimeoutHold; + } + + public Boolean isUsePtime() + { + return usePtime; + } + + public void setUsePtime(Boolean usePtime) + { + this.usePtime = usePtime; + } + + public String getMediaAddress() + { + return mediaAddress; + } + + public void setMediaAddress(String mediaAddress) + { + this.mediaAddress = mediaAddress; + } + + public String getVoicemailExtension() + { + return voicemailExtension; + } + + public void setVoicemailExtension(String voicemailExtension) + { + this.voicemailExtension = voicemailExtension; + } + + public int getRtpTimeout() + { + return rtpTimeout; + } + + public void setRtpTimeout(int rtpTimeout) + { + this.rtpTimeout = rtpTimeout; + } + + public String getSetVar() + { + return setVar; + } + + public void setSetVar(String setVar) + { + this.setVar = setVar; + } + + public String getContactAcl() + { + return contactAcl; + } + + public void setContactAcl(String contactAcl) + { + this.contactAcl = contactAcl; + } + + public Boolean isPreferredCodecOnly() + { + return preferredCodecOnly; + } + + public void setPreferredCodecOnly(Boolean preferredCodecOnly) + { + this.preferredCodecOnly = preferredCodecOnly; + } + + public Boolean isForceAvp() + { + return forceAvp; + } + + public void setForceAvp(Boolean forceAvp) + { + this.forceAvp = forceAvp; + } + + public String getRecordOffFeature() + { + return recordOffFeature; + } + + public void setRecordOffFeature(String recordOffFeature) + { + this.recordOffFeature = recordOffFeature; + } + + public String getFromUser() + { + return fromUser; + } + + public void setFromUser(String fromUser) + { + this.fromUser = fromUser; + } + + public Boolean isSendDiversion() + { + return sendDiversion; + } + + public void setSendDiversion(Boolean sendDiversion) + { + this.sendDiversion = sendDiversion; + } + + public Boolean isT38UdptlIpv6() + { + return t38UdptlIpv6; + } + + public void setT38UdptlIpv6(Boolean t38UdptlIpv6) + { + this.t38UdptlIpv6 = t38UdptlIpv6; + } + + public String getToneZone() + { + return toneZone; + } + + public void setToneZone(String toneZone) + { + this.toneZone = toneZone; + } + + public String getLanguage() + { + return language; + } + + public void setLanguage(String language) + { + this.language = language; + } + + public Boolean isAllowSubscribe() + { + return allowSubscribe; + } + + public void setAllowSubscribe(Boolean allowSubscribe) + { + this.allowSubscribe = allowSubscribe; + } + + public Boolean isRtpIpv6() + { + return rtpIpv6; + } + + public void setRtpIpv6(Boolean rtpIpv6) + { + this.rtpIpv6 = rtpIpv6; + } + + public String getCallerid() + { + return callerid; + } + + public void setCallerid(String callerid) + { + this.callerid = callerid; + } + + public Boolean isMohPassthrough() + { + return mohPassthrough; + } + + public void setMohPassthrough(Boolean mohPassthrough) + { + this.mohPassthrough = mohPassthrough; + } + + public String getCosAudio() + { + return cosAudio; + } + + public void setCosAudio(String cosAudio) + { + this.cosAudio = cosAudio; + } + + public String getCosVideo() + { + return cosVideo; + } + + public void setCosVideo(String cosVideo) + { + this.cosVideo = cosVideo; + } + + public String getDtlsAutoGenerateCert() + { + return dtlsAutoGenerateCert; + } + + public void setDtlsAutoGenerateCert(String dtlsAutoGenerateCert) + { + this.dtlsAutoGenerateCert = dtlsAutoGenerateCert; + } + + public Boolean isAsymmetricRtpCodec() + { + return asymmetricRtpCodec; + } + + public void setAsymmetricRtpCodec(Boolean asymmetricRtpCodec) + { + this.asymmetricRtpCodec = asymmetricRtpCodec; + } + + public Boolean isIceSupport() + { + return iceSupport; + } + + public void setIceSupport(Boolean iceSupport) + { + this.iceSupport = iceSupport; + } + + public Boolean isAggregateMwi() + { + return aggregateMwi; + } + + public void setAggregateMwi(Boolean aggregateMwi) + { + this.aggregateMwi = aggregateMwi; + } + + public Boolean isOneTouchRecording() + { + return oneTouchRecording; + } + + public void setOneTouchRecording(Boolean oneTouchRecording) + { + this.oneTouchRecording = oneTouchRecording; + } + + public String getMwiFromUser() + { + return mwiFromUser; + } + + public void setMwiFromUser(String mwiFromUser) + { + this.mwiFromUser = mwiFromUser; + } + + public String getAccountcode() + { + return accountcode; + } + + public void setAccountcode(String accountcode) + { + this.accountcode = accountcode; + } + + public String getAllow() + { + return allow; + } + + public void setAllow(String allow) + { + this.allow = allow; + } + + public Boolean isRewriteContact() + { + return rewriteContact; + } + + public void setRewriteContact(Boolean rewriteContact) + { + this.rewriteContact = rewriteContact; + } + + public Boolean isUserEqPhone() + { + return userEqPhone; + } + + public void setUserEqPhone(Boolean userEqPhone) + { + this.userEqPhone = userEqPhone; + } + + public String getRtpEngine() + { + return rtpEngine; + } + + public void setRtpEngine(String rtpEngine) + { + this.rtpEngine = rtpEngine; + } + + public String getSubscribeContext() + { + return subscribeContext; + } + + public void setSubscribeContext(String subscribeContext) + { + this.subscribeContext = subscribeContext; + } + + public Boolean isNotifyEarlyInuseRinging() + { + return notifyEarlyInuseRinging; + } + + public void setNotifyEarlyInuseRinging(Boolean notifyEarlyInuseRinging) + { + this.notifyEarlyInuseRinging = notifyEarlyInuseRinging; + } + + public String getIncomingMwiMailbox() + { + return incomingMwiMailbox; + } + + public void setIncomingMwiMailbox(String incomingMwiMailbox) + { + this.incomingMwiMailbox = incomingMwiMailbox; + } + + public String getAuth() + { + return auth; + } + + public void setAuth(String auth) + { + this.auth = auth; + } + + public String getDirectMediaGlareMitigation() + { + return directMediaGlareMitigation; + } + + public void setDirectMediaGlareMitigation(String directMediaGlareMitigation) + { + this.directMediaGlareMitigation = directMediaGlareMitigation; + } + + public Boolean isTrustIdInbound() + { + return trustIdInbound; + } + + public void setTrustIdInbound(Boolean trustIdInbound) + { + this.trustIdInbound = trustIdInbound; + } + + public Boolean isBindRtpToMediaAddress() + { + return bindRtpToMediaAddress; + } + + public void setBindRtpToMediaAddress(Boolean bindRtpToMediaAddress) + { + this.bindRtpToMediaAddress = bindRtpToMediaAddress; + } + + public Boolean isDisableDirectMediaOnNat() + { + return disableDirectMediaOnNat; + } + + public void setDisableDirectMediaOnNat(Boolean disableDirectMediaOnNat) + { + this.disableDirectMediaOnNat = disableDirectMediaOnNat; + } + + public Boolean isMediaEncryption() + { + return mediaEncryption; + } + + public void setMediaEncryption(Boolean mediaEncryption) + { + this.mediaEncryption = mediaEncryption; + } + + public Boolean isMediaUseReceivedTransport() + { + return mediaUseReceivedTransport; + } + + public void setMediaUseReceivedTransport(Boolean mediaUseReceivedTransport) + { + this.mediaUseReceivedTransport = mediaUseReceivedTransport; + } + + public Boolean isAllowOverlap() + { + return allowOverlap; + } + + public void setAllowOverlap(Boolean allowOverlap) + { + this.allowOverlap = allowOverlap; + } + + public String getDtmfMode() + { + return dtmfMode; + } + + public void setDtmfMode(String dtmfMode) + { + this.dtmfMode = dtmfMode; + } + + public String getOutboundAuth() + { + return outboundAuth; + } + + public void setOutboundAuth(String outboundAuth) + { + this.outboundAuth = outboundAuth; + } + + public String getTosVideo() + { + return tosVideo; + } + + public void setTosVideo(String tosVideo) + { + this.tosVideo = tosVideo; + } + + public String getTosAudio() + { + return tosAudio; + } + + public void setTosAudio(String tosAudio) + { + this.tosAudio = tosAudio; + } + + public String getDtlsCertFile() + { + return dtlsCertFile; + } + + public void setDtlsCertFile(String dtlsCertFile) + { + this.dtlsCertFile = dtlsCertFile; + } + + public String getDtlsCaPath() + { + return dtlsCaPath; + } + + public void setDtlsCaPath(String dtlsCaPath) + { + this.dtlsCaPath = dtlsCaPath; + } + + public String getDtlsSetup() + { + return dtlsSetup; + } + + public void setDtlsSetup(String dtlsSetup) + { + this.dtlsSetup = dtlsSetup; + } + + public String getConnectedLineMethod() + { + return connectedLineMethod; + } + + public void setConnectedLineMethod(String connectedLineMethod) + { + this.connectedLineMethod = connectedLineMethod; + } + + public Boolean isG726NonStandard() + { + return g726NonStandard; + } + + public void setG726NonStandard(Boolean g726NonStandard) + { + this.g726NonStandard = g726NonStandard; + } + + public String get100rel() + { + return _100rel; + } + + public void set100rel(String _100rel) + { + this._100rel = _100rel; + } + + public String getTimers() + { + return timers; + } + + public void setTimers(String timers) + { + this.timers = timers; + } + + public Boolean isDirectMedia() + { + return directMedia; + } + + public void setDirectMedia(Boolean directMedia) + { + this.directMedia = directMedia; + } + + public String getAcl() + { + return acl; + } + + public void setAcl(String acl) + { + this.acl = acl; + } + + public int getTimersMinSe() + { + return timersMinSe; + } + + public void setTimersMinSe(int timersMinSe) + { + this.timersMinSe = timersMinSe; + } + + public Boolean isTrustIdOutbound() + { + return trustIdOutbound; + } + + public void setTrustIdOutbound(Boolean trustIdOutbound) + { + this.trustIdOutbound = trustIdOutbound; + } + + public int getSubMinExpiry() + { + return subMinExpiry; + } + + public void setSubMinExpiry(int subMinExpiry) + { + this.subMinExpiry = subMinExpiry; + } + + public Boolean isRtcpMux() + { + return rtcpMux; + } + + public void setRtcpMux(Boolean rtcpMux) + { + this.rtcpMux = rtcpMux; + } + + public Boolean isAcceptMultipleSdpAnswers() + { + return acceptMultipleSdpAnswers; + } + + public void setAcceptMultipleSdpAnswers(Boolean acceptMultipleSdpAnswers) + { + this.acceptMultipleSdpAnswers = acceptMultipleSdpAnswers; + } + + public Boolean isTrustConnectedLine() + { + return trustConnectedLine; + } + + public void setTrustConnectedLine(Boolean trustConnectedLine) + { + this.trustConnectedLine = trustConnectedLine; + } + + public Boolean isSendPai() + { + return sendPai; + } + + public void setSendPai(Boolean sendPai) + { + this.sendPai = sendPai; + } + + public int getRtpKeepalive() + { + return rtpKeepalive; + } + + public void setRtpKeepalive(int rtpKeepalive) + { + this.rtpKeepalive = rtpKeepalive; + } + + public String getT38UdptlEc() + { + return t38UdptlEc; + } + + public void setT38UdptlEc(String t38UdptlEc) + { + this.t38UdptlEc = t38UdptlEc; + } + + public Boolean isT38UdptlNat() + { + return t38UdptlNat; + } + + public void setT38UdptlNat(Boolean t38UdptlNat) + { + this.t38UdptlNat = t38UdptlNat; + } + + public Boolean isAllowTransfer() + { + return allowTransfer; + } + + public void setAllowTransfer(Boolean allowTransfer) + { + this.allowTransfer = allowTransfer; + } + + public String getDtlsCaFile() + { + return dtlsCaFile; + } + + public void setDtlsCaFile(String dtlsCaFile) + { + this.dtlsCaFile = dtlsCaFile; + } + + public String getOutboundProxy() + { + return outboundProxy; + } + + public void setOutboundProxy(String outboundProxy) + { + this.outboundProxy = outboundProxy; + } + + public Boolean isInbandProgress() + { + return inbandProgress; + } + + public void setInbandProgress(Boolean inbandProgress) + { + this.inbandProgress = inbandProgress; + } + + public String getDeviceState() + { + return deviceState; + } + + public void setDeviceState(String deviceState) + { + this.deviceState = deviceState; + } + + public String getActiveChannels() + { + return activeChannels; + } + + public void setActiveChannels(String activeChannels) + { + this.activeChannels = activeChannels; + } + + public EndpointDetail(Object source) + { + super(source); + } + + public Boolean getIgnore183withoutsdp() + { + return ignore183withoutsdp; + } + + public void setIgnore183withoutsdp(Boolean ignore183withoutsdp) + { + this.ignore183withoutsdp = ignore183withoutsdp; + } } diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java index b104e2344..9964e057a 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java @@ -16,12 +16,12 @@ */ package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; -import org.asteriskjava.manager.event.BridgeEnterEvent; - import java.util.Comparator; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.asteriskjava.manager.event.BridgeEnterEvent; + public class BridgeEnterEventComparator implements Comparator { private static final Pattern UNIQUE_ID_PATTERN = Pattern.compile("([0-9]+)\\.([0-9]+)$"); diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java index c035eb46c..ff08dd374 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java @@ -3,6 +3,7 @@ import java.util.Date; import java.util.Locale; import java.util.Map; + import org.asteriskjava.manager.response.ManagerError; public class ManagerResponse From d04f2e95032c9d94d592fc28f2c95ee84ac4b0dc Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 11 Feb 2021 15:24:32 +1100 Subject: [PATCH 420/802] fix Locker and Lockable --- .../java/org/asteriskjava/util/Lockable.java | 32 ++++++++-- .../java/org/asteriskjava/util/Locker.java | 62 +++++++++++-------- 2 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/Lockable.java b/src/main/java/org/asteriskjava/util/Lockable.java index a8d25cb1f..a2ca5a078 100644 --- a/src/main/java/org/asteriskjava/util/Lockable.java +++ b/src/main/java/org/asteriskjava/util/Lockable.java @@ -18,6 +18,7 @@ public class Lockable private final AtomicInteger waited = new AtomicInteger(); private final AtomicInteger acquired = new AtomicInteger(); private volatile boolean dumped = false; + private volatile boolean blocked = false; private final static AtomicLong seed = new AtomicLong(); private final long lockableId = seed.incrementAndGet(); @@ -46,7 +47,7 @@ String getCaller() public String asString() { - return "Lockable [totalWaitTime=" + totalWaitTime + ", totalHoldTime=" + totalHoldTime + ", waited=" + waited + return "Lockable [waited=" + waited + ", waitTime=" + totalWaitTime + ", totalHoldTime=" + totalHoldTime + ", acquired=" + acquired + ", object=" + lockName + ", id=" + lockableId + "]"; } @@ -91,9 +92,9 @@ void addWaited(int time) waited.addAndGet(time); } - void addAcquired() + void addAcquired(int count) { - acquired.incrementAndGet(); + acquired.addAndGet(count); } boolean isDumped() @@ -106,9 +107,9 @@ void setDumped(boolean dumped) this.dumped = dumped; } - public long getTotalWaitTime() + public int getTotalWaitTime() { - return totalWaitTime.longValue(); + return totalWaitTime.intValue(); } public int getWaited() @@ -125,4 +126,25 @@ public Long getLockableId() { return lockableId; } + + public int getHoldTime() + { + return totalHoldTime.intValue(); + } + + public int getAcquired() + { + return acquired.intValue(); + } + + public boolean wasBlocked() + { + return blocked; + } + + public void setBlocked(boolean blocked) + { + this.blocked = blocked; + } + } diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index 84dd75a5d..8dc834a11 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -99,13 +99,14 @@ private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedExc int ctr = 0; ReentrantLock lock = lockable.getInternalLock(); - while (!lock.tryLock(250, TimeUnit.MILLISECONDS)) + while (!lock.tryLock(100, TimeUnit.MILLISECONDS)) { ctr++; dumpBlocker(lockable, ctr); + lockable.setBlocked(true); } lockable.setDumped(false); - lockable.addAcquired(); + lockable.addAcquired(1); long acquiredAt = System.currentTimeMillis(); lockable.threadHoldingLock.set(Thread.currentThread()); @@ -165,40 +166,35 @@ public void close() private static void dumpBlocker(Lockable lockable, int ctr) { - synchronized (lockable) + if (!lockable.isDumped()) { - if (!lockable.isDumped()) + Thread thread = lockable.threadHoldingLock.get(); + lockable.setDumped(true); + if (thread != null) { + StackTraceElement[] trace = new Exception().getStackTrace(); - Thread thread = lockable.threadHoldingLock.get(); - lockable.setDumped(true); - if (thread != null) - { - - StackTraceElement[] trace = new Exception().getStackTrace(); + String dump = ""; - String dump = ""; - - int i = 0; - for (; i < trace.length; i++) - { - StackTraceElement ste = trace[i]; - dump += "\tat " + ste.toString(); - dump += '\n'; - } - logger.error("Waiting on lock... blocked by..."); - logger.error(dump); - } - else + int i = 0; + for (; i < trace.length; i++) { - logger.error("Thread hasn't been set"); + StackTraceElement ste = trace[i]; + dump += "\tat " + ste.toString(); + dump += '\n'; } - + logger.error("Waiting on lock... blocked by..."); + logger.error(dump); } else { - logger.warn("Still waiting " + ctr); + logger.error("Thread hasn't been set"); } + + } + else + { + logger.warn("Still waiting " + ctr); } } @@ -257,14 +253,26 @@ static void dumpStats() boolean activity = false; for (Lockable lockable : lockables) { - if ((lockable.getWaited() > 0 && lockable.getTotalWaitTime() > lockable.getAverageHoldTime()) || first) + if (lockable.wasBlocked() || first) { + int waited = lockable.getWaited(); + int waitTime = lockable.getTotalWaitTime(); + int acquired = lockable.getAcquired(); + int holdTime = lockable.getHoldTime(); + lockable.setBlocked(false); activity = true; logger.warn(lockable.asString()); + lockable.addWaited(-waited); + lockable.addTotalWaitTime(-waitTime); + + lockable.addAcquired(-acquired); + lockable.addTotalHoldTime(-holdTime); + } } if (first || activity) + { logger.warn("Dump Lock Stats finished. Will dump every minute when there is contention..."); first = false; From de1c967efba5bc19324405e88cdc2f9280a21338 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 11 Feb 2021 15:33:23 +1100 Subject: [PATCH 421/802] make lockable method names unambiguous --- .../java/org/asteriskjava/util/Lockable.java | 38 +++++++-------- .../java/org/asteriskjava/util/Locker.java | 48 +++++++++---------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/Lockable.java b/src/main/java/org/asteriskjava/util/Lockable.java index a2ca5a078..7ecaa1abe 100644 --- a/src/main/java/org/asteriskjava/util/Lockable.java +++ b/src/main/java/org/asteriskjava/util/Lockable.java @@ -25,10 +25,10 @@ public class Lockable public Lockable() { - this.lockName = getCaller(); + this.lockName = getLockCaller(); } - String getCaller() + private String getLockCaller() { StackTraceElement[] trace = new Exception().getStackTrace(); String name = this.getClass().getCanonicalName(); @@ -45,13 +45,13 @@ String getCaller() return name; } - public String asString() + String asLockString() { return "Lockable [waited=" + waited + ", waitTime=" + totalWaitTime + ", totalHoldTime=" + totalHoldTime + ", acquired=" + acquired + ", object=" + lockName + ", id=" + lockableId + "]"; } - long getAverageHoldTime() + long getLockAverageHoldTime() { long hold = totalHoldTime.get(); long count = acquired.get(); @@ -72,77 +72,77 @@ ReentrantLock getInternalLock() return internalLock; } - void addTotalWaitTime(int time) + void addLockTotalWaitTime(int time) { totalWaitTime.addAndGet(time); } - void addTotalHoldTime(int time) + void addLockTotalHoldTime(int time) { totalHoldTime.addAndGet(time); } - int addRequested() + int addLockRequested() { return requested.incrementAndGet(); } - void addWaited(int time) + void addLockWaited(int time) { waited.addAndGet(time); } - void addAcquired(int count) + void addLockAcquired(int count) { acquired.addAndGet(count); } - boolean isDumped() + boolean isLockDumped() { return dumped; } - void setDumped(boolean dumped) + void setLockDumped(boolean dumped) { this.dumped = dumped; } - public int getTotalWaitTime() + int getLockTotalWaitTime() { return totalWaitTime.intValue(); } - public int getWaited() + int getLockWaited() { return waited.intValue(); } - public int getRequested() + int getLockRequested() { return requested.intValue(); } - public Long getLockableId() + Long getLockableId() { return lockableId; } - public int getHoldTime() + int getLockTotalHoldTime() { return totalHoldTime.intValue(); } - public int getAcquired() + int getLockAcquired() { return acquired.intValue(); } - public boolean wasBlocked() + boolean wasLockBlocked() { return blocked; } - public void setBlocked(boolean blocked) + void setLockBlocked(boolean blocked) { this.blocked = blocked; } diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/util/Locker.java index 8dc834a11..804c3fc14 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/util/Locker.java @@ -94,7 +94,7 @@ public void close() private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedException { - int offset = lockable.addRequested(); + int offset = lockable.addLockRequested(); long waitStart = System.currentTimeMillis(); int ctr = 0; @@ -103,10 +103,10 @@ private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedExc { ctr++; dumpBlocker(lockable, ctr); - lockable.setBlocked(true); + lockable.setLockBlocked(true); } - lockable.setDumped(false); - lockable.addAcquired(1); + lockable.setLockDumped(false); + lockable.addLockAcquired(1); long acquiredAt = System.currentTimeMillis(); lockable.threadHoldingLock.set(Thread.currentThread()); @@ -119,20 +119,20 @@ public void close() { // ignore any wait that may have been caused by Locker code, so // count the waiters before we release the lock - long waiters = lockable.getRequested() - offset; - lockable.addWaited((int) waiters); + long waiters = lockable.getLockRequested() - offset; + lockable.addLockWaited((int) waiters); - boolean dumped = lockable.isDumped(); + boolean dumped = lockable.isLockDumped(); // release the lock lock.unlock(); // count the time waiting and holding the lock int holdTime = (int) (System.currentTimeMillis() - acquiredAt); int waitTime = (int) (acquiredAt - waitStart); - lockable.addTotalWaitTime(waitTime); - lockable.addTotalHoldTime(holdTime); + lockable.addLockTotalWaitTime(waitTime); + lockable.addLockTotalHoldTime(holdTime); - long averageHoldTime = lockable.getAverageHoldTime(); + long averageHoldTime = lockable.getLockAverageHoldTime(); if (waiters > 0 && holdTime > averageHoldTime * 2 || dumped) { // some threads waited @@ -149,7 +149,7 @@ public void close() if (holdTime > averageHoldTime * 5.0) { // long hold! - String message = "Lock hold of lock (" + holdTime + "MS), average is " + lockable.getAverageHoldTime() + String message = "Lock hold of lock (" + holdTime + "MS), average is " + lockable.getLockAverageHoldTime() + " " + getCaller(lockable); logger.warn(message); @@ -166,10 +166,10 @@ public void close() private static void dumpBlocker(Lockable lockable, int ctr) { - if (!lockable.isDumped()) + if (!lockable.isLockDumped()) { Thread thread = lockable.threadHoldingLock.get(); - lockable.setDumped(true); + lockable.setLockDumped(true); if (thread != null) { StackTraceElement[] trace = new Exception().getStackTrace(); @@ -253,20 +253,20 @@ static void dumpStats() boolean activity = false; for (Lockable lockable : lockables) { - if (lockable.wasBlocked() || first) + if (lockable.wasLockBlocked() || first) { - int waited = lockable.getWaited(); - int waitTime = lockable.getTotalWaitTime(); - int acquired = lockable.getAcquired(); - int holdTime = lockable.getHoldTime(); - lockable.setBlocked(false); + int waited = lockable.getLockWaited(); + int waitTime = lockable.getLockTotalWaitTime(); + int acquired = lockable.getLockAcquired(); + int holdTime = lockable.getLockTotalHoldTime(); + lockable.setLockBlocked(false); activity = true; - logger.warn(lockable.asString()); - lockable.addWaited(-waited); - lockable.addTotalWaitTime(-waitTime); + logger.warn(lockable.asLockString()); + lockable.addLockWaited(-waited); + lockable.addLockTotalWaitTime(-waitTime); - lockable.addAcquired(-acquired); - lockable.addTotalHoldTime(-holdTime); + lockable.addLockAcquired(-acquired); + lockable.addLockTotalHoldTime(-holdTime); } } From c3afd87784e5df937d286cb26bf9de49414b6e18 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 12 Feb 2021 11:37:55 +1100 Subject: [PATCH 422/802] move locks to it's own package --- .../java/org/asteriskjava/config/ConfigFileImpl.java | 4 ++-- .../asteriskjava/fastagi/AbstractMappingStrategy.java | 2 +- .../java/org/asteriskjava/fastagi/AsyncAgiServer.java | 4 ++-- .../fastagi/ResourceBundleMappingStrategy.java | 2 +- .../asteriskjava/live/internal/AbstractLiveObject.java | 2 +- .../org/asteriskjava/live/internal/AgentManager.java | 4 ++-- .../asteriskjava/live/internal/AsteriskAgentImpl.java | 2 +- .../live/internal/AsteriskChannelImpl.java | 6 +++--- .../live/internal/AsteriskQueueEntryImpl.java | 2 +- .../asteriskjava/live/internal/AsteriskQueueImpl.java | 6 +++--- .../live/internal/AsteriskQueueMemberImpl.java | 2 +- .../asteriskjava/live/internal/AsteriskServerImpl.java | 10 +++++----- .../org/asteriskjava/live/internal/ChannelManager.java | 4 ++-- .../org/asteriskjava/live/internal/MeetMeManager.java | 4 ++-- .../org/asteriskjava/live/internal/MeetMeRoomImpl.java | 4 ++-- .../org/asteriskjava/live/internal/MeetMeUserImpl.java | 2 +- .../org/asteriskjava/live/internal/QueueManager.java | 4 ++-- .../java/org/asteriskjava/{util => lock}/Lockable.java | 4 ++-- .../org/asteriskjava/{util => lock}/LockableList.java | 2 +- .../org/asteriskjava/{util => lock}/LockableMap.java | 2 +- .../org/asteriskjava/{util => lock}/LockableSet.java | 2 +- .../java/org/asteriskjava/{util => lock}/Locker.java | 5 ++++- src/main/java/org/asteriskjava/manager/PingThread.java | 4 ++-- .../manager/internal/ManagerConnectionImpl.java | 8 ++++---- .../manager/internal/ManagerWriterImpl.java | 4 ++-- .../manager/internal/ResponseEventsImpl.java | 4 ++-- .../backwardsCompatibility/bridge/BridgeState.java | 4 ++-- .../pbx/internal/activity/ActivityHelper.java | 2 +- .../internal/activity/BlindTransferActivityImpl.java | 2 +- .../pbx/internal/activity/ParkActivityImpl.java | 2 +- .../pbx/internal/activity/SplitActivityImpl.java | 2 +- .../asteriskjava/pbx/internal/asterisk/MeetmeRoom.java | 4 ++-- .../pbx/internal/asterisk/MeetmeRoomControl.java | 2 +- .../asteriskjava/pbx/internal/core/AsteriskPBX.java | 2 +- .../asteriskjava/pbx/internal/core/CallTracker.java | 4 ++-- .../pbx/internal/core/CoherentManagerEventQueue.java | 4 ++-- .../pbx/internal/core/ListenerManager.java | 2 +- .../pbx/internal/core/LiveChannelManager.java | 6 +++--- .../java/org/asteriskjava/pbx/internal/core/Peer.java | 4 ++-- .../asteriskjava/pbx/internal/core/PeerMonitor.java | 4 ++-- .../internal/managerAPI/EventListenerBaseClass.java | 2 +- .../pbx/internal/managerAPI/OriginateBaseClass.java | 2 +- src/test/java/org/asteriskjava/util/LockerTest.java | 4 +++- 43 files changed, 78 insertions(+), 73 deletions(-) rename src/main/java/org/asteriskjava/{util => lock}/Lockable.java (97%) rename src/main/java/org/asteriskjava/{util => lock}/LockableList.java (99%) rename src/main/java/org/asteriskjava/{util => lock}/LockableMap.java (98%) rename src/main/java/org/asteriskjava/{util => lock}/LockableSet.java (98%) rename src/main/java/org/asteriskjava/{util => lock}/Locker.java (98%) diff --git a/src/main/java/org/asteriskjava/config/ConfigFileImpl.java b/src/main/java/org/asteriskjava/config/ConfigFileImpl.java index dc79a3cb0..4bd7f4de4 100644 --- a/src/main/java/org/asteriskjava/config/ConfigFileImpl.java +++ b/src/main/java/org/asteriskjava/config/ConfigFileImpl.java @@ -21,8 +21,8 @@ import java.util.Map; import java.util.TreeMap; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.Locker.LockCloser; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; /** * An Asterisk configuration file read from the filesystem. diff --git a/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java b/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java index 8055c696a..90b1b0f5f 100644 --- a/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java +++ b/src/main/java/org/asteriskjava/fastagi/AbstractMappingStrategy.java @@ -24,7 +24,7 @@ import java.util.ArrayList; import java.util.List; -import org.asteriskjava.util.Lockable; +import org.asteriskjava.lock.Lockable; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java b/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java index f5baa1d9c..9e2cb3d87 100644 --- a/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/AsyncAgiServer.java @@ -5,13 +5,13 @@ import org.asteriskjava.fastagi.internal.AsyncAgiConnectionHandler; import org.asteriskjava.fastagi.internal.DefaultAgiChannelFactory; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.ManagerConnection; import org.asteriskjava.manager.ManagerEventListener; import org.asteriskjava.manager.event.AsyncAgiEvent; import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.event.RenameEvent; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java b/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java index ea76dca6d..5061f00cc 100644 --- a/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java +++ b/src/main/java/org/asteriskjava/fastagi/ResourceBundleMappingStrategy.java @@ -23,7 +23,7 @@ import java.util.MissingResourceException; import java.util.ResourceBundle; -import org.asteriskjava.util.Locker.LockCloser; +import org.asteriskjava.lock.Locker.LockCloser; /** * A MappingStrategy that is configured via a resource bundle. diff --git a/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java b/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java index de2f2ecc5..23e479ae6 100644 --- a/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java +++ b/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java @@ -21,7 +21,7 @@ import org.asteriskjava.live.AsteriskServer; import org.asteriskjava.live.LiveObject; -import org.asteriskjava.util.Lockable; +import org.asteriskjava.lock.Lockable; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/live/internal/AgentManager.java b/src/main/java/org/asteriskjava/live/internal/AgentManager.java index 8cd1744e2..383929ee0 100644 --- a/src/main/java/org/asteriskjava/live/internal/AgentManager.java +++ b/src/main/java/org/asteriskjava/live/internal/AgentManager.java @@ -23,6 +23,8 @@ import org.asteriskjava.live.AgentState; import org.asteriskjava.live.AsteriskAgent; import org.asteriskjava.live.ManagerCommunicationException; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.action.AgentsAction; import org.asteriskjava.manager.event.AgentCallbackLoginEvent; @@ -34,8 +36,6 @@ import org.asteriskjava.manager.event.AgentLogoffEvent; import org.asteriskjava.manager.event.AgentsEvent; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java index 7906e3e1c..b4c207bcf 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java @@ -18,7 +18,7 @@ import org.asteriskjava.live.AgentState; import org.asteriskjava.live.AsteriskAgent; -import org.asteriskjava.util.Locker.LockCloser; +import org.asteriskjava.lock.Locker.LockCloser; /** * Default implementation of the AsteriskAgent interface. diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java index a63664edc..c3ce12250 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java @@ -36,6 +36,9 @@ import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.NoSuchChannelException; import org.asteriskjava.live.RecordingException; +import org.asteriskjava.lock.LockableList; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.AbsoluteTimeoutAction; import org.asteriskjava.manager.action.ChangeMonitorAction; import org.asteriskjava.manager.action.GetVarAction; @@ -50,9 +53,6 @@ import org.asteriskjava.manager.action.UnpauseMonitorAction; import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; -import org.asteriskjava.util.LockableList; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.MixMonitorDirection; /** diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java index 3e46c8393..f9c7b8875 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java @@ -4,7 +4,7 @@ import org.asteriskjava.live.AsteriskQueueEntry; import org.asteriskjava.live.QueueEntryState; -import org.asteriskjava.util.Locker.LockCloser; +import org.asteriskjava.lock.Locker.LockCloser; /** * Default implementation of the AsteriskQueueEntry interface. diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java index b6fb29419..4e7774b99 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java @@ -28,10 +28,10 @@ import org.asteriskjava.live.AsteriskQueueEntry; import org.asteriskjava.live.AsteriskQueueListener; import org.asteriskjava.live.AsteriskQueueMember; +import org.asteriskjava.lock.LockableList; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.util.AstUtil; -import org.asteriskjava.util.LockableList; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java index d760cb652..0169f7d5c 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java @@ -22,12 +22,12 @@ import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.NoSuchInterfaceException; import org.asteriskjava.live.QueueMemberState; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.QueuePauseAction; import org.asteriskjava.manager.action.QueuePenaltyAction; import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.AstUtil; -import org.asteriskjava.util.Locker.LockCloser; /** * Default implementation of a queue member. diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java index 12c9f962e..da5ad4610 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java @@ -46,6 +46,11 @@ import org.asteriskjava.live.NoSuchChannelException; import org.asteriskjava.live.OriginateCallback; import org.asteriskjava.live.Voicemailbox; +import org.asteriskjava.lock.Lockable; +import org.asteriskjava.lock.LockableList; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.LockableSet; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.ManagerConnection; import org.asteriskjava.manager.ManagerConnectionState; import org.asteriskjava.manager.ManagerEventListener; @@ -114,11 +119,6 @@ import org.asteriskjava.manager.response.ModuleCheckResponse; import org.asteriskjava.util.AstUtil; import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.Lockable; -import org.asteriskjava.util.LockableList; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.LockableSet; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java index 38978d63d..d1f8c121c 100644 --- a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java +++ b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java @@ -35,6 +35,8 @@ import org.asteriskjava.live.HangupCause; import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.NoSuchChannelException; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.action.StatusAction; import org.asteriskjava.manager.event.AbstractChannelEvent; @@ -59,8 +61,6 @@ import org.asteriskjava.manager.event.VarSetEvent; import org.asteriskjava.util.DaemonThreadFactory; import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java b/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java index 959268774..8d05e2f12 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java @@ -25,6 +25,8 @@ import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.MeetMeRoom; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.CommandAction; import org.asteriskjava.manager.event.AbstractMeetMeEvent; import org.asteriskjava.manager.event.MeetMeLeaveEvent; @@ -34,8 +36,6 @@ import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java b/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java index 9bd50ca7a..27b46c4b6 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java @@ -23,9 +23,9 @@ import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.MeetMeRoom; import org.asteriskjava.live.MeetMeUser; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.CommandAction; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.Locker.LockCloser; /** * Default implementation of the MeetMeRoom interface. diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java b/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java index 3c9d28bd9..7382b7bce 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java @@ -21,8 +21,8 @@ import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.MeetMeUser; import org.asteriskjava.live.MeetMeUserState; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.CommandAction; -import org.asteriskjava.util.Locker.LockCloser; class MeetMeUserImpl extends AbstractLiveObject implements MeetMeUser { diff --git a/src/main/java/org/asteriskjava/live/internal/QueueManager.java b/src/main/java/org/asteriskjava/live/internal/QueueManager.java index 471c08c14..c4b0ac879 100644 --- a/src/main/java/org/asteriskjava/live/internal/QueueManager.java +++ b/src/main/java/org/asteriskjava/live/internal/QueueManager.java @@ -27,6 +27,8 @@ import org.asteriskjava.live.AsteriskQueue; import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.QueueMemberState; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.EventTimeoutException; import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.action.QueueStatusAction; @@ -43,8 +45,6 @@ import org.asteriskjava.manager.event.QueueMemberRemovedEvent; import org.asteriskjava.manager.event.QueueMemberStatusEvent; import org.asteriskjava.manager.event.QueueParamsEvent; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/util/Lockable.java b/src/main/java/org/asteriskjava/lock/Lockable.java similarity index 97% rename from src/main/java/org/asteriskjava/util/Lockable.java rename to src/main/java/org/asteriskjava/lock/Lockable.java index 7ecaa1abe..05f200d1e 100644 --- a/src/main/java/org/asteriskjava/util/Lockable.java +++ b/src/main/java/org/asteriskjava/lock/Lockable.java @@ -1,11 +1,11 @@ -package org.asteriskjava.util; +package org.asteriskjava.lock; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; -import org.asteriskjava.util.Locker.LockCloser; +import org.asteriskjava.lock.Locker.LockCloser; public class Lockable { diff --git a/src/main/java/org/asteriskjava/util/LockableList.java b/src/main/java/org/asteriskjava/lock/LockableList.java similarity index 99% rename from src/main/java/org/asteriskjava/util/LockableList.java rename to src/main/java/org/asteriskjava/lock/LockableList.java index ab8dc252d..e9b9d6829 100644 --- a/src/main/java/org/asteriskjava/util/LockableList.java +++ b/src/main/java/org/asteriskjava/lock/LockableList.java @@ -1,4 +1,4 @@ -package org.asteriskjava.util; +package org.asteriskjava.lock; import java.util.Collection; import java.util.Comparator; diff --git a/src/main/java/org/asteriskjava/util/LockableMap.java b/src/main/java/org/asteriskjava/lock/LockableMap.java similarity index 98% rename from src/main/java/org/asteriskjava/util/LockableMap.java rename to src/main/java/org/asteriskjava/lock/LockableMap.java index b7316b040..ac506bc9c 100644 --- a/src/main/java/org/asteriskjava/util/LockableMap.java +++ b/src/main/java/org/asteriskjava/lock/LockableMap.java @@ -1,4 +1,4 @@ -package org.asteriskjava.util; +package org.asteriskjava.lock; import java.util.Collection; import java.util.Map; diff --git a/src/main/java/org/asteriskjava/util/LockableSet.java b/src/main/java/org/asteriskjava/lock/LockableSet.java similarity index 98% rename from src/main/java/org/asteriskjava/util/LockableSet.java rename to src/main/java/org/asteriskjava/lock/LockableSet.java index 92a1c4421..25d52b5cb 100644 --- a/src/main/java/org/asteriskjava/util/LockableSet.java +++ b/src/main/java/org/asteriskjava/lock/LockableSet.java @@ -1,4 +1,4 @@ -package org.asteriskjava.util; +package org.asteriskjava.lock; import java.util.Collection; import java.util.Iterator; diff --git a/src/main/java/org/asteriskjava/util/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java similarity index 98% rename from src/main/java/org/asteriskjava/util/Locker.java rename to src/main/java/org/asteriskjava/lock/Locker.java index 804c3fc14..750286192 100644 --- a/src/main/java/org/asteriskjava/util/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -1,4 +1,4 @@ -package org.asteriskjava.util; +package org.asteriskjava.lock; import java.util.HashMap; import java.util.LinkedList; @@ -10,6 +10,9 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + public class Locker { diff --git a/src/main/java/org/asteriskjava/manager/PingThread.java b/src/main/java/org/asteriskjava/manager/PingThread.java index d6ced68ad..3ff4f1b86 100644 --- a/src/main/java/org/asteriskjava/manager/PingThread.java +++ b/src/main/java/org/asteriskjava/manager/PingThread.java @@ -19,10 +19,10 @@ import java.util.HashSet; import java.util.concurrent.atomic.AtomicLong; +import org.asteriskjava.lock.LockableSet; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.PingAction; import org.asteriskjava.manager.response.ManagerResponse; -import org.asteriskjava.util.LockableSet; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 8396088c6..9aee8caaf 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -39,6 +39,10 @@ import java.util.concurrent.atomic.AtomicLong; import org.asteriskjava.AsteriskVersion; +import org.asteriskjava.lock.Lockable; +import org.asteriskjava.lock.LockableList; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.AuthenticationFailedException; import org.asteriskjava.manager.EventTimeoutException; import org.asteriskjava.manager.ExpectedResponse; @@ -71,10 +75,6 @@ import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.pbx.util.LogTime; import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.Lockable; -import org.asteriskjava.util.LockableList; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; import org.asteriskjava.util.SocketConnectionFacade; diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java index a6732a2b9..6ee8220ff 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java @@ -19,9 +19,9 @@ import java.io.IOException; import org.asteriskjava.AsteriskVersion; +import org.asteriskjava.lock.Lockable; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.ManagerAction; -import org.asteriskjava.util.Lockable; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.SocketConnectionFacade; /** diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java index 26afce8ef..7375aa0ff 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java @@ -21,11 +21,11 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.asteriskjava.lock.LockableList; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.manager.response.ManagerResponse; -import org.asteriskjava.util.LockableList; -import org.asteriskjava.util.Locker.LockCloser; /** * Implementation of the ResponseEvents interface. diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 143eb54fd..e87e9a94a 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -7,12 +7,12 @@ import java.util.LinkedList; import java.util.List; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.event.BridgeEnterEvent; import org.asteriskjava.manager.event.BridgeEvent; import org.asteriskjava.manager.event.BridgeLeaveEvent; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.util.LockableMap; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java index a9c86019a..1554c0a40 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java @@ -3,6 +3,7 @@ import java.util.HashSet; import java.util.Set; +import org.asteriskjava.lock.Lockable; import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.ActivityStatusEnum; @@ -15,7 +16,6 @@ import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; -import org.asteriskjava.util.Lockable; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index 7689c8f77..9b087704d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -5,6 +5,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.Call.OperandChannel; @@ -26,7 +27,6 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java index acd5d1d15..928fe6080 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java @@ -5,6 +5,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.AsteriskSettings; @@ -22,7 +23,6 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ParkedCallEvent; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index 5c845668a..448fc610b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -7,6 +7,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.pbx.ActivityCallback; import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Call; @@ -24,7 +25,6 @@ import org.asteriskjava.pbx.asterisk.wrap.events.RenameEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelProxy; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java index d4adb3e89..854051268 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java @@ -3,9 +3,9 @@ import java.util.Date; import java.util.LinkedList; +import org.asteriskjava.lock.Lockable; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.pbx.Channel; -import org.asteriskjava.util.Lockable; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index 85117ddf6..248539aa1 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -9,6 +9,7 @@ import org.asteriskjava.AsteriskVersion; import org.asteriskjava.live.ManagerCommunicationException; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ListenerPriority; @@ -28,7 +29,6 @@ import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.CoherentManagerEventListener; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 1f7b5e660..13dff5023 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -7,6 +7,7 @@ import java.util.concurrent.TimeUnit; import org.asteriskjava.AsteriskVersion; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.AuthenticationFailedException; import org.asteriskjava.manager.EventTimeoutException; import org.asteriskjava.manager.ManagerConnectionState; @@ -68,7 +69,6 @@ import org.asteriskjava.pbx.internal.asterisk.MeetmeRoomControl; import org.asteriskjava.pbx.internal.asterisk.RoomOwner; import org.asteriskjava.pbx.internal.managerAPI.RedirectCall; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java index c59d46d43..a020e9d2c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java @@ -4,11 +4,11 @@ import java.util.LinkedList; import java.util.List; +import org.asteriskjava.lock.LockableList; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.ChannelHangupListener; import org.asteriskjava.pbx.asterisk.wrap.events.ChannelState; -import org.asteriskjava.util.LockableList; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index 6379cab3a..cdf06e05d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -11,6 +11,8 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import org.asteriskjava.lock.LockableSet; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.ManagerConnection; import org.asteriskjava.manager.ManagerEventListener; import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; @@ -19,8 +21,6 @@ import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.internal.eventQueue.EventLifeMonitor; import org.asteriskjava.pbx.util.LogTime; -import org.asteriskjava.util.LockableSet; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java index cc61603ad..514598c03 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java @@ -6,8 +6,8 @@ import java.util.List; import java.util.TreeSet; +import org.asteriskjava.lock.Lockable; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.util.Lockable; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index aed1043fb..4b115a806 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -7,6 +7,9 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; +import org.asteriskjava.lock.Lockable; +import org.asteriskjava.lock.LockableList; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; @@ -21,9 +24,6 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvents; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; -import org.asteriskjava.util.Lockable; -import org.asteriskjava.util.LockableList; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java index 671c8cf70..5fff24573 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java @@ -2,14 +2,14 @@ import java.util.LinkedList; +import org.asteriskjava.lock.LockableList; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.asterisk.wrap.events.MasqueradeEvent; import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; import org.asteriskjava.pbx.asterisk.wrap.events.NewStateEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; -import org.asteriskjava.util.LockableList; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java index a8639c637..1377eedf1 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java @@ -5,6 +5,8 @@ import java.util.LinkedList; import java.util.List; +import org.asteriskjava.lock.LockableList; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.ListenerPriority; @@ -23,8 +25,6 @@ import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; -import org.asteriskjava.util.LockableList; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java index 6418b234e..980a3497c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java @@ -1,10 +1,10 @@ package org.asteriskjava.pbx.internal.managerAPI; +import org.asteriskjava.lock.Lockable; import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.FilteredManagerListener; -import org.asteriskjava.util.Lockable; /* * This is the basic abstract event listener class. It implements a thread diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 9191bf7ca..87a476d80 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -8,6 +8,7 @@ import java.util.concurrent.atomic.AtomicLong; import org.asteriskjava.live.ManagerCommunicationException; +import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.pbx.AsteriskSettings; import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; @@ -28,7 +29,6 @@ import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -import org.asteriskjava.util.Locker.LockCloser; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; diff --git a/src/test/java/org/asteriskjava/util/LockerTest.java b/src/test/java/org/asteriskjava/util/LockerTest.java index e25485b19..cbdbc233e 100644 --- a/src/test/java/org/asteriskjava/util/LockerTest.java +++ b/src/test/java/org/asteriskjava/util/LockerTest.java @@ -2,7 +2,9 @@ import java.util.concurrent.TimeUnit; -import org.asteriskjava.util.Locker.LockCloser; +import org.asteriskjava.lock.Lockable; +import org.asteriskjava.lock.Locker; +import org.asteriskjava.lock.Locker.LockCloser; import org.junit.Test; public class LockerTest From 8292e095545713a8530a183774cd209a209ee9c4 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 12 Feb 2021 14:33:02 +1100 Subject: [PATCH 423/802] change package --- src/test/java/org/asteriskjava/{util => lock}/LockerTest.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/java/org/asteriskjava/{util => lock}/LockerTest.java (100%) diff --git a/src/test/java/org/asteriskjava/util/LockerTest.java b/src/test/java/org/asteriskjava/lock/LockerTest.java similarity index 100% rename from src/test/java/org/asteriskjava/util/LockerTest.java rename to src/test/java/org/asteriskjava/lock/LockerTest.java From 99917d70349bcec5119d2c8f816f555ec6ae5389 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 12 Feb 2021 14:33:47 +1100 Subject: [PATCH 424/802] improve rate limiter --- .../org/asteriskjava/pbx/agi/RateLimiter.java | 50 ++++++++--- .../asteriskjava/pbx/agi/RateLimiterTest.java | 90 ++++++++++++++++++- 2 files changed, 123 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java b/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java index 0efadab42..7ce6258c0 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java +++ b/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java @@ -1,38 +1,60 @@ package org.asteriskjava.pbx.agi; -import java.util.LinkedList; -import java.util.List; - public class RateLimiter { private static final long ONE_THOUSAND_MILLIS = 1000L; - List available = new LinkedList<>(); + long next = 0; + private final long step; /** - * this is NOT thread safe! + * thread safe! * * @param perSecond - number of 'acquire()' calls allowed per second, a call * to acquire() will block(sleep) if the per second limit is * exceeded */ - RateLimiter(int perSecond) + public RateLimiter(int perSecond) { - long now = System.currentTimeMillis(); - for (int i = 0; i < perSecond; i++) - { - available.add(now - ONE_THOUSAND_MILLIS); - } + step = ONE_THOUSAND_MILLIS / perSecond; } void acquire() throws InterruptedException { + // can't use Locker here, as Locker uses this class + long delay; + synchronized (this) + { + delay = next; + if (next < System.currentTimeMillis()) + { + next = System.currentTimeMillis() + step; + } + else + { + next += step; + } + } + long now = System.currentTimeMillis(); - Long next = available.remove(0); - long timeRemaining = next - now; + long timeRemaining = delay - now; if (timeRemaining > 0) { Thread.sleep(timeRemaining); } - available.add(System.currentTimeMillis() + ONE_THOUSAND_MILLIS); + + } + + public boolean tryAcquire() throws InterruptedException + { + // can't use Locker here, as Locker uses this class + synchronized (this) + { + if (next < System.currentTimeMillis()) + { + next = System.currentTimeMillis() + step; + return true; + } + return false; + } } } diff --git a/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java b/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java index bbd63098c..7efefb819 100644 --- a/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java +++ b/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java @@ -2,7 +2,9 @@ import static org.junit.Assert.assertTrue; -import org.asteriskjava.pbx.agi.RateLimiter; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + import org.junit.Test; public class RateLimiterTest @@ -17,12 +19,94 @@ public void test() throws InterruptedException { limiter.acquire(); - System.out.println(System.currentTimeMillis()); - Thread.sleep(100); + System.out.println(System.currentTimeMillis() + " test1 " + i); + Thread.sleep(10); + } + + // this should have taken around 5 seconds + assertTrue(System.currentTimeMillis() - now > 4000L); + } + + @Test + public void test2() throws InterruptedException + { + long now = System.currentTimeMillis(); + RateLimiter limiter = new RateLimiter(3); + AtomicLong counter = new AtomicLong(); + AtomicBoolean stop = new AtomicBoolean(false); + Runnable runner = () -> { + for (int i = 0; i < 15 && !stop.get(); i++) + { + try + { + limiter.acquire(); + System.out.println(System.currentTimeMillis() + " test2 " + i); + counter.getAndIncrement(); + Thread.sleep(10); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + + } + }; + + new Thread(runner).start(); + new Thread(runner).start(); + new Thread(runner).start(); + + while (counter.intValue() < 15) + { + Thread.sleep(10); } + stop.set(true); + Thread.sleep(1000); // this should have taken around 5 seconds assertTrue(System.currentTimeMillis() - now > 4000L); } + @Test + public void test3() throws InterruptedException + { + long now = System.currentTimeMillis(); + RateLimiter limiter = new RateLimiter(3); + AtomicLong counter = new AtomicLong(); + AtomicBoolean stop = new AtomicBoolean(false); + + Runnable runner = () -> { + for (int i = 0; i < 15 && !stop.get();) + { + try + { + if (limiter.tryAcquire()) + { + i++; + System.out.println(System.currentTimeMillis() + " test3 " + i); + counter.getAndIncrement(); + + } + Thread.sleep(10); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + + } + }; + + new Thread(runner).start(); + new Thread(runner).start(); + new Thread(runner).start(); + + while (counter.intValue() < 15) + { + Thread.sleep(10); + } + stop.set(true); + // this should have taken around 5 seconds + assertTrue(System.currentTimeMillis() - now > 4000L); + } } From 761e4b8794cb73b93ff6d6925ffc572378fdaf5a Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 12 Feb 2021 15:21:18 +1100 Subject: [PATCH 425/802] accommodate changed behavior in RateLimiter --- .../org/asteriskjava/pbx/agi/ActivityAgi.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index a32853bdb..58648c0f7 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -111,16 +111,26 @@ public void channelHangup(Channel channel, Integer cause, String causeText) } boolean isAlive = true; - RateLimiter rateLimiter = new RateLimiter(2); + RateLimiter slowRateLimiter = new RateLimiter(2); + RateLimiter fastRateLimiter = new RateLimiter(10); while (!action.isDisconnect(this) && isAlive) { - + AgiChannelActivityAction oldAction = action; action.execute(this.channel, channelProxy); action = channelProxy.getCurrentActivityAction(); logger.debug("Action for proxy " + channelProxy + " is " + action.getClass().getSimpleName()); isAlive = checkChannelIsStillUp(); - rateLimiter.acquire(); + if (oldAction == action) + { + // action didn't change, lets not loop to fast + slowRateLimiter.acquire(); + } + else + { + // action changed, don't delay long + fastRateLimiter.acquire(); + } } } From 3dcc2184012fe60fb369e98a06db51c4e0649a14 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 12 Feb 2021 15:23:56 +1100 Subject: [PATCH 426/802] rate limit lock dumping --- .../java/org/asteriskjava/lock/Lockable.java | 8 +++ .../java/org/asteriskjava/lock/Locker.java | 50 ++++++++++--------- .../org/asteriskjava/lock/LockerTest.java | 2 +- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/asteriskjava/lock/Lockable.java b/src/main/java/org/asteriskjava/lock/Lockable.java index 05f200d1e..88576ad25 100644 --- a/src/main/java/org/asteriskjava/lock/Lockable.java +++ b/src/main/java/org/asteriskjava/lock/Lockable.java @@ -6,6 +6,7 @@ import java.util.concurrent.locks.ReentrantLock; import org.asteriskjava.lock.Locker.LockCloser; +import org.asteriskjava.pbx.agi.RateLimiter; public class Lockable { @@ -20,6 +21,8 @@ public class Lockable private volatile boolean dumped = false; private volatile boolean blocked = false; + private final RateLimiter rateLimiter = new RateLimiter(4); + private final static AtomicLong seed = new AtomicLong(); private final long lockableId = seed.incrementAndGet(); @@ -147,4 +150,9 @@ void setLockBlocked(boolean blocked) this.blocked = blocked; } + public RateLimiter getDumpRateLimit() + { + return rateLimiter; + } + } diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index 750286192..8c7a1c9b7 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -105,7 +105,15 @@ private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedExc while (!lock.tryLock(100, TimeUnit.MILLISECONDS)) { ctr++; - dumpBlocker(lockable, ctr); + if (!lockable.isLockDumped() && lockable.getDumpRateLimit().tryAcquire()) + { + lockable.setLockDumped(true); + dumpBlocker(lockable, ctr); + } + else + { + logger.warn("waiting " + ctr); + } lockable.setLockBlocked(true); } lockable.setLockDumped(false); @@ -152,8 +160,8 @@ public void close() if (holdTime > averageHoldTime * 5.0) { // long hold! - String message = "Lock hold of lock (" + holdTime + "MS), average is " + lockable.getLockAverageHoldTime() - + " " + getCaller(lockable); + String message = "Lock hold of lock (" + holdTime + "MS), average is " + + lockable.getLockAverageHoldTime() + " " + getCaller(lockable); logger.warn(message); if (holdTime > averageHoldTime * 10.0) @@ -169,36 +177,30 @@ public void close() private static void dumpBlocker(Lockable lockable, int ctr) { - if (!lockable.isLockDumped()) + + Thread thread = lockable.threadHoldingLock.get(); + + if (thread != null) { - Thread thread = lockable.threadHoldingLock.get(); - lockable.setLockDumped(true); - if (thread != null) - { - StackTraceElement[] trace = new Exception().getStackTrace(); + StackTraceElement[] trace = new Exception().getStackTrace(); - String dump = ""; + String dump = ""; - int i = 0; - for (; i < trace.length; i++) - { - StackTraceElement ste = trace[i]; - dump += "\tat " + ste.toString(); - dump += '\n'; - } - logger.error("Waiting on lock... blocked by..."); - logger.error(dump); - } - else + int i = 0; + for (; i < trace.length; i++) { - logger.error("Thread hasn't been set"); + StackTraceElement ste = trace[i]; + dump += "\tat " + ste.toString(); + dump += '\n'; } - + logger.error("Waiting on lock... blocked by..."); + logger.error(dump); } else { - logger.warn("Still waiting " + ctr); + logger.error("Thread hasn't been set"); } + } /** diff --git a/src/test/java/org/asteriskjava/lock/LockerTest.java b/src/test/java/org/asteriskjava/lock/LockerTest.java index cbdbc233e..72f9444e5 100644 --- a/src/test/java/org/asteriskjava/lock/LockerTest.java +++ b/src/test/java/org/asteriskjava/lock/LockerTest.java @@ -1,4 +1,4 @@ -package org.asteriskjava.util; +package org.asteriskjava.lock; import java.util.concurrent.TimeUnit; From 8bb07e1faffc090906079c2e025508b53cf5ee32 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 12 Feb 2021 17:22:22 +1100 Subject: [PATCH 427/802] change logging --- src/main/java/org/asteriskjava/lock/Locker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index 8c7a1c9b7..0bbe7427b 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -258,7 +258,7 @@ static void dumpStats() boolean activity = false; for (Lockable lockable : lockables) { - if (lockable.wasLockBlocked() || first) + if (lockable.wasLockBlocked()) { int waited = lockable.getLockWaited(); int waitTime = lockable.getLockTotalWaitTime(); @@ -279,7 +279,7 @@ static void dumpStats() if (first || activity) { - logger.warn("Dump Lock Stats finished. Will dump every minute when there is contention..."); + logger.warn("Will dump Lock stats each minute when there is contention..."); first = false; } } From e1c79afce5eda2e6ade01829ed58b4415e6b277a Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 15 Feb 2021 14:31:33 +1100 Subject: [PATCH 428/802] improve logging --- src/main/java/org/asteriskjava/lock/Locker.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index 0bbe7427b..98af44a24 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -121,7 +121,6 @@ private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedExc long acquiredAt = System.currentTimeMillis(); lockable.threadHoldingLock.set(Thread.currentThread()); - return new LockCloser() { @@ -148,7 +147,8 @@ public void close() { // some threads waited String message = "Lock held for (" + holdTime + "MS), " + waiters - + " threads waited for some of that time! " + getCaller(lockable); + + " threads waited for some of that time! " + getCaller(lockable) + " id:" + + lockable.getLockableId(); logger.warn(message); if (holdTime > averageHoldTime * 10.0 || dumped) { @@ -161,7 +161,8 @@ public void close() { // long hold! String message = "Lock hold of lock (" + holdTime + "MS), average is " - + lockable.getLockAverageHoldTime() + " " + getCaller(lockable); + + lockable.getLockAverageHoldTime() + " " + getCaller(lockable) + " id:" + + lockable.getLockableId(); logger.warn(message); if (holdTime > averageHoldTime * 10.0) From 531665d99d81220c8c4874a427e1f4399d16da32 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 15 Feb 2021 14:36:23 +1100 Subject: [PATCH 429/802] add time checking on event dispatch --- .../internal/ManagerConnectionImpl.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 9aee8caaf..62636842f 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1237,6 +1237,7 @@ public void dispatchResponse(ManagerResponse response) if (listener != null) { + LogTime timer = new LogTime(); try { listener.onResponse(response); @@ -1245,6 +1246,14 @@ public void dispatchResponse(ManagerResponse response) { logger.warn("Unexpected exception in response listener " + listener.getClass().getName(), e); } + finally + { + if (timer.timeTaken() > 20) + { + logger.warn("Slow processing of event " + listener.getClass().getCanonicalName() + " " + + timer.timeTaken() + "MS \n" + response); + } + } } } @@ -1292,6 +1301,7 @@ public void dispatchEvent(ManagerEvent event) listener = responseEventListeners.get(internalActionId); if (listener != null) { + LogTime timer = new LogTime(); try { listener.onManagerEvent(event); @@ -1301,6 +1311,14 @@ public void dispatchEvent(ManagerEvent event) logger.warn("Unexpected exception in response event listener " + listener.getClass().getName(), e); } + finally + { + if (timer.timeTaken() > 20) + { + logger.warn("Slow processing of event " + listener.getClass().getCanonicalName() + " " + + timer.timeTaken() + "MS \n" + event); + } + } } } } @@ -1395,6 +1413,7 @@ private void fireEvent(ManagerEvent event) { for (ManagerEventListener listener : eventListeners) { + LogTime timer = new LogTime(); try { listener.onManagerEvent(event); @@ -1403,6 +1422,14 @@ private void fireEvent(ManagerEvent event) { logger.warn("Unexpected exception in eventHandler " + listener.getClass().getName(), e); } + finally + { + if (timer.timeTaken() > 20) + { + logger.warn("Slow processing of event " + listener.getClass().getCanonicalName() + " " + + timer.timeTaken() + "MS \n" + event); + } + } } } } @@ -1670,6 +1697,7 @@ public void onResponse(ManagerResponse response) { logger.error("Response arrived after Disposal and assumably Timeout " + response + " elapsed: " + timer.timeTaken() + "(MS)"); + logger.error("" + response.getDateReceived()); } latch.countDown(); } From 10e161dca70cf4a0bbd6f87da79d4ad9e7757348 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 15 Feb 2021 14:38:54 +1100 Subject: [PATCH 430/802] add async event pump --- .../manager/internal/AsyncEventPump.java | 146 ++++++++++++++++++ .../manager/internal/Dispatcher.java | 6 +- .../internal/ManagerConnectionImpl.java | 6 + .../manager/internal/ManagerReaderImpl.java | 21 ++- .../internal/ManagerReaderImplTest.java | 6 + 5 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java new file mode 100644 index 000000000..5313550c7 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -0,0 +1,146 @@ +package org.asteriskjava.manager.internal; + +import java.lang.ref.WeakReference; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.response.ManagerResponse; +import org.asteriskjava.pbx.agi.RateLimiter; +import org.asteriskjava.pbx.util.LogTime; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + +public class AsyncEventPump implements Dispatcher, Runnable +{ + private final Log logger = LogFactory.getLog(AsyncEventPump.class); + + private static final long MAX_SAFE_EVENT_AGE = 250; + + private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(20000); + private final Dispatcher dispatcher; + private volatile boolean stop = false; + private final WeakReference owner; + + private final Thread thread; + + AsyncEventPump(Object owner, Dispatcher dispatcher, String string) + { + this.dispatcher = dispatcher; + this.owner = new WeakReference<>(owner); + thread = new Thread(this, string + ":AsyncEventPump"); + thread.start(); + } + + @Override + public void run() + { + RateLimiter rateLimiter = new RateLimiter(2); + while (!stop || !queue.isEmpty()) + { + try + { + EventWrapper wrapper = queue.poll(1, TimeUnit.MINUTES); + if (wrapper != null) + { + if (wrapper.timer.timeTaken() > MAX_SAFE_EVENT_AGE && rateLimiter.tryAcquire()) + { + logger.warn("The following message will only appear once per second!"); + logger.warn("Event being dispatched " + wrapper.timer.timeTaken() + + " MS after arriving, your ManagerEvent handlers are too slow!\n" + + "You should also check for Garbage Collection issues."); + logger.warn("There are " + queue.size() + " events waiting to be processed in the queue."); + + } + if (wrapper.response != null) + { + dispatcher.dispatchResponse(wrapper.response); + } + else if (wrapper.event != null) + { + dispatcher.dispatchEvent(wrapper.event); + } + } + else if (owner.get() == null) + { + stop = true; + logger.error("The owner has been garbage collected!"); + } + + } + catch (InterruptedException e) + { + logger.error(e); + } + catch (Exception e) + { + logger.error(e, e); + } + } + logger.warn("AsyncEventPump is shutting down"); + + } + + public void stop() + { + stop = true; + // poison + queue.add(new EventWrapper()); + long delay = 1; + while (!queue.isEmpty()) + { + try + { + TimeUnit.MILLISECONDS.sleep(delay); + logger.info("Stoping " + delay); + delay = Math.min(10, delay + 1); + } + catch (InterruptedException e) + { + logger.error(e); + } + } + logger.info("Stopped"); + } + + @Override + public void dispatchResponse(ManagerResponse response) + { + if (!queue.offer(new EventWrapper(response))) + { + logger.error("Event queue is full, not processing ManagerResponse " + response); + } + } + + @Override + public void dispatchEvent(ManagerEvent event) + { + if (!queue.offer(new EventWrapper(event))) + { + logger.error("Event queue is full, not processing ManagerEvent " + event); + } + } + + class EventWrapper + { + EventWrapper() + { + // poison + } + + EventWrapper(ManagerResponse response) + { + this.response = response; + } + + EventWrapper(ManagerEvent event) + { + this.event = event; + } + + LogTime timer = new LogTime(); + ManagerResponse response; + ManagerEvent event; + } + +} diff --git a/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java b/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java index 89891efc5..201c66d94 100644 --- a/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java +++ b/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java @@ -19,10 +19,10 @@ import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.response.ManagerResponse; - /** * The Dispatcher defines the interface used for communication between - * ManagerConnection and ManagerReader.

    + * ManagerConnection and ManagerReader. + *

    * Do not use this interface in your code, it is intended to be used only by the * DefaultManagerConnection and its ManagerReader. * @@ -49,4 +49,6 @@ interface Dispatcher * @see ManagerReader */ void dispatchEvent(ManagerEvent event); + + void stop(); } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 62636842f..c95bfe269 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1878,4 +1878,10 @@ public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) reader.deregisterEventClass(eventClass); } + + @Override + public void stop() + { + // NO_OP + } } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java index f41e533f4..d17fc634d 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java @@ -29,6 +29,7 @@ import org.asteriskjava.manager.event.ProtocolIdentifierReceivedEvent; import org.asteriskjava.manager.internal.backwardsCompatibility.BackwardsCompatibilityForManagerEvents; import org.asteriskjava.manager.response.ManagerResponse; +import org.asteriskjava.pbx.util.LogTime; import org.asteriskjava.util.DateUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -59,11 +60,6 @@ public class ManagerReaderImpl implements ManagerReader */ private final ResponseBuilder responseBuilder; - /** - * The dispatcher to use for dispatching events and responses. - */ - private final Dispatcher dispatcher; - private final Map> expectedResponseClasses; /** @@ -97,6 +93,8 @@ public class ManagerReaderImpl implements ManagerReader */ BackwardsCompatibilityForManagerEvents compatibility = new BackwardsCompatibilityForManagerEvents(); + private final Dispatcher rawDispatcher; + /** * Creates a new ManagerReaderImpl. * @@ -106,7 +104,7 @@ public class ManagerReaderImpl implements ManagerReader */ public ManagerReaderImpl(final Dispatcher dispatcher, Object source) { - this.dispatcher = dispatcher; + this.rawDispatcher = dispatcher; this.source = source; this.eventBuilder = new EventBuilderImpl(); @@ -157,6 +155,7 @@ public void run() this.die = false; this.dead = false; + AsyncEventPump dispatcher = new AsyncEventPump(this, rawDispatcher, Thread.currentThread().getName()); try { // main loop @@ -220,6 +219,8 @@ public void run() // ManagerConnection. if (line.length() == 0) { + Object cause = null; + LogTime timer = new LogTime(); if (buffer.containsKey("event")) { // TODO tracing @@ -228,6 +229,7 @@ public void run() ManagerEvent event = buildEvent(source, buffer); if (event != null) { + cause = event; dispatcher.dispatchEvent(event); // Backwards compatibility for bridge events. @@ -255,6 +257,7 @@ else if (buffer.containsKey("response")) // logger.debug("attempting to build response"); if (response != null) { + cause = response; dispatcher.dispatchResponse(response); } } @@ -267,6 +270,11 @@ else if (buffer.containsKey("response")) } buffer.clear(); + if (timer.timeTaken() > 50) + { + logger.warn("(This is normal during JVM warmup) Slow processing of event " + timer.timeTaken() + "\n" + + cause); + } } } this.dead = true; @@ -296,6 +304,7 @@ else if (buffer.containsKey("response")) DisconnectEvent disconnectEvent = new DisconnectEvent(source); disconnectEvent.setDateReceived(DateUtil.getDate()); dispatcher.dispatchEvent(disconnectEvent); + dispatcher.stop(); } } diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java index 6dac7843a..2ae21f1e2 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java @@ -372,5 +372,11 @@ public void dispatchEvent(ManagerEvent event) { dispatchedEvents.add(event); } + + @Override + public void stop() + { + // NO_OP + } } } From ffa76fc5e1f122c4d035c81d6ce1c98a3e74d2f5 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 15 Feb 2021 15:53:23 +1100 Subject: [PATCH 431/802] add dynamic handling speed --- .../manager/internal/AsyncEventPump.java | 24 +++++++++++-------- .../manager/internal/Dispatcher.java | 5 ++-- .../internal/ManagerConnectionImpl.java | 22 ++++++++--------- .../manager/internal/ManagerReaderImpl.java | 10 ++++---- .../internal/ManagerConnectionImplTest.java | 16 ++++++------- .../internal/ManagerReaderImplTest.java | 4 ++-- .../manager/internal/ManagerWriterMock.java | 4 ++-- 7 files changed, 45 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index 5313550c7..608eb8002 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -15,7 +15,7 @@ public class AsyncEventPump implements Dispatcher, Runnable { private final Log logger = LogFactory.getLog(AsyncEventPump.class); - private static final long MAX_SAFE_EVENT_AGE = 250; + private static final long MAX_SAFE_EVENT_AGE = 500; private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(20000); private final Dispatcher dispatcher; @@ -45,20 +45,24 @@ public void run() { if (wrapper.timer.timeTaken() > MAX_SAFE_EVENT_AGE && rateLimiter.tryAcquire()) { - logger.warn("The following message will only appear once per second!"); - logger.warn("Event being dispatched " + wrapper.timer.timeTaken() + logger.warn("The following message will only appear once per second!\n" + "Event being dispatched " + + wrapper.timer.timeTaken() + " MS after arriving, your ManagerEvent handlers are too slow!\n" - + "You should also check for Garbage Collection issues."); - logger.warn("There are " + queue.size() + " events waiting to be processed in the queue."); + + "You should also check for Garbage Collection issues.\n" + "There are " + queue.size() + + " events waiting to be processed in the queue.\n"); } + // assume we need to process all queued events in + // MAX_SAFE_EVENT_AGE + int requiredHandlingTime = (int) (MAX_SAFE_EVENT_AGE / Math.max(1, queue.size())); + if (wrapper.response != null) { - dispatcher.dispatchResponse(wrapper.response); + dispatcher.dispatchResponse(wrapper.response, requiredHandlingTime); } else if (wrapper.event != null) { - dispatcher.dispatchEvent(wrapper.event); + dispatcher.dispatchEvent(wrapper.event, requiredHandlingTime); } } else if (owner.get() == null) @@ -93,7 +97,7 @@ public void stop() { TimeUnit.MILLISECONDS.sleep(delay); logger.info("Stoping " + delay); - delay = Math.min(10, delay + 1); + delay = Math.min(10000, delay + 1); } catch (InterruptedException e) { @@ -104,7 +108,7 @@ public void stop() } @Override - public void dispatchResponse(ManagerResponse response) + public void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime) { if (!queue.offer(new EventWrapper(response))) { @@ -113,7 +117,7 @@ public void dispatchResponse(ManagerResponse response) } @Override - public void dispatchEvent(ManagerEvent event) + public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) { if (!queue.offer(new EventWrapper(event))) { diff --git a/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java b/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java index 201c66d94..34a0a7370 100644 --- a/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java +++ b/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java @@ -37,9 +37,10 @@ interface Dispatcher * {@link org.asteriskjava.manager.SendActionCallback}. * * @param response the resonse received by the reader + * @param requiredHandlingTime * @see ManagerReader */ - void dispatchResponse(ManagerResponse response); + void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime); /** * This method is called by the reader whenever a ManagerEvent is received. @@ -48,7 +49,7 @@ interface Dispatcher * @param event the event received by the reader * @see ManagerReader */ - void dispatchEvent(ManagerEvent event); + void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime); void stop(); } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index c95bfe269..ffe8b51d9 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -644,7 +644,7 @@ protected void doLogin(long timeout, String eventMask) connectEvent.setProtocolIdentifier(getProtocolIdentifier()); connectEvent.setDateReceived(DateUtil.getDate()); // TODO could this cause a deadlock? - fireEvent(connectEvent); + fireEvent(connectEvent, null); } } @@ -1184,7 +1184,7 @@ public ManagerConnectionState getState() * @param response the response received by the reader * @see ManagerReader */ - public void dispatchResponse(ManagerResponse response) + public void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime) { final String actionId; String internalActionId; @@ -1248,7 +1248,7 @@ public void dispatchResponse(ManagerResponse response) } finally { - if (timer.timeTaken() > 20) + if (requiredHandlingTime != null && timer.timeTaken() > requiredHandlingTime) { logger.warn("Slow processing of event " + listener.getClass().getCanonicalName() + " " + timer.timeTaken() + "MS \n" + response); @@ -1266,7 +1266,7 @@ public void dispatchResponse(ManagerResponse response) * @see #removeEventListener(ManagerEventListener) * @see ManagerReader */ - public void dispatchEvent(ManagerEvent event) + public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) { // shouldn't happen if (event == null) @@ -1274,7 +1274,7 @@ public void dispatchEvent(ManagerEvent event) logger.error("Unable to dispatch null event. This should never happen. Please file a bug."); return; } - dispatchLegacyEventIfNeeded(event); + dispatchLegacyEventIfNeeded(event, requiredHandlingTime); if (logger.isDebugEnabled()) { logger.debug("Dispatching event:\n" + event.toString()); @@ -1313,7 +1313,7 @@ public void dispatchEvent(ManagerEvent event) } finally { - if (timer.timeTaken() > 20) + if (requiredHandlingTime != null && timer.timeTaken() > requiredHandlingTime) { logger.warn("Slow processing of event " + listener.getClass().getCanonicalName() + " " + timer.timeTaken() + "MS \n" + event); @@ -1386,19 +1386,19 @@ public void run() return; } - fireEvent(event); + fireEvent(event, requiredHandlingTime); } /** * Enro 2015-03 Workaround to continue having Legacy Events from Asterisk * 13. */ - private void dispatchLegacyEventIfNeeded(ManagerEvent event) + private void dispatchLegacyEventIfNeeded(ManagerEvent event, Integer requiredHandlingTime) { if (event instanceof DialBeginEvent) { DialEvent legacyEvent = new DialEvent((DialBeginEvent) event); - dispatchEvent(legacyEvent); + dispatchEvent(legacyEvent, requiredHandlingTime); } } @@ -1407,7 +1407,7 @@ private void dispatchLegacyEventIfNeeded(ManagerEvent event) * * @param event the event to propagate */ - private void fireEvent(ManagerEvent event) + private void fireEvent(ManagerEvent event, Integer requiredHandlingTime) { try (LockCloser closer = eventListeners.withLock()) { @@ -1424,7 +1424,7 @@ private void fireEvent(ManagerEvent event) } finally { - if (timer.timeTaken() > 20) + if (requiredHandlingTime != null && timer.timeTaken() > requiredHandlingTime) { logger.warn("Slow processing of event " + listener.getClass().getCanonicalName() + " " + timer.timeTaken() + "MS \n" + event); diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java index d17fc634d..d251d0772 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java @@ -172,7 +172,7 @@ public void run() protocolIdentifierReceivedEvent = new ProtocolIdentifierReceivedEvent(source); protocolIdentifierReceivedEvent.setProtocolIdentifier(line); protocolIdentifierReceivedEvent.setDateReceived(DateUtil.getDate()); - dispatcher.dispatchEvent(protocolIdentifierReceivedEvent); + dispatcher.dispatchEvent(protocolIdentifierReceivedEvent, null); continue; } @@ -230,7 +230,7 @@ public void run() if (event != null) { cause = event; - dispatcher.dispatchEvent(event); + dispatcher.dispatchEvent(event, null); // Backwards compatibility for bridge events. // Asterisk 13 uses BridgeCreate, @@ -242,7 +242,7 @@ public void run() ManagerEvent secondaryEvent = compatibility.handleEvent(event); if (secondaryEvent != null) { - dispatcher.dispatchEvent(secondaryEvent); + dispatcher.dispatchEvent(secondaryEvent, null); } } else @@ -258,7 +258,7 @@ else if (buffer.containsKey("response")) if (response != null) { cause = response; - dispatcher.dispatchResponse(response); + dispatcher.dispatchResponse(response, null); } } else @@ -303,7 +303,7 @@ else if (buffer.containsKey("response")) // cleans resources and reconnects if needed DisconnectEvent disconnectEvent = new DisconnectEvent(source); disconnectEvent.setDateReceived(DateUtil.getDate()); - dispatcher.dispatchEvent(disconnectEvent); + dispatcher.dispatchEvent(disconnectEvent, null); dispatcher.stop(); } } diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerConnectionImplTest.java b/src/test/java/org/asteriskjava/manager/internal/ManagerConnectionImplTest.java index a7dbf7a60..092a9d5c3 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerConnectionImplTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerConnectionImplTest.java @@ -446,7 +446,7 @@ public void testDispatchResponseUnexpectedResponse() response.setResponse("Success"); // expected result is ignoring the response and logging - mc.dispatchResponse(response); + mc.dispatchResponse(response, null); } @Test @@ -459,7 +459,7 @@ public void testDispatchResponseMissingInternalActionId() response.setResponse("Success"); // expected result is ignoring the response and logging - mc.dispatchResponse(response); + mc.dispatchResponse(response, null); } @Test @@ -472,14 +472,14 @@ public void testDispatchResponseNullActionId() response.setResponse("Success"); // expected result is ignoring the response and logging - mc.dispatchResponse(response); + mc.dispatchResponse(response, null); } @Test public void testDispatchResponseNullResponse() { // expected result is ignoring and logging - mc.dispatchResponse(null); + mc.dispatchResponse(null, null); } @Test @@ -496,7 +496,7 @@ public void testReconnect() throws Exception mc.setUsername("username"); mc.setPassword("password"); - mc.dispatchEvent(disconnectEvent); + mc.dispatchEvent(disconnectEvent, null); // wait for reconnect thread to do its work Thread.sleep(1000); @@ -530,7 +530,7 @@ public void testReconnectWithIOException() throws Exception mc.setUsername("username"); mc.setPassword("password"); - mc.dispatchEvent(disconnectEvent); + mc.dispatchEvent(disconnectEvent, null); // wait for reconnect thread to do its work Thread.sleep(1000); @@ -565,7 +565,7 @@ public void testReconnectWithTimeoutException() throws Exception mc.setUsername("username"); mc.setPassword("password"); - mc.dispatchEvent(disconnectEvent); + mc.dispatchEvent(disconnectEvent, null); // wait for reconnect thread to do its work Thread.sleep(1000); @@ -608,7 +608,7 @@ public void onManagerEvent(ManagerEvent event) } replay(list); - mc.dispatchEvent(event); + mc.dispatchEvent(event, null); verify(list); } diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java index 2ae21f1e2..57ca31ce3 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java @@ -363,12 +363,12 @@ public MockedDispatcher() this.dispatchedResponses = new ArrayList(); } - public void dispatchResponse(ManagerResponse response) + public void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime) { dispatchedResponses.add(response); } - public void dispatchEvent(ManagerEvent event) + public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) { dispatchedEvents.add(event); } diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerWriterMock.java b/src/test/java/org/asteriskjava/manager/internal/ManagerWriterMock.java index fa8383ce6..670d8fe8c 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerWriterMock.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerWriterMock.java @@ -101,7 +101,7 @@ public void run() protocolIdentifierReceivedEvent = new ProtocolIdentifierReceivedEvent(this); protocolIdentifierReceivedEvent.setProtocolIdentifier("Asterisk Call Manager/1.0"); protocolIdentifierReceivedEvent.setDateReceived(DateUtil.getDate()); - dispatcher.dispatchEvent(protocolIdentifierReceivedEvent); + dispatcher.dispatchEvent(protocolIdentifierReceivedEvent, null); } }); future.start(); @@ -218,7 +218,7 @@ public void run() { Thread.currentThread().interrupt(); } - dispatcher.dispatchResponse(response); + dispatcher.dispatchResponse(response, null); } }); future.start(); From 346571d545f4ca0e4a69c9db4e32c77f2834cee2 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 15 Feb 2021 15:57:27 +1100 Subject: [PATCH 432/802] logging backoff --- .../java/org/asteriskjava/manager/internal/AsyncEventPump.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index 608eb8002..0c2f09be2 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -97,7 +97,7 @@ public void stop() { TimeUnit.MILLISECONDS.sleep(delay); logger.info("Stoping " + delay); - delay = Math.min(10000, delay + 1); + delay = Math.min(10000, Math.max(1, delay / 10)); } catch (InterruptedException e) { From b80bfc86742cca7d9abf14adec425eb60e229f15 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 16 Feb 2021 09:38:04 +1100 Subject: [PATCH 433/802] add some comments and cleanup shutdown --- .../manager/internal/AsyncEventPump.java | 142 ++++++++++++------ .../manager/internal/Dispatcher.java | 7 +- 2 files changed, 97 insertions(+), 52 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index 0c2f09be2..e95e43c1e 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -1,6 +1,7 @@ package org.asteriskjava.manager.internal; import java.lang.ref.WeakReference; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -11,6 +12,13 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +/** + * AsyncEventPump delivers events and responses to a Dispatcher without blocking + * the thread which is producing the events and responses. AsyncEventPump also + * adds logging around timely handling of events + * + * @author rsutton + */ public class AsyncEventPump implements Dispatcher, Runnable { private final Log logger = LogFactory.getLog(AsyncEventPump.class); @@ -24,89 +32,118 @@ public class AsyncEventPump implements Dispatcher, Runnable private final Thread thread; - AsyncEventPump(Object owner, Dispatcher dispatcher, String string) + /** + * @param owner a weak reference to the owner is created, should it be + * garbage collected then AsyncEventPump will shutdown. + * @param dispatcher the dispatcher that AsyncEventPump should deliver + * events to. + * @param threadName the AsyncEventPump's thread will be named with a + * variant of threadName + */ + AsyncEventPump(Object owner, Dispatcher dispatcher, String threadName) { this.dispatcher = dispatcher; this.owner = new WeakReference<>(owner); - thread = new Thread(this, string + ":AsyncEventPump"); + thread = new Thread(this, threadName + ":AsyncEventPump"); thread.start(); } @Override public void run() { - RateLimiter rateLimiter = new RateLimiter(2); - while (!stop || !queue.isEmpty()) + try { - try + RateLimiter rateLimiter = new RateLimiter(2); + while (!stop || !queue.isEmpty()) { - EventWrapper wrapper = queue.poll(1, TimeUnit.MINUTES); - if (wrapper != null) + try { - if (wrapper.timer.timeTaken() > MAX_SAFE_EVENT_AGE && rateLimiter.tryAcquire()) + EventWrapper wrapper = queue.poll(1, TimeUnit.MINUTES); + if (wrapper != null) { - logger.warn("The following message will only appear once per second!\n" + "Event being dispatched " - + wrapper.timer.timeTaken() - + " MS after arriving, your ManagerEvent handlers are too slow!\n" - + "You should also check for Garbage Collection issues.\n" + "There are " + queue.size() - + " events waiting to be processed in the queue.\n"); - + if (wrapper.timer.timeTaken() > MAX_SAFE_EVENT_AGE && rateLimiter.tryAcquire()) + { + logger.warn("The following message will only appear once per second!\n" + + "Event being dispatched " + wrapper.timer.timeTaken() + + " MS after arriving, your ManagerEvent handlers are too slow!\n" + + "You should also check for Garbage Collection issues.\n" + "There are " + queue.size() + + " events waiting to be processed in the queue.\n"); + + } + // assume we need to process all queued events in + // MAX_SAFE_EVENT_AGE + int requiredHandlingTime = (int) (MAX_SAFE_EVENT_AGE / Math.max(1, queue.size())); + + if (wrapper.response != null) + { + dispatcher.dispatchResponse(wrapper.response, requiredHandlingTime); + } + else if (wrapper.event != null) + { + dispatcher.dispatchEvent(wrapper.event, requiredHandlingTime); + } + else if (wrapper.poison != null) + { + wrapper.poison.countDown(); + } } - // assume we need to process all queued events in - // MAX_SAFE_EVENT_AGE - int requiredHandlingTime = (int) (MAX_SAFE_EVENT_AGE / Math.max(1, queue.size())); - - if (wrapper.response != null) + else if (owner.get() == null) { - dispatcher.dispatchResponse(wrapper.response, requiredHandlingTime); - } - else if (wrapper.event != null) - { - dispatcher.dispatchEvent(wrapper.event, requiredHandlingTime); + stop = true; + logger.error("The owner has been garbage collected!"); } + } - else if (owner.get() == null) + catch (InterruptedException e) { - stop = true; - logger.error("The owner has been garbage collected!"); + logger.error(e); + } + catch (Exception e) + { + logger.error(e, e); } - - } - catch (InterruptedException e) - { - logger.error(e); - } - catch (Exception e) - { - logger.error(e, e); } } - logger.warn("AsyncEventPump is shutting down"); + finally + { + logger.warn("AsyncEventPump has exited"); + } } + /** + * call stop() to cause the AsyncEventPump to stop, it will first empty the + * queue. + */ public void stop() { stop = true; - // poison - queue.add(new EventWrapper()); - long delay = 1; - while (!queue.isEmpty()) + EventWrapper poisonWrapper = new EventWrapper(); + queue.add(poisonWrapper); + logger.warn("Requesting AsyncEventPump to stop"); + int ctr = 0; + try { - try - { - TimeUnit.MILLISECONDS.sleep(delay); - logger.info("Stoping " + delay); - delay = Math.min(10000, Math.max(1, delay / 10)); - } - catch (InterruptedException e) + while (!poisonWrapper.poison.await(1, TimeUnit.SECONDS)) { - logger.error(e); + logger.info("Waiting for AsyncEventPump to Stop... "); + ctr++; + if (ctr > 60) + { + throw new RuntimeException("Failed to shutdown AsyncEventPump cleanly!"); + } } } - logger.info("Stopped"); + catch (InterruptedException e1) + { + logger.error(e1); + } + logger.info("AsyncEventPump consumed the poision, and may have exited before this message was logged."); } + /** + * add a ManagerResponse to the queue, only if the queue is not full + */ @Override public void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime) { @@ -116,6 +153,9 @@ public void dispatchResponse(ManagerResponse response, Integer requiredHandlingT } } + /** + * add a ManagerEvent to the queue, only if the queue is not full + */ @Override public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) { @@ -130,6 +170,7 @@ class EventWrapper EventWrapper() { // poison + poison = new CountDownLatch(1); } EventWrapper(ManagerResponse response) @@ -145,6 +186,7 @@ class EventWrapper LogTime timer = new LogTime(); ManagerResponse response; ManagerEvent event; + CountDownLatch poison; } } diff --git a/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java b/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java index 34a0a7370..84c5fcca4 100644 --- a/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java +++ b/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java @@ -36,8 +36,9 @@ interface Dispatcher * received. The response is dispatched to the associated * {@link org.asteriskjava.manager.SendActionCallback}. * - * @param response the resonse received by the reader - * @param requiredHandlingTime + * @param response the response received by the reader + * @param requiredHandlingTime the time that this event must be handled + * within to not cause a back log of events * @see ManagerReader */ void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime); @@ -47,6 +48,8 @@ interface Dispatcher * The event is dispatched to all registered ManagerEventHandlers. * * @param event the event received by the reader + * @param requiredHandlingTime the time that this event must be handled + * within to not cause a back log of events * @see ManagerReader */ void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime); From ac43500d3de275ad4b2bb6b7652dd560e6ee52ea Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 16 Feb 2021 09:43:34 +1100 Subject: [PATCH 434/802] change logging for Interrupted handling --- .../org/asteriskjava/manager/internal/AsyncEventPump.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index e95e43c1e..d902fa9d5 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -133,12 +133,12 @@ public void stop() throw new RuntimeException("Failed to shutdown AsyncEventPump cleanly!"); } } + logger.info("AsyncEventPump consumed the poision, and may have exited before this message was logged."); } catch (InterruptedException e1) { logger.error(e1); } - logger.info("AsyncEventPump consumed the poision, and may have exited before this message was logged."); } /** @@ -165,7 +165,7 @@ public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) } } - class EventWrapper + private static class EventWrapper { EventWrapper() { From 4606167f0896df5458d48ce9b3e3cc0396931a45 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 17 Feb 2021 14:40:27 +1100 Subject: [PATCH 435/802] reduce logging --- .../java/org/asteriskjava/manager/internal/AsyncEventPump.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index d902fa9d5..dd8a2a77b 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -120,7 +120,7 @@ public void stop() stop = true; EventWrapper poisonWrapper = new EventWrapper(); queue.add(poisonWrapper); - logger.warn("Requesting AsyncEventPump to stop"); + logger.info("Requesting AsyncEventPump to stop"); int ctr = 0; try { From 31929939365e076102c8d5d8fc5970eee17ae8cb Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 17 Feb 2021 15:53:07 +1100 Subject: [PATCH 436/802] pass unit test --- .../java/org/asteriskjava/lock/Locker.java | 8 +++--- .../manager/internal/AsyncEventPump.java | 27 ++++++++++++++++--- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index 98af44a24..32a66c041 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -108,7 +108,7 @@ private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedExc if (!lockable.isLockDumped() && lockable.getDumpRateLimit().tryAcquire()) { lockable.setLockDumped(true); - dumpBlocker(lockable, ctr); + dumpThread(lockable.threadHoldingLock.get(), "Waiting on lock... blocked by..."); } else { @@ -176,11 +176,9 @@ public void close() } - private static void dumpBlocker(Lockable lockable, int ctr) + public static void dumpThread(Thread thread, String message) { - Thread thread = lockable.threadHoldingLock.get(); - if (thread != null) { StackTraceElement[] trace = new Exception().getStackTrace(); @@ -194,7 +192,7 @@ private static void dumpBlocker(Lockable lockable, int ctr) dump += "\tat " + ste.toString(); dump += '\n'; } - logger.error("Waiting on lock... blocked by..."); + logger.error(message); logger.error(dump); } else diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index dd8a2a77b..a88805995 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -5,6 +5,7 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import org.asteriskjava.lock.Locker; import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.pbx.agi.RateLimiter; @@ -31,6 +32,7 @@ public class AsyncEventPump implements Dispatcher, Runnable private final WeakReference owner; private final Thread thread; + private volatile boolean terminated = false; /** * @param owner a weak reference to the owner is created, should it be @@ -106,6 +108,7 @@ else if (owner.get() == null) } finally { + terminated = true; logger.warn("AsyncEventPump has exited"); } @@ -118,22 +121,38 @@ else if (owner.get() == null) public void stop() { stop = true; + logger.info("Requesting AsyncEventPump to stop"); + if (terminated) + { + logger.warn("AsyncEventPump is already stopped"); + if (!queue.isEmpty()) + { + logger.error("There are unprocessed events in the queue"); + } + + return; + } EventWrapper poisonWrapper = new EventWrapper(); queue.add(poisonWrapper); - logger.info("Requesting AsyncEventPump to stop"); int ctr = 0; try { - while (!poisonWrapper.poison.await(1, TimeUnit.SECONDS)) + int queueSize = queue.size(); + while (!poisonWrapper.poison.await(10, TimeUnit.SECONDS)) { + if (queueSize == queue.size()) + { + Locker.dumpThread(thread, "Queue thread is blocked here..."); + throw new RuntimeException("Failed to shutdown AsyncEventPump cleanly!"); + + } logger.info("Waiting for AsyncEventPump to Stop... "); ctr++; - if (ctr > 60) + if (ctr > 6) { throw new RuntimeException("Failed to shutdown AsyncEventPump cleanly!"); } } - logger.info("AsyncEventPump consumed the poision, and may have exited before this message was logged."); } catch (InterruptedException e1) { From 733af160bbc7c7f7e52d0839656218e810239d73 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 17 Feb 2021 16:52:55 +1100 Subject: [PATCH 437/802] tidy up --- .../manager/internal/AsyncEventPump.java | 25 +++++++++++-------- .../org/asteriskjava/pbx/util/LogTime.java | 6 ++--- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index a88805995..0ea5d2c00 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -35,11 +35,11 @@ public class AsyncEventPump implements Dispatcher, Runnable private volatile boolean terminated = false; /** - * @param owner a weak reference to the owner is created, should it be + * @param owner: A weak reference to the owner is created, should it be * garbage collected then AsyncEventPump will shutdown. - * @param dispatcher the dispatcher that AsyncEventPump should deliver + * @param dispatcher: The dispatcher that AsyncEventPump should deliver * events to. - * @param threadName the AsyncEventPump's thread will be named with a + * @param threadName: The AsyncEventPump's thread will be named with a * variant of threadName */ AsyncEventPump(Object owner, Dispatcher dispatcher, String threadName) @@ -134,21 +134,23 @@ public void stop() } EventWrapper poisonWrapper = new EventWrapper(); queue.add(poisonWrapper); - int ctr = 0; + LogTime timer = new LogTime(); try { int queueSize = queue.size(); - while (!poisonWrapper.poison.await(10, TimeUnit.SECONDS)) + while (!poisonWrapper.poison.await(5, TimeUnit.SECONDS)) { + // still waiting for the poison to be consumed. if (queueSize == queue.size()) { Locker.dumpThread(thread, "Queue thread is blocked here..."); throw new RuntimeException("Failed to shutdown AsyncEventPump cleanly!"); } + queueSize = queue.size(); logger.info("Waiting for AsyncEventPump to Stop... "); - ctr++; - if (ctr > 6) + + if (timer.timeTaken() > 60_000) { throw new RuntimeException("Failed to shutdown AsyncEventPump cleanly!"); } @@ -186,6 +188,11 @@ public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) private static class EventWrapper { + LogTime timer = new LogTime(); + ManagerResponse response; + ManagerEvent event; + CountDownLatch poison; + EventWrapper() { // poison @@ -202,10 +209,6 @@ private static class EventWrapper this.event = event; } - LogTime timer = new LogTime(); - ManagerResponse response; - ManagerEvent event; - CountDownLatch poison; } } diff --git a/src/main/java/org/asteriskjava/pbx/util/LogTime.java b/src/main/java/org/asteriskjava/pbx/util/LogTime.java index 98880e42b..26db60284 100644 --- a/src/main/java/org/asteriskjava/pbx/util/LogTime.java +++ b/src/main/java/org/asteriskjava/pbx/util/LogTime.java @@ -11,11 +11,11 @@ public class LogTime { public Long dStartTime = System.currentTimeMillis(); + /** + * @return time taken from construction until now in milliseconds + */ public long timeTaken() { - // returns the time taken from construction until now in milliseconds - return System.currentTimeMillis() - this.dStartTime; - } } From 4702ff8e2a011009f6b537a5fdd4a6285d0e9c5b Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 17 Feb 2021 17:27:42 +1100 Subject: [PATCH 438/802] update rate limiter --- .../org/asteriskjava/pbx/agi/RateLimiter.java | 24 ++++++++++------ .../asteriskjava/pbx/agi/RateLimiterTest.java | 28 +++++++++++++++---- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java b/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java index 7ce6258c0..efef72b8e 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java +++ b/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java @@ -11,23 +11,27 @@ public class RateLimiter * * @param perSecond - number of 'acquire()' calls allowed per second, a call * to acquire() will block(sleep) if the per second limit is - * exceeded + * exceeded.
    + *
    + * NOTE: Max rate is 1000 per second */ - public RateLimiter(int perSecond) + public RateLimiter(double perSecond) { - step = ONE_THOUSAND_MILLIS / perSecond; + step = Math.max(1, (long) (ONE_THOUSAND_MILLIS / perSecond)); } void acquire() throws InterruptedException { // can't use Locker here, as Locker uses this class long delay; + long now; synchronized (this) { + now = System.currentTimeMillis(); delay = next; - if (next < System.currentTimeMillis()) + if (next < now) { - next = System.currentTimeMillis() + step; + next = now + step; } else { @@ -35,23 +39,25 @@ void acquire() throws InterruptedException } } - long now = System.currentTimeMillis(); long timeRemaining = delay - now; if (timeRemaining > 0) { + // Very important that this sleep does NOT happen in the + // synchronized block Thread.sleep(timeRemaining); } } - public boolean tryAcquire() throws InterruptedException + public boolean tryAcquire() { // can't use Locker here, as Locker uses this class synchronized (this) { - if (next < System.currentTimeMillis()) + long now = System.currentTimeMillis(); + if (next < now) { - next = System.currentTimeMillis() + step; + next = now + step; return true; } return false; diff --git a/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java b/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java index 7efefb819..cab6094c1 100644 --- a/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java +++ b/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java @@ -15,7 +15,7 @@ public void test() throws InterruptedException { long now = System.currentTimeMillis(); RateLimiter limiter = new RateLimiter(3); - for (int i = 0; i < 15; i++) + for (int i = 0; i < 7; i++) { limiter.acquire(); @@ -24,7 +24,7 @@ public void test() throws InterruptedException } // this should have taken around 5 seconds - assertTrue(System.currentTimeMillis() - now > 4000L); + assertTrue(System.currentTimeMillis() - now > 2000L); } @Test @@ -56,7 +56,7 @@ public void test2() throws InterruptedException new Thread(runner).start(); new Thread(runner).start(); - while (counter.intValue() < 15) + while (counter.intValue() < 9) { Thread.sleep(10); } @@ -64,7 +64,7 @@ public void test2() throws InterruptedException Thread.sleep(1000); // this should have taken around 5 seconds - assertTrue(System.currentTimeMillis() - now > 4000L); + assertTrue(System.currentTimeMillis() - now > 2500L); } @Test @@ -101,12 +101,30 @@ public void test3() throws InterruptedException new Thread(runner).start(); new Thread(runner).start(); - while (counter.intValue() < 15) + while (counter.intValue() < 9) { Thread.sleep(10); } stop.set(true); + // this should have taken around 5 seconds + assertTrue(System.currentTimeMillis() - now > 2500L); + } + + @Test + public void test4() throws InterruptedException + { + long now = System.currentTimeMillis(); + RateLimiter limiter = new RateLimiter(0.5); + for (int i = 0; i < 4; i++) + { + limiter.acquire(); + + System.out.println(System.currentTimeMillis() + " test4 " + i); + Thread.sleep(10); + } + // this should have taken around 5 seconds assertTrue(System.currentTimeMillis() - now > 4000L); } + } From ea8e507eff390575cc0ab5080882b06fb2ac18bf Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 17 Feb 2021 17:28:10 +1100 Subject: [PATCH 439/802] add warning for non diagnostic path --- .../java/org/asteriskjava/lock/Locker.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index 32a66c041..72c629fce 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -10,6 +10,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; +import org.asteriskjava.pbx.agi.RateLimiter; +import org.asteriskjava.pbx.util.LogTime; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -78,18 +80,26 @@ public interface LockCloser extends AutoCloseable public void close(); } + // Once every ten seconds max + private static RateLimiter warnRateLimiter = new RateLimiter(0.1); + private static LockCloser simpleLock(Lockable lockable) throws InterruptedException { + LogTime acquireTimer = new LogTime(); ReentrantLock lock = lockable.getInternalLock(); lock.lock(); - - return new LockCloser() + // lock acquired! + if (acquireTimer.timeTaken() > 1_000 && warnRateLimiter.tryAcquire()) { + logger.warn("Locks are being held for to long, you can enable lock diagnostics by calling Locker.enable()"); + } - @Override - public void close() + LogTime holdTimer = new LogTime(); + return () -> { + lock.unlock(); + if (holdTimer.timeTaken() > 500 && warnRateLimiter.tryAcquire()) { - lock.unlock(); + logger.warn("Locks are being held for to long, you can enable lock diagnostics by calling Locker.enable()"); } }; } @@ -143,7 +153,7 @@ public void close() lockable.addLockTotalHoldTime(holdTime); long averageHoldTime = lockable.getLockAverageHoldTime(); - if (waiters > 0 && holdTime > averageHoldTime * 2 || dumped) + if ((waiters > 0 && holdTime > averageHoldTime * 2) || dumped) { // some threads waited String message = "Lock held for (" + holdTime + "MS), " + waiters From dacc2193858b2b8a52ddfef22c849d28dfa7d901 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 18 Feb 2021 11:31:02 +1100 Subject: [PATCH 440/802] standardize on DateUtil --- .../org/asteriskjava/fastagi/GetDataScript.java | 2 +- .../backwardsCompatibility/bridge/BridgeState.java | 4 ++-- .../meetme/MeetmeCompatibility.java | 8 +++----- src/main/java/org/asteriskjava/pbx/CallImpl.java | 9 +++++---- .../asteriskjava/pbx/internal/asterisk/MeetmeRoom.java | 7 +++---- .../pbx/internal/asterisk/MeetmeRoomControl.java | 7 +++---- .../org/asteriskjava/pbx/internal/core/ChannelImpl.java | 3 +-- .../java/org/asteriskjava/util/internal/FileTrace.java | 6 +++--- 8 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/integrationtest/org/asteriskjava/fastagi/GetDataScript.java b/src/integrationtest/org/asteriskjava/fastagi/GetDataScript.java index d46c523ef..d6d3b1cb3 100644 --- a/src/integrationtest/org/asteriskjava/fastagi/GetDataScript.java +++ b/src/integrationtest/org/asteriskjava/fastagi/GetDataScript.java @@ -10,7 +10,7 @@ public class GetDataScript extends BaseAgiScript public void service(AgiRequest request, AgiChannel channel) throws AgiException { channel.streamFile("tt-monkeys"); - channel.sayDateTime(new Date().getTime()); + channel.sayDateTime(System.currentTimeMillis()); } public static void main(String[] args) throws Exception diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index e87e9a94a..1eddd264f 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -13,6 +12,7 @@ import org.asteriskjava.manager.event.BridgeEvent; import org.asteriskjava.manager.event.BridgeLeaveEvent; import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.util.DateUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -130,7 +130,7 @@ private BridgeEvent buildBridgeEvent(String bridgeState, List bridgeEvent.setChannel2(members.get(1).getChannel()); bridgeEvent.setBridgeState(bridgeState); - bridgeEvent.setDateReceived(new Date()); + bridgeEvent.setDateReceived(DateUtil.getDate()); return bridgeEvent; } diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/meetme/MeetmeCompatibility.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/meetme/MeetmeCompatibility.java index 51fd9096c..cd0dfd3cf 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/meetme/MeetmeCompatibility.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/meetme/MeetmeCompatibility.java @@ -1,7 +1,5 @@ package org.asteriskjava.manager.internal.backwardsCompatibility.meetme; -import java.util.Date; - import org.asteriskjava.manager.event.ConfbridgeEndEvent; import org.asteriskjava.manager.event.ConfbridgeJoinEvent; import org.asteriskjava.manager.event.ConfbridgeLeaveEvent; @@ -33,7 +31,7 @@ public ManagerEvent handleEvent(ManagerEvent event) else if (event instanceof ConfbridgeEndEvent) { MeetMeEndEvent endEvent = new MeetMeEndEvent(this); - endEvent.setDateReceived(new Date()); + endEvent.setDateReceived(event.getDateReceived()); endEvent.setMeetMe(((ConfbridgeEndEvent) event).getConference()); return endEvent; } @@ -47,7 +45,7 @@ else if (event instanceof ConfbridgeEndEvent) joinEvent.setUniqueId(((ConfbridgeJoinEvent) event).getUniqueId()); joinEvent.setChannel(((ConfbridgeJoinEvent) event).getChannel()); joinEvent.setMeetMe(((ConfbridgeJoinEvent) event).getBridgeName()); - joinEvent.setDateReceived(new Date()); + joinEvent.setDateReceived(event.getDateReceived()); return joinEvent; } @@ -59,7 +57,7 @@ else if (event instanceof ConfbridgeLeaveEvent) leaveEvent.setUniqueId(((ConfbridgeLeaveEvent) event).getUniqueId()); leaveEvent.setChannel(((ConfbridgeLeaveEvent) event).getChannel()); leaveEvent.setMeetMe(((ConfbridgeLeaveEvent) event).getConference()); - leaveEvent.setDateReceived(new Date()); + leaveEvent.setDateReceived(event.getDateReceived()); return leaveEvent; } diff --git a/src/main/java/org/asteriskjava/pbx/CallImpl.java b/src/main/java/org/asteriskjava/pbx/CallImpl.java index f88334549..309d24a6f 100644 --- a/src/main/java/org/asteriskjava/pbx/CallImpl.java +++ b/src/main/java/org/asteriskjava/pbx/CallImpl.java @@ -7,6 +7,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.asteriskjava.pbx.activities.BlindTransferActivity; +import org.asteriskjava.util.DateUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -132,7 +133,7 @@ public CallImpl(Channel originatingChannel, CallDirection direction) throws PBXE this._owner = OWNER.SELF; this._uniquecallID = CallImpl.global_call_identifier_index.incrementAndGet(); this._direction = direction; - this._callStarted = new Date(); + this._callStarted = DateUtil.getDate(); this.setOriginatingParty(originatingChannel); } @@ -143,7 +144,7 @@ public CallImpl(Channel originatingChannel, Channel acceptingChannel, CallDirect this._owner = OWNER.SELF; this._uniquecallID = CallImpl.global_call_identifier_index.incrementAndGet(); this._direction = direction; - this._callStarted = new Date(); + this._callStarted = DateUtil.getDate(); this.setOriginatingParty(originatingChannel); this.setAcceptingParty(acceptingChannel); @@ -154,7 +155,7 @@ public CallImpl(Channel agent, Channel callee) throws PBXException this._owner = OWNER.SELF; this._uniquecallID = CallImpl.global_call_identifier_index.incrementAndGet(); this._direction = CallDirection.OUTBOUND; - this._callStarted = new Date(); + this._callStarted = DateUtil.getDate(); this.setOriginatingParty(agent); this.setAcceptingParty(callee); @@ -490,7 +491,7 @@ public Channel getOriginatingParty() // { // if (this.holdStarted == null) // { - // this.holdStarted = new Date(); + // this.holdStarted = DateUtil.getDate(); // } // this._state = Call.CallState.TRANSFER; // } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java index 854051268..329c4a328 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.internal.asterisk; -import java.util.Date; import java.util.LinkedList; import org.asteriskjava.lock.Lockable; @@ -33,7 +32,7 @@ public class MeetmeRoom extends Lockable private boolean forceClose = false; - private Date lastUpdated = null; + private Long lastUpdated = null; private RoomOwner owner = null; @@ -91,7 +90,7 @@ public boolean getForceClose() return this.forceClose; } - public Date getLastUpdated() + public Long getLastUpdated() { return this.lastUpdated; } @@ -181,7 +180,7 @@ public void setInactive() public void setLastUpdated() { - this.lastUpdated = new Date(); + this.lastUpdated = System.currentTimeMillis(); } /** diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index 248539aa1..927fe020e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.internal.asterisk; -import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -123,11 +122,11 @@ public MeetmeRoom findAvailableRoom(RoomOwner newOwner) */ try { - final Date lastUpdated = room.getLastUpdated(); - final long now = new Date().getTime(); + final Long lastUpdated = room.getLastUpdated(); + final long now = System.currentTimeMillis(); if (lastUpdated != null) { - final long elapsedTime = now - lastUpdated.getTime(); + final long elapsedTime = now - lastUpdated; MeetmeRoomControl.logger.error( "room: " + room.getRoomNumber() + " count: " + count + " elapsed: " + elapsedTime); if ((elapsedTime > 1800000) && (room.getChannelCount() < 2)) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index 4ff574bd0..74060b348 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx.internal.core; -import java.util.Date; import java.util.concurrent.TimeUnit; import org.asteriskjava.pbx.AgiChannelActivityAction; @@ -458,7 +457,7 @@ public void setCallerId(final CallerID callerId) */ void startSweep() { - this._sweepStartTime = new Date().getTime(); + this._sweepStartTime = System.currentTimeMillis(); this._marked = false; } diff --git a/src/main/java/org/asteriskjava/util/internal/FileTrace.java b/src/main/java/org/asteriskjava/util/internal/FileTrace.java index bed1fa36a..36aa210dd 100644 --- a/src/main/java/org/asteriskjava/util/internal/FileTrace.java +++ b/src/main/java/org/asteriskjava/util/internal/FileTrace.java @@ -11,8 +11,8 @@ import java.nio.charset.StandardCharsets; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.Date; +import org.asteriskjava.util.DateUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; @@ -72,7 +72,7 @@ private String getFileName(Socket socket) { final StringBuilder sb = new StringBuilder(FILE_PREFIX); sb.append("_"); - sb.append(df.format(new Date())); + sb.append(df.format(DateUtil.getDate())); sb.append("_"); sb.append(socket.getLocalAddress().getHostAddress()); sb.append("_"); @@ -122,7 +122,7 @@ private void logException(IOException e) protected String format(String prefix, String s) { - final StringBuilder sb = new StringBuilder(df.format(new Date())); + final StringBuilder sb = new StringBuilder(df.format(DateUtil.getDate())); final String filler = String.format("%" + sb.length() + "s", ""); String[] lines = s.split("\n"); for (int i = 0; i < lines.length; i++) From bc53f4f82cda5eeb2dddb230cd1f64c9aaf0f3fc Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 18 Feb 2021 17:27:48 +1100 Subject: [PATCH 441/802] fix logging of lockup --- src/main/java/org/asteriskjava/lock/Locker.java | 2 +- .../java/org/asteriskjava/manager/internal/AsyncEventPump.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index 72c629fce..7dc4f2b7c 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -191,7 +191,7 @@ public static void dumpThread(Thread thread, String message) if (thread != null) { - StackTraceElement[] trace = new Exception().getStackTrace(); + StackTraceElement[] trace = thread.getStackTrace(); String dump = ""; diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index 0ea5d2c00..5fa3c39a1 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -143,7 +143,7 @@ public void stop() // still waiting for the poison to be consumed. if (queueSize == queue.size()) { - Locker.dumpThread(thread, "Queue thread is blocked here..."); + Locker.dumpThread(thread, "AsyncEventPump thread is blocked here..."); throw new RuntimeException("Failed to shutdown AsyncEventPump cleanly!"); } From bac689a809a2163c4f9ac58059f9a6ac95a10182 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 19 Feb 2021 09:58:02 +1100 Subject: [PATCH 442/802] fixes for lock checking and asynceventpump logging --- .../java/org/asteriskjava/lock/Locker.java | 12 ++++++--- .../manager/internal/AsyncEventPump.java | 26 +++++++++++-------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index 7dc4f2b7c..b92881995 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -31,6 +31,8 @@ public class Locker // reporting intervals private static final Map keepList = new HashMap<>(); + private static final RateLimiter waitRateLimiter = new RateLimiter(4); + public static LockCloser doWithLock(final Lockable lockable) { try @@ -118,11 +120,15 @@ private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedExc if (!lockable.isLockDumped() && lockable.getDumpRateLimit().tryAcquire()) { lockable.setLockDumped(true); - dumpThread(lockable.threadHoldingLock.get(), "Waiting on lock... blocked by..."); + dumpThread(lockable.threadHoldingLock.get(), + "Waiting on lock... blocked by... id:" + lockable.getLockableId()); } else { - logger.warn("waiting " + ctr); + if (waitRateLimiter.tryAcquire()) + { + logger.warn("waiting " + ctr + " id:" + lockable.getLockableId()); + } } lockable.setLockBlocked(true); } @@ -207,7 +213,7 @@ public static void dumpThread(Thread thread, String message) } else { - logger.error("Thread hasn't been set"); + logger.error("Thread hasn't been set: " + message); } } diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index 5fa3c39a1..8b719e292 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -34,6 +34,8 @@ public class AsyncEventPump implements Dispatcher, Runnable private final Thread thread; private volatile boolean terminated = false; + private final String name; + /** * @param owner: A weak reference to the owner is created, should it be * garbage collected then AsyncEventPump will shutdown. @@ -46,7 +48,8 @@ public class AsyncEventPump implements Dispatcher, Runnable { this.dispatcher = dispatcher; this.owner = new WeakReference<>(owner); - thread = new Thread(this, threadName + ":AsyncEventPump"); + name = threadName + ":AsyncEventPump"; + thread = new Thread(this, name); thread.start(); } @@ -55,6 +58,7 @@ public void run() { try { + logger.info("starting"); RateLimiter rateLimiter = new RateLimiter(2); while (!stop || !queue.isEmpty()) { @@ -121,13 +125,13 @@ else if (owner.get() == null) public void stop() { stop = true; - logger.info("Requesting AsyncEventPump to stop"); + logger.info(name + " Requesting AsyncEventPump to stop"); if (terminated) { - logger.warn("AsyncEventPump is already stopped"); + logger.warn(name + " AsyncEventPump is already stopped"); if (!queue.isEmpty()) { - logger.error("There are unprocessed events in the queue"); + logger.error(name + " There are unprocessed events in the queue"); } return; @@ -143,22 +147,22 @@ public void stop() // still waiting for the poison to be consumed. if (queueSize == queue.size()) { - Locker.dumpThread(thread, "AsyncEventPump thread is blocked here..."); - throw new RuntimeException("Failed to shutdown AsyncEventPump cleanly!"); + Locker.dumpThread(thread, name + " AsyncEventPump thread is blocked here..."); + throw new RuntimeException(name + " Failed to shutdown AsyncEventPump cleanly!"); } queueSize = queue.size(); - logger.info("Waiting for AsyncEventPump to Stop... "); + logger.info(name + " Waiting for AsyncEventPump to Stop... "); if (timer.timeTaken() > 60_000) { - throw new RuntimeException("Failed to shutdown AsyncEventPump cleanly!"); + throw new RuntimeException(name + " Failed to shutdown AsyncEventPump cleanly!"); } } } catch (InterruptedException e1) { - logger.error(e1); + logger.error(name + e1.getMessage()); } } @@ -170,7 +174,7 @@ public void dispatchResponse(ManagerResponse response, Integer requiredHandlingT { if (!queue.offer(new EventWrapper(response))) { - logger.error("Event queue is full, not processing ManagerResponse " + response); + logger.error(name + " Event queue is full, not processing ManagerResponse " + response); } } @@ -182,7 +186,7 @@ public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) { if (!queue.offer(new EventWrapper(event))) { - logger.error("Event queue is full, not processing ManagerEvent " + event); + logger.error(name + " Event queue is full, not processing ManagerEvent " + event); } } From eed21b69fdcf4e570c9a4228cd02bb07ad6db7ae Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 19 Feb 2021 10:01:59 +1100 Subject: [PATCH 443/802] improve logging --- src/main/java/org/asteriskjava/lock/Locker.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index b92881995..38c31f4f3 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -112,11 +112,9 @@ private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedExc int offset = lockable.addLockRequested(); long waitStart = System.currentTimeMillis(); - int ctr = 0; ReentrantLock lock = lockable.getInternalLock(); while (!lock.tryLock(100, TimeUnit.MILLISECONDS)) { - ctr++; if (!lockable.isLockDumped() && lockable.getDumpRateLimit().tryAcquire()) { lockable.setLockDumped(true); @@ -127,7 +125,8 @@ private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedExc { if (waitRateLimiter.tryAcquire()) { - logger.warn("waiting " + ctr + " id:" + lockable.getLockableId()); + long elapsed = System.currentTimeMillis() - waitStart; + logger.warn("waiting " + elapsed + "(MS) id:" + lockable.getLockableId()); } } lockable.setLockBlocked(true); From 541a551674cf2684c53372f45be3d99d516ec2c3 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 19 Feb 2021 11:02:43 +1100 Subject: [PATCH 444/802] improve logging --- .../manager/internal/AsyncEventPump.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index 8b719e292..9939f1aa4 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -69,11 +69,12 @@ public void run() { if (wrapper.timer.timeTaken() > MAX_SAFE_EVENT_AGE && rateLimiter.tryAcquire()) { - logger.warn("The following message will only appear once per second!\n" - + "Event being dispatched " + wrapper.timer.timeTaken() + logger.warn("The following message will only appear once per second!\n" + "Event dispatched " + + wrapper.timer.timeTaken() + " MS after arriving, your ManagerEvent handlers are too slow!\n" + "You should also check for Garbage Collection issues.\n" + "There are " + queue.size() - + " events waiting to be processed in the queue.\n"); + + " events waiting to be processed in the queue.\n" + "Event was " + + wrapper.getPayloadAsString()); } // assume we need to process all queued events in @@ -203,6 +204,20 @@ private static class EventWrapper poison = new CountDownLatch(1); } + public String getPayloadAsString() + { + if (response != null) + { + return response.toString(); + } + else if (event != null) + { + return event.toString(); + } + return "Poison"; + + } + EventWrapper(ManagerResponse response) { this.response = response; From 2a2c3c3882e46a3c25ee88fe096ebf18fea1596a Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 24 Feb 2021 09:34:06 +1100 Subject: [PATCH 445/802] fix comment --- src/main/java/org/asteriskjava/lock/Locker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index 38c31f4f3..49549a9b4 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -27,7 +27,7 @@ public class Locker private static final Object sync = new Object(); - // keep references to LockStats so the WeakHashMap won't remove them between + // keep references to Lockables so they can't be garbage collected between // reporting intervals private static final Map keepList = new HashMap<>(); From 0011de0c9e1691ccf94c8311732312ef0b44e3b3 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 24 Feb 2021 11:45:50 +1100 Subject: [PATCH 446/802] cleanup event pump shutdown code --- src/main/java/org/asteriskjava/lock/Locker.java | 9 ++++++++- .../asteriskjava/manager/internal/AsyncEventPump.java | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index 49549a9b4..f80040f74 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -208,7 +208,14 @@ public static void dumpThread(Thread thread, String message) dump += '\n'; } logger.error(message); - logger.error(dump); + if (dump.length() > 0) + { + logger.error(dump); + } + else + { + logger.error("Unable to create dump, thread seems to have exited."); + } } else { diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index 9939f1aa4..2c2734f20 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -125,7 +125,6 @@ else if (owner.get() == null) */ public void stop() { - stop = true; logger.info(name + " Requesting AsyncEventPump to stop"); if (terminated) { @@ -139,6 +138,7 @@ public void stop() } EventWrapper poisonWrapper = new EventWrapper(); queue.add(poisonWrapper); + stop = true; LogTime timer = new LogTime(); try { @@ -148,7 +148,10 @@ public void stop() // still waiting for the poison to be consumed. if (queueSize == queue.size()) { - Locker.dumpThread(thread, name + " AsyncEventPump thread is blocked here..."); + if (!terminated) + { + Locker.dumpThread(thread, name + " AsyncEventPump thread is blocked here..."); + } throw new RuntimeException(name + " Failed to shutdown AsyncEventPump cleanly!"); } From de588023989fe9fde6be0318c854c083ad0bcd3c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 3 Mar 2021 14:48:18 +1100 Subject: [PATCH 447/802] add guava RateLimiter and better suppress unneeded slow processing messages --- pom.xml | 5 + .../java/org/asteriskjava/lock/Lockable.java | 5 +- .../java/org/asteriskjava/lock/Locker.java | 7 +- .../manager/internal/AsyncEventPump.java | 5 +- .../manager/internal/ManagerReaderImpl.java | 43 +++++- .../org/asteriskjava/pbx/agi/ActivityAgi.java | 17 +-- .../org/asteriskjava/pbx/agi/RateLimiter.java | 66 --------- .../asteriskjava/pbx/agi/RateLimiterTest.java | 130 ------------------ 8 files changed, 59 insertions(+), 219 deletions(-) delete mode 100644 src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java delete mode 100644 src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java diff --git a/pom.xml b/pom.xml index a7f0972ac..e98a9d458 100644 --- a/pom.xml +++ b/pom.xml @@ -167,6 +167,11 @@ 4.13.1 test + + com.google.guava + guava + 30.1-jre + org.slf4j slf4j-api diff --git a/src/main/java/org/asteriskjava/lock/Lockable.java b/src/main/java/org/asteriskjava/lock/Lockable.java index 88576ad25..565b4e426 100644 --- a/src/main/java/org/asteriskjava/lock/Lockable.java +++ b/src/main/java/org/asteriskjava/lock/Lockable.java @@ -6,7 +6,8 @@ import java.util.concurrent.locks.ReentrantLock; import org.asteriskjava.lock.Locker.LockCloser; -import org.asteriskjava.pbx.agi.RateLimiter; + +import com.google.common.util.concurrent.RateLimiter; public class Lockable { @@ -21,7 +22,7 @@ public class Lockable private volatile boolean dumped = false; private volatile boolean blocked = false; - private final RateLimiter rateLimiter = new RateLimiter(4); + private final RateLimiter rateLimiter = RateLimiter.create(4); private final static AtomicLong seed = new AtomicLong(); private final long lockableId = seed.incrementAndGet(); diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index f80040f74..d9bd94eb7 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -10,11 +10,12 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; -import org.asteriskjava.pbx.agi.RateLimiter; import org.asteriskjava.pbx.util.LogTime; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import com.google.common.util.concurrent.RateLimiter; + public class Locker { @@ -31,7 +32,7 @@ public class Locker // reporting intervals private static final Map keepList = new HashMap<>(); - private static final RateLimiter waitRateLimiter = new RateLimiter(4); + private static final RateLimiter waitRateLimiter = RateLimiter.create(4); public static LockCloser doWithLock(final Lockable lockable) { @@ -83,7 +84,7 @@ public interface LockCloser extends AutoCloseable } // Once every ten seconds max - private static RateLimiter warnRateLimiter = new RateLimiter(0.1); + private static RateLimiter warnRateLimiter = RateLimiter.create(0.1); private static LockCloser simpleLock(Lockable lockable) throws InterruptedException { diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index 2c2734f20..7dd841ee9 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -8,11 +8,12 @@ import org.asteriskjava.lock.Locker; import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.response.ManagerResponse; -import org.asteriskjava.pbx.agi.RateLimiter; import org.asteriskjava.pbx.util.LogTime; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import com.google.common.util.concurrent.RateLimiter; + /** * AsyncEventPump delivers events and responses to a Dispatcher without blocking * the thread which is producing the events and responses. AsyncEventPump also @@ -59,7 +60,7 @@ public void run() try { logger.info("starting"); - RateLimiter rateLimiter = new RateLimiter(2); + RateLimiter rateLimiter = RateLimiter.create(2); while (!stop || !queue.isEmpty()) { try diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java index d251d0772..2a707db39 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java @@ -35,6 +35,8 @@ import org.asteriskjava.util.LogFactory; import org.asteriskjava.util.SocketConnectionFacade; +import com.google.common.util.concurrent.RateLimiter; + /** * Default implementation of the ManagerReader interface. * @@ -144,6 +146,8 @@ public void expectResponseClass(String internalActionId, Class< ? extends Manage */ public void run() { + long timeOfLastEvent = 0; + long reserve = 0; final Map buffer = new HashMap<>(); String line; @@ -156,6 +160,8 @@ public void run() this.dead = false; AsyncEventPump dispatcher = new AsyncEventPump(this, rawDispatcher, Thread.currentThread().getName()); + long slowEventThresholdMs = 10; + RateLimiter slowEventLogLimiter = RateLimiter.create(4); try { // main loop @@ -270,10 +276,41 @@ else if (buffer.containsKey("response")) } buffer.clear(); - if (timer.timeTaken() > 50) + + // some math to determine if events are being processed + // slowly + long elapsed = timer.timeTaken(); + long now = System.currentTimeMillis(); + long add = now - timeOfLastEvent; + + // double the elapsed time, this allows 50% slack. Also note + // that we + // would never be able to exhaust the reserve if we don't + // artificially increase the elapsed time. I'd have probably + // gone for 1.3 but I am trying to avoid floating point math + reserve = (reserve + add) - (elapsed * 2); + + // don't allow reserve to exceed 500 ms + reserve = Math.min(500, reserve); + + // don't allow reserve to go negative, otherwise we might + // accrue a large debt + reserve = Math.max(0, reserve); + timeOfLastEvent = now; + + // check if the event was slow to build and dispatch + if (elapsed > slowEventThresholdMs) { - logger.warn("(This is normal during JVM warmup) Slow processing of event " + timer.timeTaken() + "\n" - + cause); + // check for to many slow events this second. + if (reserve <= 0) + { + // check we haven't already logged this to often + if (slowEventLogLimiter.tryAcquire()) + { + logger.warn("(This is normal during JVM warmup) Slow processing of event " + elapsed + "\n" + + cause); + } + } } } } diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index 58648c0f7..ce31fcc47 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -18,6 +18,8 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import com.google.common.util.concurrent.RateLimiter; + public abstract class ActivityAgi extends ServiceAgiScriptImpl { @@ -111,26 +113,15 @@ public void channelHangup(Channel channel, Integer cause, String causeText) } boolean isAlive = true; - RateLimiter slowRateLimiter = new RateLimiter(2); - RateLimiter fastRateLimiter = new RateLimiter(10); + RateLimiter slowRateLimiter = RateLimiter.create(2); while (!action.isDisconnect(this) && isAlive) { - AgiChannelActivityAction oldAction = action; action.execute(this.channel, channelProxy); action = channelProxy.getCurrentActivityAction(); logger.debug("Action for proxy " + channelProxy + " is " + action.getClass().getSimpleName()); isAlive = checkChannelIsStillUp(); - if (oldAction == action) - { - // action didn't change, lets not loop to fast - slowRateLimiter.acquire(); - } - else - { - // action changed, don't delay long - fastRateLimiter.acquire(); - } + slowRateLimiter.acquire(); } } diff --git a/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java b/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java deleted file mode 100644 index efef72b8e..000000000 --- a/src/main/java/org/asteriskjava/pbx/agi/RateLimiter.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.asteriskjava.pbx.agi; - -public class RateLimiter -{ - private static final long ONE_THOUSAND_MILLIS = 1000L; - long next = 0; - private final long step; - - /** - * thread safe! - * - * @param perSecond - number of 'acquire()' calls allowed per second, a call - * to acquire() will block(sleep) if the per second limit is - * exceeded.
    - *
    - * NOTE: Max rate is 1000 per second - */ - public RateLimiter(double perSecond) - { - step = Math.max(1, (long) (ONE_THOUSAND_MILLIS / perSecond)); - } - - void acquire() throws InterruptedException - { - // can't use Locker here, as Locker uses this class - long delay; - long now; - synchronized (this) - { - now = System.currentTimeMillis(); - delay = next; - if (next < now) - { - next = now + step; - } - else - { - next += step; - } - } - - long timeRemaining = delay - now; - if (timeRemaining > 0) - { - // Very important that this sleep does NOT happen in the - // synchronized block - Thread.sleep(timeRemaining); - } - - } - - public boolean tryAcquire() - { - // can't use Locker here, as Locker uses this class - synchronized (this) - { - long now = System.currentTimeMillis(); - if (next < now) - { - next = now + step; - return true; - } - return false; - } - } -} diff --git a/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java b/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java deleted file mode 100644 index cab6094c1..000000000 --- a/src/test/java/org/asteriskjava/pbx/agi/RateLimiterTest.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.asteriskjava.pbx.agi; - -import static org.junit.Assert.assertTrue; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; - -import org.junit.Test; - -public class RateLimiterTest -{ - - @Test - public void test() throws InterruptedException - { - long now = System.currentTimeMillis(); - RateLimiter limiter = new RateLimiter(3); - for (int i = 0; i < 7; i++) - { - limiter.acquire(); - - System.out.println(System.currentTimeMillis() + " test1 " + i); - Thread.sleep(10); - } - - // this should have taken around 5 seconds - assertTrue(System.currentTimeMillis() - now > 2000L); - } - - @Test - public void test2() throws InterruptedException - { - long now = System.currentTimeMillis(); - RateLimiter limiter = new RateLimiter(3); - AtomicLong counter = new AtomicLong(); - AtomicBoolean stop = new AtomicBoolean(false); - Runnable runner = () -> { - for (int i = 0; i < 15 && !stop.get(); i++) - { - try - { - limiter.acquire(); - System.out.println(System.currentTimeMillis() + " test2 " + i); - counter.getAndIncrement(); - Thread.sleep(10); - } - catch (InterruptedException e) - { - e.printStackTrace(); - } - - } - }; - - new Thread(runner).start(); - new Thread(runner).start(); - new Thread(runner).start(); - - while (counter.intValue() < 9) - { - Thread.sleep(10); - } - stop.set(true); - Thread.sleep(1000); - - // this should have taken around 5 seconds - assertTrue(System.currentTimeMillis() - now > 2500L); - } - - @Test - public void test3() throws InterruptedException - { - long now = System.currentTimeMillis(); - RateLimiter limiter = new RateLimiter(3); - AtomicLong counter = new AtomicLong(); - AtomicBoolean stop = new AtomicBoolean(false); - - Runnable runner = () -> { - for (int i = 0; i < 15 && !stop.get();) - { - try - { - if (limiter.tryAcquire()) - { - i++; - System.out.println(System.currentTimeMillis() + " test3 " + i); - counter.getAndIncrement(); - - } - Thread.sleep(10); - } - catch (InterruptedException e) - { - e.printStackTrace(); - } - - } - }; - - new Thread(runner).start(); - new Thread(runner).start(); - new Thread(runner).start(); - - while (counter.intValue() < 9) - { - Thread.sleep(10); - } - stop.set(true); - // this should have taken around 5 seconds - assertTrue(System.currentTimeMillis() - now > 2500L); - } - - @Test - public void test4() throws InterruptedException - { - long now = System.currentTimeMillis(); - RateLimiter limiter = new RateLimiter(0.5); - for (int i = 0; i < 4; i++) - { - limiter.acquire(); - - System.out.println(System.currentTimeMillis() + " test4 " + i); - Thread.sleep(10); - } - - // this should have taken around 5 seconds - assertTrue(System.currentTimeMillis() - now > 4000L); - } - -} From 4c2b15ff594d1f99ca9f5223cdde374bf9238a59 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 3 Mar 2021 14:49:57 +1100 Subject: [PATCH 448/802] add guava to gradle to --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index af4d8d86d..ecdeb7043 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,7 @@ dependencies { compile group: 'log4j', name: 'log4j', version:'1.2.17' compile group: 'org.apache.commons', name: 'commons-lang3', version:'3.1' compile group: 'org.slf4j', name: 'slf4j-api', version:'1.7.9' + compile group: 'com.google.guava', name: 'guava', version:'30.1-jre' testCompile group: 'org.easymock', name: 'easymock', version:'3.3' testCompile group: 'junit', name: 'junit', version:'4.12' testCompile group: 'ch.qos.logback', name: 'logback-classic', version:'1.1.2' From 87cb36f150bda4c3fd73d4b302d6381a90db91c0 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 3 Mar 2021 15:10:45 +1100 Subject: [PATCH 449/802] clean up --- src/main/java/org/asteriskjava/lock/Locker.java | 3 ++- .../manager/internal/ManagerConnectionImpl.java | 3 --- .../manager/internal/ProtocolIdentifierWrapper.java | 8 ++------ 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index d9bd94eb7..157116335 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -102,7 +102,8 @@ private static LockCloser simpleLock(Lockable lockable) throws InterruptedExcept lock.unlock(); if (holdTimer.timeTaken() > 500 && warnRateLimiter.tryAcquire()) { - logger.warn("Locks are being held for to long, you can enable lock diagnostics by calling Locker.enable()"); + logger.warn("Locks are being held for to long (" + holdTimer.timeTaken() + + "ms), you can enable lock diagnostics by calling Locker.enable()"); } }; } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index ffe8b51d9..5fb9749ca 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1473,10 +1473,7 @@ private void setProtocolIdentifier(final String identifier) { logger.warn("Unsupported protocol version '" + identifier + "'. Use at your own risk."); } - protocolIdentifier.setValue(identifier); - protocolIdentifier.countDown(); - } /** diff --git a/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java b/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java index 8a4ab08e3..21fea6fd4 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java +++ b/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java @@ -5,7 +5,7 @@ class ProtocolIdentifierWrapper { - private CountDownLatch latch = new CountDownLatch(1); + private volatile CountDownLatch latch = new CountDownLatch(1); private String value; void reset() @@ -24,14 +24,10 @@ String getValue() return value; } - void countDown() - { - latch.countDown(); - } - public void setValue(String identifier) { value = identifier; + latch.countDown(); } } From d7f5a642aafa51702ce9d16f95ac5fbce904c49d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 3 Mar 2021 15:21:46 +1100 Subject: [PATCH 450/802] clean up --- src/main/java/org/asteriskjava/lock/Locker.java | 14 +++++++++++--- .../java/org/asteriskjava/pbx/util/LogTime.java | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index 157116335..d63d6d723 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -86,6 +86,8 @@ public interface LockCloser extends AutoCloseable // Once every ten seconds max private static RateLimiter warnRateLimiter = RateLimiter.create(0.1); + private static final LogTime startTime = new LogTime(); + private static LockCloser simpleLock(Lockable lockable) throws InterruptedException { LogTime acquireTimer = new LogTime(); @@ -94,16 +96,22 @@ private static LockCloser simpleLock(Lockable lockable) throws InterruptedExcept // lock acquired! if (acquireTimer.timeTaken() > 1_000 && warnRateLimiter.tryAcquire()) { - logger.warn("Locks are being held for to long, you can enable lock diagnostics by calling Locker.enable()"); + logger.warn("Locks are being held for to long, waited " + acquireTimer.timeTaken() + + "ms, you can enable lock diagnostics by calling Locker.enable()"); } LogTime holdTimer = new LogTime(); return () -> { lock.unlock(); + if (holdTimer.timeTaken() > 500 && warnRateLimiter.tryAcquire()) { - logger.warn("Locks are being held for to long (" + holdTimer.timeTaken() - + "ms), you can enable lock diagnostics by calling Locker.enable()"); + // don't start warning for the first 10 seconds + if (startTime.timeTaken() > 10_000) + { + logger.warn("Locks are being held for to long (" + holdTimer.timeTaken() + + "ms), you can enable lock diagnostics by calling Locker.enable()"); + } } }; } diff --git a/src/main/java/org/asteriskjava/pbx/util/LogTime.java b/src/main/java/org/asteriskjava/pbx/util/LogTime.java index 26db60284..a20fa42c1 100644 --- a/src/main/java/org/asteriskjava/pbx/util/LogTime.java +++ b/src/main/java/org/asteriskjava/pbx/util/LogTime.java @@ -9,7 +9,7 @@ */ public class LogTime { - public Long dStartTime = System.currentTimeMillis(); + private final Long dStartTime = System.currentTimeMillis(); /** * @return time taken from construction until now in milliseconds From 0d139a4ddaf53a850ce75620afb1573a64bb0611 Mon Sep 17 00:00:00 2001 From: jefaokpta Date: Wed, 3 Mar 2021 12:05:46 -0300 Subject: [PATCH 451/802] add InvalidAccountId event --- .../manager/AbstractManagerEventListener.java | 28 ++--- .../manager/event/InvalidAccountId.java | 100 ++++++++++++++++++ 2 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 4a28bb58e..57c71d230 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -764,23 +764,27 @@ public void handleEvent(UnpausedEvent event) public void handleEvent(VarSetEvent event) { } - - public void handleEvent(EndpointDetail event) - { + + public void handleEvent(EndpointDetail event) + { } - - public void handleEvent(AorDetail event) - { + + public void handleEvent(AorDetail event) + { } - public void handleEvent(ContactStatusDetail event) - { + public void handleEvent(ContactStatusDetail event) + { } - - public void handleEvent(EndpointDetailComplete event) - { + + public void handleEvent(EndpointDetailComplete event) + { } - + + public void handleEvent(InvalidAccountId event) + { + } + /** * Dispatches to the appropriate handleEvent(...) method. * diff --git a/src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java b/src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java new file mode 100644 index 000000000..7cc43affd --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java @@ -0,0 +1,100 @@ +package org.asteriskjava.manager.event; + +/** + * @author Jefferson Alves Reis (jefaokpta) < jefaokpta@hotmail.com > + * Date: 2021-03-03 + */ + +public class InvalidAccountId extends ManagerEvent { + /** + * + */ + private static final long serialVersionUID = 1L; + private String severity; + private Integer eventVersion; + private String eventtv; + private String sessionId; + private String localAddress; + private String accountId; + private String service; + private String remoteAddress; + private String event; + + public InvalidAccountId(Object source) { super(source); } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public Integer getEventVersion() { + return eventVersion; + } + + public void setEventVersion(Integer eventVersion) { + this.eventVersion = eventVersion; + } + + public String getEventtv() { + return eventtv; + } + + public void setEventtv(String eventtv) { + this.eventtv = eventtv; + } + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + public String getLocalAddress() { + return localAddress; + } + + public void setLocalAddress(String localAddress) { + this.localAddress = localAddress; + } + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public String getRemoteAddress() { + return remoteAddress; + } + + public void setRemoteAddress(String remoteAddress) { + this.remoteAddress = remoteAddress; + } + + public String getEvent() { + return event; + } + + public void setEvent(String event) { + this.event = event; + } +} From 0a3afc0ecadf105ed9166411c51244bbb735d412 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 4 Mar 2021 16:23:53 +1100 Subject: [PATCH 452/802] remove duplicate setters --- .../manager/event/DialBeginEvent.java | 29 ++++++++----------- .../manager/event/StatusCompleteEvent.java | 7 +---- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/DialBeginEvent.java b/src/main/java/org/asteriskjava/manager/event/DialBeginEvent.java index f4f3601be..09e998455 100644 --- a/src/main/java/org/asteriskjava/manager/event/DialBeginEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DialBeginEvent.java @@ -4,15 +4,15 @@ public class DialBeginEvent extends DialEvent { /** - * - */ + * + */ private static final long serialVersionUID = 1L; private String language; private String destlanguage; private String destAccountCode; private String linkedId; private String destLinkedId; - + private String accountcode; public DialBeginEvent(Object source) @@ -56,11 +56,6 @@ public String getDestlanguage() return destlanguage; } - public void setDestlanguage(String destlanguage) - { - this.destlanguage = destlanguage; - } - public String getLinkedId() { return linkedId; @@ -81,14 +76,14 @@ public void setDestLinkedId(String destLinkedId) this.destLinkedId = destLinkedId; } - public String getAccountcode() - { - return accountcode; - } + public String getAccountcode() + { + return accountcode; + } + + public void setAccountcode(String accountcode) + { + this.accountcode = accountcode; + } - public void setAccountcode(String accountcode) - { - this.accountcode = accountcode; - } - } diff --git a/src/main/java/org/asteriskjava/manager/event/StatusCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/StatusCompleteEvent.java index ac0763832..208f978af 100644 --- a/src/main/java/org/asteriskjava/manager/event/StatusCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/StatusCompleteEvent.java @@ -72,11 +72,6 @@ public Integer getListItems() return listItems; } - public void setListitems(Integer listItems) - { - this.listItems = listItems; - } - public String getEventList() { return eventList; @@ -91,5 +86,5 @@ public void setListItems(Integer listItems) { this.listItems = listItems; } - + } From dea49ee62cfcea4fba6ece91d9a19553ce978e6c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 10 Mar 2021 14:37:31 +1100 Subject: [PATCH 453/802] cache reflection of event classes --- .../org/asteriskjava/util/ReflectionUtil.java | 58 ++++++++++++++++--- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/ReflectionUtil.java b/src/main/java/org/asteriskjava/util/ReflectionUtil.java index ca9d4f5f9..f778e6296 100644 --- a/src/main/java/org/asteriskjava/util/ReflectionUtil.java +++ b/src/main/java/org/asteriskjava/util/ReflectionUtil.java @@ -33,6 +33,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -98,6 +99,27 @@ else if (methodName.startsWith("is")) return accessors; } + private final static ConcurrentHashMap, Map> setterMap = new ConcurrentHashMap<>(); + + /** + * The main benefit here is that there will not be repeated errors when + * inspecting classes for setters on every single Event being processed. + *
    + *
    + * While this method adds caching which is 100 times faster, the time + * Benefit is largely insignificant as the execution time was already very + * fast. + * + * @param clazz + * @return + */ + public static Map getSetters(Class< ? > clazz) + { + return setterMap.computeIfAbsent(clazz, (c) -> { + return getSettersInternal(c); + }); + } + /** * Returns a Map of setter methods of the given class. *

    @@ -109,7 +131,7 @@ else if (methodName.startsWith("is")) * @param clazz the class to return the setters for * @return a Map of attributes and their accessor methods (setters) */ - public static Map getSetters(Class< ? > clazz) + private static Map getSettersInternal(Class< ? > clazz) { final Map accessors = new HashMap<>(); final Method[] methods = clazz.getMethods(); @@ -117,9 +139,7 @@ public static Map getSetters(Class< ? > clazz) for (Method method : methods) { String name; - String methodName; - - methodName = method.getName(); + String methodName = method.getName(); if (!methodName.startsWith("set")) { continue; @@ -131,11 +151,35 @@ public static Map getSetters(Class< ? > clazz) continue; } - // ok seems to be an accessor + // OK seems to be an setter name = methodName.substring("set".length()).toLowerCase(Locale.US); - accessors.put(name, method); - } + // if an event class implements a setter that exists in + // ManagerEvent, then prefer the setter from the extending class + Method existing = accessors.get(name); + if (existing != null) + { + logger.warn("multiple setters (case insensitive) exist for " + name + " on class(es) " + + existing.getDeclaringClass() + " and " + method.getDeclaringClass()); + } + if (existing == null) + { + // we don't have a mapping for this setter so add it. + accessors.put(name, method); + } + else if (method.getDeclaringClass().isAssignableFrom(existing.getDeclaringClass())) + { + // we already have a mapping for this setter, but this one is + // from an extending class so replace it. + logger.warn("Preferring setter from extending class " + existing + " -> " + method); + accessors.put(name, method); + } + else + { + // there is already a mapping for this setter from class + logger.warn("Preferring setter from extending class " + method + " -> " + existing); + } + } return accessors; } From ff5c92d16531b253103e28b2a0f4daa4f17e0e72 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 19 Mar 2021 10:52:40 +1100 Subject: [PATCH 454/802] update dcli version --- pubspec.lock | 185 ++++++++++++++++++++++++++++---------------- pubspec.yaml | 8 +- triggerRelease.dart | 4 +- 3 files changed, 123 insertions(+), 74 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 4d600c6ee..c0143ffb5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,229 +1,278 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.2" args: dependency: "direct main" description: name: args url: "https://pub.dartlang.org" source: hosted - version: "1.5.2" + version: "2.0.0" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.0" - boolean_selector: + version: "2.5.0" + basic_utils: dependency: transitive description: - name: boolean_selector + name: basic_utils url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "3.0.0-nullsafety.1" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" + version: "1.2.0" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.12" + version: "1.15.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" csv: dependency: transitive description: name: csv url: "https://pub.dartlang.org" source: hosted - version: "4.0.3" - dshell: + version: "5.0.0" + dcli: dependency: "direct main" description: - name: dshell + name: dcli url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "0.51.5" equatable: dependency: transitive description: name: equatable url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "2.0.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" file: dependency: transitive description: name: file url: "https://pub.dartlang.org" source: hosted - version: "5.1.0" - file_utils: + version: "6.1.0" + glob: dependency: transitive description: - name: file_utils + name: glob url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" - globbing: + version: "2.0.0" + http: dependency: transitive description: - name: globbing + name: http url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" - intl: + version: "0.13.0" + http_parser: dependency: transitive description: - name: intl + name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "0.16.1" - io: + version: "4.0.0" + ini: dependency: transitive description: - name: io + name: ini url: "https://pub.dartlang.org" source: hosted - version: "0.3.3" - logger: + version: "2.1.0-beta" + json_annotation: dependency: transitive description: - name: logger + name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "0.8.3" + version: "4.0.0" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.10" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" - mockito: + version: "1.3.0" + path: + dependency: "direct main" + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + pedantic: dependency: transitive description: - name: mockito + name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "4.1.1" - money2: + version: "1.11.0" + pointycastle: dependency: transitive description: - name: money2 + name: pointycastle url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" - path: - dependency: "direct main" + version: "3.0.0-nullsafety.2" + posix: + dependency: transitive description: - name: path + name: posix url: "https://pub.dartlang.org" source: hosted - version: "1.6.4" + version: "2.0.0" pub_semver: dependency: transitive description: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "1.4.3" - pubspec: + version: "2.0.0" + pubspec2: dependency: transitive description: - name: pubspec + name: pubspec2 url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "1.0.0" quiver: dependency: transitive description: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.1.2+1" - recase: + version: "3.0.0" + random_string: dependency: transitive description: - name: recase + name: random_string url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "2.2.0-nullsafety" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.6.0" + version: "1.8.1" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" + version: "1.10.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" - test_api: + version: "1.2.0" + typed_data: dependency: transitive description: - name: test_api + name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "0.2.14" + version: "1.3.0" uri: dependency: transitive description: name: uri url: "https://pub.dartlang.org" source: hosted - version: "0.11.3+1" - utf: + version: "1.0.0" + uuid: + dependency: transitive + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + validators2: + dependency: transitive + description: + name: validators2 + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + vin_decoder: dependency: transitive description: - name: utf + name: vin_decoder url: "https://pub.dartlang.org" source: hosted - version: "0.9.0+5" + version: "0.2.0-nullsafety" yaml: dependency: transitive description: name: yaml url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "3.1.0" sdks: - dart: ">=2.7.0 <3.0.0" + dart: ">=2.12.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index e3067123e..23958b051 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,11 +1,11 @@ name: asterisk_java_installer version: 1.0.0 environment: - sdk: '>=2.7.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: - dshell: ^1.4.3 - args: ^1.5.2 - path: ^1.6.4 + dcli: '>=0.51.1' + args: ^2.0.0 + path: ^1.8.0 diff --git a/triggerRelease.dart b/triggerRelease.dart index 831ff1096..22aec3a21 100755 --- a/triggerRelease.dart +++ b/triggerRelease.dart @@ -1,7 +1,7 @@ -#! /usr/bin/env dshell +#! /usr/bin/env dcli import 'dart:io'; -import 'package:dshell/dshell.dart'; +import 'package:dcli/dcli.dart'; /// comment From 7f0cfba734a23fe6f4d46f641a25a90c1b42a5c5 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 19 Mar 2021 10:59:02 +1100 Subject: [PATCH 455/802] update for dcli changes --- triggerRelease.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/triggerRelease.dart b/triggerRelease.dart index 22aec3a21..cc95b94af 100755 --- a/triggerRelease.dart +++ b/triggerRelease.dart @@ -1,4 +1,5 @@ #! /usr/bin/env dcli + import 'dart:io'; import 'package:dcli/dcli.dart'; @@ -6,10 +7,10 @@ import 'package:dcli/dcli.dart'; /// comment void main() { - int major; - int minor; + int major = 0; + int minor = 0; int rev = 0; - var dir = dirname(Settings().scriptPath); + var dir = dirname(Script.current.pathToScript); print(dir); read(join(dir, "pom.xml")).forEach((line) { if (line.contains("")) { @@ -25,7 +26,7 @@ void main() { }); var postFix = ""; - if (confirm(prompt: "Is this a SNAPSHOT release (y/n)?")) { + if (confirm("Is this a SNAPSHOT release (y/n)?")) { postFix = "-SNAPSHOT"; rev++; } else { From 7126f6e9124fd86da21b2d4cf6481b1c0cd222b3 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 19 Mar 2021 10:59:15 +1100 Subject: [PATCH 456/802] for version 3.11.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e98a9d458..ca74bf7b5 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.10.0 + 3.11.0 UTF-8 From 8d8a0cee47282733cf88de4a41ec78757ea6c96a Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 22 Mar 2021 10:46:04 +1100 Subject: [PATCH 457/802] update junit version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ca74bf7b5..209789b0b 100644 --- a/pom.xml +++ b/pom.xml @@ -164,7 +164,7 @@ junit junit - 4.13.1 + 4.13.2 test From 830aafcdc603f3bdf7268ab4ce0248e741d58076 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 8 Apr 2021 15:39:38 +1000 Subject: [PATCH 458/802] reduce logging --- .../backwardsCompatibility/bridge/BridgeState.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index 1eddd264f..ec0d6727b 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -13,8 +13,6 @@ import org.asteriskjava.manager.event.BridgeLeaveEvent; import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; /** * Track the current members of a bridge, emmitting BridgeEvents when 2 members @@ -24,7 +22,7 @@ */ class BridgeState { - private final Log logger = LogFactory.getLog(getClass()); + // private final Log logger = LogFactory.getLog(getClass()); private static final BridgeEnterEventComparator BRIDGE_ENTER_EVENT_COMPARATOR = new BridgeEnterEventComparator(); private static final String HOLDING_BRIDGE_TECH = "holding_bridge"; @@ -69,11 +67,12 @@ ManagerEvent addMember(BridgeEnterEvent event) return null; } - logger.info("Members size " + remaining.size() + " " + event); + // logger.info("Members size " + remaining.size() + " " + event); BridgeEvent bridgeEvent = buildBridgeEvent(BridgeEvent.BRIDGE_STATE_LINK, remaining); - logger.info("Bridge " + bridgeEvent.getChannel1() + " " + bridgeEvent.getChannel2()); + // logger.info("Bridge " + bridgeEvent.getChannel1() + " " + + // bridgeEvent.getChannel2()); return bridgeEvent; } From 1f97a4070e35c2cdeb4cc48799e95f2516ba16eb Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 8 Apr 2021 15:39:56 +1000 Subject: [PATCH 459/802] add missing event properties --- .../manager/event/PickupEvent.java | 246 +++++++++++++++--- 1 file changed, 216 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/PickupEvent.java b/src/main/java/org/asteriskjava/manager/event/PickupEvent.java index b7c829cda..9ba8eaf91 100644 --- a/src/main/java/org/asteriskjava/manager/event/PickupEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PickupEvent.java @@ -2,37 +2,223 @@ public class PickupEvent extends ManagerEvent { + /** + * + */ + private static final long serialVersionUID = 1L; + private String accountcode; private String channel; + private String language; + private String linkedid; + private String targetaccountcode; + private String targetcalleridname; + private String targetcalleridnum; private String targetchannel; - - public PickupEvent(Object source) - { - super(source); - } - - /** - * - */ - private static final long serialVersionUID = 1L; - - public String getChannel() - { - return channel; - } - - public void setChannel(String channel) - { - this.channel = channel; - } - - public String getTargetchannel() - { - return targetchannel; - } - - public void setTargetchannel(String targetchannel) - { - this.targetchannel = targetchannel; - } + private String targetchannelstate; + private String targetchannelstatedesc; + private String targetconnectedlinename; + private String targetconnectedlinenum; + private String targetcontext; + private String targetexten; + private String targetlanguage; + private String targetlinkedid; + private String targetpriority; + private String targetuniqueid; + private String uniqueid; + + public PickupEvent(Object source) + { + super(source); + } + + public String getAccountcode() + { + return accountcode; + } + + public String getChannel() + { + return channel; + } + + public String getLanguage() + { + return language; + } + + public String getLinkedid() + { + return linkedid; + } + + public String getTargetaccountcode() + { + return targetaccountcode; + } + + public String getTargetcalleridname() + { + return targetcalleridname; + } + + public String getTargetcalleridnum() + { + return targetcalleridnum; + } + + public String getTargetchannel() + { + return targetchannel; + } + + public String getTargetchannelstate() + { + return targetchannelstate; + } + + public String getTargetchannelstatedesc() + { + return targetchannelstatedesc; + } + + public String getTargetconnectedlinename() + { + return targetconnectedlinename; + } + + public String getTargetconnectedlinenum() + { + return targetconnectedlinenum; + } + + public String getTargetcontext() + { + return targetcontext; + } + + public String getTargetexten() + { + return targetexten; + } + + public String getTargetlanguage() + { + return targetlanguage; + } + + public String getTargetlinkedid() + { + return targetlinkedid; + } + + public String getTargetpriority() + { + return targetpriority; + } + + public String getTargetuniqueid() + { + return targetuniqueid; + } + + public String getUniqueid() + { + return uniqueid; + } + + public void setAccountcode(String accountcode) + { + this.accountcode = accountcode; + } + + public void setChannel(String channel) + { + this.channel = channel; + } + + public void setLanguage(String language) + { + this.language = language; + } + + public void setLinkedid(String linkedid) + { + this.linkedid = linkedid; + } + + public void setTargetaccountcode(String targetaccountcode) + { + this.targetaccountcode = targetaccountcode; + } + + public void setTargetcalleridname(String targetcalleridname) + { + this.targetcalleridname = targetcalleridname; + } + + public void setTargetcalleridnum(String targetcalleridnum) + { + this.targetcalleridnum = targetcalleridnum; + } + + public void setTargetchannel(String targetchannel) + { + this.targetchannel = targetchannel; + } + + public void setTargetchannelstate(String targetchannelstate) + { + this.targetchannelstate = targetchannelstate; + } + + public void setTargetchannelstatedesc(String targetchannelstatedesc) + { + this.targetchannelstatedesc = targetchannelstatedesc; + } + + public void setTargetconnectedlinename(String targetconnectedlinename) + { + this.targetconnectedlinename = targetconnectedlinename; + } + + public void setTargetconnectedlinenum(String targetconnectedlinenum) + { + this.targetconnectedlinenum = targetconnectedlinenum; + } + + public void setTargetcontext(String targetcontext) + { + this.targetcontext = targetcontext; + } + + public void setTargetexten(String targetexten) + { + this.targetexten = targetexten; + } + + public void setTargetlanguage(String targetlanguage) + { + this.targetlanguage = targetlanguage; + } + + public void setTargetlinkedid(String targetlinkedid) + { + this.targetlinkedid = targetlinkedid; + } + + public void setTargetpriority(String targetpriority) + { + this.targetpriority = targetpriority; + } + + public void setTargetuniqueid(String targetuniqueid) + { + this.targetuniqueid = targetuniqueid; + } + + public void setUniqueid(String uniqueid) + { + this.uniqueid = uniqueid; + } } From 742e7fdf8102c9608c24ff57bfcef4470b007925 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 8 Apr 2021 15:50:43 +1000 Subject: [PATCH 460/802] for version 3.12.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 209789b0b..b47cfb955 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.11.0 + 3.12.0 UTF-8 From cd5eef0a504df3ca12d8a6d77fabb79331e773c5 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 4 May 2021 15:20:31 +1000 Subject: [PATCH 461/802] clean up imports --- src/test/java/org/asteriskjava/lock/LockerTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/org/asteriskjava/lock/LockerTest.java b/src/test/java/org/asteriskjava/lock/LockerTest.java index 72f9444e5..154d89426 100644 --- a/src/test/java/org/asteriskjava/lock/LockerTest.java +++ b/src/test/java/org/asteriskjava/lock/LockerTest.java @@ -2,8 +2,6 @@ import java.util.concurrent.TimeUnit; -import org.asteriskjava.lock.Lockable; -import org.asteriskjava.lock.Locker; import org.asteriskjava.lock.Locker.LockCloser; import org.junit.Test; From 779b5809711e8549f5cc1f04e59e5711f12a3b16 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 2 Jun 2021 17:34:55 +1000 Subject: [PATCH 462/802] update to allow overriding getAddress --- .../fastagi/DefaultAgiServer.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java b/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java index 77ac2e9de..f7852935f 100644 --- a/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java @@ -65,8 +65,8 @@ public class DefaultAgiServer extends AbstractAgiServer implements AgiServer private InetAddress address = null; /** - * Closes the connection if no input has been read for the - * given amount of milliseconds. + * Closes the connection if no input has been read for the given amount of + * milliseconds. * * @see Socket#setSoTimeout(int) */ @@ -312,7 +312,9 @@ public void setSocketReadTimeout(int socketReadTimeout) protected ServerSocketFacade createServerSocket() throws IOException { - ServerSocketFacade serverSocketFacade = new ServerSocketFacadeImpl(port, BACKLOG, address); + // referred to the address by getAddress(), so that overloading the + // getAddress() method works as expected + ServerSocketFacade serverSocketFacade = new ServerSocketFacadeImpl(port, BACKLOG, getAddress()); serverSocketFacade.setSocketReadTimeout(socketReadTimeout); return serverSocketFacade; } @@ -328,8 +330,18 @@ public void startup() throws IOException, IllegalStateException logger.error("Unable start AgiServer: cannot to bind to *:" + port + ".", e); throw e; } - - logger.info("Listening on *:" + port + "."); + // referred to the address by getAddress(), so that overloading the + // getAddress() method works as expected + if (getAddress() != null) + { + // referred to the address by getAddress(), so that overloading the + // getAddress() method works as expected + logger.info("Listening on " + getAddress() + ":" + port + "."); + } + else + { + logger.info("Listening on *:" + port + "."); + } // loop will be terminated by accept() throwing an IOException when the // ServerSocket is closed. From 6b9fdb5cb6efd3de05ef12cf95ad8638f504f7c0 Mon Sep 17 00:00:00 2001 From: Mario Lenis Date: Fri, 4 Jun 2021 14:16:52 -0500 Subject: [PATCH 463/802] Added setters and getters for QueueMemberPenaltyEvent --- .../event/QueueMemberPenaltyEvent.java | 246 ++++++++++++++++++ 1 file changed, 246 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java index d16723dca..6ac91dbc1 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java @@ -35,6 +35,19 @@ public class QueueMemberPenaltyEvent extends ManagerEvent private String queue; private String location; private Integer penalty; + private Boolean paused; + private Integer wrapuptime; + private Integer lastpause; + private String stateinterface; + private String pausedreason; + private Integer incall; + private String membership; + private String _interface; + private Integer callstaken; + private Integer ringinuse; + private Integer lastcall; + private String membername; + private Integer status; /** * Creates a new instance. @@ -46,6 +59,239 @@ public QueueMemberPenaltyEvent(Object source) super(source); } + /** + * Returns if the member is pause + * + * @return if the member is pause + */ + public Boolean getPaused() { + return paused; + } + + /** + * Sets if member is paused or not + * + * @param paused if paused + */ + public void setPaused(Boolean paused) { + this.paused = paused; + } + + /** + * Returns wrapuptime + * + * @return Returns wrapuptime + */ + public Integer getWrapuptime() { + return wrapuptime; + } + + /** + * Sets wrapuptime + * + * @param wrapuptime the wrapuptime + */ + public void setWrapuptime(Integer wrapuptime) { + this.wrapuptime = wrapuptime; + } + + /** + * Returns time in seconds when started last paused the queue member + * + * @return Returns time in seconds when started last paused the queue member + */ + public Integer getLastpause() { + return lastpause; + } + + /** + * Sets time in seconds when started last paused the queue member + * + * @param lastpause time in seconds when started last paused the queue member + */ + public void setLastpause(Integer lastpause) { + this.lastpause = lastpause; + } + + /** + * Returns the queue member's tech or location state + * + * @return the queue member's tech or location state + */ + public String getStateinterface() { + return stateinterface; + } + + /** + * Sets channel technology or location from which the member device changed + * + * @param stateinterface channel technology or location from which the member device changed + */ + public void setStateinterface(String stateinterface) { + this.stateinterface = stateinterface; + } + + /** + * Returns reason if set when paused + * + * @return reason if set when paused + */ + public String getPausedreason() { + return pausedreason; + } + + /** + * Sets reason if set when paused + * + * @param pausedreason reason if set when paused + */ + public void setPausedreason(String pausedreason) { + this.pausedreason = pausedreason; + } + + /** + * Returns if member is in call when event is raised + * + * @return if member is in call when event is raised + */ + public Integer getIncall() { + return incall; + } + + /** + * Sets if member is in call when event is raised + * + * @param incall if member is in call when event is raised + */ + public void setIncall(Integer incall) { + this.incall = incall; + } + + /** + * Returns membership in queue + * E.g. dynamic, realtime, static + * + * @return membership in queue + */ + public String getMembership() { + return membership; + } + + /** + * Sets membership in queue + * + * @param membership membership in queue + */ + public void setMembership(String membership) { + this.membership = membership; + } + + /** + * Returns queue member's tech or location name + * + * @return queue member's tech or location name + */ + public String getInterface() { + return _interface; + } + + /** + * Sets queue member's tech or location name + * + * @param _interface queue member's tech or location name + */ + public void setInterface(String _interface) { + this._interface = _interface; + } + + /** + * Returns number of calls this queue member has serviced + * + * @return number of calls this queue member has serviced + */ + public Integer getCallstaken() { + return callstaken; + } + + /** + * Sets number of calls this queue member has serviced + * + * @param callstaken number of calls this queue member has serviced + */ + public void setCallstaken(Integer callstaken) { + this.callstaken = callstaken; + } + + /** + * Returns member's ring in use setup + * + * @return member's ring in use setup + */ + public Integer getRinginuse() { + return ringinuse; + } + + /** + * Sets member's ring in use setup + * + * @param ringinuse member's ring in use setup + */ + public void setRinginuse(Integer ringinuse) { + this.ringinuse = ringinuse; + } + + /** + * Returns time this member last took a call, expressed in seconds + * + * @return time this member last took a call, expressed in seconds + */ + public Integer getLastcall() { + return lastcall; + } + + /** + * Sets time this member last took a call, expressed in seconds + * + * @param lastcall time this member last took a call, expressed in seconds + */ + public void setLastcall(Integer lastcall) { + this.lastcall = lastcall; + } + + /** + * Returns name of the queue member. + * + * @return name of the queue member. + */ + public String getMembername() { + return membername; + } + + /** + * Sets name of the queue member. + * + * @param membername name of the queue member. + */ + public void setMembername(String membername) { + this.membername = membername; + } + + /** + * Returns numeric device state status of the queue member + * + * @return numeric device state status of the queue member + */ + public Integer getStatus() { return status; } + + /** + * Sets numeric device state status of the queue member + * + * @param status numeric device state status of the queue member + */ + public void setStatus(Integer status) { + this.status = status; + } + /** * Returns the name of the queue. * From f63702c0ac3cf60dce4d4a60454e20f268b7764b Mon Sep 17 00:00:00 2001 From: Mario Lenis Date: Fri, 4 Jun 2021 15:27:56 -0500 Subject: [PATCH 464/802] Added setters and getters for lastpause time in seconds when the evento was raised. --- .../manager/event/QueueMemberPauseEvent.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java index 3b44bd2e1..ed7dbe9fd 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java @@ -7,6 +7,7 @@ public class QueueMemberPauseEvent extends QueueMemberPausedEvent // Logger logger = LogManager.getLogger(); String membership; Long lastcall; + Long lastpause; Integer callsTaken; Integer penalty; Integer status; @@ -54,6 +55,22 @@ public void setLastcall(Long lastcall) this.lastcall = lastcall; } + /** + * @return the lastpause time in seconds + */ + public Long getLastpause() + { + return lastpause; + } + + /** + * @param lastpause the lastpause time in seconds to set + */ + public void setLastpause(Long lastpause) + { + this.lastpause = lastpause; + } + /** * @return the callsTaken */ @@ -166,12 +183,12 @@ public void setIncall(Integer incall) this.incall = incall; } - public String getPausedreason() + public String getPausedreason() { return pausedreason; } - public void setPausedreason(String pausedreason) + public void setPausedreason(String pausedreason) { this.pausedreason = pausedreason; } From 6d0fc86deadb901257288f946ef9f315f4836ee7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Jun 2021 17:57:14 +0000 Subject: [PATCH 465/802] Bump logback-classic from 1.1.2 to 1.2.0 Bumps logback-classic from 1.1.2 to 1.2.0. --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b47cfb955..08a2ef0c0 100644 --- a/pom.xml +++ b/pom.xml @@ -187,7 +187,7 @@ ch.qos.logback logback-classic - 1.1.2 + 1.2.0 test From 33cddf51670f1c03c0ee053e63cc660a1f1dfa77 Mon Sep 17 00:00:00 2001 From: Alex Abreu Date: Tue, 17 Aug 2021 12:31:52 +0100 Subject: [PATCH 466/802] Support of Asterisk 18 version --- README.md | 4 ++-- pom.xml | 2 +- src/main/java/org/asteriskjava/AsteriskVersion.java | 10 +++++++++- .../manager/internal/ManagerConnectionImpl.java | 1 + .../java/org/asteriskjava/AsteriskVersionTest.java | 8 +++++++- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 625aa24db..90560e212 100644 --- a/README.md +++ b/README.md @@ -44,12 +44,12 @@ Asterisk-Java is available from [here](https://github.com/asterisk-java/asterisk Maven Dependency ---------------- -Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 16) (master) +Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.11.0 + 3.13.0 Asterisk-Java 2.x (Java 1.7 and Asterisk < Version 10) (branch 2.0.4) diff --git a/pom.xml b/pom.xml index b47cfb955..eebfd2426 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.12.0 + 3.13.0-SNAPSHOT UTF-8 diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index bdcf1a0f1..c23969eac 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -28,6 +28,7 @@ */ public class AsteriskVersion implements Comparable, Serializable { + private static final String VERSION_PATTERN_18 = "^\\s*Asterisk (GIT-)?18[-. ].*"; private static final String VERSION_PATTERN_17 = "^\\s*Asterisk (GIT-)?17[-. ].*"; private static final String VERSION_PATTERN_16 = "^\\s*Asterisk (GIT-)?16[-. ].*"; private static final String VERSION_PATTERN_15 = "^\\s*Asterisk (GIT-)?15[-. ].*"; @@ -130,7 +131,14 @@ public class AsteriskVersion implements Comparable, Serializabl */ public static final AsteriskVersion ASTERISK_17 = new AsteriskVersion(1700, "Asterisk 17", VERSION_PATTERN_17); - private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ASTERISK_17, ASTERISK_16, ASTERISK_15, ASTERISK_14, + /** + * Represents the Asterisk 18 series. + * + * @since 3.13.0 + */ + public static final AsteriskVersion ASTERISK_18 = new AsteriskVersion(1800, "Asterisk 18", VERSION_PATTERN_18); + + private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ASTERISK_18, ASTERISK_17, ASTERISK_16, ASTERISK_15, ASTERISK_14, ASTERISK_13, ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6}; // current debian stable version, as of 09/10/2018 diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 5fb9749ca..053c68888 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -110,6 +110,7 @@ public class ManagerConnectionImpl extends Lockable implements ManagerConnection "4.0", // Asterisk 15 "5.0", // Asterisk 16 "6.0", // Asterisk 17 + "7.0", // Asterisk 18 }; private static final AtomicLong idCounter = new AtomicLong(0); diff --git a/src/test/java/org/asteriskjava/AsteriskVersionTest.java b/src/test/java/org/asteriskjava/AsteriskVersionTest.java index 8942533c5..78704f625 100644 --- a/src/test/java/org/asteriskjava/AsteriskVersionTest.java +++ b/src/test/java/org/asteriskjava/AsteriskVersionTest.java @@ -13,7 +13,7 @@ public void testNullIfNoMatch() { assertNull(AsteriskVersion.getDetermineVersionFromString("")); } - + @Test public void test13() { @@ -33,4 +33,10 @@ public void test15() assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 15.1.0").equals(AsteriskVersion.ASTERISK_15)); } + @Test + public void test18() + { + assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 18.1.0").equals(AsteriskVersion.ASTERISK_18)); + } + } From 44f41258c5ba57d7a653a3f7bad84569116a148a Mon Sep 17 00:00:00 2001 From: Chen Zhang <340355960@qq.com> Date: Wed, 18 Aug 2021 16:45:36 +0800 Subject: [PATCH 467/802] Improve Travis CI build Performance --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 366fe82b8..727636ad4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,3 +11,7 @@ script: install: - /bin/true + +cache: + directories: + - $HOME/.m2 From b3528634a9116f411077b4c35be5a39ce9fd7a75 Mon Sep 17 00:00:00 2001 From: Alex Abreu Date: Mon, 23 Aug 2021 14:33:32 +0100 Subject: [PATCH 468/802] Support of MixMonitorStart / Stop AMI events --- pom.xml | 2 +- .../event/AbstractMixMonitorEvent.java | 62 +++++++++++++++++++ .../manager/event/MixMonitorStartEvent.java | 17 +++++ .../manager/event/MixMonitorStopEvent.java | 17 +++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/asteriskjava/manager/event/AbstractMixMonitorEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/MixMonitorStartEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/MixMonitorStopEvent.java diff --git a/pom.xml b/pom.xml index b47cfb955..101f8b611 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.12.0 + 3.13.0-SNAPSHOT UTF-8 diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractMixMonitorEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractMixMonitorEvent.java new file mode 100644 index 000000000..1faf62441 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/AbstractMixMonitorEvent.java @@ -0,0 +1,62 @@ +package org.asteriskjava.manager.event; + +/** + * Abstract base class for mix monitoring events.

    + * + * @version $Id$ + * @since 3.13.0 + */ +public abstract class AbstractMixMonitorEvent extends ManagerEvent +{ + private static final long serialVersionUID = 1L; + private String accountCode; + private String channel; + private String language; + private String linkedId; + private String uniqueId; + + protected AbstractMixMonitorEvent(Object source) + { + super(source); + } + + public String getChannel() { + return channel; + } + + public void setChannel(String channel) { + this.channel = channel; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } + + public String getAccountCode() { + return accountCode; + } + + public void setAccountCode(String accountCode) { + this.accountCode = accountCode; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getLinkedId() { + return linkedId; + } + + public void setLinkedId(String linkedId) { + this.linkedId = linkedId; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/MixMonitorStartEvent.java b/src/main/java/org/asteriskjava/manager/event/MixMonitorStartEvent.java new file mode 100644 index 000000000..dab79b443 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/MixMonitorStartEvent.java @@ -0,0 +1,17 @@ +package org.asteriskjava.manager.event; + +/** + * A MixMonitorStartEvent indicates that monitoring was started on a channel.

    + * + * @since 3.13.0 + * @see org.asteriskjava.manager.event.MixMonitorStopEvent + */ +public class MixMonitorStartEvent extends AbstractMixMonitorEvent +{ + private static final long serialVersionUID = 1L; + + public MixMonitorStartEvent(Object source) + { + super(source); + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/MixMonitorStopEvent.java b/src/main/java/org/asteriskjava/manager/event/MixMonitorStopEvent.java new file mode 100644 index 000000000..54f59b072 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/MixMonitorStopEvent.java @@ -0,0 +1,17 @@ +package org.asteriskjava.manager.event; + +/** + * A MixMonitorStopEvent indicates that monitoring was stopped on a channel.

    + * + * @since 3.13.0 + * @see org.asteriskjava.manager.event.MixMonitorStartEvent + */ +public class MixMonitorStopEvent extends AbstractMixMonitorEvent +{ + private static final long serialVersionUID = 1L; + + public MixMonitorStopEvent(Object source) + { + super(source); + } +} From 46ace973e0e822fc5bb6ec7dcb35ef53e7aefaa7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 6 Oct 2021 15:32:41 +1100 Subject: [PATCH 469/802] for version 3.14.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6e6aef9cd..f04e3010e 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.13.0-SNAPSHOT + 3.14.0 UTF-8 From 9774cc10518bc0aee9dc8c41de237cf37352f490 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 6 Oct 2021 15:33:46 +1100 Subject: [PATCH 470/802] update version number in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 90560e212..e048aacd6 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.13.0 + 3.14.0 Asterisk-Java 2.x (Java 1.7 and Asterisk < Version 10) (branch 2.0.4) From 8382171f50eb9d81b4d1076fa35e118c5a318908 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 21 Oct 2021 16:29:02 +1100 Subject: [PATCH 471/802] clean up --- .../internal/ManagerReaderImplTest.java | 504 +++++++++--------- .../internal/ManagerWriterImplTest.java | 63 ++- 2 files changed, 285 insertions(+), 282 deletions(-) diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java index 57ca31ce3..89571a3d3 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java @@ -45,338 +45,342 @@ public class ManagerReaderImplTest { - private Date now; - private MockedDispatcher dispatcher; - private SocketConnectionFacade socketConnectionFacade; - private ManagerReader managerReader; - - @Before - public void setUp() - { - now = new Date(); - DateUtil.overrideCurrentDate(now); - dispatcher = new MockedDispatcher(); - managerReader = new ManagerReaderImpl(dispatcher, this); + private Date now; + private MockedDispatcher dispatcher; + private SocketConnectionFacade socketConnectionFacade; + private ManagerReader managerReader; + + @Before + public void setUp() + { + now = new Date(); + DateUtil.overrideCurrentDate(now); + dispatcher = new MockedDispatcher(); + managerReader = new ManagerReaderImpl(dispatcher, this); - socketConnectionFacade = createMock(SocketConnectionFacade.class); - } - - @After - public void tearDown() - { - DateUtil.overrideCurrentDate(null); - } + socketConnectionFacade = createMock(SocketConnectionFacade.class); + } + + @After + public void tearDown() + { + DateUtil.overrideCurrentDate(null); + } - @SuppressWarnings("cast") - @Test - public void testRunWithoutSocket() - { - try - { - managerReader.run(); - fail("Must throw IllegalStateException"); - } - catch (IllegalStateException e) - { - assertTrue("Exception must be of type IllegalStateException", e instanceof IllegalStateException); - } - } + @Test + public void testRunWithoutSocket() + { + try + { + managerReader.run(); + fail("Must throw IllegalStateException"); + } + catch (IllegalStateException e) + { + assertTrue("Exception must be of type IllegalStateException", e instanceof IllegalStateException); + } + } + + @Test + public void testRunReceivingProtocolIdentifier() throws Exception + { + expect(socketConnectionFacade.readLine()).andReturn("Asterisk Call Manager/1.0"); + expect(socketConnectionFacade.readLine()).andReturn(null); - @Test - public void testRunReceivingProtocolIdentifier() throws Exception - { - expect(socketConnectionFacade.readLine()).andReturn("Asterisk Call Manager/1.0"); - expect(socketConnectionFacade.readLine()).andReturn(null); + replay(socketConnectionFacade); - replay(socketConnectionFacade); + managerReader.setSocket(socketConnectionFacade); + managerReader.run(); - managerReader.setSocket(socketConnectionFacade); - managerReader.run(); + verify(socketConnectionFacade); - verify(socketConnectionFacade); + assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); - assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); + assertEquals("first event must be a ProtocolIdentifierReceivedEvent", ProtocolIdentifierReceivedEvent.class, + dispatcher.dispatchedEvents.get(0).getClass()); - assertEquals("first event must be a ProtocolIdentifierReceivedEvent", ProtocolIdentifierReceivedEvent.class, - dispatcher.dispatchedEvents.get(0).getClass()); + assertEquals("ProtocolIdentifierReceivedEvent contains incorrect protocol identifier", + "Asterisk Call Manager/1.0", + ((ProtocolIdentifierReceivedEvent) dispatcher.dispatchedEvents.get(0)).getProtocolIdentifier()); + + assertEquals("ProtocolIdentifierReceivedEvent contains incorrect dateReceived", now, + dispatcher.dispatchedEvents.get(0).getDateReceived()); + + assertEquals("second event must be a DisconnectEvent", DisconnectEvent.class, + dispatcher.dispatchedEvents.get(1).getClass()); + + assertEquals("DisconnectEvent contains incorrect dateReceived", now, + dispatcher.dispatchedEvents.get(1).getDateReceived()); + } - assertEquals("ProtocolIdentifierReceivedEvent contains incorrect protocol identifier", "Asterisk Call Manager/1.0", - ((ProtocolIdentifierReceivedEvent) dispatcher.dispatchedEvents.get(0)).getProtocolIdentifier()); - - assertEquals("ProtocolIdentifierReceivedEvent contains incorrect dateReceived", now, - dispatcher.dispatchedEvents.get(0).getDateReceived()); - - assertEquals("second event must be a DisconnectEvent", DisconnectEvent.class, - dispatcher.dispatchedEvents.get(1).getClass()); - - assertEquals("DisconnectEvent contains incorrect dateReceived", now, - dispatcher.dispatchedEvents.get(1).getDateReceived()); - } + @Test + public void testRunReceivingEvent() throws Exception + { + expect(socketConnectionFacade.readLine()).andReturn("Event: StatusComplete"); + expect(socketConnectionFacade.readLine()).andReturn(""); + expect(socketConnectionFacade.readLine()).andReturn(null); - @Test - public void testRunReceivingEvent() throws Exception - { - expect(socketConnectionFacade.readLine()).andReturn("Event: StatusComplete"); - expect(socketConnectionFacade.readLine()).andReturn(""); - expect(socketConnectionFacade.readLine()).andReturn(null); + replay(socketConnectionFacade); - replay(socketConnectionFacade); + managerReader.setSocket(socketConnectionFacade); + managerReader.run(); - managerReader.setSocket(socketConnectionFacade); - managerReader.run(); + verify(socketConnectionFacade); - verify(socketConnectionFacade); + assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); - assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); + assertEquals("first event must be a StatusCompleteEvent", StatusCompleteEvent.class, + dispatcher.dispatchedEvents.get(0).getClass()); - assertEquals("first event must be a StatusCompleteEvent", StatusCompleteEvent.class, - dispatcher.dispatchedEvents.get(0).getClass()); + assertEquals("second event must be a DisconnectEvent", DisconnectEvent.class, + dispatcher.dispatchedEvents.get(1).getClass()); + } - assertEquals("second event must be a DisconnectEvent", DisconnectEvent.class, - dispatcher.dispatchedEvents.get(1).getClass()); - } + @Test + public void testRunReceivingEventWithMapProperty() throws Exception + { + expect(socketConnectionFacade.readLine()).andReturn("Event: AgentCalled"); + expect(socketConnectionFacade.readLine()).andReturn("Variable: var1=val1"); + expect(socketConnectionFacade.readLine()).andReturn("Variable: var2=val2"); + expect(socketConnectionFacade.readLine()).andReturn(""); + expect(socketConnectionFacade.readLine()).andReturn(null); - @Test - public void testRunReceivingEventWithMapProperty() throws Exception - { - expect(socketConnectionFacade.readLine()).andReturn("Event: AgentCalled"); - expect(socketConnectionFacade.readLine()).andReturn("Variable: var1=val1"); - expect(socketConnectionFacade.readLine()).andReturn("Variable: var2=val2"); - expect(socketConnectionFacade.readLine()).andReturn(""); - expect(socketConnectionFacade.readLine()).andReturn(null); + replay(socketConnectionFacade); - replay(socketConnectionFacade); + managerReader.setSocket(socketConnectionFacade); + managerReader.run(); - managerReader.setSocket(socketConnectionFacade); - managerReader.run(); + verify(socketConnectionFacade); - verify(socketConnectionFacade); + assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); - assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); + assertEquals("first event must be a AgentCalledEvent", AgentCalledEvent.class, + dispatcher.dispatchedEvents.get(0).getClass()); - assertEquals("first event must be a AgentCalledEvent", AgentCalledEvent.class, - dispatcher.dispatchedEvents.get(0).getClass()); + AgentCalledEvent event = (AgentCalledEvent) dispatcher.dispatchedEvents.get(0); + assertEquals("Returned event is of wrong type", AgentCalledEvent.class, event.getClass()); + assertEquals("Property variables[var1] is not set correctly", "val1", event.getVariables().get("var1")); + assertEquals("Property variables[var2] is not set correctly", "val2", event.getVariables().get("var2")); + assertEquals("Invalid size of variables property", 2, event.getVariables().size()); - AgentCalledEvent event = (AgentCalledEvent) dispatcher.dispatchedEvents.get(0); - assertEquals("Returned event is of wrong type", AgentCalledEvent.class, event.getClass()); - assertEquals("Property variables[var1] is not set correctly", "val1", event.getVariables().get("var1")); - assertEquals("Property variables[var2] is not set correctly", "val2", event.getVariables().get("var2")); - assertEquals("Invalid size of variables property", 2, event.getVariables().size()); + assertEquals("second event must be an DisconnectEvent", DisconnectEvent.class, + dispatcher.dispatchedEvents.get(1).getClass()); + } - assertEquals("second event must be an DisconnectEvent", DisconnectEvent.class, - dispatcher.dispatchedEvents.get(1).getClass()); - } + @Test + public void testRunReceivingEventWithMapPropertyAndOnlyOneEntry() throws Exception + { + expect(socketConnectionFacade.readLine()).andReturn("Event: AgentCalled"); + expect(socketConnectionFacade.readLine()).andReturn("Variable: var1=val1"); + expect(socketConnectionFacade.readLine()).andReturn(""); + expect(socketConnectionFacade.readLine()).andReturn(null); - @Test - public void testRunReceivingEventWithMapPropertyAndOnlyOneEntry() throws Exception - { - expect(socketConnectionFacade.readLine()).andReturn("Event: AgentCalled"); - expect(socketConnectionFacade.readLine()).andReturn("Variable: var1=val1"); - expect(socketConnectionFacade.readLine()).andReturn(""); - expect(socketConnectionFacade.readLine()).andReturn(null); + replay(socketConnectionFacade); - replay(socketConnectionFacade); + managerReader.setSocket(socketConnectionFacade); + managerReader.run(); - managerReader.setSocket(socketConnectionFacade); - managerReader.run(); + verify(socketConnectionFacade); - verify(socketConnectionFacade); + assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); - assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); + assertEquals("first event must be a AgentCalledEvent", AgentCalledEvent.class, + dispatcher.dispatchedEvents.get(0).getClass()); - assertEquals("first event must be a AgentCalledEvent", AgentCalledEvent.class, - dispatcher.dispatchedEvents.get(0).getClass()); + AgentCalledEvent event = (AgentCalledEvent) dispatcher.dispatchedEvents.get(0); + assertEquals("Returned event is of wrong type", AgentCalledEvent.class, event.getClass()); + assertEquals("Property variables[var1] is not set correctly", "val1", event.getVariables().get("var1")); + assertEquals("Invalid size of variables property", 1, event.getVariables().size()); - AgentCalledEvent event = (AgentCalledEvent) dispatcher.dispatchedEvents.get(0); - assertEquals("Returned event is of wrong type", AgentCalledEvent.class, event.getClass()); - assertEquals("Property variables[var1] is not set correctly", "val1", event.getVariables().get("var1")); - assertEquals("Invalid size of variables property", 1, event.getVariables().size()); + assertEquals("second event must be an DisconnectEvent", DisconnectEvent.class, + dispatcher.dispatchedEvents.get(1).getClass()); + } - assertEquals("second event must be an DisconnectEvent", DisconnectEvent.class, - dispatcher.dispatchedEvents.get(1).getClass()); - } + @Test + public void testWorkaroundForAsteriskBug13319() throws Exception + { + expect(socketConnectionFacade.readLine()).andReturn("Event: RTCPReceived"); + expect(socketConnectionFacade.readLine()).andReturn("From 192.168.0.1:1234"); + expect(socketConnectionFacade.readLine()).andReturn("HighestSequence: 999"); + expect(socketConnectionFacade.readLine()).andReturn(""); + expect(socketConnectionFacade.readLine()).andReturn(null); - @Test - public void testWorkaroundForAsteriskBug13319() throws Exception - { - expect(socketConnectionFacade.readLine()).andReturn("Event: RTCPReceived"); - expect(socketConnectionFacade.readLine()).andReturn("From 192.168.0.1:1234"); - expect(socketConnectionFacade.readLine()).andReturn("HighestSequence: 999"); - expect(socketConnectionFacade.readLine()).andReturn(""); - expect(socketConnectionFacade.readLine()).andReturn(null); + replay(socketConnectionFacade); - replay(socketConnectionFacade); + managerReader.setSocket(socketConnectionFacade); + managerReader.run(); - managerReader.setSocket(socketConnectionFacade); - managerReader.run(); + verify(socketConnectionFacade); - verify(socketConnectionFacade); + assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); - assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); + assertEquals("first event must be a RtcpReceivedEvent", RtcpReceivedEvent.class, + dispatcher.dispatchedEvents.get(0).getClass()); - assertEquals("first event must be a RtcpReceivedEvent", RtcpReceivedEvent.class, - dispatcher.dispatchedEvents.get(0).getClass()); + RtcpReceivedEvent rtcpReceivedEvent = (RtcpReceivedEvent) dispatcher.dispatchedEvents.get(0); + assertEquals("Invalid from address on RtcpReceivedEvent", "192.168.0.1", + rtcpReceivedEvent.getFromAddress().getHostAddress()); + assertEquals("Invalid from port on RtcpReceivedEvent", new Integer(1234), rtcpReceivedEvent.getFromPort()); + assertEquals("Invalid highest sequence on RtcpReceivedEvent", new Long(999), + rtcpReceivedEvent.getHighestSequence()); - RtcpReceivedEvent rtcpReceivedEvent = (RtcpReceivedEvent) dispatcher.dispatchedEvents.get(0); - assertEquals("Invalid from address on RtcpReceivedEvent", "192.168.0.1", - rtcpReceivedEvent.getFromAddress().getHostAddress()); - assertEquals("Invalid from port on RtcpReceivedEvent", new Integer(1234), rtcpReceivedEvent.getFromPort()); - assertEquals("Invalid highest sequence on RtcpReceivedEvent", new Long(999), rtcpReceivedEvent.getHighestSequence()); + assertEquals("second event must be a DisconnectEvent", DisconnectEvent.class, + dispatcher.dispatchedEvents.get(1).getClass()); + } - assertEquals("second event must be a DisconnectEvent", DisconnectEvent.class, - dispatcher.dispatchedEvents.get(1).getClass()); - } + // todo fix testRunReceivingUserEvent + public void XtestRunReceivingUserEvent() throws Exception + { + managerReader.registerEventClass(MyUserEvent.class); - // todo fix testRunReceivingUserEvent - public void XtestRunReceivingUserEvent() throws Exception - { - managerReader.registerEventClass(MyUserEvent.class); + expect(socketConnectionFacade.readLine()).andReturn("Event: MyUser"); + expect(socketConnectionFacade.readLine()).andReturn(""); + expect(socketConnectionFacade.readLine()).andReturn(null); - expect(socketConnectionFacade.readLine()).andReturn("Event: MyUser"); - expect(socketConnectionFacade.readLine()).andReturn(""); - expect(socketConnectionFacade.readLine()).andReturn(null); + replay(socketConnectionFacade); - replay(socketConnectionFacade); + managerReader.setSocket(socketConnectionFacade); + managerReader.run(); - managerReader.setSocket(socketConnectionFacade); - managerReader.run(); + verify(socketConnectionFacade); - verify(socketConnectionFacade); + assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); - assertEquals("not exactly two events dispatched", 2, dispatcher.dispatchedEvents.size()); + assertEquals("first event must be a MyUserEvent", MyUserEvent.class, + dispatcher.dispatchedEvents.get(0).getClass()); - assertEquals("first event must be a MyUserEvent", MyUserEvent.class, dispatcher.dispatchedEvents.get(0).getClass()); + assertEquals("second event must be a DisconnectEvent", DisconnectEvent.class, + dispatcher.dispatchedEvents.get(1).getClass()); + } - assertEquals("second event must be a DisconnectEvent", DisconnectEvent.class, - dispatcher.dispatchedEvents.get(1).getClass()); - } + @Test + public void testRunReceivingResponse() throws Exception + { + expect(socketConnectionFacade.readLine()).andReturn("Response: Success"); + expect(socketConnectionFacade.readLine()).andReturn("Message: Authentication accepted"); + expect(socketConnectionFacade.readLine()).andReturn(""); + expect(socketConnectionFacade.readLine()).andReturn(null); - @Test - public void testRunReceivingResponse() throws Exception - { - expect(socketConnectionFacade.readLine()).andReturn("Response: Success"); - expect(socketConnectionFacade.readLine()).andReturn("Message: Authentication accepted"); - expect(socketConnectionFacade.readLine()).andReturn(""); - expect(socketConnectionFacade.readLine()).andReturn(null); + replay(socketConnectionFacade); - replay(socketConnectionFacade); + managerReader.setSocket(socketConnectionFacade); + managerReader.run(); - managerReader.setSocket(socketConnectionFacade); - managerReader.run(); + verify(socketConnectionFacade); - verify(socketConnectionFacade); + assertEquals("not exactly one response dispatched", 1, dispatcher.dispatchedResponses.size()); - assertEquals("not exactly one response dispatched", 1, dispatcher.dispatchedResponses.size()); + assertEquals("first response must be a ManagerResponse", ManagerResponse.class, + dispatcher.dispatchedResponses.get(0).getClass()); - assertEquals("first response must be a ManagerResponse", ManagerResponse.class, - dispatcher.dispatchedResponses.get(0).getClass()); + assertEquals("ManagerResponse contains incorrect response", "Success", + dispatcher.dispatchedResponses.get(0).getResponse()); - assertEquals("ManagerResponse contains incorrect response", "Success", - dispatcher.dispatchedResponses.get(0).getResponse()); + assertEquals("ManagerResponse contains incorrect message", "Authentication accepted", + dispatcher.dispatchedResponses.get(0).getMessage()); - assertEquals("ManagerResponse contains incorrect message", "Authentication accepted", - dispatcher.dispatchedResponses.get(0).getMessage()); + assertEquals("ManagerResponse contains incorrect message (via getAttribute)", "Authentication accepted", + dispatcher.dispatchedResponses.get(0).getAttribute("MESSAGE")); - assertEquals("ManagerResponse contains incorrect message (via getAttribute)", "Authentication accepted", - dispatcher.dispatchedResponses.get(0).getAttribute("MESSAGE")); + assertEquals("ManagerResponse contains incorrect dateReceived", now, + dispatcher.dispatchedResponses.get(0).getDateReceived()); - assertEquals("ManagerResponse contains incorrect dateReceived", now, - dispatcher.dispatchedResponses.get(0).getDateReceived()); + assertEquals("not exactly one events dispatched", 1, dispatcher.dispatchedEvents.size()); - assertEquals("not exactly one events dispatched", 1, dispatcher.dispatchedEvents.size()); + assertEquals("first event must be a DisconnectEvent", DisconnectEvent.class, + dispatcher.dispatchedEvents.get(0).getClass()); + } - assertEquals("first event must be a DisconnectEvent", DisconnectEvent.class, - dispatcher.dispatchedEvents.get(0).getClass()); - } + @Test + public void testRunReceivingCommandResponse() throws Exception + { + List result = new ArrayList(); - @Test - public void testRunReceivingCommandResponse() throws Exception - { - List result = new ArrayList(); + expect(socketConnectionFacade.readLine()).andReturn("Response: Follows"); + expect(socketConnectionFacade.readLine()).andReturn("ActionID: 678#12345"); + expect(socketConnectionFacade.readLine()).andReturn("Line1\nLine2\n--END COMMAND--"); + expect(socketConnectionFacade.readLine()).andReturn(""); + expect(socketConnectionFacade.readLine()).andReturn(null); - expect(socketConnectionFacade.readLine()).andReturn("Response: Follows"); - expect(socketConnectionFacade.readLine()).andReturn("ActionID: 678#12345"); - expect(socketConnectionFacade.readLine()).andReturn("Line1\nLine2\n--END COMMAND--"); - expect(socketConnectionFacade.readLine()).andReturn(""); - expect(socketConnectionFacade.readLine()).andReturn(null); + result.add("Line1"); + result.add("Line2"); - result.add("Line1"); - result.add("Line2"); + replay(socketConnectionFacade); - replay(socketConnectionFacade); + managerReader.setSocket(socketConnectionFacade); + managerReader.expectResponseClass("678", CommandResponse.class); + managerReader.run(); - managerReader.setSocket(socketConnectionFacade); - managerReader.expectResponseClass("678", CommandResponse.class); - managerReader.run(); + verify(socketConnectionFacade); - verify(socketConnectionFacade); + assertEquals("not exactly one response dispatched", 1, dispatcher.dispatchedResponses.size()); - assertEquals("not exactly one response dispatched", 1, dispatcher.dispatchedResponses.size()); + assertEquals("first response must be a CommandResponse", CommandResponse.class, + dispatcher.dispatchedResponses.get(0).getClass()); - assertEquals("first response must be a CommandResponse", CommandResponse.class, - dispatcher.dispatchedResponses.get(0).getClass()); + assertEquals("CommandResponse contains incorrect response", "Follows", + dispatcher.dispatchedResponses.get(0).getResponse()); - assertEquals("CommandResponse contains incorrect response", "Follows", - dispatcher.dispatchedResponses.get(0).getResponse()); + assertEquals("CommandResponse contains incorrect actionId", "678#12345", + dispatcher.dispatchedResponses.get(0).getActionId()); - assertEquals("CommandResponse contains incorrect actionId", "678#12345", - dispatcher.dispatchedResponses.get(0).getActionId()); + assertEquals("CommandResponse contains incorrect actionId (via getAttribute)", "678#12345", + dispatcher.dispatchedResponses.get(0).getAttribute("actionId")); - assertEquals("CommandResponse contains incorrect actionId (via getAttribute)", "678#12345", - dispatcher.dispatchedResponses.get(0).getAttribute("actionId")); + assertEquals("CommandResponse contains incorrect result", result, + ((CommandResponse) dispatcher.dispatchedResponses.get(0)).getResult()); - assertEquals("CommandResponse contains incorrect result", result, - ((CommandResponse) dispatcher.dispatchedResponses.get(0)).getResult()); + assertEquals("CommandResponse contains incorrect dateReceived", now, + dispatcher.dispatchedResponses.get(0).getDateReceived()); + } - assertEquals("CommandResponse contains incorrect dateReceived", now, - dispatcher.dispatchedResponses.get(0).getDateReceived()); - } + @Test + public void testRunCatchingIOException() throws Exception + { + expect(socketConnectionFacade.readLine()).andThrow(new IOException("Something happened to the network...")); - @Test - public void testRunCatchingIOException() throws Exception - { - expect(socketConnectionFacade.readLine()).andThrow(new IOException("Something happened to the network...")); + replay(socketConnectionFacade); - replay(socketConnectionFacade); + managerReader.setSocket(socketConnectionFacade); + managerReader.run(); - managerReader.setSocket(socketConnectionFacade); - managerReader.run(); + verify(socketConnectionFacade); - verify(socketConnectionFacade); + assertEquals("must not dispatch a response", 0, dispatcher.dispatchedResponses.size()); - assertEquals("must not dispatch a response", 0, dispatcher.dispatchedResponses.size()); + assertEquals("not exactly one events dispatched", 1, dispatcher.dispatchedEvents.size()); - assertEquals("not exactly one events dispatched", 1, dispatcher.dispatchedEvents.size()); + assertEquals("first event must be a DisconnectEvent", DisconnectEvent.class, + dispatcher.dispatchedEvents.get(0).getClass()); + } - assertEquals("first event must be a DisconnectEvent", DisconnectEvent.class, - dispatcher.dispatchedEvents.get(0).getClass()); - } + private class MockedDispatcher implements Dispatcher + { + List dispatchedEvents; + List dispatchedResponses; - private class MockedDispatcher implements Dispatcher - { - List dispatchedEvents; - List dispatchedResponses; + public MockedDispatcher() + { + this.dispatchedEvents = new ArrayList(); + this.dispatchedResponses = new ArrayList(); + } - public MockedDispatcher() - { - this.dispatchedEvents = new ArrayList(); - this.dispatchedResponses = new ArrayList(); - } + @Override + public void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime) + { + dispatchedResponses.add(response); + } - public void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime) - { - dispatchedResponses.add(response); - } + @Override + public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) + { + dispatchedEvents.add(event); + } - public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) - { - dispatchedEvents.add(event); - } - - @Override - public void stop() - { - // NO_OP - } - } + @Override + public void stop() + { + // NO_OP + } + } } diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerWriterImplTest.java b/src/test/java/org/asteriskjava/manager/internal/ManagerWriterImplTest.java index ba2289038..197935fca 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerWriterImplTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerWriterImplTest.java @@ -29,41 +29,40 @@ public class ManagerWriterImplTest { - private ManagerWriter managerWriter; + private ManagerWriter managerWriter; - @Before - public void setUp() - { - managerWriter = new ManagerWriterImpl(); - } + @Before + public void setUp() + { + managerWriter = new ManagerWriterImpl(); + } - @SuppressWarnings("cast") - @Test - public void testSendActionWithoutSocket() throws Exception - { - try - { - managerWriter.sendAction(new StatusAction(), null); - fail("Must throw IllegalStateException"); - } - catch (IllegalStateException e) - { - assertTrue("Exception must be of type IllegalStateException", e instanceof IllegalStateException); - } - } + @Test + public void testSendActionWithoutSocket() throws Exception + { + try + { + managerWriter.sendAction(new StatusAction(), null); + fail("Must throw IllegalStateException"); + } + catch (IllegalStateException e) + { + assertTrue("Exception must be of type IllegalStateException", e instanceof IllegalStateException); + } + } - @Test - public void testSendAction() throws Exception - { - SocketConnectionFacade socketConnectionFacade; + @Test + public void testSendAction() throws Exception + { + SocketConnectionFacade socketConnectionFacade; - socketConnectionFacade = createMock(SocketConnectionFacade.class); - socketConnectionFacade.write("action: Status\r\n\r\n"); - socketConnectionFacade.flush(); - replay(socketConnectionFacade); + socketConnectionFacade = createMock(SocketConnectionFacade.class); + socketConnectionFacade.write("action: Status\r\n\r\n"); + socketConnectionFacade.flush(); + replay(socketConnectionFacade); - managerWriter.setSocket(socketConnectionFacade); - managerWriter.sendAction(new StatusAction(), null); - verify(socketConnectionFacade); - } + managerWriter.setSocket(socketConnectionFacade); + managerWriter.sendAction(new StatusAction(), null); + verify(socketConnectionFacade); + } } From 29d7c83c82b9b1830172fb0a6b582f37c10b76f9 Mon Sep 17 00:00:00 2001 From: Bartosz Malkowski Date: Thu, 9 Dec 2021 15:06:39 +0100 Subject: [PATCH 472/802] fix problem with overriding setters. #360: NumberFormatException: For input string: "true" --- .../org/asteriskjava/util/ReflectionUtil.java | 6 +-- .../asteriskjava/manager/internal/EEvent.java | 47 +++++++++++++++++++ .../internal/EventBuilderImplTest.java | 47 +++++++++---------- 3 files changed, 71 insertions(+), 29 deletions(-) create mode 100644 src/test/java/org/asteriskjava/manager/internal/EEvent.java diff --git a/src/main/java/org/asteriskjava/util/ReflectionUtil.java b/src/main/java/org/asteriskjava/util/ReflectionUtil.java index f778e6296..68e563033 100644 --- a/src/main/java/org/asteriskjava/util/ReflectionUtil.java +++ b/src/main/java/org/asteriskjava/util/ReflectionUtil.java @@ -109,7 +109,7 @@ else if (methodName.startsWith("is")) * While this method adds caching which is 100 times faster, the time * Benefit is largely insignificant as the execution time was already very * fast. - * + * * @param clazz * @return */ @@ -167,7 +167,7 @@ private static Map getSettersInternal(Class< ? > clazz) // we don't have a mapping for this setter so add it. accessors.put(name, method); } - else if (method.getDeclaringClass().isAssignableFrom(existing.getDeclaringClass())) + else if (!method.getDeclaringClass().isAssignableFrom(existing.getDeclaringClass())) { // we already have a mapping for this setter, but this one is // from an extending class so replace it. @@ -355,7 +355,7 @@ public static Set> loadClasses(String packageName, Class baseCla /** * retrieve all the classes that can be found on the classpath for the * specified packageName - * + * * @param packageName * @return * @throws IOException diff --git a/src/test/java/org/asteriskjava/manager/internal/EEvent.java b/src/test/java/org/asteriskjava/manager/internal/EEvent.java new file mode 100644 index 000000000..f8bc5ef17 --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/internal/EEvent.java @@ -0,0 +1,47 @@ +/* + * 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.manager.internal; + +import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.UserEvent; + +public class EEvent + extends ManagerEvent { + + private static final long serialVersionUID = 3545240219457894199L; + + private Boolean line; + + public EEvent(Object source) { + super(source); + } + + public Boolean getLineAsBoolean() { + return line; + } + + public void setLine(Boolean line) { + this.line = line; + if (line == null) { + super.setLine(null); + } else if (line) { + super.setLine(1); + } else { + super.setLine(0); + } + } +} diff --git a/src/test/java/org/asteriskjava/manager/internal/EventBuilderImplTest.java b/src/test/java/org/asteriskjava/manager/internal/EventBuilderImplTest.java index 5a238802c..235ef90cb 100644 --- a/src/test/java/org/asteriskjava/manager/internal/EventBuilderImplTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/EventBuilderImplTest.java @@ -16,36 +16,15 @@ */ package org.asteriskjava.manager.internal; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.asteriskjava.manager.event.*; +import org.junit.Before; +import org.junit.Test; import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import org.asteriskjava.manager.event.AbstractChannelEvent; -import org.asteriskjava.manager.event.AgentCalledEvent; -import org.asteriskjava.manager.event.CdrEvent; -import org.asteriskjava.manager.event.HangupEvent; -import org.asteriskjava.manager.event.LogChannelEvent; -import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.MeetMeLeaveEvent; -import org.asteriskjava.manager.event.MusicOnHoldEvent; -import org.asteriskjava.manager.event.NewCallerIdEvent; -import org.asteriskjava.manager.event.NewChannelEvent; -import org.asteriskjava.manager.event.NewExtenEvent; -import org.asteriskjava.manager.event.PeersEvent; -import org.asteriskjava.manager.event.ResponseEvent; -import org.asteriskjava.manager.event.RtpReceiverStatEvent; -import org.asteriskjava.manager.event.ShutdownEvent; -import org.asteriskjava.manager.event.StatusCompleteEvent; -import org.asteriskjava.manager.event.T38FaxStatusEvent; -import org.asteriskjava.manager.event.TransferEvent; -import org.junit.Before; -import org.junit.Test; +import static org.junit.Assert.*; public class EventBuilderImplTest { @@ -126,7 +105,23 @@ public void testRegisterUserEventWithUserEventDEvent() assertTrue("Wrong type", event instanceof UserEventDEvent); } - @Test + @Test + public void testBuildEventWithOverrideSetter() { + ManagerEvent event; + + eventBuilder.registerEventClass(EEvent.class); + properties.put("event", "e"); + properties.put("line", "true"); + properties.put("exten", "1abz"); + event = eventBuilder.buildEvent(this, properties); + + assertTrue("Wrong type", event instanceof EEvent); + assertEquals("1abz", event.getExten()); + assertEquals(Integer.valueOf(1), event.getLine()); + assertTrue(((EEvent) event).getLineAsBoolean()); + } + + @Test public void testRegisterEventWithAbstractEvent() { try From d70c33d8fe893f343103b5c3eaf974bba85ce2d0 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Sat, 11 Dec 2021 06:53:33 +1100 Subject: [PATCH 473/802] for version 3.15.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f04e3010e..249eb419c 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.14.0 + 3.15.0 UTF-8 From fb4a7aed6e78557c08bc5e9286a4b1c741ef8c7c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 10:57:02 +1100 Subject: [PATCH 474/802] update log4j to 2.15 --- pom.xml | 14 +- .../org/asteriskjava/util/LogFactory.java | 172 +++--- .../util/internal/Log4JLogger.java | 496 +++++++----------- 3 files changed, 292 insertions(+), 390 deletions(-) diff --git a/pom.xml b/pom.xml index 249eb419c..8a6ab8119 100644 --- a/pom.xml +++ b/pom.xml @@ -173,15 +173,15 @@ 30.1-jre - org.slf4j - slf4j-api - 1.7.9 - compile + + org.apache.logging.log4j + log4j-slf4j-impl + 2.15.0 - log4j - log4j - 1.2.17 + org.apache.logging.log4j + log4j-core + 2.15.0 provided diff --git a/src/main/java/org/asteriskjava/util/LogFactory.java b/src/main/java/org/asteriskjava/util/LogFactory.java index 356b8787e..300c905a7 100644 --- a/src/main/java/org/asteriskjava/util/LogFactory.java +++ b/src/main/java/org/asteriskjava/util/LogFactory.java @@ -45,98 +45,100 @@ */ public final class LogFactory { - private static Boolean slf4jLoggingAvailable = null; + private static Boolean slf4jLoggingAvailable = null; - /** - * Indicates if log4j is available on the classpath or not. If the check has - * not yet performed this is null. - */ - private static Boolean log4jLoggingAvailable = null; + /** + * Indicates if log4j is available on the classpath or not. If the check has + * not yet performed this is null. + */ + private static Boolean log4jLoggingAvailable = null; - /** - * Indicates if java.util.logging is available on the classpath or not. If - * the check has not yet performed this is null. - */ - private static Boolean javaLoggingAvailable = null; + /** + * Indicates if java.util.logging is available on the classpath or not. If + * the check has not yet performed this is null. + */ + private static Boolean javaLoggingAvailable = null; - private static ClassLoader classLoader = LogFactory.class.getClassLoader(); - - private LogFactory() { - - } + private static ClassLoader classLoader = LogFactory.class.getClassLoader(); - public static void setClassLoader(ClassLoader classLoader) - { - LogFactory.classLoader = classLoader; - } + private LogFactory() + { - /** - * Returns an instance of Log suitable for logging from the given class. - * - * @param clazz the class to create the logger for. - * @return the created logger. - */ - public synchronized static Log getLog(Class< ? > clazz) - { - if (slf4jLoggingAvailable == null) - { - try - { - classLoader.loadClass("org.slf4j.Logger"); - slf4jLoggingAvailable = Boolean.TRUE; - } - catch (Exception e) - { - slf4jLoggingAvailable = Boolean.FALSE; - } - } + } - if (slf4jLoggingAvailable) - { - try - { - return new Slf4JLogger(clazz); - } - catch (Throwable e) - { - slf4jLoggingAvailable = Boolean.FALSE; - } - } + public static void setClassLoader(ClassLoader classLoader) + { + LogFactory.classLoader = classLoader; + } - if (log4jLoggingAvailable == null) - { - try - { - classLoader.loadClass("org.apache.log4j.Logger"); - log4jLoggingAvailable = Boolean.TRUE; - } - catch (Exception e) - { - log4jLoggingAvailable = Boolean.FALSE; - } - } + /** + * Returns an instance of Log suitable for logging from the given class. + * + * @param clazz + * the class to create the logger for. + * @return the created logger. + */ + public synchronized static Log getLog(Class clazz) + { + if (slf4jLoggingAvailable == null) + { + try + { + classLoader.loadClass("org.slf4j.Logger"); + slf4jLoggingAvailable = Boolean.TRUE; + } + catch (Exception e) + { + slf4jLoggingAvailable = Boolean.FALSE; + } + } - if (log4jLoggingAvailable) - { - return new Log4JLogger(clazz); - } + if (slf4jLoggingAvailable) + { + try + { + return new Slf4JLogger(clazz); + } + catch (Throwable e) + { + slf4jLoggingAvailable = Boolean.FALSE; + } + } - if (javaLoggingAvailable == null) - { - try - { - classLoader.loadClass("java.util.logging.Logger"); - javaLoggingAvailable = Boolean.TRUE; - } - catch (Exception e) - { - javaLoggingAvailable = Boolean.FALSE; - } - } - if (javaLoggingAvailable) - { - return new JavaLoggingLog(clazz); - } - return new NullLog(); - } + if (log4jLoggingAvailable == null) + { + try + { + classLoader.loadClass("org.apache.logging.log4j.Logger"); + log4jLoggingAvailable = Boolean.TRUE; + } + catch (Exception e) + { + log4jLoggingAvailable = Boolean.FALSE; + } + } + + if (log4jLoggingAvailable) + { + return new Log4JLogger(clazz); + } + + if (javaLoggingAvailable == null) + { + try + { + classLoader.loadClass("java.util.logging.Logger"); + javaLoggingAvailable = Boolean.TRUE; + } + catch (Exception e) + { + javaLoggingAvailable = Boolean.FALSE; + } + } + if (javaLoggingAvailable) + { + return new JavaLoggingLog(clazz); + } + return new NullLog(); + } } diff --git a/src/main/java/org/asteriskjava/util/internal/Log4JLogger.java b/src/main/java/org/asteriskjava/util/internal/Log4JLogger.java index 96c05fb0b..97775a2b6 100644 --- a/src/main/java/org/asteriskjava/util/internal/Log4JLogger.java +++ b/src/main/java/org/asteriskjava/util/internal/Log4JLogger.java @@ -18,9 +18,10 @@ import java.io.Serializable; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.log4j.Priority; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.spi.AbstractLogger; import org.asteriskjava.util.Log; /** @@ -40,299 +41,198 @@ public class Log4JLogger implements Log, Serializable { - // ------------------------------------------------------------- Attributes - - /** - * The serial version identifier. - */ - private static final long serialVersionUID = 3545240215095883829L; - - /** The fully qualified name of the Log4JLogger class. */ - private static final String FQCN = Log4JLogger.class.getName(); - - private static final boolean IS12 = Priority.class.isAssignableFrom(Level.class); - - /** Log to this logger */ - private transient Logger logger = null; // NOPMD by srt on 7/5/06 11:18 PM - - /** Logger name */ - private String name = null; - - // ------------------------------------------------------------ Constructor - - public Log4JLogger() - { - } - - /** - * Base constructor. - */ - public Log4JLogger(Class< ? > clazz) - { - this.name = clazz.getName(); - this.logger = getLogger(); - } - - // --------------------------------------------------------- Implementation - - /** - * Log a message to the Log4j Logger with TRACE priority. - * Currently logs to DEBUG level in Log4J. - */ - public void trace(Object message) - { - if (IS12) - { - getLogger().log(FQCN, Level.DEBUG, message, null); - } - else - { - getLogger().log(FQCN, Level.DEBUG, message, null); - } - } - - /** - * Log an error to the Log4j Logger with TRACE priority. - * Currently logs to DEBUG level in Log4J. - */ - public void trace(Object message, Throwable t) - { - if (IS12) - { - getLogger().log(FQCN, Level.DEBUG, message, t); - } - else - { - getLogger().log(FQCN, Level.DEBUG, message, t); - } - } - - /** - * Log a message to the Log4j Logger with DEBUG priority. - */ - public void debug(Object message) - { - if (IS12) - { - getLogger().log(FQCN, Level.DEBUG, message, null); - } - else - { - getLogger().log(FQCN, Level.DEBUG, message, null); - } - } - - /** - * Log an error to the Log4j Logger with DEBUG priority. - */ - public void debug(Object message, Throwable t) - { - if (IS12) - { - getLogger().log(FQCN, Level.DEBUG, message, t); - } - else - { - getLogger().log(FQCN, Level.DEBUG, message, t); - } - } - - /** - * Log a message to the Log4j Logger with INFO priority. - */ - public void info(Object message) - { - if (IS12) - { - getLogger().log(FQCN, Level.INFO, message, null); - } - else - { - getLogger().log(FQCN, Level.INFO, message, null); - } - } - - /** - * Log an error to the Log4j Logger with INFO priority. - */ - public void info(Object message, Throwable t) - { - if (IS12) - { - getLogger().log(FQCN, Level.INFO, message, t); - } - else - { - getLogger().log(FQCN, Level.INFO, message, t); - } - } - - /** - * Log a message to the Log4j Logger with WARN priority. - */ - public void warn(Object message) - { - if (IS12) - { - getLogger().log(FQCN, Level.WARN, message, null); - } - else - { - getLogger().log(FQCN, Level.WARN, message, null); - } - } - - /** - * Log an error to the Log4j Logger with WARN priority. - */ - public void warn(Object message, Throwable t) - { - if (IS12) - { - getLogger().log(FQCN, Level.WARN, message, t); - } - else - { - getLogger().log(FQCN, Level.WARN, message, t); - } - } - - /** - * Log a message to the Log4j Logger with ERROR priority. - */ - public void error(Object message) - { - if (IS12) - { - getLogger().log(FQCN, Level.ERROR, message, null); - } - else - { - getLogger().log(FQCN, Level.ERROR, message, null); - } - } - - /** - * Log an error to the Log4j Logger with ERROR priority. - */ - public void error(Object message, Throwable t) - { - if (IS12) - { - getLogger().log(FQCN, Level.ERROR, message, t); - } - else - { - getLogger().log(FQCN, Level.ERROR, message, t); - } - } - - /** - * Log a message to the Log4j Logger with FATAL priority. - */ - public void fatal(Object message) - { - if (IS12) - { - getLogger().log(FQCN, Level.FATAL, message, null); - } - else - { - getLogger().log(FQCN, Level.FATAL, message, null); - } - } - - /** - * Log an error to the Log4j Logger with FATAL priority. - */ - public void fatal(Object message, Throwable t) - { - if (IS12) - { - getLogger().log(FQCN, Level.FATAL, message, t); - } - else - { - getLogger().log(FQCN, Level.FATAL, message, t); - } - } - - /** - * Return the native Logger instance we are using. - */ - public final Logger getLogger() - { - if (logger == null) - { - logger = Logger.getLogger(name); - } - return this.logger; - } - - /** - * Check whether the Log4j Logger used is enabled for DEBUG - * priority. - */ - public boolean isDebugEnabled() - { - return getLogger().isDebugEnabled(); - } - - /** - * Check whether the Log4j Logger used is enabled for ERROR - * priority. - */ - public boolean isErrorEnabled() - { - if (IS12) - { - return getLogger().isEnabledFor(Level.ERROR); - } - return getLogger().isEnabledFor(Level.ERROR); - } - - /** - * Check whether the Log4j Logger used is enabled for FATAL - * priority. - */ - public boolean isFatalEnabled() - { - if (IS12) - { - return getLogger().isEnabledFor(Level.FATAL); - } - return getLogger().isEnabledFor(Level.FATAL); - } - - /** - * Check whether the Log4j Logger used is enabled for INFO - * priority. - */ - public boolean isInfoEnabled() - { - return getLogger().isInfoEnabled(); - } - - /** - * Check whether the Log4j Logger used is enabled for TRACE - * priority. For Log4J, this returns the value of - * isDebugEnabled() - */ - public boolean isTraceEnabled() - { - return getLogger().isDebugEnabled(); - } - - /** - * Check whether the Log4j Logger used is enabled for WARN - * priority. - */ - public boolean isWarnEnabled() - { - if (IS12) - { - return getLogger().isEnabledFor(Level.WARN); - } - return getLogger().isEnabledFor(Level.WARN); - } + // ------------------------------------------------------------- Attributes + + /** + * The serial version identifier. + */ + private static final long serialVersionUID = 3545240215095883829L; + + /** The fully qualified name of the Log4JLogger class. */ + private static final String FQCN = Log4JLogger.class.getName(); + + /** Log to this logger */ + private transient final AbstractLogger logger; + + /** + * Base constructor. + */ + public Log4JLogger(Class clazz) + { + this.logger = (AbstractLogger) LogManager.getLogger(clazz.getName()); + } + + // --------------------------------------------------------- Implementation + + /** + * Log a message to the Log4j Logger with TRACE priority. + * Currently logs to DEBUG level in Log4J. + */ + public void trace(Object message) + { + logger.logIfEnabled(FQCN, Level.TRACE, null, message, (Throwable) null); + } + + /** + * Log an error to the Log4j Logger with TRACE priority. + * Currently logs to DEBUG level in Log4J. + */ + public void trace(Object message, Throwable t) + { + logger.logIfEnabled(FQCN, Level.TRACE, null, message, t); + } + + /** + * Log a message to the Log4j Logger with DEBUG priority. + */ + @Override + public void debug(Object message) + { + logger.logIfEnabled(FQCN, Level.DEBUG, null, message, (Throwable) null); + } + + /** + * Log an error to the Log4j Logger with DEBUG priority. + */ + @Override + public void debug(Object message, Throwable t) + { + logger.logIfEnabled(FQCN, Level.DEBUG, null, message, t); + } + + /** + * Log a message to the Log4j Logger with INFO priority. + */ + @Override + public void info(Object message) + { + logger.logIfEnabled(FQCN, Level.INFO, null, message, (Throwable) null); + + } + + /** + * Log an error to the Log4j Logger with INFO priority. + */ + public void info(Object message, Throwable t) + { + logger.logIfEnabled(FQCN, Level.INFO, null, message, t); + } + + /** + * Log a message to the Log4j Logger with WARN priority. + */ + @Override + public void warn(Object message) + { + logger.logIfEnabled(FQCN, Level.WARN, null, message, (Throwable) null); + } + + /** + * Log an error to the Log4j Logger with WARN priority. + */ + @Override + public void warn(Object message, Throwable t) + { + logger.logIfEnabled(FQCN, Level.WARN, null, message, t); + } + + /** + * Log a message to the Log4j Logger with ERROR priority. + */ + @Override + public void error(Object message) + { + logger.logIfEnabled(FQCN, Level.ERROR, null, message, (Throwable) null); + } + + /** + * Log an error to the Log4j Logger with ERROR priority. + */ + @Override + public void error(Object message, Throwable t) + { + logger.logIfEnabled(FQCN, Level.ERROR, null, message, t); + } + + /** + * Log a message to the Log4j Logger with FATAL priority. + */ + public void fatal(Object message) + { + logger.logIfEnabled(FQCN, Level.FATAL, null, message, (Throwable) null); + } + + /** + * Log an error to the Log4j Logger with FATAL priority. + */ + public void fatal(Object message, Throwable t) + { + logger.logIfEnabled(FQCN, Level.FATAL, null, message, t); + } + + /** + * Return the native Logger instance we are using. + */ + public final Logger getLogger() + { + return logger; + } + + /** + * Check whether the Log4j Logger used is enabled for DEBUG + * priority. + */ + @Override + public boolean isDebugEnabled() + { + return logger.isDebugEnabled(); + } + + /** + * Check whether the Log4j Logger used is enabled for ERROR + * priority. + */ + public boolean isErrorEnabled() + { + return logger.isErrorEnabled(); + + } + + /** + * Check whether the Log4j Logger used is enabled for FATAL + * priority. + */ + public boolean isFatalEnabled() + { + return logger.isFatalEnabled(); + + } + + /** + * Check whether the Log4j Logger used is enabled for INFO + * priority. + */ + public boolean isInfoEnabled() + { + return logger.isInfoEnabled(); + } + + /** + * Check whether the Log4j Logger used is enabled for TRACE + * priority. For Log4J, this returns the value of + * isDebugEnabled() + */ + public boolean isTraceEnabled() + { + return logger.isDebugEnabled(); + } + + /** + * Check whether the Log4j Logger used is enabled for WARN + * priority. + */ + public boolean isWarnEnabled() + { + return logger.isWarnEnabled(); + } } From 17bc2578ecb442d44fb181cdfb9046b0ecb764b1 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 10:58:11 +1100 Subject: [PATCH 475/802] update readme to next release --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e048aacd6..143379180 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.14.0 + 3.16.0 Asterisk-Java 2.x (Java 1.7 and Asterisk < Version 10) (branch 2.0.4) From 1167f0b6aa0318ad42d3840b679b128c058c2a3d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 10:58:34 +1100 Subject: [PATCH 476/802] for version 3.16.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8a6ab8119..5b39d1ae3 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.15.0 + 3.16.0 UTF-8 From 3eb1cdd08468729b59b1e0e9324d0fa776944288 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 11:14:26 +1100 Subject: [PATCH 477/802] fix dependency --- pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 5b39d1ae3..afada703f 100644 --- a/pom.xml +++ b/pom.xml @@ -173,15 +173,15 @@ 30.1-jre - - org.apache.logging.log4j - log4j-slf4j-impl - 2.15.0 + org.slf4j + slf4j-api + 1.7.26 + compile org.apache.logging.log4j log4j-core - 2.15.0 + 2.16.0 provided From 6ba5a1ae4e0294bc96aa4ca496e1eda7e99e263d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 11:16:20 +1100 Subject: [PATCH 478/802] update version number in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 143379180..16552310d 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.16.0 + 3.17.0 Asterisk-Java 2.x (Java 1.7 and Asterisk < Version 10) (branch 2.0.4) From d47ea3ac1ed2b351de0a20f74359830e57a4a4de Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 11:17:02 +1100 Subject: [PATCH 479/802] for version 3.17.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index afada703f..3cb0c19dc 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.16.0 + 3.17.0 UTF-8 From b7464128dff1145ebaa0670bb1bebd0d2abcb0ae Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 12:15:37 +1100 Subject: [PATCH 480/802] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16552310d..dd8217b5f 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.17.0 + 3.18.0 Asterisk-Java 2.x (Java 1.7 and Asterisk < Version 10) (branch 2.0.4) From 6900dc8768e7c77c2edd83d1edadcd6a46f4b50e Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 12:16:04 +1100 Subject: [PATCH 481/802] for version 3.18.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3cb0c19dc..0b69a1d0c 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.17.0 + 3.18.0 UTF-8 From b43202c4e55bd5806058ccf02b67cb049f86c7d2 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 15:48:00 +1100 Subject: [PATCH 482/802] auto update readme for release --- README.md | 9 --------- triggerRelease.dart | 23 +++++++++++++++++++++-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index dd8217b5f..9a6ac8155 100644 --- a/README.md +++ b/README.md @@ -52,15 +52,6 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) 3.18.0 -Asterisk-Java 2.x (Java 1.7 and Asterisk < Version 10) (branch 2.0.4) - - - org.asteriskjava - asterisk-java - 2.2.0 - - - INSTALLATION FROM SOURCE ------------------------ diff --git a/triggerRelease.dart b/triggerRelease.dart index cc95b94af..203b247e6 100755 --- a/triggerRelease.dart +++ b/triggerRelease.dart @@ -36,7 +36,8 @@ void main() { String version = "$major.$minor.$rev$postFix"; - replace(join(dir, "pom.xml"), version); + replacePomVersion(join(dir, "pom.xml"), version); + replaceReadMeVersion(join(dir, "pom.xml"), version); 'git pull'.run; 'git add .'.run; @@ -46,7 +47,25 @@ void main() { 'git push origin tag $version'.run; } -void replace(String path, String version) { + 3.18.0 + +void replaceReadMeVersion(String path, String version) { + var tmp = '$path.tmp'; + if (exists(tmp)) { + delete(tmp); + } + read(path).forEach((line) { + if (line.contains("")) { + line = " $version"; + } + tmp.append(line); + }); + move(path, '$path.bak'); + move(tmp, path); + delete('$path.bak'); +} + +void replacePomVersion(String path, String version) { var tmp = '$path.tmp'; if (exists(tmp)) { delete(tmp); From 13859fdc5da5e68676441a5091aa0e09effa89b2 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 15:51:17 +1100 Subject: [PATCH 483/802] fix script --- triggerRelease.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/triggerRelease.dart b/triggerRelease.dart index 203b247e6..e1a4c6d7e 100755 --- a/triggerRelease.dart +++ b/triggerRelease.dart @@ -47,8 +47,6 @@ void main() { 'git push origin tag $version'.run; } - 3.18.0 - void replaceReadMeVersion(String path, String version) { var tmp = '$path.tmp'; if (exists(tmp)) { From e695cadbbc68d4e9f86ef18c2047907ca6c25017 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 15:51:28 +1100 Subject: [PATCH 484/802] for version 3.19.0 --- pom.xml | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/pom.xml b/pom.xml index 0b69a1d0c..1f6f3d9b3 100644 --- a/pom.xml +++ b/pom.xml @@ -5,13 +5,13 @@ org.asteriskjava asterisk-java Asterisk-Java - ${releaseVersion} + 3.19.0 The free Java library for Asterisk PBX integration. 2004 - 3.18.0 + 3.19.0 UTF-8 @@ -91,7 +91,7 @@ org.apache.maven.plugins maven-jar-plugin - 2.5 + 3.19.0 true @@ -99,7 +99,7 @@ biz.aQute.bnd bnd-maven-plugin - 3.2.0 + 3.19.0 @@ -111,7 +111,7 @@ org.apache.maven.plugins maven-release-plugin - 2.5.3 + 3.19.0 true false @@ -122,7 +122,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.19.0 1.8 1.8 @@ -131,11 +131,11 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M4 + 3.19.0 maven-assembly-plugin - 2.5.3 + 3.19.0 ${project.basedir}/src/main/assembly/bin.xml @@ -158,42 +158,42 @@ org.easymock easymock - 3.3 + 3.19.0 test junit junit - 4.13.2 + 3.19.0 test com.google.guava guava - 30.1-jre + 3.19.0 org.slf4j slf4j-api - 1.7.26 + 3.19.0 compile org.apache.logging.log4j log4j-core - 2.16.0 + 3.19.0 provided ch.qos.logback logback-classic - 1.2.0 + 3.19.0 test org.reflections reflections - 0.9.12 + 3.19.0 @@ -204,7 +204,7 @@ org.apache.maven.plugins maven-source-plugin - 2.4 + 3.19.0 attach-sources @@ -217,7 +217,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.3 + 3.19.0 attach-javadocs @@ -255,7 +255,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.6 + 3.19.0 EA919AF2 @@ -279,7 +279,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.7 + 3.19.0 true ossrh From b76ebe66ff824f2b2a5189b2bf0a3326d7fefc9a Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 15:53:40 +1100 Subject: [PATCH 485/802] fix pom and script --- pom.xml | 38 +++++++++++++++++++------------------- triggerRelease.dart | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index 1f6f3d9b3..70ab78fb8 100644 --- a/pom.xml +++ b/pom.xml @@ -5,13 +5,13 @@ org.asteriskjava asterisk-java Asterisk-Java - 3.19.0 + ${releaseVersion} The free Java library for Asterisk PBX integration. 2004 - 3.19.0 + 3.20.0 UTF-8 @@ -91,7 +91,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.19.0 + 2.5 true @@ -99,7 +99,7 @@ biz.aQute.bnd bnd-maven-plugin - 3.19.0 + 3.2.0 @@ -111,7 +111,7 @@ org.apache.maven.plugins maven-release-plugin - 3.19.0 + 2.5.3 true false @@ -122,7 +122,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.19.0 + 3.2 1.8 1.8 @@ -131,11 +131,11 @@ org.apache.maven.plugins maven-surefire-plugin - 3.19.0 + 3.0.0-M4 maven-assembly-plugin - 3.19.0 + 2.5.3 ${project.basedir}/src/main/assembly/bin.xml @@ -158,42 +158,42 @@ org.easymock easymock - 3.19.0 + 3.3 test junit junit - 3.19.0 + 4.13.2 test com.google.guava guava - 3.19.0 + 30.1-jre org.slf4j slf4j-api - 3.19.0 + 1.7.26 compile org.apache.logging.log4j log4j-core - 3.19.0 + 2.16.0 provided ch.qos.logback logback-classic - 3.19.0 + 1.2.0 test org.reflections reflections - 3.19.0 + 0.9.12 @@ -204,7 +204,7 @@ org.apache.maven.plugins maven-source-plugin - 3.19.0 + 2.4 attach-sources @@ -217,7 +217,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.19.0 + 2.10.3 attach-javadocs @@ -255,7 +255,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.19.0 + 1.6 EA919AF2 @@ -279,7 +279,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 3.19.0 + 1.6.7 true ossrh diff --git a/triggerRelease.dart b/triggerRelease.dart index e1a4c6d7e..a4f46645a 100755 --- a/triggerRelease.dart +++ b/triggerRelease.dart @@ -37,7 +37,7 @@ void main() { String version = "$major.$minor.$rev$postFix"; replacePomVersion(join(dir, "pom.xml"), version); - replaceReadMeVersion(join(dir, "pom.xml"), version); + replaceReadMeVersion(join(dir, "README.MD"), version); 'git pull'.run; 'git add .'.run; From 89515f0487d8b297b1a6e1ecb04f7c6b7964dbcd Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 15:55:02 +1100 Subject: [PATCH 486/802] fix typo --- triggerRelease.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triggerRelease.dart b/triggerRelease.dart index a4f46645a..8399effad 100755 --- a/triggerRelease.dart +++ b/triggerRelease.dart @@ -37,7 +37,7 @@ void main() { String version = "$major.$minor.$rev$postFix"; replacePomVersion(join(dir, "pom.xml"), version); - replaceReadMeVersion(join(dir, "README.MD"), version); + replaceReadMeVersion(join(dir, "README.md"), version); 'git pull'.run; 'git add .'.run; From 83f980f25cad53da9918cfb39648a70129458dd9 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 15:55:15 +1100 Subject: [PATCH 487/802] rev --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 70ab78fb8..52b9305e5 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.20.0 + 3.21.0 UTF-8 From a7f895a0d04f95e72853d9122a09abc38ddc3b3f Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Wed, 15 Dec 2021 15:55:30 +1100 Subject: [PATCH 488/802] for version 3.22.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9a6ac8155..b741c4479 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.18.0 + 3.22.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 52b9305e5..f54d6170c 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.21.0 + 3.22.0 UTF-8 From e44ac6c3a9321a547df9bf321d56537a8fc4a7e2 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 16 Dec 2021 08:05:52 +1100 Subject: [PATCH 489/802] for version 3.23.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b741c4479..5df6b8a2d 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.22.0 + 3.23.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index f54d6170c..9c911ccf3 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.22.0 + 3.23.0 UTF-8 From 57f17cc7198b00986123dad0f9f3ea2586993bff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 18 Dec 2021 18:39:35 +0000 Subject: [PATCH 490/802] Bump log4j-core from 2.16.0 to 2.17.0 Bumps log4j-core from 2.16.0 to 2.17.0. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9c911ccf3..9b16597ee 100644 --- a/pom.xml +++ b/pom.xml @@ -181,7 +181,7 @@ org.apache.logging.log4j log4j-core - 2.16.0 + 2.17.0 provided From 6db3938d44b01b430a832ee3930f86facc91be45 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 20 Dec 2021 09:11:20 +1100 Subject: [PATCH 491/802] for version 3.24.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5df6b8a2d..663c4f2d0 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.23.0 + 3.24.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 9b16597ee..2ef53ca33 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.23.0 + 3.24.0 UTF-8 From 55bfa504d7670db72d7ef7423dd9a293d4514f6b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jan 2022 16:58:34 +0000 Subject: [PATCH 492/802] Bump log4j-core from 2.17.0 to 2.17.1 Bumps log4j-core from 2.17.0 to 2.17.1. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2ef53ca33..0d9f62166 100644 --- a/pom.xml +++ b/pom.xml @@ -181,7 +181,7 @@ org.apache.logging.log4j log4j-core - 2.17.0 + 2.17.1 provided From 3f23225b2ea2d7276b22891d671296c4dcfe05a8 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 31 Jan 2022 17:03:38 +1100 Subject: [PATCH 493/802] nump log4j version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2ef53ca33..0d9f62166 100644 --- a/pom.xml +++ b/pom.xml @@ -181,7 +181,7 @@ org.apache.logging.log4j log4j-core - 2.17.0 + 2.17.1 provided From 1103a4e3c11a680ecae94168e9df6f59b634da9d Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 31 Jan 2022 17:04:11 +1100 Subject: [PATCH 494/802] for version 3.25.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 663c4f2d0..ed1fbaf69 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.24.0 + 3.25.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 0d9f62166..0ae8b278c 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.24.0 + 3.25.0 UTF-8 From c898627aaeded752ccddd868d7bfdfb9f599f868 Mon Sep 17 00:00:00 2001 From: mcilibrizzi Date: Mon, 31 Jan 2022 22:56:45 +0100 Subject: [PATCH 495/802] Add wrapuptime getter and setter to QueueMemberEvent --- .../manager/event/QueueMemberEvent.java | 50 +++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java index 236abab97..2aef06cb5 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java @@ -21,7 +21,7 @@ * contains information about a member of a queue. *

    * It is implemented in apps/app_queue.c - * + * * @see org.asteriskjava.manager.action.QueueStatusAction * @author srt * @version $Id$ @@ -63,6 +63,7 @@ public class QueueMemberEvent extends ResponseEvent private String stateinterface; private Integer incall; private String pausedreason; + private Integer wrapuptime; private String _interface; /** @@ -75,7 +76,7 @@ public QueueMemberEvent(Object source) /** * Returns the name of the queue. - * + * * @return the name of the queue. */ public String getQueue() @@ -85,7 +86,7 @@ public String getQueue() /** * Sets the name of the queue. - * + * * @param queue the name of the queue. */ public void setQueue(String queue) @@ -107,7 +108,7 @@ final public String getInterface() /** * Sets the name of the member's interface. - * + * * @param member the name of the member's interface. */ final public void setInterface(String _interface) @@ -148,7 +149,7 @@ final public void setLocation(String _interface) * Returns if this member has been dynamically added by the QueueAdd command * (in the dialplan or via the Manager API) or if this member is has been * statically defined in queues.conf. - * + * * @return "dynamic" if the added member is a dynamic queue member, "static" * if the added member is a static queue member. */ @@ -160,7 +161,7 @@ public String getMembership() /** * Convenience method that checks whether this member has been statically * defined in queues.conf. - * + * * @return true if this member has been statically defined in * queues.conf, false otherwise. * @since 0.3 @@ -173,7 +174,7 @@ public boolean isStatic() /** * Convenience method that checks whether this member has been dynamically * added by the QueueAdd command. - * + * * @return true if this member has been dynamically added by * the QueueAdd command, false otherwise. * @since 0.3 @@ -185,7 +186,7 @@ public boolean isDynamic() /** * Sets if this member has been dynamically or statically added. - * + * * @param membership "dynamic" if the added member is a dynamic queue * member, "static" if the added member is a static queue member. */ @@ -197,7 +198,7 @@ public void setMembership(String membership) /** * Returns the penalty for the added member. When calls are distributed * members with higher penalties are considered last. - * + * * @return the penalty for the added member. */ public Integer getPenalty() @@ -207,7 +208,7 @@ public Integer getPenalty() /** * Sets the penalty for this member. - * + * * @param penalty the penalty for this member. */ public void setPenalty(Integer penalty) @@ -217,7 +218,7 @@ public void setPenalty(Integer penalty) /** * Returns the number of calls answered by the member. - * + * * @return the number of calls answered by the member. */ public Integer getCallsTaken() @@ -227,7 +228,7 @@ public Integer getCallsTaken() /** * Sets the number of calls answered by the added member. - * + * * @param callsTaken the number of calls answered by the added member. */ public void setCallsTaken(Integer callsTaken) @@ -238,7 +239,7 @@ public void setCallsTaken(Integer callsTaken) /** * Returns the time the last successful call answered by the added member * was hungup. - * + * * @return the time (in seconds since 01/01/1970) the last successful call * answered by the added member was hungup. */ @@ -250,7 +251,7 @@ public Long getLastCall() /** * Sets the time the last successful call answered by this member was * hungup. - * + * * @param lastCall the time (in seconds since 01/01/1970) the last * successful call answered by the added member was hungup. */ @@ -258,17 +259,17 @@ public void setLastCall(Long lastCall) { this.lastCall = lastCall; } - + /** * The time when started last pause for queue member. - * + * * @return the time (in seconds since 01/01/1970) */ public Long getLastPause() { return lastPause; } - + /** * Sets the time when started last pause for queue member. * @param lastPause the time (in seconds since 01/01/1970) @@ -304,7 +305,7 @@ public void setLastPause(Long lastPause) *

    AST_DEVICE_ONHOLD (8)
    *
    Device is on hold
    * - * + * * @return the status of this queue member or null if this * attribute is not supported by your version of Asterisk. * @since 0.2 @@ -316,7 +317,7 @@ public Integer getStatus() /** * Sets the status of this queue member. - * + * * @param status the status of this queue member * @since 0.2 */ @@ -329,7 +330,7 @@ public void setStatus(Integer status) * Is this queue member paused (not accepting calls)? *

    * Available since Asterisk 1.2. - * + * * @return Boolean.TRUE if this member has been paused, * Boolean.FALSE if not or null if pausing * is not supported by your version of Asterisk. @@ -342,7 +343,7 @@ public Boolean getPaused() /** * Sets if this member has been paused. - * + * * @since 0.2 */ public void setPaused(Boolean paused) @@ -422,4 +423,11 @@ public void setPausedreason(String pausedreason) this.pausedreason = pausedreason; } + public Integer getWrapuptime() { + return wrapuptime; + } + + public void setWrapuptime(Integer wrapuptime) { + this.wrapuptime = wrapuptime; + } } From d8b3f3805ac6d851de0443e6b9ce682563931eb2 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 8 Feb 2022 09:56:51 +1100 Subject: [PATCH 496/802] bump version of reflections --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0ae8b278c..2f8c78fcd 100644 --- a/pom.xml +++ b/pom.xml @@ -193,7 +193,7 @@ org.reflections reflections - 0.9.12 + 0.10.2 From f7621750cc143fb75cc08998f6291add409bb28b Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 8 Feb 2022 09:57:07 +1100 Subject: [PATCH 497/802] for version 3.26.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ed1fbaf69..e952487eb 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.25.0 + 3.26.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 2f8c78fcd..9c99cf806 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.25.0 + 3.26.0 UTF-8 From 67779365932b4fc546a9a983a1166fb8ddbf4750 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 28 Feb 2022 15:09:08 +1100 Subject: [PATCH 498/802] add cache to reduce amount of garbage created. --- .../pbx/internal/core/ChannelImpl.java | 1690 +++++++++-------- 1 file changed, 862 insertions(+), 828 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index 74060b348..c3227115e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -38,833 +38,867 @@ */ public class ChannelImpl implements Channel { - public static final String ZOMBIE = ""; //$NON-NLS-1$ - public static final String MASQ = ""; //$NON-NLS-1$ - - public static final String UNKNOWN_UNIQUE_ID = "-1"; //$NON-NLS-1$ - - private static final Log logger = LogFactory.getLog(ChannelImpl.class); - private static int logCounter = 100; - - /** - * The channel name including the tech and the channel sequence number but - * not the masquerade prefix and not the zombie suffix. Forced to upper case - * for comparisons. - */ - private String _channelName; - - /** - * A unique id created by Asterisk to uniquely identify this channel. Often - * a channel can be 're-created' on the fly. In this case the channels name - * will be the same but the unique id will change. - */ - private String _uniqueID; - /** - * This is an abbreviated form of the channel name obtained by removing - * everything after the '-' in the channel name. - */ - private EndPoint _endPoint; - - /** - * The caller id for this channel. If this is an inbound channel then it the - * callerid received from the remote end. If this is an outbound channel - * then this is the caller id we are to present to the remote end. - */ - private CallerID _callerID; - - /** - * A globally unique id assigned to each channel as it is created - */ - private long _channelId; - - private boolean _muted = false; - - private boolean _parked = false; - - private volatile boolean _isZombie = false; - - /** - * A channel is live if it has not been hungup. - */ - private boolean _isLive = true; - - /** - * Indicates that the channel is being masquerading by another channel. - * Masqueraded channels have an extra suffix after the sequence - * number e.g. SIP/100-000009823 - */ - private volatile boolean _isMasqueraded = false; - - /** - * Indicates that the channel is undergoing an action such as being parked. - * Action channels have an extra prefix before the tech e.g. - * Parked/SIP/100-000009823 - */ - private volatile boolean _isInAction = false; - - /** - * Indicates that the channel has been originated directly from the Asterisk - * console. We can generally ignore these cases. - */ - private boolean _isConsole = false; - - /** - * The prefix added to a channel during some type of action: e.g. - * Parked/SIP/100-0000032323 In this case the prefix is Parked. - */ - private String _actionPrefix = null; - - public static final String[] _actions = new String[]{"PARKED/", "ASYNCGOTO/", "BRIDGE/"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - - /** - * There should be only one hangup listener which is the ChannelProxy that - * wraps this channel. - */ - private ChannelHangupListener hangupListener; - - /** - * When validating channels the start time is set in the _sweepStartTime. as - * a channel is validated the _mark field is set to true. if new channels - * are created as the sweep is in progress the _sweepStartTime will not be - * set so they won't be cleaned up. - */ - private Long _sweepStartTime = null; - private boolean _marked = false; - - /** - * Creates a channel from a channelName
    - *
    - * This constructor is package private for a reason, and is called from - * AsteriskPBX... If you need to add a channel to the PBX do it like - * this
    - *
    - * AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX();
    - * final Channel channel = pbx.registerChannel(channelName, uniqueId);
    - *
    - * Channel names are one of the following formats: - * [Action/]Tech/EndPointName-[][ ] - * DAHDI/i/[:]-
    - *
    - * Where: [Action/] is an action that is being performed on a channel. e.g. - * Parked Tech is the Tech used to reach the end point.
    - *
    - * The set of supported techs are defined by the enum Tech.
    - *
    - * EndPointName the name of the endpoint.
    - *
    - * '' the optional terminating '' which indicates the channel is - * now being masqueraded. A masqueraded channel is one that has been cloned. - * The original channel is marked as being masqueraded and will hangup - * shortly. It plays no further part in the Call.
    - *
    - * '' the optional terminating '' which indicates the - * channel is now a zombie. A zombie channel is one that has been hungup and - * is awaiting final cleanup. I believe the zombie channel is used by the - * hangup extension 'h' in the dialplan.
    - *
    - * The channel name is stripped of the Action, MASQ and ZOMBIE elements. - * - * @param asteriskStateName - * @throws InvalidChannelName - */ - ChannelImpl(final String channelName, final String uniqueID) throws InvalidChannelName - { - if (uniqueID == null) - throw new IllegalArgumentException("The UniqueID may not be null."); //$NON-NLS-1$ - - if (channelName == null) - throw new IllegalArgumentException("The channelName may not be null."); //$NON-NLS-1$ - - if (uniqueID.compareToIgnoreCase("-1") == 0) - { - logger.debug("uniqueID is -1"); - } - - this._uniqueID = uniqueID; - - this.setChannelName(channelName); - - } - - /** - * designed for use by the ChannelProxy when a channel is being cloned as a - * result of Asterisk undertaking an Masquerade. This is not intended to be - * a complete clone just the key elements that we generally track on our - * side rather than getting directly from asterisk. - */ - public void masquerade(Channel channel) - { - // If the channel doesn't have a caller id - // preserve the existing one (as given this is a clone they should be - // identical). - // Asterisk doesn't always pass the caller ID on the channel hence this - // protects us from Asterisk accidentally clearing the caller id. - if (channel.hasCallerID()) - { - this._callerID = channel.getCallerID(); - } - else if (this._callerID != null && ((ChannelImpl) channel)._callerID != null) - { - // Force the caller id back into the channel so it has one as well. - PBX pbx = PBXFactory.getActivePBX(); - if (this._callerID != null) - { - ((ChannelImpl) channel)._callerID = pbx.buildCallerID(this._callerID.getNumber(), this._callerID.getName()); - } - } - - this._muted = channel.isMute(); - - this._parked = channel.isParked(); - - // just in case the original channel is part way through a sweep by the - // PeerMonitor - // marking the sweep as true will stop the new clone being hungup as it - // may not have been around when the sweep started. - this._marked = true; - this._sweepStartTime = null; - } - - private void setChannelName(final String channelName) throws InvalidChannelName - { - logger.debug("Renamed channel from " + this._channelName + " to " + channelName); - this._channelName = this.cleanChannelName(channelName); - this.validateChannelName(this._channelName); - - this._channelId = ChannelFactory.getNextChannelId(); - this._endPoint = new EndPointImpl(this.extractPeerName(this._channelName)); - - // After stripping everything from the channel name after the hypen - // we should have the endpoint name which shouldn't match the - // channel name - // unless its a channel caused by a console dial (Console/dsp) which - // we don't really care about. - // If the peer name still matches then we have a malformed channel - // name. - if ((this._channelName.compareTo(this.getEndPoint().getFullyQualifiedName()) == 0) && !this._isConsole) - { - if (ChannelImpl.logCounter > 0) - { - ChannelImpl.logger.warn("Invalid channel name " + this._channelName); //$NON-NLS-1$ - ChannelImpl.logCounter--; - } - else if (ChannelImpl.logCounter == 0) - { - ChannelImpl.logger.warn("Further Invalid channel name warnings suppressed"); //$NON-NLS-1$ - ChannelImpl.logCounter--; - } - } - } - - /** - * validates the channel name. Validate is to be called after the channel - * has been cleaned. - * - * @param channelName - * @throws InvalidChannelName - */ - private void validateChannelName(final String channelName) throws InvalidChannelName - { - if (!this._isConsole) - { - if (!TechType.hasValidTech(channelName)) - { - throw new InvalidChannelName("Invalid channelName: " + channelName + ". Unknown tech."); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Check we have the expected hypen - final int hypen = channelName.indexOf("-"); //$NON-NLS-1$ - if (hypen == -1) - { - throw new InvalidChannelName("Invalid channelName: " + channelName + ". Missing hypen."); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Check we have the expected slash - final int slash = channelName.indexOf("/"); //$NON-NLS-1$ - if (slash == -1) - { - throw new InvalidChannelName("Invalid channelName: " + channelName + ". Missing slash."); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Check that the hypen is after the slash. - if (hypen < slash) - { - throw new InvalidChannelName("Invalid channelName: " + channelName + ". Hypen must be after the slash."); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Check that there is at least one characters between the hypen and - // the - // slash - if ((hypen - slash) < 2) - { - throw new InvalidChannelName("Invalid channelName: " + channelName //$NON-NLS-1$ - + ". Must be one character between the hypen and the slash."); //$NON-NLS-1$ - } - - // Check that the channel sequence number is at least 1 character - // long. - if ((channelName.length() - hypen) < 2) - { - throw new InvalidChannelName("Invalid channelName: " + channelName //$NON-NLS-1$ - + ". The channel sequence number must be at least 1 character."); //$NON-NLS-1$ - } - } - - } - - /** - * Cleans up the channel name by applying the following: 1) trim any - * whitespace 2) convert to upper case for easy string comparisions 3) strip - * of the masquerade prefix if it exists and mark the channel as - * masquerading 4) strip the zombie suffix and mark it as being a zombie. - * - * @param name - * @return - */ - private String cleanChannelName(final String name) - { - String cleanedName = name.trim().toUpperCase(); - - // If if the channel is the console - this._isConsole = false; - if (name.compareToIgnoreCase("Console/dsp") == 0) //$NON-NLS-1$ - { - this._isConsole = true; - } - - // Check if the channel is in an action - boolean wasInAction = this._isInAction; - this._isInAction = false; - for (final String prefix : ChannelImpl._actions) - { - if (cleanedName.startsWith(prefix)) - { - this._isInAction = true; - this._actionPrefix = cleanedName.substring(0, prefix.length() - 1); - cleanedName = cleanedName.substring(prefix.length()); - break; - } - } - if (wasInAction != this._isInAction) - { - logger.debug("Channel " + this + " : inaction status changed from " + wasInAction + " to " + this._isInAction); - } - - // Channels can be marked as in a zombie state - // so we need to strip of the zombie suffix and just mark the channel - // as a - // zombie. - this._isZombie = false; - if (cleanedName.contains(ChannelImpl.ZOMBIE)) - { - this._isZombie = true; - cleanedName = cleanedName.substring(0, cleanedName.indexOf(ChannelImpl.ZOMBIE)); - } - - // Channels can be marked as in a MASQ state - // This happens during transfers (and other times) when the channel is - // replaced - // by a new channel in the call. The old channel is renamed with the - // word - // added as a suffix. - this._isMasqueraded = false; - if (cleanedName.contains(ChannelImpl.MASQ)) - { - this._isMasqueraded = true; - cleanedName = cleanedName.substring(0, cleanedName.indexOf(ChannelImpl.MASQ)); - } - - return cleanedName; - } - - @Override - public void rename(final String newName, String uniqueId) throws InvalidChannelName - { - - String oldChannelName = getChannelName(); - logger.info("Changing " + oldChannelName + " to " + newName + " on " + oldChannelName + " " + _uniqueID); - this.setChannelName(newName); - - if (_uniqueID.equalsIgnoreCase("-1")) - { - logger.info("Changing " + _uniqueID + " to " + uniqueId + " on " + oldChannelName + " " + _uniqueID); - _uniqueID = uniqueId; - } - - // the new replacement channel will go through a rename (without - // MASQ) and is ready to use. - - // the old channel will go through a rename (MASQ), then anther - // rename (ZOMBIE) and finally a hangup - - _isInAction = false; - - } - - @Override - public String getChannelName() - { - return this._channelName; - } - - @Override - public EndPoint getEndPoint() - { - return this._endPoint; - } - - /* - * Extracts the peer name from a full channel name. The channel name is - * created by asterisk and consists of the peer name a hypen and a unique - * sequence number. e.g. SIP/100-000000123 * For SIP channels the Peer name - * is of the form: SIP/100 For dahdi channels the channel name is of the - * form: DAHDI/i/[:]-0000000123 With the peer name - * of the form: DAHDI/i/[:] - */ - private final String extractPeerName(final String channelName) - { - // Find the start of the sequence number - int channelNameEndPoint = channelName.lastIndexOf("-"); //$NON-NLS-1$ - if (channelNameEndPoint == -1) - { - channelNameEndPoint = channelName.length(); - } - // return the peer name which is everything before the sequence number - // (and its hypen). - return channelName.substring(0, channelNameEndPoint); - } - - boolean wasMarkedDuringSweep() - { - boolean ret = false; - if (this._sweepStartTime == null || this._marked) - { - this._sweepStartTime = null; - ret = true; - } - return ret; - } - - public void setCallerId(final CallerID callerId) - { - this._callerID = callerId; - } - - /** - * Used to start the Mark and Sweep process by setting the marked status to - * false. At the end of the sweep the marked flag should have been set to - * true. If not then this channel has been hungup. - */ - void startSweep() - { - this._sweepStartTime = System.currentTimeMillis(); - this._marked = false; - } - - /** - * The channel was found to be active on asterisk so it is still alive. - */ - void markChannel() - { - this._marked = true; - - } - - /** - * ************************************************************************* - * ************************** The remaining methods are bridging methods to - * the new abstract PBX classes. - * ************************************************************************* - * ************************** - */ - @Override - public boolean isSame(final Channel _rhs) - { - boolean equals = false; - - if (_rhs == null) - { - logger.warn("isSame called with null"); - return false; - } - ChannelImpl rhs; - if (_rhs instanceof ChannelImpl) - { - rhs = (ChannelImpl) _rhs; - } - else - { - rhs = ((ChannelProxy) _rhs).getRealChannel(); - } - // If we have unique id's for both channels then we can compare the id's - // directly. - if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) - && (rhs._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) - { - if (this._uniqueID.compareToIgnoreCase(rhs._uniqueID) == 0) - { - equals = true; - } - } - else - { - boolean ok = (this._channelName != null) && (rhs._channelName != null); - final boolean namesMatch = (ok && (this._channelName.compareToIgnoreCase(rhs._channelName) == 0)); - - if (namesMatch) - { - // check if the actions match - if (this._isInAction != rhs._isInAction) - { - ok = false; - } - else if (this._isInAction) - { - ok = this._actionPrefix.compareTo(rhs._actionPrefix) == 0; - } - } - - if (ok && namesMatch) - { - // check if the zombie match - if (this._isZombie != rhs._isZombie) - { - ok = false; - } - } - - if (ok && namesMatch) - { - // check if the masquerade match - if (this._isMasqueraded != rhs._isMasqueraded) - { - ok = false; - } - } - - equals = ok & namesMatch; - } - return equals; - } - - @Override - public boolean isSame(final String extendedChannelName, final String uniqueID) - { - boolean equals = false; - if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) - && (uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) - { - if (this._uniqueID.compareTo(uniqueID) == 0) - { - equals = true; - } - } - else - { - equals = this.sameExtenededChannelName(extendedChannelName); - } - - return equals; - } - - @Override - public boolean sameExtenededChannelName(final String extendedChannelName) - { - boolean ok = (this.getExtendedChannelName() != null) && (extendedChannelName != null); - - return ok && (this.getExtendedChannelName().compareToIgnoreCase(extendedChannelName) == 0); - } - - /** - * Try to match a channel based solely on its unique ID - * - * @param uniqueID - * @return - */ - public boolean sameUniqueID(String uniqueID) - { - boolean equals = false; - if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) - && (uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) - { - if (this._uniqueID.compareTo(uniqueID) == 0) - { - equals = true; - } - } - - return equals; - } - - @Override - public boolean sameEndPoint(final Channel rhs) - { - return this.sameEndPoint(rhs.getEndPoint()); - } - - @Override - public boolean sameEndPoint(final EndPoint rhs) - { - boolean ok = (this._endPoint != null) && (rhs != null); - return ok && this._endPoint.isSame(rhs); - } - - @Override - public long getChannelId() - { - return this._channelId; - } - - @Override - public boolean isLive() - { - return this._isLive; - } - - @Override - public void addHangupListener(final ChannelHangupListener listener) - { - if (this.hangupListener != null) - throw new IllegalStateException("This channel may only have ONE listener which should be its ChannelProxy"); //$NON-NLS-1$ - - this.hangupListener = listener; - } - - @Override - public void removeListener(final ChannelHangupListener listener) - { - - if (this.hangupListener != listener) - throw new IllegalStateException("An invalid attempt was made to remove a non-existant listener."); //$NON-NLS-1$ - - this.hangupListener = null; - - } - - /** - * Called by Peer when we have been hungup. This can happen when Peer - * receives a HangupEvent or during a periodic sweep done by PeerMonitor to - * find the status of all channels. Notify any listeners that this channel - * has been hung up. - */ - @Override - public void notifyHangupListeners(Integer cause, String causeText) - { - this._isLive = false; - if (this.hangupListener != null) - { - this.hangupListener.channelHangup(this, cause, causeText); - } - else - { - logger.warn("Hangup listener is null"); - } - } - - @Override - public boolean isConnectedTo(final EndPoint endPoint) - { - return this._endPoint.isSame(endPoint); - } - - @Override - public boolean isMute() - { - return this._muted; - } - - @Override - public void setMute(final boolean mutedState) - { - this._muted = mutedState; - } - - @Override - public void setParked(final boolean parked) - { - this._parked = parked; - - } - - @Override - public boolean isParked() - { - return this._parked; - } - - @Override - public String toString() - { - return this.getExtendedChannelName() + ":" + this._uniqueID; //$NON-NLS-1$ - } - - /** - * Returns the full channel name including the masquerade prefix and the - * zombie suffix. - * - * @return - */ - @Override - public String getExtendedChannelName() - { - final StringBuilder name = new StringBuilder(); - - if (this._isInAction) - { - name.append(this._actionPrefix); - name.append("/"); //$NON-NLS-1$ - } - name.append(this._channelName); - - if (this._isMasqueraded) - { - name.append(ChannelImpl.MASQ); - } - - if (this._isZombie) - { - name.append(ChannelImpl.ZOMBIE); - } - - return name.toString(); - - } - - @Override - public boolean isLocal() - { - return this._endPoint.isLocal(); - } - - @Override - public boolean isZombie() - { - return this._isZombie; - } - - @Override - public boolean isConsole() - { - return this._isConsole; - } - - TechType getTech() - { - return this._endPoint.getTech(); - } - - /** - * Returns the actionPrefix for the channel or an empty string if the - * channel is not doing an action. - * - * @return - */ - String getActionPrefix() - { - return this._isInAction ? this._actionPrefix : ""; //$NON-NLS-1$ - } - - boolean isInAction() - { - return this._isInAction; - } - - boolean isMasqueraded() - { - return this._isMasqueraded; - } - - @Override - public boolean hasCallerID() - { - return this._callerID != null && !this._callerID.isUnknown(); - } - - @Override - public CallerID getCallerID() - { - if (this._callerID == null) - { - final CoherentManagerConnection smc = CoherentManagerConnection.getInstance(); - final String number = smc.getVariable(this, "CALLERID(number)"); //$NON-NLS-1$ - final String name = smc.getVariable(this, "CALLERID(name)"); //$NON-NLS-1$ - final PBX pbx = PBXFactory.getActivePBX(); - this._callerID = pbx.buildCallerID(number, name); - } - - return this._callerID; - - } - - @Override - public String getUniqueId() - { - return this._uniqueID; - } - - /* - * Returns true if this channel can detect hangups A SIP channel can always - * detect a hangup if its not channel then we need to check the profile to - * see if hangup detection is available. Hangup detection is important as we - * don't want to connect two channels both of which can't do hangup - * detection. If this happened then we would end up with a call which would - * never hangup. - */ - @Override - public boolean canDetectHangup() - { - boolean canDetectHangup = true; - - AsteriskSettings profile = PBXFactory.getActiveProfile(); - final boolean detect = profile.getCanDetectHangup(); - if (!this.getEndPoint().isSIP() && !detect) - { - canDetectHangup = false; - } - return canDetectHangup; - } - - /** - * Returns true if the channel is quiescent. A quescent channel is one that - * is current not going through a transition (name change) such as MASQ, - * ZOMBIE, ASYNC, PARK - * - * @return - */ - @Override - public boolean isQuiescent() - { - return !(_isInAction || _isMasqueraded || _isZombie); - } - - @Override - public AgiChannelActivityAction getCurrentActivityAction() - { - throw new RuntimeException("This method is only implemented in ChannelProxy"); - } - - @Override - public void setCurrentActivityAction(AgiChannelActivityAction action) - { - throw new RuntimeException("This method is only implemented in ChannelProxy"); - } - - @Override - public void setIsInAgi(boolean b) - { - throw new RuntimeException("This method is only implemented in ChannelProxy"); - } - - @Override - public boolean isInAgi() - { - throw new RuntimeException("This method is only implemented in ChannelProxy"); - } - - @Override - public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException - { - throw new RuntimeException("This method is only implemented in ChannelProxy"); - } + public static final String ZOMBIE = ""; //$NON-NLS-1$ + public static final String MASQ = ""; //$NON-NLS-1$ + + public static final String UNKNOWN_UNIQUE_ID = "-1"; //$NON-NLS-1$ + + private static final Log logger = LogFactory.getLog(ChannelImpl.class); + private static int logCounter = 100; + + /** + * The channel name including the tech and the channel sequence number but + * not the masquerade prefix and not the zombie suffix. Forced to upper case + * for comparisons. + */ + private String _channelName; + + /** + * A unique id created by Asterisk to uniquely identify this channel. Often + * a channel can be 're-created' on the fly. In this case the channels name + * will be the same but the unique id will change. + */ + private String _uniqueID; + /** + * This is an abbreviated form of the channel name obtained by removing + * everything after the '-' in the channel name. + */ + private EndPoint _endPoint; + + /** + * The caller id for this channel. If this is an inbound channel then it the + * callerid received from the remote end. If this is an outbound channel + * then this is the caller id we are to present to the remote end. + */ + private CallerID _callerID; + + /** + * A globally unique id assigned to each channel as it is created + */ + private long _channelId; + + private boolean _muted = false; + + private boolean _parked = false; + + private volatile boolean _isZombie = false; + + /** + * A channel is live if it has not been hungup. + */ + private boolean _isLive = true; + + /** + * Indicates that the channel is being masquerading by another channel. + * Masqueraded channels have an extra suffix after the sequence + * number e.g. SIP/100-000009823 + */ + private volatile boolean _isMasqueraded = false; + + /** + * Indicates that the channel is undergoing an action such as being parked. + * Action channels have an extra prefix before the tech e.g. + * Parked/SIP/100-000009823 + */ + private volatile boolean _isInAction = false; + + /** + * Indicates that the channel has been originated directly from the Asterisk + * console. We can generally ignore these cases. + */ + private boolean _isConsole = false; + + /** + * The prefix added to a channel during some type of action: e.g. + * Parked/SIP/100-0000032323 In this case the prefix is Parked. + */ + private String _actionPrefix = null; + + public static final String[] _actions = new String[] { "PARKED/", "ASYNCGOTO/", "BRIDGE/" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + /** + * There should be only one hangup listener which is the ChannelProxy that + * wraps this channel. + */ + private ChannelHangupListener hangupListener; + + /** + * When validating channels the start time is set in the _sweepStartTime. as + * a channel is validated the _mark field is set to true. if new channels + * are created as the sweep is in progress the _sweepStartTime will not be + * set so they won't be cleaned up. + */ + private Long _sweepStartTime = null; + private boolean _marked = false; + + /** + * Creates a channel from a channelName
    + *
    + * This constructor is package private for a reason, and is called from + * AsteriskPBX... If you need to add a channel to the PBX do it like + * this
    + *
    + * AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX();
    + * final Channel channel = pbx.registerChannel(channelName, uniqueId);
    + *
    + * Channel names are one of the following formats: + * [Action/]Tech/EndPointName-[][ ] + * DAHDI/i/[:]-
    + *
    + * Where: [Action/] is an action that is being performed on a channel. e.g. + * Parked Tech is the Tech used to reach the end point.
    + *
    + * The set of supported techs are defined by the enum Tech.
    + *
    + * EndPointName the name of the endpoint.
    + *
    + * '' the optional terminating '' which indicates the channel is + * now being masqueraded. A masqueraded channel is one that has been cloned. + * The original channel is marked as being masqueraded and will hangup + * shortly. It plays no further part in the Call.
    + *
    + * '' the optional terminating '' which indicates the + * channel is now a zombie. A zombie channel is one that has been hungup and + * is awaiting final cleanup. I believe the zombie channel is used by the + * hangup extension 'h' in the dialplan.
    + *
    + * The channel name is stripped of the Action, MASQ and ZOMBIE elements. + * + * @param asteriskStateName + * @throws InvalidChannelName + */ + ChannelImpl(final String channelName, final String uniqueID) throws InvalidChannelName + { + if (uniqueID == null) + throw new IllegalArgumentException("The UniqueID may not be null."); //$NON-NLS-1$ + + if (channelName == null) + throw new IllegalArgumentException("The channelName may not be null."); //$NON-NLS-1$ + + if (uniqueID.compareToIgnoreCase("-1") == 0) + { + logger.debug("uniqueID is -1"); + } + + this._uniqueID = uniqueID; + + this.setChannelName(channelName); + + } + + /** + * designed for use by the ChannelProxy when a channel is being cloned as a + * result of Asterisk undertaking an Masquerade. This is not intended to be + * a complete clone just the key elements that we generally track on our + * side rather than getting directly from asterisk. + */ + public void masquerade(Channel channel) + { + // If the channel doesn't have a caller id + // preserve the existing one (as given this is a clone they should be + // identical). + // Asterisk doesn't always pass the caller ID on the channel hence this + // protects us from Asterisk accidentally clearing the caller id. + if (channel.hasCallerID()) + { + this._callerID = channel.getCallerID(); + } + else if (this._callerID != null && ((ChannelImpl) channel)._callerID != null) + { + // Force the caller id back into the channel so it has one as well. + PBX pbx = PBXFactory.getActivePBX(); + if (this._callerID != null) + { + ((ChannelImpl) channel)._callerID = pbx.buildCallerID(this._callerID.getNumber(), + this._callerID.getName()); + } + } + + this._muted = channel.isMute(); + + this._parked = channel.isParked(); + + // just in case the original channel is part way through a sweep by the + // PeerMonitor + // marking the sweep as true will stop the new clone being hungup as it + // may not have been around when the sweep started. + this._marked = true; + this._sweepStartTime = null; + } + + private void setChannelName(final String channelName) throws InvalidChannelName + { + logger.debug("Renamed channel from " + this._channelName + " to " + channelName); + this._channelName = this.cleanChannelName(channelName); + this.validateChannelName(this._channelName); + + this._channelId = ChannelFactory.getNextChannelId(); + this._endPoint = new EndPointImpl(this.extractPeerName(this._channelName)); + + // After stripping everything from the channel name after the hypen + // we should have the endpoint name which shouldn't match the + // channel name + // unless its a channel caused by a console dial (Console/dsp) which + // we don't really care about. + // If the peer name still matches then we have a malformed channel + // name. + if ((this._channelName.compareTo(this.getEndPoint().getFullyQualifiedName()) == 0) && !this._isConsole) + { + if (ChannelImpl.logCounter > 0) + { + ChannelImpl.logger.warn("Invalid channel name " + this._channelName); //$NON-NLS-1$ + ChannelImpl.logCounter--; + } + else if (ChannelImpl.logCounter == 0) + { + ChannelImpl.logger.warn("Further Invalid channel name warnings suppressed"); //$NON-NLS-1$ + ChannelImpl.logCounter--; + } + } + } + + /** + * validates the channel name. Validate is to be called after the channel + * has been cleaned. + * + * @param channelName + * @throws InvalidChannelName + */ + private void validateChannelName(final String channelName) throws InvalidChannelName + { + if (!this._isConsole) + { + if (!TechType.hasValidTech(channelName)) + { + throw new InvalidChannelName("Invalid channelName: " + channelName + ". Unknown tech."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check we have the expected hypen + final int hypen = channelName.indexOf("-"); //$NON-NLS-1$ + if (hypen == -1) + { + throw new InvalidChannelName("Invalid channelName: " + channelName + ". Missing hypen."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check we have the expected slash + final int slash = channelName.indexOf("/"); //$NON-NLS-1$ + if (slash == -1) + { + throw new InvalidChannelName("Invalid channelName: " + channelName + ". Missing slash."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check that the hypen is after the slash. + if (hypen < slash) + { + throw new InvalidChannelName( + "Invalid channelName: " + channelName + ". Hypen must be after the slash."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check that there is at least one characters between the hypen and + // the + // slash + if ((hypen - slash) < 2) + { + throw new InvalidChannelName("Invalid channelName: " + channelName //$NON-NLS-1$ + + ". Must be one character between the hypen and the slash."); //$NON-NLS-1$ + } + + // Check that the channel sequence number is at least 1 character + // long. + if ((channelName.length() - hypen) < 2) + { + throw new InvalidChannelName("Invalid channelName: " + channelName //$NON-NLS-1$ + + ". The channel sequence number must be at least 1 character."); //$NON-NLS-1$ + } + } + + } + + /** + * Cleans up the channel name by applying the following: 1) trim any + * whitespace 2) convert to upper case for easy string comparisions 3) strip + * of the masquerade prefix if it exists and mark the channel as + * masquerading 4) strip the zombie suffix and mark it as being a zombie. + * + * @param name + * @return + */ + private String cleanChannelName(final String name) + { + String cleanedName = name.trim().toUpperCase(); + + // If if the channel is the console + this._isConsole = false; + if (name.compareToIgnoreCase("Console/dsp") == 0) //$NON-NLS-1$ + { + this._isConsole = true; + } + + // Check if the channel is in an action + boolean wasInAction = this._isInAction; + this._isInAction = false; + for (final String prefix : ChannelImpl._actions) + { + if (cleanedName.startsWith(prefix)) + { + this._isInAction = true; + this._actionPrefix = cleanedName.substring(0, prefix.length() - 1); + cleanedName = cleanedName.substring(prefix.length()); + break; + } + } + if (wasInAction != this._isInAction) + { + logger.debug( + "Channel " + this + " : inaction status changed from " + wasInAction + " to " + this._isInAction); + } + + // Channels can be marked as in a zombie state + // so we need to strip of the zombie suffix and just mark the channel + // as a + // zombie. + this._isZombie = false; + if (cleanedName.contains(ChannelImpl.ZOMBIE)) + { + this._isZombie = true; + cleanedName = cleanedName.substring(0, cleanedName.indexOf(ChannelImpl.ZOMBIE)); + } + + // Channels can be marked as in a MASQ state + // This happens during transfers (and other times) when the channel is + // replaced + // by a new channel in the call. The old channel is renamed with the + // word + // added as a suffix. + this._isMasqueraded = false; + if (cleanedName.contains(ChannelImpl.MASQ)) + { + this._isMasqueraded = true; + cleanedName = cleanedName.substring(0, cleanedName.indexOf(ChannelImpl.MASQ)); + } + + return cleanedName; + } + + @Override + public void rename(final String newName, String uniqueId) throws InvalidChannelName + { + + String oldChannelName = getChannelName(); + logger.info("Changing " + oldChannelName + " to " + newName + " on " + oldChannelName + " " + _uniqueID); + this.setChannelName(newName); + + if (_uniqueID.equalsIgnoreCase("-1")) + { + logger.info("Changing " + _uniqueID + " to " + uniqueId + " on " + oldChannelName + " " + _uniqueID); + _uniqueID = uniqueId; + } + + // the new replacement channel will go through a rename (without + // MASQ) and is ready to use. + + // the old channel will go through a rename (MASQ), then anther + // rename (ZOMBIE) and finally a hangup + + _isInAction = false; + + } + + @Override + public String getChannelName() + { + return this._channelName; + } + + @Override + public EndPoint getEndPoint() + { + return this._endPoint; + } + + /* + * Extracts the peer name from a full channel name. The channel name is + * created by asterisk and consists of the peer name a hypen and a unique + * sequence number. e.g. SIP/100-000000123 * For SIP channels the Peer name + * is of the form: SIP/100 For dahdi channels the channel name is of the + * form: DAHDI/i/[:]-0000000123 With the peer name + * of the form: DAHDI/i/[:] + */ + private final String extractPeerName(final String channelName) + { + // Find the start of the sequence number + int channelNameEndPoint = channelName.lastIndexOf("-"); //$NON-NLS-1$ + if (channelNameEndPoint == -1) + { + channelNameEndPoint = channelName.length(); + } + // return the peer name which is everything before the sequence number + // (and its hypen). + return channelName.substring(0, channelNameEndPoint); + } + + boolean wasMarkedDuringSweep() + { + boolean ret = false; + if (this._sweepStartTime == null || this._marked) + { + this._sweepStartTime = null; + ret = true; + } + return ret; + } + + @Override + public void setCallerId(final CallerID callerId) + { + this._callerID = callerId; + } + + /** + * Used to start the Mark and Sweep process by setting the marked status to + * false. At the end of the sweep the marked flag should have been set to + * true. If not then this channel has been hungup. + */ + void startSweep() + { + this._sweepStartTime = System.currentTimeMillis(); + this._marked = false; + } + + /** + * The channel was found to be active on asterisk so it is still alive. + */ + void markChannel() + { + this._marked = true; + + } + + /** + * ************************************************************************* + * ************************** The remaining methods are bridging methods to + * the new abstract PBX classes. + * ************************************************************************* + * ************************** + */ + @Override + public boolean isSame(final Channel _rhs) + { + boolean equals = false; + + if (_rhs == null) + { + logger.warn("isSame called with null"); + return false; + } + ChannelImpl rhs; + if (_rhs instanceof ChannelImpl) + { + rhs = (ChannelImpl) _rhs; + } + else + { + rhs = ((ChannelProxy) _rhs).getRealChannel(); + } + // If we have unique id's for both channels then we can compare the id's + // directly. + if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) + && (rhs._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) + { + if (this._uniqueID.compareToIgnoreCase(rhs._uniqueID) == 0) + { + equals = true; + } + } + else + { + boolean ok = (this._channelName != null) && (rhs._channelName != null); + final boolean namesMatch = (ok && (this._channelName.compareToIgnoreCase(rhs._channelName) == 0)); + + if (namesMatch) + { + // check if the actions match + if (this._isInAction != rhs._isInAction) + { + ok = false; + } + else if (this._isInAction) + { + ok = this._actionPrefix.compareTo(rhs._actionPrefix) == 0; + } + } + + if (ok && namesMatch) + { + // check if the zombie match + if (this._isZombie != rhs._isZombie) + { + ok = false; + } + } + + if (ok && namesMatch) + { + // check if the masquerade match + if (this._isMasqueraded != rhs._isMasqueraded) + { + ok = false; + } + } + + equals = ok & namesMatch; + } + return equals; + } + + @Override + public boolean isSame(final String extendedChannelName, final String uniqueID) + { + boolean equals = false; + if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) + && (uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) + { + if (this._uniqueID.compareTo(uniqueID) == 0) + { + equals = true; + } + } + else + { + equals = this.sameExtenededChannelName(extendedChannelName); + } + + return equals; + } + + @Override + public boolean sameExtenededChannelName(final String extendedChannelName) + { + boolean ok = (this.getExtendedChannelName() != null) && (extendedChannelName != null); + + return ok && (this.getExtendedChannelName().compareToIgnoreCase(extendedChannelName) == 0); + } + + /** + * Try to match a channel based solely on its unique ID + * + * @param uniqueID + * @return + */ + public boolean sameUniqueID(String uniqueID) + { + boolean equals = false; + if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) + && (uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) + { + if (this._uniqueID.compareTo(uniqueID) == 0) + { + equals = true; + } + } + + return equals; + } + + @Override + public boolean sameEndPoint(final Channel rhs) + { + return this.sameEndPoint(rhs.getEndPoint()); + } + + @Override + public boolean sameEndPoint(final EndPoint rhs) + { + boolean ok = (this._endPoint != null) && (rhs != null); + return ok && this._endPoint.isSame(rhs); + } + + @Override + public long getChannelId() + { + return this._channelId; + } + + @Override + public boolean isLive() + { + return this._isLive; + } + + @Override + public void addHangupListener(final ChannelHangupListener listener) + { + if (this.hangupListener != null) + throw new IllegalStateException("This channel may only have ONE listener which should be its ChannelProxy"); //$NON-NLS-1$ + + this.hangupListener = listener; + } + + @Override + public void removeListener(final ChannelHangupListener listener) + { + + if (this.hangupListener != listener) + throw new IllegalStateException("An invalid attempt was made to remove a non-existant listener."); //$NON-NLS-1$ + + this.hangupListener = null; + + } + + /** + * Called by Peer when we have been hungup. This can happen when Peer + * receives a HangupEvent or during a periodic sweep done by PeerMonitor to + * find the status of all channels. Notify any listeners that this channel + * has been hung up. + */ + @Override + public void notifyHangupListeners(Integer cause, String causeText) + { + this._isLive = false; + if (this.hangupListener != null) + { + this.hangupListener.channelHangup(this, cause, causeText); + } + else + { + logger.warn("Hangup listener is null"); + } + } + + @Override + public boolean isConnectedTo(final EndPoint endPoint) + { + return this._endPoint.isSame(endPoint); + } + + @Override + public boolean isMute() + { + return this._muted; + } + + @Override + public void setMute(final boolean mutedState) + { + this._muted = mutedState; + } + + @Override + public void setParked(final boolean parked) + { + this._parked = parked; + + } + + @Override + public boolean isParked() + { + return this._parked; + } + + @Override + public String toString() + { + return this.getExtendedChannelName() + ":" + this._uniqueID; //$NON-NLS-1$ + } + + /** + * Returns the full channel name including the masquerade prefix and the + * zombie suffix. + * + * @return + */ + + @Override + public String getExtendedChannelName() + { + int state = getState(); + if (state != lastState || !_channelName.equals(lastChannelName)) + { + final StringBuilder name = new StringBuilder(); + + if (this._isInAction) + { + name.append(this._actionPrefix); + name.append("/"); //$NON-NLS-1$ + } + name.append(this._channelName); + + if (this._isMasqueraded) + { + name.append(ChannelImpl.MASQ); + } + + if (this._isZombie) + { + name.append(ChannelImpl.ZOMBIE); + } + lastState = state; + lastChannelName = _channelName; + cachedExtenedChannelName = name.toString(); + + } + return cachedExtenedChannelName; + + } + + String cachedExtenedChannelName = null; + int lastState = -1; + String lastChannelName = null; + + int getState() + { + int state = 0; + if (_isInAction) + { + state += 2; + } + if (_isZombie) + { + state += 4; + } + if (_isMasqueraded) + { + state += 8; + } + return state; + } + + @Override + public boolean isLocal() + { + return this._endPoint.isLocal(); + } + + @Override + public boolean isZombie() + { + return this._isZombie; + } + + @Override + public boolean isConsole() + { + return this._isConsole; + } + + TechType getTech() + { + return this._endPoint.getTech(); + } + + /** + * Returns the actionPrefix for the channel or an empty string if the + * channel is not doing an action. + * + * @return + */ + String getActionPrefix() + { + return this._isInAction ? this._actionPrefix : ""; //$NON-NLS-1$ + } + + boolean isInAction() + { + return this._isInAction; + } + + boolean isMasqueraded() + { + return this._isMasqueraded; + } + + @Override + public boolean hasCallerID() + { + return this._callerID != null && !this._callerID.isUnknown(); + } + + @Override + public CallerID getCallerID() + { + if (this._callerID == null) + { + final CoherentManagerConnection smc = CoherentManagerConnection.getInstance(); + final String number = smc.getVariable(this, "CALLERID(number)"); //$NON-NLS-1$ + final String name = smc.getVariable(this, "CALLERID(name)"); //$NON-NLS-1$ + final PBX pbx = PBXFactory.getActivePBX(); + this._callerID = pbx.buildCallerID(number, name); + } + + return this._callerID; + + } + + @Override + public String getUniqueId() + { + return this._uniqueID; + } + + /* + * Returns true if this channel can detect hangups A SIP channel can always + * detect a hangup if its not channel then we need to check the profile to + * see if hangup detection is available. Hangup detection is important as we + * don't want to connect two channels both of which can't do hangup + * detection. If this happened then we would end up with a call which would + * never hangup. + */ + @Override + public boolean canDetectHangup() + { + boolean canDetectHangup = true; + + AsteriskSettings profile = PBXFactory.getActiveProfile(); + final boolean detect = profile.getCanDetectHangup(); + if (!this.getEndPoint().isSIP() && !detect) + { + canDetectHangup = false; + } + return canDetectHangup; + } + + /** + * Returns true if the channel is quiescent. A quescent channel is one that + * is current not going through a transition (name change) such as MASQ, + * ZOMBIE, ASYNC, PARK + * + * @return + */ + @Override + public boolean isQuiescent() + { + return !(_isInAction || _isMasqueraded || _isZombie); + } + + @Override + public AgiChannelActivityAction getCurrentActivityAction() + { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public void setCurrentActivityAction(AgiChannelActivityAction action) + { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public void setIsInAgi(boolean b) + { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public boolean isInAgi() + { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException + { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } } From 901ca308d90a8d1f0160fbe985777e863b714104 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Mon, 28 Feb 2022 15:51:19 +1100 Subject: [PATCH 499/802] for version 3.27.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e952487eb..d959acae8 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.26.0 + 3.27.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 9c99cf806..0ac7b0d25 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.26.0 + 3.27.0 UTF-8 From bc14ca072bc057112837ffe7d82653eafdcdb3f7 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Fri, 18 Mar 2022 12:15:48 +1100 Subject: [PATCH 500/802] for version 3.28.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d959acae8..e8f2f3776 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.27.0 + 3.28.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 0ac7b0d25..07143e0dd 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.27.0 + 3.28.0 UTF-8 From c048b360dd536716bb133eda1fadf1e58a533bc1 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 28 Apr 2022 16:44:45 +1000 Subject: [PATCH 501/802] update log4j version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 07143e0dd..0f69b20e6 100644 --- a/pom.xml +++ b/pom.xml @@ -181,7 +181,7 @@ org.apache.logging.log4j log4j-core - 2.17.1 + 2.17.2 provided From ede147826337160ae9b7cb60799feadfd9b184e3 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Thu, 28 Apr 2022 16:48:16 +1000 Subject: [PATCH 502/802] for version 3.29.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e8f2f3776..cba8e57be 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.28.0 + 3.29.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 0f69b20e6..153573377 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.28.0 + 3.29.0 UTF-8 From 10bb9c8a794b0a385429a0b30271e4832328405c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 19 Jul 2022 16:53:51 +1000 Subject: [PATCH 503/802] update log4j version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 153573377..25135bca6 100644 --- a/pom.xml +++ b/pom.xml @@ -181,7 +181,7 @@ org.apache.logging.log4j log4j-core - 2.17.2 + 2.18.0 provided From 0bd88b50a04d55602eeeecf8a12c1af6a0d43917 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 19 Jul 2022 17:16:45 +1000 Subject: [PATCH 504/802] for version 3.30.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cba8e57be..3ef75df8e 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.29.0 + 3.30.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 25135bca6..17d816a45 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.29.0 + 3.30.0 UTF-8 From b1934d3010b785114c4d583aba3b94f691bf61a6 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Fri, 2 Sep 2022 17:22:27 +0200 Subject: [PATCH 505/802] Add GitHub Action to run tests --- .github/workflows/ci.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..3d59b779d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,28 @@ +name: CI + +on: + push: + branches: [ '*' ] + pull_request: + branches: [ '*' ] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + java: [ 8, 11, 17 ] + steps: + - name: Check out code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Setup Java ${{ matrix.java }} + uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: ${{ matrix.java }} + + - name: Build + run: mvn clean package From 2ce88162e2849e06d09903733acb0772840c76d9 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Fri, 2 Sep 2022 18:04:59 +0200 Subject: [PATCH 506/802] Remove unused files --- .travis.yml | 17 -- ANNOUNCEMENT | 39 ---- CHANGES | 145 -------------- atlassian-ide-plugin.xml | 28 --- dist/agi/demo.groovy | 18 -- dist/agi/demo.js | 23 --- dist/agi/demo.php | 24 --- dist/lib/groovy-all-1.6.2.jar | Bin 4446142 -> 0 bytes dist/lib/javamail-141.jar | Bin 371264 -> 0 bytes dist/lib/jruby-complete-1.2.0.jar | Bin 10086099 -> 0 bytes dist/lib/mysql-connector-java-5.1.7-bin.jar | Bin 709922 -> 0 bytes dist/lib/quercus-3.2.1.jar | Bin 3780985 -> 0 bytes dist/lib/resin-util-3.2.1.jar | Bin 673506 -> 0 bytes dist/lib/servlet-api-2.5.jar | Bin 132529 -> 0 bytes src/main/java/org/asteriskjava/.gitignore | 2 - .../java/org/asteriskjava/config/.gitignore | 13 -- .../asteriskjava/config/dialplan/.gitignore | 4 - .../java/org/asteriskjava/fastagi/.gitignore | 31 --- .../asteriskjava/fastagi/command/.gitignore | 49 ----- .../asteriskjava/fastagi/internal/.gitignore | 14 -- .../org/asteriskjava/fastagi/reply/.gitignore | 1 - .../java/org/asteriskjava/live/.gitignore | 36 ---- .../org/asteriskjava/live/internal/.gitignore | 20 -- .../java/org/asteriskjava/manager/.gitignore | 17 -- .../asteriskjava/manager/action/.gitignore | 99 ---------- .../org/asteriskjava/manager/event/.gitignore | 179 ------------------ .../asteriskjava/manager/internal/.gitignore | 20 -- .../asteriskjava/manager/response/.gitignore | 16 -- .../java/org/asteriskjava/tools/.gitignore | 2 - .../java/org/asteriskjava/util/.gitignore | 11 -- .../org/asteriskjava/util/internal/.gitignore | 8 - .../FastScannerDeterministicTest.java | 55 ++---- .../NlStreamReaderFast273316816601633219.txt | 0 33 files changed, 20 insertions(+), 851 deletions(-) delete mode 100644 .travis.yml delete mode 100644 ANNOUNCEMENT delete mode 100644 CHANGES delete mode 100644 atlassian-ide-plugin.xml delete mode 100644 dist/agi/demo.groovy delete mode 100644 dist/agi/demo.js delete mode 100644 dist/agi/demo.php delete mode 100644 dist/lib/groovy-all-1.6.2.jar delete mode 100644 dist/lib/javamail-141.jar delete mode 100644 dist/lib/jruby-complete-1.2.0.jar delete mode 100644 dist/lib/mysql-connector-java-5.1.7-bin.jar delete mode 100644 dist/lib/quercus-3.2.1.jar delete mode 100644 dist/lib/resin-util-3.2.1.jar delete mode 100644 dist/lib/servlet-api-2.5.jar delete mode 100644 src/main/java/org/asteriskjava/.gitignore delete mode 100644 src/main/java/org/asteriskjava/config/.gitignore delete mode 100644 src/main/java/org/asteriskjava/config/dialplan/.gitignore delete mode 100644 src/main/java/org/asteriskjava/fastagi/.gitignore delete mode 100644 src/main/java/org/asteriskjava/fastagi/command/.gitignore delete mode 100644 src/main/java/org/asteriskjava/fastagi/internal/.gitignore delete mode 100644 src/main/java/org/asteriskjava/fastagi/reply/.gitignore delete mode 100644 src/main/java/org/asteriskjava/live/.gitignore delete mode 100644 src/main/java/org/asteriskjava/live/internal/.gitignore delete mode 100644 src/main/java/org/asteriskjava/manager/.gitignore delete mode 100644 src/main/java/org/asteriskjava/manager/action/.gitignore delete mode 100644 src/main/java/org/asteriskjava/manager/event/.gitignore delete mode 100644 src/main/java/org/asteriskjava/manager/internal/.gitignore delete mode 100644 src/main/java/org/asteriskjava/manager/response/.gitignore delete mode 100644 src/main/java/org/asteriskjava/tools/.gitignore delete mode 100644 src/main/java/org/asteriskjava/util/.gitignore delete mode 100644 src/main/java/org/asteriskjava/util/internal/.gitignore rename NlStreamReaderFast273316816601633219txt => src/test/resources/NlStreamReaderFast273316816601633219.txt (100%) diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 727636ad4..000000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: java - -jdk: -- oraclejdk7 -- oraclejdk8 -- openjdk7 - -script: -- ./gradlew test - -install: -- /bin/true - - -cache: - directories: - - $HOME/.m2 diff --git a/ANNOUNCEMENT b/ANNOUNCEMENT deleted file mode 100644 index 4bee82219..000000000 --- a/ANNOUNCEMENT +++ /dev/null @@ -1,39 +0,0 @@ -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 diff --git a/CHANGES b/CHANGES deleted file mode 100644 index de254ee1a..000000000 --- a/CHANGES +++ /dev/null @@ -1,145 +0,0 @@ -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", "none", "", "-none-", "(none)", - "", "(not set)", "", "n/a", "" 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 diff --git a/atlassian-ide-plugin.xml b/atlassian-ide-plugin.xml deleted file mode 100644 index d48888417..000000000 --- a/atlassian-ide-plugin.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - e88a6130-6bd2-45dd-aa5d-57b845f76d0f - reucon - https://secure.reucon.net/issues - false - - - 68a20e42-e943-4a1d-b807-45cad35b4f73 - reucon - https://secure.reucon.net/build - false - false - false - - - - - - - 89c4100c-3c20-4d7d-8611-0dbe1bee742e - repos - asterisk-java/trunk - e88a6130-6bd2-45dd-aa5d-57b845f76d0f - - \ No newline at end of file diff --git a/dist/agi/demo.groovy b/dist/agi/demo.groovy deleted file mode 100644 index 49563fa31..000000000 --- a/dist/agi/demo.groovy +++ /dev/null @@ -1,18 +0,0 @@ -// 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'); - diff --git a/dist/agi/demo.js b/dist/agi/demo.js deleted file mode 100644 index 58ade0537..000000000 --- a/dist/agi/demo.js +++ /dev/null @@ -1,23 +0,0 @@ -// countdown -for (var i = 10; i >= 0; i--) -{ - channel.sayNumber(i); -} - -channel.streamFile('beep'); - -// read a few dtmf digits -var code; -while ((code = channel.waitForDigit(10000)) != 0) -{ - var digit = String.fromCharCode(code); - if (digit == '#' || digit == '*') - { - break; - } - channel.sayDigits(digit); -} - -// beep to say good bye ;) -channel.streamFile('beep'); - diff --git a/dist/agi/demo.php b/dist/agi/demo.php deleted file mode 100644 index 3117f8409..000000000 --- a/dist/agi/demo.php +++ /dev/null @@ -1,24 +0,0 @@ -= 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'); - -?> diff --git a/dist/lib/groovy-all-1.6.2.jar b/dist/lib/groovy-all-1.6.2.jar deleted file mode 100644 index 34051aa357f01ebb87f3b18506fd3e66d001679c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4446142 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%0Ags=tec%U1Fo2 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�e5*s4V^u?omm^BNF*0E4yP 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

    UVV7|gv8ExLx%u;SR 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 X;Vwg;zVvN4R;y+ui=JZ;q05yLRSe@@ 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�X)2bjA=NIU@ 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 >t>TEyR;}H04-tDM+9W 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

    gEaJ9+ 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 u|%gh55;tV`{e00-h+^MkhjIvYptc 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�Am7Y2YG^=+SmmUQE;%Og^H0!&l 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
  • bY;%)V9pr?)w1 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 ?GAB<;8LILxsQ2xASVTH-|h*X~7>1lyMf= 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

    * - * @since 0.3.1 * @author Patrick Breucking * @version $Id$ + * @since 0.3.1 */ -public interface AsteriskAgent extends LiveObject -{ +public interface AsteriskAgent extends LiveObject { String PROPERTY_STATE = "state"; /** diff --git a/src/main/java/org/asteriskjava/live/AsteriskChannel.java b/src/main/java/org/asteriskjava/live/AsteriskChannel.java index 124017e8a..06da80821 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskChannel.java +++ b/src/main/java/org/asteriskjava/live/AsteriskChannel.java @@ -16,12 +16,12 @@ */ package org.asteriskjava.live; +import org.asteriskjava.util.MixMonitorDirection; + import java.util.Date; import java.util.List; import java.util.Map; -import org.asteriskjava.util.MixMonitorDirection; - /** * Represents an Asterisk channel. *

    @@ -44,11 +44,10 @@ *

    xG<;bi2VlRKZDwstT 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%0DB#VK0iRYbK~`Yw^PCe75*7kf{b=d- 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

  • dtmfReceived *
  • dtmfSent * - * + * * @author srt */ -public interface AsteriskChannel extends LiveObject -{ +public interface AsteriskChannel extends LiveObject { String PROPERTY_ID = "id"; String PROPERTY_NAME = "name"; String PROPERTY_CALLER_ID = "callerId"; @@ -70,32 +69,35 @@ public interface AsteriskChannel extends LiveObject String VARIABLE_MONITOR_EXEC = "MONITOR_EXEC"; String VARIABLE_MONITOR_EXEC_ARGS = "MONITOR_EXEC_ARGS"; - /** Pseudo-variable to store {@link org.asteriskjava.manager.event.DialEvent#getDialStatus()} */ - String VAR_AJ_DIAL_STATUS = "AJ_DIAL_STATUS"; + /** + * Pseudo-variable to store {@link org.asteriskjava.manager.event.DialEvent#getDialStatus()} + */ + String VAR_AJ_DIAL_STATUS = "AJ_DIAL_STATUS"; + /** * Returns the unique id of this channel, for example "1099015093.165". - * + * * @return the unique id of this channel. */ String getId(); /** * Returns the name of this channel, for example "SIP/1310-20da". - * + * * @return the name of this channel. */ String getName(); /** * Returns the caller id of this channel. - * + * * @return the caller id of this channel. */ CallerId getCallerId(); /** * Returns the state of this channel. - * + * * @return the state of this channel. */ ChannelState getState(); @@ -105,37 +107,37 @@ public interface AsteriskChannel extends LiveObject *

    * For example you can use this method the check if this channel had been * answered: - * + * *

          * boolean answered = channel.wasInState(ChannelState.UP);
          * 
    - * + * * @param state the state to look for. * @return true if this channel was at least once in the - * given state; false otherwise. + * given state; false otherwise. * @since 0.3 */ boolean wasInState(ChannelState state); /** * Checks if this channel was busy. - * + * * @return true if this channel was busy; false - * otherwise. + * otherwise. * @since 0.3 */ boolean wasBusy(); /** * Returns the account code used to bill this channel. - * + * * @return the account code used to bill this channel. */ String getAccount(); /** * Returns the last visited dialplan entry. - * + * * @return the last visited dialplan entry. * @since 0.2 */ @@ -143,7 +145,7 @@ public interface AsteriskChannel extends LiveObject /** * Returns the first visited dialplan entry. - * + * * @return the first visited dialplan entry. * @since 0.2 */ @@ -151,7 +153,7 @@ public interface AsteriskChannel extends LiveObject /** * Returns a list of all visited dialplan entries. - * + * * @return a list of all visited dialplan entries. * @since 0.3 */ @@ -161,7 +163,7 @@ public interface AsteriskChannel extends LiveObject * Returns the date this channel has been created. *

    * This property is immutable. - * + * * @return the date this channel has been created. */ Date getDateOfCreation(); @@ -169,39 +171,39 @@ public interface AsteriskChannel extends LiveObject /** * Returns the date this channel has left the Asterisk server for example by * a hangup. - * + * * @return the date this channel has left the Asterisk server or - * null if this channel is still active. + * null if this channel is still active. * @since 0.3 */ Date getDateOfRemoval(); /** * Returns the reason for hangup. - * + * * @return the reason for hangup or null if the channel has - * not yet been hung up or no hangup cause is available for this - * type of channel. + * not yet been hung up or no hangup cause is available for this + * type of channel. * @since 0.3 */ HangupCause getHangupCause(); /** * Returns a textual representation of the reason for hangup. - * + * * @return the textual representation of the reason for hangup or - * null if the channel has not yet been hung up or no - * hangup cause is available for this type of channel. If no hangup - * cause is available an empty String may be returned, too. + * null if the channel has not yet been hung up or no + * hangup cause is available for this type of channel. If no hangup + * cause is available an empty String may be returned, too. * @since 0.3 */ String getHangupCauseText(); /** * Returns the call detail record for this channel. - * + * * @return the call detail record for this channel or null if - * none has (yet) been received. + * none has (yet) been received. */ CallDetailRecord getCallDetailRecord(); @@ -209,15 +211,15 @@ public interface AsteriskChannel extends LiveObject * Returns the channel that has been dialed by this channel most recently, * this is the destination channel that was created because this channel * dialed it. - * + * * @return the channel that has been dialed by this channel or - * null if none has been dialed. + * null if none has been dialed. */ AsteriskChannel getDialedChannel(); /** * Returns a list of all channels that have been dialed by this channel. - * + * * @return a list of all channels that have been dialed by this channel. */ List getDialedChannelHistory(); @@ -225,41 +227,41 @@ public interface AsteriskChannel extends LiveObject /** * Returns the channel that was dialing this channel, this is the source * channel that created this channel by dialing it. - * + * * @return the channel that was dialing this channel or null - * if none was dialing. + * if none was dialing. */ AsteriskChannel getDialingChannel(); /** * Returns the channel set that are dialing this channel, this is the source * channel that created this channel by dialing it. - * + * * @return the channel set that is dialing this channel or null - * if none was dialing. + * if none was dialing. */ - List getDialedChannels(); + List getDialedChannels(); /** * Returns the channel this channel is currently bridged with, if any. - * + * * @return the channel this channel is bridged with, or null - * if this channel is currently not bridged to another channel. + * if this channel is currently not bridged to another channel. */ AsteriskChannel getLinkedChannel(); /** * Returns a list of all channels this channel was briged with. - * + * * @return a list of all channels this channel was briged with. */ List getLinkedChannelHistory(); /** * Indicates if this channel was linked to another channel at least once. - * + * * @return true if this channel was linked to another channel - * at least once, false otherwise. + * at least once, false otherwise. * @since 0.2 */ boolean wasLinked(); @@ -267,10 +269,10 @@ public interface AsteriskChannel extends LiveObject /** * Returns the MeetMeUser associated with this channel if this channel is * currently taking part in a MeetMe conference. - * + * * @return the MeetMeUser associated with this channel or null - * if this channel is currently not taking part in a MeetMe - * conference. + * if this channel is currently not taking part in a MeetMe + * conference. */ MeetMeUser getMeetMeUser(); @@ -280,7 +282,7 @@ public interface AsteriskChannel extends LiveObject * @return the queue entry associated with this channel if any, null otherwise. */ AsteriskQueueEntry getQueueEntry(); - + /** * Return the extension to dial to pickup he channel of the parking if the channel is * currently parked. @@ -331,14 +333,14 @@ public interface AsteriskChannel extends LiveObject boolean isMonitored(); /* Actions */ - + /** * Hangs up this channel. - * + * * @throws ManagerCommunicationException if the hangup action cannot be sent - * to Asterisk. - * @throws NoSuchChannelException if this channel had already been hung up - * before the hangup was sent. + * to Asterisk. + * @throws NoSuchChannelException if this channel had already been hung up + * before the hangup was sent. * @since 0.3 */ void hangup() throws ManagerCommunicationException, NoSuchChannelException; @@ -347,12 +349,12 @@ public interface AsteriskChannel extends LiveObject * Hangs up this channel using a given cause code. The cause code is mainly * used for Zap PRI channels where it makes Asterisk send a PRI DISCONNECT * message with the set CAUSE element to the switch. - * + * * @param cause the cause code to send. * @throws ManagerCommunicationException if the hangup action cannot be sent - * to Asterisk. - * @throws NoSuchChannelException if this channel had already been hung up - * before the hangup was sent. + * to Asterisk. + * @throws NoSuchChannelException if this channel had already been hung up + * before the hangup was sent. * @since 0.3 */ void hangup(HangupCause cause) throws ManagerCommunicationException, NoSuchChannelException; @@ -363,16 +365,16 @@ public interface AsteriskChannel extends LiveObject *

    * Time is counted from when you call setAbsoluteTimeout, not from the * beginning of the call. - * + * * @param seconds maximum duration of the call in seconds, 0 for unlimited - * call length. + * call length. * @throws ManagerCommunicationException if the absolute timeout action - * cannot be sent to Asterisk. - * @throws NoSuchChannelException if this channel had already been hung up - * before the absolute timeout was set. + * cannot be sent to Asterisk. + * @throws NoSuchChannelException if this channel had already been hung up + * before the absolute timeout was set. * @since 0.3 */ - //TODO exception when setting it to 0: NoSuchChannelException: Channel + //TODO exception when setting it to 0: NoSuchChannelException: Channel // 'SIP/248-0a02fcd0' is not available: No timeout specified void setAbsoluteTimeout(int seconds) throws ManagerCommunicationException, NoSuchChannelException; @@ -381,14 +383,14 @@ public interface AsteriskChannel extends LiveObject *

    * If this channel is linked to another channel, the linked channel is hung * up. - * - * @param context the destination context. - * @param exten the destination extension. + * + * @param context the destination context. + * @param exten the destination extension. * @param priority the destination priority. * @throws ManagerCommunicationException if the redirect action cannot be - * sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * the redirect was sent. + * sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * the redirect was sent. * @since 0.3 */ void redirect(String context, String exten, int priority) throws ManagerCommunicationException, NoSuchChannelException; @@ -399,14 +401,14 @@ public interface AsteriskChannel extends LiveObject *

    * If this channel is not linked to another channel only this channel is * redirected. - * - * @param context the destination context. - * @param exten the destination extension. + * + * @param context the destination context. + * @param exten the destination extension. * @param priority the destination priority. * @throws ManagerCommunicationException if the redirect action cannot be - * sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * the redirect was sent. + * sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * the redirect was sent. * @since 0.3 */ void redirectBothLegs(String context, String exten, int priority) throws ManagerCommunicationException, @@ -418,27 +420,27 @@ void redirectBothLegs(String context, String exten, int priority) throws Manager * Currently Asterisk does not support the retrieval of built-in variables * like EXTEN or CALLERIDNUM but only custom variables set via Asterisk's * Set command or via {@link #setVariable(String, String)}. - * + * * @param variable the name of the channel variable to return. * @return the value of the channel variable or null if it is - * not set. + * not set. * @throws ManagerCommunicationException if the get variable action cannot - * be sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * the variable was requested. + * be sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * the variable was requested. * @since 0.3 */ String getVariable(String variable) throws ManagerCommunicationException, NoSuchChannelException; /** * Sets the value of the given channel variable. - * + * * @param variable the name of the channel variable to set. - * @param value the value of the channel variable to set. + * @param value the value of the channel variable to set. * @throws ManagerCommunicationException if the set variable action cannot - * be sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * the variable was set. + * be sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * the variable was set. * @since 0.3 */ void setVariable(String variable, String value) throws ManagerCommunicationException, NoSuchChannelException; @@ -447,13 +449,13 @@ void redirectBothLegs(String context, String exten, int priority) throws Manager * Plays the given DTMF digit on this channel. *

    * Available since Asterisk 1.2.8 - * + * * @param digit the DTMF digit to play. * @throws ManagerCommunicationException if the play DTMF action cannot be - * sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * the DTMF digit was set. - * @throws IllegalArgumentException if the digit is null. + * sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * the DTMF digit was set. + * @throws IllegalArgumentException if the digit is null. * @since 0.3 */ void playDtmf(String digit) throws ManagerCommunicationException, NoSuchChannelException, IllegalArgumentException; @@ -464,14 +466,14 @@ void redirectBothLegs(String context, String exten, int priority) throws Manager * The format of the files is "wav", they are not mixed. *

    * The files are called filename-in.wav and filename-out.wav. - * + * * @param filename the basename of the files created in the monitor spool - * directory. If null the channel name (with - * slashed replaced by dashes) is used. + * directory. If null the channel name (with + * slashed replaced by dashes) is used. * @throws ManagerCommunicationException if the monitor action cannot be - * sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * starting monitoring. + * sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * starting monitoring. * @see #stopMonitoring() * @see #pauseMonitoring() * @since 0.3 @@ -484,16 +486,16 @@ void redirectBothLegs(String context, String exten, int priority) throws Manager * The files are not mixed. *

    * The files are called filename-in.format and filename-out.format. - * + * * @param filename the basename of the files created in the monitor spool - * directory. If null the channel name (with - * slashed replaced by dashes) is used. - * @param format the audio recording format. If null wav is - * used. + * directory. If null the channel name (with + * slashed replaced by dashes) is used. + * @param format the audio recording format. If null wav is + * used. * @throws ManagerCommunicationException if the monitor action cannot be - * sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * starting monitoring. + * sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * starting monitoring. * @see #stopMonitoring() * @see #pauseMonitoring() * @since 0.3 @@ -518,31 +520,31 @@ void redirectBothLegs(String context, String exten, int priority) throws Manager * spaces). *

    * Example: - * + * *

          *      AsteriskChannel c;
    -     *      
    +     *
          *      [...]
          *      c.setVariable(AsteriskChannel.VARIABLE_MONITOR_EXEC, "/usr/local/bin/2wav2mp3");
          *      c.startMonitoring("my-recording", "wav", true);
          * 
    - * + *

    * Side note: 2wav2mp3 is a nice script by Dietmar Zlabinger to mix the two * legs to a stero mp3 file, for details see * voip-info.org. - * + * * @param filename the basename of the file(s) created in the monitor spool - * directory. If null the channel name (with - * slashed replaced by dashes) is used. - * @param format the audio recording format. If null wav is - * used. - * @param mix true to mix input and output data together - * after recording is finished, false to not mix - * them. + * directory. If null the channel name (with + * slashed replaced by dashes) is used. + * @param format the audio recording format. If null wav is + * used. + * @param mix true to mix input and output data together + * after recording is finished, false to not mix + * them. * @throws ManagerCommunicationException if the monitor action cannot be - * sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * starting monitoring. + * sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * starting monitoring. * @see #VARIABLE_MONITOR_EXEC * @see #VARIABLE_MONITOR_EXEC_ARGS * @see #stopMonitoring() @@ -559,14 +561,14 @@ void startMonitoring(String filename, String format, boolean mix) throws Manager * ignored and a warning message is written to Asterisk's CLI. *

    * Use with care, this doesn't always seem to work. - * + * * @param filename the basename of the file(s) created in the monitor spool - * directory. + * directory. * @throws ManagerCommunicationException if the change monitor action cannot - * be sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * changing monitoring. - * @throws IllegalArgumentException if filename is null. + * be sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * changing monitoring. + * @throws IllegalArgumentException if filename is null. * @see #stopMonitoring() * @see #pauseMonitoring() * @since 0.3 @@ -579,11 +581,11 @@ void changeMonitoring(String filename) throws ManagerCommunicationException, NoS *

    * If the channel exists but is not currently monitored your request is * ignored. - * + * * @throws ManagerCommunicationException if the stop monitor action cannot - * be sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * stopping monitoring. + * be sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * stopping monitoring. * @see #startMonitoring(String) * @see #startMonitoring(String, String) * @see #startMonitoring(String, String, boolean) @@ -598,11 +600,11 @@ void changeMonitoring(String filename) throws ManagerCommunicationException, NoS * ignored. *

    * This method is available since Asterisk 1.4. - * + * * @throws ManagerCommunicationException if the pause monitor action cannot - * be sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * temporarily stopping monitoring. + * be sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * temporarily stopping monitoring. * @see #unpauseMonitoring() * @since 0.3 */ @@ -616,34 +618,34 @@ void changeMonitoring(String filename) throws ManagerCommunicationException, NoS * ignored. *

    * This method is available since Asterisk 1.4. - * + * * @throws ManagerCommunicationException if the unpause monitor action - * cannot be sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * re-enabling monitoring. + * cannot be sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * re-enabling monitoring. * @see #pauseMonitoring() * @since 0.3 */ void unpauseMonitoring() throws ManagerCommunicationException, NoSuchChannelException; - - + + /** * Temporarily stops monitoring this channel if this is monitored with MixMonitor. *

    * If the channel exists but is not currently monitored your request is * ignored. *

    - * + * * @throws ManagerCommunicationException if the pause monitor action cannot - * be sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * temporarily stopping monitoring. + * be sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * temporarily stopping monitoring. * @see #unPauseMixMonitor(org.asteriskjava.util.MixMonitorDirection) * @since 1.0.0 */ void pauseMixMonitor(MixMonitorDirection direction) throws ManagerCommunicationException, NoSuchChannelException; - - + + /** * Re-enables monitoring this channel after calling * {@link #pauseMixMonitor(org.asteriskjava.util.MixMonitorDirection)} ()} @@ -652,14 +654,14 @@ void changeMonitoring(String filename) throws ManagerCommunicationException, NoS * If the channel exists but monitoring has not been paused your request is * ignored. *

    - * + * * @throws ManagerCommunicationException if the unpause monitor action - * cannot be sent to Asterisk. - * @throws NoSuchChannelException if this channel had been hung up before - * re-enabling monitoring. + * cannot be sent to Asterisk. + * @throws NoSuchChannelException if this channel had been hung up before + * re-enabling monitoring. * @see #pauseMixMonitor(org.asteriskjava.util.MixMonitorDirection) * @since 1.0.0 */ void unPauseMixMonitor(MixMonitorDirection direction) throws ManagerCommunicationException, NoSuchChannelException; - + } diff --git a/src/main/java/org/asteriskjava/live/AsteriskQueue.java b/src/main/java/org/asteriskjava/live/AsteriskQueue.java index 23a4f4a41..9393c6119 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskQueue.java +++ b/src/main/java/org/asteriskjava/live/AsteriskQueue.java @@ -26,8 +26,7 @@ * @author itaqua * @version $Id$ */ -public interface AsteriskQueue -{ +public interface AsteriskQueue { String STRATEGY_RINGALL = "ringall"; String STRATEGY_ROUNDROBIN = "roundrobin"; String STRATAGY_LEAST_RECENT = "leastrecent"; @@ -91,7 +90,7 @@ public interface AsteriskQueue * Available since Asterisk 1.2 * * @return the weight of this queue or null if not supported - * by your version of Asterisk. + * by your version of Asterisk. */ Integer getWeight(); @@ -138,63 +137,70 @@ public interface AsteriskQueue /** * Returns the number of abandoned calls. - * @author itaqua + * * @return the number of abandoned calls. + * @author itaqua */ Integer getAbandoned(); /** * Returns the ratio of calls answered within the specified service level per total completed * calls (in percent). - * @author itaqua + * * @return the ratio of calls answered within the specified service level per total completed - * calls (in percent). + * calls (in percent). + * @author itaqua */ - Double getServiceLevelPerf(); + Double getServiceLevelPerf(); - /** + /** * Returns the number of completed calls. - * @author itaqua + * * @return the number of completed calls. + * @author itaqua */ - Integer getCompleted(); + Integer getCompleted(); - /** + /** * Returns the current average talk time for this queue based on an exponential average. * * @return the current average talk time for this queue. */ - Integer getTalkTime(); + Integer getTalkTime(); - /** + /** * Returns the current average holdtime for this queue (in seconds). - * @author itaqua + * * @return the current average holdtime for this queue (in seconds). + * @author itaqua */ - Integer getHoldTime(); + Integer getHoldTime(); - /** + /** * Returns the number of calls currently waiting in the queue. * Is better to use get Waiting() + * + * @return the number of calls currently waiting in the queue. * @author itaqua * @see getWaiting() - * @return the number of calls currently waiting in the queue. */ - Integer getCalls(); + Integer getCalls(); - /** + /** * Returns the number of calls currently waiting in the queue. * More verbose Method than getCalls() - * @author itaqua + * * @return the number of calls currently waiting in the queue. + * @author itaqua */ - Integer getWaiting(); + Integer getWaiting(); - /** + /** * timestamp (miliseconds) of last update of this object + * + * @return * @todo maybe change this to an immutable object * @author itaqua - * @return */ long getLastUpdateMillis(); diff --git a/src/main/java/org/asteriskjava/live/AsteriskQueueEntry.java b/src/main/java/org/asteriskjava/live/AsteriskQueueEntry.java index b91688e7e..066a44d06 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskQueueEntry.java +++ b/src/main/java/org/asteriskjava/live/AsteriskQueueEntry.java @@ -13,8 +13,7 @@ * * @author gmi */ -public interface AsteriskQueueEntry extends LiveObject -{ +public interface AsteriskQueueEntry extends LiveObject { String PROPERTY_STATE = "state"; String PROPERTY_POSITION = "position"; String PROPERTY_REPORTED_POSITION = "reportedPosition"; @@ -36,7 +35,7 @@ public interface AsteriskQueueEntry extends LiveObject * member left when entering {@link QueueEntryState#LEFT}. * * @return the date this member left the Queue or - * null if the user did not yet leave. + * null if the user did not yet leave. */ Date getDateLeft(); diff --git a/src/main/java/org/asteriskjava/live/AsteriskQueueListener.java b/src/main/java/org/asteriskjava/live/AsteriskQueueListener.java index 0cee29a1d..27b1a3ee2 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskQueueListener.java +++ b/src/main/java/org/asteriskjava/live/AsteriskQueueListener.java @@ -8,8 +8,7 @@ * @author gmi * @since 0.3 */ -public interface AsteriskQueueListener -{ +public interface AsteriskQueueListener { /** * Called whenever an entry appears in the queue. * @@ -36,7 +35,7 @@ public interface AsteriskQueueListener * @param entry */ void onEntryServiceLevelExceeded(AsteriskQueueEntry entry); - + /** * Called whenever a new member is added to the queue. * diff --git a/src/main/java/org/asteriskjava/live/AsteriskQueueMember.java b/src/main/java/org/asteriskjava/live/AsteriskQueueMember.java index e8951b6ea..c88dbe7df 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskQueueMember.java +++ b/src/main/java/org/asteriskjava/live/AsteriskQueueMember.java @@ -31,8 +31,7 @@ * @version $Id$ * @since 0.3.1 */ -public interface AsteriskQueueMember extends LiveObject -{ +public interface AsteriskQueueMember extends LiveObject { String PROPERTY_STATE = "state"; String PROPERTY_PENALTY = "penalty"; String PROPERTY_PAUSED = "paused"; @@ -66,7 +65,8 @@ public interface AsteriskQueueMember extends LiveObject * @return paused true is this queue member is paused, false otherwise. * @deprecated as of 1.0.0. Use {@link #isPaused()} instead. */ - @Deprecated boolean getPaused(); + @Deprecated + boolean getPaused(); /** * Returns whether this member is currently paused.. @@ -102,7 +102,7 @@ public interface AsteriskQueueMember extends LiveObject * statically defined in queues.conf. * * @return "dynamic" if the added member is a dynamic queue member, "static" - * if the added member is a static queue member. + * if the added member is a static queue member. * @since 1.0.0 */ String getMembership(); @@ -112,7 +112,7 @@ public interface AsteriskQueueMember extends LiveObject * defined in queues.conf. * * @return true if this member has been statically defined in - * queues.conf, false otherwise. + * queues.conf, false otherwise. * @since 1.0.0 */ boolean isStatic(); @@ -122,7 +122,7 @@ public interface AsteriskQueueMember extends LiveObject * added by the QueueAdd command. * * @return true if this member has been dynamically added by - * the QueueAdd command, false otherwise. + * the QueueAdd command, false otherwise. * @since 1.0.0 */ boolean isDynamic(); @@ -149,15 +149,17 @@ public interface AsteriskQueueMember extends LiveObject /** * get the timestamp when the last call was terminated - * @author itaqua + * * @return + * @author itaqua */ - Long getLastCall(); + Long getLastCall(); /** * total calls taken - * @author itaqua + * * @return + * @author itaqua */ - Integer getCallsTaken(); + Integer getCallsTaken(); } diff --git a/src/main/java/org/asteriskjava/live/AsteriskServer.java b/src/main/java/org/asteriskjava/live/AsteriskServer.java index da543db02..4eea8687d 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskServer.java +++ b/src/main/java/org/asteriskjava/live/AsteriskServer.java @@ -16,16 +16,16 @@ */ package org.asteriskjava.live; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Map; - import org.asteriskjava.config.ConfigFile; import org.asteriskjava.manager.ManagerConnection; import org.asteriskjava.manager.ManagerEventListener; import org.asteriskjava.manager.action.OriginateAction; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; + /** * The AsteriskServer is built on top of the * {@link org.asteriskjava.manager.ManagerConnection} and is an attempt to @@ -35,12 +35,11 @@ * open channels).
    * AsteriskServer is still in an early state of development. So, when using * AsteriskServer be aware that it might change in the future. - * + * * @author srt * @version $Id$ */ -public interface AsteriskServer -{ +public interface AsteriskServer { /** * Returns the underlying ManagerConnection. *

    @@ -50,57 +49,57 @@ public interface AsteriskServer * ManagerEventListeners} before the connection to the Asterisk server is * established. If you want to ensure that the connection is established * call {@link #initialize()}. - * + * * @return the underlying ManagerConnection. */ ManagerConnection getManagerConnection(); /** * Generates an outgoing channel. - * + * * @param originateAction the action that contains parameters for the - * originate + * originate * @return the generated channel - * @throws NoSuchChannelException if the channel is not available on the - * Asterisk server, for example because you used "SIP/1310" and - * 1310 is not a valid SIP user, the SIP channel module hasn't - * been loaded or the SIP or IAX peer is not registered - * currently. + * @throws NoSuchChannelException if the channel is not available on the + * Asterisk server, for example because you used "SIP/1310" and + * 1310 is not a valid SIP user, the SIP channel module hasn't + * been loaded or the SIP or IAX peer is not registered + * currently. * @throws ManagerCommunicationException if the originate action cannot be - * sent to Asterisk + * sent to Asterisk */ AsteriskChannel originate(OriginateAction originateAction) throws ManagerCommunicationException, NoSuchChannelException; /** * Asynchronously generates an outgoing channel. - * + * * @param originateAction the action that contains parameters for the - * originate - * @param cb callback to inform about the result + * originate + * @param cb callback to inform about the result * @throws ManagerCommunicationException if the originate action cannot be - * sent to Asterisk + * sent to Asterisk */ void originateAsync(OriginateAction originateAction, OriginateCallback cb) throws ManagerCommunicationException; /** * Generates an outgoing channel to a dialplan entry (extension, context, * priority). - * - * @param channel channel name to call, for example "SIP/1310". - * @param context context to connect to - * @param exten extension to connect to + * + * @param channel channel name to call, for example "SIP/1310". + * @param context context to connect to + * @param exten extension to connect to * @param priority priority to connect to - * @param timeout how long to wait for the channel to be answered before its - * considered to have failed (in ms) + * @param timeout how long to wait for the channel to be answered before its + * considered to have failed (in ms) * @return the generated channel - * @throws NoSuchChannelException if the channel is not available on the - * Asterisk server, for example because you used "SIP/1310" and - * 1310 is not a valid SIP user, the SIP channel module hasn't - * been loaded or the SIP or IAX peer is not registered - * currently. + * @throws NoSuchChannelException if the channel is not available on the + * Asterisk server, for example because you used "SIP/1310" and + * 1310 is not a valid SIP user, the SIP channel module hasn't + * been loaded or the SIP or IAX peer is not registered + * currently. * @throws ManagerCommunicationException if the originate action cannot be - * sent to Asterisk + * sent to Asterisk */ AsteriskChannel originateToExtension(String channel, String context, String exten, int priority, long timeout) throws ManagerCommunicationException, NoSuchChannelException; @@ -108,45 +107,45 @@ AsteriskChannel originateToExtension(String channel, String context, String exte /** * Generates an outgoing channel to a dialplan entry (extension, context, * priority) and sets an optional map of channel variables. - * - * @param channel channel name to call, for example "SIP/1310". - * @param context context to connect to - * @param exten extension to connect to - * @param priority priority to connect to - * @param timeout how long to wait for the channel to be answered before its - * considered to have failed (in ms) - * @param callerId callerId to use for the outgoing channel, may be - * null. + * + * @param channel channel name to call, for example "SIP/1310". + * @param context context to connect to + * @param exten extension to connect to + * @param priority priority to connect to + * @param timeout how long to wait for the channel to be answered before its + * considered to have failed (in ms) + * @param callerId callerId to use for the outgoing channel, may be + * null. * @param variables channel variables to set, may be null. * @return the generated channel - * @throws NoSuchChannelException if the channel is not available on the - * Asterisk server, for example because you used "SIP/1310" and - * 1310 is not a valid SIP user, the SIP channel module hasn't - * been loaded or the SIP or IAX peer is not registered - * currently. + * @throws NoSuchChannelException if the channel is not available on the + * Asterisk server, for example because you used "SIP/1310" and + * 1310 is not a valid SIP user, the SIP channel module hasn't + * been loaded or the SIP or IAX peer is not registered + * currently. * @throws ManagerCommunicationException if the originate action cannot be - * sent to Asterisk + * sent to Asterisk */ AsteriskChannel originateToExtension(String channel, String context, String exten, int priority, long timeout, - CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException; + CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException; /** * Generates an outgoing channel to an application. - * - * @param channel channel name to call, for example "SIP/1310". + * + * @param channel channel name to call, for example "SIP/1310". * @param application application to connect to, for example "MeetMe" - * @param data data to pass to the application, for example "1000|d", may be - * null. - * @param timeout how long to wait for the channel to be answered before its - * considered to have failed (in ms) + * @param data data to pass to the application, for example "1000|d", may be + * null. + * @param timeout how long to wait for the channel to be answered before its + * considered to have failed (in ms) * @return the generated channel - * @throws NoSuchChannelException if the channel is not available on the - * Asterisk server, for example because you used "SIP/1310" and - * 1310 is not a valid SIP user, the SIP channel module hasn't - * been loaded or the SIP or IAX peer is not registered - * currently. + * @throws NoSuchChannelException if the channel is not available on the + * Asterisk server, for example because you used "SIP/1310" and + * 1310 is not a valid SIP user, the SIP channel module hasn't + * been loaded or the SIP or IAX peer is not registered + * currently. * @throws ManagerCommunicationException if the originate action cannot be - * sent to Asterisk + * sent to Asterisk */ AsteriskChannel originateToApplication(String channel, String application, String data, long timeout) throws ManagerCommunicationException, NoSuchChannelException; @@ -154,170 +153,170 @@ AsteriskChannel originateToApplication(String channel, String application, Strin /** * Generates an outgoing channel to an application and sets an optional map * of channel variables. - * - * @param channel channel name to call, for example "SIP/1310". + * + * @param channel channel name to call, for example "SIP/1310". * @param application application to connect to, for example "MeetMe" - * @param data data to pass to the application, for example "1000|d", may be - * null. - * @param timeout how long to wait for the channel to be answered before its - * considered to have failed (in ms) - * @param callerId callerId to use for the outgoing channel, may be - * null. - * @param variables channel variables to set, may be null. + * @param data data to pass to the application, for example "1000|d", may be + * null. + * @param timeout how long to wait for the channel to be answered before its + * considered to have failed (in ms) + * @param callerId callerId to use for the outgoing channel, may be + * null. + * @param variables channel variables to set, may be null. * @return the generated channel - * @throws NoSuchChannelException if the channel is not available on the - * Asterisk server, for example because you used "SIP/1310" and - * 1310 is not a valid SIP user, the SIP channel module hasn't - * been loaded or the SIP or IAX peer is not registered - * currently. + * @throws NoSuchChannelException if the channel is not available on the + * Asterisk server, for example because you used "SIP/1310" and + * 1310 is not a valid SIP user, the SIP channel module hasn't + * been loaded or the SIP or IAX peer is not registered + * currently. * @throws ManagerCommunicationException if the originate action cannot be - * sent to Asterisk + * sent to Asterisk */ AsteriskChannel originateToApplication(String channel, String application, String data, long timeout, CallerId callerId, - Map variables) throws ManagerCommunicationException, NoSuchChannelException; + Map variables) throws ManagerCommunicationException, NoSuchChannelException; /** * Asynchronously generates an outgoing channel to a dialplan entry * (extension, context, priority). - * - * @param channel channel name to call, for example "SIP/1310". - * @param context context to connect to - * @param exten extension to connect to + * + * @param channel channel name to call, for example "SIP/1310". + * @param context context to connect to + * @param exten extension to connect to * @param priority priority to connect to - * @param timeout how long to wait for the channel to be answered before its - * considered to have failed (in ms) + * @param timeout how long to wait for the channel to be answered before its + * considered to have failed (in ms) * @param callback callback to inform about the result * @throws ManagerCommunicationException if the originate action cannot be - * sent to Asterisk + * sent to Asterisk */ void originateToExtensionAsync(String channel, String context, String exten, int priority, long timeout, - OriginateCallback callback) throws ManagerCommunicationException; + OriginateCallback callback) throws ManagerCommunicationException; /** * Asynchronously generates an outgoing channel to a dialplan entry * (extension, context, priority) and sets an optional map of channel * variables. - * - * @param channel channel name to call, for example "SIP/1310". - * @param context context to connect to - * @param exten extension to connect to - * @param priority priority to connect to - * @param timeout how long to wait for the channel to be answered before its - * considered to have failed (in ms) - * @param callerId callerId to use for the outgoing channel, may be - * null. + * + * @param channel channel name to call, for example "SIP/1310". + * @param context context to connect to + * @param exten extension to connect to + * @param priority priority to connect to + * @param timeout how long to wait for the channel to be answered before its + * considered to have failed (in ms) + * @param callerId callerId to use for the outgoing channel, may be + * null. * @param variables channel variables to set, may be null. - * @param callback callback to inform about the result + * @param callback callback to inform about the result * @throws ManagerCommunicationException if the originate action cannot be - * sent to Asterisk + * sent to Asterisk */ void originateToExtensionAsync(String channel, String context, String exten, int priority, long timeout, - CallerId callerId, Map variables, OriginateCallback callback) - throws ManagerCommunicationException; + CallerId callerId, Map variables, OriginateCallback callback) + throws ManagerCommunicationException; /** * Asynchronously generates an outgoing channel to an application. - * - * @param channel channel name to call, for example "SIP/1310". + * + * @param channel channel name to call, for example "SIP/1310". * @param application application to connect to, for example "MeetMe" - * @param data data to pass to the application, for example "1000|d", may be - * null. - * @param timeout how long to wait for the channel to be answered before its - * considered to have failed (in ms) - * @param callback callback to inform about the result + * @param data data to pass to the application, for example "1000|d", may be + * null. + * @param timeout how long to wait for the channel to be answered before its + * considered to have failed (in ms) + * @param callback callback to inform about the result * @throws ManagerCommunicationException if the originate action cannot be - * sent to Asterisk + * sent to Asterisk */ void originateToApplicationAsync(String channel, String application, String data, long timeout, - OriginateCallback callback) throws ManagerCommunicationException; + OriginateCallback callback) throws ManagerCommunicationException; /** * Asynchronously generates an outgoing channel to an application and sets * an optional map of channel variables. - * - * @param channel channel name to call, for example "SIP/1310". + * + * @param channel channel name to call, for example "SIP/1310". * @param application application to connect to, for example "MeetMe" - * @param data data to pass to the application, for example "1000|d", may be - * null. - * @param timeout how long to wait for the channel to be answered before its - * considered to have failed (in ms) - * @param callerId callerId to use for the outgoing channel, may be - * null. - * @param variables channel variables to set, may be null. - * @param callback callback to inform about the result + * @param data data to pass to the application, for example "1000|d", may be + * null. + * @param timeout how long to wait for the channel to be answered before its + * considered to have failed (in ms) + * @param callerId callerId to use for the outgoing channel, may be + * null. + * @param variables channel variables to set, may be null. + * @param callback callback to inform about the result * @throws ManagerCommunicationException if the originate action cannot be - * sent to Asterisk + * sent to Asterisk */ void originateToApplicationAsync(String channel, String application, String data, long timeout, CallerId callerId, - Map variables, OriginateCallback callback) throws ManagerCommunicationException; + Map variables, OriginateCallback callback) throws ManagerCommunicationException; /** * Returns the active channels of the Asterisk server. - * + * * @return a Collection of active channels. * @throws ManagerCommunicationException if there is a problem communication - * with Asterisk + * with Asterisk */ Collection getChannels() throws ManagerCommunicationException; /** * Returns a channel by its name. - * + * * @param name name of the channel to return * @return the channel with the given name or null if there is - * no such channel. + * no such channel. * @throws ManagerCommunicationException if there is a problem communication - * with Asterisk + * with Asterisk */ AsteriskChannel getChannelByName(String name) throws ManagerCommunicationException; /** * Returns a channel by its unique id. - * + * * @param id the unique id of the channel to return * @return the channel with the given unique id or null if - * there is no such channel. + * there is no such channel. * @throws ManagerCommunicationException if there is a problem communication - * with Asterisk + * with Asterisk */ AsteriskChannel getChannelById(String id) throws ManagerCommunicationException; /** * Returns the acitve MeetMe rooms on the Asterisk server. - * + * * @return a Collection of MeetMeRooms * @throws ManagerCommunicationException if there is a problem communication - * with Asterisk + * with Asterisk */ Collection getMeetMeRooms() throws ManagerCommunicationException; /** * Returns the MeetMe room with the given number, if the room does not yet * exist a new {@link MeetMeRoom} object is created. - * + * * @param roomNumber the number of the room to return * @return the MeetMe room with the given number. * @throws ManagerCommunicationException if there is a problem communication - * with Asterisk + * with Asterisk */ MeetMeRoom getMeetMeRoom(String roomNumber) throws ManagerCommunicationException; /** * Returns the queues served by the Asterisk server. - * + * * @return a Collection of queues. * @throws ManagerCommunicationException if there is a problem communication - * with Asterisk + * with Asterisk */ Collection getQueues() throws ManagerCommunicationException; /** * Return the agents, registered at Asterisk server. (Consider remarks for * {@link AsteriskAgent}) - * + * * @return a Collection of agents * @throws ManagerCommunicationException if there is a problem communication - * with Asterisk + * with Asterisk */ Collection getAgents() throws ManagerCommunicationException; @@ -325,10 +324,10 @@ void originateToApplicationAsync(String channel, String application, String data * Returns the exact version string of this Asterisk server.
    * This typically looks like "Asterisk 1.2.9.1-BRIstuffed-0.3.0-PRE-1q built * by root @ pbx0 on a i686 running Linux on 2006-06-20 20:21:30 UTC". - * + * * @return the version of this Asterisk server * @throws ManagerCommunicationException if the version cannot be retrieved - * from Asterisk + * from Asterisk * @since 0.2 */ String getVersion() throws ManagerCommunicationException; @@ -344,37 +343,37 @@ void originateToApplicationAsync(String channel, String application, String data * You can use this feature if you need to write applications that behave * different depending on specific modules being available in a specific * version or not. - * + * * @param file the file for which to get the version like "app_meetme.c" * @return the CVS revision of the file, or null if that file - * is not part of the Asterisk instance you are connected to (maybe - * due to a module that provides it has not been loaded) or if you - * are connected to an Astersion 1.0.x + * is not part of the Asterisk instance you are connected to (maybe + * due to a module that provides it has not been loaded) or if you + * are connected to an Astersion 1.0.x * @throws ManagerCommunicationException if the version cannot be retrieved - * from Asterisk + * from Asterisk * @since 0.2 */ int[] getVersion(String file) throws ManagerCommunicationException; /** * Returns the value of the given global variable. - * + * * @param variable the name of the global variable to return. * @return the value of the global variable or null if it is - * not set. + * not set. * @throws ManagerCommunicationException if the get variable action cannot - * be sent to Asterisk. + * be sent to Asterisk. * @since 0.3 */ String getGlobalVariable(String variable) throws ManagerCommunicationException; /** * Sets the value of the given global variable. - * + * * @param variable the name of the global variable to set. - * @param value the value of the global variable to set. + * @param value the value of the global variable to set. * @throws ManagerCommunicationException if the set variable action cannot - * be sent to Asterisk. + * be sent to Asterisk. * @since 0.3 */ void setGlobalVariable(String variable, String value) throws ManagerCommunicationException; @@ -382,21 +381,21 @@ void originateToApplicationAsync(String channel, String application, String data /** * Returns a collection of all voicemailboxes configured for this Asterisk * server with the number of new and old messages they contain. - * + * * @return a collection of all voicemailboxes configured for this Asterisk - * server + * server * @throws ManagerCommunicationException if the voicemailboxes can't be - * retrieved. + * retrieved. * @since 0.3 */ Collection getVoicemailboxes() throws ManagerCommunicationException; /** * Executes a command line interface (CLI) command. - * + * * @param command the command to execute, for example "sip show peers". * @return a List containing strings representing the lines returned by the - * CLI command. + * CLI command. * @throws ManagerCommunicationException if the command can't be executed. * @see org.asteriskjava.manager.action.CommandAction * @since 0.3 @@ -409,9 +408,9 @@ void originateToApplicationAsync(String channel, String application, String data * Available since Asterisk 1.6 * * @param module name of the module to load (with out without the ".so" - * extension). + * extension). * @return true if the module is currently loaded, - * false otherwise. + * false otherwise. * @throws ManagerCommunicationException if the module can't be checked. */ boolean isModuleLoaded(String module) throws ManagerCommunicationException; @@ -422,7 +421,7 @@ void originateToApplicationAsync(String channel, String application, String data * Available since Asterisk 1.6 * * @param module name of the module to load (including ".so" extension) or - * subsystem name. + * subsystem name. * @throws ManagerCommunicationException if the module cannot be loaded. * @since 1.0.0 */ @@ -434,7 +433,7 @@ void originateToApplicationAsync(String channel, String application, String data * Available since Asterisk 1.6 * * @param module name of the module to unload (including ".so" extension) or - * subsystem name. + * subsystem name. * @throws ManagerCommunicationException if the module cannot be unloaded. * @since 1.0.0 */ @@ -446,7 +445,7 @@ void originateToApplicationAsync(String channel, String application, String data * Available since Asterisk 1.6 * * @param module name of the module to reload (including ".so" extension) or - * subsystem name. + * subsystem name. * @throws ManagerCommunicationException if the module cannot be reloaded. * @since 1.0.0 */ @@ -474,16 +473,16 @@ void originateToApplicationAsync(String channel, String application, String data /** * Adds a listener to this AsteriskServer.
    * If this server is not yet connected it will be implicitly connected. - * + * * @param listener the listener to add. * @throws ManagerCommunicationException if the server is not yet connected - * and the connection or initialization fails. + * and the connection or initialization fails. */ void addAsteriskServerListener(AsteriskServerListener listener) throws ManagerCommunicationException; /** * Removes a listener from this Asterisk server. - * + * * @param listener the listener to remove. */ void removeAsteriskServerListener(AsteriskServerListener listener); @@ -517,7 +516,7 @@ void originateToApplicationAsync(String channel, String application, String data /** * remove the chain listener. - * + * * @param chainListener */ void removeChainListener(ManagerEventListener chainListener); @@ -529,42 +528,42 @@ void originateToApplicationAsync(String channel, String application, String data /** * Opens the connection to this server. - * + * * @throws ManagerCommunicationException if login fails */ void initialize() throws ManagerCommunicationException; /** * get Asterisk Queue by name - * - * @author itaqua + * * @param queueName Name of the queue to retrieve * @return + * @author itaqua */ AsteriskQueue getQueueByName(String queueName); /** * List of Queues Objects updated after certain date - * - * @author itaqua + * * @param date * @return + * @author itaqua */ List getQueuesUpdatedAfter(Date date); /** * every time we get an event of a queue we reload the information about it * from the Asterisk Server - * + * * @author itaqua */ void forceQueuesMonitor(boolean force); /** * Check if the Queue Information is forced - * - * @author itaqua + * * @return + * @author itaqua */ boolean isQueuesMonitorForced(); } diff --git a/src/main/java/org/asteriskjava/live/AsteriskServerListener.java b/src/main/java/org/asteriskjava/live/AsteriskServerListener.java index 922369881..4cbf1ee92 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskServerListener.java +++ b/src/main/java/org/asteriskjava/live/AsteriskServerListener.java @@ -8,37 +8,36 @@ * Usually it is better to extend {@link AbstractAsteriskServerListener} than to * implement this interface directly as additonal methods will probably be added * in future versions of Asterisk-Java. - * + * * @author srt * @version $Id$ * @since 0.3 */ -public interface AsteriskServerListener -{ +public interface AsteriskServerListener { /** * Called whenever a new channel appears on the Asterisk server. - * + * * @param channel the new channel. */ void onNewAsteriskChannel(AsteriskChannel channel); /** * Called whenever a user joins a {@link MeetMeRoom}. - * + * * @param user the user that joined. */ void onNewMeetMeUser(MeetMeUser user); /** * Called whenever a new agent will be registered at Asterisk server. - * + * * @param agent */ void onNewAgent(AsteriskAgent agent); - + /** * Called whenever a queue entry ( ~ wapper over channel) joins a {@link org.asteriskjava.live.AsteriskQueue}. - * + * * @param entry the queue entry that joined. */ void onNewQueueEntry(AsteriskQueueEntry entry); diff --git a/src/main/java/org/asteriskjava/live/CallDetailRecord.java b/src/main/java/org/asteriskjava/live/CallDetailRecord.java index 46caef42f..53d2d7eaa 100644 --- a/src/main/java/org/asteriskjava/live/CallDetailRecord.java +++ b/src/main/java/org/asteriskjava/live/CallDetailRecord.java @@ -20,14 +20,13 @@ /** * Represents an Asterisk Call Detail Record (CDR). - * - * @see org.asteriskjava.manager.event.CdrEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.CdrEvent * @since 0.3 */ -public interface CallDetailRecord -{ +public interface CallDetailRecord { AsteriskChannel getChannel(); AsteriskChannel getDestinationChannel(); @@ -35,7 +34,7 @@ public interface CallDetailRecord /** * Returns the account number that is usually used to identify the party to bill for the call.

    * Corresponds to CDR field accountcode. - * + * * @return the account number. */ String getAccountCode(); @@ -45,7 +44,7 @@ public interface CallDetailRecord /** * Returns the destination context.

    * Corresponds to CDR field dcontext. - * + * * @return the destination context. */ String getDestinationContext(); @@ -53,7 +52,7 @@ public interface CallDetailRecord /** * Returns the destination extension.

    * Corresponds to CDR field dst. - * + * * @return the destination extension. */ String getDestinationExtension(); @@ -69,7 +68,7 @@ public interface CallDetailRecord /** * Returns the total time (in seconds) the caller spent in the system from dial to hangup.

    * Corresponds to CDR field duration. - * + * * @return the total time in system in seconds. */ Integer getDuration(); @@ -77,7 +76,7 @@ public interface CallDetailRecord /** * Returns the total time (in seconds) the call was up from answer to hangup.

    * Corresponds to CDR field billsec. - * + * * @return the total time in call in seconds. */ Integer getBillableSeconds(); @@ -85,7 +84,7 @@ public interface CallDetailRecord /** * Returns the last application if appropriate, for example "VoiceMail".

    * Corresponds to CDR field lastapp. - * + * * @return the last application or null if not avaialble. */ String getLastApplication(); @@ -93,7 +92,7 @@ public interface CallDetailRecord /** * Returns the last application's data (arguments), for example "s1234".

    * Corresponds to CDR field lastdata. - * + * * @return the last application's data or null if not avaialble. */ String getLastAppData(); @@ -101,7 +100,7 @@ public interface CallDetailRecord /** * Returns the user-defined field as set by Set(CDR(userfield)=Value).

    * Corresponds to CDR field userfield. - * + * * @return the user-defined field. */ String getUserField(); diff --git a/src/main/java/org/asteriskjava/live/CallerId.java b/src/main/java/org/asteriskjava/live/CallerId.java index 592b5e1ca..216eccc67 100644 --- a/src/main/java/org/asteriskjava/live/CallerId.java +++ b/src/main/java/org/asteriskjava/live/CallerId.java @@ -16,10 +16,10 @@ */ package org.asteriskjava.live; -import java.io.Serializable; - import org.asteriskjava.util.AstUtil; +import java.io.Serializable; + /** * Represents a Caller*ID containing name and number. *
    @@ -29,8 +29,7 @@ * @version $Id$ * @since 0.3 */ -public class CallerId implements Serializable -{ +public class CallerId implements Serializable { /** * Serial version identifier. */ @@ -44,8 +43,7 @@ public class CallerId implements Serializable * @param name the Caller*ID name. * @param number the Caller*ID number. */ - public CallerId(String name, String number) - { + public CallerId(String name, String number) { this.name = (AstUtil.isNull(name)) ? null : name; this.number = (AstUtil.isNull(number)) ? null : number; } @@ -55,8 +53,7 @@ public CallerId(String name, String number) * * @return the Caller*ID name. */ - public String getName() - { + public String getName() { return name; } @@ -65,8 +62,7 @@ public String getName() * * @return the Caller*ID number. */ - public String getNumber() - { + public String getNumber() { return number; } @@ -78,8 +74,7 @@ public String getNumber() * @return the corresponding CallerId object which is never null. * @see AstUtil#parseCallerId(String) */ - public static CallerId valueOf(String s) - { + public static CallerId valueOf(String s) { final String[] parsedCallerId; parsedCallerId = AstUtil.parseCallerId(s); @@ -91,24 +86,20 @@ public static CallerId valueOf(String s) * "Some Name" <1234>. */ @Override - public String toString() - { + public String toString() { final StringBuilder sb; sb = new StringBuilder(); - if (name != null) - { + if (name != null) { sb.append("\""); sb.append(name); sb.append("\""); - if (number != null) - { + if (number != null) { sb.append(" "); } } - if (number != null) - { + if (number != null) { sb.append("<"); sb.append(number); sb.append(">"); @@ -117,25 +108,20 @@ public String toString() } @Override - public boolean equals(Object o) - { - if (this == o) - { + public boolean equals(Object o) { + if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) - { + if (o == null || getClass() != o.getClass()) { return false; } CallerId callerId = (CallerId) o; - if (name != null ? !name.equals(callerId.name) : callerId.name != null) - { + if (name != null ? !name.equals(callerId.name) : callerId.name != null) { return false; } - if (number != null ? !number.equals(callerId.number) : callerId.number != null) - { + if (number != null ? !number.equals(callerId.number) : callerId.number != null) { return false; } @@ -143,8 +129,7 @@ public boolean equals(Object o) } @Override - public int hashCode() - { + public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (number != null ? number.hashCode() : 0); return result; diff --git a/src/main/java/org/asteriskjava/live/ChannelState.java b/src/main/java/org/asteriskjava/live/ChannelState.java index 0394a5cac..a27f4b2bd 100644 --- a/src/main/java/org/asteriskjava/live/ChannelState.java +++ b/src/main/java/org/asteriskjava/live/ChannelState.java @@ -22,12 +22,11 @@ * The lifecycle status of an {@link org.asteriskjava.live.AsteriskChannel}. *
    * Defined in channel.c function ast_state2str. - * + * * @author srt * @version $Id$ */ -public enum ChannelState -{ +public enum ChannelState { /** * Channel is down and available. * This is the initial state of the channel when it is not yet in use. @@ -91,8 +90,7 @@ public enum ChannelState * * @param status the numerical status code. */ - ChannelState(int status) - { + ChannelState(int status) { this.status = status; } @@ -101,8 +99,7 @@ public enum ChannelState * * @return the numerical status code. */ - public int getStatus() - { + public int getStatus() { return status; } @@ -113,17 +110,13 @@ public int getStatus() * @param status integer representation of the status. * @return corresponding ChannelState object or null if none matches. */ - public static ChannelState valueOf(Integer status) - { - if (status == null) - { + public static ChannelState valueOf(Integer status) { + if (status == null) { return null; } - for (ChannelState tmp : ChannelState.values()) - { - if (tmp.getStatus() == status) - { + for (ChannelState tmp : ChannelState.values()) { + if (tmp.getStatus() == status) { return tmp; } } diff --git a/src/main/java/org/asteriskjava/live/ChannelStateHistoryEntry.java b/src/main/java/org/asteriskjava/live/ChannelStateHistoryEntry.java index f07a85327..746e12a45 100644 --- a/src/main/java/org/asteriskjava/live/ChannelStateHistoryEntry.java +++ b/src/main/java/org/asteriskjava/live/ChannelStateHistoryEntry.java @@ -26,8 +26,7 @@ * @version $Id$ * @since 0.3 */ -public class ChannelStateHistoryEntry implements Serializable -{ +public class ChannelStateHistoryEntry implements Serializable { /** * Serial version identifier. */ @@ -41,8 +40,7 @@ public class ChannelStateHistoryEntry implements Serializable * @param date the date the channel entered the state. * @param state the state the channel entered. */ - public ChannelStateHistoryEntry(Date date, ChannelState state) - { + public ChannelStateHistoryEntry(Date date, ChannelState state) { this.date = date; this.state = state; } @@ -52,8 +50,7 @@ public ChannelStateHistoryEntry(Date date, ChannelState state) * * @return the date the channel entered the state. */ - public Date getDate() - { + public Date getDate() { return date; } @@ -62,14 +59,12 @@ public Date getDate() * * @return the state the channel entered. */ - public ChannelState getState() - { + public ChannelState getState() { return state; } @Override - public String toString() - { + public String toString() { final StringBuilder sb; sb = new StringBuilder("ChannelStateHistoryEntry["); diff --git a/src/main/java/org/asteriskjava/live/DefaultAsteriskServer.java b/src/main/java/org/asteriskjava/live/DefaultAsteriskServer.java index 88820d140..0d919c280 100644 --- a/src/main/java/org/asteriskjava/live/DefaultAsteriskServer.java +++ b/src/main/java/org/asteriskjava/live/DefaultAsteriskServer.java @@ -16,11 +16,6 @@ */ package org.asteriskjava.live; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Map; - import org.asteriskjava.config.ConfigFile; import org.asteriskjava.live.internal.AsteriskServerImpl; import org.asteriskjava.manager.DefaultManagerConnection; @@ -28,6 +23,11 @@ import org.asteriskjava.manager.ManagerEventListener; import org.asteriskjava.manager.action.OriginateAction; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; + /** * Default implementation of the AsteriskServer interface. * @@ -35,8 +35,7 @@ * @version $Id$ * @see org.asteriskjava.live.AsteriskServer */ -public class DefaultAsteriskServer implements AsteriskServer -{ +public class DefaultAsteriskServer implements AsteriskServer { private final AsteriskServerImpl impl; /** @@ -45,8 +44,7 @@ public class DefaultAsteriskServer implements AsteriskServer * {@link #setManagerConnection(ManagerConnection)} before you can use this * AsteriskServer. */ - public DefaultAsteriskServer() - { + public DefaultAsteriskServer() { this.impl = new AsteriskServerImpl(); } @@ -58,8 +56,7 @@ public DefaultAsteriskServer() * @param username the username to use for login * @param password the password to use for login */ - public DefaultAsteriskServer(String hostname, String username, String password) - { + public DefaultAsteriskServer(String hostname, String username, String password) { final ManagerConnection connection; connection = createManagerConnection(hostname, 0, username, password); this.impl = new AsteriskServerImpl(connection); @@ -70,20 +67,18 @@ public DefaultAsteriskServer(String hostname, String username, String password) * connection data. * * @param hostname the hostname of the Asterisk server to connect to. - * @param port the port where Asterisk listens for incoming Manager API - * connections, usually 5038. + * @param port the port where Asterisk listens for incoming Manager API + * connections, usually 5038. * @param username the username to use for login * @param password the password to use for login */ - public DefaultAsteriskServer(String hostname, int port, String username, String password) - { + public DefaultAsteriskServer(String hostname, int port, String username, String password) { final ManagerConnection connection; connection = createManagerConnection(hostname, port, username, password); this.impl = new AsteriskServerImpl(connection); } - protected DefaultManagerConnection createManagerConnection(String hostname, int port, String username, String password) - { + protected DefaultManagerConnection createManagerConnection(String hostname, int port, String username, String password) { DefaultManagerConnection dmc; dmc = new DefaultManagerConnection(hostname, port, username, password); return dmc; @@ -93,10 +88,9 @@ protected DefaultManagerConnection createManagerConnection(String hostname, int * Creates a new instance that uses the given {@link ManagerConnection}. * * @param eventConnection the ManagerConnection to use for receiving events - * from Asterisk. + * from Asterisk. */ - public DefaultAsteriskServer(ManagerConnection eventConnection) - { + public DefaultAsteriskServer(ManagerConnection eventConnection) { this.impl = new AsteriskServerImpl(eventConnection); } @@ -108,237 +102,194 @@ public DefaultAsteriskServer(ManagerConnection eventConnection) * Default is false. * * @param skipQueues true to skip queue initialization, - * false to not skip. + * false to not skip. * @since 0.2 */ - public void setSkipQueues(boolean skipQueues) - { + public void setSkipQueues(boolean skipQueues) { this.impl.setSkipQueues(skipQueues); } - public void setManagerConnection(ManagerConnection eventConnection) - { + public void setManagerConnection(ManagerConnection eventConnection) { this.impl.setManagerConnection(eventConnection); } - public void initialize() throws ManagerCommunicationException - { + public void initialize() throws ManagerCommunicationException { this.impl.initialize(); } /* Implementation of the AsteriskServer interface */ - public ManagerConnection getManagerConnection() - { + public ManagerConnection getManagerConnection() { return this.impl.getManagerConnection(); } public AsteriskChannel originate(OriginateAction originateAction) - throws ManagerCommunicationException, NoSuchChannelException - { + throws ManagerCommunicationException, NoSuchChannelException { return this.impl.originate(originateAction); } public AsteriskChannel originateToExtension(String channel, String context, String exten, int priority, long timeout) - throws ManagerCommunicationException, NoSuchChannelException - { + throws ManagerCommunicationException, NoSuchChannelException { return this.impl.originateToExtension(channel, context, exten, priority, timeout); } public AsteriskChannel originateToExtension(String channel, String context, String exten, int priority, long timeout, - CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException - { + CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException { return this.impl.originateToExtension(channel, context, exten, priority, timeout, callerId, variables); } public AsteriskChannel originateToApplication(String channel, String application, String data, long timeout) - throws ManagerCommunicationException, NoSuchChannelException - { + throws ManagerCommunicationException, NoSuchChannelException { return this.impl.originateToApplication(channel, application, data, timeout); } public AsteriskChannel originateToApplication(String channel, String application, String data, long timeout, - CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException - { + CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException { return this.impl.originateToApplication(channel, application, data, timeout, callerId, variables); } - public void originateAsync(OriginateAction originateAction, OriginateCallback cb) throws ManagerCommunicationException - { + public void originateAsync(OriginateAction originateAction, OriginateCallback cb) throws ManagerCommunicationException { this.impl.originateAsync(originateAction, cb); } public void originateToApplicationAsync(String channel, String application, String data, long timeout, CallerId callerId, - Map variables, OriginateCallback cb) throws ManagerCommunicationException - { + Map variables, OriginateCallback cb) throws ManagerCommunicationException { this.impl.originateToApplicationAsync(channel, application, data, timeout, callerId, variables, cb); } public void originateToApplicationAsync(String channel, String application, String data, long timeout, - OriginateCallback cb) throws ManagerCommunicationException - { + OriginateCallback cb) throws ManagerCommunicationException { this.impl.originateToApplicationAsync(channel, application, data, timeout, cb); } public void originateToExtensionAsync(String channel, String context, String exten, int priority, long timeout, - CallerId callerId, Map variables, OriginateCallback cb) throws ManagerCommunicationException - { + CallerId callerId, Map variables, OriginateCallback cb) throws ManagerCommunicationException { this.impl.originateToExtensionAsync(channel, context, exten, priority, timeout, callerId, variables, cb); } public void originateToExtensionAsync(String channel, String context, String exten, int priority, long timeout, - OriginateCallback cb) throws ManagerCommunicationException - { + OriginateCallback cb) throws ManagerCommunicationException { this.impl.originateToExtensionAsync(channel, context, exten, priority, timeout, cb); } - public Collection getChannels() throws ManagerCommunicationException - { + public Collection getChannels() throws ManagerCommunicationException { return this.impl.getChannels(); } - public AsteriskChannel getChannelByName(String name) throws ManagerCommunicationException - { + public AsteriskChannel getChannelByName(String name) throws ManagerCommunicationException { return this.impl.getChannelByName(name); } - public AsteriskChannel getChannelById(String id) throws ManagerCommunicationException - { + public AsteriskChannel getChannelById(String id) throws ManagerCommunicationException { return this.impl.getChannelById(id); } - public Collection getMeetMeRooms() throws ManagerCommunicationException - { + public Collection getMeetMeRooms() throws ManagerCommunicationException { return this.impl.getMeetMeRooms(); } - public MeetMeRoom getMeetMeRoom(String name) throws ManagerCommunicationException - { + public MeetMeRoom getMeetMeRoom(String name) throws ManagerCommunicationException { return this.impl.getMeetMeRoom(name); } - public Collection getQueues() throws ManagerCommunicationException - { + public Collection getQueues() throws ManagerCommunicationException { return this.impl.getQueues(); } - public String getVersion() throws ManagerCommunicationException - { + public String getVersion() throws ManagerCommunicationException { return this.impl.getVersion(); } - public int[] getVersion(String file) throws ManagerCommunicationException - { + public int[] getVersion(String file) throws ManagerCommunicationException { return this.impl.getVersion(file); } - public String getGlobalVariable(String variable) throws ManagerCommunicationException - { + public String getGlobalVariable(String variable) throws ManagerCommunicationException { return this.impl.getGlobalVariable(variable); } - public void setGlobalVariable(String variable, String value) throws ManagerCommunicationException - { + public void setGlobalVariable(String variable, String value) throws ManagerCommunicationException { this.impl.setGlobalVariable(variable, value); } - public Collection getVoicemailboxes() throws ManagerCommunicationException - { + public Collection getVoicemailboxes() throws ManagerCommunicationException { return this.impl.getVoicemailboxes(); } - public List executeCliCommand(String command) throws ManagerCommunicationException - { + public List executeCliCommand(String command) throws ManagerCommunicationException { return this.impl.executeCliCommand(command); } - public boolean isModuleLoaded(String module) throws ManagerCommunicationException - { + public boolean isModuleLoaded(String module) throws ManagerCommunicationException { return this.impl.isModuleLoaded(module); } - public ConfigFile getConfig(String filename) throws ManagerCommunicationException - { + public ConfigFile getConfig(String filename) throws ManagerCommunicationException { return this.impl.getConfig(filename); } - public void reloadAllModules() throws ManagerCommunicationException - { + public void reloadAllModules() throws ManagerCommunicationException { this.impl.reloadAllModules(); } - public void reloadModule(String module) throws ManagerCommunicationException - { + public void reloadModule(String module) throws ManagerCommunicationException { this.impl.reloadModule(module); } - public void unloadModule(String module) throws ManagerCommunicationException - { + public void unloadModule(String module) throws ManagerCommunicationException { this.impl.unloadModule(module); } - public void loadModule(String module) throws ManagerCommunicationException - { + public void loadModule(String module) throws ManagerCommunicationException { this.impl.loadModule(module); } - public void addAsteriskServerListener(AsteriskServerListener listener) throws ManagerCommunicationException - { + public void addAsteriskServerListener(AsteriskServerListener listener) throws ManagerCommunicationException { this.impl.addAsteriskServerListener(listener); } - public void removeAsteriskServerListener(AsteriskServerListener listener) - { + public void removeAsteriskServerListener(AsteriskServerListener listener) { this.impl.removeAsteriskServerListener(listener); } - public boolean isAsteriskServerListening(AsteriskServerListener listener) - { + public boolean isAsteriskServerListening(AsteriskServerListener listener) { return this.impl.isAsteriskServerListening(listener); } - public void shutdown() - { + public void shutdown() { this.impl.shutdown(); } - public Collection getAgents() throws ManagerCommunicationException - { + public Collection getAgents() throws ManagerCommunicationException { return this.impl.getAgents(); } - public AsteriskQueue getQueueByName(String queueName) - { + public AsteriskQueue getQueueByName(String queueName) { return impl.getQueueByName(queueName); } @Override - public List getQueuesUpdatedAfter(Date date) - { + public List getQueuesUpdatedAfter(Date date) { return impl.getQueuesUpdatedAfter(date); } @Override - public void forceQueuesMonitor(boolean force) - { + public void forceQueuesMonitor(boolean force) { impl.forceQueuesMonitor(force); } @Override - public boolean isQueuesMonitorForced() - { + public boolean isQueuesMonitorForced() { return impl.isQueuesMonitorForced(); } @Override - public void addChainListener(ManagerEventListener chainListener) - { + public void addChainListener(ManagerEventListener chainListener) { this.impl.addChainListener(chainListener); } @Override - public void removeChainListener(ManagerEventListener chainListener) - { + public void removeChainListener(ManagerEventListener chainListener) { this.impl.removeChainListener(chainListener); } diff --git a/src/main/java/org/asteriskjava/live/DialedChannelHistoryEntry.java b/src/main/java/org/asteriskjava/live/DialedChannelHistoryEntry.java index a542e7598..a240d3bdf 100644 --- a/src/main/java/org/asteriskjava/live/DialedChannelHistoryEntry.java +++ b/src/main/java/org/asteriskjava/live/DialedChannelHistoryEntry.java @@ -25,8 +25,7 @@ * @version $Id$ * @since 0.3 */ -public class DialedChannelHistoryEntry -{ +public class DialedChannelHistoryEntry { private final Date date; private final AsteriskChannel channel; @@ -36,8 +35,7 @@ public class DialedChannelHistoryEntry * @param date the date the channel was dialed. * @param channel the channel that has been dialed. */ - public DialedChannelHistoryEntry(Date date, AsteriskChannel channel) - { + public DialedChannelHistoryEntry(Date date, AsteriskChannel channel) { this.date = date; this.channel = channel; } @@ -47,8 +45,7 @@ public DialedChannelHistoryEntry(Date date, AsteriskChannel channel) * * @return the date the channel was dialed. */ - public Date getDate() - { + public Date getDate() { return date; } @@ -57,14 +54,12 @@ public Date getDate() * * @return the channel that has been dialed. */ - public AsteriskChannel getChannel() - { + public AsteriskChannel getChannel() { return channel; } @Override - public String toString() - { + public String toString() { final StringBuilder sb; sb = new StringBuilder("DialedChannelHistoryEntry["); diff --git a/src/main/java/org/asteriskjava/live/Disposition.java b/src/main/java/org/asteriskjava/live/Disposition.java index 6823897c1..d71ed3ec0 100644 --- a/src/main/java/org/asteriskjava/live/Disposition.java +++ b/src/main/java/org/asteriskjava/live/Disposition.java @@ -16,11 +16,10 @@ */ package org.asteriskjava.live; -public enum Disposition -{ +public enum Disposition { NO_ANSWER, FAILED, BUSY, ANSWERED, UNKNOWN -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/live/Extension.java b/src/main/java/org/asteriskjava/live/Extension.java index f944001ee..58c22f745 100644 --- a/src/main/java/org/asteriskjava/live/Extension.java +++ b/src/main/java/org/asteriskjava/live/Extension.java @@ -18,8 +18,7 @@ import java.io.Serializable; -public class Extension implements Serializable -{ +public class Extension implements Serializable { /** * Serial version identifier. */ @@ -35,8 +34,7 @@ public class Extension implements Serializable * @param extension * @param priority */ - public Extension(String context, String extension, Integer priority) - { + public Extension(String context, String extension, Integer priority) { this(context, extension, priority, null, null); } @@ -48,8 +46,7 @@ public Extension(String context, String extension, Integer priority) * @param appData */ public Extension(String context, String extension, - Integer priority, String application, String appData) - { + Integer priority, String application, String appData) { this.context = context; this.extension = extension; this.priority = priority; @@ -57,35 +54,29 @@ public Extension(String context, String extension, this.appData = appData; } - public String getContext() - { + public String getContext() { return context; } - public String getExtension() - { + public String getExtension() { return extension; } - public Integer getPriority() - { + public Integer getPriority() { return priority; } - public String getApplication() - { + public String getApplication() { return application; } - public String getAppData() - { + public String getAppData() { return appData; } @Override - public String toString() - { - StringBuilder sb; + public String toString() { + StringBuilder sb; sb = new StringBuilder("Extension["); sb.append("context='").append(getContext()).append("',"); diff --git a/src/main/java/org/asteriskjava/live/ExtensionHistoryEntry.java b/src/main/java/org/asteriskjava/live/ExtensionHistoryEntry.java index 4f496c108..a5baca7bb 100644 --- a/src/main/java/org/asteriskjava/live/ExtensionHistoryEntry.java +++ b/src/main/java/org/asteriskjava/live/ExtensionHistoryEntry.java @@ -26,8 +26,7 @@ * @version $Id$ * @since 0.3 */ -public class ExtensionHistoryEntry implements Serializable -{ +public class ExtensionHistoryEntry implements Serializable { /** * Serial version identifier. */ @@ -41,8 +40,7 @@ public class ExtensionHistoryEntry implements Serializable * @param date the date the extension has been visited. * @param extension the extension that has been visited. */ - public ExtensionHistoryEntry(Date date, Extension extension) - { + public ExtensionHistoryEntry(Date date, Extension extension) { this.date = date; this.extension = extension; } @@ -52,8 +50,7 @@ public ExtensionHistoryEntry(Date date, Extension extension) * * @return the date the extension has been visited. */ - public Date getDate() - { + public Date getDate() { return date; } @@ -62,14 +59,12 @@ public Date getDate() * * @return the extension that has been visited. */ - public Extension getExtension() - { + public Extension getExtension() { return extension; } @Override - public String toString() - { + public String toString() { final StringBuilder sb; sb = new StringBuilder(100); diff --git a/src/main/java/org/asteriskjava/live/HangupCause.java b/src/main/java/org/asteriskjava/live/HangupCause.java index ae08cccef..c8c81ae91 100644 --- a/src/main/java/org/asteriskjava/live/HangupCause.java +++ b/src/main/java/org/asteriskjava/live/HangupCause.java @@ -26,8 +26,7 @@ * @author srt * @version $Id$ */ -public enum HangupCause -{ +public enum HangupCause { AST_CAUSE_UNALLOCATED(1), AST_CAUSE_NO_ROUTE_TRANSIT_NET(2), AST_CAUSE_NO_ROUTE_DESTINATION(3), @@ -88,13 +87,11 @@ public enum HangupCause AST_CAUSE_NOTDEFINED(0), AST_CAUSE_NOSUCHDRIVER(AST_CAUSE_CHAN_NOT_IMPLEMENTED); - HangupCause(int code) - { + HangupCause(int code) { this.code = code; } - HangupCause(HangupCause cause) - { + HangupCause(HangupCause cause) { this.code = cause.code; } @@ -104,8 +101,7 @@ public enum HangupCause * * @return the numeric cause code. */ - public int getCode() - { + public int getCode() { return code; } @@ -115,15 +111,12 @@ public int getCode() * * @param code the numeric cause code. * @return the corresponding HangupCode enum or - * null if there is no such HangupCause. + * null if there is no such HangupCause. */ - public static synchronized HangupCause getByCode(int code) - { - if (causes == null) - { + public static synchronized HangupCause getByCode(int code) { + if (causes == null) { causes = new HashMap<>(); - for (HangupCause cause : values()) - { + for (HangupCause cause : values()) { causes.put(cause.code, cause); } } @@ -132,10 +125,8 @@ public static synchronized HangupCause getByCode(int code) } @Override - public String toString() - { - if (name().startsWith("AST_CAUSE_")) - { + public String toString() { + if (name().startsWith("AST_CAUSE_")) { return name().substring(10); } return name(); diff --git a/src/main/java/org/asteriskjava/live/InvalidPenaltyException.java b/src/main/java/org/asteriskjava/live/InvalidPenaltyException.java index 341b321ce..9c37eb4b2 100644 --- a/src/main/java/org/asteriskjava/live/InvalidPenaltyException.java +++ b/src/main/java/org/asteriskjava/live/InvalidPenaltyException.java @@ -22,8 +22,7 @@ * @author srt * @version $Id$ */ -public class InvalidPenaltyException extends LiveException -{ +public class InvalidPenaltyException extends LiveException { /** * Serial version identifier. */ @@ -34,8 +33,7 @@ public class InvalidPenaltyException extends LiveException * * @param message the message */ - public InvalidPenaltyException(String message) - { + public InvalidPenaltyException(String message) { super(message); } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/live/LinkedChannelHistoryEntry.java b/src/main/java/org/asteriskjava/live/LinkedChannelHistoryEntry.java index 3b93cda86..525f750db 100644 --- a/src/main/java/org/asteriskjava/live/LinkedChannelHistoryEntry.java +++ b/src/main/java/org/asteriskjava/live/LinkedChannelHistoryEntry.java @@ -25,8 +25,7 @@ * @version $Id$ * @since 0.3 */ -public class LinkedChannelHistoryEntry -{ +public class LinkedChannelHistoryEntry { private final Date dateLinked; private Date dateUnlinked; private final AsteriskChannel channel; @@ -37,8 +36,7 @@ public class LinkedChannelHistoryEntry * @param dateLinked the date the channel was linked. * @param channel the channel that has been linked. */ - public LinkedChannelHistoryEntry(Date dateLinked, AsteriskChannel channel) - { + public LinkedChannelHistoryEntry(Date dateLinked, AsteriskChannel channel) { this.dateLinked = dateLinked; this.channel = channel; } @@ -48,8 +46,7 @@ public LinkedChannelHistoryEntry(Date dateLinked, AsteriskChannel channel) * * @return the date the channel was linked. */ - public Date getDateLinked() - { + public Date getDateLinked() { return dateLinked; } @@ -58,8 +55,7 @@ public Date getDateLinked() * * @return the date the channel was unlinked. */ - public Date getDateUnlinked() - { + public Date getDateUnlinked() { return dateUnlinked; } @@ -68,8 +64,7 @@ public Date getDateUnlinked() * * @param dateUnlinked the date the channel was unlinked. */ - public void setDateUnlinked(Date dateUnlinked) - { + public void setDateUnlinked(Date dateUnlinked) { this.dateUnlinked = dateUnlinked; } @@ -78,14 +73,12 @@ public void setDateUnlinked(Date dateUnlinked) * * @return the channel that has been linked. */ - public AsteriskChannel getChannel() - { + public AsteriskChannel getChannel() { return channel; } @Override - public String toString() - { + public String toString() { final StringBuilder sb; sb = new StringBuilder(100); diff --git a/src/main/java/org/asteriskjava/live/LiveException.java b/src/main/java/org/asteriskjava/live/LiveException.java index 1f095eedd..34ab0fa77 100644 --- a/src/main/java/org/asteriskjava/live/LiveException.java +++ b/src/main/java/org/asteriskjava/live/LiveException.java @@ -18,12 +18,11 @@ /** * Base class for exceptions thrown by the live package. - * + * * @author srt * @version $Id$ */ -public abstract class LiveException extends RuntimeException -{ +public abstract class LiveException extends RuntimeException { /** * Serial version identifier. */ @@ -31,22 +30,20 @@ public abstract class LiveException extends RuntimeException /** * Creates a new instance with the given message. - * + * * @param message the message */ - protected LiveException(String message) - { + protected LiveException(String message) { super(message); } /** * Creates a new instance with the given message and cause. - * + * * @param message the message - * @param cause the cause + * @param cause the cause */ - protected LiveException(String message, Throwable cause) - { + protected LiveException(String message, Throwable cause) { super(message, cause); } } diff --git a/src/main/java/org/asteriskjava/live/LiveObject.java b/src/main/java/org/asteriskjava/live/LiveObject.java index 3186f4d34..a956e3a8e 100644 --- a/src/main/java/org/asteriskjava/live/LiveObject.java +++ b/src/main/java/org/asteriskjava/live/LiveObject.java @@ -24,16 +24,15 @@ * Allows you to retrieve the {@link org.asteriskjava.live.AsteriskServer} this * live object belongs to and provides support for * {@link java.beans.PropertyChangeEvent}s. - * + * * @author srt * @version $Id$ * @since 0.3 */ -public interface LiveObject -{ +public interface LiveObject { /** * Returns the AsteriskServer this live object belongs to. - * + * * @return the AsteriskServer this live object belongs to. */ AsteriskServer getServer(); @@ -41,7 +40,7 @@ public interface LiveObject /** * Adds a PropertyChangeListener that is notified whenever a property value * changes. - * + * * @param listener listener to notify */ void addPropertyChangeListener(PropertyChangeListener listener); @@ -49,9 +48,9 @@ public interface LiveObject /** * Adds a PropertyChangeListener that is notified whenever a given property * value changes. - * + * * @param propertyName property to observe - * @param listener listener to notify + * @param listener listener to notify * @see #addPropertyChangeListener(PropertyChangeListener) */ void addPropertyChangeListener(String propertyName, PropertyChangeListener listener); @@ -59,7 +58,7 @@ public interface LiveObject /** * Removes the given PropertyChangeListener that was added by calling * {@link #addPropertyChangeListener(PropertyChangeListener)}. - * + * * @param listener listener to remove */ void removePropertyChangeListener(PropertyChangeListener listener); @@ -67,14 +66,15 @@ public interface LiveObject /** * Removes the given PropertyChangeListener that was added by calling * {@link #addPropertyChangeListener(String, PropertyChangeListener)}. - * + * * @param propertyName property that is observed - * @param listener listener to remove + * @param listener listener to remove */ void removePropertyChangeListener(String propertyName, PropertyChangeListener listener); /** * Timestamp of last update of the Object + * * @return */ long getLastUpdateMillis(); diff --git a/src/main/java/org/asteriskjava/live/ManagerCommunicationException.java b/src/main/java/org/asteriskjava/live/ManagerCommunicationException.java index 395b543ef..0d54b9aa5 100644 --- a/src/main/java/org/asteriskjava/live/ManagerCommunicationException.java +++ b/src/main/java/org/asteriskjava/live/ManagerCommunicationException.java @@ -17,15 +17,13 @@ package org.asteriskjava.live; -public class ManagerCommunicationException extends LiveException -{ +public class ManagerCommunicationException extends LiveException { /** * Serial version identifier. */ private static final long serialVersionUID = -1183197752451685927L; - public ManagerCommunicationException(String message, Throwable cause) - { + public ManagerCommunicationException(String message, Throwable cause) { super(message, cause); } } diff --git a/src/main/java/org/asteriskjava/live/MeetMeRoom.java b/src/main/java/org/asteriskjava/live/MeetMeRoom.java index 4756f0bfd..07c7de102 100644 --- a/src/main/java/org/asteriskjava/live/MeetMeRoom.java +++ b/src/main/java/org/asteriskjava/live/MeetMeRoom.java @@ -21,23 +21,22 @@ /** * Represents an Asterisk MeetMe room.

    * MeetMe rooms bridge multiple channels. - * + * * @author srt * @since 0.3 */ -public interface MeetMeRoom -{ +public interface MeetMeRoom { /** * Returns the number of this MeetMe room.

    * This property is immutable. - * + * * @return the number of this MeetMe room. */ String getRoomNumber(); /** * Returns a collection of all active users in this MeetMe room. - * + * * @return a collection of all active users in this MeetMe room. */ Collection getUsers(); @@ -52,14 +51,14 @@ public interface MeetMeRoom /** * Locks this room so no addtional users can join. - * + * * @throws ManagerCommunicationException if the room can't be locked. */ void lock() throws ManagerCommunicationException; /** * Unlocks this room so additional users can join again. - * + * * @throws ManagerCommunicationException if the room can't be locked. */ void unlock() throws ManagerCommunicationException; diff --git a/src/main/java/org/asteriskjava/live/MeetMeUser.java b/src/main/java/org/asteriskjava/live/MeetMeUser.java index dc883ee51..1b9e10677 100644 --- a/src/main/java/org/asteriskjava/live/MeetMeUser.java +++ b/src/main/java/org/asteriskjava/live/MeetMeUser.java @@ -26,39 +26,38 @@ *

  • muted *
  • state * - * - * @see org.asteriskjava.live.MeetMeRoom + * * @author srt + * @see org.asteriskjava.live.MeetMeRoom * @since 0.3 */ -public interface MeetMeUser extends LiveObject -{ +public interface MeetMeUser extends LiveObject { String PROPERTY_TALKING = "talking"; String PROPERTY_MUTED = "muted"; String PROPERTY_STATE = "state"; - + /** * Returns whether this user is currently talking or not.

    * Asterisk supports talker detection since version 1.2. - * + * * @return true if this user is currently talking and - * talker detection is supported, false otherwise. + * talker detection is supported, false otherwise. */ boolean isTalking(); /** * Returns whether this user is muted or not.

    * Supported since Asterisk version 1.4. - * + * * @return true if this user is muted and - * mute detection is supported, false otherwise. + * mute detection is supported, false otherwise. */ boolean isMuted(); - + /** * Returns the date this user joined the MeetMe room.

    * This property is immutable. - * + * * @return the date this user joined the MeetMe room. */ Date getDateJoined(); @@ -68,16 +67,16 @@ public interface MeetMeUser extends LiveObject * This property is null as long as the user is * in state {@link MeetMeUserState#JOINED} and set to date the * user left when entering {@link MeetMeUserState#LEFT}. - * - * @return the date this user left the MeetMe room or - * null if the user did not yet leave. + * + * @return the date this user left the MeetMe room or + * null if the user did not yet leave. */ Date getDateLeft(); - + /** * Returns the lifecycle status of this MeetMeUser.

    * Initially the user is in state {@link MeetMeUserState#JOINED}. - * + * * @return the lifecycle status of this MeetMeUser. */ MeetMeUserState getState(); @@ -85,7 +84,7 @@ public interface MeetMeUser extends LiveObject /** * Returns the MeetMe room this user joined.

    * This property is immutable. - * + * * @return the MeetMe room this user joined. */ MeetMeRoom getRoom(); @@ -94,7 +93,7 @@ public interface MeetMeUser extends LiveObject * Returns the user number assigned to this user in the room.

    * Usually you won't need to access this property directly.

    * This property is immutable. - * + * * @return the user number assigned to this user in the room. */ Integer getUserNumber(); @@ -102,28 +101,28 @@ public interface MeetMeUser extends LiveObject /** * Returns the channel associated with this user.

    * This property is immutable. - * + * * @return the channel associated with this user. */ AsteriskChannel getChannel(); /** * Stops sending voice from this user to the MeetMe room. - * + * * @throws ManagerCommunicationException if there is a problem talking to the Asterisk server. */ void mute() throws ManagerCommunicationException; /** * (Re)starts sending voice from this user to the MeetMe room. - * + * * @throws ManagerCommunicationException if there is a problem talking to the Asterisk server. */ void unmute() throws ManagerCommunicationException; /** * Removes this user from the MeetMe room. - * + * * @throws ManagerCommunicationException if there is a problem talking to the Asterisk server. */ void kick() throws ManagerCommunicationException; diff --git a/src/main/java/org/asteriskjava/live/MeetMeUserState.java b/src/main/java/org/asteriskjava/live/MeetMeUserState.java index 5a33f6221..24de928b4 100644 --- a/src/main/java/org/asteriskjava/live/MeetMeUserState.java +++ b/src/main/java/org/asteriskjava/live/MeetMeUserState.java @@ -18,12 +18,11 @@ /** * The lifecycle status of a {@link org.asteriskjava.live.MeetMeUser}. - * + * * @author srt * @version $Id$ */ -public enum MeetMeUserState -{ +public enum MeetMeUserState { /** * The user joined the MeetMe room. */ diff --git a/src/main/java/org/asteriskjava/live/NoSuchChannelException.java b/src/main/java/org/asteriskjava/live/NoSuchChannelException.java index faa73050b..0e0d7a368 100644 --- a/src/main/java/org/asteriskjava/live/NoSuchChannelException.java +++ b/src/main/java/org/asteriskjava/live/NoSuchChannelException.java @@ -18,12 +18,11 @@ /** * Indicates that the channel is not available on the Asterisk server. - * + * * @author srt * @version $Id$ */ -public class NoSuchChannelException extends LiveException -{ +public class NoSuchChannelException extends LiveException { /** * Serial version identifier. */ @@ -31,11 +30,10 @@ public class NoSuchChannelException extends LiveException /** * Creates a new instance with the given message. - * + * * @param message the message */ - public NoSuchChannelException(String message) - { + public NoSuchChannelException(String message) { super(message); } } diff --git a/src/main/java/org/asteriskjava/live/NoSuchInterfaceException.java b/src/main/java/org/asteriskjava/live/NoSuchInterfaceException.java index a0c2714d2..afe79568d 100644 --- a/src/main/java/org/asteriskjava/live/NoSuchInterfaceException.java +++ b/src/main/java/org/asteriskjava/live/NoSuchInterfaceException.java @@ -23,8 +23,7 @@ * @version $Id$ * @since 1.0.0 */ -public class NoSuchInterfaceException extends LiveException -{ +public class NoSuchInterfaceException extends LiveException { /** * Serial version identifier. */ @@ -35,8 +34,7 @@ public class NoSuchInterfaceException extends LiveException * * @param message the message */ - public NoSuchInterfaceException(String message) - { + public NoSuchInterfaceException(String message) { super(message); } } diff --git a/src/main/java/org/asteriskjava/live/OriginateCallback.java b/src/main/java/org/asteriskjava/live/OriginateCallback.java index 32e94121e..62883571b 100644 --- a/src/main/java/org/asteriskjava/live/OriginateCallback.java +++ b/src/main/java/org/asteriskjava/live/OriginateCallback.java @@ -26,20 +26,19 @@ * and it is called exactly once.
    * Otherwise one of {@link #onSuccess(AsteriskChannel)} {@link #onBusy(AsteriskChannel)} or * {@link #onNoAnswer(AsteriskChannel)} is called exactly once. - * + * + * @author srt + * @version $Id$ * @see AsteriskServer#originateToApplicationAsync(String, String, String, long, OriginateCallback) * @see AsteriskServer#originateToApplicationAsync(String, String, String, long, CallerId, java.util.Map, OriginateCallback) * @see AsteriskServer#originateToExtensionAsync(String, String, String, int, long, OriginateCallback) * @see AsteriskServer#originateToExtensionAsync(String, String, String, int, long, CallerId, java.util.Map, OriginateCallback) - * @author srt - * @version $Id$ * @since 0.3 */ -public interface OriginateCallback -{ +public interface OriginateCallback { /** * Called when the channel has been created and before it starts ringing. - * + * * @param channel the channel created. */ void onDialing(AsteriskChannel channel); @@ -47,7 +46,7 @@ public interface OriginateCallback /** * Called if the originate was successful and the called party answered the * call. - * + * * @param channel the channel created. */ void onSuccess(AsteriskChannel channel); @@ -55,7 +54,7 @@ public interface OriginateCallback /** * Called if the originate was unsuccessful because the called party did not * answer the call. - * + * * @param channel the channel created. */ void onNoAnswer(AsteriskChannel channel); @@ -63,7 +62,7 @@ public interface OriginateCallback /** * Called if the originate was unsuccessful because the called party was * busy. - * + * * @param channel the channel created. */ void onBusy(AsteriskChannel channel); @@ -71,7 +70,7 @@ public interface OriginateCallback /** * Called if the originate failed for example due to an invalid channel name * or an originate to an unregistered SIP or IAX peer. - * + * * @param cause the exception that caused the failure. */ void onFailure(LiveException cause); diff --git a/src/main/java/org/asteriskjava/live/QueueEntryState.java b/src/main/java/org/asteriskjava/live/QueueEntryState.java index 24e419263..0480428f3 100644 --- a/src/main/java/org/asteriskjava/live/QueueEntryState.java +++ b/src/main/java/org/asteriskjava/live/QueueEntryState.java @@ -2,11 +2,10 @@ /** * The lifecycle status of a {@link org.asteriskjava.live.AsteriskQueueEntry}. - * + * * @author gmi */ -public enum QueueEntryState -{ +public enum QueueEntryState { /** * The user joined the queue. */ diff --git a/src/main/java/org/asteriskjava/live/QueueMemberState.java b/src/main/java/org/asteriskjava/live/QueueMemberState.java index 8a4ca11ed..384f00248 100644 --- a/src/main/java/org/asteriskjava/live/QueueMemberState.java +++ b/src/main/java/org/asteriskjava/live/QueueMemberState.java @@ -47,11 +47,10 @@ * @author Patrick Breucking * @author itaqua * @version $Id$ - * @since 0.3.1 * @see org.asteriskjava.manager.event.QueueMemberEvent + * @since 0.3.1 */ -public enum QueueMemberState -{ +public enum QueueMemberState { DEVICE_UNKNOWN(QueueMemberEvent.AST_DEVICE_UNKNOWN), /** @@ -89,8 +88,6 @@ public enum QueueMemberState DEVICE_ONHOLD(QueueMemberEvent.AST_DEVICE_ONHOLD); - - private final int status; /** @@ -98,8 +95,7 @@ public enum QueueMemberState * * @param status the numerical status code. */ - QueueMemberState(int status) - { + QueueMemberState(int status) { this.status = status; } @@ -107,10 +103,9 @@ public enum QueueMemberState * Returns the numerical status code. * * @return the numerical status code. - * @see org.asteriskjava.manager.event.QueueMemberEvent#getStatus() + * @see org.asteriskjava.manager.event.QueueMemberEvent#getStatus() */ - public int getStatus() - { + public int getStatus() { return status; } @@ -121,17 +116,13 @@ public int getStatus() * @param status integer representation of the status. * @return corresponding QueueMemberState object or null if none matches. */ - public static QueueMemberState valueOf(Integer status) - { - if (status == null) - { + public static QueueMemberState valueOf(Integer status) { + if (status == null) { return null; } - for (QueueMemberState tmp : QueueMemberState.values()) - { - if (tmp.getStatus() == status) - { + for (QueueMemberState tmp : QueueMemberState.values()) { + if (tmp.getStatus() == status) { return tmp; } } diff --git a/src/main/java/org/asteriskjava/live/RecordingException.java b/src/main/java/org/asteriskjava/live/RecordingException.java index b54a7e05d..25a1aff66 100644 --- a/src/main/java/org/asteriskjava/live/RecordingException.java +++ b/src/main/java/org/asteriskjava/live/RecordingException.java @@ -18,12 +18,11 @@ /** * Indicates that a record operation related issue has occured, - * + * * @author videanuadrian * @version $Id$ */ -public class RecordingException extends LiveException -{ +public class RecordingException extends LiveException { /** * Serial version identifier. */ @@ -32,11 +31,10 @@ public class RecordingException extends LiveException /** * Creates a new instance with the given message. - * + * * @param message the message */ - public RecordingException(String message) - { + public RecordingException(String message) { super(message); } } diff --git a/src/main/java/org/asteriskjava/live/SecureAsteriskServer.java b/src/main/java/org/asteriskjava/live/SecureAsteriskServer.java index 0fde9ecc0..3a7f80673 100644 --- a/src/main/java/org/asteriskjava/live/SecureAsteriskServer.java +++ b/src/main/java/org/asteriskjava/live/SecureAsteriskServer.java @@ -11,8 +11,7 @@ * @version $Id$ * @see org.asteriskjava.live.AsteriskServer */ -public class SecureAsteriskServer extends DefaultAsteriskServer -{ +public class SecureAsteriskServer extends DefaultAsteriskServer { /** * Creates a new instance and a new SSL secured {@link ManagerConnection} with the given * connection data. @@ -22,14 +21,12 @@ public class SecureAsteriskServer extends DefaultAsteriskServer * @param username the username to use for login * @param password the password to use for login */ - public SecureAsteriskServer(String hostname, int port, String username, String password) - { + public SecureAsteriskServer(String hostname, int port, String username, String password) { super(hostname, port, username, password); } @Override - protected DefaultManagerConnection createManagerConnection(String hostname, int port, String username, String password) - { + protected DefaultManagerConnection createManagerConnection(String hostname, int port, String username, String password) { DefaultManagerConnection dmc; dmc = super.createManagerConnection(hostname, port, username, password); dmc.setSsl(true); diff --git a/src/main/java/org/asteriskjava/live/Voicemailbox.java b/src/main/java/org/asteriskjava/live/Voicemailbox.java index 15367b458..4daf1a860 100644 --- a/src/main/java/org/asteriskjava/live/Voicemailbox.java +++ b/src/main/java/org/asteriskjava/live/Voicemailbox.java @@ -20,13 +20,12 @@ /** * An Asterisk voicemailbox with status. - * + * * @author srt * @version $Id$ * @since 0.3 */ -public class Voicemailbox implements Serializable -{ +public class Voicemailbox implements Serializable { /** * Serial version identifier. */ @@ -39,13 +38,12 @@ public class Voicemailbox implements Serializable /** * Creates a new instance. - * + * * @param mailbox the name of this mailbox as defined in voicemail.conf. * @param context the context of this mailbox as defined in voicemail.conf. - * @param user the user of this mailbox as defined in voicemail.conf. + * @param user the user of this mailbox as defined in voicemail.conf. */ - public Voicemailbox(String mailbox, String context, String user) - { + public Voicemailbox(String mailbox, String context, String user) { this.mailbox = mailbox; this.context = context; this.user = user; @@ -53,78 +51,70 @@ public Voicemailbox(String mailbox, String context, String user) /** * Returns the name of this mailbox as defined in voicemail.conf. - * + * * @return the name of this mailbox as defined in voicemail.conf. */ - public String getMailbox() - { + public String getMailbox() { return mailbox; } /** * Returns the context of this mailbox as defined in voicemail.conf. - * + * * @return the context of this mailbox as defined in voicemail.conf. */ - public String getContext() - { + public String getContext() { return context; } /** * Returns the user (usually the full name) of this mailbox as defined in voicemail.conf. - * + * * @return the user of this mailbox as defined in voicemail.conf. */ - public String getUser() - { + public String getUser() { return user; } /** * Returns the number of new messages. - * + * * @return the number of new messages. */ - public int getNewMessages() - { + public int getNewMessages() { return newMessages; } /** * Sets the number of new messages. - * + * * @param newMessages the number of new messages. */ - public void setNewMessages(int newMessages) - { + public void setNewMessages(int newMessages) { this.newMessages = newMessages; } /** * Returns the number of old messages. - * + * * @return the number of old messages. */ - public int getOldMessages() - { + public int getOldMessages() { return oldMessages; } /** * Sets the number of old messages. - * + * * @param oldMessages the number of old messages. */ - public void setOldMessages(int oldMessages) - { + public void setOldMessages(int oldMessages) { this.oldMessages = oldMessages; } @Override - public String toString() - { - StringBuilder sb; + public String toString() { + StringBuilder sb; sb = new StringBuilder(100); sb.append("Voicemailbox["); diff --git a/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java b/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java index 23e479ae6..231bb9c0e 100644 --- a/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java +++ b/src/main/java/org/asteriskjava/live/internal/AbstractLiveObject.java @@ -16,23 +16,22 @@ */ package org.asteriskjava.live.internal; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - import org.asteriskjava.live.AsteriskServer; import org.asteriskjava.live.LiveObject; import org.asteriskjava.lock.Lockable; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + /** * Abstract base class for all live objects. - * + * * @author srt * @since 0.3 */ -abstract class AbstractLiveObject extends Lockable implements LiveObject -{ +abstract class AbstractLiveObject extends Lockable implements LiveObject { private final Log logger = LogFactory.getLog(this.getClass()); private final PropertyChangeSupport changes; protected final AsteriskServerImpl server; @@ -40,74 +39,58 @@ abstract class AbstractLiveObject extends Lockable implements LiveObject // last time this object was updated private long lastUpdate; - AbstractLiveObject(AsteriskServerImpl server) - { + AbstractLiveObject(AsteriskServerImpl server) { this.server = server; this.changes = new PropertyChangeSupport(this); stampLastUpdate(); } - public AsteriskServer getServer() - { + public AsteriskServer getServer() { return server; } - public void addPropertyChangeListener(PropertyChangeListener listener) - { + public void addPropertyChangeListener(PropertyChangeListener listener) { changes.addPropertyChangeListener(listener); } - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) - { + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { boolean haveToAdd = true; - for (PropertyChangeListener l : changes.getPropertyChangeListeners()) - { - if (l == listener) - { + for (PropertyChangeListener l : changes.getPropertyChangeListeners()) { + if (l == listener) { haveToAdd = false; break; } } - if (haveToAdd) - { + if (haveToAdd) { changes.addPropertyChangeListener(propertyName, listener); } } - public void removePropertyChangeListener(PropertyChangeListener listener) - { + public void removePropertyChangeListener(PropertyChangeListener listener) { changes.removePropertyChangeListener(listener); } - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) - { + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { changes.removePropertyChangeListener(propertyName, listener); } - protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) - { - if (oldValue != null || newValue != null) - { + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + if (oldValue != null || newValue != null) { stampLastUpdate(); - try - { + try { changes.firePropertyChange(propertyName, oldValue, newValue); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Uncaught exception in PropertyChangeListener", e); } } } @Override - public long getLastUpdateMillis() - { + public long getLastUpdateMillis() { return lastUpdate; } - public void stampLastUpdate() - { + public void stampLastUpdate() { lastUpdate = System.currentTimeMillis(); } } diff --git a/src/main/java/org/asteriskjava/live/internal/AgentManager.java b/src/main/java/org/asteriskjava/live/internal/AgentManager.java index 383929ee0..f9f5a2533 100644 --- a/src/main/java/org/asteriskjava/live/internal/AgentManager.java +++ b/src/main/java/org/asteriskjava/live/internal/AgentManager.java @@ -16,10 +16,6 @@ */ package org.asteriskjava.live.internal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; - import org.asteriskjava.live.AgentState; import org.asteriskjava.live.AsteriskAgent; import org.asteriskjava.live.ManagerCommunicationException; @@ -27,18 +23,14 @@ import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.action.AgentsAction; -import org.asteriskjava.manager.event.AgentCallbackLoginEvent; -import org.asteriskjava.manager.event.AgentCallbackLogoffEvent; -import org.asteriskjava.manager.event.AgentCalledEvent; -import org.asteriskjava.manager.event.AgentCompleteEvent; -import org.asteriskjava.manager.event.AgentConnectEvent; -import org.asteriskjava.manager.event.AgentLoginEvent; -import org.asteriskjava.manager.event.AgentLogoffEvent; -import org.asteriskjava.manager.event.AgentsEvent; -import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.*; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; + /** * Manages all events related to agents on Asterisk server. For correct work * ensure enabled AgentCalledEvents. You have to set @@ -48,8 +40,7 @@ * @version $Id$ * @since 0.3.1 */ -public class AgentManager -{ +public class AgentManager { private final Log logger = LogFactory.getLog(this.getClass()); @@ -66,8 +57,7 @@ public class AgentManager */ private final LockableMap ringingAgents; - AgentManager(AsteriskServerImpl asteriskServerImpl) - { + AgentManager(AsteriskServerImpl asteriskServerImpl) { this.server = asteriskServerImpl; agents = new LockableMap<>(new HashMap<>()); ringingAgents = new LockableMap<>(new HashMap<>()); @@ -78,28 +68,23 @@ public class AgentManager * AgentsAction. * * @throws ManagerCommunicationException if communication with Asterisk - * server fails. + * server fails. */ - void initialize() throws ManagerCommunicationException - { + void initialize() throws ManagerCommunicationException { ResponseEvents re; re = server.sendEventGeneratingAction(new AgentsAction()); - for (ManagerEvent event : re.getEvents()) - { - if (event instanceof AgentsEvent) - { + for (ManagerEvent event : re.getEvents()) { + if (event instanceof AgentsEvent) { logger.info(event); handleAgentsEvent((AgentsEvent) event); } } } - void disconnected() - { - try (LockCloser closer = agents.withLock()) - { + void disconnected() { + try (LockCloser closer = agents.withLock()) { agents.clear(); } } @@ -109,8 +94,7 @@ void disconnected() * * @param event generated by Asterisk server. */ - void handleAgentsEvent(AgentsEvent event) - { + void handleAgentsEvent(AgentsEvent event) { AsteriskAgentImpl agent = new AsteriskAgentImpl(server, event.getName(), "Agent/" + event.getAgent(), AgentState.valueOf(event.getStatus())); logger.info("Adding agent " + agent.getName() + "(" + agent.getAgentId() + ")"); @@ -123,10 +107,8 @@ void handleAgentsEvent(AgentsEvent event) * * @param agent agent to add. */ - private void addAgent(AsteriskAgentImpl agent) - { - try (LockCloser closer = agents.withLock()) - { + private void addAgent(AsteriskAgentImpl agent) { + try (LockCloser closer = agents.withLock()) { agents.put(agent.getAgentId(), agent); } server.fireNewAgent(agent); @@ -138,10 +120,8 @@ private void addAgent(AsteriskAgentImpl agent) * @param agentId identifier for agent * @return the requested agent */ - AsteriskAgentImpl getAgentByAgentId(String agentId) - { - try (LockCloser closer = agents.withLock()) - { + AsteriskAgentImpl getAgentByAgentId(String agentId) { + try (LockCloser closer = agents.withLock()) { return agents.get(agentId); } } @@ -151,11 +131,9 @@ AsteriskAgentImpl getAgentByAgentId(String agentId) * * @param event */ - void handleAgentCalledEvent(AgentCalledEvent event) - { + void handleAgentCalledEvent(AgentCalledEvent event) { AsteriskAgentImpl agent = getAgentByAgentId(event.getAgentCalled()); - if (agent == null) - { + if (agent == null) { logger.error("Ignored AgentCalledEvent for unknown agent " + event.getAgentCalled()); return; } @@ -168,11 +146,9 @@ void handleAgentCalledEvent(AgentCalledEvent event) * * @param agent */ - private void updateAgentState(AsteriskAgentImpl agent, AgentState newState) - { + private void updateAgentState(AsteriskAgentImpl agent, AgentState newState) { logger.info("Set state of agent " + agent.getAgentId() + " to " + newState); - try (LockCloser closer = agent.withLock()) - { + try (LockCloser closer = agent.withLock()) { agent.updateState(newState); } } @@ -185,12 +161,9 @@ private void updateAgentState(AsteriskAgentImpl agent, AgentState newState) * @param channelCalling * @param agent */ - private void updateRingingAgents(String channelCalling, AsteriskAgentImpl agent) - { - try (LockCloser closer = ringingAgents.withLock()) - { - if (ringingAgents.containsKey(channelCalling)) - { + private void updateRingingAgents(String channelCalling, AsteriskAgentImpl agent) { + try (LockCloser closer = ringingAgents.withLock()) { + if (ringingAgents.containsKey(channelCalling)) { updateAgentState(ringingAgents.get(channelCalling), AgentState.AGENT_IDLE); } ringingAgents.put(channelCalling, agent); @@ -202,11 +175,9 @@ private void updateRingingAgents(String channelCalling, AsteriskAgentImpl agent) * * @param event */ - void handleAgentConnectEvent(AgentConnectEvent event) - { + void handleAgentConnectEvent(AgentConnectEvent event) { AsteriskAgentImpl agent = getAgentByAgentId(event.getChannel()); - if (agent == null) - { + if (agent == null) { logger.error("Ignored AgentConnectEvent for unknown agent " + event.getChannel()); return; } @@ -218,13 +189,10 @@ void handleAgentConnectEvent(AgentConnectEvent event) * * @param event */ - void handleAgentLoginEvent(AgentLoginEvent event) - { + void handleAgentLoginEvent(AgentLoginEvent event) { AsteriskAgentImpl agent = getAgentByAgentId("Agent/" + event.getAgent()); - if (agent == null) - { - try (LockCloser closer = agents.withLock()) - { + if (agent == null) { + try (LockCloser closer = agents.withLock()) { logger.error("Ignored AgentLoginEvent for unknown agent " + event.getAgent() + ". Agents: " + agents.values().toString()); @@ -239,11 +207,9 @@ void handleAgentLoginEvent(AgentLoginEvent event) * * @param event */ - void handleAgentLogoffEvent(AgentLogoffEvent event) - { + void handleAgentLogoffEvent(AgentLogoffEvent event) { AsteriskAgentImpl agent = getAgentByAgentId("Agent/" + event.getAgent()); - if (agent == null) - { + if (agent == null) { logger.error("Ignored AgentLogoffEvent for unknown agent " + event.getAgent() + ". Agents: " + agents.values().toString()); return; @@ -256,13 +222,10 @@ void handleAgentLogoffEvent(AgentLogoffEvent event) * * @param event */ - void handleAgentCallbackLoginEvent(AgentCallbackLoginEvent event) - { + void handleAgentCallbackLoginEvent(AgentCallbackLoginEvent event) { AsteriskAgentImpl agent = getAgentByAgentId("Agent/" + event.getAgent()); - if (agent == null) - { - try (LockCloser closer = agents.withLock()) - { + if (agent == null) { + try (LockCloser closer = agents.withLock()) { logger.error("Ignored AgentCallbackLoginEvent for unknown agent " + event.getAgent() + ". Agents: " + agents.values().toString()); @@ -277,11 +240,9 @@ void handleAgentCallbackLoginEvent(AgentCallbackLoginEvent event) * * @param event */ - void handleAgentCallbackLogoffEvent(AgentCallbackLogoffEvent event) - { + void handleAgentCallbackLogoffEvent(AgentCallbackLogoffEvent event) { AsteriskAgentImpl agent = getAgentByAgentId("Agent/" + event.getAgent()); - if (agent == null) - { + if (agent == null) { logger.error("Ignored AgentCallbackLogoffEvent for unknown agent " + event.getAgent() + ". Agents: " + agents.values().toString()); return; @@ -295,12 +256,10 @@ void handleAgentCallbackLogoffEvent(AgentCallbackLogoffEvent event) * * @return a collection of all agents. */ - Collection getAgents() - { + Collection getAgents() { Collection copy; - try (LockCloser closer = agents.withLock()) - { + try (LockCloser closer = agents.withLock()) { copy = new ArrayList(agents.values()); } return copy; @@ -311,11 +270,9 @@ Collection getAgents() * * @param event */ - void handleAgentCompleteEvent(AgentCompleteEvent event) - { + void handleAgentCompleteEvent(AgentCompleteEvent event) { AsteriskAgentImpl agent = getAgentByAgentId(event.getChannel()); - if (agent == null) - { + if (agent == null) { logger.error("Ignored AgentCompleteEvent for unknown agent " + event.getChannel()); return; } diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java index b4c207bcf..97d3ef6c7 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskAgentImpl.java @@ -26,17 +26,14 @@ * @author Patrick Breucking * @version $Id$ */ -public class AsteriskAgentImpl extends AbstractLiveObject implements AsteriskAgent -{ +public class AsteriskAgentImpl extends AbstractLiveObject implements AsteriskAgent { private String name; private String agentId; private AgentState state; - AsteriskAgentImpl(AsteriskServerImpl server, String name, String agentId, AgentState state) - { + AsteriskAgentImpl(AsteriskServerImpl server, String name, String agentId, AgentState state) { super(server); - if (server == null || name == null || agentId == null) - { + if (server == null || name == null || agentId == null) { throw new IllegalArgumentException("Parameters passed to AsteriskAgentImpl() must not be null."); } this.name = name; @@ -44,26 +41,21 @@ public class AsteriskAgentImpl extends AbstractLiveObject implements AsteriskAge this.state = state; } - public String getName() - { + public String getName() { return name; } - public String getAgentId() - { + public String getAgentId() { return agentId; } - public AgentState getState() - { + public AgentState getState() { return state; } - void updateState(AgentState state) - { + void updateState(AgentState state) { - try (LockCloser closer = this.withLock()) - { + try (LockCloser closer = this.withLock()) { final AgentState oldState = this.state; this.state = state; firePropertyChange(PROPERTY_STATE, oldState, this.state); @@ -71,8 +63,7 @@ void updateState(AgentState state) } @Override - public String toString() - { + public String toString() { final StringBuilder sb; sb = new StringBuilder("AsteriskAgent["); diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java index c3ce12250..ff1015708 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskChannelImpl.java @@ -16,53 +16,24 @@ */ package org.asteriskjava.live.internal; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.asteriskjava.live.AsteriskChannel; -import org.asteriskjava.live.AsteriskQueueEntry; -import org.asteriskjava.live.CallDetailRecord; -import org.asteriskjava.live.CallerId; -import org.asteriskjava.live.ChannelState; -import org.asteriskjava.live.ChannelStateHistoryEntry; -import org.asteriskjava.live.DialedChannelHistoryEntry; -import org.asteriskjava.live.Extension; -import org.asteriskjava.live.ExtensionHistoryEntry; -import org.asteriskjava.live.HangupCause; -import org.asteriskjava.live.LinkedChannelHistoryEntry; -import org.asteriskjava.live.ManagerCommunicationException; -import org.asteriskjava.live.NoSuchChannelException; -import org.asteriskjava.live.RecordingException; +import org.asteriskjava.live.*; import org.asteriskjava.lock.LockableList; import org.asteriskjava.lock.LockableMap; import org.asteriskjava.lock.Locker.LockCloser; -import org.asteriskjava.manager.action.AbsoluteTimeoutAction; -import org.asteriskjava.manager.action.ChangeMonitorAction; -import org.asteriskjava.manager.action.GetVarAction; -import org.asteriskjava.manager.action.HangupAction; -import org.asteriskjava.manager.action.MonitorAction; -import org.asteriskjava.manager.action.PauseMixMonitorAction; -import org.asteriskjava.manager.action.PauseMonitorAction; -import org.asteriskjava.manager.action.PlayDtmfAction; -import org.asteriskjava.manager.action.RedirectAction; -import org.asteriskjava.manager.action.SetVarAction; -import org.asteriskjava.manager.action.StopMonitorAction; -import org.asteriskjava.manager.action.UnpauseMonitorAction; +import org.asteriskjava.manager.action.*; import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.MixMonitorDirection; +import java.util.*; + /** * Default implementation of the AsteriskChannel interface. * * @author srt * @version $Id$ */ -class AsteriskChannelImpl extends AbstractLiveObject implements AsteriskChannel -{ +class AsteriskChannelImpl extends AbstractLiveObject implements AsteriskChannel { private static final String CAUSE_VARIABLE_NAME = "PRI_CAUSE"; /** * Date this channel has been created. @@ -152,31 +123,26 @@ class AsteriskChannelImpl extends AbstractLiveObject implements AsteriskChannel /** * Creates a new Channel. * - * @param server server this channel belongs to. - * @param name name of this channel, for example "SIP/1310-20da". - * @param id unique id of this channel, for example "1099015093.165". + * @param server server this channel belongs to. + * @param name name of this channel, for example "SIP/1310-20da". + * @param id unique id of this channel, for example "1099015093.165". * @param dateOfCreation date this channel has been created. * @throws IllegalArgumentException if any of the parameters are null. */ AsteriskChannelImpl(final AsteriskServerImpl server, final String name, final String id, final Date dateOfCreation) - throws IllegalArgumentException - { + throws IllegalArgumentException { super(server); - if (server == null) - { + if (server == null) { throw new IllegalArgumentException("Parameter 'server' passed to AsteriskChannelImpl() must not be null."); } - if (name == null) - { + if (name == null) { throw new IllegalArgumentException("Parameter 'name' passed to AsteriskChannelImpl() must not be null."); } - if (id == null) - { + if (id == null) { throw new IllegalArgumentException("Parameter 'id' passed to AsteriskChannelImpl() must not be null."); } - if (dateOfCreation == null) - { + if (dateOfCreation == null) { throw new IllegalArgumentException( "Parameter 'dateOfCreation' passed to AsteriskChannelImpl() must not be null."); } @@ -194,8 +160,7 @@ class AsteriskChannelImpl extends AbstractLiveObject implements AsteriskChannel this.linkedChannels = new LockableList<>(new ArrayList<>()); } - public String getId() - { + public String getId() { return id; } @@ -203,14 +168,12 @@ public String getId() * Changes the id of this channel. * * @param date date of the name change. - * @param id the new unique id of this channel. + * @param id the new unique id of this channel. */ - void idChanged(Date date, String id) - { + void idChanged(Date date, String id) { final String oldId = this.id; - if (oldId != null && oldId.equals(id)) - { + if (oldId != null && oldId.equals(id)) { return; } @@ -218,18 +181,15 @@ void idChanged(Date date, String id) firePropertyChange(PROPERTY_ID, oldId, id); } - String getTraceId() - { + String getTraceId() { return traceId; } - void setTraceId(String traceId) - { + void setTraceId(String traceId) { this.traceId = traceId; } - public String getName() - { + public String getName() { return name; } @@ -239,12 +199,10 @@ public String getName() * @param date date of the name change. * @param name the new name of this channel. */ - void nameChanged(Date date, String name) - { + void nameChanged(Date date, String name) { final String oldName = this.name; - if (oldName != null && oldName.equals(name)) - { + if (oldName != null && oldName.equals(name)) { return; } @@ -252,8 +210,7 @@ void nameChanged(Date date, String name) firePropertyChange(PROPERTY_NAME, oldName, name); } - public CallerId getCallerId() - { + public CallerId getCallerId() { return callerId; } @@ -262,27 +219,21 @@ public CallerId getCallerId() * * @param callerId the caller id of this channel. */ - void setCallerId(final CallerId callerId) - { + void setCallerId(final CallerId callerId) { final CallerId oldCallerId = this.callerId; this.callerId = callerId; firePropertyChange(PROPERTY_CALLER_ID, oldCallerId, callerId); } - public ChannelState getState() - { + public ChannelState getState() { return state; } - public boolean wasInState(ChannelState state) - { - try (LockCloser closer = stateHistory.withLock()) - { - for (ChannelStateHistoryEntry historyEntry : stateHistory) - { - if (historyEntry.getState() == state) - { + public boolean wasInState(ChannelState state) { + try (LockCloser closer = stateHistory.withLock()) { + for (ChannelStateHistoryEntry historyEntry : stateHistory) { + if (historyEntry.getState() == state) { return true; } } @@ -291,8 +242,7 @@ public boolean wasInState(ChannelState state) return false; } - public boolean wasBusy() - { + public boolean wasBusy() { return wasInState(ChannelState.BUSY) || hangupCause == HangupCause.AST_CAUSE_BUSY || hangupCause == HangupCause.AST_CAUSE_USER_BUSY; } @@ -300,18 +250,15 @@ public boolean wasBusy() /** * Changes the state of this channel. * - * @param date when the state change occurred. + * @param date when the state change occurred. * @param state the new state of this channel. */ - void stateChanged(Date date, ChannelState state) - { - try (LockCloser closer = this.withLock()) - { + void stateChanged(Date date, ChannelState state) { + try (LockCloser closer = this.withLock()) { final ChannelStateHistoryEntry historyEntry; final ChannelState oldState = this.state; - if (oldState == state) - { + if (oldState == state) { return; } @@ -319,8 +266,7 @@ void stateChanged(Date date, ChannelState state) // state // + " (" + name + ")"); historyEntry = new ChannelStateHistoryEntry(date, state); - try (LockCloser closer2 = stateHistory.withLock()) - { + try (LockCloser closer2 = stateHistory.withLock()) { stateHistory.add(historyEntry); } @@ -329,8 +275,7 @@ void stateChanged(Date date, ChannelState state) } } - public String getAccount() - { + public String getAccount() { return account; } @@ -339,26 +284,20 @@ public String getAccount() * * @param account the account code used to bill this channel. */ - void setAccount(String account) - { + void setAccount(String account) { final String oldAccount = this.account; this.account = account; firePropertyChange(PROPERTY_ACCOUNT, oldAccount, account); } - public Extension getCurrentExtension() - { + public Extension getCurrentExtension() { final Extension extension; - try (LockCloser closer = extensionHistory.withLock()) - { - if (extensionHistory.isEmpty()) - { + try (LockCloser closer = extensionHistory.withLock()) { + if (extensionHistory.isEmpty()) { extension = null; - } - else - { + } else { extension = extensionHistory.get(extensionHistory.size() - 1).getExtension(); } } @@ -366,18 +305,13 @@ public Extension getCurrentExtension() return extension; } - public Extension getFirstExtension() - { + public Extension getFirstExtension() { final Extension extension; - try (LockCloser closer = extensionHistory.withLock()) - { - if (extensionHistory.isEmpty()) - { + try (LockCloser closer = extensionHistory.withLock()) { + if (extensionHistory.isEmpty()) { extension = null; - } - else - { + } else { extension = extensionHistory.get(0).getExtension(); } } @@ -385,12 +319,10 @@ public Extension getFirstExtension() return extension; } - public List getExtensionHistory() - { + public List getExtensionHistory() { final List copy; - try (LockCloser closer = extensionHistory.withLock()) - { + try (LockCloser closer = extensionHistory.withLock()) { copy = new ArrayList<>(extensionHistory); } @@ -400,51 +332,43 @@ public List getExtensionHistory() /** * Adds a visted dialplan entry to the history. * - * @param date the date the extension has been visited. + * @param date the date the extension has been visited. * @param extension the visted dialplan entry to add. */ - void extensionVisited(Date date, Extension extension) - { + void extensionVisited(Date date, Extension extension) { final Extension oldCurrentExtension = getCurrentExtension(); final ExtensionHistoryEntry historyEntry; historyEntry = new ExtensionHistoryEntry(date, extension); - try (LockCloser closer = extensionHistory.withLock()) - { + try (LockCloser closer = extensionHistory.withLock()) { extensionHistory.add(historyEntry); } firePropertyChange(PROPERTY_CURRENT_EXTENSION, oldCurrentExtension, extension); } - public Date getDateOfCreation() - { + public Date getDateOfCreation() { return dateOfCreation; } - public Date getDateOfRemoval() - { + public Date getDateOfRemoval() { return dateOfRemoval; } - public HangupCause getHangupCause() - { + public HangupCause getHangupCause() { return hangupCause; } - public String getHangupCauseText() - { + public String getHangupCauseText() { return hangupCauseText; } - public CallDetailRecord getCallDetailRecord() - { + public CallDetailRecord getCallDetailRecord() { return callDetailRecord; } - void callDetailRecordReceived(Date date, CallDetailRecordImpl callDetailRecord) - { + void callDetailRecordReceived(Date date, CallDetailRecordImpl callDetailRecord) { final CallDetailRecordImpl oldCallDetailRecord = this.callDetailRecord; this.callDetailRecord = callDetailRecord; @@ -455,14 +379,12 @@ void callDetailRecordReceived(Date date, CallDetailRecordImpl callDetailRecord) * Sets dateOfRemoval, hangupCause and hangupCauseText and changes state to * {@link ChannelState#HUNGUP}. Fires a PropertyChangeEvent for state. * - * @param dateOfRemoval date the channel was hung up - * @param hangupCause cause for hangup + * @param dateOfRemoval date the channel was hung up + * @param hangupCause cause for hangup * @param hangupCauseText textual representation of hangup cause */ - void hungup(Date dateOfRemoval, HangupCause hangupCause, String hangupCauseText) - { - try (LockCloser closer = this.withLock()) - { + void hungup(Date dateOfRemoval, HangupCause hangupCause, String hangupCauseText) { + try (LockCloser closer = this.withLock()) { this.dateOfRemoval = dateOfRemoval; this.hangupCause = hangupCause; this.hangupCauseText = hangupCauseText; @@ -476,12 +398,10 @@ void hungup(Date dateOfRemoval, HangupCause hangupCause, String hangupCauseText) * * @return List of all dialed channels */ - public List getDialedChannels() - { + public List getDialedChannels() { final List copy; - try (LockCloser closer = dialedChannels.withLock()) - { + try (LockCloser closer = dialedChannels.withLock()) { copy = new ArrayList<>(dialedChannels); } @@ -490,12 +410,9 @@ public List getDialedChannels() /* dialed channels */ - public AsteriskChannel getDialedChannel() - { - try (LockCloser closer = dialedChannels.withLock()) - { - for (AsteriskChannel channel : dialedChannels) - { + public AsteriskChannel getDialedChannel() { + try (LockCloser closer = dialedChannels.withLock()) { + for (AsteriskChannel channel : dialedChannels) { if (channel != null) return channel; } @@ -503,25 +420,20 @@ public AsteriskChannel getDialedChannel() return null; } - public List getDialedChannelHistory() - { + public List getDialedChannelHistory() { final List copy; - try (LockCloser closer = dialedChannelHistory.withLock()) - { + try (LockCloser closer = dialedChannelHistory.withLock()) { copy = new ArrayList<>(dialedChannelHistory); } return copy; } - void channelDialed(Date date, AsteriskChannel dialedChannel) - { - try (LockCloser closer = this.withLock()) - { + void channelDialed(Date date, AsteriskChannel dialedChannel) { + try (LockCloser closer = this.withLock()) { final AsteriskChannel oldDialedChannel; - try (LockCloser closer2 = dialedChannels.withLock()) - { + try (LockCloser closer2 = dialedChannels.withLock()) { if (dialedChannels.isEmpty()) oldDialedChannel = null; else @@ -531,8 +443,7 @@ void channelDialed(Date date, AsteriskChannel dialedChannel) final DialedChannelHistoryEntry historyEntry; historyEntry = new DialedChannelHistoryEntry(date, dialedChannel); - try (LockCloser closer3 = dialedChannelHistory.withLock()) - { + try (LockCloser closer3 = dialedChannelHistory.withLock()) { dialedChannelHistory.add(historyEntry); } @@ -542,30 +453,22 @@ void channelDialed(Date date, AsteriskChannel dialedChannel) /* dialed channels */ - public AsteriskChannel getDialingChannel() - { - try (LockCloser closer = dialingChannels.withLock()) - { + public AsteriskChannel getDialingChannel() { + try (LockCloser closer = dialingChannels.withLock()) { if (dialingChannels.isEmpty()) return null; return dialingChannels.get(0); } } - void channelDialing(Date date, AsteriskChannel dialingChannel) - { - try (LockCloser closer = this.withLock()) - { + void channelDialing(Date date, AsteriskChannel dialingChannel) { + try (LockCloser closer = this.withLock()) { final AsteriskChannel oldDialingChannel; - try (LockCloser closer2 = this.dialingChannels.withLock()) - { - if (this.dialingChannels.isEmpty()) - { + try (LockCloser closer2 = this.dialingChannels.withLock()) { + if (this.dialingChannels.isEmpty()) { oldDialingChannel = null; this.dialingChannels.add(dialingChannel); - } - else - { + } else { oldDialingChannel = this.dialingChannels.get(0); this.dialingChannels.set(0, dialingChannel); } @@ -577,53 +480,42 @@ void channelDialing(Date date, AsteriskChannel dialingChannel) /* linked channels */ - public AsteriskChannel getLinkedChannel() - { - try (LockCloser closer = linkedChannels.withLock()) - { + public AsteriskChannel getLinkedChannel() { + try (LockCloser closer = linkedChannels.withLock()) { if (linkedChannels.isEmpty()) return null; return linkedChannels.get(0); } } - public List getLinkedChannelHistory() - { + public List getLinkedChannelHistory() { final List copy; - try (LockCloser closer = linkedChannelHistory.withLock()) - { + try (LockCloser closer = linkedChannelHistory.withLock()) { copy = new ArrayList<>(linkedChannelHistory); } return copy; } - public boolean wasLinked() - { + public boolean wasLinked() { return wasLinked; } /** * Sets the channel this channel is bridged with. * - * @param date the date this channel was linked. + * @param date the date this channel was linked. * @param linkedChannel the channel this channel is bridged with. */ - void channelLinked(Date date, AsteriskChannel linkedChannel) - { - try (LockCloser closer = this.withLock()) - { + void channelLinked(Date date, AsteriskChannel linkedChannel) { + try (LockCloser closer = this.withLock()) { final AsteriskChannel oldLinkedChannel; - try (LockCloser closer2 = this.linkedChannels.withLock()) - { - if (this.linkedChannels.isEmpty()) - { + try (LockCloser closer2 = this.linkedChannels.withLock()) { + if (this.linkedChannels.isEmpty()) { oldLinkedChannel = null; this.linkedChannels.add(linkedChannel); - } - else - { + } else { oldLinkedChannel = this.linkedChannels.get(0); this.linkedChannels.set(0, linkedChannel); } @@ -632,8 +524,7 @@ void channelLinked(Date date, AsteriskChannel linkedChannel) final LinkedChannelHistoryEntry historyEntry; historyEntry = new LinkedChannelHistoryEntry(date, linkedChannel); - try (LockCloser closer3 = linkedChannelHistory.withLock()) - { + try (LockCloser closer3 = linkedChannelHistory.withLock()) { linkedChannelHistory.add(historyEntry); } this.wasLinked = true; @@ -641,20 +532,14 @@ void channelLinked(Date date, AsteriskChannel linkedChannel) } } - void channelUnlinked(Date date) - { - try (LockCloser closer = this.withLock()) - { + void channelUnlinked(Date date) { + try (LockCloser closer = this.withLock()) { final AsteriskChannel oldLinkedChannel; - try (LockCloser closer2 = this.linkedChannels.withLock()) - { - if (this.linkedChannels.isEmpty()) - { + try (LockCloser closer2 = this.linkedChannels.withLock()) { + if (this.linkedChannels.isEmpty()) { oldLinkedChannel = null; - } - else - { + } else { oldLinkedChannel = this.linkedChannels.get(0); } linkedChannels.clear(); @@ -662,20 +547,15 @@ void channelUnlinked(Date date) final LinkedChannelHistoryEntry historyEntry; - try (LockCloser closer3 = linkedChannelHistory.withLock()) - { - if (linkedChannelHistory.isEmpty()) - { + try (LockCloser closer3 = linkedChannelHistory.withLock()) { + if (linkedChannelHistory.isEmpty()) { historyEntry = null; - } - else - { + } else { historyEntry = linkedChannelHistory.get(linkedChannelHistory.size() - 1); } } - if (historyEntry != null) - { + if (historyEntry != null) { historyEntry.setDateUnlinked(date); } @@ -685,13 +565,11 @@ void channelUnlinked(Date date) /* MeetMe user */ - public MeetMeUserImpl getMeetMeUser() - { + public MeetMeUserImpl getMeetMeUser() { return meetMeUserImpl; } - void setMeetMeUserImpl(MeetMeUserImpl meetMeUserImpl) - { + void setMeetMeUserImpl(MeetMeUserImpl meetMeUserImpl) { final MeetMeUserImpl oldMeetMeUserImpl = this.meetMeUserImpl; this.meetMeUserImpl = meetMeUserImpl; firePropertyChange(PROPERTY_MEET_ME_USER, oldMeetMeUserImpl, meetMeUserImpl); @@ -699,102 +577,81 @@ void setMeetMeUserImpl(MeetMeUserImpl meetMeUserImpl) // action methods - public void hangup() throws ManagerCommunicationException, NoSuchChannelException - { + public void hangup() throws ManagerCommunicationException, NoSuchChannelException { hangup(null); } - public void hangup(HangupCause cause) throws ManagerCommunicationException, NoSuchChannelException - { + public void hangup(HangupCause cause) throws ManagerCommunicationException, NoSuchChannelException { final HangupAction action; final ManagerResponse response; - if (cause != null) - { + if (cause != null) { setVariable(CAUSE_VARIABLE_NAME, Integer.toString(cause.getCode())); action = new HangupAction(name, cause.getCode()); - } - else - { + } else { action = new HangupAction(name); } response = server.sendAction(action); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } } - public void setAbsoluteTimeout(int seconds) throws ManagerCommunicationException, NoSuchChannelException - { + public void setAbsoluteTimeout(int seconds) throws ManagerCommunicationException, NoSuchChannelException { ManagerResponse response; response = server.sendAction(new AbsoluteTimeoutAction(name, seconds)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } } public void redirect(String context, String exten, int priority) - throws ManagerCommunicationException, NoSuchChannelException - { + throws ManagerCommunicationException, NoSuchChannelException { ManagerResponse response; response = server.sendAction(new RedirectAction(name, context, exten, priority)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } } public void redirectBothLegs(String context, String exten, int priority) - throws ManagerCommunicationException, NoSuchChannelException - { + throws ManagerCommunicationException, NoSuchChannelException { ManagerResponse response; - try (LockCloser closer = linkedChannels.withLock()) - { - if (linkedChannels.isEmpty()) - { + try (LockCloser closer = linkedChannels.withLock()) { + if (linkedChannels.isEmpty()) { response = server.sendAction(new RedirectAction(name, context, exten, priority)); - } - else - { + } else { response = server.sendAction(new RedirectAction(name, linkedChannels.get(0).getName(), context, exten, priority, context, exten, priority)); } } - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } } - public String getVariable(String variable) throws ManagerCommunicationException, NoSuchChannelException - { + public String getVariable(String variable) throws ManagerCommunicationException, NoSuchChannelException { ManagerResponse response; String value; - try (LockCloser closer = variables.withLock()) - { + try (LockCloser closer = variables.withLock()) { value = variables.get(variable); - if (value != null) - { + if (value != null) { return value; } response = server.sendAction(new GetVarAction(name, variable)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } value = response.getAttribute("Value"); - if (value == null) - { + if (value == null) { value = response.getAttribute(variable); // for Asterisk 1.0.x } @@ -803,118 +660,96 @@ public String getVariable(String variable) throws ManagerCommunicationException, return value; } - public void setVariable(String variable, String value) throws ManagerCommunicationException, NoSuchChannelException - { + public void setVariable(String variable, String value) throws ManagerCommunicationException, NoSuchChannelException { ManagerResponse response; response = server.sendAction(new SetVarAction(name, variable, value)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } - try (LockCloser closer = variables.withLock()) - { + try (LockCloser closer = variables.withLock()) { variables.put(variable, value); } } - public void playDtmf(String digit) throws ManagerCommunicationException, NoSuchChannelException, IllegalArgumentException - { + public void playDtmf(String digit) throws ManagerCommunicationException, NoSuchChannelException, IllegalArgumentException { ManagerResponse response; - if (digit == null) - { + if (digit == null) { throw new IllegalArgumentException("DTMF digit to send must not be null"); } response = server.sendAction(new PlayDtmfAction(name, digit)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } } - public void startMonitoring(String filename) throws ManagerCommunicationException, NoSuchChannelException - { + public void startMonitoring(String filename) throws ManagerCommunicationException, NoSuchChannelException { startMonitoring(filename, null, false); } - public void startMonitoring(String filename, String format) throws ManagerCommunicationException, NoSuchChannelException - { + public void startMonitoring(String filename, String format) throws ManagerCommunicationException, NoSuchChannelException { startMonitoring(filename, format, false); } public void startMonitoring(String filename, String format, boolean mix) - throws ManagerCommunicationException, NoSuchChannelException - { + throws ManagerCommunicationException, NoSuchChannelException { ManagerResponse response; response = server.sendAction(new MonitorAction(name, filename, format, mix)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } } public void changeMonitoring(String filename) - throws ManagerCommunicationException, NoSuchChannelException, IllegalArgumentException - { + throws ManagerCommunicationException, NoSuchChannelException, IllegalArgumentException { ManagerResponse response; - if (filename == null) - { + if (filename == null) { throw new IllegalArgumentException("New filename must not be null"); } response = server.sendAction(new ChangeMonitorAction(name, filename)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } } - public void stopMonitoring() throws ManagerCommunicationException, NoSuchChannelException - { + public void stopMonitoring() throws ManagerCommunicationException, NoSuchChannelException { ManagerResponse response; response = server.sendAction(new StopMonitorAction(name)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } } - public void pauseMonitoring() throws ManagerCommunicationException, NoSuchChannelException - { + public void pauseMonitoring() throws ManagerCommunicationException, NoSuchChannelException { ManagerResponse response; response = server.sendAction(new PauseMonitorAction(name)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } } - public void unpauseMonitoring() throws ManagerCommunicationException, NoSuchChannelException - { + public void unpauseMonitoring() throws ManagerCommunicationException, NoSuchChannelException { ManagerResponse response; response = server.sendAction(new UnpauseMonitorAction(name)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } } public void pauseMixMonitor(MixMonitorDirection direction) - throws ManagerCommunicationException, NoSuchChannelException, RecordingException - { + throws ManagerCommunicationException, NoSuchChannelException, RecordingException { ManagerResponse response; response = server.sendAction(new PauseMixMonitorAction(this.name, 1, direction.getStateName())); - if (response instanceof ManagerError) - { - if (response.getMessage().equals("Cannot set mute flag")) - { + if (response instanceof ManagerError) { + if (response.getMessage().equals("Cannot set mute flag")) { throw new RecordingException(response.getMessage() + " on channel: '" + name); } throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); @@ -922,35 +757,29 @@ public void pauseMixMonitor(MixMonitorDirection direction) } public void unPauseMixMonitor(MixMonitorDirection direction) - throws ManagerCommunicationException, NoSuchChannelException, RecordingException - { + throws ManagerCommunicationException, NoSuchChannelException, RecordingException { ManagerResponse response; response = server.sendAction(new PauseMixMonitorAction(this.name, 0, direction.getStateName())); - if (response instanceof ManagerError) - { - if (response.getMessage().equals("Cannot set mute flag")) - { + if (response instanceof ManagerError) { + if (response.getMessage().equals("Cannot set mute flag")) { throw new RecordingException(response.getMessage() + " on channel: '" + name); } throw new NoSuchChannelException("Channel '" + name + "' is not available: " + response.getMessage()); } } - public Extension getParkedAt() - { + public Extension getParkedAt() { // warning: the context of this extension will be null until we get the // context property from // the parked call event! return parkedAt; } - public String getParkingLot() - { + public String getParkingLot() { return this.parkingLot; } - void setParkedAt(Extension parkedAt, String parkingLot) - { + void setParkedAt(Extension parkedAt, String parkingLot) { final Extension oldParkedAt = this.parkedAt; final String oldParkingLot = this.parkingLot; @@ -960,70 +789,58 @@ void setParkedAt(Extension parkedAt, String parkingLot) firePropertyChange(PROPERTY_PARKING_LOT, oldParkingLot, parkingLot); } - void updateVariable(String name, String value) - { - try (LockCloser closer = variables.withLock()) - { + void updateVariable(String name, String value) { + try (LockCloser closer = variables.withLock()) { // final String oldValue = variables.get(name); variables.put(name, value); // TODO add notification for updated channel variables } } - public Map getVariables() - { - try (LockCloser closer = variables.withLock()) - { + public Map getVariables() { + try (LockCloser closer = variables.withLock()) { return new HashMap<>(variables); } } - public Character getDtmfReceived() - { + public Character getDtmfReceived() { return this.dtmfReceived; } - public Character getDtmfSent() - { + public Character getDtmfSent() { return this.dtmfSent; } - void dtmfReceived(Character digit) - { + void dtmfReceived(Character digit) { final Character oldDtmfReceived = this.dtmfReceived; this.dtmfReceived = digit; firePropertyChange(PROPERTY_DTMF_RECEIVED, oldDtmfReceived, digit); } - void dtmfSent(Character digit) - { + void dtmfSent(Character digit) { final Character oldDtmfSent = this.dtmfSent; this.dtmfSent = digit; firePropertyChange(PROPERTY_DTMF_SENT, oldDtmfSent, digit); } - public AsteriskQueueEntryImpl getQueueEntry() - { + public AsteriskQueueEntryImpl getQueueEntry() { return queueEntryImpl; } - void setQueueEntry(AsteriskQueueEntryImpl queueEntry) - { + void setQueueEntry(AsteriskQueueEntryImpl queueEntry) { final AsteriskQueueEntry oldQueueEntry = this.queueEntryImpl; this.queueEntryImpl = queueEntry; firePropertyChange(PROPERTY_QUEUE_ENTRY, oldQueueEntry, queueEntry); } - public boolean isMonitored() - { + public boolean isMonitored() { return this.isMonitored; } - void setMonitored(boolean monitored) - { + void setMonitored(boolean monitored) { final boolean oldMonitored = this.isMonitored; this.isMonitored = monitored; @@ -1031,16 +848,14 @@ void setMonitored(boolean monitored) } @Override - public String toString() - { + public String toString() { final StringBuilder sb; final LockableList dialingChannel; final LockableList linkedChannel; sb = new StringBuilder("AsteriskChannel["); - try (LockCloser closer = this.withLock()) - { + try (LockCloser closer = this.withLock()) { sb.append("id='").append(getId()).append("',"); sb.append("name='").append(getName()).append("',"); sb.append("callerId='").append(getCallerId()).append("',"); @@ -1050,41 +865,29 @@ public String toString() dialingChannel = this.dialingChannels; linkedChannel = this.linkedChannels; } - if (dialedChannels.isEmpty()) - { + if (dialedChannels.isEmpty()) { sb.append("dialedChannel=null,"); - } - else - { + } else { sb.append("dialedChannel=AsteriskChannel["); - try (LockCloser closer = dialedChannels.withLock()) - { - for (AsteriskChannel dialedChannel : dialedChannels) - { + try (LockCloser closer = dialedChannels.withLock()) { + for (AsteriskChannel dialedChannel : dialedChannels) { sb.append("[id='").append(dialedChannel.getId()).append("',"); sb.append("name='").append(dialedChannel.getName()).append("'],"); } sb.append("],"); } } - if (dialingChannel.isEmpty()) - { + if (dialingChannel.isEmpty()) { sb.append("dialingChannel=null,"); - } - else - { + } else { sb.append("dialingChannel=AsteriskChannel["); sb.append("id='").append(dialingChannel.get(0).getId()).append("',"); sb.append("name='").append(dialingChannel.get(0).getName()).append("'],"); } - try (LockCloser closer = linkedChannel.withLock()) - { - if (linkedChannel.isEmpty()) - { + try (LockCloser closer = linkedChannel.withLock()) { + if (linkedChannel.isEmpty()) { sb.append("linkedChannel=null"); - } - else - { + } else { sb.append("linkedChannel=AsteriskChannel["); { sb.append("id='").append(linkedChannel.get(0).getId()).append("',"); diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java index f9c7b8875..d10f1856b 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueEntryImpl.java @@ -1,18 +1,17 @@ package org.asteriskjava.live.internal; -import java.util.Date; - import org.asteriskjava.live.AsteriskQueueEntry; import org.asteriskjava.live.QueueEntryState; import org.asteriskjava.lock.Locker.LockCloser; +import java.util.Date; + /** * Default implementation of the AsteriskQueueEntry interface. * * @author gmi */ -class AsteriskQueueEntryImpl extends AbstractLiveObject implements AsteriskQueueEntry -{ +class AsteriskQueueEntryImpl extends AbstractLiveObject implements AsteriskQueueEntry { private final AsteriskQueueImpl queue; private final AsteriskChannelImpl channel; private final Date dateJoined; @@ -32,8 +31,7 @@ class AsteriskQueueEntryImpl extends AbstractLiveObject implements AsteriskQueue private int position = POSITION_UNDETERMINED; AsteriskQueueEntryImpl(AsteriskServerImpl server, AsteriskQueueImpl queue, AsteriskChannelImpl channel, - int reportedPosition, Date dateJoined) - { + int reportedPosition, Date dateJoined) { super(server); this.queue = queue; this.channel = channel; @@ -42,28 +40,23 @@ class AsteriskQueueEntryImpl extends AbstractLiveObject implements AsteriskQueue this.reportedPosition = reportedPosition; } - public String getChannelName() - { + public String getChannelName() { return channel.getName(); } - public AsteriskQueueImpl getQueue() - { + public AsteriskQueueImpl getQueue() { return queue; } - public AsteriskChannelImpl getChannel() - { + public AsteriskChannelImpl getChannel() { return channel; } - public Date getDateJoined() - { + public Date getDateJoined() { return dateJoined; } - public Date getDateLeft() - { + public Date getDateLeft() { return dateLeft; } @@ -73,11 +66,9 @@ public Date getDateLeft() * * @param dateLeft the date this member left the queue. */ - void left(Date dateLeft) - { + void left(Date dateLeft) { QueueEntryState oldState; - try (LockCloser closer = this.withLock()) - { + try (LockCloser closer = this.withLock()) { oldState = this.state; this.dateLeft = dateLeft; this.state = QueueEntryState.LEFT; @@ -85,8 +76,7 @@ void left(Date dateLeft) firePropertyChange(PROPERTY_STATE, oldState, state); } - public QueueEntryState getState() - { + public QueueEntryState getState() { return state; } @@ -97,8 +87,7 @@ public QueueEntryState getState() * * @return the position of the entry in the respective queue, starting at 1 */ - public int getReportedPosition() - { + public int getReportedPosition() { return reportedPosition; } @@ -115,51 +104,42 @@ public int getReportedPosition() * * @return the position of the entry in the respective queue, starting at 1 */ - public int getPosition() - { + public int getPosition() { return position; } - void setPosition(int position) - { + void setPosition(int position) { int oldPosition = this.position; this.position = position; firePropertyChange(PROPERTY_POSITION, oldPosition, position); } - void setReportedPosition(int reportedPosition) - { + void setReportedPosition(int reportedPosition) { int oldPosition = this.reportedPosition; this.reportedPosition = reportedPosition; firePropertyChange(PROPERTY_REPORTED_POSITION, oldPosition, reportedPosition); } @Override - public String toString() - { + public String toString() { StringBuilder sb; int systemHashcode; sb = new StringBuilder("AsteriskQueueEntry["); - try (LockCloser closer = this.withLock()) - { + try (LockCloser closer = this.withLock()) { sb.append("dateJoined=").append(getDateJoined()).append(","); sb.append("postition=").append(getPosition()).append(","); sb.append("dateLeft=").append(getDateLeft()).append(","); systemHashcode = System.identityHashCode(this); } - if (channel != null) - { + if (channel != null) { sb.append("channel=AsteriskChannel["); - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { sb.append("id='").append(channel.getId()).append("',"); sb.append("name='").append(channel.getName()).append("'],"); } - } - else - { + } else { sb.append("channel=null,"); } sb.append("systemHashcode=").append(systemHashcode); diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java index 4e7774b99..b3b922ef6 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueImpl.java @@ -16,14 +16,6 @@ */ package org.asteriskjava.live.internal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; - import org.asteriskjava.live.AsteriskQueue; import org.asteriskjava.live.AsteriskQueueEntry; import org.asteriskjava.live.AsteriskQueueListener; @@ -35,31 +27,29 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.*; + /** * Default implementation of the AsteriskQueue interface. * * @author srt * @version $Id$ */ -class AsteriskQueueImpl extends AbstractLiveObject implements AsteriskQueue -{ +class AsteriskQueueImpl extends AbstractLiveObject implements AsteriskQueue { /** * TimerTask that monitors exceeding service levels. * * @author Patrick Breucking */ - private class ServiceLevelTimerTask extends TimerTask - { + private class ServiceLevelTimerTask extends TimerTask { private final AsteriskQueueEntry entry; - ServiceLevelTimerTask(AsteriskQueueEntry entry) - { + ServiceLevelTimerTask(AsteriskQueueEntry entry) { this.entry = entry; } @Override - public void run() - { + public void run() { fireServiceLevelExceeded(entry); } } @@ -70,7 +60,9 @@ public void run() private String strategy; private Integer serviceLevel; - /** 101118 Octavio Luna Agregado para Ver cambios en Vivo **/ + /** + * 101118 Octavio Luna Agregado para Ver cambios en Vivo + **/ private Integer calls; private Integer holdTime; private Integer talkTime; @@ -87,9 +79,8 @@ public void run() private final LockableMap serviceLevelTimerTasks; AsteriskQueueImpl(AsteriskServerImpl server, String name, Integer max, String strategy, Integer serviceLevel, - Integer weight, Integer calls, Integer holdTime, Integer talkTime, Integer completed, Integer abandoned, - Double serviceLevelPerf) - { + Integer weight, Integer calls, Integer holdTime, Integer talkTime, Integer completed, Integer abandoned, + Double serviceLevelPerf) { super(server); this.name = name; this.max = max; @@ -111,23 +102,19 @@ public void run() stampLastUpdate(); } - void cancelServiceLevelTimer() - { + void cancelServiceLevelTimer() { timer.cancel(); } - public String getName() - { + public String getName() { return name; } - public Integer getMax() - { + public Integer getMax() { return max; } - public String getStrategy() - { + public String getStrategy() { return strategy; } @@ -135,10 +122,8 @@ public String getStrategy() * @param max * @return true if value updated, false otherwise */ - boolean setMax(Integer max) - { - if (!AstUtil.isEqual(this.max, max)) - { + boolean setMax(Integer max) { + if (!AstUtil.isEqual(this.max, max)) { this.max = max; stampLastUpdate(); return true; @@ -146,8 +131,7 @@ boolean setMax(Integer max) return false; } - public Integer getServiceLevel() - { + public Integer getServiceLevel() { return serviceLevel; } @@ -155,10 +139,8 @@ public Integer getServiceLevel() * @param serviceLevel * @return */ - boolean setServiceLevel(Integer serviceLevel) - { - if (!AstUtil.isEqual(this.serviceLevel, serviceLevel)) - { + boolean setServiceLevel(Integer serviceLevel) { + if (!AstUtil.isEqual(this.serviceLevel, serviceLevel)) { this.serviceLevel = serviceLevel; stampLastUpdate(); return true; @@ -168,8 +150,7 @@ boolean setServiceLevel(Integer serviceLevel) } @Override - public Integer getCalls() - { + public Integer getCalls() { return calls; } @@ -177,10 +158,8 @@ public Integer getCalls() * @param calls * @return true if value updated, false otherwise */ - boolean setCalls(Integer calls) - { - if (!AstUtil.isEqual(this.calls, calls)) - { + boolean setCalls(Integer calls) { + if (!AstUtil.isEqual(this.calls, calls)) { this.calls = calls; stampLastUpdate(); return true; @@ -189,14 +168,12 @@ boolean setCalls(Integer calls) } @Override - public Integer getWaiting() - { + public Integer getWaiting() { return calls; } @Override - public Integer getHoldTime() - { + public Integer getHoldTime() { return holdTime; } @@ -204,10 +181,8 @@ public Integer getHoldTime() * @param holdTime * @return true if value updated, false otherwise */ - boolean setHoldTime(Integer holdTime) - { - if (!AstUtil.isEqual(this.holdTime, holdTime)) - { + boolean setHoldTime(Integer holdTime) { + if (!AstUtil.isEqual(this.holdTime, holdTime)) { this.holdTime = holdTime; stampLastUpdate(); return true; @@ -216,8 +191,7 @@ boolean setHoldTime(Integer holdTime) } @Override - public Integer getTalkTime() - { + public Integer getTalkTime() { return talkTime; } @@ -225,10 +199,8 @@ public Integer getTalkTime() * @param talkTime * @return true if value updated, false otherwise */ - boolean setTalkTime(Integer talkTime) - { - if (!AstUtil.isEqual(this.talkTime, talkTime)) - { + boolean setTalkTime(Integer talkTime) { + if (!AstUtil.isEqual(this.talkTime, talkTime)) { this.talkTime = talkTime; stampLastUpdate(); return true; @@ -237,8 +209,7 @@ boolean setTalkTime(Integer talkTime) } @Override - public Integer getCompleted() - { + public Integer getCompleted() { return completed; } @@ -246,10 +217,8 @@ public Integer getCompleted() * @param completed * @return true if value updated, false otherwise */ - boolean setCompleted(Integer completed) - { - if (!AstUtil.isEqual(this.completed, completed)) - { + boolean setCompleted(Integer completed) { + if (!AstUtil.isEqual(this.completed, completed)) { this.completed = completed; stampLastUpdate(); return true; @@ -258,8 +227,7 @@ boolean setCompleted(Integer completed) } @Override - public Integer getAbandoned() - { + public Integer getAbandoned() { return abandoned; } @@ -267,10 +235,8 @@ public Integer getAbandoned() * @param abandoned * @return true if value updated, false otherwise */ - boolean setAbandoned(Integer abandoned) - { - if (!AstUtil.isEqual(this.abandoned, abandoned)) - { + boolean setAbandoned(Integer abandoned) { + if (!AstUtil.isEqual(this.abandoned, abandoned)) { this.abandoned = abandoned; stampLastUpdate(); return true; @@ -280,8 +246,7 @@ boolean setAbandoned(Integer abandoned) } @Override - public Double getServiceLevelPerf() - { + public Double getServiceLevelPerf() { return serviceLevelPerf; } @@ -289,10 +254,8 @@ public Double getServiceLevelPerf() * @param serviceLevelPerf * @return true if value updated, false otherwise */ - boolean setServiceLevelPerf(Double serviceLevelPerf) - { - if (!AstUtil.isEqual(this.serviceLevelPerf, serviceLevelPerf)) - { + boolean setServiceLevelPerf(Double serviceLevelPerf) { + if (!AstUtil.isEqual(this.serviceLevelPerf, serviceLevelPerf)) { this.serviceLevelPerf = serviceLevelPerf; stampLastUpdate(); return true; @@ -300,8 +263,7 @@ boolean setServiceLevelPerf(Double serviceLevelPerf) return false; } - public Integer getWeight() - { + public Integer getWeight() { return weight; } @@ -309,10 +271,8 @@ public Integer getWeight() * @param weight * @return true if value updated, false otherwise */ - boolean setWeight(Integer weight) - { - if (!AstUtil.isEqual(this.weight, weight)) - { + boolean setWeight(Integer weight) { + if (!AstUtil.isEqual(this.weight, weight)) { this.weight = weight; stampLastUpdate(); return true; @@ -320,10 +280,8 @@ boolean setWeight(Integer weight) return false; } - public List getEntries() - { - try (LockCloser closer = entries.withLock()) - { + public List getEntries() { + try (LockCloser closer = entries.withLock()) { return new ArrayList(entries); } } @@ -332,17 +290,13 @@ public List getEntries() * Shifts the position of the queue entries if needed (and fire PCE on queue * entries if appropriate). */ - private void shift() - { + private void shift() { int currentPos = 1; // Asterisk starts at 1 - try (LockCloser closer = entries.withLock()) - { - for (AsteriskQueueEntryImpl qe : entries) - { + try (LockCloser closer = entries.withLock()) { + for (AsteriskQueueEntryImpl qe : entries) { // Only set (and fire PCE on qe) if necessary - if (qe.getPosition() != currentPos) - { + if (qe.getPosition() != currentPos) { qe.setPosition(currentPos); } currentPos++; @@ -361,21 +315,17 @@ private void shift() *

  • NewQueueEntry on server
  • * * - * @param channel the channel that joined the queue + * @param channel the channel that joined the queue * @param reportedPosition the position as given by Asterisk (currently not - * used) - * @param dateReceived the date the hannel joined the queue + * used) + * @param dateReceived the date the hannel joined the queue */ - void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date dateReceived) - { + void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date dateReceived) { AsteriskQueueEntryImpl qe = new AsteriskQueueEntryImpl(server, this, channel, reportedPosition, dateReceived); - try (LockCloser closer = entries.withLock()) - { - if (getEntry(channel.getName()) != null) - { - if (logger.isDebugEnabled()) - { + try (LockCloser closer = entries.withLock()) { + if (getEntry(channel.getName()) != null) { + if (logger.isDebugEnabled()) { logger.debug("Ignored duplicate queue entry during population in queue " + name + " for channel " + channel.getName()); } @@ -391,12 +341,10 @@ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date date } long delay = serviceLevel * 1000L; - if (delay > 0) - { + if (delay > 0) { ServiceLevelTimerTask timerTask = new ServiceLevelTimerTask(qe); timer.schedule(timerTask, delay); - try (LockCloser closer = serviceLevelTimerTasks.withLock()) - { + try (LockCloser closer = serviceLevelTimerTasks.withLock()) { serviceLevelTimerTasks.put(qe, timerTask); } } @@ -421,15 +369,12 @@ void createNewEntry(AsteriskChannelImpl channel, int reportedPosition, Date date *
  • PCE on other queue entries if shifted
  • * * - * @param entry an existing entry object. + * @param entry an existing entry object. * @param dateReceived the remove event was received. */ - void removeEntry(AsteriskQueueEntryImpl entry, Date dateReceived) - { - try (LockCloser closer = serviceLevelTimerTasks.withLock()) - { - if (serviceLevelTimerTasks.containsKey(entry)) - { + void removeEntry(AsteriskQueueEntryImpl entry, Date dateReceived) { + try (LockCloser closer = serviceLevelTimerTasks.withLock()) { + if (serviceLevelTimerTasks.containsKey(entry)) { ServiceLevelTimerTask timerTask = serviceLevelTimerTasks.get(entry); timerTask.cancel(); serviceLevelTimerTasks.remove(entry); @@ -437,20 +382,17 @@ void removeEntry(AsteriskQueueEntryImpl entry, Date dateReceived) } boolean changed; - try (LockCloser closer = entries.withLock()) - { + try (LockCloser closer = entries.withLock()) { changed = entries.remove(entry); - if (changed) - { + if (changed) { // Keep the lock ! shift(); } } // Fire outside lock - if (changed) - { + if (changed) { entry.getChannel().setQueueEntry(null); entry.left(dateReceived); fireEntryLeave(entry); @@ -458,8 +400,7 @@ void removeEntry(AsteriskQueueEntryImpl entry, Date dateReceived) } @Override - public String toString() - { + public String toString() { final StringBuilder sb; sb = new StringBuilder("AsteriskQueue["); @@ -475,12 +416,10 @@ public String toString() sb.append("abandoned='").append(getAbandoned()).append("',"); sb.append("serviceLevelPerf='").append(getServiceLevelPerf()).append("',"); - try (LockCloser closer = entries.withLock()) - { + try (LockCloser closer = entries.withLock()) { sb.append("entries='").append(entries.toString()).append("',"); } - try (LockCloser closer = members.withLock()) - { + try (LockCloser closer = members.withLock()) { sb.append("members='").append(members.toString()).append("',"); } sb.append("systemHashcode=").append(System.identityHashCode(this)); @@ -489,18 +428,14 @@ public String toString() return sb.toString(); } - public void addAsteriskQueueListener(AsteriskQueueListener listener) - { - try (LockCloser closer = listeners.withLock()) - { + public void addAsteriskQueueListener(AsteriskQueueListener listener) { + try (LockCloser closer = listeners.withLock()) { listeners.add(listener); } } - public void removeAsteriskQueueListener(AsteriskQueueListener listener) - { - try (LockCloser closer = listeners.withLock()) - { + public void removeAsteriskQueueListener(AsteriskQueueListener listener) { + try (LockCloser closer = listeners.withLock()) { listeners.remove(listener); } } @@ -510,18 +445,12 @@ public void removeAsteriskQueueListener(AsteriskQueueListener listener) * * @param entry that joins the queue */ - void fireNewEntry(AsteriskQueueEntryImpl entry) - { - try (LockCloser closer = listeners.withLock()) - { - for (AsteriskQueueListener listener : listeners) - { - try - { + void fireNewEntry(AsteriskQueueEntryImpl entry) { + try (LockCloser closer = listeners.withLock()) { + for (AsteriskQueueListener listener : listeners) { + try { listener.onNewEntry(entry); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Exception in onNewEntry()", e); } } @@ -533,18 +462,12 @@ void fireNewEntry(AsteriskQueueEntryImpl entry) * * @param entry that leaves the queue. */ - void fireEntryLeave(AsteriskQueueEntryImpl entry) - { - try (LockCloser closer = listeners.withLock()) - { - for (AsteriskQueueListener listener : listeners) - { - try - { + void fireEntryLeave(AsteriskQueueEntryImpl entry) { + try (LockCloser closer = listeners.withLock()) { + for (AsteriskQueueListener listener : listeners) { + try { listener.onEntryLeave(entry); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Exception in onEntryLeave()", e); } } @@ -557,18 +480,12 @@ void fireEntryLeave(AsteriskQueueEntryImpl entry) * * @param member added to the queue */ - void fireMemberAdded(AsteriskQueueMemberImpl member) - { - try (LockCloser closer = listeners.withLock()) - { - for (AsteriskQueueListener listener : listeners) - { - try - { + void fireMemberAdded(AsteriskQueueMemberImpl member) { + try (LockCloser closer = listeners.withLock()) { + for (AsteriskQueueListener listener : listeners) { + try { listener.onMemberAdded(member); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Exception in onMemberAdded()", e); } } @@ -581,18 +498,12 @@ void fireMemberAdded(AsteriskQueueMemberImpl member) * * @param member that has been removed. */ - void fireMemberRemoved(AsteriskQueueMemberImpl member) - { - try (LockCloser closer = listeners.withLock()) - { - for (AsteriskQueueListener listener : listeners) - { - try - { + void fireMemberRemoved(AsteriskQueueMemberImpl member) { + try (LockCloser closer = listeners.withLock()) { + for (AsteriskQueueListener listener : listeners) { + try { listener.onMemberRemoved(member); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Exception in onMemberRemoved()", e); } } @@ -604,11 +515,9 @@ void fireMemberRemoved(AsteriskQueueMemberImpl member) * * @see org.asteriskjava.live.AsteriskQueue#getMembers() */ - public Collection getMembers() - { + public Collection getMembers() { List listOfMembers = new ArrayList<>(members.size()); - try (LockCloser closer = members.withLock()) - { + try (LockCloser closer = members.withLock()) { listOfMembers.addAll(members.values()); } return listOfMembers; @@ -620,12 +529,9 @@ public Collection getMembers() * @param location ot the member * @return the member by its location. */ - AsteriskQueueMemberImpl getMember(String location) - { - try (LockCloser closer = members.withLock()) - { - if (members.containsKey(location)) - { + AsteriskQueueMemberImpl getMember(String location) { + try (LockCloser closer = members.withLock()) { + if (members.containsKey(location)) { return members.get(location); } } @@ -637,13 +543,10 @@ AsteriskQueueMemberImpl getMember(String location) * * @param member to add */ - void addMember(AsteriskQueueMemberImpl member) - { - try (LockCloser closer = members.withLock()) - { + void addMember(AsteriskQueueMemberImpl member) { + try (LockCloser closer = members.withLock()) { // Check if member already exists - if (members.containsValue(member)) - { + if (members.containsValue(member)) { return; } // If not, add the new member. @@ -660,15 +563,12 @@ void addMember(AsteriskQueueMemberImpl member) * @param location of the member * @return the requested member. */ - AsteriskQueueMemberImpl getMemberByLocation(String location) - { + AsteriskQueueMemberImpl getMemberByLocation(String location) { AsteriskQueueMemberImpl member; - try (LockCloser closer = members.withLock()) - { + try (LockCloser closer = members.withLock()) { member = members.get(location); } - if (member == null) - { + if (member == null) { logger.error("Requested member at location " + location + " not found!"); } return member; @@ -679,18 +579,12 @@ AsteriskQueueMemberImpl getMemberByLocation(String location) * * @param member the changed member. */ - void fireMemberStateChanged(AsteriskQueueMemberImpl member) - { - try (LockCloser closer = listeners.withLock()) - { - for (AsteriskQueueListener listener : listeners) - { - try - { + void fireMemberStateChanged(AsteriskQueueMemberImpl member) { + try (LockCloser closer = listeners.withLock()) { + for (AsteriskQueueListener listener : listeners) { + try { listener.onMemberStateChange(member); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Exception in onMemberStateChange()", e); } } @@ -703,14 +597,10 @@ void fireMemberStateChanged(AsteriskQueueMemberImpl member) * @param channelName The entry's channel name. * @return the queue entry if found, null otherwise. */ - AsteriskQueueEntryImpl getEntry(String channelName) - { - try (LockCloser closer = entries.withLock()) - { - for (AsteriskQueueEntryImpl entry : entries) - { - if (entry.getChannel().getName().equals(channelName)) - { + AsteriskQueueEntryImpl getEntry(String channelName) { + try (LockCloser closer = entries.withLock()) { + for (AsteriskQueueEntryImpl entry : entries) { + if (entry.getChannel().getName().equals(channelName)) { return entry; } } @@ -723,13 +613,10 @@ AsteriskQueueEntryImpl getEntry(String channelName) * * @param member the member to remove. */ - public void removeMember(AsteriskQueueMemberImpl member) - { - try (LockCloser closer = members.withLock()) - { + public void removeMember(AsteriskQueueMemberImpl member) { + try (LockCloser closer = members.withLock()) { // Check if member exists - if (!members.containsValue(member)) - { + if (!members.containsValue(member)) { return; } // If so, remove the member. @@ -740,18 +627,12 @@ public void removeMember(AsteriskQueueMemberImpl member) fireMemberRemoved(member); } - void fireServiceLevelExceeded(AsteriskQueueEntry entry) - { - try (LockCloser closer = listeners.withLock()) - { - for (AsteriskQueueListener listener : listeners) - { - try - { + void fireServiceLevelExceeded(AsteriskQueueEntry entry) { + try (LockCloser closer = listeners.withLock()) { + for (AsteriskQueueListener listener : listeners) { + try { listener.onEntryServiceLevelExceeded(entry); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Exception in fireServiceLevelExceeded()", e); } } @@ -764,19 +645,14 @@ void fireServiceLevelExceeded(AsteriskQueueEntry entry) * @param position the position, starting at 1. * @return the queue entry if exiting at this position, null otherwise. */ - AsteriskQueueEntryImpl getEntry(int position) - { + AsteriskQueueEntryImpl getEntry(int position) { // positions in asterisk start at 1, but list starts at 0 position--; AsteriskQueueEntryImpl foundEntry = null; - try (LockCloser closer = entries.withLock()) - { - try - { + try (LockCloser closer = entries.withLock()) { + try { foundEntry = entries.get(position); - } - catch (IndexOutOfBoundsException e) - { + } catch (IndexOutOfBoundsException e) { // For consistency with the above method, // swallow. We might indeed request the 1st one from time to // time diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java index 0169f7d5c..e37a44f61 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskQueueMemberImpl.java @@ -16,12 +16,7 @@ */ package org.asteriskjava.live.internal; -import org.asteriskjava.live.AsteriskQueue; -import org.asteriskjava.live.AsteriskQueueMember; -import org.asteriskjava.live.InvalidPenaltyException; -import org.asteriskjava.live.ManagerCommunicationException; -import org.asteriskjava.live.NoSuchInterfaceException; -import org.asteriskjava.live.QueueMemberState; +import org.asteriskjava.live.*; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.QueuePauseAction; import org.asteriskjava.manager.action.QueuePenaltyAction; @@ -37,8 +32,7 @@ * @see AsteriskQueueMember * @since 0.3.1 */ -class AsteriskQueueMemberImpl extends AbstractLiveObject implements AsteriskQueueMember -{ +class AsteriskQueueMemberImpl extends AbstractLiveObject implements AsteriskQueueMember { private AsteriskQueue queue; private QueueMemberState state; private String location; @@ -51,19 +45,18 @@ class AsteriskQueueMemberImpl extends AbstractLiveObject implements AsteriskQueu /** * Creates a new queue member. * - * @param server server this channel belongs to. - * @param queue queue this member is registered to. - * @param location location of member. - * @param state state of this member. - * @param paused true if this member is currently paused, - * false otherwise. - * @param penalty penalty of this member. + * @param server server this channel belongs to. + * @param queue queue this member is registered to. + * @param location location of member. + * @param state state of this member. + * @param paused true if this member is currently paused, + * false otherwise. + * @param penalty penalty of this member. * @param membership "dynamic" if the added member is a dynamic queue - * member, "static" if the added member is a static queue member. + * member, "static" if the added member is a static queue member. */ AsteriskQueueMemberImpl(final AsteriskServerImpl server, final AsteriskQueueImpl queue, String location, - QueueMemberState state, boolean paused, Integer penalty, String membership, Integer callsTaken, Long lastCall) - { + QueueMemberState state, boolean paused, Integer penalty, String membership, Integer callsTaken, Long lastCall) { super(server); this.queue = queue; this.location = location; @@ -75,29 +68,24 @@ class AsteriskQueueMemberImpl extends AbstractLiveObject implements AsteriskQueu this.membership = membership; } - public AsteriskQueue getQueue() - { + public AsteriskQueue getQueue() { return queue; } - public String getLocation() - { + public String getLocation() { return location; } - public QueueMemberState getState() - { + public QueueMemberState getState() { return state; } @Override - public Integer getCallsTaken() - { + public Integer getCallsTaken() { return callsTaken; } - public void setCallsTaken(Integer callsTaken) - { + public void setCallsTaken(Integer callsTaken) { this.callsTaken = callsTaken; } @@ -106,49 +94,40 @@ public void setCallsTaken(Integer callsTaken) * was hungup. * * @return the time (in seconds since 01/01/1970) the last successful call - * answered by the added member was hungup. + * answered by the added member was hungup. */ @Override - public Long getLastCall() - { + public Long getLastCall() { return lastCall; } - public void setLastCall(Long lastCall) - { + public void setLastCall(Long lastCall) { this.lastCall = lastCall; } @Deprecated - public boolean getPaused() - { + public boolean getPaused() { return isPaused(); } - public boolean isPaused() - { + public boolean isPaused() { return paused; } - public void setPaused(boolean paused) throws ManagerCommunicationException, NoSuchInterfaceException - { + public void setPaused(boolean paused) throws ManagerCommunicationException, NoSuchInterfaceException { sendPauseAction(new QueuePauseAction(location, queue.getName(), paused)); } - public void setPausedAll(boolean paused) throws ManagerCommunicationException, NoSuchInterfaceException - { + public void setPausedAll(boolean paused) throws ManagerCommunicationException, NoSuchInterfaceException { sendPauseAction(new QueuePauseAction(location, paused)); } - private void sendPauseAction(QueuePauseAction action) throws ManagerCommunicationException, NoSuchInterfaceException - { + private void sendPauseAction(QueuePauseAction action) throws ManagerCommunicationException, NoSuchInterfaceException { final ManagerResponse response = server.sendAction(action); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { // Message: Interface not found - if (action.getQueue() != null) - { + if (action.getQueue() != null) { // Message: Interface not found throw new NoSuchInterfaceException("Unable to change paused state for '" + action.getInterface() + "' on '" + action.getQueue() + "': " + response.getMessage()); @@ -158,45 +137,37 @@ private void sendPauseAction(QueuePauseAction action) throws ManagerCommunicatio } } - public String getMembership() - { + public String getMembership() { return membership; } - public boolean isStatic() - { + public boolean isStatic() { return "static".equals(membership); } - public boolean isDynamic() - { + public boolean isDynamic() { return "dynamic".equals(membership); } - public Integer getPenalty() - { + public Integer getPenalty() { return penalty; } public void setPenalty(int penalty) - throws IllegalArgumentException, ManagerCommunicationException, InvalidPenaltyException - { - if (penalty < 0) - { + throws IllegalArgumentException, ManagerCommunicationException, InvalidPenaltyException { + if (penalty < 0) { throw new IllegalArgumentException("Penalty must not be negative"); } final ManagerResponse response = server.sendAction(new QueuePenaltyAction(location, penalty, queue.getName())); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { throw new InvalidPenaltyException( "Unable to set penalty for '" + location + "' on '" + queue.getName() + "': " + response.getMessage()); } } @Override - public String toString() - { + public String toString() { final StringBuilder sb; sb = new StringBuilder("AsteriskQueueMember["); @@ -213,12 +184,9 @@ public String toString() return sb.toString(); } - boolean stateChanged(QueueMemberState state) - { - try (LockCloser closer = this.withLock()) - { - if (!AstUtil.isEqual(this.state, state)) - { + boolean stateChanged(QueueMemberState state) { + try (LockCloser closer = this.withLock()) { + if (!AstUtil.isEqual(this.state, state)) { QueueMemberState oldState = this.state; this.state = state; firePropertyChange(PROPERTY_STATE, oldState, state); @@ -228,12 +196,9 @@ boolean stateChanged(QueueMemberState state) } } - boolean penaltyChanged(Integer penalty) - { - try (LockCloser closer = this.withLock()) - { - if (!AstUtil.isEqual(this.penalty, penalty)) - { + boolean penaltyChanged(Integer penalty) { + try (LockCloser closer = this.withLock()) { + if (!AstUtil.isEqual(this.penalty, penalty)) { Integer oldPenalty = this.penalty; this.penalty = penalty; firePropertyChange(PROPERTY_PENALTY, oldPenalty, penalty); @@ -244,12 +209,9 @@ boolean penaltyChanged(Integer penalty) } } - boolean pausedChanged(boolean paused) - { - try (LockCloser closer = this.withLock()) - { - if (!AstUtil.isEqual(this.paused, paused)) - { + boolean pausedChanged(boolean paused) { + try (LockCloser closer = this.withLock()) { + if (!AstUtil.isEqual(this.paused, paused)) { boolean oldPaused = this.paused; this.paused = paused; firePropertyChange(PROPERTY_PAUSED, oldPaused, paused); @@ -259,12 +221,9 @@ boolean pausedChanged(boolean paused) } } - boolean callsTakenChanged(Integer callsTaken) - { - try (LockCloser closer = this.withLock()) - { - if (!AstUtil.isEqual(this.callsTaken, callsTaken)) - { + boolean callsTakenChanged(Integer callsTaken) { + try (LockCloser closer = this.withLock()) { + if (!AstUtil.isEqual(this.callsTaken, callsTaken)) { Integer oldcallsTaken = this.callsTaken; this.callsTaken = callsTaken; firePropertyChange(PROPERTY_CALLSTAKEN, oldcallsTaken, callsTaken); @@ -274,12 +233,9 @@ boolean callsTakenChanged(Integer callsTaken) } } - boolean lastCallChanged(Long lastCall) - { - try (LockCloser closer = this.withLock()) - { - if (!AstUtil.isEqual(this.lastCall, lastCall)) - { + boolean lastCallChanged(Long lastCall) { + try (LockCloser closer = this.withLock()) { + if (!AstUtil.isEqual(this.lastCall, lastCall)) { Long oldlastCall = this.lastCall; this.lastCall = lastCall; firePropertyChange(PROPERTY_LASTCALL, oldlastCall, lastCall); diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java index da5ad4610..7062e5ad7 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java @@ -16,120 +16,35 @@ */ package org.asteriskjava.live.internal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.asteriskjava.AsteriskVersion; import org.asteriskjava.config.ConfigFile; -import org.asteriskjava.live.AsteriskAgent; -import org.asteriskjava.live.AsteriskChannel; -import org.asteriskjava.live.AsteriskQueue; -import org.asteriskjava.live.AsteriskQueueEntry; -import org.asteriskjava.live.AsteriskServer; -import org.asteriskjava.live.AsteriskServerListener; -import org.asteriskjava.live.CallerId; -import org.asteriskjava.live.ChannelState; -import org.asteriskjava.live.LiveException; -import org.asteriskjava.live.ManagerCommunicationException; -import org.asteriskjava.live.MeetMeRoom; -import org.asteriskjava.live.MeetMeUser; -import org.asteriskjava.live.NoSuchChannelException; -import org.asteriskjava.live.OriginateCallback; -import org.asteriskjava.live.Voicemailbox; +import org.asteriskjava.live.*; import org.asteriskjava.lock.Lockable; import org.asteriskjava.lock.LockableList; import org.asteriskjava.lock.LockableMap; import org.asteriskjava.lock.LockableSet; import org.asteriskjava.lock.Locker.LockCloser; -import org.asteriskjava.manager.ManagerConnection; -import org.asteriskjava.manager.ManagerConnectionState; -import org.asteriskjava.manager.ManagerEventListener; -import org.asteriskjava.manager.ManagerEventListenerProxy; -import org.asteriskjava.manager.ResponseEvents; -import org.asteriskjava.manager.action.CommandAction; -import org.asteriskjava.manager.action.DbGetAction; -import org.asteriskjava.manager.action.DbPutAction; -import org.asteriskjava.manager.action.EventGeneratingAction; -import org.asteriskjava.manager.action.GetConfigAction; -import org.asteriskjava.manager.action.GetVarAction; -import org.asteriskjava.manager.action.MailboxCountAction; -import org.asteriskjava.manager.action.ManagerAction; -import org.asteriskjava.manager.action.ModuleCheckAction; -import org.asteriskjava.manager.action.ModuleLoadAction; -import org.asteriskjava.manager.action.OriginateAction; -import org.asteriskjava.manager.action.SetVarAction; -import org.asteriskjava.manager.action.SipPeersAction; -import org.asteriskjava.manager.event.AbstractMeetMeEvent; -import org.asteriskjava.manager.event.AgentCallbackLoginEvent; -import org.asteriskjava.manager.event.AgentCallbackLogoffEvent; -import org.asteriskjava.manager.event.AgentCalledEvent; -import org.asteriskjava.manager.event.AgentCompleteEvent; -import org.asteriskjava.manager.event.AgentConnectEvent; -import org.asteriskjava.manager.event.AgentLoginEvent; -import org.asteriskjava.manager.event.AgentLogoffEvent; -import org.asteriskjava.manager.event.AgentsEvent; -import org.asteriskjava.manager.event.BridgeEvent; -import org.asteriskjava.manager.event.CdrEvent; -import org.asteriskjava.manager.event.ConnectEvent; -import org.asteriskjava.manager.event.DbGetResponseEvent; -import org.asteriskjava.manager.event.DialEvent; -import org.asteriskjava.manager.event.DisconnectEvent; -import org.asteriskjava.manager.event.DtmfEvent; -import org.asteriskjava.manager.event.HangupEvent; -import org.asteriskjava.manager.event.JoinEvent; -import org.asteriskjava.manager.event.LeaveEvent; -import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.MonitorStartEvent; -import org.asteriskjava.manager.event.MonitorStopEvent; -import org.asteriskjava.manager.event.NewCallerIdEvent; -import org.asteriskjava.manager.event.NewChannelEvent; -import org.asteriskjava.manager.event.NewExtenEvent; -import org.asteriskjava.manager.event.NewStateEvent; -import org.asteriskjava.manager.event.OriginateResponseEvent; -import org.asteriskjava.manager.event.ParkedCallEvent; -import org.asteriskjava.manager.event.ParkedCallGiveUpEvent; -import org.asteriskjava.manager.event.ParkedCallTimeOutEvent; -import org.asteriskjava.manager.event.PeerEntryEvent; -import org.asteriskjava.manager.event.QueueCallerJoinEvent; -import org.asteriskjava.manager.event.QueueCallerLeaveEvent; -import org.asteriskjava.manager.event.QueueMemberAddedEvent; -import org.asteriskjava.manager.event.QueueMemberPausedEvent; -import org.asteriskjava.manager.event.QueueMemberPenaltyEvent; -import org.asteriskjava.manager.event.QueueMemberRemovedEvent; -import org.asteriskjava.manager.event.QueueMemberStatusEvent; -import org.asteriskjava.manager.event.RenameEvent; -import org.asteriskjava.manager.event.ResponseEvent; -import org.asteriskjava.manager.event.UnparkedCallEvent; -import org.asteriskjava.manager.event.VarSetEvent; -import org.asteriskjava.manager.response.CommandResponse; -import org.asteriskjava.manager.response.GetConfigResponse; -import org.asteriskjava.manager.response.MailboxCountResponse; -import org.asteriskjava.manager.response.ManagerError; -import org.asteriskjava.manager.response.ManagerResponse; -import org.asteriskjava.manager.response.ModuleCheckResponse; +import org.asteriskjava.manager.*; +import org.asteriskjava.manager.action.*; +import org.asteriskjava.manager.event.*; +import org.asteriskjava.manager.response.*; import org.asteriskjava.util.AstUtil; import org.asteriskjava.util.DateUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.*; +import java.util.concurrent.atomic.AtomicLong; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * Default implementation of the {@link AsteriskServer} interface. * * @author srt * @version $Id$ */ -public class AsteriskServerImpl extends Lockable implements AsteriskServer, ManagerEventListener -{ +public class AsteriskServerImpl extends Lockable implements AsteriskServer, ManagerEventListener { private static final String ACTION_ID_PREFIX_ORIGINATE = "AJ_ORIGINATE_"; private static final String SHOW_VERSION_COMMAND = "show version"; private static final String SHOW_VERSION_1_6_COMMAND = "core show version"; @@ -214,8 +129,7 @@ public class AsteriskServerImpl extends Lockable implements AsteriskServer, Mana /** * Creates a new instance. */ - public AsteriskServerImpl() - { + public AsteriskServerImpl() { idCounter = new AtomicLong(); listeners = new LockableSet<>(new LinkedHashSet<>()); originateCallbacks = new LockableMap<>(new HashMap<>()); @@ -229,14 +143,13 @@ public AsteriskServerImpl() * Creates a new instance. * * @param eventConnection the ManagerConnection to use for receiving events - * from Asterisk. + * from Asterisk. */ - public AsteriskServerImpl(ManagerConnection eventConnection) - { + public AsteriskServerImpl(ManagerConnection eventConnection) { this(); setManagerConnection(eventConnection); // todo: !!! Possible bug !!!: - // call to overridable method - // over object construction + // call to overridable method + // over object construction } /** @@ -247,49 +160,38 @@ public AsteriskServerImpl(ManagerConnection eventConnection) * Default is false. * * @param skipQueues true to skip queue initialization, - * false to not skip. + * false to not skip. * @since 0.2 */ - public void setSkipQueues(boolean skipQueues) - { + public void setSkipQueues(boolean skipQueues) { this.skipQueues = skipQueues; } - public void setManagerConnection(ManagerConnection eventConnection) - { - if (this.eventConnection != null) - { + public void setManagerConnection(ManagerConnection eventConnection) { + if (this.eventConnection != null) { throw new IllegalStateException("ManagerConnection already set."); } this.eventConnection = eventConnection; } - public ManagerConnection getManagerConnection() - { + public ManagerConnection getManagerConnection() { return eventConnection; } - public void initialize() throws ManagerCommunicationException - { + public void initialize() throws ManagerCommunicationException { initializeIfNeeded(); } - private void initializeIfNeeded() throws ManagerCommunicationException - { - try (LockCloser closer = this.withLock()) - { - if (initialized || initializing) - { + private void initializeIfNeeded() throws ManagerCommunicationException { + try (LockCloser closer = this.withLock()) { + if (initialized || initializing) { return; } - if (asyncEventHandling && managerEventListenerProxy == null) - { + if (asyncEventHandling && managerEventListenerProxy == null) { managerEventListenerProxy = new ManagerEventListenerProxy(this); eventConnection.addEventListener(managerEventListenerProxy); - } - else if (!asyncEventHandling && eventListener == null) - { + } else if (!asyncEventHandling && eventListener == null) { eventListener = this; eventConnection.addEventListener(eventListener); } @@ -297,14 +199,10 @@ else if (!asyncEventHandling && eventListener == null) initializing = true; if (eventConnection.getState() == ManagerConnectionState.INITIAL - || eventConnection.getState() == ManagerConnectionState.DISCONNECTED) - { - try - { + || eventConnection.getState() == ManagerConnectionState.DISCONNECTED) { + try { eventConnection.login(); - } - catch (Exception e) - { + } catch (Exception e) { throw new ManagerCommunicationException("Unable to login: " + e.getMessage(), e); } } @@ -312,18 +210,14 @@ else if (!asyncEventHandling && eventListener == null) channelManager.initialize(); agentManager.initialize(); meetMeManager.initialize(); - if (!skipQueues) - { + if (!skipQueues) { queueManager.initialize(); } - if (asyncEventHandling && managerEventListenerProxy == null) - { + if (asyncEventHandling && managerEventListenerProxy == null) { managerEventListenerProxy = new ManagerEventListenerProxy(this); eventConnection.addEventListener(managerEventListenerProxy); - } - else if (!asyncEventHandling && eventListener == null) - { + } else if (!asyncEventHandling && eventListener == null) { eventListener = this; eventConnection.addEventListener(eventListener); } @@ -336,14 +230,12 @@ else if (!asyncEventHandling && eventListener == null) /* Implementation of the AsteriskServer interface */ public AsteriskChannel originateToExtension(String channel, String context, String exten, int priority, long timeout) - throws ManagerCommunicationException, NoSuchChannelException - { + throws ManagerCommunicationException, NoSuchChannelException { return originateToExtension(channel, context, exten, priority, timeout, null, null); } public AsteriskChannel originateToExtension(String channel, String context, String exten, int priority, long timeout, - CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException - { + CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException { final OriginateAction originateAction; originateAction = new OriginateAction(); @@ -352,8 +244,7 @@ public AsteriskChannel originateToExtension(String channel, String context, Stri originateAction.setExten(exten); originateAction.setPriority(priority); originateAction.setTimeout(timeout); - if (callerId != null) - { + if (callerId != null) { originateAction.setCallerId(callerId.toString()); } originateAction.setVariables(variables); @@ -362,14 +253,12 @@ public AsteriskChannel originateToExtension(String channel, String context, Stri } public AsteriskChannel originateToApplication(String channel, String application, String data, long timeout) - throws ManagerCommunicationException, NoSuchChannelException - { + throws ManagerCommunicationException, NoSuchChannelException { return originateToApplication(channel, application, data, timeout, null, null); } public AsteriskChannel originateToApplication(String channel, String application, String data, long timeout, - CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException - { + CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException { final OriginateAction originateAction; originateAction = new OriginateAction(); @@ -377,8 +266,7 @@ public AsteriskChannel originateToApplication(String channel, String application originateAction.setApplication(application); originateAction.setData(data); originateAction.setTimeout(timeout); - if (callerId != null) - { + if (callerId != null) { originateAction.setCallerId(callerId.toString()); } originateAction.setVariables(variables); @@ -387,8 +275,7 @@ public AsteriskChannel originateToApplication(String channel, String application } public AsteriskChannel originate(OriginateAction originateAction) - throws ManagerCommunicationException, NoSuchChannelException - { + throws ManagerCommunicationException, NoSuchChannelException { final ResponseEvents responseEvents; final Iterator responseEventIterator; String uniqueId; @@ -403,21 +290,18 @@ public AsteriskChannel originate(OriginateAction originateAction) responseEvents = sendEventGeneratingAction(originateAction, originateAction.getTimeout() + 2000); responseEventIterator = responseEvents.getEvents().iterator(); - if (responseEventIterator.hasNext()) - { + if (responseEventIterator.hasNext()) { ResponseEvent responseEvent; responseEvent = responseEventIterator.next(); - if (responseEvent instanceof OriginateResponseEvent) - { + if (responseEvent instanceof OriginateResponseEvent) { uniqueId = ((OriginateResponseEvent) responseEvent).getUniqueId(); logger.debug(responseEvent.getClass().getName() + " received with uniqueId " + uniqueId); channel = getChannelById(uniqueId); } } - if (channel == null) - { + if (channel == null) { throw new NoSuchChannelException("Channel '" + originateAction.getChannel() + "' is not available"); } @@ -425,14 +309,12 @@ public AsteriskChannel originate(OriginateAction originateAction) } public void originateToExtensionAsync(String channel, String context, String exten, int priority, long timeout, - OriginateCallback cb) throws ManagerCommunicationException - { + OriginateCallback cb) throws ManagerCommunicationException { originateToExtensionAsync(channel, context, exten, priority, timeout, null, null, cb); } public void originateToExtensionAsync(String channel, String context, String exten, int priority, long timeout, - CallerId callerId, Map variables, OriginateCallback cb) throws ManagerCommunicationException - { + CallerId callerId, Map variables, OriginateCallback cb) throws ManagerCommunicationException { final OriginateAction originateAction; originateAction = new OriginateAction(); @@ -441,8 +323,7 @@ public void originateToExtensionAsync(String channel, String context, String ext originateAction.setExten(exten); originateAction.setPriority(priority); originateAction.setTimeout(timeout); - if (callerId != null) - { + if (callerId != null) { originateAction.setCallerId(callerId.toString()); } originateAction.setVariables(variables); @@ -451,14 +332,12 @@ public void originateToExtensionAsync(String channel, String context, String ext } public void originateToApplicationAsync(String channel, String application, String data, long timeout, - OriginateCallback cb) throws ManagerCommunicationException - { + OriginateCallback cb) throws ManagerCommunicationException { originateToApplicationAsync(channel, application, data, timeout, null, null, cb); } public void originateToApplicationAsync(String channel, String application, String data, long timeout, CallerId callerId, - Map variables, OriginateCallback cb) throws ManagerCommunicationException - { + Map variables, OriginateCallback cb) throws ManagerCommunicationException { final OriginateAction originateAction; originateAction = new OriginateAction(); @@ -466,8 +345,7 @@ public void originateToApplicationAsync(String channel, String application, Stri originateAction.setApplication(application); originateAction.setData(data); originateAction.setTimeout(timeout); - if (callerId != null) - { + if (callerId != null) { originateAction.setCallerId(callerId.toString()); } originateAction.setVariables(variables); @@ -475,18 +353,14 @@ public void originateToApplicationAsync(String channel, String application, Stri originateAsync(originateAction, cb); } - public void originateAsync(OriginateAction originateAction, OriginateCallback cb) throws ManagerCommunicationException - { + public void originateAsync(OriginateAction originateAction, OriginateCallback cb) throws ManagerCommunicationException { final Map variables; final String traceId; traceId = ACTION_ID_PREFIX_ORIGINATE + idCounter.getAndIncrement(); - if (originateAction.getVariables() == null) - { + if (originateAction.getVariables() == null) { variables = new HashMap<>(); - } - else - { + } else { variables = new HashMap<>(originateAction.getVariables()); } @@ -499,14 +373,12 @@ public void originateAsync(OriginateAction originateAction, OriginateCallback cb originateAction.setAsync(Boolean.TRUE); originateAction.setActionId(traceId); - if (cb != null) - { + if (cb != null) { final OriginateCallbackData callbackData; callbackData = new OriginateCallbackData(originateAction, DateUtil.getDate(), cb); // register callback - try (LockCloser closer = originateCallbacks.withLock()) - { + try (LockCloser closer = originateCallbacks.withLock()) { originateCallbacks.put(traceId, callbackData); } } @@ -515,88 +387,70 @@ public void originateAsync(OriginateAction originateAction, OriginateCallback cb sendActionOnEventConnection(originateAction); } - public Collection getChannels() throws ManagerCommunicationException - { + public Collection getChannels() throws ManagerCommunicationException { initializeIfNeeded(); return channelManager.getChannels(); } - public AsteriskChannel getChannelByName(String name) throws ManagerCommunicationException - { + public AsteriskChannel getChannelByName(String name) throws ManagerCommunicationException { initializeIfNeeded(); return channelManager.getChannelImplByName(name); } - public AsteriskChannel getChannelById(String id) throws ManagerCommunicationException - { + public AsteriskChannel getChannelById(String id) throws ManagerCommunicationException { initializeIfNeeded(); return channelManager.getChannelImplById(id); } - public Collection getMeetMeRooms() throws ManagerCommunicationException - { + public Collection getMeetMeRooms() throws ManagerCommunicationException { initializeIfNeeded(); return meetMeManager.getMeetMeRooms(); } - public MeetMeRoom getMeetMeRoom(String name) throws ManagerCommunicationException - { + public MeetMeRoom getMeetMeRoom(String name) throws ManagerCommunicationException { initializeIfNeeded(); return meetMeManager.getOrCreateRoomImpl(name); } - public Collection getQueues() throws ManagerCommunicationException - { + public Collection getQueues() throws ManagerCommunicationException { initializeIfNeeded(); return queueManager.getQueues(); } @Override - public AsteriskQueue getQueueByName(String queueName) - { + public AsteriskQueue getQueueByName(String queueName) { initializeIfNeeded(); return queueManager.getQueueByName(queueName); } @Override - public List getQueuesUpdatedAfter(Date date) - { + public List getQueuesUpdatedAfter(Date date) { initializeIfNeeded(); return queueManager.getQueuesUpdatedAfter(date); } - public String getVersion() throws ManagerCommunicationException - { - try (LockCloser closer = this.withLock()) - { + public String getVersion() throws ManagerCommunicationException { + try (LockCloser closer = this.withLock()) { final ManagerResponse response; final String command; initializeIfNeeded(); - if (version == null) - { - if (eventConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) - { + if (version == null) { + if (eventConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) { command = SHOW_VERSION_1_6_COMMAND; - } - else - { + } else { command = SHOW_VERSION_COMMAND; } response = sendAction(new CommandAction(command)); - if (response instanceof CommandResponse) - { + if (response instanceof CommandResponse) { final List result; result = ((CommandResponse) response).getResult(); - if (!result.isEmpty()) - { + if (!result.isEmpty()) { version = result.get(0); } - } - else - { + } else { logger.error("Response to CommandAction(\"" + command + "\") was not a CommandResponse but " + response); } } @@ -605,46 +459,37 @@ public String getVersion() throws ManagerCommunicationException } } - public int[] getVersion(String file) throws ManagerCommunicationException - { + public int[] getVersion(String file) throws ManagerCommunicationException { String fileVersion = null; String[] parts; int[] intParts; initializeIfNeeded(); - if (versions == null) - { + if (versions == null) { LockableMap map; ManagerResponse response; map = new LockableMap<>(new HashMap<>()); - try - { + try { final String command; - if (eventConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) - { + if (eventConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) { command = SHOW_VERSION_FILES_1_6_COMMAND; - } - else - { + } else { command = SHOW_VERSION_FILES_COMMAND; } response = sendAction(new CommandAction(command)); - if (response instanceof CommandResponse) - { + if (response instanceof CommandResponse) { List result; result = ((CommandResponse) response).getResult(); - for (int i = 2; i < result.size(); i++) - { + for (int i = 2; i < result.size(); i++) { String line; Matcher matcher; line = result.get(i); matcher = SHOW_VERSION_FILES_PATTERN.matcher(line); - if (matcher.find()) - { + if (matcher.find()) { String key = matcher.group(1); String value = matcher.group(2); @@ -654,41 +499,29 @@ public int[] getVersion(String file) throws ManagerCommunicationException fileVersion = map.get(file); versions = map; - } - else - { + } else { logger.error("Response to CommandAction(\"" + command + "\") was not a CommandResponse but " + response); } - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Unable to send '" + SHOW_VERSION_FILES_COMMAND + "' command.", e); } - } - else - { - try (LockCloser closer = versions.withLock()) - { + } else { + try (LockCloser closer = versions.withLock()) { fileVersion = versions.get(file); } } - if (fileVersion == null) - { + if (fileVersion == null) { return null; } parts = fileVersion.split("\\."); intParts = new int[parts.length]; - for (int i = 0; i < parts.length; i++) - { - try - { + for (int i = 0; i < parts.length; i++) { + try { intParts[i] = Integer.parseInt(parts[i]); - } - catch (NumberFormatException e) - { + } catch (NumberFormatException e) { intParts[i] = 0; } } @@ -696,71 +529,59 @@ public int[] getVersion(String file) throws ManagerCommunicationException return intParts; } - public String getGlobalVariable(String variable) throws ManagerCommunicationException - { + public String getGlobalVariable(String variable) throws ManagerCommunicationException { ManagerResponse response; String value; initializeIfNeeded(); response = sendAction(new GetVarAction(variable)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { return null; } value = response.getAttribute("Value"); - if (value == null) - { + if (value == null) { value = response.getAttribute(variable); // for Asterisk 1.0.x } return value; } - public void setGlobalVariable(String variable, String value) throws ManagerCommunicationException - { + public void setGlobalVariable(String variable, String value) throws ManagerCommunicationException { ManagerResponse response; initializeIfNeeded(); response = sendAction(new SetVarAction(variable, value)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { logger.error("Unable to set global variable '" + variable + "' to '" + value + "':" + response.getMessage()); } } - public Collection getVoicemailboxes() throws ManagerCommunicationException - { + public Collection getVoicemailboxes() throws ManagerCommunicationException { final Collection voicemailboxes; ManagerResponse response; final List result; initializeIfNeeded(); voicemailboxes = new ArrayList<>(); - if (eventConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) - { + if (eventConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) { response = sendAction(new CommandAction(SHOW_VOICEMAIL_USERS_1_6_COMMAND)); - } - else - { + } else { response = sendAction(new CommandAction(SHOW_VOICEMAIL_USERS_COMMAND)); } - if (!(response instanceof CommandResponse)) - { + if (!(response instanceof CommandResponse)) { logger.error("Response to CommandAction(\"" + SHOW_VOICEMAIL_USERS_COMMAND + "\") was not a CommandResponse but " + response); return voicemailboxes; } result = ((CommandResponse) response).getResult(); - if (result == null || result.isEmpty()) - { + if (result == null || result.isEmpty()) { return voicemailboxes; } // remove headline result.remove(0); - for (String line : result) - { + for (String line : result) { final Matcher matcher; final Voicemailbox voicemailbox; final String context; @@ -768,8 +589,7 @@ public Collection getVoicemailboxes() throws ManagerCommunicationE final String user; matcher = SHOW_VOICEMAIL_USERS_PATTERN.matcher(line); - if (!matcher.find()) - { + if (!matcher.find()) { continue; } @@ -782,22 +602,18 @@ public Collection getVoicemailboxes() throws ManagerCommunicationE } // get message count for each mailbox - for (Voicemailbox voicemailbox : voicemailboxes) - { + for (Voicemailbox voicemailbox : voicemailboxes) { final String fullname; fullname = voicemailbox.getMailbox() + "@" + voicemailbox.getContext(); response = sendAction(new MailboxCountAction(fullname)); - if (response instanceof MailboxCountResponse) - { + if (response instanceof MailboxCountResponse) { MailboxCountResponse mailboxCountResponse; mailboxCountResponse = (MailboxCountResponse) response; voicemailbox.setNewMessages(mailboxCountResponse.getNewMessages()); voicemailbox.setOldMessages(mailboxCountResponse.getOldMessages()); - } - else - { + } else { logger.error("Response to MailboxCountAction was not a MailboxCountResponse but " + response); } } @@ -805,14 +621,12 @@ public Collection getVoicemailboxes() throws ManagerCommunicationE return voicemailboxes; } - public List executeCliCommand(String command) throws ManagerCommunicationException - { + public List executeCliCommand(String command) throws ManagerCommunicationException { final ManagerResponse response; initializeIfNeeded(); response = sendAction(new CommandAction(command)); - if (!(response instanceof CommandResponse)) - { + if (!(response instanceof CommandResponse)) { throw new ManagerCommunicationException( "Response to CommandAction(\"" + command + "\") was not a CommandResponse but " + response, null); } @@ -820,52 +634,43 @@ public List executeCliCommand(String command) throws ManagerCommunicatio return ((CommandResponse) response).getResult(); } - public boolean isModuleLoaded(String module) throws ManagerCommunicationException - { + public boolean isModuleLoaded(String module) throws ManagerCommunicationException { return sendAction(new ModuleCheckAction(module)) instanceof ModuleCheckResponse; } - public void loadModule(String module) throws ManagerCommunicationException - { + public void loadModule(String module) throws ManagerCommunicationException { sendModuleLoadAction(module, ModuleLoadAction.LOAD_TYPE_LOAD); } - public void unloadModule(String module) throws ManagerCommunicationException - { + public void unloadModule(String module) throws ManagerCommunicationException { sendModuleLoadAction(module, ModuleLoadAction.LOAD_TYPE_UNLOAD); } - public void reloadModule(String module) throws ManagerCommunicationException - { + public void reloadModule(String module) throws ManagerCommunicationException { sendModuleLoadAction(module, ModuleLoadAction.LOAD_TYPE_RELOAD); } - public void reloadAllModules() throws ManagerCommunicationException - { + public void reloadAllModules() throws ManagerCommunicationException { sendModuleLoadAction(null, ModuleLoadAction.LOAD_TYPE_RELOAD); } - protected void sendModuleLoadAction(String module, String loadType) throws ManagerCommunicationException - { + protected void sendModuleLoadAction(String module, String loadType) throws ManagerCommunicationException { final ManagerResponse response; response = sendAction(new ModuleLoadAction(module, loadType)); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { final ManagerError error = (ManagerError) response; throw new ManagerCommunicationException(error.getMessage(), null); } } - public ConfigFile getConfig(String filename) throws ManagerCommunicationException - { + public ConfigFile getConfig(String filename) throws ManagerCommunicationException { final ManagerResponse response; final GetConfigResponse getConfigResponse; initializeIfNeeded(); response = sendAction(new GetConfigAction(filename)); - if (!(response instanceof GetConfigResponse)) - { + if (!(response instanceof GetConfigResponse)) { throw new ManagerCommunicationException( "Response to GetConfigAction(\"" + filename + "\") was not a CommandResponse but " + response, null); } @@ -874,17 +679,13 @@ public ConfigFile getConfig(String filename) throws ManagerCommunicationExceptio final Map categoryMap = getConfigResponse.getCategories(); final Map> categories = new LinkedHashMap<>(); - for (Map.Entry categoryEntry : categoryMap.entrySet()) - { + for (Map.Entry categoryEntry : categoryMap.entrySet()) { final List lines; final Map lineMap = getConfigResponse.getLines(categoryEntry.getKey()); - if (lineMap == null) - { + if (lineMap == null) { lines = new ArrayList<>(); - } - else - { + } else { lines = new ArrayList<>(lineMap.values()); } @@ -895,141 +696,102 @@ public ConfigFile getConfig(String filename) throws ManagerCommunicationExceptio } @Override - public void addAsteriskServerListener(AsteriskServerListener listener) throws ManagerCommunicationException - { + public void addAsteriskServerListener(AsteriskServerListener listener) throws ManagerCommunicationException { initializeIfNeeded(); - try (LockCloser closer = listeners.withLock()) - { - if (!listeners.contains(listener)) - { + try (LockCloser closer = listeners.withLock()) { + if (!listeners.contains(listener)) { listeners.add(listener); } } } @Override - public void removeAsteriskServerListener(AsteriskServerListener listener) - { - try (LockCloser closer = listeners.withLock()) - { + public void removeAsteriskServerListener(AsteriskServerListener listener) { + try (LockCloser closer = listeners.withLock()) { listeners.remove(listener); } } @Override - public boolean isAsteriskServerListening(AsteriskServerListener listener) - { + public boolean isAsteriskServerListening(AsteriskServerListener listener) { return listeners.contains(listener); } - public void addChainListener(ManagerEventListener chainListener) - { - try (LockCloser closer = this.chainListeners.withLock()) - { + public void addChainListener(ManagerEventListener chainListener) { + try (LockCloser closer = this.chainListeners.withLock()) { if (!this.chainListeners.contains(chainListener)) this.chainListeners.add(chainListener); } } - public void removeChainListener(ManagerEventListener chainListener) - { + public void removeChainListener(ManagerEventListener chainListener) { this.chainListeners.remove(chainListener); } - void fireNewAsteriskChannel(AsteriskChannel channel) - { - try (LockCloser closer = listeners.withLock()) - { - for (AsteriskServerListener listener : listeners) - { - try - { + void fireNewAsteriskChannel(AsteriskChannel channel) { + try (LockCloser closer = listeners.withLock()) { + for (AsteriskServerListener listener : listeners) { + try { listener.onNewAsteriskChannel(channel); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Exception in onNewAsteriskChannel()", e); } } } } - void fireNewMeetMeUser(MeetMeUser user) - { - try (LockCloser closer = listeners.withLock()) - { - for (AsteriskServerListener listener : listeners) - { - try - { + void fireNewMeetMeUser(MeetMeUser user) { + try (LockCloser closer = listeners.withLock()) { + for (AsteriskServerListener listener : listeners) { + try { listener.onNewMeetMeUser(user); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Exception in onNewMeetMeUser()", e); } } } } - ManagerResponse sendActionOnEventConnection(ManagerAction action) throws ManagerCommunicationException - { - try - { + ManagerResponse sendActionOnEventConnection(ManagerAction action) throws ManagerCommunicationException { + try { return eventConnection.sendAction(action); - } - catch (Exception e) - { + } catch (Exception e) { throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e); } } - ManagerResponse sendAction(ManagerAction action) throws ManagerCommunicationException - { + ManagerResponse sendAction(ManagerAction action) throws ManagerCommunicationException { // return connectionPool.sendAction(action); - try - { + try { return eventConnection.sendAction(action); - } - catch (Exception e) - { + } catch (Exception e) { throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e); } } - ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws ManagerCommunicationException - { + ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws ManagerCommunicationException { // return connectionPool.sendEventGeneratingAction(action); - try - { + try { return eventConnection.sendEventGeneratingAction(action); - } - catch (Exception e) - { + } catch (Exception e) { throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e); } } ResponseEvents - sendEventGeneratingAction(EventGeneratingAction action, long timeout) throws ManagerCommunicationException - { + sendEventGeneratingAction(EventGeneratingAction action, long timeout) throws ManagerCommunicationException { // return connectionPool.sendEventGeneratingAction(action, timeout); - try - { + try { return eventConnection.sendEventGeneratingAction(action, timeout); - } - catch (Exception e) - { + } catch (Exception e) { throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e); } } - OriginateCallbackData getOriginateCallbackDataByTraceId(String traceId) - { - try (LockCloser closer = originateCallbacks.withLock()) - { + OriginateCallbackData getOriginateCallbackDataByTraceId(String traceId) { + try (LockCloser closer = originateCallbacks.withLock()) { return originateCallbacks.get(traceId); } } @@ -1041,166 +803,94 @@ OriginateCallbackData getOriginateCallbackDataByTraceId(String traceId) * Events are queued until channels and queues are initialized and then * delegated to the dispatchEvent method. */ - public void onManagerEvent(ManagerEvent event) - { + public void onManagerEvent(ManagerEvent event) { // Handle Channel related events - if (event instanceof ConnectEvent) - { + if (event instanceof ConnectEvent) { handleConnectEvent((ConnectEvent) event); - } - else if (event instanceof DisconnectEvent) - { + } else if (event instanceof DisconnectEvent) { handleDisconnectEvent((DisconnectEvent) event); - } - else if (event instanceof NewChannelEvent) - { + } else if (event instanceof NewChannelEvent) { channelManager.handleNewChannelEvent((NewChannelEvent) event); - } - else if (event instanceof NewExtenEvent) - { + } else if (event instanceof NewExtenEvent) { channelManager.handleNewExtenEvent((NewExtenEvent) event); - } - else if (event instanceof NewStateEvent) - { + } else if (event instanceof NewStateEvent) { channelManager.handleNewStateEvent((NewStateEvent) event); - } - else if (event instanceof NewCallerIdEvent) - { + } else if (event instanceof NewCallerIdEvent) { channelManager.handleNewCallerIdEvent((NewCallerIdEvent) event); - } - else if (event instanceof DialEvent) - { + } else if (event instanceof DialEvent) { channelManager.handleDialEvent((DialEvent) event); - } - else if (event instanceof BridgeEvent) - { + } else if (event instanceof BridgeEvent) { channelManager.handleBridgeEvent((BridgeEvent) event); - } - else if (event instanceof RenameEvent) - { + } else if (event instanceof RenameEvent) { channelManager.handleRenameEvent((RenameEvent) event); - } - else if (event instanceof HangupEvent) - { + } else if (event instanceof HangupEvent) { channelManager.handleHangupEvent((HangupEvent) event); - } - else if (event instanceof CdrEvent) - { + } else if (event instanceof CdrEvent) { channelManager.handleCdrEvent((CdrEvent) event); - } - else if (event instanceof VarSetEvent) - { + } else if (event instanceof VarSetEvent) { channelManager.handleVarSetEvent((VarSetEvent) event); - } - else if (event instanceof DtmfEvent) - { + } else if (event instanceof DtmfEvent) { channelManager.handleDtmfEvent((DtmfEvent) event); - } - else if (event instanceof MonitorStartEvent) - { + } else if (event instanceof MonitorStartEvent) { channelManager.handleMonitorStartEvent((MonitorStartEvent) event); - } - else if (event instanceof MonitorStopEvent) - { + } else if (event instanceof MonitorStopEvent) { channelManager.handleMonitorStopEvent((MonitorStopEvent) event); } // End of channel related events // Handle parking related event - else if (event instanceof ParkedCallEvent) - { + else if (event instanceof ParkedCallEvent) { channelManager.handleParkedCallEvent((ParkedCallEvent) event); - } - else if (event instanceof ParkedCallGiveUpEvent) - { + } else if (event instanceof ParkedCallGiveUpEvent) { channelManager.handleParkedCallGiveUpEvent((ParkedCallGiveUpEvent) event); - } - else if (event instanceof ParkedCallTimeOutEvent) - { + } else if (event instanceof ParkedCallTimeOutEvent) { channelManager.handleParkedCallTimeOutEvent((ParkedCallTimeOutEvent) event); - } - else if (event instanceof UnparkedCallEvent) - { + } else if (event instanceof UnparkedCallEvent) { channelManager.handleUnparkedCallEvent((UnparkedCallEvent) event); } // End of parking related events // Handle queue related event - else if (event instanceof JoinEvent) - { + else if (event instanceof JoinEvent) { queueManager.handleJoinEvent((JoinEvent) event); - } - else if (event instanceof LeaveEvent) - { + } else if (event instanceof LeaveEvent) { queueManager.handleLeaveEvent((LeaveEvent) event); - } - else if (event instanceof QueueMemberStatusEvent) - { + } else if (event instanceof QueueMemberStatusEvent) { queueManager.handleQueueMemberStatusEvent((QueueMemberStatusEvent) event); - } - else if (event instanceof QueueMemberPenaltyEvent) - { + } else if (event instanceof QueueMemberPenaltyEvent) { queueManager.handleQueueMemberPenaltyEvent((QueueMemberPenaltyEvent) event); - } - else if (event instanceof QueueMemberAddedEvent) - { + } else if (event instanceof QueueMemberAddedEvent) { queueManager.handleQueueMemberAddedEvent((QueueMemberAddedEvent) event); - } - else if (event instanceof QueueMemberRemovedEvent) - { + } else if (event instanceof QueueMemberRemovedEvent) { queueManager.handleQueueMemberRemovedEvent((QueueMemberRemovedEvent) event); - } - else if (event instanceof QueueMemberPausedEvent) - { + } else if (event instanceof QueueMemberPausedEvent) { queueManager.handleQueueMemberPausedEvent((QueueMemberPausedEvent) event); - } - else if (event instanceof QueueCallerJoinEvent) - { + } else if (event instanceof QueueCallerJoinEvent) { queueManager.handleJoinEvent((QueueCallerJoinEvent) event); - } - else if (event instanceof QueueCallerLeaveEvent) - { + } else if (event instanceof QueueCallerLeaveEvent) { queueManager.handleLeaveEvent((QueueCallerLeaveEvent) event); } // >>>>>> AJ 94 // Handle meetMeEvents - else if (event instanceof AbstractMeetMeEvent) - { + else if (event instanceof AbstractMeetMeEvent) { meetMeManager.handleMeetMeEvent((AbstractMeetMeEvent) event); - } - else if (event instanceof OriginateResponseEvent) - { + } else if (event instanceof OriginateResponseEvent) { handleOriginateEvent((OriginateResponseEvent) event); } // Handle agents-related events - else if (event instanceof AgentsEvent) - { + else if (event instanceof AgentsEvent) { agentManager.handleAgentsEvent((AgentsEvent) event); - } - else if (event instanceof AgentCalledEvent) - { + } else if (event instanceof AgentCalledEvent) { agentManager.handleAgentCalledEvent((AgentCalledEvent) event); - } - else if (event instanceof AgentConnectEvent) - { + } else if (event instanceof AgentConnectEvent) { agentManager.handleAgentConnectEvent((AgentConnectEvent) event); - } - else if (event instanceof AgentCompleteEvent) - { + } else if (event instanceof AgentCompleteEvent) { agentManager.handleAgentCompleteEvent((AgentCompleteEvent) event); - } - else if (event instanceof AgentCallbackLoginEvent) - { + } else if (event instanceof AgentCallbackLoginEvent) { agentManager.handleAgentCallbackLoginEvent((AgentCallbackLoginEvent) event); - } - else if (event instanceof AgentCallbackLogoffEvent) - { + } else if (event instanceof AgentCallbackLogoffEvent) { agentManager.handleAgentCallbackLogoffEvent((AgentCallbackLogoffEvent) event); - } - else if (event instanceof AgentLoginEvent) - { + } else if (event instanceof AgentLoginEvent) { agentManager.handleAgentLoginEvent((AgentLoginEvent) event); - } - else if (event instanceof AgentLogoffEvent) - { + } else if (event instanceof AgentLogoffEvent) { agentManager.handleAgentLogoffEvent((AgentLogoffEvent) event); } // End of agent-related events @@ -1214,10 +904,8 @@ else if (event instanceof AgentLogoffEvent) * * @param event */ - private void fireChainListeners(ManagerEvent event) - { - try (LockCloser closer = this.chainListeners.withLock()) - { + private void fireChainListeners(ManagerEvent event) { + try (LockCloser closer = this.chainListeners.withLock()) { for (ManagerEventListener listener : this.chainListeners) listener.onManagerEvent(event); } @@ -1228,8 +916,7 @@ private void fireChainListeners(ManagerEvent event) * lost. */ - private void handleDisconnectEvent(DisconnectEvent disconnectEvent) - { + private void handleDisconnectEvent(DisconnectEvent disconnectEvent) { // reset version information as it might have changed while Asterisk // restarted version = null; @@ -1250,69 +937,55 @@ private void handleDisconnectEvent(DisconnectEvent disconnectEvent) * to the asterisk server is restored. */ - private void handleConnectEvent(ConnectEvent connectEvent) - { - try - { + private void handleConnectEvent(ConnectEvent connectEvent) { + try { initialize(); channelManager.initialize(); agentManager.initialize(); meetMeManager.initialize(); - if (!skipQueues) - { + if (!skipQueues) { queueManager.initialize(); } logger.info("Initializing done"); initialized = true; initializing = false; - } - catch (Exception e) - { + } catch (Exception e) { logger.error("Unable to reinitialize state after reconnection", e); } } - private void handleOriginateEvent(OriginateResponseEvent originateEvent) - { + private void handleOriginateEvent(OriginateResponseEvent originateEvent) { final String traceId; final OriginateCallbackData callbackData; final OriginateCallback cb; final AsteriskChannelImpl channel; final AsteriskChannelImpl otherChannel; // the other side if local - // channel + // channel traceId = originateEvent.getActionId(); - if (traceId == null) - { + if (traceId == null) { return; } - try (LockCloser closer = originateCallbacks.withLock()) - { + try (LockCloser closer = originateCallbacks.withLock()) { callbackData = originateCallbacks.get(traceId); - if (callbackData == null) - { + if (callbackData == null) { return; } originateCallbacks.remove(traceId); } cb = callbackData.getCallback(); - if (!AstUtil.isNull(originateEvent.getUniqueId())) - { + if (!AstUtil.isNull(originateEvent.getUniqueId())) { channel = channelManager.getChannelImplById(originateEvent.getUniqueId()); - } - else - { + } else { channel = callbackData.getChannel(); } - try - { - if (channel == null) - { + try { + if (channel == null) { final LiveException cause; cause = new NoSuchChannelException( @@ -1321,14 +994,12 @@ private void handleOriginateEvent(OriginateResponseEvent originateEvent) return; } - if (channel.wasInState(ChannelState.UP)) - { + if (channel.wasInState(ChannelState.UP)) { cb.onSuccess(channel); return; } - if (channel.wasBusy()) - { + if (channel.wasBusy()) { cb.onBusy(channel); return; } @@ -1337,16 +1008,14 @@ private void handleOriginateEvent(OriginateResponseEvent originateEvent) // special treatment of local channels: // the interesting things happen to the other side so we have a look // at that - if (otherChannel != null) - { + if (otherChannel != null) { final AsteriskChannel dialedChannel; dialedChannel = otherChannel.getDialedChannel(); // on busy the other channel is in state busy when we receive // the originate event - if (otherChannel.wasBusy()) - { + if (otherChannel.wasBusy()) { cb.onBusy(channel); return; } @@ -1358,8 +1027,7 @@ private void handleOriginateEvent(OriginateResponseEvent originateEvent) // this alternative has the drawback that there might by // multiple channels that have been dialed by the local channel // but we only look at the last one. - if (dialedChannel != null && dialedChannel.wasBusy()) - { + if (dialedChannel != null && dialedChannel.wasBusy()) { cb.onBusy(channel); return; } @@ -1367,132 +1035,100 @@ private void handleOriginateEvent(OriginateResponseEvent originateEvent) // if nothing else matched we asume no answer cb.onNoAnswer(channel); - } - catch (Throwable t) - { + } catch (Throwable t) { logger.warn("Exception dispatching originate progress", t); } } @Override - public void shutdown() - { + public void shutdown() { if (eventConnection != null && (eventConnection.getState() == ManagerConnectionState.CONNECTED - || eventConnection.getState() == ManagerConnectionState.RECONNECTING)) - { - try - { + || eventConnection.getState() == ManagerConnectionState.RECONNECTING)) { + try { eventConnection.logoff(); - } - catch (Exception ignore) - { + } catch (Exception ignore) { } } - if (managerEventListenerProxy != null) - { - if (eventConnection != null) - { + if (managerEventListenerProxy != null) { + if (eventConnection != null) { eventConnection.removeEventListener(managerEventListenerProxy); } managerEventListenerProxy.shutdown(); } - if (eventConnection != null && eventListener != null) - { + if (eventConnection != null && eventListener != null) { eventConnection.removeEventListener(eventListener); } managerEventListenerProxy = null; eventListener = null; - if (initialized) - {// incredible, but it happened + if (initialized) {// incredible, but it happened handleDisconnectEvent(null); } // i }// shutdown - public List getPeerEntries() throws ManagerCommunicationException - { + public List getPeerEntries() throws ManagerCommunicationException { ResponseEvents responseEvents = sendEventGeneratingAction(new SipPeersAction(), 2000); List peerEntries = new ArrayList<>(30); - for (ResponseEvent re : responseEvents.getEvents()) - { - if (re instanceof PeerEntryEvent) - { + for (ResponseEvent re : responseEvents.getEvents()) { + if (re instanceof PeerEntryEvent) { peerEntries.add((PeerEntryEvent) re); } } return peerEntries; } - public DbGetResponseEvent dbGet(String family, String key) throws ManagerCommunicationException - { + public DbGetResponseEvent dbGet(String family, String key) throws ManagerCommunicationException { ResponseEvents responseEvents = sendEventGeneratingAction(new DbGetAction(family, key), 2000); DbGetResponseEvent dbgre = null; - for (ResponseEvent re : responseEvents.getEvents()) - { + for (ResponseEvent re : responseEvents.getEvents()) { dbgre = (DbGetResponseEvent) re; } return dbgre; } - public void dbDel(String family, String key) throws ManagerCommunicationException - { + public void dbDel(String family, String key) throws ManagerCommunicationException { // The following only works with BRIStuffed asrterisk: sendAction(new // DbDelAction(family,key)); // Use cli command instead ... sendAction(new CommandAction("database del " + family + " " + key)); } - public void dbPut(String family, String key, String value) throws ManagerCommunicationException - { + public void dbPut(String family, String key, String value) throws ManagerCommunicationException { sendAction(new DbPutAction(family, key, value)); } - public AsteriskChannel getChannelByNameAndActive(String name) throws ManagerCommunicationException - { + public AsteriskChannel getChannelByNameAndActive(String name) throws ManagerCommunicationException { initializeIfNeeded(); return channelManager.getChannelImplByNameAndActive(name); } - public Collection getAgents() throws ManagerCommunicationException - { + public Collection getAgents() throws ManagerCommunicationException { initializeIfNeeded(); return agentManager.getAgents(); } - void fireNewAgent(AsteriskAgentImpl agent) - { - try (LockCloser closer = listeners.withLock()) - { - for (AsteriskServerListener listener : listeners) - { - try - { + void fireNewAgent(AsteriskAgentImpl agent) { + try (LockCloser closer = listeners.withLock()) { + for (AsteriskServerListener listener : listeners) { + try { listener.onNewAgent(agent); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Exception in onNewAgent()", e); } } } } - void fireNewQueueEntry(AsteriskQueueEntry entry) - { - try (LockCloser closer = listeners.withLock()) - { - for (AsteriskServerListener listener : listeners) - { - try - { + void fireNewQueueEntry(AsteriskQueueEntry entry) { + try (LockCloser closer = listeners.withLock()) { + for (AsteriskServerListener listener : listeners) { + try { listener.onNewQueueEntry(entry); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Exception in onNewQueueEntry()", e); } } @@ -1501,14 +1137,12 @@ void fireNewQueueEntry(AsteriskQueueEntry entry) /* OCTAVIO LUNA */ @Override - public void forceQueuesMonitor(boolean force) - { + public void forceQueuesMonitor(boolean force) { queueManager.forceQueuesMonitor(force); } @Override - public boolean isQueuesMonitorForced() - { + public boolean isQueuesMonitorForced() { return queueManager.isQueuesMonitorForced(); } } diff --git a/src/main/java/org/asteriskjava/live/internal/CallDetailRecordImpl.java b/src/main/java/org/asteriskjava/live/internal/CallDetailRecordImpl.java index cc93521ba..141d0429f 100644 --- a/src/main/java/org/asteriskjava/live/internal/CallDetailRecordImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/CallDetailRecordImpl.java @@ -16,22 +16,21 @@ */ package org.asteriskjava.live.internal; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.TimeZone; - import org.asteriskjava.live.AmaFlags; import org.asteriskjava.live.AsteriskChannel; import org.asteriskjava.live.CallDetailRecord; import org.asteriskjava.live.Disposition; import org.asteriskjava.manager.event.CdrEvent; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.TimeZone; + /** * Default implementation of the CallDetailRecord interface. */ -public class CallDetailRecordImpl implements CallDetailRecord -{ +public class CallDetailRecordImpl implements CallDetailRecord { private static final Map DISPOSITION_MAP; private static final Map AMA_FLAGS_MAP; private final AsteriskChannelImpl channel; @@ -51,8 +50,7 @@ public class CallDetailRecordImpl implements CallDetailRecord private final AmaFlags amaFlags; private final String userField; - static - { + static { DISPOSITION_MAP = new HashMap<>(); DISPOSITION_MAP.put(CdrEvent.DISPOSITION_ANSWERED, Disposition.ANSWERED); DISPOSITION_MAP.put(CdrEvent.DISPOSITION_BUSY, Disposition.BUSY); @@ -67,8 +65,7 @@ public class CallDetailRecordImpl implements CallDetailRecord AMA_FLAGS_MAP.put(CdrEvent.AMA_FLAG_UNKNOWN, AmaFlags.UNKNOWN); } - CallDetailRecordImpl(AsteriskChannelImpl channel, AsteriskChannelImpl destinationChannel, CdrEvent cdrEvent) - { + CallDetailRecordImpl(AsteriskChannelImpl channel, AsteriskChannelImpl destinationChannel, CdrEvent cdrEvent) { //TODO add timezone to AsteriskServer TimeZone tz = TimeZone.getDefault(); this.channel = channel; @@ -84,97 +81,76 @@ public class CallDetailRecordImpl implements CallDetailRecord endDate = cdrEvent.getEndTimeAsDate(tz); duration = cdrEvent.getDuration(); billableSeconds = cdrEvent.getBillableSeconds(); - if (cdrEvent.getAmaFlags() != null) - { + if (cdrEvent.getAmaFlags() != null) { amaFlags = AMA_FLAGS_MAP.get(cdrEvent.getAmaFlags()); - } - else - { + } else { amaFlags = null; } - if (cdrEvent.getDisposition() != null) - { + if (cdrEvent.getDisposition() != null) { disposition = DISPOSITION_MAP.get(cdrEvent.getDisposition()); - } - else - { + } else { disposition = null; } userField = cdrEvent.getUserField(); } - public AsteriskChannel getChannel() - { + public AsteriskChannel getChannel() { return channel; } - public AsteriskChannel getDestinationChannel() - { + public AsteriskChannel getDestinationChannel() { return destinationChannel; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public AmaFlags getAmaFlags() - { + public AmaFlags getAmaFlags() { return amaFlags; } - public Date getAnswerDate() - { + public Date getAnswerDate() { return answerDate; } - public Integer getBillableSeconds() - { + public Integer getBillableSeconds() { return billableSeconds; } - public String getDestinationContext() - { + public String getDestinationContext() { return destinationContext; } - public String getDestinationExtension() - { + public String getDestinationExtension() { return destinationExtension; } - public Disposition getDisposition() - { + public Disposition getDisposition() { return disposition; } - public Integer getDuration() - { + public Integer getDuration() { return duration; } - public Date getEndDate() - { + public Date getEndDate() { return endDate; } - public String getLastApplication() - { + public String getLastApplication() { return lastApplication; } - public String getLastAppData() - { + public String getLastAppData() { return lastAppData; } - public Date getStartDate() - { + public Date getStartDate() { return startDate; } - public String getUserField() - { + public String getUserField() { return userField; } } diff --git a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java index d1f8c121c..a7bf7e2f3 100644 --- a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java +++ b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java @@ -16,62 +16,29 @@ */ package org.asteriskjava.live.internal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import org.asteriskjava.live.AsteriskChannel; -import org.asteriskjava.live.CallerId; -import org.asteriskjava.live.ChannelState; -import org.asteriskjava.live.Extension; -import org.asteriskjava.live.HangupCause; -import org.asteriskjava.live.ManagerCommunicationException; -import org.asteriskjava.live.NoSuchChannelException; +import org.asteriskjava.live.*; import org.asteriskjava.lock.LockableMap; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.action.StatusAction; -import org.asteriskjava.manager.event.AbstractChannelEvent; -import org.asteriskjava.manager.event.BridgeEvent; -import org.asteriskjava.manager.event.CdrEvent; -import org.asteriskjava.manager.event.DialEvent; -import org.asteriskjava.manager.event.DtmfEvent; -import org.asteriskjava.manager.event.HangupEvent; -import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.MonitorStartEvent; -import org.asteriskjava.manager.event.MonitorStopEvent; -import org.asteriskjava.manager.event.NewCallerIdEvent; -import org.asteriskjava.manager.event.NewChannelEvent; -import org.asteriskjava.manager.event.NewExtenEvent; -import org.asteriskjava.manager.event.NewStateEvent; -import org.asteriskjava.manager.event.ParkedCallEvent; -import org.asteriskjava.manager.event.ParkedCallGiveUpEvent; -import org.asteriskjava.manager.event.ParkedCallTimeOutEvent; -import org.asteriskjava.manager.event.RenameEvent; -import org.asteriskjava.manager.event.StatusEvent; -import org.asteriskjava.manager.event.UnparkedCallEvent; -import org.asteriskjava.manager.event.VarSetEvent; +import org.asteriskjava.manager.event.*; import org.asteriskjava.util.DaemonThreadFactory; import org.asteriskjava.util.DateUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + /** * Manages channel events on behalf of an AsteriskServer. * * @author srt * @version $Id$ */ -class ChannelManager -{ +class ChannelManager { private final Log logger = LogFactory.getLog(getClass()); /** @@ -95,18 +62,15 @@ class ChannelManager * * @param server the server this channel manager belongs to. */ - ChannelManager(AsteriskServerImpl server) - { + ChannelManager(AsteriskServerImpl server) { this.server = server; } - void initialize() throws ManagerCommunicationException - { + void initialize() throws ManagerCommunicationException { initialize(null); } - void initialize(List variables) throws ManagerCommunicationException - { + void initialize(List variables) throws ManagerCommunicationException { ResponseEvents re; shutdown(); @@ -116,10 +80,8 @@ void initialize(List variables) throws ManagerCommunicationException StatusAction sa = new StatusAction(); sa.setVariables(variables); re = server.sendEventGeneratingAction(sa); - for (ManagerEvent event : re.getEvents()) - { - if (event instanceof StatusEvent) - { + for (ManagerEvent event : re.getEvents()) { + if (event instanceof StatusEvent) { handleStatusEvent((StatusEvent) event); } } @@ -127,20 +89,16 @@ void initialize(List variables) throws ManagerCommunicationException } - void disconnected() - { + void disconnected() { shutdown(); logger.debug("ChannelManager has been disconnected from Asterisk."); } - private void shutdown() - { - if (traceScheduledExecutorService != null) - { + private void shutdown() { + if (traceScheduledExecutorService != null) { traceScheduledExecutorService.shutdown(); } - try (LockCloser closer = channels.withLock()) - { + try (LockCloser closer = channels.withLock()) { channels.clear(); } @@ -151,17 +109,13 @@ private void shutdown() * * @return a collection of all active AsteriskChannels. */ - Collection getChannels() - { + Collection getChannels() { Collection copy; - try (LockCloser closer = channels.withLock()) - { + try (LockCloser closer = channels.withLock()) { copy = new ArrayList<>(channels.size() + 2); - for (AsteriskChannel channel : channels.values()) - { - if (channel.getState() != ChannelState.HUNGUP) - { + for (AsteriskChannel channel : channels.values()) { + if (channel.getState() != ChannelState.HUNGUP) { copy.add(channel); } } @@ -169,10 +123,8 @@ Collection getChannels() return copy; } - private void addChannel(AsteriskChannelImpl channel) - { - try (LockCloser closer = channels.withLock()) - { + private void addChannel(AsteriskChannelImpl channel) { + try (LockCloser closer = channels.withLock()) { channels.put(channel.getId(), channel); } } @@ -181,22 +133,17 @@ private void addChannel(AsteriskChannelImpl channel) * Removes channels that have been hung more than {@link #REMOVAL_THRESHOLD} * milliseconds. */ - private void removeOldChannels() - { + private void removeOldChannels() { Iterator i; - try (LockCloser closer = channels.withLock()) - { + try (LockCloser closer = channels.withLock()) { i = channels.values().iterator(); - while (i.hasNext()) - { + while (i.hasNext()) { final AsteriskChannel channel = i.next(); final Date dateOfRemoval = channel.getDateOfRemoval(); - if (channel.getState() == ChannelState.HUNGUP && dateOfRemoval != null) - { + if (channel.getState() == ChannelState.HUNGUP && dateOfRemoval != null) { final long diff = DateUtil.getDate().getTime() - dateOfRemoval.getTime(); - if (diff >= REMOVAL_THRESHOLD) - { + if (diff >= REMOVAL_THRESHOLD) { i.remove(); } } @@ -205,32 +152,23 @@ private void removeOldChannels() } private AsteriskChannelImpl addNewChannel(String uniqueId, final String name, Date dateOfCreation, String callerIdNumber, - String callerIdName, ChannelState state, String account) - { + String callerIdName, ChannelState state, String account) { final AsteriskChannelImpl channel = new AsteriskChannelImpl(server, name, uniqueId, dateOfCreation); channel.setCallerId(new CallerId(callerIdName, callerIdNumber)); channel.setAccount(account); channel.stateChanged(dateOfCreation, state); logger.info("Adding channel " + channel.getName() + "(" + channel.getId() + ")"); - if (SLEEP_TIME_BEFORE_GET_VAR > 0) - { + if (SLEEP_TIME_BEFORE_GET_VAR > 0) { long start = System.currentTimeMillis(); long end = start + SLEEP_TIME_BEFORE_GET_VAR; - while (System.currentTimeMillis() < end) - { - try - { + while (System.currentTimeMillis() < end) { + try { channel.getVariable(Constants.VARIABLE_TRACE_ID); - } - catch (NoSuchChannelException | ManagerCommunicationException e) - { - try - { + } catch (NoSuchChannelException | ManagerCommunicationException e) { + try { Thread.sleep(1L); - } - catch (InterruptedException intEx) - { + } catch (InterruptedException intEx) { Thread.currentThread().interrupt(); } } @@ -243,28 +181,21 @@ private AsteriskChannelImpl addNewChannel(String uniqueId, final String name, Da addChannel(channel); // todo getChannelImplById -> LinkedHashMap, callbacks order - traceScheduledExecutorService.schedule(new Runnable() - { + traceScheduledExecutorService.schedule(new Runnable() { @Override - public void run() - { + public void run() { final String traceId = getTraceId(channel); channel.setTraceId(traceId); if (traceId != null && (!name.toLowerCase(Locale.ENGLISH).startsWith("local/") || name.endsWith(",1") - || name.endsWith(";1"))) - { + || name.endsWith(";1"))) { final OriginateCallbackData callbackData = server.getOriginateCallbackDataByTraceId(traceId); - if (callbackData != null && callbackData.getChannel() == null) - { + if (callbackData != null && callbackData.getChannel() == null) { callbackData.setChannel(channel); - try - { + try { callbackData.getCallback().onDialing(channel); - } - catch (Throwable t) - { + } catch (Throwable t) { logger.warn("Exception dispatching originate progress. " + channel, t); } // t } // i @@ -276,73 +207,57 @@ public void run() return channel; }// addNewChannel - void handleStatusEvent(StatusEvent event) - { + void handleStatusEvent(StatusEvent event) { AsteriskChannelImpl channel; final Extension extension; boolean isNew = false; Map variables = event.getVariables(); channel = getChannelImplById(event.getUniqueId()); - if (channel == null) - { + if (channel == null) { Date dateOfCreation; - if (event.getSeconds() != null) - { + if (event.getSeconds() != null) { dateOfCreation = new Date(DateUtil.getDate().getTime() - (event.getSeconds() * 1000L)); - } - else - { + } else { dateOfCreation = DateUtil.getDate(); } channel = new AsteriskChannelImpl(server, event.getChannel(), event.getUniqueId(), dateOfCreation); isNew = true; - if (variables != null) - { - for (Entry variable : variables.entrySet()) - { + if (variables != null) { + for (Entry variable : variables.entrySet()) { channel.updateVariable(variable.getKey(), variable.getValue()); } } } - if (event.getContext() == null && event.getExtension() == null && event.getPriority() == null) - { + if (event.getContext() == null && event.getExtension() == null && event.getPriority() == null) { extension = null; - } - else - { + } else { extension = new Extension(event.getContext(), event.getExtension(), event.getPriority()); } - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.setCallerId(new CallerId(event.getCallerIdName(), event.getCallerIdNum())); channel.setAccount(event.getAccountCode()); - if (event.getChannelState() != null) - { + if (event.getChannelState() != null) { channel.stateChanged(event.getDateReceived(), ChannelState.valueOf(event.getChannelState())); } channel.extensionVisited(event.getDateReceived(), extension); - if (event.getBridgedChannel() != null) - { + if (event.getBridgedChannel() != null) { final AsteriskChannelImpl linkedChannel = getChannelImplByName(event.getBridgedChannel()); - if (linkedChannel != null) - { + if (linkedChannel != null) { // the date used here is not correct! channel.channelLinked(event.getDateReceived(), linkedChannel); - try (LockCloser closer2 = linkedChannel.withLock()) - { + try (LockCloser closer2 = linkedChannel.withLock()) { linkedChannel.channelLinked(event.getDateReceived(), channel); } } } } - if (isNew) - { + if (isNew) { logger.info("Adding new channel " + channel.getName()); addChannel(channel); server.fireNewAsteriskChannel(channel); @@ -356,29 +271,23 @@ void handleStatusEvent(StatusEvent event) * * @param name the name of the requested channel. * @return the (most recent) channel if found, in any state, or null if none - * found. + * found. */ - AsteriskChannelImpl getChannelImplByName(String name) - { + AsteriskChannelImpl getChannelImplByName(String name) { Date dateOfCreation = null; AsteriskChannelImpl channel = null; - if (name == null) - { + if (name == null) { return null; } - try (LockCloser closer = channels.withLock()) - { - for (AsteriskChannelImpl tmp : channels.values()) - { - if (name.equals(tmp.getName())) - { + try (LockCloser closer = channels.withLock()) { + for (AsteriskChannelImpl tmp : channels.values()) { + if (name.equals(tmp.getName())) { // return the most recent channel or when dates are similar, // the active one if (dateOfCreation == null || tmp.getDateOfCreation().after(dateOfCreation) - || (tmp.getDateOfCreation().equals(dateOfCreation) && tmp.getState() != ChannelState.HUNGUP)) - { + || (tmp.getDateOfCreation().equals(dateOfCreation) && tmp.getState() != ChannelState.HUNGUP)) { channel = tmp; dateOfCreation = channel.getDateOfCreation(); } @@ -395,8 +304,7 @@ AsteriskChannelImpl getChannelImplByName(String name) * @param name the name of the requested channel. * @return the NON-HUNGUP channel if found, or null if none is found. */ - AsteriskChannelImpl getChannelImplByNameAndActive(String name) - { + AsteriskChannelImpl getChannelImplByNameAndActive(String name) { // In non bristuffed AST 1.2, we don't have uniqueid header to match the // channel @@ -407,17 +315,13 @@ AsteriskChannelImpl getChannelImplByNameAndActive(String name) AsteriskChannelImpl channel = null; - if (name == null) - { + if (name == null) { return null; } - try (LockCloser closer = channels.withLock()) - { - for (AsteriskChannelImpl tmp : channels.values()) - { - if (name.equals(tmp.getName()) && tmp.getState() != ChannelState.HUNGUP) - { + try (LockCloser closer = channels.withLock()) { + for (AsteriskChannelImpl tmp : channels.values()) { + if (name.equals(tmp.getName()) && tmp.getState() != ChannelState.HUNGUP) { channel = tmp; } } @@ -425,15 +329,12 @@ AsteriskChannelImpl getChannelImplByNameAndActive(String name) return channel; } - AsteriskChannelImpl getChannelImplById(String uniqueId) - { - if (uniqueId == null) - { + AsteriskChannelImpl getChannelImplById(String uniqueId) { + if (uniqueId == null) { return null; } - try (LockCloser closer = channels.withLock()) - { + try (LockCloser closer = channels.withLock()) { return channels.get(uniqueId); } }// getChannelImplById @@ -447,62 +348,46 @@ AsteriskChannelImpl getChannelImplById(String uniqueId) * * @param localChannel one side * @return the other side, or null if not available or if the - * given channel is not a local channel. + * given channel is not a local channel. */ - AsteriskChannelImpl getOtherSideOfLocalChannel(AsteriskChannel localChannel) - { + AsteriskChannelImpl getOtherSideOfLocalChannel(AsteriskChannel localChannel) { final String name; final char num; - if (localChannel == null) - { + if (localChannel == null) { return null; } name = localChannel.getName(); if (name == null || !name.startsWith("Local/") - || (name.charAt(name.length() - 2) != ',' && name.charAt(name.length() - 2) != ';')) - { + || (name.charAt(name.length() - 2) != ',' && name.charAt(name.length() - 2) != ';')) { return null; } num = name.charAt(name.length() - 1); - if (num == '1') - { + if (num == '1') { return getChannelImplByName(name.substring(0, name.length() - 1) + "2"); - } - else if (num == '2') - { + } else if (num == '2') { return getChannelImplByName(name.substring(0, name.length() - 1) + "1"); - } - else - { + } else { return null; } } - void handleNewChannelEvent(NewChannelEvent event) - { + void handleNewChannelEvent(NewChannelEvent event) { final AsteriskChannelImpl channel = getChannelImplById(event.getUniqueId()); - if (channel == null) - { - if (event.getChannel() == null) - { + if (channel == null) { + if (event.getChannel() == null) { logger.info("Ignored NewChannelEvent with empty channel name (uniqueId=" + event.getUniqueId() + ")"); - } - else - { + } else { addNewChannel(event.getUniqueId(), event.getChannel(), event.getDateReceived(), event.getCallerIdNum(), event.getCallerIdName(), ChannelState.valueOf(event.getChannelState()), event.getAccountCode()); } - } - else - { + } else { // channel had already been created probably by a NewCallerIdEvent - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.nameChanged(event.getDateReceived(), event.getChannel()); channel.setCallerId(new CallerId(event.getCallerIdName(), event.getCallerIdNum())); channel.stateChanged(event.getDateReceived(), ChannelState.valueOf(event.getChannelState())); @@ -510,14 +395,12 @@ void handleNewChannelEvent(NewChannelEvent event) } } - void handleNewExtenEvent(NewExtenEvent event) - { + void handleNewExtenEvent(NewExtenEvent event) { AsteriskChannelImpl channel; final Extension extension; channel = getChannelImplById(event.getUniqueId()); - if (channel == null) - { + if (channel == null) { logger.warn("handleNewExtenEvent: Ignored NewExtenEvent for unknown channel " + event.getChannel()); return; } @@ -525,27 +408,22 @@ void handleNewExtenEvent(NewExtenEvent event) extension = new Extension(event.getContext(), event.getExtension(), event.getPriority(), event.getApplication(), event.getAppData()); - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.extensionVisited(event.getDateReceived(), extension); } } - private void idChanged(AsteriskChannelImpl channel, AbstractChannelEvent event) - { - if (channel != null) - { + private void idChanged(AsteriskChannelImpl channel, AbstractChannelEvent event) { + if (channel != null) { final String oldId = channel.getId(); final String newId = event.getUniqueId(); - if (oldId != null && oldId.equals(newId)) - { + if (oldId != null && oldId.equals(newId)) { return; } logger.info("Changing unique_id for '" + channel.getName() + "' from " + oldId + " to " + newId + " < " + event); - try (LockCloser closer = channels.withLock()) - { + try (LockCloser closer = channels.withLock()) { channels.remove(oldId); channels.put(newId, channel); channel.idChanged(event.getDateReceived(), newId); @@ -553,19 +431,16 @@ private void idChanged(AsteriskChannelImpl channel, AbstractChannelEvent event) } }// idChanged - void handleNewStateEvent(NewStateEvent event) - { + void handleNewStateEvent(NewStateEvent event) { AsteriskChannelImpl channel = getChannelImplById(event.getUniqueId()); - if (channel == null) - { + if (channel == null) { // NewStateEvent can occur for an existing channel that now has a // different unique id (originate with Local/) channel = getChannelImplByNameAndActive(event.getChannel()); idChanged(channel, event); - if (channel == null) - { + if (channel == null) { logger.info("Creating new channel due to NewStateEvent '" + event.getChannel() + "' unique id " + event.getUniqueId()); // NewStateEvent can occur instead of a NewChannelEvent @@ -579,25 +454,21 @@ void handleNewStateEvent(NewStateEvent event) // previously received through a // NewCallerIdEvent. This happens at least on outgoing legs from the // queue application to agents. - if (event.getCallerIdNum() != null || event.getCallerIdName() != null) - { + if (event.getCallerIdNum() != null || event.getCallerIdName() != null) { String cidnum = ""; String cidname = ""; CallerId currentCallerId = channel.getCallerId(); - if (currentCallerId != null) - { + if (currentCallerId != null) { cidnum = currentCallerId.getNumber(); cidname = currentCallerId.getName(); } - if (event.getCallerIdNum() != null) - { + if (event.getCallerIdNum() != null) { cidnum = event.getCallerIdNum(); } - if (event.getCallerIdName() != null) - { + if (event.getCallerIdName() != null) { cidname = event.getCallerIdName(); } @@ -609,39 +480,32 @@ void handleNewStateEvent(NewStateEvent event) // channel uniqueid, indicating the channel has been // renamed but no related RenameEvent has been received. // This happens with mISDN channels (see AJ-153) - if (event.getChannel() != null && !event.getChannel().equals(channel.getName())) - { + if (event.getChannel() != null && !event.getChannel().equals(channel.getName())) { logger.info("Renaming channel (following NewStateEvent) '" + channel.getName() + "' to '" + event.getChannel() + "'"); - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.nameChanged(event.getDateReceived(), event.getChannel()); } } } - if (event.getChannelState() != null) - { - try (LockCloser closer = channel.withLock()) - { + if (event.getChannelState() != null) { + try (LockCloser closer = channel.withLock()) { channel.stateChanged(event.getDateReceived(), ChannelState.valueOf(event.getChannelState())); } } } - void handleNewCallerIdEvent(NewCallerIdEvent event) - { + void handleNewCallerIdEvent(NewCallerIdEvent event) { AsteriskChannelImpl channel = getChannelImplById(event.getUniqueId()); - if (channel == null) - { + if (channel == null) { // NewCallerIdEvent can occur for an existing channel that now has a // different unique id (originate with Local/) channel = getChannelImplByNameAndActive(event.getChannel()); idChanged(channel, event); - if (channel == null) - { + if (channel == null) { // NewCallerIdEvent can occur before NewChannelEvent channel = addNewChannel(event.getUniqueId(), event.getChannel(), event.getDateReceived(), event.getCallerIdNum(), event.getCallerIdName(), ChannelState.DOWN, @@ -649,30 +513,25 @@ void handleNewCallerIdEvent(NewCallerIdEvent event) } } - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.setCallerId(new CallerId(event.getCallerIdName(), event.getCallerIdNum())); } } - void handleHangupEvent(HangupEvent event) - { + void handleHangupEvent(HangupEvent event) { HangupCause cause = null; AsteriskChannelImpl channel = getChannelImplById(event.getUniqueId()); - if (channel == null) - { + if (channel == null) { logger.warn("handleHangupEvent: Ignored HangupEvent for unknown channel " + event.getChannel()); return; } - if (event.getCause() != null) - { + if (event.getCause() != null) { cause = HangupCause.getByCode(event.getCause()); } - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.hungup(event.getDateReceived(), cause, event.getCauseTxt()); } @@ -680,27 +539,21 @@ void handleHangupEvent(HangupEvent event) removeOldChannels(); } - void handleDialEvent(DialEvent event) - { + void handleDialEvent(DialEvent event) { final AsteriskChannelImpl sourceChannel = getChannelImplById(event.getUniqueId()); final AsteriskChannelImpl destinationChannel = getChannelImplById(event.getDestUniqueId()); - if (sourceChannel == null) - { + if (sourceChannel == null) { logger.warn("handleDialEvent: Ignored DialEvent for unknown source channel " + event.getChannel() + " with unique id " + event.getUniqueId()); return; } - if (destinationChannel == null) - { - if (DialEvent.SUBEVENT_END.equalsIgnoreCase(event.getSubEvent())) - { + if (destinationChannel == null) { + if (DialEvent.SUBEVENT_END.equalsIgnoreCase(event.getSubEvent())) { sourceChannel.updateVariable(AsteriskChannel.VAR_AJ_DIAL_STATUS, event.getDialStatus()); logger.info("handleDialEvent: Ignored DialEvent for unknown dst channel " + event.getDestination() + " with unique_id " + event.getDestUniqueId()); - } - else - { + } else { logger.warn("handleDialEvent: Ignored DialEvent for unknown dst channel " + event.getDestination() + " with unique_id " + event.getDestUniqueId()); } @@ -710,109 +563,88 @@ void handleDialEvent(DialEvent event) logger.info(sourceChannel.getName() + " dialed " + destinationChannel.getName()); getTraceId(sourceChannel); getTraceId(destinationChannel); - try (LockCloser closer = sourceChannel.withLock()) - { + try (LockCloser closer = sourceChannel.withLock()) { sourceChannel.channelDialed(event.getDateReceived(), destinationChannel); } - try (LockCloser closer = destinationChannel.withLock()) - { + try (LockCloser closer = destinationChannel.withLock()) { destinationChannel.channelDialing(event.getDateReceived(), sourceChannel); } } - void handleBridgeEvent(BridgeEvent event) - { + void handleBridgeEvent(BridgeEvent event) { final AsteriskChannelImpl channel1 = getChannelImplById(event.getUniqueId1()); final AsteriskChannelImpl channel2 = getChannelImplById(event.getUniqueId2()); - if (channel1 == null) - { + if (channel1 == null) { logger.warn("handleBridgeEvent: Ignored BridgeEvent for unknown channel " + event.getChannel1()); return; } - if (channel2 == null) - { + if (channel2 == null) { logger.warn("handleBridgeEvent: Ignored BridgeEvent for unknown channel " + event.getChannel2()); return; } - if (event.isLink()) - { + if (event.isLink()) { logger.info("Linking channels " + channel1.getName() + " and " + channel2.getName()); - try (LockCloser closer = channel1.withLock()) - { + try (LockCloser closer = channel1.withLock()) { channel1.channelLinked(event.getDateReceived(), channel2); } - try (LockCloser closer = channel2.withLock()) - { + try (LockCloser closer = channel2.withLock()) { channel2.channelLinked(event.getDateReceived(), channel1); } } - if (event.isUnlink()) - { + if (event.isUnlink()) { logger.info("Unlinking channels " + channel1.getName() + " and " + channel2.getName()); - try (LockCloser closer = channel1.withLock()) - { + try (LockCloser closer = channel1.withLock()) { channel1.channelUnlinked(event.getDateReceived()); } - try (LockCloser closer = channel2.withLock()) - { + try (LockCloser closer = channel2.withLock()) { channel2.channelUnlinked(event.getDateReceived()); } } } - void handleRenameEvent(RenameEvent event) - { + void handleRenameEvent(RenameEvent event) { AsteriskChannelImpl channel = getChannelImplById(event.getUniqueId()); - if (channel == null) - { + if (channel == null) { logger.warn("handleRenameEvent: Ignored RenameEvent for unknown channel with uniqueId " + event.getUniqueId()); return; } logger.info("Renaming channel '" + channel.getName() + "' to '" + event.getNewname() + "', uniqueId is " + event.getUniqueId()); - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.nameChanged(event.getDateReceived(), event.getNewname()); } } - void handleCdrEvent(CdrEvent event) - { + void handleCdrEvent(CdrEvent event) { final AsteriskChannelImpl channel = getChannelImplById(event.getUniqueId()); final AsteriskChannelImpl destinationChannel = getChannelImplByName(event.getDestinationChannel()); final CallDetailRecordImpl cdr; - if (channel == null) - { + if (channel == null) { logger.info("Ignored CdrEvent for unknown channel with uniqueId " + event.getUniqueId()); return; } cdr = new CallDetailRecordImpl(channel, destinationChannel, event); - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.callDetailRecordReceived(event.getDateReceived(), cdr); } } - private String getTraceId(AsteriskChannel channel) - { + private String getTraceId(AsteriskChannel channel) { String traceId; - try - { + try { traceId = channel.getVariable(Constants.VARIABLE_TRACE_ID); - } - catch (Exception e) - { + } catch (Exception e) { traceId = null; } // logger.info("TraceId for channel " + channel.getName() + " is " + @@ -820,21 +652,18 @@ private String getTraceId(AsteriskChannel channel) return traceId; } - void handleParkedCallEvent(ParkedCallEvent event) - { + void handleParkedCallEvent(ParkedCallEvent event) { logger.info("Trace - ChannelManager.java - handleParkedCallEvent: " + event); // Only bristuffed versions: AsteriskChannelImpl channel = // getChannelImplById(event.getUniqueId()); AsteriskChannelImpl channel = getChannelImplByNameAndActive(event.getParkeeChannel()); - if (channel == null) - { + if (channel == null) { logger.info("Ignored ParkedCallEvent for unknown channel " + event.getParkeeChannel()); return; } - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { Extension ext = new Extension(null, (event.getParkingSpace() != null) ? event.getParkingSpace() : event.getExten(), 1); String parkinglot = event.getParkingLot(); @@ -843,195 +672,161 @@ void handleParkedCallEvent(ParkedCallEvent event) } } - void handleParkedCallGiveUpEvent(ParkedCallGiveUpEvent event) - { + void handleParkedCallGiveUpEvent(ParkedCallGiveUpEvent event) { // Only bristuffed versions: AsteriskChannelImpl channel = // getChannelImplById(event.getUniqueId()); AsteriskChannelImpl channel = getChannelImplByNameAndActive(event.getParkeeChannel()); - if (channel == null) - { + if (channel == null) { logger.info("Ignored ParkedCallGiveUpEvent for unknown channel " + event.getParkeeChannel()); return; } Extension wasParkedAt = channel.getParkedAt(); - if (wasParkedAt == null) - { + if (wasParkedAt == null) { logger.info("Ignored ParkedCallGiveUpEvent as the channel was not parked"); return; } - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.setParkedAt(null, null); } logger.info("Channel " + channel.getName() + " is unparked (GiveUp) from " + wasParkedAt.getExtension()); } - void handleParkedCallTimeOutEvent(ParkedCallTimeOutEvent event) - { + void handleParkedCallTimeOutEvent(ParkedCallTimeOutEvent event) { // Only bristuffed versions: AsteriskChannelImpl channel = // getChannelImplById(event.getUniqueId()); final AsteriskChannelImpl channel = getChannelImplByNameAndActive(event.getParkeeChannel()); - if (channel == null) - { + if (channel == null) { logger.info("Ignored ParkedCallTimeOutEvent for unknown channel " + event.getParkeeChannel()); return; } Extension wasParkedAt = channel.getParkedAt(); - if (wasParkedAt == null) - { + if (wasParkedAt == null) { logger.info("Ignored ParkedCallTimeOutEvent as the channel was not parked"); return; } - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.setParkedAt(null, null); } logger.info("Channel " + channel.getName() + " is unparked (Timeout) from " + wasParkedAt.getExtension()); } - void handleUnparkedCallEvent(UnparkedCallEvent event) - { + void handleUnparkedCallEvent(UnparkedCallEvent event) { // Only bristuffed versions: AsteriskChannelImpl channel = // getChannelImplById(event.getUniqueId()); final AsteriskChannelImpl channel = getChannelImplByNameAndActive(event.getParkeeChannel()); - if (channel == null) - { + if (channel == null) { logger.info("Ignored UnparkedCallEvent for unknown channel " + event.getParkeeChannel()); return; } Extension wasParkedAt = channel.getParkedAt(); - if (wasParkedAt == null) - { + if (wasParkedAt == null) { logger.info("Ignored UnparkedCallEvent as the channel was not parked"); return; } - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.setParkedAt(null, null); } logger.info("Channel " + channel.getName() + " is unparked (moved away) from " + wasParkedAt.getExtension()); } - void handleVarSetEvent(VarSetEvent event) - { - if (event.getUniqueId() == null) - { + void handleVarSetEvent(VarSetEvent event) { + if (event.getUniqueId() == null) { return; } final AsteriskChannelImpl channel = getChannelImplById(event.getUniqueId()); - if (channel == null) - { + if (channel == null) { logger.info("Ignored VarSetEvent for unknown channel with uniqueId " + event.getUniqueId()); return; } - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.updateVariable(event.getVariable(), event.getValue()); } } - void handleDtmfEvent(DtmfEvent event) - { + void handleDtmfEvent(DtmfEvent event) { // we are only intrested in END events - if (event.isBegin()) - { + if (event.isBegin()) { return; } - if (event.getUniqueId() == null) - { + if (event.getUniqueId() == null) { return; } final AsteriskChannelImpl channel = getChannelImplById(event.getUniqueId()); - if (channel == null) - { + if (channel == null) { logger.info("Ignored DtmfEvent for unknown channel with uniqueId " + event.getUniqueId()); return; } final Character dtmfDigit; - if (event.getDigit() == null || event.getDigit().length() < 1) - { + if (event.getDigit() == null || event.getDigit().length() < 1) { dtmfDigit = null; - } - else - { + } else { dtmfDigit = event.getDigit().charAt(0); } - try (LockCloser closer = channel.withLock()) - { - if (event.isReceived()) - { + try (LockCloser closer = channel.withLock()) { + if (event.isReceived()) { channel.dtmfReceived(dtmfDigit); } - if (event.isSent()) - { + if (event.isSent()) { channel.dtmfSent(dtmfDigit); } } } - void handleMonitorStartEvent(MonitorStartEvent event) - { + void handleMonitorStartEvent(MonitorStartEvent event) { final AsteriskChannelImpl channel = getChannelImplByNameAndActive(event.getChannel()); - if (channel == null) - { + if (channel == null) { logger.info("Ignored MonitorStartEvent for unknown channel " + event.getChannel()); return; } boolean isMonitored = channel.isMonitored(); - if (isMonitored) - { + if (isMonitored) { logger.info("Ignored MonitorStartEvent as the channel was already monitored"); return; } - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.setMonitored(true); } logger.info("Channel " + channel.getName() + " is monitored"); } - void handleMonitorStopEvent(MonitorStopEvent event) - { + void handleMonitorStopEvent(MonitorStopEvent event) { final AsteriskChannelImpl channel = getChannelImplByNameAndActive(event.getChannel()); - if (channel == null) - { + if (channel == null) { logger.info("Ignored MonitorStopEvent for unknown channel " + event.getChannel()); return; } boolean isMonitored = channel.isMonitored(); - if (!isMonitored) - { + if (!isMonitored) { logger.info("Ignored MonitorStopEvent as the channel was not monitored"); return; } - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { channel.setMonitored(false); } logger.info("Channel " + channel.getName() + " is not monitored"); diff --git a/src/main/java/org/asteriskjava/live/internal/ConfigFileImpl.java b/src/main/java/org/asteriskjava/live/internal/ConfigFileImpl.java index 20239ad82..105bc6f22 100644 --- a/src/main/java/org/asteriskjava/live/internal/ConfigFileImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/ConfigFileImpl.java @@ -16,11 +16,11 @@ */ package org.asteriskjava.live.internal; +import org.asteriskjava.config.ConfigFile; + import java.util.List; import java.util.Map; -import org.asteriskjava.config.ConfigFile; - /** * ConfigFile implementation based on the config actions of the Manager API. * @@ -28,34 +28,28 @@ * @version $Id$ * @since 1.0.0 */ -public class ConfigFileImpl implements ConfigFile -{ +public class ConfigFileImpl implements ConfigFile { private final String filename; private final Map> categories; - public ConfigFileImpl(String filename, Map> categories) - { + public ConfigFileImpl(String filename, Map> categories) { this.filename = filename; this.categories = categories; } - public String getFilename() - { + public String getFilename() { return filename; } - public Map> getCategories() - { + public Map> getCategories() { return categories; } - public String getValue(String category, String key) - { + public String getValue(String category, String key) { throw new UnsupportedOperationException("Not yet inmplemented"); } - public List getValues(String category, String key) - { + public List getValues(String category, String key) { throw new UnsupportedOperationException("Not yet inmplemented"); } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/live/internal/Constants.java b/src/main/java/org/asteriskjava/live/internal/Constants.java index 230c98a64..2ffa3bd45 100644 --- a/src/main/java/org/asteriskjava/live/internal/Constants.java +++ b/src/main/java/org/asteriskjava/live/internal/Constants.java @@ -2,15 +2,13 @@ /** * Defines constants used internally in the live package in multiple classes. - * + * * @author srt * @version $Id$ */ -class Constants -{ +class Constants { // hide constructor - private Constants() - { + private Constants() { } diff --git a/src/main/java/org/asteriskjava/live/internal/ManagerCommunicationExceptionMapper.java b/src/main/java/org/asteriskjava/live/internal/ManagerCommunicationExceptionMapper.java index 61d0cdc49..2ed537a59 100644 --- a/src/main/java/org/asteriskjava/live/internal/ManagerCommunicationExceptionMapper.java +++ b/src/main/java/org/asteriskjava/live/internal/ManagerCommunicationExceptionMapper.java @@ -23,15 +23,13 @@ * Maps exceptions received from * {@link org.asteriskjava.manager.ManagerConnection} to the corresponding * {@link org.asteriskjava.live.ManagerCommunicationException}. - * + * * @author srt * @version $Id$ */ -class ManagerCommunicationExceptionMapper -{ +class ManagerCommunicationExceptionMapper { // hide constructor - private ManagerCommunicationExceptionMapper() - { + private ManagerCommunicationExceptionMapper() { } @@ -40,23 +38,17 @@ private ManagerCommunicationExceptionMapper() * {@link org.asteriskjava.manager.ManagerConnection} when sending a * {@link org.asteriskjava.manager.action.ManagerAction} to the corresponding * {@link org.asteriskjava.live.ManagerCommunicationException}. - * + * * @param actionName name of the action that has been tried to send - * @param exception exception received + * @param exception exception received * @return the corresponding ManagerCommunicationException */ - static ManagerCommunicationException mapSendActionException(String actionName, Exception exception) - { - if (exception instanceof IllegalStateException) - { + static ManagerCommunicationException mapSendActionException(String actionName, Exception exception) { + if (exception instanceof IllegalStateException) { return new ManagerCommunicationException("Not connected to Asterisk Server", exception); - } - else if (exception instanceof EventTimeoutException) - { + } else if (exception instanceof EventTimeoutException) { return new ManagerCommunicationException("Timeout waiting for events from " + actionName + "Action", exception); - } - else - { + } else { return new ManagerCommunicationException("Unable to send " + actionName + "Action", exception); } } diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java b/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java index 8d05e2f12..42f2230cc 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeManager.java @@ -16,13 +16,6 @@ */ package org.asteriskjava.live.internal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.MeetMeRoom; import org.asteriskjava.lock.LockableMap; @@ -39,13 +32,19 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * Manages MeetMe events on behalf of an AsteriskServer. * * @author srt */ -class MeetMeManager -{ +class MeetMeManager { private static final String MEETME_LIST_COMMAND = "meetme list"; private static final Pattern MEETME_LIST_PATTERN = Pattern.compile("^User #: ([0-9]+).*Channel: (\\S+).*$"); @@ -58,42 +57,33 @@ class MeetMeManager */ private final LockableMap rooms; - MeetMeManager(AsteriskServerImpl server, ChannelManager channelManager) - { + MeetMeManager(AsteriskServerImpl server, ChannelManager channelManager) { this.server = server; this.channelManager = channelManager; this.rooms = new LockableMap<>(new HashMap<>()); } - void initialize() - { - try (LockCloser closer = rooms.withLock()) - { - for (MeetMeRoomImpl room : rooms.values()) - { + void initialize() { + try (LockCloser closer = rooms.withLock()) { + for (MeetMeRoomImpl room : rooms.values()) { populateRoom(room); } } } - void disconnected() - { + void disconnected() { /* * try (LockCloser closer = Locker2.lock(rooms) { rooms.clear(); } */ } - Collection getMeetMeRooms() - { + Collection getMeetMeRooms() { final Collection result; result = new ArrayList<>(); - try (LockCloser closer = rooms.withLock()) - { - for (MeetMeRoom room : rooms.values()) - { - if (!room.isEmpty()) - { + try (LockCloser closer = rooms.withLock()) { + for (MeetMeRoom room : rooms.values()) { + if (!room.isEmpty()) { result.add(room); } } @@ -101,8 +91,7 @@ Collection getMeetMeRooms() return result; } - void handleMeetMeEvent(AbstractMeetMeEvent event) - { + void handleMeetMeEvent(AbstractMeetMeEvent event) { String roomNumber; Integer userNumber; AsteriskChannelImpl channel; @@ -110,41 +99,33 @@ void handleMeetMeEvent(AbstractMeetMeEvent event) MeetMeUserImpl user; roomNumber = event.getMeetMe(); - if (roomNumber == null) - { + if (roomNumber == null) { logger.warn("RoomNumber (meetMe property) is null. Ignoring " + event.getClass().getName()); return; } userNumber = event.getUser(); - if (userNumber == null) - { + if (userNumber == null) { logger.warn("UserNumber (userNum property) is null. Ignoring " + event.getClass().getName()); return; } user = getOrCreateUserImpl(event); - if (user == null) - { + if (user == null) { return; } channel = user.getChannel(); room = user.getRoom(); - if (event instanceof MeetMeLeaveEvent) - { + if (event instanceof MeetMeLeaveEvent) { logger.info("Removing channel " + channel.getName() + " from room " + roomNumber); - if (room != user.getRoom()) - { - if (user.getRoom() != null) - { + if (room != user.getRoom()) { + if (user.getRoom() != null) { logger.error("Channel " + channel.getName() + " should be removed from room " + roomNumber + " but is user of room " + user.getRoom().getRoomNumber()); user.getRoom().removeUser(user); - } - else - { + } else { logger.error("Channel " + channel.getName() + " should be removed from room " + roomNumber + " but is user of no room"); } @@ -154,71 +135,56 @@ void handleMeetMeEvent(AbstractMeetMeEvent event) user.left(event.getDateReceived()); room.removeUser(user); channel.setMeetMeUserImpl(null); - } - else if (event instanceof MeetMeTalkingEvent) - { + } else if (event instanceof MeetMeTalkingEvent) { Boolean status; status = ((MeetMeTalkingEvent) event).getStatus(); - if (status != null) - { + if (status != null) { user.setTalking(status); - } - else - { + } else { user.setTalking(true); } - } - else if (event instanceof MeetMeMuteEvent) - { + } else if (event instanceof MeetMeMuteEvent) { Boolean status; status = ((MeetMeMuteEvent) event).getStatus(); - if (status != null) - { + if (status != null) { user.setMuted(status); } } } - private void populateRoom(MeetMeRoomImpl room) - { + private void populateRoom(MeetMeRoomImpl room) { final CommandAction meetMeListAction; final ManagerResponse response; final List lines; final Collection userNumbers = new ArrayList<>(); // list - // of - // user - // numbers - // in - // the - // room + // of + // user + // numbers + // in + // the + // room meetMeListAction = new CommandAction(MEETME_LIST_COMMAND + " " + room.getRoomNumber()); - try - { + try { response = server.sendAction(meetMeListAction); - } - catch (ManagerCommunicationException e) - { + } catch (ManagerCommunicationException e) { logger.error("Unable to send \"" + MEETME_LIST_COMMAND + "\" command", e); return; } - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { logger.error("Unable to send \"" + MEETME_LIST_COMMAND + "\" command: " + response.getMessage()); return; } - if (!(response instanceof CommandResponse)) - { + if (!(response instanceof CommandResponse)) { logger.error("Response to \"" + MEETME_LIST_COMMAND + "\" command is not a CommandResponse but " + response.getClass()); return; } lines = ((CommandResponse) response).getResult(); - for (String line : lines) - { + for (String line : lines) { final Matcher matcher; final Integer userNumber; final AsteriskChannelImpl channel; @@ -228,47 +194,41 @@ private void populateRoom(MeetMeRoomImpl room) MeetMeUserImpl roomUser; matcher = MEETME_LIST_PATTERN.matcher(line); - if (!matcher.matches()) - { + if (!matcher.matches()) { continue; } userNumber = Integer.valueOf(matcher.group(1)); channel = channelManager.getChannelImplByName(matcher.group(2)); if (channel == null) // User has left the room already in the - // meanwhile + // meanwhile { continue; } userNumbers.add(userNumber); - if (line.contains("(Admin Muted)") || line.contains("(Muted)")) - { + if (line.contains("(Admin Muted)") || line.contains("(Muted)")) { muted = true; } - if (line.contains("(talking)")) - { + if (line.contains("(talking)")) { talking = true; } channelUser = channel.getMeetMeUser(); - if (channelUser != null && channelUser.getRoom() != room) - { + if (channelUser != null && channelUser.getRoom() != room) { channelUser.left(DateUtil.getDate()); channelUser = null; } roomUser = room.getUser(userNumber); - if (roomUser != null && roomUser.getChannel() != channel) - { + if (roomUser != null && roomUser.getChannel() != channel) { room.removeUser(roomUser); roomUser = null; } - if (channelUser == null && roomUser == null) - { + if (channelUser == null && roomUser == null) { final MeetMeUserImpl user; // using the current date as dateJoined is not correct but we // don't have anything that is better @@ -278,21 +238,14 @@ private void populateRoom(MeetMeRoomImpl room) room.addUser(user); channel.setMeetMeUserImpl(user); server.fireNewMeetMeUser(user); - } - else if (channelUser != null && roomUser == null) - { + } else if (channelUser != null && roomUser == null) { channelUser.setMuted(muted); room.addUser(channelUser); - } - else if (channelUser == null && roomUser != null) - { + } else if (channelUser == null && roomUser != null) { roomUser.setMuted(muted); channel.setMeetMeUserImpl(roomUser); - } - else - { - if (channelUser != roomUser) - { + } else { + if (channelUser != roomUser) { logger.error("Inconsistent state: channelUser != roomUser, channelUser=" + channelUser + ", roomUser=" + roomUser); } @@ -301,24 +254,20 @@ else if (channelUser == null && roomUser != null) Collection users = room.getUserImpls(); Collection usersToRemove = new ArrayList<>(); - for (MeetMeUserImpl user : users) - { - if (!userNumbers.contains(user.getUserNumber())) - { + for (MeetMeUserImpl user : users) { + if (!userNumbers.contains(user.getUserNumber())) { // remove user as he is no longer in the room usersToRemove.add(user); } } - for (MeetMeUserImpl user : usersToRemove) - { + for (MeetMeUserImpl user : usersToRemove) { user.left(DateUtil.getDate()); room.removeUser(user); user.getChannel().setMeetMeUserImpl(null); } } - private MeetMeUserImpl getOrCreateUserImpl(AbstractMeetMeEvent event) - { + private MeetMeUserImpl getOrCreateUserImpl(AbstractMeetMeEvent event) { final String roomNumber; final MeetMeRoomImpl room; final String uniqueId; @@ -328,33 +277,28 @@ private MeetMeUserImpl getOrCreateUserImpl(AbstractMeetMeEvent event) roomNumber = event.getMeetMe(); room = getOrCreateRoomImpl(roomNumber); user = room.getUser(event.getUser()); - if (user != null) - { + if (user != null) { return user; } // ok create a new one uniqueId = event.getUniqueId(); - if (uniqueId == null) - { + if (uniqueId == null) { logger.warn("UniqueId is null. Ignoring MeetMeEvent"); return null; } channel = channelManager.getChannelImplById(uniqueId); - if (channel == null) - { + if (channel == null) { logger.warn("No channel with unique id " + uniqueId + ". Ignoring MeetMeEvent"); return null; } user = channel.getMeetMeUser(); - if (user != null) - { + if (user != null) { logger.error("Got MeetMeEvent for channel " + channel.getName() + " that is already user of a room"); user.left(event.getDateReceived()); - if (user.getRoom() != null) - { + if (user.getRoom() != null) { user.getRoom().removeUser(user); } channel.setMeetMeUserImpl(null); @@ -376,16 +320,13 @@ private MeetMeUserImpl getOrCreateUserImpl(AbstractMeetMeEvent event) * @param roomNumber number of the room to get or create. * @return the room with the given number. */ - MeetMeRoomImpl getOrCreateRoomImpl(String roomNumber) - { + MeetMeRoomImpl getOrCreateRoomImpl(String roomNumber) { MeetMeRoomImpl room; boolean created = false; - try (LockCloser closer = rooms.withLock()) - { + try (LockCloser closer = rooms.withLock()) { room = rooms.get(roomNumber); - if (room == null) - { + if (room == null) { room = new MeetMeRoomImpl(server, roomNumber); populateRoom(room); rooms.put(roomNumber, room); @@ -393,8 +334,7 @@ MeetMeRoomImpl getOrCreateRoomImpl(String roomNumber) } } - if (created) - { + if (created) { logger.debug("Created MeetMeRoom " + roomNumber); } diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java b/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java index 27b46c4b6..59da00312 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeRoomImpl.java @@ -16,10 +16,6 @@ */ package org.asteriskjava.live.internal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; - import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.MeetMeRoom; import org.asteriskjava.live.MeetMeUser; @@ -27,11 +23,14 @@ import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.CommandAction; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; + /** * Default implementation of the MeetMeRoom interface. */ -class MeetMeRoomImpl extends AbstractLiveObject implements MeetMeRoom -{ +class MeetMeRoomImpl extends AbstractLiveObject implements MeetMeRoom { private static final String COMMAND_PREFIX = "meetme"; private static final String LOCK_COMMAND = "lock"; private static final String UNLOCK_COMMAND = "unlock"; @@ -43,80 +42,63 @@ class MeetMeRoomImpl extends AbstractLiveObject implements MeetMeRoom */ private final LockableMap users; - MeetMeRoomImpl(AsteriskServerImpl server, String roomNumber) - { + MeetMeRoomImpl(AsteriskServerImpl server, String roomNumber) { super(server); this.roomNumber = roomNumber; this.users = new LockableMap<>(new HashMap<>(20)); } - public String getRoomNumber() - { + public String getRoomNumber() { return roomNumber; } - public Collection getUsers() - { - try (LockCloser closer = users.withLock()) - { + public Collection getUsers() { + try (LockCloser closer = users.withLock()) { return new ArrayList(users.values()); } } - public boolean isEmpty() - { - try (LockCloser closer = users.withLock()) - { + public boolean isEmpty() { + try (LockCloser closer = users.withLock()) { return users.isEmpty(); } } - Collection getUserImpls() - { - try (LockCloser closer = users.withLock()) - { + Collection getUserImpls() { + try (LockCloser closer = users.withLock()) { return new ArrayList<>(users.values()); } } - void addUser(MeetMeUserImpl user) - { - try (LockCloser closer = users.withLock()) - { + void addUser(MeetMeUserImpl user) { + try (LockCloser closer = users.withLock()) { users.put(user.getUserNumber(), user); } } - MeetMeUserImpl getUser(Integer userNumber) - { - try (LockCloser closer = users.withLock()) - { + MeetMeUserImpl getUser(Integer userNumber) { + try (LockCloser closer = users.withLock()) { return users.get(userNumber); } } - void removeUser(MeetMeUserImpl user) - { - try (LockCloser closer = users.withLock()) - { + void removeUser(MeetMeUserImpl user) { + try (LockCloser closer = users.withLock()) { users.remove(user.getUserNumber()); } } // action methods - public void lock() throws ManagerCommunicationException - { + public void lock() throws ManagerCommunicationException { sendMeetMeCommand(LOCK_COMMAND); } - public void unlock() throws ManagerCommunicationException - { + public void unlock() throws ManagerCommunicationException { sendMeetMeCommand(UNLOCK_COMMAND); } - private void sendMeetMeCommand(String command) throws ManagerCommunicationException - { + private void sendMeetMeCommand(String command) throws ManagerCommunicationException { final StringBuilder sb = new StringBuilder(); sb.append(COMMAND_PREFIX); sb.append(" "); @@ -128,15 +110,13 @@ private void sendMeetMeCommand(String command) throws ManagerCommunicationExcept } @Override - public String toString() - { + public String toString() { StringBuilder sb; int systemHashcode; sb = new StringBuilder("MeetMeRoom["); - try (LockCloser closer = this.withLock()) - { + try (LockCloser closer = this.withLock()) { sb.append("roomNumber='").append(getRoomNumber()).append("',"); systemHashcode = System.identityHashCode(this); } diff --git a/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java b/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java index 7382b7bce..099afe65a 100644 --- a/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/MeetMeUserImpl.java @@ -16,16 +16,15 @@ */ package org.asteriskjava.live.internal; -import java.util.Date; - import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.MeetMeUser; import org.asteriskjava.live.MeetMeUserState; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.CommandAction; -class MeetMeUserImpl extends AbstractLiveObject implements MeetMeUser -{ +import java.util.Date; + +class MeetMeUserImpl extends AbstractLiveObject implements MeetMeUser { private static final String COMMAND_PREFIX = "meetme"; private static final String MUTE_COMMAND = "mute"; private static final String UNMUTE_COMMAND = "unmute"; @@ -42,8 +41,7 @@ class MeetMeUserImpl extends AbstractLiveObject implements MeetMeUser private boolean muted; MeetMeUserImpl(AsteriskServerImpl server, MeetMeRoomImpl room, Integer userNumber, AsteriskChannelImpl channel, - Date dateJoined) - { + Date dateJoined) { super(server); this.room = room; this.userNumber = userNumber; @@ -52,42 +50,35 @@ class MeetMeUserImpl extends AbstractLiveObject implements MeetMeUser this.state = MeetMeUserState.JOINED; } - public MeetMeRoomImpl getRoom() - { + public MeetMeRoomImpl getRoom() { return room; } - public Integer getUserNumber() - { + public Integer getUserNumber() { return userNumber; } - public AsteriskChannelImpl getChannel() - { + public AsteriskChannelImpl getChannel() { return channel; } - public Date getDateJoined() - { + public Date getDateJoined() { return dateJoined; } - public Date getDateLeft() - { + public Date getDateLeft() { return dateLeft; } /** * Sets the status to {@link MeetMeUserState#LEFT} and dateLeft to the given * date. - * + * * @param dateLeft the date this user left the room. */ - void left(Date dateLeft) - { + void left(Date dateLeft) { MeetMeUserState oldState; - try (LockCloser closer = this.withLock()) - { + try (LockCloser closer = this.withLock()) { oldState = this.state; this.dateLeft = dateLeft; this.state = MeetMeUserState.LEFT; @@ -95,30 +86,25 @@ void left(Date dateLeft) firePropertyChange(PROPERTY_STATE, oldState, state); } - public MeetMeUserState getState() - { + public MeetMeUserState getState() { return state; } - public boolean isTalking() - { + public boolean isTalking() { return talking; } - void setTalking(boolean talking) - { + void setTalking(boolean talking) { boolean oldTalking = this.talking; this.talking = talking; firePropertyChange(PROPERTY_TALKING, oldTalking, talking); } - public boolean isMuted() - { + public boolean isMuted() { return muted; } - void setMuted(boolean muted) - { + void setMuted(boolean muted) { boolean oldMuted = this.muted; this.muted = muted; firePropertyChange(PROPERTY_MUTED, oldMuted, muted); @@ -126,23 +112,19 @@ void setMuted(boolean muted) // action methods - public void kick() throws ManagerCommunicationException - { + public void kick() throws ManagerCommunicationException { sendMeetMeUserCommand(KICK_COMMAND); } - public void mute() throws ManagerCommunicationException - { + public void mute() throws ManagerCommunicationException { sendMeetMeUserCommand(MUTE_COMMAND); } - public void unmute() throws ManagerCommunicationException - { + public void unmute() throws ManagerCommunicationException { sendMeetMeUserCommand(UNMUTE_COMMAND); } - private void sendMeetMeUserCommand(String command) throws ManagerCommunicationException - { + private void sendMeetMeUserCommand(String command) throws ManagerCommunicationException { StringBuilder sb = new StringBuilder(); sb.append(COMMAND_PREFIX); sb.append(" "); @@ -156,15 +138,13 @@ private void sendMeetMeUserCommand(String command) throws ManagerCommunicationEx } @Override - public String toString() - { + public String toString() { StringBuilder sb; int systemHashcode; sb = new StringBuilder("MeetMeUser["); - try (LockCloser closer = this.withLock()) - { + try (LockCloser closer = this.withLock()) { sb.append("dateJoined='").append(getDateJoined()).append("',"); sb.append("dateLeft='").append(getDateLeft()).append("',"); sb.append("talking=").append(isTalking()).append(","); @@ -173,8 +153,7 @@ public String toString() systemHashcode = System.identityHashCode(this); } sb.append("channel=AsteriskChannel["); - try (LockCloser closer = channel.withLock()) - { + try (LockCloser closer = channel.withLock()) { sb.append("id='").append(channel.getId()).append("',"); sb.append("name='").append(channel.getName()).append("'],"); } diff --git a/src/main/java/org/asteriskjava/live/internal/OriginateCallbackData.java b/src/main/java/org/asteriskjava/live/internal/OriginateCallbackData.java index bc7236190..246690b1c 100644 --- a/src/main/java/org/asteriskjava/live/internal/OriginateCallbackData.java +++ b/src/main/java/org/asteriskjava/live/internal/OriginateCallbackData.java @@ -1,21 +1,20 @@ /** - * + * */ package org.asteriskjava.live.internal; -import java.util.Date; - import org.asteriskjava.live.OriginateCallback; import org.asteriskjava.manager.action.OriginateAction; +import java.util.Date; + /** * Wrapper class for OriginateCallbacks. - * + * * @author srt * @version $Id$ */ -class OriginateCallbackData -{ +class OriginateCallbackData { private OriginateAction originateAction; private Date dateSent; private OriginateCallback callback; @@ -23,42 +22,36 @@ class OriginateCallbackData /** * Creates a new instance. - * + * * @param originateAction the action that has been sent to the Asterisk - * server - * @param dateSent date when the the action has been sent - * @param callback callback to notify about result + * server + * @param dateSent date when the the action has been sent + * @param callback callback to notify about result */ - OriginateCallbackData(OriginateAction originateAction, Date dateSent, OriginateCallback callback) - { + OriginateCallbackData(OriginateAction originateAction, Date dateSent, OriginateCallback callback) { super(); this.originateAction = originateAction; this.dateSent = dateSent; this.callback = callback; } - OriginateAction getOriginateAction() - { + OriginateAction getOriginateAction() { return originateAction; } - Date getDateSent() - { + Date getDateSent() { return dateSent; } - OriginateCallback getCallback() - { + OriginateCallback getCallback() { return callback; } - AsteriskChannelImpl getChannel() - { + AsteriskChannelImpl getChannel() { return channel; } - void setChannel(AsteriskChannelImpl channel) - { + void setChannel(AsteriskChannelImpl channel) { this.channel = channel; } } diff --git a/src/main/java/org/asteriskjava/live/internal/QueueManager.java b/src/main/java/org/asteriskjava/live/internal/QueueManager.java index c4b0ac879..2194fd78c 100644 --- a/src/main/java/org/asteriskjava/live/internal/QueueManager.java +++ b/src/main/java/org/asteriskjava/live/internal/QueueManager.java @@ -16,14 +16,6 @@ */ package org.asteriskjava.live.internal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.ListIterator; -import java.util.Map.Entry; - import org.asteriskjava.live.AsteriskQueue; import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.live.QueueMemberState; @@ -32,30 +24,20 @@ import org.asteriskjava.manager.EventTimeoutException; import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.action.QueueStatusAction; -import org.asteriskjava.manager.event.JoinEvent; -import org.asteriskjava.manager.event.LeaveEvent; -import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.QueueCallerJoinEvent; -import org.asteriskjava.manager.event.QueueCallerLeaveEvent; -import org.asteriskjava.manager.event.QueueEntryEvent; -import org.asteriskjava.manager.event.QueueMemberAddedEvent; -import org.asteriskjava.manager.event.QueueMemberEvent; -import org.asteriskjava.manager.event.QueueMemberPausedEvent; -import org.asteriskjava.manager.event.QueueMemberPenaltyEvent; -import org.asteriskjava.manager.event.QueueMemberRemovedEvent; -import org.asteriskjava.manager.event.QueueMemberStatusEvent; -import org.asteriskjava.manager.event.QueueParamsEvent; +import org.asteriskjava.manager.event.*; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.*; +import java.util.Map.Entry; + /** * Manages queue events on behalf of an AsteriskServer. * * @author srt * @version $Id$ */ -class QueueManager -{ +class QueueManager { private final Log logger = LogFactory.getLog(this.getClass()); private final AsteriskServerImpl server; @@ -70,48 +52,34 @@ class QueueManager */ private final LockableMap queuesLRU = new LockableMap<>(new LinkedHashMap<>()); - QueueManager(AsteriskServerImpl server, ChannelManager channelManager) - { + QueueManager(AsteriskServerImpl server, ChannelManager channelManager) { this.server = server; this.channelManager = channelManager; } - void initialize() throws ManagerCommunicationException - { + void initialize() throws ManagerCommunicationException { ResponseEvents re; - try - { + try { re = server.sendEventGeneratingAction(new QueueStatusAction()); - } - catch (ManagerCommunicationException e) - { + } catch (ManagerCommunicationException e) { final Throwable cause = e.getCause(); - if (cause instanceof EventTimeoutException) - { + if (cause instanceof EventTimeoutException) { // this happens with Asterisk 1.0.x as it doesn't send a // QueueStatusCompleteEvent re = ((EventTimeoutException) cause).getPartialResult(); - } - else - { + } else { throw e; } } - for (ManagerEvent event : re.getEvents()) - { - if (event instanceof QueueParamsEvent) - { + for (ManagerEvent event : re.getEvents()) { + if (event instanceof QueueParamsEvent) { handleQueueParamsEvent((QueueParamsEvent) event); - } - else if (event instanceof QueueMemberEvent) - { + } else if (event instanceof QueueMemberEvent) { handleQueueMemberEvent((QueueMemberEvent) event); - } - else if (event instanceof QueueEntryEvent) - { + } else if (event instanceof QueueEntryEvent) { handleQueueEntryEvent((QueueEntryEvent) event); } } @@ -121,62 +89,45 @@ else if (event instanceof QueueEntryEvent) /** * Method to ask for a Queue data update * - * @author Octavio Luna * @param queue * @throws ManagerCommunicationException + * @author Octavio Luna */ - void updateQueue(String queue) throws ManagerCommunicationException - { + void updateQueue(String queue) throws ManagerCommunicationException { ResponseEvents re; - try - { + try { QueueStatusAction queueStatusAction = new QueueStatusAction(); queueStatusAction.setQueue(queue); re = server.sendEventGeneratingAction(queueStatusAction); - } - catch (ManagerCommunicationException e) - { + } catch (ManagerCommunicationException e) { final Throwable cause = e.getCause(); - if (cause instanceof EventTimeoutException) - { + if (cause instanceof EventTimeoutException) { // this happens with Asterisk 1.0.x as it doesn't send a // QueueStatusCompleteEvent re = ((EventTimeoutException) cause).getPartialResult(); - } - else - { + } else { throw e; } } - for (ManagerEvent event : re.getEvents()) - { + for (ManagerEvent event : re.getEvents()) { // 101119 OLB: solo actualizamos el QUEUE por ahora - if (event instanceof QueueParamsEvent) - { + if (event instanceof QueueParamsEvent) { handleQueueParamsEvent((QueueParamsEvent) event); - } - - else if (event instanceof QueueMemberEvent) - { + } else if (event instanceof QueueMemberEvent) { handleQueueMemberEvent((QueueMemberEvent) event); - } - else if (event instanceof QueueEntryEvent) - { + } else if (event instanceof QueueEntryEvent) { handleQueueEntryEvent((QueueEntryEvent) event); } } } - void disconnected() - { - try (LockCloser closer = queuesLRU.withLock()) - { - for (AsteriskQueueImpl queue : queuesLRU.values()) - { + void disconnected() { + try (LockCloser closer = queuesLRU.withLock()) { + for (AsteriskQueueImpl queue : queuesLRU.values()) { queue.cancelServiceLevelTimer(); } queuesLRU.clear(); @@ -188,36 +139,30 @@ void disconnected() * * @return a copy of the list of the queues. */ - Collection getQueues() - { + Collection getQueues() { refreshQueuesIfForced(); Collection copy; - try (LockCloser closer = queuesLRU.withLock()) - { + try (LockCloser closer = queuesLRU.withLock()) { copy = new ArrayList(queuesLRU.values()); } return copy; } - public List getQueuesUpdatedAfter(Date date) - { + public List getQueuesUpdatedAfter(Date date) { refreshQueuesIfForced(); List copy = new ArrayList<>(); - try (LockCloser closer = queuesLRU.withLock()) - { + try (LockCloser closer = queuesLRU.withLock()) { List> list = new ArrayList<>(queuesLRU.entrySet()); ListIterator> iter = list.listIterator(list.size()); Entry entry; - while (iter.hasPrevious()) - { + while (iter.hasPrevious()) { entry = iter.previous(); AsteriskQueueImpl astQueue = entry.getValue(); - if (astQueue.getLastUpdateMillis() <= date.getTime()) - { + if (astQueue.getLastUpdateMillis() <= date.getTime()) { break; } copy.add(astQueue); @@ -233,10 +178,8 @@ public List getQueuesUpdatedAfter(Date date) * * @param queue the AsteriskQueueImpl to be added */ - private void addQueue(AsteriskQueueImpl queue) - { - try (LockCloser closer = queuesLRU.withLock()) - { + private void addQueue(AsteriskQueueImpl queue) { + try (LockCloser closer = queuesLRU.withLock()) { queuesLRU.put(queue.getName(), queue); } } @@ -246,8 +189,7 @@ private void addQueue(AsteriskQueueImpl queue) * * @param event the event received */ - private void handleQueueParamsEvent(QueueParamsEvent event) - { + private void handleQueueParamsEvent(QueueParamsEvent event) { AsteriskQueueImpl queue; final String name = event.getQueue(); @@ -264,28 +206,22 @@ private void handleQueueParamsEvent(QueueParamsEvent event) queue = getInternalQueueByName(name); - if (queue == null) - { + if (queue == null) { queue = new AsteriskQueueImpl(server, name, max, strategy, serviceLevel, weight, calls, holdTime, talkTime, completed, abandoned, serviceLevelPerf); logger.info("Adding new queue " + queue); addQueue(queue); - } - else - { + } else { // We should never reach that code as this method is only called for // initialization // So the queue should never be in the queues list - try (LockCloser closer = queue.withLock()) - { - try (LockCloser closer2 = queuesLRU.withLock()) - { + try (LockCloser closer = queue.withLock()) { + try (LockCloser closer2 = queuesLRU.withLock()) { if (queue.setMax(max) | queue.setServiceLevel(serviceLevel) | queue.setWeight(weight) | queue.setCalls(calls) | queue.setHoldTime(holdTime) | queue.setTalkTime(talkTime) | queue.setCompleted(completed) | queue.setAbandoned(abandoned) - | queue.setServiceLevelPerf(serviceLevelPerf)) - { + | queue.setServiceLevelPerf(serviceLevelPerf)) { queuesLRU.remove(queue.getName()); queuesLRU.put(queue.getName(), queue); @@ -300,37 +236,30 @@ private void handleQueueParamsEvent(QueueParamsEvent event) * * @param event the QueueMemberEvent received */ - private void handleQueueMemberEvent(QueueMemberEvent event) - { + private void handleQueueMemberEvent(QueueMemberEvent event) { final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); - if (queue == null) - { + if (queue == null) { logger.error("Ignored QueueEntryEvent for unknown queue " + event.getQueue()); return; } AsteriskQueueMemberImpl member = queue.getMember(event.getInterface()); - if (member == null) - { + if (member == null) { member = new AsteriskQueueMemberImpl(server, queue, event.getInterface(), QueueMemberState.valueOf(event.getStatus()), event.getPaused(), event.getPenalty(), event.getMembership(), event.getCallsTaken(), event.getLastCall()); queue.addMember(member); - } - else - { + } else { manageQueueMemberChange(queue, member, event); } } - private void manageQueueMemberChange(AsteriskQueueImpl queue, AsteriskQueueMemberImpl member, QueueMemberEvent event) - { + private void manageQueueMemberChange(AsteriskQueueImpl queue, AsteriskQueueMemberImpl member, QueueMemberEvent event) { if (member.stateChanged(QueueMemberState.valueOf(event.getStatus())) | member.pausedChanged(event.getPaused()) | member.penaltyChanged(event.getPenalty()) | member.callsTakenChanged(event.getCallsTaken()) - | member.lastCallChanged(event.getLastCall())) - { + | member.lastCallChanged(event.getLastCall())) { queue.stampLastUpdate(); } } @@ -341,18 +270,15 @@ private void manageQueueMemberChange(AsteriskQueueImpl queue, AsteriskQueueMembe * * @param event - the QueueEntryEvent received */ - private void handleQueueEntryEvent(QueueEntryEvent event) - { + private void handleQueueEntryEvent(QueueEntryEvent event) { final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); final AsteriskChannelImpl channel = channelManager.getChannelImplByName(event.getChannel()); - if (queue == null) - { + if (queue == null) { logger.error("Ignored QueueEntryEvent for unknown queue " + event.getQueue()); return; } - if (channel == null) - { + if (channel == null) { logger.error("Ignored QueueEntryEvent for unknown channel " + event.getChannel()); return; } @@ -373,18 +299,15 @@ private void handleQueueEntryEvent(QueueEntryEvent event) * + * Called from AsteriskServerImpl whenever a new entry appears in a * queue. + * + * @param event the JoinEvent received + */ - void handleJoinEvent(QueueCallerJoinEvent event) - { + void handleJoinEvent(QueueCallerJoinEvent event) { final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); final AsteriskChannelImpl channel = channelManager.getChannelImplByName(event.getChannel()); - if (queue == null) - { + if (queue == null) { logger.error("Ignored JoinEvent for unknown queue " + event.getQueue()); return; } - if (channel == null) - { + if (channel == null) { logger.error("Ignored JoinEvent for unknown channel " + event.getChannel()); return; } @@ -406,18 +329,15 @@ void handleJoinEvent(QueueCallerJoinEvent event) * * @param event the JoinEvent received */ - void handleJoinEvent(JoinEvent event) - { + void handleJoinEvent(JoinEvent event) { final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); final AsteriskChannelImpl channel = channelManager.getChannelImplByName(event.getChannel()); - if (queue == null) - { + if (queue == null) { logger.error("Ignored JoinEvent for unknown queue " + event.getQueue()); return; } - if (channel == null) - { + if (channel == null) { logger.error("Ignored JoinEvent for unknown channel " + event.getChannel()); return; } @@ -439,25 +359,21 @@ void handleJoinEvent(JoinEvent event) * * @param event - the LeaveEvent received */ - void handleLeaveEvent(QueueCallerLeaveEvent event) - { + void handleLeaveEvent(QueueCallerLeaveEvent event) { final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); final AsteriskChannelImpl channel = channelManager.getChannelImplByName(event.getChannel()); - if (queue == null) - { + if (queue == null) { logger.error("Ignored LeaveEvent for unknown queue " + event.getQueue()); return; } - if (channel == null) - { + if (channel == null) { logger.error("Ignored LeaveEvent for unknown channel " + event.getChannel()); return; } final AsteriskQueueEntryImpl existingQueueEntry = queue.getEntry(event.getChannel()); - if (existingQueueEntry == null) - { + if (existingQueueEntry == null) { logger.error("Ignored leave event for non existing queue entry in queue " + event.getQueue() + " for channel " + event.getChannel()); return; @@ -471,25 +387,21 @@ void handleLeaveEvent(QueueCallerLeaveEvent event) * * @param event - the LeaveEvent received */ - void handleLeaveEvent(LeaveEvent event) - { + void handleLeaveEvent(LeaveEvent event) { final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); final AsteriskChannelImpl channel = channelManager.getChannelImplByName(event.getChannel()); - if (queue == null) - { + if (queue == null) { logger.error("Ignored LeaveEvent for unknown queue " + event.getQueue()); return; } - if (channel == null) - { + if (channel == null) { logger.error("Ignored LeaveEvent for unknown channel " + event.getChannel()); return; } final AsteriskQueueEntryImpl existingQueueEntry = queue.getEntry(event.getChannel()); - if (existingQueueEntry == null) - { + if (existingQueueEntry == null) { logger.error("Ignored leave event for non existing queue entry in queue " + event.getQueue() + " for channel " + event.getChannel()); return; @@ -504,19 +416,16 @@ void handleLeaveEvent(LeaveEvent event) * * @param event that was triggered by Asterisk server. */ - void handleQueueMemberStatusEvent(QueueMemberStatusEvent event) - { + void handleQueueMemberStatusEvent(QueueMemberStatusEvent event) { AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); - if (queue == null) - { + if (queue == null) { logger.error("Ignored QueueMemberStatusEvent for unknown queue " + event.getQueue()); return; } AsteriskQueueMemberImpl member = queue.getMemberByLocation(event.getInterface()); - if (member == null) - { + if (member == null) { logger.error("Ignored QueueMemberStatusEvent for unknown member " + event.getInterface()); return; } @@ -525,19 +434,16 @@ void handleQueueMemberStatusEvent(QueueMemberStatusEvent event) queue.fireMemberStateChanged(member); } - void handleQueueMemberPausedEvent(QueueMemberPausedEvent event) - { + void handleQueueMemberPausedEvent(QueueMemberPausedEvent event) { AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); - if (queue == null) - { + if (queue == null) { logger.error("Ignored QueueMemberPausedEvent for unknown queue " + event.getQueue()); return; } AsteriskQueueMemberImpl member = queue.getMemberByLocation(event.getInterface()); - if (member == null) - { + if (member == null) { logger.error("Ignored QueueMemberPausedEvent for unknown member " + event.getInterface()); return; } @@ -545,19 +451,16 @@ void handleQueueMemberPausedEvent(QueueMemberPausedEvent event) member.pausedChanged(event.getPaused()); } - void handleQueueMemberPenaltyEvent(QueueMemberPenaltyEvent event) - { + void handleQueueMemberPenaltyEvent(QueueMemberPenaltyEvent event) { AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); - if (queue == null) - { + if (queue == null) { logger.error("Ignored QueueMemberStatusEvent for unknown queue " + event.getQueue()); return; } AsteriskQueueMemberImpl member = queue.getMemberByLocation(event.getLocation()); - if (member == null) - { + if (member == null) { logger.error("Ignored QueueMemberStatusEvent for unknown member " + event.getLocation()); return; } @@ -570,44 +473,36 @@ void handleQueueMemberPenaltyEvent(QueueMemberPenaltyEvent event) * * @param queueName name of the queue. * @return the requested queue or null if there is no queue - * with the given name. + * with the given name. */ - AsteriskQueueImpl getQueueByName(String queueName) - { + AsteriskQueueImpl getQueueByName(String queueName) { refreshQueueIfForced(queueName); AsteriskQueueImpl queue = getInternalQueueByName(queueName); - if (queue == null) - { + if (queue == null) { logger.error("Requested queue '" + queueName + "' not found!"); } return queue; } - private AsteriskQueueImpl getInternalQueueByName(String queueName) - { + private AsteriskQueueImpl getInternalQueueByName(String queueName) { AsteriskQueueImpl queue; - try (LockCloser closer = queuesLRU.withLock()) - { + try (LockCloser closer = queuesLRU.withLock()) { queue = queuesLRU.get(queueName); } return queue; } - private void refreshQueueIfForced(String queueName) - { - if (queuesMonitorForced) - { + private void refreshQueueIfForced(String queueName) { + if (queuesMonitorForced) { updateQueue(queueName); } } - private void refreshQueuesIfForced() - { - if (queuesMonitorForced && (System.currentTimeMillis() - queueMonitorLastTimeReloaded) > queuesMonitorLeaseTime) - { + private void refreshQueuesIfForced() { + if (queuesMonitorForced && (System.currentTimeMillis() - queueMonitorLastTimeReloaded) > queuesMonitorLeaseTime) { initialize(); queueMonitorLastTimeReloaded = System.currentTimeMillis(); } @@ -618,18 +513,15 @@ private void refreshQueuesIfForced() * * @param event - the generated QueueMemberAddedEvent. */ - public void handleQueueMemberAddedEvent(QueueMemberAddedEvent event) - { + public void handleQueueMemberAddedEvent(QueueMemberAddedEvent event) { final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); - if (queue == null) - { + if (queue == null) { logger.error("Ignored QueueMemberAddedEvent for unknown queue " + event.getQueue()); return; } AsteriskQueueMemberImpl member = queue.getMember(event.getInterface()); - if (member == null) - { + if (member == null) { member = new AsteriskQueueMemberImpl(server, queue, event.getInterface(), QueueMemberState.valueOf(event.getStatus()), event.getPaused(), event.getPenalty(), event.getMembership(), event.getCallsTaken(), event.getLastCall()); @@ -643,18 +535,15 @@ public void handleQueueMemberAddedEvent(QueueMemberAddedEvent event) * * @param event - the generated QueueMemberRemovedEvent. */ - public void handleQueueMemberRemovedEvent(QueueMemberRemovedEvent event) - { + public void handleQueueMemberRemovedEvent(QueueMemberRemovedEvent event) { final AsteriskQueueImpl queue = getInternalQueueByName(event.getQueue()); - if (queue == null) - { + if (queue == null) { logger.error("Ignored QueueMemberRemovedEvent for unknown queue " + event.getQueue()); return; } final AsteriskQueueMemberImpl member = queue.getMember(event.getInterface()); - if (member == null) - { + if (member == null) { logger.error("Ignored QueueMemberRemovedEvent for unknown agent name: " + event.getMemberName() + " location: " + event.getInterface() + " queue: " + event.getQueue()); return; @@ -663,13 +552,11 @@ public void handleQueueMemberRemovedEvent(QueueMemberRemovedEvent event) queue.removeMember(member); } - public void forceQueuesMonitor(boolean force) - { + public void forceQueuesMonitor(boolean force) { queuesMonitorForced = force; } - public boolean isQueuesMonitorForced() - { + public boolean isQueuesMonitorForced() { return queuesMonitorForced; } } diff --git a/src/main/java/org/asteriskjava/live/internal/package.html b/src/main/java/org/asteriskjava/live/internal/package.html index 90995dfa5..5f3ca4a84 100644 --- a/src/main/java/org/asteriskjava/live/internal/package.html +++ b/src/main/java/org/asteriskjava/live/internal/package.html @@ -1,28 +1,28 @@ - + -

    Provides private implementations and helper classes for interfaces +

    Provides private implementations and helper classes for interfaces defined in the org.asteriskjava.live package.

    - \ No newline at end of file + diff --git a/src/main/java/org/asteriskjava/live/package.html b/src/main/java/org/asteriskjava/live/package.html index 1560b214b..d33273ce2 100644 --- a/src/main/java/org/asteriskjava/live/package.html +++ b/src/main/java/org/asteriskjava/live/package.html @@ -1,27 +1,27 @@ - +

    Provides a higher level API on top of Asterisk's Manager API.

    - \ No newline at end of file + diff --git a/src/main/java/org/asteriskjava/lock/Lockable.java b/src/main/java/org/asteriskjava/lock/Lockable.java index 565b4e426..e1e7b06c4 100644 --- a/src/main/java/org/asteriskjava/lock/Lockable.java +++ b/src/main/java/org/asteriskjava/lock/Lockable.java @@ -1,16 +1,14 @@ package org.asteriskjava.lock; +import com.google.common.util.concurrent.RateLimiter; +import org.asteriskjava.lock.Locker.LockCloser; + import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; -import org.asteriskjava.lock.Locker.LockCloser; - -import com.google.common.util.concurrent.RateLimiter; - -public class Lockable -{ +public class Lockable { private final ReentrantLock internalLock = new ReentrantLock(false); final private String lockName; final AtomicReference threadHoldingLock = new AtomicReference<>(); @@ -27,19 +25,15 @@ public class Lockable private final static AtomicLong seed = new AtomicLong(); private final long lockableId = seed.incrementAndGet(); - public Lockable() - { + public Lockable() { this.lockName = getLockCaller(); } - private String getLockCaller() - { + private String getLockCaller() { StackTraceElement[] trace = new Exception().getStackTrace(); String name = this.getClass().getCanonicalName(); - for (StackTraceElement element : trace) - { - if (element.getFileName() != null && !element.getFileName().contains(Lockable.class.getSimpleName())) - { + for (StackTraceElement element : trace) { + if (element.getFileName() != null && !element.getFileName().contains(Lockable.class.getSimpleName())) { name = element.getFileName() + " " + element.getMethodName() + " " + element.getLineNumber() + " " + element.getClassName(); break; @@ -49,110 +43,89 @@ private String getLockCaller() return name; } - String asLockString() - { + String asLockString() { return "Lockable [waited=" + waited + ", waitTime=" + totalWaitTime + ", totalHoldTime=" + totalHoldTime + ", acquired=" + acquired + ", object=" + lockName + ", id=" + lockableId + "]"; } - long getLockAverageHoldTime() - { + long getLockAverageHoldTime() { long hold = totalHoldTime.get(); long count = acquired.get(); - if (count < 10) - { + if (count < 10) { return 250; } return Math.max(hold / count, 50); } - public LockCloser withLock() - { + public LockCloser withLock() { return Locker.doWithLock(this); } - ReentrantLock getInternalLock() - { + ReentrantLock getInternalLock() { return internalLock; } - void addLockTotalWaitTime(int time) - { + void addLockTotalWaitTime(int time) { totalWaitTime.addAndGet(time); } - void addLockTotalHoldTime(int time) - { + void addLockTotalHoldTime(int time) { totalHoldTime.addAndGet(time); } - int addLockRequested() - { + int addLockRequested() { return requested.incrementAndGet(); } - void addLockWaited(int time) - { + void addLockWaited(int time) { waited.addAndGet(time); } - void addLockAcquired(int count) - { + void addLockAcquired(int count) { acquired.addAndGet(count); } - boolean isLockDumped() - { + boolean isLockDumped() { return dumped; } - void setLockDumped(boolean dumped) - { + void setLockDumped(boolean dumped) { this.dumped = dumped; } - int getLockTotalWaitTime() - { + int getLockTotalWaitTime() { return totalWaitTime.intValue(); } - int getLockWaited() - { + int getLockWaited() { return waited.intValue(); } - int getLockRequested() - { + int getLockRequested() { return requested.intValue(); } - Long getLockableId() - { + Long getLockableId() { return lockableId; } - int getLockTotalHoldTime() - { + int getLockTotalHoldTime() { return totalHoldTime.intValue(); } - int getLockAcquired() - { + int getLockAcquired() { return acquired.intValue(); } - boolean wasLockBlocked() - { + boolean wasLockBlocked() { return blocked; } - void setLockBlocked(boolean blocked) - { + void setLockBlocked(boolean blocked) { this.blocked = blocked; } - public RateLimiter getDumpRateLimit() - { + public RateLimiter getDumpRateLimit() { return rateLimiter; } diff --git a/src/main/java/org/asteriskjava/lock/LockableList.java b/src/main/java/org/asteriskjava/lock/LockableList.java index e9b9d6829..78c87b68a 100644 --- a/src/main/java/org/asteriskjava/lock/LockableList.java +++ b/src/main/java/org/asteriskjava/lock/LockableList.java @@ -1,186 +1,146 @@ package org.asteriskjava.lock; -import java.util.Collection; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Spliterator; +import java.util.*; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.UnaryOperator; import java.util.stream.Stream; -public class LockableList extends Lockable implements List -{ +public class LockableList extends Lockable implements List { final List list; - public LockableList(List list) - { - if (list instanceof Lockable) - { + public LockableList(List list) { + if (list instanceof Lockable) { throw new RuntimeException("list is already lockable"); } this.list = list; } - public void forEach(Consumer< ? super S> action) - { + public void forEach(Consumer action) { list.forEach(action); } - public int size() - { + public int size() { return list.size(); } - public boolean isEmpty() - { + public boolean isEmpty() { return list.isEmpty(); } - public boolean contains(Object o) - { + public boolean contains(Object o) { return list.contains(o); } - public Iterator iterator() - { + public Iterator iterator() { return list.iterator(); } - public Object[] toArray() - { + public Object[] toArray() { return list.toArray(); } - public T[] toArray(T[] a) - { + public T[] toArray(T[] a) { return list.toArray(a); } - public boolean add(S e) - { + public boolean add(S e) { return list.add(e); } - public boolean remove(Object o) - { + public boolean remove(Object o) { return list.remove(o); } - public boolean containsAll(Collection< ? > c) - { + public boolean containsAll(Collection c) { return list.containsAll(c); } - public boolean addAll(Collection< ? extends S> c) - { + public boolean addAll(Collection c) { return list.addAll(c); } - public boolean addAll(int index, Collection< ? extends S> c) - { + public boolean addAll(int index, Collection c) { return list.addAll(index, c); } - public boolean removeAll(Collection< ? > c) - { + public boolean removeAll(Collection c) { return list.removeAll(c); } - public boolean retainAll(Collection< ? > c) - { + public boolean retainAll(Collection c) { return list.retainAll(c); } - public void replaceAll(UnaryOperator operator) - { + public void replaceAll(UnaryOperator operator) { list.replaceAll(operator); } - public boolean removeIf(Predicate< ? super S> filter) - { + public boolean removeIf(Predicate filter) { return list.removeIf(filter); } - public void sort(Comparator< ? super S> c) - { + public void sort(Comparator c) { list.sort(c); } - public void clear() - { + public void clear() { list.clear(); } - public boolean equals(Object o) - { + public boolean equals(Object o) { return list.equals(o); } - public int hashCode() - { + public int hashCode() { return list.hashCode(); } - public S get(int index) - { + public S get(int index) { return list.get(index); } - public S set(int index, S element) - { + public S set(int index, S element) { return list.set(index, element); } - public void add(int index, S element) - { + public void add(int index, S element) { list.add(index, element); } - public Stream stream() - { + public Stream stream() { return list.stream(); } - public S remove(int index) - { + public S remove(int index) { return list.remove(index); } - public Stream parallelStream() - { + public Stream parallelStream() { return list.parallelStream(); } - public int indexOf(Object o) - { + public int indexOf(Object o) { return list.indexOf(o); } - public int lastIndexOf(Object o) - { + public int lastIndexOf(Object o) { return list.lastIndexOf(o); } - public ListIterator listIterator() - { + public ListIterator listIterator() { return list.listIterator(); } - public ListIterator listIterator(int index) - { + public ListIterator listIterator(int index) { return list.listIterator(index); } - public List subList(int fromIndex, int toIndex) - { + public List subList(int fromIndex, int toIndex) { return list.subList(fromIndex, toIndex); } - public Spliterator spliterator() - { + public Spliterator spliterator() { return list.spliterator(); } diff --git a/src/main/java/org/asteriskjava/lock/LockableMap.java b/src/main/java/org/asteriskjava/lock/LockableMap.java index ac506bc9c..ca919bc0d 100644 --- a/src/main/java/org/asteriskjava/lock/LockableMap.java +++ b/src/main/java/org/asteriskjava/lock/LockableMap.java @@ -7,141 +7,113 @@ import java.util.function.BiFunction; import java.util.function.Function; -public class LockableMap extends Lockable implements Map -{ +public class LockableMap extends Lockable implements Map { final Map map; - public LockableMap(Map map) - { - if (map instanceof Lockable) - { + public LockableMap(Map map) { + if (map instanceof Lockable) { throw new RuntimeException("map is already lockable"); } this.map = map; } - public int size() - { + public int size() { return map.size(); } - public boolean isEmpty() - { + public boolean isEmpty() { return map.isEmpty(); } - public boolean containsKey(Object key) - { + public boolean containsKey(Object key) { return map.containsKey(key); } - public boolean containsValue(Object value) - { + public boolean containsValue(Object value) { return map.containsValue(value); } - public P get(Object key) - { + public P get(Object key) { return map.get(key); } - public P put(S key, P value) - { + public P put(S key, P value) { return map.put(key, value); } - public P remove(Object key) - { + public P remove(Object key) { return map.remove(key); } - public void putAll(Map< ? extends S, ? extends P> m) - { + public void putAll(Map m) { map.putAll(m); } - public void clear() - { + public void clear() { map.clear(); } - public Set keySet() - { + public Set keySet() { return map.keySet(); } - public Collection

    values() - { + public Collection

    values() { return map.values(); } - public Set> entrySet() - { + public Set> entrySet() { return map.entrySet(); } - public boolean equals(Object o) - { + public boolean equals(Object o) { return map.equals(o); } - public int hashCode() - { + public int hashCode() { return map.hashCode(); } - public P getOrDefault(Object key, P defaultValue) - { + public P getOrDefault(Object key, P defaultValue) { return map.getOrDefault(key, defaultValue); } - public void forEach(BiConsumer< ? super S, ? super P> action) - { + public void forEach(BiConsumer action) { map.forEach(action); } - public void replaceAll(BiFunction< ? super S, ? super P, ? extends P> function) - { + public void replaceAll(BiFunction function) { map.replaceAll(function); } - public P putIfAbsent(S key, P value) - { + public P putIfAbsent(S key, P value) { return map.putIfAbsent(key, value); } - public boolean remove(Object key, Object value) - { + public boolean remove(Object key, Object value) { return map.remove(key, value); } - public boolean replace(S key, P oldValue, P newValue) - { + public boolean replace(S key, P oldValue, P newValue) { return map.replace(key, oldValue, newValue); } - public P replace(S key, P value) - { + public P replace(S key, P value) { return map.replace(key, value); } - public P computeIfAbsent(S key, Function< ? super S, ? extends P> mappingFunction) - { + public P computeIfAbsent(S key, Function mappingFunction) { return map.computeIfAbsent(key, mappingFunction); } - public P computeIfPresent(S key, BiFunction< ? super S, ? super P, ? extends P> remappingFunction) - { + public P computeIfPresent(S key, BiFunction remappingFunction) { return map.computeIfPresent(key, remappingFunction); } - public P compute(S key, BiFunction< ? super S, ? super P, ? extends P> remappingFunction) - { + public P compute(S key, BiFunction remappingFunction) { return map.compute(key, remappingFunction); } - public P merge(S key, P value, BiFunction< ? super P, ? super P, ? extends P> remappingFunction) - { + public P merge(S key, P value, BiFunction remappingFunction) { return map.merge(key, value, remappingFunction); } diff --git a/src/main/java/org/asteriskjava/lock/LockableSet.java b/src/main/java/org/asteriskjava/lock/LockableSet.java index 25d52b5cb..f88bd5de6 100644 --- a/src/main/java/org/asteriskjava/lock/LockableSet.java +++ b/src/main/java/org/asteriskjava/lock/LockableSet.java @@ -8,116 +8,93 @@ import java.util.function.Predicate; import java.util.stream.Stream; -public class LockableSet extends Lockable implements Set -{ +public class LockableSet extends Lockable implements Set { final Set set; - public LockableSet(Set set) - { - if (set instanceof Lockable) - { + public LockableSet(Set set) { + if (set instanceof Lockable) { throw new RuntimeException("set is already lockable"); } this.set = set; } - public void forEach(Consumer< ? super S> action) - { + public void forEach(Consumer action) { set.forEach(action); } - public int size() - { + public int size() { return set.size(); } - public boolean isEmpty() - { + public boolean isEmpty() { return set.isEmpty(); } - public boolean contains(Object o) - { + public boolean contains(Object o) { return set.contains(o); } - public Iterator iterator() - { + public Iterator iterator() { return set.iterator(); } - public Object[] toArray() - { + public Object[] toArray() { return set.toArray(); } - public T[] toArray(T[] a) - { + public T[] toArray(T[] a) { return set.toArray(a); } - public boolean add(S e) - { + public boolean add(S e) { return set.add(e); } - public boolean remove(Object o) - { + public boolean remove(Object o) { return set.remove(o); } - public boolean containsAll(Collection< ? > c) - { + public boolean containsAll(Collection c) { return set.containsAll(c); } - public boolean addAll(Collection< ? extends S> c) - { + public boolean addAll(Collection c) { return set.addAll(c); } - public boolean retainAll(Collection< ? > c) - { + public boolean retainAll(Collection c) { return set.retainAll(c); } - public boolean removeAll(Collection< ? > c) - { + public boolean removeAll(Collection c) { return set.removeAll(c); } - public void clear() - { + public void clear() { set.clear(); } - public boolean equals(Object o) - { + public boolean equals(Object o) { return set.equals(o); } - public int hashCode() - { + public int hashCode() { return set.hashCode(); } - public Spliterator spliterator() - { + public Spliterator spliterator() { return set.spliterator(); } - public boolean removeIf(Predicate< ? super S> filter) - { + public boolean removeIf(Predicate filter) { return set.removeIf(filter); } - public Stream stream() - { + public Stream stream() { return set.stream(); } - public Stream parallelStream() - { + public Stream parallelStream() { return set.parallelStream(); } diff --git a/src/main/java/org/asteriskjava/lock/Locker.java b/src/main/java/org/asteriskjava/lock/Locker.java index d63d6d723..d8edcab28 100644 --- a/src/main/java/org/asteriskjava/lock/Locker.java +++ b/src/main/java/org/asteriskjava/lock/Locker.java @@ -1,5 +1,10 @@ package org.asteriskjava.lock; +import com.google.common.util.concurrent.RateLimiter; +import org.asteriskjava.pbx.util.LogTime; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -10,20 +15,13 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; -import org.asteriskjava.pbx.util.LogTime; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; - -import com.google.common.util.concurrent.RateLimiter; - -public class Locker -{ +public class Locker { private static final Log logger = LogFactory.getLog(Locker.class); private static volatile boolean diags = false; - private static ScheduledFuture< ? > future; + private static ScheduledFuture future; private static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); private static final Object sync = new Object(); @@ -34,22 +32,16 @@ public class Locker private static final RateLimiter waitRateLimiter = RateLimiter.create(4); - public static LockCloser doWithLock(final Lockable lockable) - { - try - { - if (diags) - { - synchronized (sync) - { + public static LockCloser doWithLock(final Lockable lockable) { + try { + if (diags) { + synchronized (sync) { keepList.put(lockable.getLockableId(), lockable); } return lockWithDiags(lockable); } return simpleLock(lockable); - } - catch (Exception e) - { + } catch (Exception e) { throw new RuntimeException(e); } @@ -57,18 +49,15 @@ public static LockCloser doWithLock(final Lockable lockable) /** * determine the caller to Locker - * + * * @param lockable * @return */ - static String getCaller(Lockable lockable) - { + static String getCaller(Lockable lockable) { StackTraceElement[] trace = new Exception().getStackTrace(); String name = lockable.getClass().getCanonicalName(); - for (StackTraceElement element : trace) - { - if (element.getFileName() != null && !element.getFileName().contains(Locker.class.getSimpleName())) - { + for (StackTraceElement element : trace) { + if (element.getFileName() != null && !element.getFileName().contains(Locker.class.getSimpleName())) { name = element.getFileName() + " " + element.getMethodName() + " " + element.getLineNumber() + " " + element.getClassName(); break; @@ -78,8 +67,7 @@ static String getCaller(Lockable lockable) return name; } - public interface LockCloser extends AutoCloseable - { + public interface LockCloser extends AutoCloseable { public void close(); } @@ -88,14 +76,12 @@ public interface LockCloser extends AutoCloseable private static final LogTime startTime = new LogTime(); - private static LockCloser simpleLock(Lockable lockable) throws InterruptedException - { + private static LockCloser simpleLock(Lockable lockable) throws InterruptedException { LogTime acquireTimer = new LogTime(); ReentrantLock lock = lockable.getInternalLock(); lock.lock(); // lock acquired! - if (acquireTimer.timeTaken() > 1_000 && warnRateLimiter.tryAcquire()) - { + if (acquireTimer.timeTaken() > 1_000 && warnRateLimiter.tryAcquire()) { logger.warn("Locks are being held for to long, waited " + acquireTimer.timeTaken() + "ms, you can enable lock diagnostics by calling Locker.enable()"); } @@ -104,11 +90,9 @@ private static LockCloser simpleLock(Lockable lockable) throws InterruptedExcept return () -> { lock.unlock(); - if (holdTimer.timeTaken() > 500 && warnRateLimiter.tryAcquire()) - { + if (holdTimer.timeTaken() > 500 && warnRateLimiter.tryAcquire()) { // don't start warning for the first 10 seconds - if (startTime.timeTaken() > 10_000) - { + if (startTime.timeTaken() > 10_000) { logger.warn("Locks are being held for to long (" + holdTimer.timeTaken() + "ms), you can enable lock diagnostics by calling Locker.enable()"); } @@ -116,25 +100,19 @@ private static LockCloser simpleLock(Lockable lockable) throws InterruptedExcept }; } - private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedException - { + private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedException { int offset = lockable.addLockRequested(); long waitStart = System.currentTimeMillis(); ReentrantLock lock = lockable.getInternalLock(); - while (!lock.tryLock(100, TimeUnit.MILLISECONDS)) - { - if (!lockable.isLockDumped() && lockable.getDumpRateLimit().tryAcquire()) - { + while (!lock.tryLock(100, TimeUnit.MILLISECONDS)) { + if (!lockable.isLockDumped() && lockable.getDumpRateLimit().tryAcquire()) { lockable.setLockDumped(true); dumpThread(lockable.threadHoldingLock.get(), "Waiting on lock... blocked by... id:" + lockable.getLockableId()); - } - else - { - if (waitRateLimiter.tryAcquire()) - { + } else { + if (waitRateLimiter.tryAcquire()) { long elapsed = System.currentTimeMillis() - waitStart; logger.warn("waiting " + elapsed + "(MS) id:" + lockable.getLockableId()); } @@ -146,12 +124,10 @@ private static LockCloser lockWithDiags(Lockable lockable) throws InterruptedExc long acquiredAt = System.currentTimeMillis(); lockable.threadHoldingLock.set(Thread.currentThread()); - return new LockCloser() - { + return new LockCloser() { @Override - public void close() - { + public void close() { // ignore any wait that may have been caused by Locker code, so // count the waiters before we release the lock long waiters = lockable.getLockRequested() - offset; @@ -168,30 +144,26 @@ public void close() lockable.addLockTotalHoldTime(holdTime); long averageHoldTime = lockable.getLockAverageHoldTime(); - if ((waiters > 0 && holdTime > averageHoldTime * 2) || dumped) - { + if ((waiters > 0 && holdTime > averageHoldTime * 2) || dumped) { // some threads waited String message = "Lock held for (" + holdTime + "MS), " + waiters + " threads waited for some of that time! " + getCaller(lockable) + " id:" + lockable.getLockableId(); logger.warn(message); - if (holdTime > averageHoldTime * 10.0 || dumped) - { + if (holdTime > averageHoldTime * 10.0 || dumped) { Exception trace = new Exception(message); logger.error(trace, trace); } } - if (holdTime > averageHoldTime * 5.0) - { + if (holdTime > averageHoldTime * 5.0) { // long hold! String message = "Lock hold of lock (" + holdTime + "MS), average is " + lockable.getLockAverageHoldTime() + " " + getCaller(lockable) + " id:" + lockable.getLockableId(); logger.warn(message); - if (holdTime > averageHoldTime * 10.0) - { + if (holdTime > averageHoldTime * 10.0) { Exception trace = new Exception(message); logger.error(trace, trace); } @@ -201,34 +173,26 @@ public void close() } - public static void dumpThread(Thread thread, String message) - { + public static void dumpThread(Thread thread, String message) { - if (thread != null) - { + if (thread != null) { StackTraceElement[] trace = thread.getStackTrace(); String dump = ""; int i = 0; - for (; i < trace.length; i++) - { + for (; i < trace.length; i++) { StackTraceElement ste = trace[i]; dump += "\tat " + ste.toString(); dump += '\n'; } logger.error(message); - if (dump.length() > 0) - { + if (dump.length() > 0) { logger.error(dump); - } - else - { + } else { logger.error("Unable to create dump, thread seems to have exited."); } - } - else - { + } else { logger.error("Thread hasn't been set: " + message); } @@ -237,38 +201,28 @@ public static void dumpThread(Thread thread, String message) /** * start dumping lock stats once per minute, can't be stopped once started. */ - public static void enable() - { - synchronized (sync) - { - if (!diags) - { + public static void enable() { + synchronized (sync) { + if (!diags) { diags = true; future = executor.scheduleWithFixedDelay(() -> { dumpStats(); }, 1, 1, TimeUnit.MINUTES); logger.warn("Lock checking enabled"); - } - else - { + } else { logger.warn("Already enabled"); } } } - public static void disable() - { - synchronized (sync) - { - if (diags) - { + public static void disable() { + synchronized (sync) { + if (diags) { diags = false; future.cancel(false); dumpStats(); logger.warn("Lock checking disabled"); - } - else - { + } else { logger.warn("Lock checking is already disabled"); } } @@ -276,21 +230,17 @@ public static void disable() private static volatile boolean first = true; - static void dumpStats() - { + static void dumpStats() { List lockables = new LinkedList<>(); - synchronized (sync) - { + synchronized (sync) { lockables.addAll(keepList.values()); keepList.clear(); } boolean activity = false; - for (Lockable lockable : lockables) - { - if (lockable.wasLockBlocked()) - { + for (Lockable lockable : lockables) { + if (lockable.wasLockBlocked()) { int waited = lockable.getLockWaited(); int waitTime = lockable.getLockTotalWaitTime(); int acquired = lockable.getLockAcquired(); @@ -307,9 +257,7 @@ static void dumpStats() } } - if (first || activity) - - { + if (first || activity) { logger.warn("Will dump Lock stats each minute when there is contention..."); first = false; } diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 57c71d230..1f977a1ae 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -1,11 +1,11 @@ package org.asteriskjava.manager; -import java.lang.reflect.Method; - import org.asteriskjava.manager.event.*; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.lang.reflect.Method; + /** * Utility class that provides a protected handler method for each concrete * manager event. Makes life easier by removing the need to code endless @@ -62,728 +62,548 @@ * @author srt * @since 0.3 */ -public abstract class AbstractManagerEventListener implements ManagerEventListener -{ +public abstract class AbstractManagerEventListener implements ManagerEventListener { private static final Log LOGGER = LogFactory.getLog(AbstractManagerEventListener.class); - public void handleEvent(AgentCompleteEvent event) - { + public void handleEvent(AgentCompleteEvent event) { } - public void handleEvent(AgentConnectEvent event) - { + public void handleEvent(AgentConnectEvent event) { } - public void handleEvent(AgentDumpEvent event) - { + public void handleEvent(AgentDumpEvent event) { } - public void handleEvent(AgentRingNoAnswerEvent event) - { + public void handleEvent(AgentRingNoAnswerEvent event) { } - public void handleEvent(AttendedTransferEvent event) - { + public void handleEvent(AttendedTransferEvent event) { } - public void handleEvent(BlindTransferEvent event) - { + public void handleEvent(BlindTransferEvent event) { } - public void handleEvent(BridgeCreateEvent event) - { + public void handleEvent(BridgeCreateEvent event) { } - public void handleEvent(BridgeDestroyEvent event) - { + public void handleEvent(BridgeDestroyEvent event) { } - public void handleEvent(BridgeEnterEvent event) - { + public void handleEvent(BridgeEnterEvent event) { } - public void handleEvent(BridgeLeaveEvent event) - { + public void handleEvent(BridgeLeaveEvent event) { } - public void handleEvent(HangupEvent event) - { + public void handleEvent(HangupEvent event) { } - public void handleEvent(NewChannelEvent event) - { + public void handleEvent(NewChannelEvent event) { } - public void handleEvent(NewStateEvent event) - { + public void handleEvent(NewStateEvent event) { } - public void handleEvent(ConfbridgeEndEvent event) - { + public void handleEvent(ConfbridgeEndEvent event) { } - public void handleEvent(ConfbridgeJoinEvent event) - { + public void handleEvent(ConfbridgeJoinEvent event) { } - public void handleEvent(ConfbridgeLeaveEvent event) - { + public void handleEvent(ConfbridgeLeaveEvent event) { } - public void handleEvent(ConfbridgeStartEvent event) - { + public void handleEvent(ConfbridgeStartEvent event) { } - public void handleEvent(ConfbridgeTalkingEvent event) - { + public void handleEvent(ConfbridgeTalkingEvent event) { } - public void handleEvent(AntennaLevelEvent event) - { + public void handleEvent(AntennaLevelEvent event) { } - public void handleEvent(HangupRequestEvent event) - { + public void handleEvent(HangupRequestEvent event) { } - public void handleEvent(NewCallerIdEvent event) - { + public void handleEvent(NewCallerIdEvent event) { } - public void handleEvent(SoftHangupRequestEvent event) - { + public void handleEvent(SoftHangupRequestEvent event) { } - public void handleEvent(FaxDocumentStatusEvent event) - { + public void handleEvent(FaxDocumentStatusEvent event) { } - public void handleEvent(FaxReceivedEvent event) - { + public void handleEvent(FaxReceivedEvent event) { } - public void handleEvent(FaxStatusEvent event) - { + public void handleEvent(FaxStatusEvent event) { } - public void handleEvent(SendFaxEvent event) - { + public void handleEvent(SendFaxEvent event) { } - public void handleEvent(SendFaxStatusEvent event) - { + public void handleEvent(SendFaxStatusEvent event) { } - public void handleEvent(T38FaxStatusEvent event) - { + public void handleEvent(T38FaxStatusEvent event) { } - public void handleEvent(HoldEvent event) - { + public void handleEvent(HoldEvent event) { } - public void handleEvent(UnholdEvent event) - { + public void handleEvent(UnholdEvent event) { } - public void handleEvent(MeetMeJoinEvent event) - { + public void handleEvent(MeetMeJoinEvent event) { } - public void handleEvent(MeetMeLeaveEvent event) - { + public void handleEvent(MeetMeLeaveEvent event) { } - public void handleEvent(MeetMeMuteEvent event) - { + public void handleEvent(MeetMeMuteEvent event) { } - public void handleEvent(MeetMeTalkingEvent event) - { + public void handleEvent(MeetMeTalkingEvent event) { } - public void handleEvent(MeetMeTalkingRequestEvent event) - { + public void handleEvent(MeetMeTalkingRequestEvent event) { } - public void handleEvent(MonitorStartEvent event) - { + public void handleEvent(MonitorStartEvent event) { } - public void handleEvent(MonitorStopEvent event) - { + public void handleEvent(MonitorStopEvent event) { } - public void handleEvent(ParkedCallEvent event) - { + public void handleEvent(ParkedCallEvent event) { } - public void handleEvent(QueueMemberAddedEvent event) - { + public void handleEvent(QueueMemberAddedEvent event) { } - public void handleEvent(QueueMemberPausedEvent event) - { + public void handleEvent(QueueMemberPausedEvent event) { } - public void handleEvent(QueueMemberRemovedEvent event) - { + public void handleEvent(QueueMemberRemovedEvent event) { } - public void handleEvent(RtcpReceivedEvent event) - { + public void handleEvent(RtcpReceivedEvent event) { } - public void handleEvent(RtcpSentEvent event) - { + public void handleEvent(RtcpSentEvent event) { } - public void handleEvent(RtpReceiverStatEvent event) - { + public void handleEvent(RtpReceiverStatEvent event) { } - public void handleEvent(RtpSenderStatEvent event) - { + public void handleEvent(RtpSenderStatEvent event) { } - public void handleEvent(AgentCallbackLoginEvent event) - { + public void handleEvent(AgentCallbackLoginEvent event) { } - public void handleEvent(AgentCallbackLogoffEvent event) - { + public void handleEvent(AgentCallbackLogoffEvent event) { } - public void handleEvent(AgentCalledEvent event) - { + public void handleEvent(AgentCalledEvent event) { } - public void handleEvent(AgentLoginEvent event) - { + public void handleEvent(AgentLoginEvent event) { } - public void handleEvent(AgentLogoffEvent event) - { + public void handleEvent(AgentLogoffEvent event) { } - public void handleEvent(AgiExecEvent event) - { + public void handleEvent(AgiExecEvent event) { } - public void handleEvent(AgiExecEndEvent event) - { + public void handleEvent(AgiExecEndEvent event) { } - public void handleEvent(AgiExecStartEvent event) - { + public void handleEvent(AgiExecStartEvent event) { } - public void handleEvent(AlarmClearEvent event) - { + public void handleEvent(AlarmClearEvent event) { } - public void handleEvent(AlarmEvent event) - { + public void handleEvent(AlarmEvent event) { } - public void handleEvent(BridgeEvent event) - { + public void handleEvent(BridgeEvent event) { } @SuppressWarnings("deprecation") - public void handleEvent(LinkEvent event) - { + public void handleEvent(LinkEvent event) { } @SuppressWarnings("deprecation") - public void handleEvent(UnlinkEvent event) - { + public void handleEvent(UnlinkEvent event) { } - public void handleEvent(BridgeExecEvent event) - { + public void handleEvent(BridgeExecEvent event) { } - public void handleEvent(BridgeMergeEvent event) - { + public void handleEvent(BridgeMergeEvent event) { } - public void handleEvent(CdrEvent event) - { + public void handleEvent(CdrEvent event) { } - public void handleEvent(CelEvent event) - { + public void handleEvent(CelEvent event) { } - public void handleEvent(ChallengeResponseFailedEvent event) - { + public void handleEvent(ChallengeResponseFailedEvent event) { } - public void handleEvent(ChallengeSentEvent event) - { + public void handleEvent(ChallengeSentEvent event) { } - public void handleEvent(ChannelReloadEvent event) - { + public void handleEvent(ChannelReloadEvent event) { } - public void handleEvent(ChannelUpdateEvent event) - { + public void handleEvent(ChannelUpdateEvent event) { } - public void handleEvent(ChanSpyStartEvent event) - { + public void handleEvent(ChanSpyStartEvent event) { } - public void handleEvent(ChanSpyStopEvent event) - { + public void handleEvent(ChanSpyStopEvent event) { } - public void handleEvent(ConnectEvent event) - { + public void handleEvent(ConnectEvent event) { } - public void handleEvent(ContactStatusEvent event) - { + public void handleEvent(ContactStatusEvent event) { } - public void handleEvent(DAHDIChannelEvent event) - { + public void handleEvent(DAHDIChannelEvent event) { } - public void handleEvent(DeviceStateChangeEvent event) - { + public void handleEvent(DeviceStateChangeEvent event) { } - public void handleEvent(DialEvent event) - { + public void handleEvent(DialEvent event) { } - public void handleEvent(DialBeginEvent event) - { + public void handleEvent(DialBeginEvent event) { } - public void handleEvent(DialEndEvent event) - { + public void handleEvent(DialEndEvent event) { } - public void handleEvent(DialStateEvent event) - { + public void handleEvent(DialStateEvent event) { } - public void handleEvent(DisconnectEvent event) - { + public void handleEvent(DisconnectEvent event) { } - public void handleEvent(DndStateEvent event) - { + public void handleEvent(DndStateEvent event) { } - public void handleEvent(DongleCallStateChangeEvent event) - { + public void handleEvent(DongleCallStateChangeEvent event) { } - public void handleEvent(DongleCENDEvent event) - { + public void handleEvent(DongleCENDEvent event) { } - public void handleEvent(DongleNewCMGREvent event) - { + public void handleEvent(DongleNewCMGREvent event) { } - public void handleEvent(DongleNewSMSBase64Event event) - { + public void handleEvent(DongleNewSMSBase64Event event) { } - public void handleEvent(DongleNewSMSEvent event) - { + public void handleEvent(DongleNewSMSEvent event) { } - public void handleEvent(DongleStatusEvent event) - { + public void handleEvent(DongleStatusEvent event) { } - public void handleEvent(DtmfEvent event) - { + public void handleEvent(DtmfEvent event) { } - public void handleEvent(DtmfBeginEvent event) - { + public void handleEvent(DtmfBeginEvent event) { } - public void handleEvent(DtmfEndEvent event) - { + public void handleEvent(DtmfEndEvent event) { } - public void handleEvent(ExtensionStatusEvent event) - { + public void handleEvent(ExtensionStatusEvent event) { } - public void handleEvent(FullyBootedEvent event) - { + public void handleEvent(FullyBootedEvent event) { } - public void handleEvent(HoldedCallEvent event) - { + public void handleEvent(HoldedCallEvent event) { } - public void handleEvent(InvalidPasswordEvent event) - { + public void handleEvent(InvalidPasswordEvent event) { } - public void handleEvent(JabberEventEvent event) - { + public void handleEvent(JabberEventEvent event) { } - public void handleEvent(JitterBufStatsEvent event) - { + public void handleEvent(JitterBufStatsEvent event) { } - public void handleEvent(LocalBridgeEvent event) - { + public void handleEvent(LocalBridgeEvent event) { } - public void handleEvent(LocalOptimizationBeginEvent event) - { + public void handleEvent(LocalOptimizationBeginEvent event) { } - public void handleEvent(LocalOptimizationEndEvent event) - { + public void handleEvent(LocalOptimizationEndEvent event) { } - public void handleEvent(LogChannelEvent event) - { + public void handleEvent(LogChannelEvent event) { } - public void handleEvent(MasqueradeEvent event) - { + public void handleEvent(MasqueradeEvent event) { } - public void handleEvent(MeetMeEndEvent event) - { + public void handleEvent(MeetMeEndEvent event) { } - public void handleEvent(MessageWaitingEvent event) - { + public void handleEvent(MessageWaitingEvent event) { } - public void handleEvent(ModuleLoadReportEvent event) - { + public void handleEvent(ModuleLoadReportEvent event) { } - public void handleEvent(MusicOnHoldEvent event) - { + public void handleEvent(MusicOnHoldEvent event) { } - public void handleEvent(MusicOnHoldStartEvent event) - { + public void handleEvent(MusicOnHoldStartEvent event) { } - public void handleEvent(MusicOnHoldStopEvent event) - { + public void handleEvent(MusicOnHoldStopEvent event) { } - public void handleEvent(NewAccountCodeEvent event) - { + public void handleEvent(NewAccountCodeEvent event) { } - public void handleEvent(NewConnectedLineEvent event) - { + public void handleEvent(NewConnectedLineEvent event) { } - public void handleEvent(NewExtenEvent event) - { + public void handleEvent(NewExtenEvent event) { } - public void handleEvent(PeerStatusEvent event) - { + public void handleEvent(PeerStatusEvent event) { } - public void handleEvent(PickupEvent event) - { + public void handleEvent(PickupEvent event) { } - public void handleEvent(PriEventEvent event) - { + public void handleEvent(PriEventEvent event) { } - public void handleEvent(ProtocolIdentifierReceivedEvent event) - { + public void handleEvent(ProtocolIdentifierReceivedEvent event) { } - public void handleEvent(QueueEvent event) - { + public void handleEvent(QueueEvent event) { } - public void handleEvent(JoinEvent event) - { + public void handleEvent(JoinEvent event) { } - public void handleEvent(LeaveEvent event) - { + public void handleEvent(LeaveEvent event) { } - public void handleEvent(QueueCallerAbandonEvent event) - { + public void handleEvent(QueueCallerAbandonEvent event) { } - public void handleEvent(QueueCallerJoinEvent event) - { + public void handleEvent(QueueCallerJoinEvent event) { } - public void handleEvent(QueueCallerLeaveEvent event) - { + public void handleEvent(QueueCallerLeaveEvent event) { } - public void handleEvent(QueueMemberPenaltyEvent event) - { + public void handleEvent(QueueMemberPenaltyEvent event) { } - public void handleEvent(ReceiveFaxEvent event) - { + public void handleEvent(ReceiveFaxEvent event) { } - public void handleEvent(RegistryEvent event) - { + public void handleEvent(RegistryEvent event) { } - public void handleEvent(ReloadEvent event) - { + public void handleEvent(ReloadEvent event) { } - public void handleEvent(RenameEvent event) - { + public void handleEvent(RenameEvent event) { } - public void handleEvent(ResponseEvent event) - { + public void handleEvent(ResponseEvent event) { } - public void handleEvent(AgentsCompleteEvent event) - { + public void handleEvent(AgentsCompleteEvent event) { } - public void handleEvent(AgentsEvent event) - { + public void handleEvent(AgentsEvent event) { } - public void handleEvent(AsyncAgiEvent event) - { + public void handleEvent(AsyncAgiEvent event) { } - public void handleEvent(ConfbridgeListCompleteEvent event) - { + public void handleEvent(ConfbridgeListCompleteEvent event) { } - public void handleEvent(ConfbridgeListEvent event) - { + public void handleEvent(ConfbridgeListEvent event) { } - public void handleEvent(ConfbridgeListRoomsCompleteEvent event) - { + public void handleEvent(ConfbridgeListRoomsCompleteEvent event) { } - public void handleEvent(ConfbridgeListRoomsEvent event) - { + public void handleEvent(ConfbridgeListRoomsEvent event) { } - public void handleEvent(CoreShowChannelEvent event) - { + public void handleEvent(CoreShowChannelEvent event) { } - public void handleEvent(CoreShowChannelsCompleteEvent event) - { + public void handleEvent(CoreShowChannelsCompleteEvent event) { } - public void handleEvent(DahdiShowChannelsCompleteEvent event) - { + public void handleEvent(DahdiShowChannelsCompleteEvent event) { } - public void handleEvent(DahdiShowChannelsEvent event) - { + public void handleEvent(DahdiShowChannelsEvent event) { } - public void handleEvent(DbGetResponseEvent event) - { + public void handleEvent(DbGetResponseEvent event) { } - public void handleEvent(DongleDeviceEntryEvent event) - { + public void handleEvent(DongleDeviceEntryEvent event) { } - public void handleEvent(DongleShowDevicesCompleteEvent event) - { + public void handleEvent(DongleShowDevicesCompleteEvent event) { } - public void handleEvent(EndpointList event) - { + public void handleEvent(EndpointList event) { } - public void handleEvent(EndpointListComplete event) - { + public void handleEvent(EndpointListComplete event) { } - public void handleEvent(ListDialplanEvent event) - { + public void handleEvent(ListDialplanEvent event) { } - public void handleEvent(OriginateResponseEvent event) - { + public void handleEvent(OriginateResponseEvent event) { } - public void handleEvent(ParkedCallsCompleteEvent event) - { + public void handleEvent(ParkedCallsCompleteEvent event) { } - public void handleEvent(PeerEntryEvent event) - { + public void handleEvent(PeerEntryEvent event) { } - public void handleEvent(PeerlistCompleteEvent event) - { + public void handleEvent(PeerlistCompleteEvent event) { } - public void handleEvent(PeersEvent event) - { + public void handleEvent(PeersEvent event) { } - public void handleEvent(QueueEntryEvent event) - { + public void handleEvent(QueueEntryEvent event) { } - public void handleEvent(QueueMemberEvent event) - { + public void handleEvent(QueueMemberEvent event) { } - public void handleEvent(QueueParamsEvent event) - { + public void handleEvent(QueueParamsEvent event) { } - public void handleEvent(QueueStatusCompleteEvent event) - { + public void handleEvent(QueueStatusCompleteEvent event) { } - public void handleEvent(QueueSummaryCompleteEvent event) - { + public void handleEvent(QueueSummaryCompleteEvent event) { } - public void handleEvent(QueueSummaryEvent event) - { + public void handleEvent(QueueSummaryEvent event) { } - public void handleEvent(RegistrationsCompleteEvent event) - { + public void handleEvent(RegistrationsCompleteEvent event) { } - public void handleEvent(RegistryEntryEvent event) - { + public void handleEvent(RegistryEntryEvent event) { } - public void handleEvent(ShowDialplanCompleteEvent event) - { + public void handleEvent(ShowDialplanCompleteEvent event) { } - public void handleEvent(SkypeBuddyEntryEvent event) - { + public void handleEvent(SkypeBuddyEntryEvent event) { } - public void handleEvent(SkypeBuddyListCompleteEvent event) - { + public void handleEvent(SkypeBuddyListCompleteEvent event) { } - public void handleEvent(SkypeLicenseEvent event) - { + public void handleEvent(SkypeLicenseEvent event) { } - public void handleEvent(SkypeLicenseListCompleteEvent event) - { + public void handleEvent(SkypeLicenseListCompleteEvent event) { } - public void handleEvent(StatusCompleteEvent event) - { + public void handleEvent(StatusCompleteEvent event) { } - public void handleEvent(StatusEvent event) - { + public void handleEvent(StatusEvent event) { } - public void handleEvent(VoicemailUserEntryCompleteEvent event) - { + public void handleEvent(VoicemailUserEntryCompleteEvent event) { } - public void handleEvent(VoicemailUserEntryEvent event) - { + public void handleEvent(VoicemailUserEntryEvent event) { } - public void handleEvent(ZapShowChannelsCompleteEvent event) - { + public void handleEvent(ZapShowChannelsCompleteEvent event) { } - public void handleEvent(ZapShowChannelsEvent event) - { + public void handleEvent(ZapShowChannelsEvent event) { } - public void handleEvent(ShutdownEvent event) - { + public void handleEvent(ShutdownEvent event) { } - public void handleEvent(SkypeAccountStatusEvent event) - { + public void handleEvent(SkypeAccountStatusEvent event) { } - public void handleEvent(SkypeBuddyStatusEvent event) - { + public void handleEvent(SkypeBuddyStatusEvent event) { } - public void handleEvent(SkypeChatMessageEvent event) - { + public void handleEvent(SkypeChatMessageEvent event) { } - public void handleEvent(SuccessfulAuthEvent event) - { + public void handleEvent(SuccessfulAuthEvent event) { } - public void handleEvent(TransferEvent event) - { + public void handleEvent(TransferEvent event) { } - public void handleEvent(UserEvent event) - { + public void handleEvent(UserEvent event) { } - public void handleEvent(PausedEvent event) - { + public void handleEvent(PausedEvent event) { } - public void handleEvent(UnpausedEvent event) - { + public void handleEvent(UnpausedEvent event) { } - public void handleEvent(VarSetEvent event) - { + public void handleEvent(VarSetEvent event) { } - public void handleEvent(EndpointDetail event) - { + public void handleEvent(EndpointDetail event) { } - public void handleEvent(AorDetail event) - { + public void handleEvent(AorDetail event) { } - public void handleEvent(ContactStatusDetail event) - { + public void handleEvent(ContactStatusDetail event) { } - public void handleEvent(EndpointDetailComplete event) - { + public void handleEvent(EndpointDetailComplete event) { } - public void handleEvent(InvalidAccountId event) - { - } + public void handleEvent(InvalidAccountId event) { + } /** * Dispatches to the appropriate handleEvent(...) method. @@ -791,22 +611,17 @@ public void handleEvent(InvalidAccountId event) * @param event the event to handle */ @Override - public void onManagerEvent(ManagerEvent event) - { + public void onManagerEvent(ManagerEvent event) { // if this turns out to be slow, we could consider caching the // reflection lookup - try - { + try { Method method = this.getClass().getMethod("handleEvent", event.getClass()); - if (method != null) - { + if (method != null) { method.invoke(this, event); return; } - } - catch (Exception e) - { + } catch (Exception e) { LOGGER.error(e, e); } diff --git a/src/main/java/org/asteriskjava/manager/AsteriskMapping.java b/src/main/java/org/asteriskjava/manager/AsteriskMapping.java index 55d2e1ce9..aa4287c34 100644 --- a/src/main/java/org/asteriskjava/manager/AsteriskMapping.java +++ b/src/main/java/org/asteriskjava/manager/AsteriskMapping.java @@ -1,12 +1,12 @@ package org.asteriskjava.manager; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - /** * Customized the mapping to Asterisk. In general the mapping is done implicitly based * on reflection but there are certain action that are using headers with specical @@ -17,7 +17,6 @@ */ @Target({METHOD, FIELD}) @Retention(RUNTIME) -public @interface AsteriskMapping -{ +public @interface AsteriskMapping { String value(); -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/AuthenticationFailedException.java b/src/main/java/org/asteriskjava/manager/AuthenticationFailedException.java index f74a5481d..06c71a4f3 100644 --- a/src/main/java/org/asteriskjava/manager/AuthenticationFailedException.java +++ b/src/main/java/org/asteriskjava/manager/AuthenticationFailedException.java @@ -19,12 +19,11 @@ /** * An AuthenticationFailedException is thrown when a login fails due to an incorrect username and/or * password. - * + * * @author srt * @version $Id$ */ -public class AuthenticationFailedException extends Exception -{ +public class AuthenticationFailedException extends Exception { /** * Serializable version identifier */ @@ -32,22 +31,20 @@ public class AuthenticationFailedException extends Exception /** * Creates a new AuthenticationFailedException with the given message. - * + * * @param message message describing the authentication failure */ - public AuthenticationFailedException(final String message) - { + public AuthenticationFailedException(final String message) { super(message); } /** * Creates a new AuthenticationFailedException with the given message and cause. - * + * * @param message message describing the authentication failure - * @param cause exception that caused the authentication failure + * @param cause exception that caused the authentication failure */ - public AuthenticationFailedException(final String message, final Throwable cause) - { + public AuthenticationFailedException(final String message, final Throwable cause) { super(message, cause); } } diff --git a/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java b/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java index 18b65fc4c..e7c10501e 100644 --- a/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/DefaultManagerConnection.java @@ -16,10 +16,6 @@ */ package org.asteriskjava.manager; -import java.io.IOException; -import java.net.InetAddress; -import java.nio.charset.Charset; - import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.action.EventGeneratingAction; import org.asteriskjava.manager.action.ManagerAction; @@ -27,6 +23,10 @@ import org.asteriskjava.manager.internal.ManagerConnectionImpl; import org.asteriskjava.manager.response.ManagerResponse; +import java.io.IOException; +import java.net.InetAddress; +import java.nio.charset.Charset; + /** * Default implemention of the * {@link org.asteriskjava.manager.ManagerConnection} interface. @@ -43,19 +43,17 @@ * data from Asterisk once it is * {@link org.asteriskjava.manager.ManagerConnectionState#CONNECTING}. * - * @see org.asteriskjava.manager.ManagerConnectionFactory * @author srt * @version $Id$ + * @see org.asteriskjava.manager.ManagerConnectionFactory */ -public class DefaultManagerConnection implements ManagerConnection -{ +public class DefaultManagerConnection implements ManagerConnection { private ManagerConnectionImpl impl; /** * Creates a new instance. */ - public DefaultManagerConnection() - { + public DefaultManagerConnection() { this.impl = new ManagerConnectionImpl(); } @@ -67,8 +65,7 @@ public DefaultManagerConnection() * @param username the username to use for login * @param password the password to use for login */ - public DefaultManagerConnection(String hostname, String username, String password) - { + public DefaultManagerConnection(String hostname, String username, String password) { this(); impl.setHostname(hostname); impl.setUsername(username); @@ -79,13 +76,12 @@ public DefaultManagerConnection(String hostname, String username, String passwor * Creates a new instance with the given connection parameters. * * @param hostname the hostname of the Asterisk server to connect to. - * @param port the port where Asterisk listens for incoming Manager API - * connections, usually 5038. + * @param port the port where Asterisk listens for incoming Manager API + * connections, usually 5038. * @param username the username to use for login * @param password the password to use for login */ - public DefaultManagerConnection(String hostname, int port, String username, String password) - { + public DefaultManagerConnection(String hostname, int port, String username, String password) { this(); impl.setHostname(hostname); impl.setPort(port); @@ -100,8 +96,7 @@ public DefaultManagerConnection(String hostname, int port, String username, Stri * * @param hostname the hostname to connect to */ - public void setHostname(String hostname) - { + public void setHostname(String hostname) { impl.setHostname(hostname); } @@ -113,8 +108,7 @@ public void setHostname(String hostname) * * @param port the port to connect to */ - public void setPort(int port) - { + public void setPort(int port) { impl.setPort(port); } @@ -127,8 +121,7 @@ public void setPort(int port) * false for a plain text connection. * @since 0.3 */ - public void setSsl(boolean ssl) - { + public void setSsl(boolean ssl) { impl.setSsl(ssl); } @@ -138,8 +131,7 @@ public void setSsl(boolean ssl) * * @param username the username to use for login */ - public void setUsername(String username) - { + public void setUsername(String username) { impl.setUsername(username); } @@ -149,14 +141,12 @@ public void setUsername(String username) * * @param password the password to use for login */ - public void setPassword(String password) - { + public void setPassword(String password) { impl.setPassword(password); } @Override - public void setEncoding(Charset encoding) - { + public void setEncoding(Charset encoding) { impl.setEncoding(encoding); } @@ -171,8 +161,7 @@ public void setEncoding(Charset encoding) * @deprecated use {@link #setDefaultResponseTimeout(long)} instead */ @Deprecated - public void setDefaultTimeout(long defaultTimeout) - { + public void setDefaultTimeout(long defaultTimeout) { impl.setDefaultResponseTimeout(defaultTimeout); } @@ -186,8 +175,7 @@ public void setDefaultTimeout(long defaultTimeout) * @param defaultResponseTimeout default response timeout in milliseconds * @since 0.2 */ - public void setDefaultResponseTimeout(long defaultResponseTimeout) - { + public void setDefaultResponseTimeout(long defaultResponseTimeout) { impl.setDefaultResponseTimeout(defaultResponseTimeout); } @@ -201,8 +189,7 @@ public void setDefaultResponseTimeout(long defaultResponseTimeout) * @param defaultEventTimeout default event timeout in milliseconds * @since 0.2 */ - public void setDefaultEventTimeout(long defaultEventTimeout) - { + public void setDefaultEventTimeout(long defaultEventTimeout) { impl.setDefaultEventTimeout(defaultEventTimeout); } @@ -212,11 +199,10 @@ public void setDefaultEventTimeout(long defaultEventTimeout) * It does nothing. * * @deprecated no longer needed as we now use an interrupt based response - * checking approach. + * checking approach. */ @Deprecated - public void setSleepTime(long sleepTime) - { + public void setSleepTime(long sleepTime) { } @@ -226,161 +212,132 @@ public void setSleepTime(long sleepTime) *

    * Default is true. */ - public void setKeepAliveAfterAuthenticationFailure(boolean keepAliveAfterAuthenticationFailure) - { + public void setKeepAliveAfterAuthenticationFailure(boolean keepAliveAfterAuthenticationFailure) { impl.setKeepAliveAfterAuthenticationFailure(keepAliveAfterAuthenticationFailure); } /* Implementation of ManagerConnection interface */ - public String getHostname() - { + public String getHostname() { return impl.getHostname(); } - public int getPort() - { + public int getPort() { return impl.getPort(); } - public String getUsername() - { + public String getUsername() { return impl.getUsername(); } - public String getPassword() - { + public String getPassword() { return impl.getPassword(); } @Override - public Charset getEncoding() - { + public Charset getEncoding() { return impl.getEncoding(); } - public AsteriskVersion getVersion() - { + public AsteriskVersion getVersion() { return impl.getVersion(); } - public boolean isSsl() - { + public boolean isSsl() { return impl.isSsl(); } - public InetAddress getLocalAddress() - { + public InetAddress getLocalAddress() { return impl.getLocalAddress(); } - public int getLocalPort() - { + public int getLocalPort() { return impl.getLocalPort(); } - public InetAddress getRemoteAddress() - { + public InetAddress getRemoteAddress() { return impl.getRemoteAddress(); } - public int getRemotePort() - { + public int getRemotePort() { return impl.getRemotePort(); } - public void registerUserEventClass(Class< ? extends ManagerEvent> userEventClass) - { + public void registerUserEventClass(Class userEventClass) { impl.registerUserEventClass(userEventClass); } - public void setSocketTimeout(int socketTimeout) - { + public void setSocketTimeout(int socketTimeout) { impl.setSocketTimeout(socketTimeout); } - public void setSocketReadTimeout(int socketReadTimeout) - { + public void setSocketReadTimeout(int socketReadTimeout) { impl.setSocketReadTimeout(socketReadTimeout); } - public void login() throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException - { + public void login() throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException { impl.login(); } public void login(String events) - throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException - { + throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException { impl.login(events); } - public void logoff() throws IllegalStateException - { + public void logoff() throws IllegalStateException { impl.logoff(); } public ManagerResponse sendAction(ManagerAction action) - throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException - { + throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException { return impl.sendAction(action); } public ManagerResponse sendAction(ManagerAction action, long timeout) - throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException - { + throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException { return impl.sendAction(action, timeout); } public void sendAction(ManagerAction action, SendActionCallback callbackHandler) - throws IOException, IllegalArgumentException, IllegalStateException - { + throws IOException, IllegalArgumentException, IllegalStateException { impl.sendAction(action, callbackHandler); } public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) - throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException - { + throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException { return impl.sendEventGeneratingAction(action); } public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long timeout) - throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException - { + throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException { return impl.sendEventGeneratingAction(action, timeout); } @Override public void sendEventGeneratingAction(EventGeneratingAction action, - SendEventGeneratingActionCallback callback) - throws IOException, IllegalArgumentException, IllegalStateException - { + SendEventGeneratingActionCallback callback) + throws IOException, IllegalArgumentException, IllegalStateException { impl.sendEventGeneratingAction(action, callback); } - public void addEventListener(final ManagerEventListener listener) - { + public void addEventListener(final ManagerEventListener listener) { impl.addEventListener(listener); } - public void removeEventListener(final ManagerEventListener listener) - { + public void removeEventListener(final ManagerEventListener listener) { impl.removeEventListener(listener); } - public String getProtocolIdentifier() - { + public String getProtocolIdentifier() { return impl.getProtocolIdentifier(); } - public ManagerConnectionState getState() - { + public ManagerConnectionState getState() { return impl.getState(); } @Override - public String toString() - { + public String toString() { final StringBuilder sb = new StringBuilder("DefaultManagerConnection["); sb.append("hostname='").append(getHostname()).append("',"); sb.append("port=").append(getPort()).append("]"); @@ -388,8 +345,7 @@ public String toString() } @Override - public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) - { + public void deregisterEventClass(Class eventClass) { impl.deregisterEventClass(eventClass); } diff --git a/src/main/java/org/asteriskjava/manager/EventTimeoutException.java b/src/main/java/org/asteriskjava/manager/EventTimeoutException.java index 8da0c19e7..5142b9cc2 100644 --- a/src/main/java/org/asteriskjava/manager/EventTimeoutException.java +++ b/src/main/java/org/asteriskjava/manager/EventTimeoutException.java @@ -21,13 +21,12 @@ * ResponseEvents are not completely received within the expected time period.

    * This exception allows you to retrieve the partial result, that is the events * that have been successfully received before the timeout occured. - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class EventTimeoutException extends TimeoutException -{ +public class EventTimeoutException extends TimeoutException { /** * Serial version identifier. */ @@ -37,13 +36,12 @@ public class EventTimeoutException extends TimeoutException /** * Creates a new EventTimeoutException with the given message and partial * result. - * - * @param message message with details about the timeout. + * + * @param message message with details about the timeout. * @param partialResult the ResponseEvents object filled with the parts that - * have been received before the timeout occured. + * have been received before the timeout occured. */ - public EventTimeoutException(String message, ResponseEvents partialResult) - { + public EventTimeoutException(String message, ResponseEvents partialResult) { super(message); this.partialResult = partialResult; } @@ -55,13 +53,12 @@ public EventTimeoutException(String message, ResponseEvents partialResult) * wherever possible. This is only a hack to handle those versions of * Asterisk that don't follow the Manager API conventions, for example by * not sending the correct ActionCompleteEvent. - * + * * @return the ResponseEvents object filled with the parts that have been - * received before the timeout occured. Note: The response attribute - * may be null when no response has been received. + * received before the timeout occured. Note: The response attribute + * may be null when no response has been received. */ - public ResponseEvents getPartialResult() - { + public ResponseEvents getPartialResult() { return partialResult; } } diff --git a/src/main/java/org/asteriskjava/manager/ExpectedResponse.java b/src/main/java/org/asteriskjava/manager/ExpectedResponse.java index 06bd2cda2..da5c836c6 100644 --- a/src/main/java/org/asteriskjava/manager/ExpectedResponse.java +++ b/src/main/java/org/asteriskjava/manager/ExpectedResponse.java @@ -1,12 +1,12 @@ package org.asteriskjava.manager; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; +import org.asteriskjava.manager.response.ManagerResponse; import java.lang.annotation.Retention; import java.lang.annotation.Target; -import org.asteriskjava.manager.response.ManagerResponse; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * Indicates that an annotated {@link org.asteriskjava.manager.action.ManagerAction} expects @@ -17,7 +17,6 @@ */ @Target(TYPE) @Retention(RUNTIME) -public @interface ExpectedResponse -{ +public @interface ExpectedResponse { Class value(); } diff --git a/src/main/java/org/asteriskjava/manager/ManagerConnection.java b/src/main/java/org/asteriskjava/manager/ManagerConnection.java index 82cac30c9..1fdbc8e42 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerConnection.java +++ b/src/main/java/org/asteriskjava/manager/ManagerConnection.java @@ -16,16 +16,16 @@ */ package org.asteriskjava.manager; -import java.io.IOException; -import java.net.InetAddress; -import java.nio.charset.Charset; - import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.action.EventGeneratingAction; import org.asteriskjava.manager.action.ManagerAction; import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.response.ManagerResponse; +import java.io.IOException; +import java.net.InetAddress; +import java.nio.charset.Charset; + /** * The main interface to talk to an Asterisk server via the Asterisk Manager * API. @@ -43,12 +43,11 @@ * A concrete implementation of this interface can be obtained from a * {@link org.asteriskjava.manager.ManagerConnectionFactory}. * - * @see org.asteriskjava.manager.ManagerConnectionFactory * @author srt * @version $Id$ + * @see org.asteriskjava.manager.ManagerConnectionFactory */ -public interface ManagerConnection -{ +public interface ManagerConnection { /** * Returns the hostname of the connected Asterisk server. * @@ -115,7 +114,7 @@ public interface ManagerConnection * Default is false. * * @return true if SSL is used for the connection, - * false for a plain text connection. + * false for a plain text connection. * @since 0.3 */ boolean isSsl(); @@ -172,11 +171,11 @@ public interface ManagerConnection * * @param userEventClass the class representing the user event to register. * @throws IllegalArgumentException if userEventClass is not a valid event - * class. + * class. * @see org.asteriskjava.manager.event.UserEvent * @see ManagerEvent */ - void registerUserEventClass(Class< ? extends ManagerEvent> userEventClass); + void registerUserEventClass(Class userEventClass); /** * The timeout to use when connecting the the Asterisk server. @@ -202,19 +201,20 @@ public interface ManagerConnection * Default is 0, that is no read timeout. * * @param socketReadTimeout the read timeout value to be used in - * milliseconds. + * milliseconds. * @see java.net.Socket#setSoTimeout(int) * @since 0.3 */ void setSocketReadTimeout(int socketReadTimeout); + /** * Set to true to try reconnecting to ther asterisk serve even * if the reconnection attempt threw an AuthenticationFailedException.
    * Default is true. * * @param keepAliveAfterAuthenticationFailure true to try - * reconnecting to ther asterisk serve even if the reconnection attempt - * threw an AuthenticationFailedException, false otherwise. + * reconnecting to ther asterisk serve even if the reconnection attempt + * threw an AuthenticationFailedException, false otherwise. */ void setKeepAliveAfterAuthenticationFailure(boolean keepAliveAfterAuthenticationFailure); @@ -222,13 +222,13 @@ public interface ManagerConnection * Logs in to the Asterisk server with the username and password specified * when this connection was created. * - * @throws IllegalStateException if connection is not in state INITIAL or - * DISCONNECTED. - * @throws IOException if the network connection is disrupted. + * @throws IllegalStateException if connection is not in state INITIAL or + * DISCONNECTED. + * @throws IOException if the network connection is disrupted. * @throws AuthenticationFailedException if the username and/or password are - * incorrect or the ChallengeResponse could not be built. - * @throws TimeoutException if a timeout occurs while waiting for the - * protocol identifier. The connection is closed in this case. + * incorrect or the ChallengeResponse could not be built. + * @throws TimeoutException if a timeout occurs while waiting for the + * protocol identifier. The connection is closed in this case. * @see org.asteriskjava.manager.action.LoginAction * @see org.asteriskjava.manager.action.ChallengeAction */ @@ -239,19 +239,19 @@ public interface ManagerConnection * when this connection was created and a given event mask. * * @param events the event mask. Set to "on" if all events should be send, - * "off" if not events should be sent or a combination of - * "system", "call" and "log" (separated by ',') to specify what - * kind of events should be sent. - * @throws IllegalStateException if connection is not in state INITIAL or - * DISCONNECTED. - * @throws IOException if the network connection is disrupted. + * "off" if not events should be sent or a combination of + * "system", "call" and "log" (separated by ',') to specify what + * kind of events should be sent. + * @throws IllegalStateException if connection is not in state INITIAL or + * DISCONNECTED. + * @throws IOException if the network connection is disrupted. * @throws AuthenticationFailedException if the username and/or password are - * incorrect or the ChallengeResponse could not be built. - * @throws TimeoutException if a timeout occurs while waiting for the - * protocol identifier. The connection is closed in this case. - * @since 0.3 + * incorrect or the ChallengeResponse could not be built. + * @throws TimeoutException if a timeout occurs while waiting for the + * protocol identifier. The connection is closed in this case. * @see org.asteriskjava.manager.action.LoginAction * @see org.asteriskjava.manager.action.ChallengeAction + * @since 0.3 */ void login(String events) throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException; @@ -268,7 +268,7 @@ public interface ManagerConnection * Manager/1.0". * * @return the protocol identifier of the Asterisk Manager Interface in use - * if it has already been received; null otherwise + * if it has already been received; null otherwise */ String getProtocolIdentifier(); @@ -285,12 +285,12 @@ public interface ManagerConnection * * @param action the action to send to the Asterisk server * @return the corresponding response received from the Asterisk server - * @throws IOException if the network connection is disrupted. - * @throws TimeoutException if no response is received within the default - * timeout period. + * @throws IOException if the network connection is disrupted. + * @throws TimeoutException if no response is received within the default + * timeout period. * @throws IllegalArgumentException if the action is null. - * @throws IllegalStateException if you are not connected to an Asterisk - * server. + * @throws IllegalStateException if you are not connected to an Asterisk + * server. * @see #sendAction(ManagerAction, long) * @see #sendAction(ManagerAction, SendActionCallback) */ @@ -301,16 +301,16 @@ ManagerResponse sendAction(ManagerAction action) * Sends a ManagerAction to the Asterisk server and waits for the * corresponding {@link ManagerResponse}. * - * @param action the action to send to the Asterisk server + * @param action the action to send to the Asterisk server * @param timeout milliseconds to wait for the response before throwing a - * TimeoutException + * TimeoutException * @return the corresponding response received from the Asterisk server - * @throws IOException if the network connection is disrupted. - * @throws TimeoutException if no response is received within the given - * timeout period. + * @throws IOException if the network connection is disrupted. + * @throws TimeoutException if no response is received within the given + * timeout period. * @throws IllegalArgumentException if the action is null. - * @throws IllegalStateException if you are not connected to an Asterisk - * server. + * @throws IllegalStateException if you are not connected to an Asterisk + * server. * @see #sendAction(ManagerAction, SendActionCallback) */ ManagerResponse sendAction(ManagerAction action, long timeout) @@ -324,14 +324,14 @@ ManagerResponse sendAction(ManagerAction action, long timeout) * the reader thread which is blocked for the time it takes to execute your * callbackHandler. * - * @param action the action to send to the Asterisk server + * @param action the action to send to the Asterisk server * @param callback the callback handler to call when the response is - * received or null if you are not interested in the - * response - * @throws IOException if the network connection is disrupted. + * received or null if you are not interested in the + * response + * @throws IOException if the network connection is disrupted. * @throws IllegalArgumentException if the action is null. - * @throws IllegalStateException if you are not connected to the Asterisk - * server. + * @throws IllegalStateException if you are not connected to the Asterisk + * server. */ void sendAction(ManagerAction action, SendActionCallback callback) throws IOException, IllegalArgumentException, IllegalStateException; @@ -356,16 +356,16 @@ void sendAction(ManagerAction action, SendActionCallback callback) * * @param action the action to send to the Asterisk server * @return a ResponseEvents that contains the corresponding response and - * response events received from the Asterisk server - * @throws IOException if the network connection is disrupted. - * @throws EventTimeoutException if no response or not all response events - * are received within the given timeout period. + * response events received from the Asterisk server + * @throws IOException if the network connection is disrupted. + * @throws EventTimeoutException if no response or not all response events + * are received within the given timeout period. * @throws IllegalArgumentException if the action is null, the - * actionCompleteEventClass property of the action is - * null or if actionCompleteEventClass is not a - * ResponseEvent. - * @throws IllegalStateException if you are not connected to an Asterisk - * server. + * actionCompleteEventClass property of the action is + * null or if actionCompleteEventClass is not a + * ResponseEvent. + * @throws IllegalStateException if you are not connected to an Asterisk + * server. * @see EventGeneratingAction * @see org.asteriskjava.manager.event.ResponseEvent * @since 0.2 @@ -392,20 +392,20 @@ ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) * {@link org.asteriskjava.manager.action.QueueStatusAction} or the * {@link org.asteriskjava.manager.action.AgentsAction}. * - * @param action the action to send to the Asterisk server + * @param action the action to send to the Asterisk server * @param timeout milliseconds to wait for the response and the action - * complete event before throwing a TimeoutException + * complete event before throwing a TimeoutException * @return a ResponseEvents that contains the corresponding response and - * response events received from the Asterisk server - * @throws IOException if the network connection is disrupted. - * @throws EventTimeoutException if no response or not all response events - * are received within the given timeout period. + * response events received from the Asterisk server + * @throws IOException if the network connection is disrupted. + * @throws EventTimeoutException if no response or not all response events + * are received within the given timeout period. * @throws IllegalArgumentException if the action is null, the - * actionCompleteEventClass property of the action is - * null or if actionCompleteEventClass is not a - * ResponseEvent. - * @throws IllegalStateException if you are not connected to an Asterisk - * server. + * actionCompleteEventClass property of the action is + * null or if actionCompleteEventClass is not a + * ResponseEvent. + * @throws IllegalStateException if you are not connected to an Asterisk + * server. * @see EventGeneratingAction * @see org.asteriskjava.manager.event.ResponseEvent * @since 0.2 @@ -426,7 +426,8 @@ ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long time void sendEventGeneratingAction( EventGeneratingAction action, SendEventGeneratingActionCallback callback) - throws IOException, IllegalArgumentException, IllegalStateException; + throws IOException, IllegalArgumentException, IllegalStateException; + /** * Registers an event listener that is called whenever an * {@link org.asteriskjava.manager.event.ManagerEvent} is receiced from the @@ -436,7 +437,7 @@ void sendEventGeneratingAction( * were registered. * * @param eventListener the listener to call whenever a manager event is - * received + * received * @see #removeEventListener(ManagerEventListener) */ void addEventListener(ManagerEventListener eventListener); @@ -451,5 +452,5 @@ void sendEventGeneratingAction( */ void removeEventListener(ManagerEventListener eventListener); - void deregisterEventClass(Class< ? extends ManagerEvent> eventClass); + void deregisterEventClass(Class eventClass); } diff --git a/src/main/java/org/asteriskjava/manager/ManagerConnectionFactory.java b/src/main/java/org/asteriskjava/manager/ManagerConnectionFactory.java index 7672b35df..9417c96bd 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerConnectionFactory.java +++ b/src/main/java/org/asteriskjava/manager/ManagerConnectionFactory.java @@ -17,11 +17,11 @@ package org.asteriskjava.manager; /** - * This factory is the canonical way to obtain new + * This factory is the canonical way to obtain new * {@link org.asteriskjava.manager.ManagerConnection}s.

    - * It creates new connections in state + * It creates new connections in state * {@link org.asteriskjava.manager.ManagerConnectionState#INITIAL}. Before - * you can start using such a connection (i.e. sending + * you can start using such a connection (i.e. sending * {@link org.asteriskjava.manager.action.ManagerAction}s you must * {@link org.asteriskjava.manager.ManagerConnection#login()} to change its state * to {@link org.asteriskjava.manager.ManagerConnectionState#CONNECTED}.

    @@ -29,7 +29,7 @@ *

      * ManagerConnectionFactory factory;
      * ManagerConnection connection;
    - * 
    + *
      * factory = new ManagerConnectionFactory("localhost", "manager", "secret");
      * connection = factory.createManagerConnection();
      * connection.login();
    @@ -38,13 +38,12 @@
      * 
    * If want you can use the factory to create multiple connections to the same * server by calling {@link #createManagerConnection()} multiple times.

    - * - * @see org.asteriskjava.manager.ManagerConnection + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.ManagerConnection */ -public class ManagerConnectionFactory -{ +public class ManagerConnectionFactory { private static final int DEFAULT_PORT = 5038; private final String hostname; @@ -55,14 +54,13 @@ public class ManagerConnectionFactory /** * Creates a new ManagerConnectionFactory with the given connection data and * the default port 5038. - * + * * @param hostname the hostname of the Asterisk server to connect to. * @param username the username to use for login as defined in Asterisk's manager.conf. * @param password the password to use for login as defined in Asterisk's manager.conf. * @since 0.3 */ - public ManagerConnectionFactory(String hostname, String username, String password) - { + public ManagerConnectionFactory(String hostname, String username, String password) { this.hostname = hostname; this.port = DEFAULT_PORT; this.username = username; @@ -71,16 +69,15 @@ public ManagerConnectionFactory(String hostname, String username, String passwor /** * Creates a new ManagerConnectionFactory with the given connection data. - * + * * @param hostname the hostname of the Asterisk server to connect to. - * @param port the port where Asterisk listens for incoming Manager API - * connections, usually 5038. + * @param port the port where Asterisk listens for incoming Manager API + * connections, usually 5038. * @param username the username to use for login as defined in Asterisk's manager.conf. * @param password the password to use for login as defined in Asterisk's manager.conf. * @since 0.3 */ - public ManagerConnectionFactory(String hostname, int port, String username, String password) - { + public ManagerConnectionFactory(String hostname, int port, String username, String password) { this.hostname = hostname; this.port = port; this.username = username; @@ -89,23 +86,21 @@ public ManagerConnectionFactory(String hostname, int port, String username, Stri /** * Returns a new ManagerConnection in state {@link ManagerConnectionState#CONNECTED}. - * + * * @return the created connection to the Asterisk server. * @since 0.3 */ - public ManagerConnection createManagerConnection() - { + public ManagerConnection createManagerConnection() { return new DefaultManagerConnection(hostname, port, username, password); } /** * Returns a new SSL secured ManagerConnection in state {@link ManagerConnectionState#CONNECTED}. - * + * * @return the created connection to the Asterisk server. * @since 0.3 */ - public ManagerConnection createSecureManagerConnection() - { + public ManagerConnection createSecureManagerConnection() { DefaultManagerConnection dmc; dmc = new DefaultManagerConnection(hostname, port, username, password); dmc.setSsl(true); diff --git a/src/main/java/org/asteriskjava/manager/ManagerConnectionState.java b/src/main/java/org/asteriskjava/manager/ManagerConnectionState.java index 4ec1209ad..ea058e109 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerConnectionState.java +++ b/src/main/java/org/asteriskjava/manager/ManagerConnectionState.java @@ -2,12 +2,11 @@ /** * The lifecycle status of a {@link org.asteriskjava.manager.ManagerConnection}. - * + * * @author srt * @since 0.3 */ -public enum ManagerConnectionState -{ +public enum ManagerConnectionState { /** * The initial state after the ManagerConnection object has been created * but the connection has not yet been established.

    @@ -15,14 +14,14 @@ public enum ManagerConnectionState * is called. */ INITIAL, - + /** * The connection is being made and login is performed.

    * Changes to {@link #CONNECTED} when login has successfully completed or - * {@link #DISCONNECTED} if login fails. + * {@link #DISCONNECTED} if login fails. */ CONNECTING, - + /** * The connection has been successfully established, login has been perfomed and * the connection is ready to be used.

    @@ -31,7 +30,7 @@ public enum ManagerConnectionState * when {@link org.asteriskjava.manager.ManagerConnection#logoff()} is called. */ CONNECTED, - + /** * The connection has been disrupted and is about to be reestablished.

    * Changes to {@link #CONNECTED} when connection is successfully reestablished or @@ -39,16 +38,16 @@ public enum ManagerConnectionState * is called. */ RECONNECTING, - + /** * The connection is about to be closed by user request.

    * Changes to {@link #DISCONNECTED} when connection has been closed. */ DISCONNECTING, - + /** * The connection has been closed on user's request is not about to be reestablished.

    - * Can be changed to {@link #CONNECTING} by calling + * Can be changed to {@link #CONNECTING} by calling * {@link org.asteriskjava.manager.ManagerConnection#login()}. */ DISCONNECTED diff --git a/src/main/java/org/asteriskjava/manager/ManagerEventListener.java b/src/main/java/org/asteriskjava/manager/ManagerEventListener.java index 33ac2f9a6..bc829999e 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/ManagerEventListener.java @@ -16,23 +16,22 @@ */ package org.asteriskjava.manager; -import java.util.EventListener; - import org.asteriskjava.manager.event.ManagerEvent; +import java.util.EventListener; + /** * An interface to listen for events received from an Asterisk server. - * - * @see org.asteriskjava.manager.event.ManagerEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.ManagerEvent */ -public interface ManagerEventListener extends EventListener -{ +public interface ManagerEventListener extends EventListener { /** * This method is called when an event is received. - * + * * @param event the event that has been received */ void onManagerEvent(ManagerEvent event); diff --git a/src/main/java/org/asteriskjava/manager/ManagerEventListenerProxy.java b/src/main/java/org/asteriskjava/manager/ManagerEventListenerProxy.java index 2813cfbba..12050c8e8 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerEventListenerProxy.java +++ b/src/main/java/org/asteriskjava/manager/ManagerEventListenerProxy.java @@ -1,14 +1,10 @@ package org.asteriskjava.manager; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.util.DaemonThreadFactory; +import java.util.concurrent.*; + /** * Proxies a ManagerEventListener and dispatches events asynchronously by using * a single threaded executor.

    @@ -27,38 +23,40 @@ * ... * connection.addEventListener(new ManagerEventListenerProxy(myListener)); * - * + * * @author srt * @author fink * @since 0.3 */ public class ManagerEventListenerProxy implements ManagerEventListener { - private final ThreadPoolExecutor executor; + private final ThreadPoolExecutor executor; private final ManagerEventListener target; /** * Creates a new ManagerEventListenerProxy that notifies the given target * asynchronously when new events are received. - * + * * @param target the target listener to invoke. * @see Executors#newSingleThreadExecutor(ThreadFactory) */ public ManagerEventListenerProxy(ManagerEventListener target) { - executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new DaemonThreadFactory()); - this.target = target; - if (target == null) { - throw new NullPointerException("ManagerEventListener target is null!"); - } + executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new DaemonThreadFactory()); + this.target = target; + if (target == null) { + throw new NullPointerException("ManagerEventListener target is null!"); + } }//new - @Override public void onManagerEvent(final ManagerEvent event) { - executor.execute(new Runnable() { - @Override public void run() { - target.onManagerEvent(event); - } - }); + @Override + public void onManagerEvent(final ManagerEvent event) { + executor.execute(new Runnable() { + @Override + public void run() { + target.onManagerEvent(event); + } + }); }//onManagerEvent @@ -66,13 +64,13 @@ public void shutdown() { executor.shutdown(); } - public static class Access { - private Access() { - - } - - public static int getThreadQueueSize (ManagerEventListenerProxy proxy) { - return proxy.executor.getQueue().size(); - } - }//Access + public static class Access { + private Access() { + + } + + public static int getThreadQueueSize(ManagerEventListenerProxy proxy) { + return proxy.executor.getQueue().size(); + } + }//Access } diff --git a/src/main/java/org/asteriskjava/manager/PingThread.java b/src/main/java/org/asteriskjava/manager/PingThread.java index 3ff4f1b86..862f882be 100644 --- a/src/main/java/org/asteriskjava/manager/PingThread.java +++ b/src/main/java/org/asteriskjava/manager/PingThread.java @@ -16,9 +16,6 @@ */ package org.asteriskjava.manager; -import java.util.HashSet; -import java.util.concurrent.atomic.AtomicLong; - import org.asteriskjava.lock.LockableSet; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.PingAction; @@ -26,6 +23,9 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.HashSet; +import java.util.concurrent.atomic.AtomicLong; + /** * A Thread that pings the Asterisk server at a given interval. You can use this * to prevent the connection being shut down when there is no traffic. @@ -36,8 +36,7 @@ * @author srt * @version $Id$ */ -public class PingThread extends Thread -{ +public class PingThread extends Thread { private static final long DEFAULT_INTERVAL = 20 * 1000L; private static final long DEFAULT_TIMEOUT = 0L; private static final AtomicLong idCounter = new AtomicLong(0); @@ -58,8 +57,7 @@ public class PingThread extends Thread * * @since 1.0.0 */ - public PingThread() - { + public PingThread() { super(); this.connections = new LockableSet<>(new HashSet<>()); this.die = false; @@ -73,8 +71,7 @@ public PingThread() * * @param connection ManagerConnection that is pinged */ - public PingThread(ManagerConnection connection) - { + public PingThread(ManagerConnection connection) { this(); this.connections.add(connection); } @@ -85,8 +82,7 @@ public PingThread(ManagerConnection connection) * * @param interval the interval in milliseconds */ - public void setInterval(long interval) - { + public void setInterval(long interval) { this.interval = interval; } @@ -100,8 +96,7 @@ public void setInterval(long interval) * @param timeout the timeout in milliseconds or 0 to indicate no timeout. * @since 0.3 */ - public void setTimeout(long timeout) - { + public void setTimeout(long timeout) { this.timeout = timeout; } @@ -111,10 +106,8 @@ public void setTimeout(long timeout) * @param connection the connection to ping. * @since 1.0.0 */ - public void addConnection(ManagerConnection connection) - { - try (LockCloser closer = connections.withLock()) - { + public void addConnection(ManagerConnection connection) { + try (LockCloser closer = connections.withLock()) { connections.add(connection); } } @@ -125,10 +118,8 @@ public void addConnection(ManagerConnection connection) * @param connection the connection that will no longer be pinged. * @since 1.0.0 */ - public void removeConnection(ManagerConnection connection) - { - try (LockCloser closer = connections.withLock()) - { + public void removeConnection(ManagerConnection connection) { + try (LockCloser closer = connections.withLock()) { connections.remove(connection); } } @@ -136,39 +127,30 @@ public void removeConnection(ManagerConnection connection) /** * Terminates this PingThread. */ - public void die() - { + public void die() { this.die = true; interrupt(); } @Override - public void run() - { - while (!die) - { - try - { + public void run() { + while (!die) { + try { sleep(interval); - } - catch (InterruptedException e) // NOPMD + } catch (InterruptedException e) // NOPMD { Thread.currentThread().interrupt(); } // exit if die is set - if (die) - { + if (die) { break; } - try (LockCloser closer = connections.withLock()) - { - for (ManagerConnection c : connections) - { + try (LockCloser closer = connections.withLock()) { + for (ManagerConnection c : connections) { // skip if not connected - if (c.getState() != ManagerConnectionState.CONNECTED) - { + if (c.getState() != ManagerConnectionState.CONNECTED) { continue; } @@ -183,24 +165,17 @@ public void run() * * @param c the connection to ping. */ - protected void ping(ManagerConnection c) - { - try - { - if (timeout <= 0) - { + protected void ping(ManagerConnection c) { + try { + if (timeout <= 0) { c.sendAction(new PingAction(), null); - } - else - { + } else { final ManagerResponse response; response = c.sendAction(new PingAction(), timeout); logger.debug("Ping response '" + response + "' for " + c.toString()); } - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Exception on sending Ping to " + c.toString(), e); } } diff --git a/src/main/java/org/asteriskjava/manager/ResponseEvents.java b/src/main/java/org/asteriskjava/manager/ResponseEvents.java index 568b254fd..a271d733f 100644 --- a/src/main/java/org/asteriskjava/manager/ResponseEvents.java +++ b/src/main/java/org/asteriskjava/manager/ResponseEvents.java @@ -16,28 +16,27 @@ */ package org.asteriskjava.manager; -import java.util.Collection; - import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.manager.response.ManagerResponse; +import java.util.Collection; + /** - * Contains the result of executing an + * Contains the result of executing an * {@link org.asteriskjava.manager.action.EventGeneratingAction}, that is the - * {@link org.asteriskjava.manager.response.ManagerResponse} and any received + * {@link org.asteriskjava.manager.response.ManagerResponse} and any received * {@link org.asteriskjava.manager.event.ManagerEvent}s. - * - * @see org.asteriskjava.manager.action.EventGeneratingAction + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.EventGeneratingAction * @since 0.2 */ -public interface ResponseEvents -{ +public interface ResponseEvents { /** * Returns the response received. - * + * * @return the response received. */ ManagerResponse getResponse(); @@ -45,7 +44,7 @@ public interface ResponseEvents /** * Returns a Collection of ManagerEvents that have been received including * the last one that indicates completion. - * + * * @return a Collection of ManagerEvents received. */ Collection getEvents(); diff --git a/src/main/java/org/asteriskjava/manager/SendActionCallback.java b/src/main/java/org/asteriskjava/manager/SendActionCallback.java index 3f2f9f542..0e315621c 100644 --- a/src/main/java/org/asteriskjava/manager/SendActionCallback.java +++ b/src/main/java/org/asteriskjava/manager/SendActionCallback.java @@ -22,16 +22,15 @@ /** * Callback interface to send {@link org.asteriskjava.manager.action.ManagerAction}s * asynchronously. - * - * @see org.asteriskjava.manager.ManagerConnection#sendAction(ManagerAction, SendActionCallback) + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.ManagerConnection#sendAction(ManagerAction, SendActionCallback) */ -public interface SendActionCallback -{ +public interface SendActionCallback { /** * This method is called when a response is received. - * + * * @param response the response that has been received */ void onResponse(ManagerResponse response); diff --git a/src/main/java/org/asteriskjava/manager/SendEventGeneratingActionCallback.java b/src/main/java/org/asteriskjava/manager/SendEventGeneratingActionCallback.java index 09feda162..528e7d643 100644 --- a/src/main/java/org/asteriskjava/manager/SendEventGeneratingActionCallback.java +++ b/src/main/java/org/asteriskjava/manager/SendEventGeneratingActionCallback.java @@ -8,12 +8,11 @@ * {@link org.asteriskjava.manager.action.EventGeneratingAction} asynchronously. * * @see org.asteriskjava.manager.ManagerConnection#sendEventGeneratingAction(org.asteriskjava.manager.action.EventGeneratingAction, SendEventGeneratingActionCallback) - * + *

    * Initial response is passed to one of {@link #onResponse(ManagerResponse)} or * {@link #onErrorResponse(ManagerResponse)}. but not both. */ -public interface SendEventGeneratingActionCallback -{ +public interface SendEventGeneratingActionCallback { /** * Called to notify that * {@link ManagerConnection#sendEventGeneratingAction(org.asteriskjava.manager.action.EventGeneratingAction, SendEventGeneratingActionCallback)} @@ -24,8 +23,7 @@ public interface SendEventGeneratingActionCallback * be lacking some events including end event. The * {@link ResponseEvents#getResponse()} can also be {@link ManagerError} * - * @param responseEvents - * the response at whatever state it was when action ended. + * @param responseEvents the response at whatever state it was when action ended. */ public void onResponse(ResponseEvents responseEvents); -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/TimeoutException.java b/src/main/java/org/asteriskjava/manager/TimeoutException.java index 372df55bc..b9f26612a 100644 --- a/src/main/java/org/asteriskjava/manager/TimeoutException.java +++ b/src/main/java/org/asteriskjava/manager/TimeoutException.java @@ -19,12 +19,11 @@ /** * A TimeoutException is thrown if a ManagerResponse is not received within the * expected time period. - * + * * @author srt * @version $Id$ */ -public class TimeoutException extends Exception -{ +public class TimeoutException extends Exception { /** * Serial version identifier */ @@ -32,11 +31,10 @@ public class TimeoutException extends Exception /** * Creates a new TimeoutException with the given message. - * + * * @param message message with details about the timeout. */ - public TimeoutException(final String message) - { + public TimeoutException(final String message) { super(message); } } diff --git a/src/main/java/org/asteriskjava/manager/action/AbsoluteTimeoutAction.java b/src/main/java/org/asteriskjava/manager/action/AbsoluteTimeoutAction.java index c1ef7c3aa..eb6ec8830 100644 --- a/src/main/java/org/asteriskjava/manager/action/AbsoluteTimeoutAction.java +++ b/src/main/java/org/asteriskjava/manager/action/AbsoluteTimeoutAction.java @@ -29,12 +29,11 @@ * This action corresponds the the AbsoluteTimeout command used in the dialplan. *

    * Implemented in manager.c - * + * * @author srt * @version $Id$ */ -public class AbsoluteTimeoutAction extends AbstractManagerAction -{ +public class AbsoluteTimeoutAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -46,20 +45,18 @@ public class AbsoluteTimeoutAction extends AbstractManagerAction /** * Creates a new empty AbsoluteTimeoutAction. */ - public AbsoluteTimeoutAction() - { + public AbsoluteTimeoutAction() { } /** * Creates a new AbsoluteTimeoutAction with the given channel and timeout. - * + * * @param channel the name of the channel * @param timeout the maximum duation of the call in seconds or 0 to cancel the AbsoluteTimeout * @since 0.2 */ - public AbsoluteTimeoutAction(String channel, Integer timeout) - { + public AbsoluteTimeoutAction(String channel, Integer timeout) { this.channel = channel; this.timeout = timeout; } @@ -68,32 +65,28 @@ public AbsoluteTimeoutAction(String channel, Integer timeout) * Returns the name of this action, i.e. "AbsoluteTimeout". */ @Override - public String getAction() - { + public String getAction() { return "AbsoluteTimeout"; } /** * Returns the name of the channel. */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the the maximum duation of the call (in seconds) to set. */ - public Integer getTimeout() - { + public Integer getTimeout() { return timeout; } @@ -101,8 +94,7 @@ public Integer getTimeout() * Sets the the maximum duation of the call (in seconds) to set on channel.

    * Setting the timeout to 0 cancels the timeout. */ - public void setTimeout(Integer timeout) - { + public void setTimeout(Integer timeout) { this.timeout = timeout; } } diff --git a/src/main/java/org/asteriskjava/manager/action/AbstractManagerAction.java b/src/main/java/org/asteriskjava/manager/action/AbstractManagerAction.java index 386934f0a..7280ecda2 100644 --- a/src/main/java/org/asteriskjava/manager/action/AbstractManagerAction.java +++ b/src/main/java/org/asteriskjava/manager/action/AbstractManagerAction.java @@ -16,21 +16,20 @@ */ package org.asteriskjava.manager.action; +import org.asteriskjava.util.ReflectionUtil; + import java.lang.reflect.Method; import java.util.Map; -import org.asteriskjava.util.ReflectionUtil; - /** * This class implements the ManagerAction interface and can serve as base class * for your concrete Action implementations. - * + * * @author srt * @version $Id$ * @since 0.2 */ -public abstract class AbstractManagerAction implements ManagerAction -{ +public abstract class AbstractManagerAction implements ManagerAction { /** * Serializable version identifier. */ @@ -40,40 +39,33 @@ public abstract class AbstractManagerAction implements ManagerAction public abstract String getAction(); - public String getActionId() - { + public String getActionId() { return actionId; } - public void setActionId(String actionId) - { + public void setActionId(String actionId) { this.actionId = actionId; } @Override - public String toString() - { - StringBuilder sb; + public String toString() { + StringBuilder sb; Map getters; sb = new StringBuilder(getClass().getName() + "["); sb.append("action='").append(getAction()).append("',"); getters = ReflectionUtil.getGetters(getClass()); - for (Map.Entry entry : getters.entrySet()) - { + for (Map.Entry entry : getters.entrySet()) { final String attribute = entry.getKey(); - if ("action".equals(attribute) || "class".equals(attribute)) - { + if ("action".equals(attribute) || "class".equals(attribute)) { continue; } - try - { + try { Object value; value = entry.getValue().invoke(this); sb.append(attribute).append("='").append(value).append("',"); - } - catch (Exception e) // NOPMD + } catch (Exception e) // NOPMD { // swallow } diff --git a/src/main/java/org/asteriskjava/manager/action/AbstractMeetMeMuteAction.java b/src/main/java/org/asteriskjava/manager/action/AbstractMeetMeMuteAction.java index 515097aca..684cc562b 100644 --- a/src/main/java/org/asteriskjava/manager/action/AbstractMeetMeMuteAction.java +++ b/src/main/java/org/asteriskjava/manager/action/AbstractMeetMeMuteAction.java @@ -18,12 +18,11 @@ /** * Abstract base class for mute and unmute actions. - * + * * @author srt * @version $Id$ */ -public abstract class AbstractMeetMeMuteAction extends AbstractManagerAction -{ +public abstract class AbstractMeetMeMuteAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -32,13 +31,11 @@ public abstract class AbstractMeetMeMuteAction extends AbstractManagerAction private String meetMe; private Integer userNum; - protected AbstractMeetMeMuteAction() - { + protected AbstractMeetMeMuteAction() { super(); } - protected AbstractMeetMeMuteAction(String meetMe, Integer userNum) - { + protected AbstractMeetMeMuteAction(String meetMe, Integer userNum) { super(); this.meetMe = meetMe; this.userNum = userNum; @@ -46,43 +43,39 @@ protected AbstractMeetMeMuteAction(String meetMe, Integer userNum) /** * Returns the conference number. - * + * * @return the conference number. */ - public String getMeetMe() - { + public String getMeetMe() { return meetMe; } /** * Sets the conference number.

    * This property is mandatory. - * + * * @param meetMe the conference number. */ - public void setMeetMe(String meetMe) - { + public void setMeetMe(String meetMe) { this.meetMe = meetMe; } /** * Returns the index of the user in the conference. - * + * * @return the index of the user in the conference. */ - public Integer getUserNum() - { + public Integer getUserNum() { return userNum; } /** * Sets the index of the user in the conference.

    * This property is mandatory. - * + * * @param userNum the index of the user in the conference. */ - public void setUserNum(Integer userNum) - { + public void setUserNum(Integer userNum) { this.userNum = userNum; } } diff --git a/src/main/java/org/asteriskjava/manager/action/AgentCallbackLoginAction.java b/src/main/java/org/asteriskjava/manager/action/AgentCallbackLoginAction.java index e00cde322..10598f07e 100644 --- a/src/main/java/org/asteriskjava/manager/action/AgentCallbackLoginAction.java +++ b/src/main/java/org/asteriskjava/manager/action/AgentCallbackLoginAction.java @@ -30,8 +30,8 @@ * @since 0.2 * @deprecated use {@link org.asteriskjava.manager.action.QueueAddAction} instead. */ -@Deprecated public class AgentCallbackLoginAction extends AbstractManagerAction -{ +@Deprecated +public class AgentCallbackLoginAction extends AbstractManagerAction { /** * Serializable version identifier. */ @@ -45,8 +45,7 @@ /** * Creates a new empty AgentCallbackLoginAction. */ - public AgentCallbackLoginAction() - { + public AgentCallbackLoginAction() { } @@ -58,8 +57,7 @@ public AgentCallbackLoginAction() * @param exten the extension that is called to connect a queue member with * this agent */ - public AgentCallbackLoginAction(String agent, String exten) - { + public AgentCallbackLoginAction(String agent, String exten) { this.agent = agent; this.exten = exten; } @@ -73,8 +71,7 @@ public AgentCallbackLoginAction(String agent, String exten) * this agent * @param context the context of the extension to use for callback */ - public AgentCallbackLoginAction(String agent, String exten, String context) - { + public AgentCallbackLoginAction(String agent, String exten, String context) { this(agent, exten); this.context = context; } @@ -95,8 +92,7 @@ public AgentCallbackLoginAction(String agent, String exten, String context) * null if default should be used. * @since 1.0.0 */ - public AgentCallbackLoginAction(String agent, String exten, String context, Boolean ackCall, Long wrapupTime) - { + public AgentCallbackLoginAction(String agent, String exten, String context, Boolean ackCall, Long wrapupTime) { this(agent, exten, context); this.ackCall = ackCall; this.wrapupTime = wrapupTime; @@ -108,8 +104,7 @@ public AgentCallbackLoginAction(String agent, String exten, String context, Bool * @return the name of this action */ @Override - public String getAction() - { + public String getAction() { return "AgentCallbackLogin"; } @@ -118,8 +113,7 @@ public String getAction() * * @return the name of the agent to log in */ - public String getAgent() - { + public String getAgent() { return agent; } @@ -129,8 +123,7 @@ public String getAgent() * * @param agent the name of the agent to log in */ - public void setAgent(String agent) - { + public void setAgent(String agent) { this.agent = agent; } @@ -139,8 +132,7 @@ public void setAgent(String agent) * * @return the extension to use for callback. */ - public String getExten() - { + public String getExten() { return exten; } @@ -150,8 +142,7 @@ public String getExten() * * @param exten the extension to use for callback. */ - public void setExten(String exten) - { + public void setExten(String exten) { this.exten = exten; } @@ -160,8 +151,7 @@ public void setExten(String exten) * * @return the context of the extension to use for callback. */ - public String getContext() - { + public String getContext() { return context; } @@ -170,8 +160,7 @@ public String getContext() * * @param context the context of the extension to use for callback. */ - public void setContext(String context) - { + public void setContext(String context) { this.context = context; } @@ -179,11 +168,10 @@ public void setContext(String context) * Returns if an acknowledgement is needed when agent is called back. * * @return Boolean.TRUE if acknowledgement by '#' is required when agent is - * called back, Boolean.FALSE otherwise. null if - * default should be used. + * called back, Boolean.FALSE otherwise. null if + * default should be used. */ - public Boolean getAckCall() - { + public Boolean getAckCall() { return ackCall; } @@ -196,8 +184,7 @@ public Boolean getAckCall() * '#' when agent is called back, Boolean.FALSE otherwise. * null if default should be used. */ - public void setAckCall(Boolean ackCall) - { + public void setAckCall(Boolean ackCall) { this.ackCall = ackCall; } @@ -206,10 +193,9 @@ public void setAckCall(Boolean ackCall) * can receive a new call. * * @return the minimum amount of time after disconnecting before the caller - * can receive a new call in seconds. + * can receive a new call in seconds. */ - public Long getWrapupTime() - { + public Long getWrapupTime() { return wrapupTime; } @@ -223,8 +209,7 @@ public Long getWrapupTime() * the caller can receive a new call. * null if default should be used. */ - public void setWrapupTime(Long wrapupTime) - { + public void setWrapupTime(Long wrapupTime) { this.wrapupTime = wrapupTime; } } diff --git a/src/main/java/org/asteriskjava/manager/action/AgentLogoffAction.java b/src/main/java/org/asteriskjava/manager/action/AgentLogoffAction.java index 2ed5ba1d4..940bbe1c4 100644 --- a/src/main/java/org/asteriskjava/manager/action/AgentLogoffAction.java +++ b/src/main/java/org/asteriskjava/manager/action/AgentLogoffAction.java @@ -19,13 +19,12 @@ /** * The AgentLogoffAction sets an agent as no longer logged in.

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class AgentLogoffAction extends AbstractManagerAction -{ +public class AgentLogoffAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -36,89 +35,81 @@ public class AgentLogoffAction extends AbstractManagerAction /** * Creates a new empty AgentLogoffAction. */ - public AgentLogoffAction() - { + public AgentLogoffAction() { } /** * Creates a new AgentLogoffAction that logs off the given agent - * + * * @param agent the name of the agent to log off. */ - public AgentLogoffAction(String agent) - { + public AgentLogoffAction(String agent) { this.agent = agent; } /** * Creates a new AgentLogoffAction that logs off the given agent - * + * * @param agent the name of the agent to log off. - * @param soft Boolean.TRUE if exisiting calls should not be hung up on - * logout. + * @param soft Boolean.TRUE if exisiting calls should not be hung up on + * logout. */ - public AgentLogoffAction(String agent, Boolean soft) - { + public AgentLogoffAction(String agent, Boolean soft) { this(agent); this.soft = soft; } /** * Returns the name of this action, i.e. "AgentLogoff". - * + * * @return the name of this action */ @Override - public String getAction() - { + public String getAction() { return "AgentLogoff"; } /** * Returns the name of the agent to log off, for example "1002". - * + * * @return the name of the agent to log off */ - public String getAgent() - { + public String getAgent() { return agent; } /** * Sets the name of the agent to log off, for example "1002".

    * This is property is mandatory. - * + * * @param agent the name of the agent to log off */ - public void setAgent(String agent) - { + public void setAgent(String agent) { this.agent = agent; } /** * Returns whether to hangup existing calls or not.

    * Default is to hangup existing calls on logoff. - * + * * @return Boolean.TRUE if existing calls should not be hung up, - * Boolean.FALSE otherwise. null if default should be - * used. + * Boolean.FALSE otherwise. null if default should be + * used. */ - public Boolean getSoft() - { + public Boolean getSoft() { return soft; } /** * Sets whether existing calls should be hung up or not.

    * Default is to hangup existing calls on logoff. - * + * * @param soft Boolean.TRUE if existing calls should not be hung up, - * Boolean.FALSE otherwise. null if default should - * be used. + * Boolean.FALSE otherwise. null if default should + * be used. */ - public void setSoft(Boolean soft) - { + public void setSoft(Boolean soft) { this.soft = soft; } } diff --git a/src/main/java/org/asteriskjava/manager/action/AgentsAction.java b/src/main/java/org/asteriskjava/manager/action/AgentsAction.java index 8e2324d62..2077b93ce 100644 --- a/src/main/java/org/asteriskjava/manager/action/AgentsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/AgentsAction.java @@ -24,16 +24,14 @@ * For each agent an AgentsEvent is generated. After the state of all agents has been * reported an AgentsCompleteEvent is generated.

    * Available since Asterisk 1.2 - * - * @see org.asteriskjava.manager.event.AgentsEvent - * @see org.asteriskjava.manager.event.AgentsCompleteEvent - * + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.AgentsEvent + * @see org.asteriskjava.manager.event.AgentsCompleteEvent * @since 0.2 */ -public class AgentsAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class AgentsAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serializable version identifier */ @@ -42,22 +40,19 @@ public class AgentsAction extends AbstractManagerAction implements EventGenerati /** * Creates a new AgentsAction. */ - public AgentsAction() - { - + public AgentsAction() { + } - + /** * Returns the name of this action, i.e. "Agents". */ @Override - public String getAction() - { + public String getAction() { return "Agents"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return AgentsCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/AgiAction.java b/src/main/java/org/asteriskjava/manager/action/AgiAction.java index de2bfa66f..014cefd15 100644 --- a/src/main/java/org/asteriskjava/manager/action/AgiAction.java +++ b/src/main/java/org/asteriskjava/manager/action/AgiAction.java @@ -27,13 +27,12 @@ *
    * Available since Asterisk 1.6 * - * @see org.asteriskjava.manager.event.AsyncAgiEvent * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.AsyncAgiEvent * @since 1.0.0 */ -public class AgiAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class AgiAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serializable version identifier. */ @@ -46,8 +45,7 @@ public class AgiAction extends AbstractManagerAction implements EventGeneratingA /** * Creates a new empty AgiAction. */ - public AgiAction() - { + public AgiAction() { } @@ -57,8 +55,7 @@ public AgiAction() * @param channel the name of the channel to execute the AGI command on. * @param command the AGI command to execute. */ - public AgiAction(String channel, String command) - { + public AgiAction(String channel, String command) { this.channel = channel; this.command = command; } @@ -70,8 +67,7 @@ public AgiAction(String channel, String command) * @param command the AGI command to execute. * @param commandId the command id to track execution progress. */ - public AgiAction(String channel, String command, String commandId) - { + public AgiAction(String channel, String command, String commandId) { this.channel = channel; this.command = command; this.commandId = commandId; @@ -81,13 +77,11 @@ public AgiAction(String channel, String command, String commandId) * Returns the name of this action. */ @Override - public String getAction() - { + public String getAction() { return "AGI"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return AsyncAgiEvent.class; } @@ -96,8 +90,7 @@ public Class getActionCompleteEventClass() * * @return the name of the channel to execute the AGI command on. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -108,8 +101,7 @@ public String getChannel() * * @param channel the name of the channel to execute the AGI command on. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -118,8 +110,7 @@ public void setChannel(String channel) * * @return the AGI command to execute. */ - public String getCommand() - { + public String getCommand() { return command; } @@ -129,8 +120,7 @@ public String getCommand() * * @param command the AGI command to execute. */ - public void setCommand(String command) - { + public void setCommand(String command) { this.command = command; } @@ -139,8 +129,7 @@ public void setCommand(String command) * * @return the command id to track execution progress. */ - public String getCommandId() - { + public String getCommandId() { return commandId; } @@ -150,8 +139,7 @@ public String getCommandId() * * @param commandId the command id to track execution progress. */ - public void setCommandId(String commandId) - { + public void setCommandId(String commandId) { this.commandId = commandId; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/AtxferAction.java b/src/main/java/org/asteriskjava/manager/action/AtxferAction.java index 01e6f65f7..12b08fc5d 100644 --- a/src/main/java/org/asteriskjava/manager/action/AtxferAction.java +++ b/src/main/java/org/asteriskjava/manager/action/AtxferAction.java @@ -26,8 +26,7 @@ * @version $Id$ * @since 1.0.0 */ -public class AtxferAction extends AbstractManagerAction -{ +public class AtxferAction extends AbstractManagerAction { static final long serialVersionUID = 1L; private String channel; @@ -38,8 +37,7 @@ public class AtxferAction extends AbstractManagerAction /** * Creates a new empty AtxferAction. */ - public AtxferAction() - { + public AtxferAction() { } @@ -52,8 +50,7 @@ public AtxferAction() * @param exten the destination extension * @param priority the destination priority */ - public AtxferAction(String channel, String context, String exten, Integer priority) - { + public AtxferAction(String channel, String context, String exten, Integer priority) { this.channel = channel; this.context = context; this.exten = exten; @@ -65,8 +62,7 @@ public AtxferAction(String channel, String context, String exten, Integer priori * Returns the name of this action, i.e. "Atxfer". */ @Override - public String getAction() - { + public String getAction() { return "Atxfer"; } @@ -75,8 +71,7 @@ public String getAction() * * @return the name of the channel to transfer */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -85,8 +80,7 @@ public String getChannel() * * @param channel the name of the channel to transfer */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -95,8 +89,7 @@ public void setChannel(String channel) * * @return the destination context */ - public String getContext() - { + public String getContext() { return context; } @@ -105,8 +98,7 @@ public String getContext() * * @param context the destination context */ - public void setContext(String context) - { + public void setContext(String context) { this.context = context; } @@ -115,8 +107,7 @@ public void setContext(String context) * * @return the destination extension */ - public String getExten() - { + public String getExten() { return exten; } @@ -125,8 +116,7 @@ public String getExten() * * @param exten the destination extension */ - public void setExten(String exten) - { + public void setExten(String exten) { this.exten = exten; } @@ -135,8 +125,7 @@ public void setExten(String exten) * * @return the destination priority */ - public Integer getPriority() - { + public Integer getPriority() { return priority; } @@ -145,8 +134,7 @@ public Integer getPriority() * * @param priority the destination priority */ - public void setPriority(Integer priority) - { + public void setPriority(Integer priority) { this.priority = priority; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/BridgeAction.java b/src/main/java/org/asteriskjava/manager/action/BridgeAction.java index 1de6df0f9..17121eeda 100644 --- a/src/main/java/org/asteriskjava/manager/action/BridgeAction.java +++ b/src/main/java/org/asteriskjava/manager/action/BridgeAction.java @@ -25,8 +25,7 @@ * @version $Id$ * @since 1.0.0 */ -public class BridgeAction extends AbstractManagerAction -{ +public class BridgeAction extends AbstractManagerAction { /** * Serializable version identifier. */ @@ -39,8 +38,7 @@ public class BridgeAction extends AbstractManagerAction /** * Creates a new empty BridgeAction. */ - public BridgeAction() - { + public BridgeAction() { } @@ -50,8 +48,7 @@ public BridgeAction() * @param channel1 the name of the channel to bridge to channel2. * @param channel2 the name of the channel to bridge to channel1. */ - public BridgeAction(String channel1, String channel2) - { + public BridgeAction(String channel1, String channel2) { this.channel1 = channel1; this.channel2 = channel2; } @@ -63,8 +60,7 @@ public BridgeAction(String channel1, String channel2) * @param channel2 the name of the channel to bridge to channel1. * @param tone true to play a courtesy tone to channel2, false otherwise. */ - public BridgeAction(String channel1, String channel2, Boolean tone) - { + public BridgeAction(String channel1, String channel2, Boolean tone) { this.channel1 = channel1; this.channel2 = channel2; this.tone = tone; @@ -74,8 +70,7 @@ public BridgeAction(String channel1, String channel2, Boolean tone) * Returns the name of this action, i.e. "Bridge". */ @Override - public String getAction() - { + public String getAction() { return "Bridge"; } @@ -84,8 +79,7 @@ public String getAction() * * @return the name of the channel to bridge to channel2. */ - public String getChannel1() - { + public String getChannel1() { return channel1; } @@ -94,8 +88,7 @@ public String getChannel1() * * @param channel1 the name of the channel to bridge to channel2. */ - public void setChannel1(String channel1) - { + public void setChannel1(String channel1) { this.channel1 = channel1; } @@ -104,8 +97,7 @@ public void setChannel1(String channel1) * * @return the name of the channel to bridge to channel1. */ - public String getChannel2() - { + public String getChannel2() { return channel2; } @@ -114,8 +106,7 @@ public String getChannel2() * * @param channel2 the name of the channel to bridge to channel1. */ - public void setChannel2(String channel2) - { + public void setChannel2(String channel2) { this.channel2 = channel2; } @@ -123,10 +114,9 @@ public void setChannel2(String channel2) * Returns whether a courtesy tone will be played to channel2. * * @return true to play a courtesy tone to channel2, false or - * null (if not set) otherwise. + * null (if not set) otherwise. */ - public Boolean getTone() - { + public Boolean getTone() { return tone; } @@ -135,8 +125,7 @@ public Boolean getTone() * * @param tone true to play a courtesy tone to channel2, false otherwise. */ - public void setTone(Boolean tone) - { + public void setTone(Boolean tone) { this.tone = tone; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/ChallengeAction.java b/src/main/java/org/asteriskjava/manager/action/ChallengeAction.java index 01e10a25c..9b0f0a993 100644 --- a/src/main/java/org/asteriskjava/manager/action/ChallengeAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ChallengeAction.java @@ -30,16 +30,14 @@ * @see org.asteriskjava.manager.response.ChallengeResponse */ @ExpectedResponse(ChallengeResponse.class) -public class ChallengeAction extends AbstractManagerAction -{ +public class ChallengeAction extends AbstractManagerAction { static final long serialVersionUID = 7240516124871953971L; private String authType; /** * Creates a new empty ChallengeAction. */ - public ChallengeAction() - { + public ChallengeAction() { } @@ -50,8 +48,7 @@ public ChallengeAction() * @param authType the digest alogrithm to use. * @since 0.2 */ - public ChallengeAction(String authType) - { + public ChallengeAction(String authType) { this.authType = authType; } @@ -59,24 +56,21 @@ public ChallengeAction(String authType) * Returns Returns the name of this action, i.e. "Challenge". */ @Override - public String getAction() - { + public String getAction() { return "Challenge"; } /** * Returns the digest alogrithm to use. */ - public String getAuthType() - { + public String getAuthType() { return authType; } /** * Sets the digest alogrithm to use. Currently asterisk only supports "MD5". */ - public void setAuthType(String authType) - { + public void setAuthType(String authType) { this.authType = authType; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ChangeMonitorAction.java b/src/main/java/org/asteriskjava/manager/action/ChangeMonitorAction.java index a413fd3a4..1947eadcc 100644 --- a/src/main/java/org/asteriskjava/manager/action/ChangeMonitorAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ChangeMonitorAction.java @@ -20,12 +20,11 @@ * The ChangeMonitorAction changes the monitoring filename of a channel. It has * no effect if the channel is not monitored.

    * It is implemented in res/res_monitor.c - * + * * @author srt * @version $Id$ */ -public class ChangeMonitorAction extends AbstractManagerAction -{ +public class ChangeMonitorAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -36,22 +35,20 @@ public class ChangeMonitorAction extends AbstractManagerAction /** * Creates a new empty ChangeMonitorAction. */ - public ChangeMonitorAction() - { + public ChangeMonitorAction() { } /** * Creates a new ChangeMonitorAction that causes monitoring data for the * given channel to be written to the given file(s). - * + * * @param channel the name of the channel that is monitored - * @param file the (base) name of the file(s) to which the voice data is - * written + * @param file the (base) name of the file(s) to which the voice data is + * written * @since 0.2 */ - public ChangeMonitorAction(String channel, String file) - { + public ChangeMonitorAction(String channel, String file) { this.channel = channel; this.file = file; } @@ -60,16 +57,14 @@ public ChangeMonitorAction(String channel, String file) * Returns the name of this action, i.e. "ChangeMonitor". */ @Override - public String getAction() - { + public String getAction() { return "ChangeMonitor"; } /** * Returns the name of the monitored channel. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -77,16 +72,14 @@ public String getChannel() * Sets the name of the monitored channel.

    * This property is mandatory. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the name of the file to which the voice data is written. */ - public String getFile() - { + public String getFile() { return file; } @@ -94,8 +87,7 @@ public String getFile() * Sets the (base) name of the file(s) to which the voice data is written.

    * This property is mandatory. */ - public void setFile(String file) - { + public void setFile(String file) { this.file = file; } } diff --git a/src/main/java/org/asteriskjava/manager/action/CommandAction.java b/src/main/java/org/asteriskjava/manager/action/CommandAction.java index df7a4eaec..118d8acbd 100644 --- a/src/main/java/org/asteriskjava/manager/action/CommandAction.java +++ b/src/main/java/org/asteriskjava/manager/action/CommandAction.java @@ -43,16 +43,14 @@ * @see org.asteriskjava.manager.response.CommandResponse */ @ExpectedResponse(CommandResponse.class) -public class CommandAction extends AbstractManagerAction -{ +public class CommandAction extends AbstractManagerAction { static final long serialVersionUID = 4753117770471622025L; protected String command; /** * Creates a new CommandAction. */ - public CommandAction() - { + public CommandAction() { } @@ -62,8 +60,7 @@ public CommandAction() * @param command the CLI command to execute. * @since 0.2 */ - public CommandAction(String command) - { + public CommandAction(String command) { this.command = command; } @@ -71,24 +68,21 @@ public CommandAction(String command) * Returns the name of this action, i.e. "Command". */ @Override - public String getAction() - { + public String getAction() { return "Command"; } /** * Returns the command. */ - public String getCommand() - { + public String getCommand() { return command; } /** * Sets the CLI command to send to the Asterisk server. */ - public void setCommand(String command) - { + public void setCommand(String command) { this.command = command; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeKickAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeKickAction.java index e6192a62a..eb7527d86 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeKickAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeKickAction.java @@ -2,72 +2,72 @@ /** * The ConfbridgeKickAction kicks a channel out of a conference. - * + * * @author jmb * @version $Id$ */ public class ConfbridgeKickAction extends AbstractManagerAction { - + /** * Serializable version identifier */ - private static final long serialVersionUID = 3827556611709875112L; - - private String conference; + private static final long serialVersionUID = 3827556611709875112L; + + private String conference; private String channel; /** * Creates a new empty ConfbridgeKickAction. */ - public ConfbridgeKickAction() { - super(); - } - + public ConfbridgeKickAction() { + super(); + } + /** * Creates a new ConfbridgeKickAction. - * + * * @param conference the conference number. - * @param channel number of the channel in the conference. + * @param channel number of the channel in the conference. */ - public ConfbridgeKickAction(String conference, String channel) { - this.setConference(conference); - this.setChannel(channel); - } + public ConfbridgeKickAction(String conference, String channel) { + this.setConference(conference); + this.setChannel(channel); + } /** * Returns the name of this action, i.e. "ConfbridgeKick". */ - @Override - public String getAction() { - return "ConfbridgeKick"; - } + @Override + public String getAction() { + return "ConfbridgeKick"; + } - /** + /** * Sets the id of the conference to kick a channel from. - */ - public void setConference(String conference) { - this.conference = conference; - } + */ + public void setConference(String conference) { + this.conference = conference; + } /** * Returns the id of the conference to kick a channel from. - */ - public String getConference() { - return conference; - } + */ + public String getConference() { + return conference; + } /** * Sets the number of the channel to kick. */ - public void setChannel(String channel) { - this.channel = channel; - } + public void setChannel(String channel) { + this.channel = channel; + } /** * Returns the number of the channel to kick. - */ - public String getChannel() { - return channel; - } + */ + public String getChannel() { + return channel; + } } diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeListAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeListAction.java index 45d4d4bd7..e22d06589 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeListAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeListAction.java @@ -9,39 +9,32 @@ * * @since 1.0.0 */ -public class ConfbridgeListAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class ConfbridgeListAction extends AbstractManagerAction implements EventGeneratingAction { private static final long serialVersionUID = 1L; private String conference; - public ConfbridgeListAction() - { + public ConfbridgeListAction() { } - public ConfbridgeListAction(String conference) - { + public ConfbridgeListAction(String conference) { this.conference = conference; } - public void setConference(String conference) - { + public void setConference(String conference) { this.conference = conference; } - public String getConference() - { + public String getConference() { return conference; } @Override - public String getAction() - { + public String getAction() { return "ConfbridgeList"; } @Override - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return ConfbridgeListCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeListRoomsAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeListRoomsAction.java index f44916009..024fb6188 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeListRoomsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeListRoomsAction.java @@ -10,8 +10,7 @@ * * @since 1.0.0 */ -public class ConfbridgeListRoomsAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class ConfbridgeListRoomsAction extends AbstractManagerAction implements EventGeneratingAction { private static final long serialVersionUID = 1L; /** @@ -19,14 +18,12 @@ public class ConfbridgeListRoomsAction extends AbstractManagerAction implements */ @Override - public String getAction() - { + public String getAction() { return "ConfbridgeListRooms"; } @Override - public Class< ? extends ResponseEvent> getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return ConfbridgeListRoomsCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeLockAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeLockAction.java index 64e0704e0..c55b9bfb1 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeLockAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeLockAction.java @@ -2,53 +2,53 @@ /** * The ConfbridgeLockAction lockes a specified conference. - * + * * @author jmb * @version $Id$ */ public class ConfbridgeLockAction extends AbstractManagerAction { - /** + /** * Serializable version identifier */ - private static final long serialVersionUID = 6146611916322541533L; - - private String conference; - + private static final long serialVersionUID = 6146611916322541533L; + + private String conference; + /** * Creates a new empty ConfbridgeLockAction. */ - public ConfbridgeLockAction() { - super(); - } - - /** + public ConfbridgeLockAction() { + super(); + } + + /** * Creates a new ConfbridgeLockAction for a specific conference. - */ - public ConfbridgeLockAction(String conference) { - this.setConference(conference); - } - + */ + public ConfbridgeLockAction(String conference) { + this.setConference(conference); + } + /** * Returns the name of this action "ConfbridgeLock". */ - @Override - public String getAction() { - return "ConfbridgeLock"; - } - - /** + @Override + public String getAction() { + return "ConfbridgeLock"; + } + + /** * Sets the id of the conference to lock. - */ - public void setConference(String conference) { - this.conference = conference; - } - + */ + public void setConference(String conference) { + this.conference = conference; + } + /** * Returns the id of the conference to lock. - */ - public String getConference() { - return conference; - } + */ + public String getConference() { + return conference; + } } diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeMuteAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeMuteAction.java index 9e10e62ed..86c688cce 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeMuteAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeMuteAction.java @@ -2,7 +2,7 @@ /** * The ConfbridgeMuteAction mutes a channel in a conference. - * + * * @author jmb * @version $Id$ */ @@ -11,60 +11,60 @@ public class ConfbridgeMuteAction extends AbstractManagerAction { /** * Serializable version identifier */ - private static final long serialVersionUID = 1439791922666681989L; + private static final long serialVersionUID = 1439791922666681989L; - private String conference; + private String conference; private String channel; - + /** * Creates a new empty ConfbridgeMuteAction. */ - public ConfbridgeMuteAction() { - super(); - } + public ConfbridgeMuteAction() { + super(); + } /** * Creates a new ConfbridgeMuteAction. - * + * * @param conference the conference number. - * @param channel number of the channel in the conference. + * @param channel number of the channel in the conference. */ - public ConfbridgeMuteAction(String conference, String channel) { - this.setConference(conference); - this.setChannel(channel); - } - + public ConfbridgeMuteAction(String conference, String channel) { + this.setConference(conference); + this.setChannel(channel); + } + /** * Returns the name of this action, i.e. "ConfbridgeMute". */ - @Override - public String getAction() { - return "ConfbridgeMute"; - } - - /** + @Override + public String getAction() { + return "ConfbridgeMute"; + } + + /** * Sets the id of the conference. - */ - public void setConference(String conference) { - this.conference = conference; - } - + */ + public void setConference(String conference) { + this.conference = conference; + } + /** * Returns the id of the conference. - */ - public String getConference() { - return conference; - } + */ + public String getConference() { + return conference; + } /** * Sets the number of the channel to mute. */ - public void setChannel(String channel) { - this.channel = channel; - } - - public String getChannel() { - return channel; - } - + public void setChannel(String channel) { + this.channel = channel; + } + + public String getChannel() { + return channel; + } + } diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeSetSingleVideoSrcAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeSetSingleVideoSrcAction.java index a8f89b5ce..7d6f33e29 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeSetSingleVideoSrcAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeSetSingleVideoSrcAction.java @@ -2,61 +2,61 @@ /** * The ConfbridgeSetSingleVideoSrcAction sets a conference user as the single video source distributed to all other video-capable participants. - * + * * @author jmb * @version $Id$ */ public class ConfbridgeSetSingleVideoSrcAction extends AbstractManagerAction { - /** + /** * Serializable version identifier */ - private static final long serialVersionUID = 88241670521642551L; - - private String conference; - private String channel; - + private static final long serialVersionUID = 88241670521642551L; + + private String conference; + private String channel; + /** * Creates a new empty ConfbridgeSetSingleVideoSrcAction. */ - public ConfbridgeSetSingleVideoSrcAction() { - super(); - } - + public ConfbridgeSetSingleVideoSrcAction() { + super(); + } + /** * Returns the name of this action "ConfbridgeSetSingleVideoSrc". */ - @Override - public String getAction() { - return "ConfbridgeSetSingleVideoSrc"; - } - - /** + @Override + public String getAction() { + return "ConfbridgeSetSingleVideoSrc"; + } + + /** * Sets the id of the conference for which the video source is to be set. - */ - public void setConference(String conference) { - this.conference = conference; - } - + */ + public void setConference(String conference) { + this.conference = conference; + } + /** * Returns the id of the conference for which the video source is to be set. - */ - public String getConference() { - return conference; - } + */ + public String getConference() { + return conference; + } - /** + /** * Sets the channel which will be the single video source of the conference. - */ - public void setChannel(String channel) { - this.channel = channel; - } - - /** + */ + public void setChannel(String channel) { + this.channel = channel; + } + + /** * Returns the channel which will be the single video source of the conference. - */ - public String getChannel() { - return channel; - } + */ + public String getChannel() { + return channel; + } } diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeStartRecordAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeStartRecordAction.java index 8202944ed..b9feec800 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeStartRecordAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeStartRecordAction.java @@ -2,7 +2,7 @@ /** * The ConfbridgeStartAction starts an audio recording of a conference. - * + * * @author jmb * @version $Id$ */ @@ -11,44 +11,44 @@ public class ConfbridgeStartRecordAction extends AbstractManagerAction { /** * Serializable version identifier */ - private static final long serialVersionUID = 3059632508521358701L; - - private String conference; - + private static final long serialVersionUID = 3059632508521358701L; + + private String conference; + /** * Creates a new empty ConfbridgeStartRecordAction. */ - public ConfbridgeStartRecordAction() { - super(); - } - - /** + public ConfbridgeStartRecordAction() { + super(); + } + + /** * Creates a new ConfbridgeStartRecordAction for a specific conference. - */ - public ConfbridgeStartRecordAction(String conference) { - this.setConference(conference); - } - + */ + public ConfbridgeStartRecordAction(String conference) { + this.setConference(conference); + } + /** * Returns the name of this action, i.e. "ConfbridgeStartRecord". */ - @Override - public String getAction() { - return "ConfbridgeStartRecord"; - } - - /** + @Override + public String getAction() { + return "ConfbridgeStartRecord"; + } + + /** * Sets the id of the conference for which to start an audio recording. - */ - public void setConference(String conference) { - this.conference = conference; - } - + */ + public void setConference(String conference) { + this.conference = conference; + } + /** * Returns the id of the conference for which to start an audio recording. - */ - public String getConference() { - return conference; - } + */ + public String getConference() { + return conference; + } } diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeStopRecordAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeStopRecordAction.java index 5abf5dec8..2a5d8c6ec 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeStopRecordAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeStopRecordAction.java @@ -2,7 +2,7 @@ /** * The ConfbridgeStopAction stops an audio recording of a conference. - * + * * @author jmb * @version $Id$ */ @@ -11,44 +11,44 @@ public class ConfbridgeStopRecordAction extends AbstractManagerAction { /** * Serializable version identifier */ - private static final long serialVersionUID = 7429055239528793083L; - - private String conference; + private static final long serialVersionUID = 7429055239528793083L; + + private String conference; /** * Creates a new empty ConfbridgeStopRecordAction. */ - public ConfbridgeStopRecordAction() { - super(); - } - - /** + public ConfbridgeStopRecordAction() { + super(); + } + + /** * Creates a new ConfbridgeStopRecordAction for a specific conference. - */ - public ConfbridgeStopRecordAction(String conference) { - this.setConference(conference); - } - + */ + public ConfbridgeStopRecordAction(String conference) { + this.setConference(conference); + } + /** * Returns the name of this action, i.e. "ConfbridgeStopRecord". */ - @Override - public String getAction() { - return "ConfbridgeStopRecord"; - } + @Override + public String getAction() { + return "ConfbridgeStopRecord"; + } - /** + /** * Sets the id of the conference for which to stop an audio recording. - */ - public void setConference(String conference) { - this.conference = conference; - } + */ + public void setConference(String conference) { + this.conference = conference; + } /** * Returns the id of the conference for which to stop an audio recording. - */ - public String getConference() { - return conference; - } + */ + public String getConference() { + return conference; + } } diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeUnlockAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeUnlockAction.java index 056dac808..fb91b522f 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeUnlockAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeUnlockAction.java @@ -2,53 +2,53 @@ /** * The ConfbridgeUnlockAction unlocks a specified conference. - * + * * @author jmb * @version $Id$ */ public class ConfbridgeUnlockAction extends AbstractManagerAction { - /** + /** * Serializable version identifier */ - private static final long serialVersionUID = 88241670521642551L; - - private String conference; - + private static final long serialVersionUID = 88241670521642551L; + + private String conference; + /** * Creates a new empty ConfbridgeUnlockAction. */ - public ConfbridgeUnlockAction() { - super(); - } - - /** + public ConfbridgeUnlockAction() { + super(); + } + + /** * Creates a new ConfbridgeUnlockAction for a specific conference. - */ - public ConfbridgeUnlockAction(String conference) { - this.setConference(conference); - } - + */ + public ConfbridgeUnlockAction(String conference) { + this.setConference(conference); + } + /** * Returns the name of this action "ConfbridgeUnlock". */ - @Override - public String getAction() { - return "ConfbridgeUnlock"; - } - - /** + @Override + public String getAction() { + return "ConfbridgeUnlock"; + } + + /** * Sets the id of the conference to unlock. - */ - public void setConference(String conference) { - this.conference = conference; - } - + */ + public void setConference(String conference) { + this.conference = conference; + } + /** * Returns the id of the conference to unlock. - */ - public String getConference() { - return conference; - } + */ + public String getConference() { + return conference; + } } diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeUnmuteAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeUnmuteAction.java index 40a18ece5..f6a4845ff 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeUnmuteAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeUnmuteAction.java @@ -2,73 +2,73 @@ /** * The ConfbridgeUnmuteAction unmutes a channel in a conference. - * + * * @author jmb * @version $Id$ */ public class ConfbridgeUnmuteAction extends AbstractManagerAction { - /** + /** * Serializable version identifier */ - private static final long serialVersionUID = -590852239774371298L; - - private String conference; + private static final long serialVersionUID = -590852239774371298L; + + private String conference; private String channel; - + /** * Creates a new empty ConfbridgeUnmuteAction. */ - public ConfbridgeUnmuteAction() { - super(); - } + public ConfbridgeUnmuteAction() { + super(); + } /** * Creates a new ConfbridgeUnmuteAction. - * + * * @param conference the conference number. - * @param channel number of the channel in the conference. + * @param channel number of the channel in the conference. */ - public ConfbridgeUnmuteAction(String conference, String channel) { - this.setConference(conference); - this.setChannel(channel); - } + public ConfbridgeUnmuteAction(String conference, String channel) { + this.setConference(conference); + this.setChannel(channel); + } /** * Returns the name of this action, i.e. "ConfbridgeUnmute". */ - @Override - public String getAction() { - return "ConfbridgeUnmute"; - } + @Override + public String getAction() { + return "ConfbridgeUnmute"; + } - /** + /** * Sets the id of the conference. - */ - public void setConference(String conference) { - this.conference = conference; - } + */ + public void setConference(String conference) { + this.conference = conference; + } /** * Returns the id of the conference. - */ - public String getConference() { - return conference; - } + */ + public String getConference() { + return conference; + } /** * Sets the number of the channel to unmute. */ - public void setChannel(String channel) { - this.channel = channel; - } + public void setChannel(String channel) { + this.channel = channel; + } /** * Returns the number of the channel to unmute. - */ - public String getChannel() { - return channel; - } - + */ + public String getChannel() { + return channel; + } + } diff --git a/src/main/java/org/asteriskjava/manager/action/CoreSettingsAction.java b/src/main/java/org/asteriskjava/manager/action/CoreSettingsAction.java index 64dee5171..0a81b36b2 100644 --- a/src/main/java/org/asteriskjava/manager/action/CoreSettingsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/CoreSettingsAction.java @@ -31,15 +31,13 @@ * @since 1.0.0 */ @ExpectedResponse(CoreSettingsResponse.class) -public class CoreSettingsAction extends AbstractManagerAction -{ +public class CoreSettingsAction extends AbstractManagerAction { static final long serialVersionUID = 1L; /** * Creates a new CoreSettingsAction. */ - public CoreSettingsAction() - { + public CoreSettingsAction() { } @@ -47,8 +45,7 @@ public CoreSettingsAction() * Returns the name of this action, i.e. "CoreSettings". */ @Override - public String getAction() - { + public String getAction() { return "CoreSettings"; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/CoreShowChannelsAction.java b/src/main/java/org/asteriskjava/manager/action/CoreShowChannelsAction.java index 4c0eea236..b6210c2c2 100644 --- a/src/main/java/org/asteriskjava/manager/action/CoreShowChannelsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/CoreShowChannelsAction.java @@ -1,12 +1,12 @@ /* * Copyright 2009 Sebastian. - * + * * 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. @@ -32,27 +32,23 @@ * @see org.asteriskjava.manager.event.CoreShowChannelsCompleteEvent * @since 1.0.0 */ -public class CoreShowChannelsAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class CoreShowChannelsAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serializable version identifier. */ static final long serialVersionUID = 0L; - public CoreShowChannelsAction() - { + public CoreShowChannelsAction() { } @Override - public String getAction() - { + public String getAction() { return "CoreShowChannels"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return CoreShowChannelsCompleteEvent.class; } diff --git a/src/main/java/org/asteriskjava/manager/action/CoreStatusAction.java b/src/main/java/org/asteriskjava/manager/action/CoreStatusAction.java index 5f7180497..7a178d5ed 100644 --- a/src/main/java/org/asteriskjava/manager/action/CoreStatusAction.java +++ b/src/main/java/org/asteriskjava/manager/action/CoreStatusAction.java @@ -30,15 +30,13 @@ * @since 1.0.0 */ @ExpectedResponse(CoreStatusResponse.class) -public class CoreStatusAction extends AbstractManagerAction -{ +public class CoreStatusAction extends AbstractManagerAction { static final long serialVersionUID = 1L; /** * Creates a new CoreStatusAction. */ - public CoreStatusAction() - { + public CoreStatusAction() { } @@ -46,8 +44,7 @@ public CoreStatusAction() * Returns the name of this action, i.e. "CoreStatus". */ @Override - public String getAction() - { + public String getAction() { return "CoreStatus"; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/DahdiShowChannelsAction.java b/src/main/java/org/asteriskjava/manager/action/DahdiShowChannelsAction.java index 1d5b72785..a52b21cbd 100644 --- a/src/main/java/org/asteriskjava/manager/action/DahdiShowChannelsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/DahdiShowChannelsAction.java @@ -23,16 +23,15 @@ * The DahdiShowChannelsAction requests the state of all Dahdi channels.

    * For each Dahdi channel aDahdiShowChannelsEvent is generated. After all Dahdi * channels have been listed a DahdiShowChannelsCompleteEvent is generated. - * - * @see org.asteriskjava.manager.event.DahdiShowChannelsEvent - * @see org.asteriskjava.manager.event.DahdiShowChannelsCompleteEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.DahdiShowChannelsEvent + * @see org.asteriskjava.manager.event.DahdiShowChannelsCompleteEvent */ public class DahdiShowChannelsAction extends AbstractManagerAction implements - EventGeneratingAction -{ + EventGeneratingAction { /** * Serializable version identifier */ @@ -41,8 +40,7 @@ public class DahdiShowChannelsAction extends AbstractManagerAction /** * Creates a new DahdiShowChannelsAction. */ - public DahdiShowChannelsAction() - { + public DahdiShowChannelsAction() { } @@ -50,13 +48,11 @@ public DahdiShowChannelsAction() * Returns the name of this action, i.e. "DahdiShowChannels". */ @Override - public String getAction() - { + public String getAction() { return "DahdiShowChannels"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return DahdiShowChannelsCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/DbDelAction.java b/src/main/java/org/asteriskjava/manager/action/DbDelAction.java index f64aa4dc4..528424fe0 100644 --- a/src/main/java/org/asteriskjava/manager/action/DbDelAction.java +++ b/src/main/java/org/asteriskjava/manager/action/DbDelAction.java @@ -19,11 +19,10 @@ /** * Deletes an entry in the Asterisk database for a given family and key.

    * Available since Asterisk 1.2 with BRIStuff patches and since Asterisk 1.6 - * + * * @author gmi */ -public class DbDelAction extends AbstractManagerAction -{ +public class DbDelAction extends AbstractManagerAction { private static final long serialVersionUID = 921037572305993779L; private String family; private String key; @@ -31,66 +30,59 @@ public class DbDelAction extends AbstractManagerAction /** * Creates a new empty DbDelAction. */ - public DbDelAction() - { + public DbDelAction() { } /** * Creates a new DbDelAction that deletes the value of the database - * + * * @param family the family of the key - * @param key the key of the entry to delete + * @param key the key of the entry to delete */ - public DbDelAction(String family, String key) - { + public DbDelAction(String family, String key) { this.family = family; this.key = key; } @Override - public String getAction() - { + public String getAction() { return "DBDel"; } /** * Returns the family of the key to delete - * + * * @return the family of the key to delete */ - public String getFamily() - { + 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) - { + public void setFamily(String family) { this.family = family; } /** * Returns the the key to delete - * + * * @return the key to delete */ - public String getKey() - { + public String getKey() { return key; } /** * Sets the key to delete - * + * * @param key the key to delete */ - public void setKey(String key) - { + public void setKey(String key) { this.key = key; } } diff --git a/src/main/java/org/asteriskjava/manager/action/DbDelTreeAction.java b/src/main/java/org/asteriskjava/manager/action/DbDelTreeAction.java index 2807135df..6b21c94d4 100644 --- a/src/main/java/org/asteriskjava/manager/action/DbDelTreeAction.java +++ b/src/main/java/org/asteriskjava/manager/action/DbDelTreeAction.java @@ -23,8 +23,7 @@ * @author gmi * @since 1.0.0 */ -public class DbDelTreeAction extends AbstractManagerAction -{ +public class DbDelTreeAction extends AbstractManagerAction { private static final long serialVersionUID = 1L; private String family; private String key; @@ -32,8 +31,7 @@ public class DbDelTreeAction extends AbstractManagerAction /** * Creates a new empty DbDelTreeAction. */ - public DbDelTreeAction() - { + public DbDelTreeAction() { } @@ -41,17 +39,15 @@ public DbDelTreeAction() * Creates a new DbDelTreeAction. * * @param family the family of the key - * @param key the key of the entries to delete + * @param key the key of the entries to delete */ - public DbDelTreeAction(String family, String key) - { + public DbDelTreeAction(String family, String key) { this.family = family; this.key = key; } @Override - public String getAction() - { + public String getAction() { return "DBDelTree"; } @@ -60,8 +56,7 @@ public String getAction() * * @return the family of the key to delete */ - public String getFamily() - { + public String getFamily() { return family; } @@ -70,8 +65,7 @@ public String getFamily() * * @param family the family of the key to delete */ - public void setFamily(String family) - { + public void setFamily(String family) { this.family = family; } @@ -80,8 +74,7 @@ public void setFamily(String family) * * @return the key to delete */ - public String getKey() - { + public String getKey() { return key; } @@ -90,8 +83,7 @@ public String getKey() * * @param key the key to delete */ - public void setKey(String key) - { + public void setKey(String key) { this.key = key; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/DbGetAction.java b/src/main/java/org/asteriskjava/manager/action/DbGetAction.java index eceda8b05..591abf8b0 100644 --- a/src/main/java/org/asteriskjava/manager/action/DbGetAction.java +++ b/src/main/java/org/asteriskjava/manager/action/DbGetAction.java @@ -31,8 +31,7 @@ * @see org.asteriskjava.manager.event.DbGetResponseEvent * @since 0.2 */ -public class DbGetAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class DbGetAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serial version identifier */ @@ -43,8 +42,7 @@ public class DbGetAction extends AbstractManagerAction implements EventGeneratin /** * Creates a new empty DbGetAction. */ - public DbGetAction() - { + public DbGetAction() { } @@ -56,15 +54,13 @@ public DbGetAction() * @param key the key of the entry to retrieve * @since 0.2 */ - public DbGetAction(String family, String key) - { + public DbGetAction(String family, String key) { this.family = family; this.key = key; } @Override - public String getAction() - { + public String getAction() { return "DBGet"; } @@ -73,8 +69,7 @@ public String getAction() * * @return the family of the key. */ - public String getFamily() - { + public String getFamily() { return family; } @@ -83,8 +78,7 @@ public String getFamily() * * @param family the family of the key. */ - public void setFamily(String family) - { + public void setFamily(String family) { this.family = family; } @@ -93,8 +87,7 @@ public void setFamily(String family) * * @return the key of the entry to retrieve. */ - public String getKey() - { + public String getKey() { return key; } @@ -103,13 +96,11 @@ public String getKey() * * @param key the key of the entry to retrieve. */ - public void setKey(String key) - { + public void setKey(String key) { this.key = key; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return DbGetResponseEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/DbPutAction.java b/src/main/java/org/asteriskjava/manager/action/DbPutAction.java index 9eb4d1f28..d91242c50 100644 --- a/src/main/java/org/asteriskjava/manager/action/DbPutAction.java +++ b/src/main/java/org/asteriskjava/manager/action/DbPutAction.java @@ -20,13 +20,12 @@ * Adds or updates an entry in the Asterisk database for a given family, key, * and value.

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class DbPutAction extends AbstractManagerAction -{ +public class DbPutAction extends AbstractManagerAction { /** * Serial version identifier. */ @@ -38,101 +37,91 @@ public class DbPutAction extends AbstractManagerAction /** * Creates a new empty DbPutAction. */ - public DbPutAction() - { + public DbPutAction() { } /** * Creates a new DbPutAction that sets the value of the database entry with * the given key in the given family. - * + * * @param family the family of the key - * @param key the key of the entry to set - * @param val the value to set + * @param key the key of the entry to set + * @param val the value to set * @since 0.2 */ - public DbPutAction(String family, String key, String val) - { + public DbPutAction(String family, String key, String val) { this.family = family; this.key = key; this.val = val; } @Override - public String getAction() - { + public String getAction() { return "DBPut"; } /** * Returns the family of the key to set. - * + * * @return the family of the key to set. */ - public String getFamily() - { + public String getFamily() { return family; } /** * Sets the family of the key to set. - * + * * @param family the family of the key to set. */ - public void setFamily(String family) - { + public void setFamily(String family) { this.family = family; } /** * Returns the the key to set. - * + * * @return the key to set. */ - public String getKey() - { + public String getKey() { return key; } /** * Sets the key to set. - * + * * @param key the key to set. */ - public void setKey(String key) - { + public void setKey(String key) { this.key = key; } /** * Returns the value to set. - * + * * @return the value to set. */ - public String getVal() - { + public String getVal() { return val; } /** * Sets the value to set. - * + * * @param val the value to set. */ - public void setVal(String val) - { + public void setVal(String val) { this.val = val; } - + /** * Returns the value to set for BRIstuffed versions. - * + * * @return the value to set. * @since 1.0.0 */ - public String getValue() - { + public String getValue() { return val; } } diff --git a/src/main/java/org/asteriskjava/manager/action/DongleSendSMSAction.java b/src/main/java/org/asteriskjava/manager/action/DongleSendSMSAction.java index 2a37c2b35..a0dde3f58 100644 --- a/src/main/java/org/asteriskjava/manager/action/DongleSendSMSAction.java +++ b/src/main/java/org/asteriskjava/manager/action/DongleSendSMSAction.java @@ -1,45 +1,37 @@ package org.asteriskjava.manager.action; -public class DongleSendSMSAction extends AbstractManagerAction -{ - static final long serialVersionUID = 8194597741743334704L; - private String device; - private String number; - private String message; +public class DongleSendSMSAction extends AbstractManagerAction { + static final long serialVersionUID = 8194597741743334704L; + private String device; + private String number; + private String message; @Override - public String getAction() - { - return "DongleSendSMS"; - } - - public String getDevice() - { - return this.device; - } - - public void setDevice(String d) - { - this.device = d; - } - - public String getNumber() - { - return this.number; - } - - public void setNumber(String callerId) - { - this.number = callerId; - } - - public String getMessage() - { - return this.message; - } - - public void setMessage(String m) - { - this.message = m; - } -} \ No newline at end of file + public String getAction() { + return "DongleSendSMS"; + } + + public String getDevice() { + return this.device; + } + + public void setDevice(String d) { + this.device = d; + } + + public String getNumber() { + return this.number; + } + + public void setNumber(String callerId) { + this.number = callerId; + } + + public String getMessage() { + return this.message; + } + + public void setMessage(String m) { + this.message = m; + } +} diff --git a/src/main/java/org/asteriskjava/manager/action/DongleShowDevicesAction.java b/src/main/java/org/asteriskjava/manager/action/DongleShowDevicesAction.java index 1f9fd7abe..c2418b717 100644 --- a/src/main/java/org/asteriskjava/manager/action/DongleShowDevicesAction.java +++ b/src/main/java/org/asteriskjava/manager/action/DongleShowDevicesAction.java @@ -1,4 +1,3 @@ - package org.asteriskjava.manager.action; import org.asteriskjava.manager.event.DongleShowDevicesCompleteEvent; @@ -7,8 +6,7 @@ public class DongleShowDevicesAction extends AbstractManagerAction implements - EventGeneratingAction -{ + EventGeneratingAction { /** * Serializable version identifier */ @@ -17,8 +15,7 @@ public class DongleShowDevicesAction extends AbstractManagerAction /** * Creates a new DahdiShowChannelsAction. */ - public DongleShowDevicesAction() - { + public DongleShowDevicesAction() { } @@ -26,13 +23,11 @@ public DongleShowDevicesAction() * Returns the name of this action, i.e. "DahdiShowChannels". */ @Override - public String getAction() - { + public String getAction() { return "DongleShowDevices"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return DongleShowDevicesCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/EventGeneratingAction.java b/src/main/java/org/asteriskjava/manager/action/EventGeneratingAction.java index c521748a7..acd4bf04e 100644 --- a/src/main/java/org/asteriskjava/manager/action/EventGeneratingAction.java +++ b/src/main/java/org/asteriskjava/manager/action/EventGeneratingAction.java @@ -24,18 +24,17 @@ * events.

    * The event type that indicates that Asterisk is finished is returned by the * getActionCompleteEventClass() method. - * - * @see org.asteriskjava.manager.event.ResponseEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.ResponseEvent * @since 0.2 */ -public interface EventGeneratingAction extends ManagerAction -{ +public interface EventGeneratingAction extends ManagerAction { /** * Returns the event type that indicates that Asterisk is finished sending * response events for this action. - * + * * @return a Class that is an instance of ResponseEvent. * @see org.asteriskjava.manager.event.ResponseEvent */ diff --git a/src/main/java/org/asteriskjava/manager/action/EventsAction.java b/src/main/java/org/asteriskjava/manager/action/EventsAction.java index 811867c03..953a47ce8 100644 --- a/src/main/java/org/asteriskjava/manager/action/EventsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/EventsAction.java @@ -19,12 +19,11 @@ /** * With the EventsAction you can specify what kind of events should be sent to * this manager connection. - * + * * @author srt * @version $Id$ */ -public class EventsAction extends AbstractManagerAction -{ +public class EventsAction extends AbstractManagerAction { /** * Serializable version identifier. */ @@ -35,23 +34,21 @@ public class EventsAction extends AbstractManagerAction /** * Creates a new empty EventsAction. */ - public EventsAction() - { + public EventsAction() { } /** * Creates a new EventsAction that applies the given event mask to the * current manager connection. - * + * * @param eventMask the event mask. Set to "on" if all events should be - * send, "off" if not events should be sent or a combination of - * "system", "call" and "log" (separated by ',') to specify what - * kind of events should be sent. + * send, "off" if not events should be sent or a combination of + * "system", "call" and "log" (separated by ',') to specify what + * kind of events should be sent. * @since 0.2 */ - public EventsAction(String eventMask) - { + public EventsAction(String eventMask) { this.eventMask = eventMask; } @@ -59,16 +56,14 @@ public EventsAction(String eventMask) * Returns the name of this action, i.e. "Events". */ @Override - public String getAction() - { + public String getAction() { return "Events"; } /** * Returns the event mask. */ - public String getEventMask() - { + public String getEventMask() { return eventMask; } @@ -78,8 +73,7 @@ public String getEventMask() * sent or a combination of "system", "call" and "log" (separated by ',') to * specify what kind of events should be sent. */ - public void setEventMask(String eventMask) - { + public void setEventMask(String eventMask) { this.eventMask = eventMask; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ExecAction.java b/src/main/java/org/asteriskjava/manager/action/ExecAction.java index 3a80a702a..7fa229e13 100644 --- a/src/main/java/org/asteriskjava/manager/action/ExecAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ExecAction.java @@ -30,7 +30,7 @@ * contains the CLI output. *

    * Example: - * + * *

      * CommandAction commandAction = new CommandAction("iax2 show peers");
      * CommandResponse response = (CommandResponse) c.sendAction(commandAction);
    @@ -39,7 +39,7 @@
      *     System.out.println(line);
      * }
      * 
    - * + *

    * Where c is an instance of * {@link org.asteriskjava.manager.ManagerConnection}. * @@ -48,16 +48,14 @@ * @see org.asteriskjava.manager.response.CommandResponse */ @ExpectedResponse(CommandResponse.class) -public class ExecAction extends AbstractManagerAction -{ +public class ExecAction extends AbstractManagerAction { static final long serialVersionUID = 4753117770471622025L; protected String command; /** * Creates a new CommandAction. */ - public ExecAction() - { + public ExecAction() { } @@ -67,8 +65,7 @@ public ExecAction() * @param command the CLI command to execute. * @since 0.2 */ - public ExecAction(String command) - { + public ExecAction(String command) { this.command = command; } @@ -76,24 +73,21 @@ public ExecAction(String command) * Returns the name of this action, i.e. "Command". */ @Override - public String getAction() - { + public String getAction() { return "exec"; } /** * Returns the command. */ - public String getCommand() - { + public String getCommand() { return command; } /** * Sets the CLI command to send to the Asterisk server. */ - public void setCommand(String command) - { + public void setCommand(String command) { this.command = command; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ExtensionStateAction.java b/src/main/java/org/asteriskjava/manager/action/ExtensionStateAction.java index 9f2b3be4f..b3062022a 100644 --- a/src/main/java/org/asteriskjava/manager/action/ExtensionStateAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ExtensionStateAction.java @@ -28,8 +28,7 @@ * @version $Id$ */ @ExpectedResponse(ExtensionStateResponse.class) -public class ExtensionStateAction extends AbstractManagerAction -{ +public class ExtensionStateAction extends AbstractManagerAction { static final long serialVersionUID = 6537408784388696403L; private String exten; @@ -38,20 +37,18 @@ public class ExtensionStateAction extends AbstractManagerAction /** * Creates a new ExtensionStateAction. */ - public ExtensionStateAction() - { + public ExtensionStateAction() { } /** * Creates a new ExtensionStateAction that queries the state of the given extension in * the given context. * - * @param exten the extension to query. + * @param exten the extension to query. * @param context the name of the context that contains the extension to query. * @since 1.0.0 */ - public ExtensionStateAction(String exten, String context) - { + public ExtensionStateAction(String exten, String context) { this.exten = exten; this.context = context; } @@ -60,8 +57,7 @@ public ExtensionStateAction(String exten, String context) * Returns the name of this action, i.e. "ExtensionState". */ @Override - public String getAction() - { + public String getAction() { return "ExtensionState"; } @@ -70,8 +66,7 @@ public String getAction() * * @return the extension to query. */ - public String getExten() - { + public String getExten() { return exten; } @@ -80,8 +75,7 @@ public String getExten() * * @param exten the extension to query. */ - public void setExten(String exten) - { + public void setExten(String exten) { this.exten = exten; } @@ -90,8 +84,7 @@ public void setExten(String exten) * * @return the name of the context that contains the extension to query. */ - public String getContext() - { + public String getContext() { return context; } @@ -100,8 +93,7 @@ public String getContext() * * @param context the name of the context that contains the extension to query. */ - public void setContext(String context) - { + public void setContext(String context) { this.context = context; } } diff --git a/src/main/java/org/asteriskjava/manager/action/FilterAction.java b/src/main/java/org/asteriskjava/manager/action/FilterAction.java index d81436134..ec4ddcc32 100644 --- a/src/main/java/org/asteriskjava/manager/action/FilterAction.java +++ b/src/main/java/org/asteriskjava/manager/action/FilterAction.java @@ -19,28 +19,27 @@ /** * The FilterAction dynamically adds filters for the current user in a manager session. * The filters added are only used for the current session. Once the connection is closed the filters are removed. - * - * This command requires the user has read access to specific events(manager.conf) and system permission - * because it can be used to create filters that may bypass filters defined in manager.conf - * - * There are 2 Types of filters: - * Blacklist: The event you no longer want to receive. It starts with an exclamation. eg. "!RTCPReceived". - * Whitelist: The event you are interested in receiving. eg. "RTCPReceived". - * - * Regular expressions can be used for the filters. - * + *

    + * This command requires the user has read access to specific events(manager.conf) and system permission + * because it can be used to create filters that may bypass filters defined in manager.conf + *

    + * There are 2 Types of filters: + * Blacklist: The event you no longer want to receive. It starts with an exclamation. eg. "!RTCPReceived". + * Whitelist: The event you are interested in receiving. eg. "RTCPReceived". + *

    + * Regular expressions can be used for the filters. + *

    * Evaluation of the filters is as follows: * If no filters are configured all events are reported as normal. * If there are white filters only: Then it is implied that all events are black listed and only the specified white filter events are returned. - * If there are black filters only: Then it is implied that all events are white listed and only the specified black filter events are removed. - * If there are both white and black filters: Then it is implied that all events are black listed and only the specified white filter events are returned, - * and then specific blacklisted events are further removed. (Limited use cases) - * + * If there are black filters only: Then it is implied that all events are white listed and only the specified black filter events are removed. + * If there are both white and black filters: Then it is implied that all events are black listed and only the specified white filter events are returned, + * and then specific blacklisted events are further removed. (Limited use cases) + * * @author aavaz * @version $Id$ */ -public class FilterAction extends AbstractManagerAction -{ +public class FilterAction extends AbstractManagerAction { static final long serialVersionUID = 5537508784388696503L; private String operation = "Add";//No other option other than Add at the moment. @@ -49,18 +48,16 @@ public class FilterAction extends AbstractManagerAction /** * Creates a new FilterAction. */ - public FilterAction() - { + public FilterAction() { } /** * Creates a new FilterAction with the filter specified * - * @param filter the whitelist or blacklist filter to be added. + * @param filter the whitelist or blacklist filter to be added. * @since ??? */ - public FilterAction(String filter) - { + public FilterAction(String filter) { this.filter = filter; } @@ -68,8 +65,7 @@ public FilterAction(String filter) * Returns the name of this action, i.e. "Filter". */ @Override - public String getAction() - { + public String getAction() { return "Filter"; } @@ -78,28 +74,25 @@ public String getAction() * * @return the filter operation which is "Add" by default */ - public String getOperation() - { + public String getOperation() { return operation; - } - + } + /** * Returns the filter. * * @return the filter. */ - public String getFilter() - { + public String getFilter() { return filter; } /** - * Sets the filter. + * Sets the filter. * - * @param filter add the whitelist or blacklist event to be filtered. + * @param filter add the whitelist or blacklist event to be filtered. */ - public void setFilter(String filter) - { + public void setFilter(String filter) { this.filter = filter; } diff --git a/src/main/java/org/asteriskjava/manager/action/GetConfigAction.java b/src/main/java/org/asteriskjava/manager/action/GetConfigAction.java index dbea4242a..e64de5148 100644 --- a/src/main/java/org/asteriskjava/manager/action/GetConfigAction.java +++ b/src/main/java/org/asteriskjava/manager/action/GetConfigAction.java @@ -28,16 +28,14 @@ * @since 0.3 */ @ExpectedResponse(GetConfigResponse.class) -public class GetConfigAction extends AbstractManagerAction -{ +public class GetConfigAction extends AbstractManagerAction { static final long serialVersionUID = 4753117770471622025L; private String filename; /** * Creates a new GetConfigAction. */ - public GetConfigAction() - { + public GetConfigAction() { } @@ -46,8 +44,7 @@ public GetConfigAction() * * @param filename the name of the file to get. */ - public GetConfigAction(String filename) - { + public GetConfigAction(String filename) { this.filename = filename; } @@ -55,24 +52,21 @@ public GetConfigAction(String filename) * Returns the name of this action, i.e. "GetConfig". */ @Override - public String getAction() - { + public String getAction() { return "GetConfig"; } /** * Returns the filename. */ - public String getFilename() - { + public String getFilename() { return filename; } /** * Sets filename. */ - public void setFilename(String filename) - { + public void setFilename(String filename) { this.filename = filename; } } diff --git a/src/main/java/org/asteriskjava/manager/action/GetVarAction.java b/src/main/java/org/asteriskjava/manager/action/GetVarAction.java index 17f988b5f..6d0f14727 100644 --- a/src/main/java/org/asteriskjava/manager/action/GetVarAction.java +++ b/src/main/java/org/asteriskjava/manager/action/GetVarAction.java @@ -42,7 +42,7 @@ * String value = response.getAttribute("Value"); * System.out.println("MY_VAR on " + channel + " is " + value); * - * Where c is an instance of + * Where c is an instance of * {@link org.asteriskjava.manager.ManagerConnection} and channel * contains the name of a channel instance, for example "SIP/1234-9cd". *

    @@ -52,13 +52,12 @@ *

    * Since Asterisk 1.4 this action also supports built-in functions like * DB(), CALLERID() and ENV(). - * + * * @author srt * @version $Id$ */ @ExpectedResponse(GetVarResponse.class) -public class GetVarAction extends AbstractManagerAction -{ +public class GetVarAction extends AbstractManagerAction { private static final long serialVersionUID = 5239805071977668779L; private String channel; private String variable; @@ -66,32 +65,29 @@ public class GetVarAction extends AbstractManagerAction /** * Creates a new empty GetVarAction. */ - public GetVarAction() - { + public GetVarAction() { } /** * Creates a new GetVarAction that queries for the given global variable. - * + * * @param variable the name of the global variable to query. * @since 0.2 */ - public GetVarAction(String variable) - { + public GetVarAction(String variable) { this.variable = variable; } /** * Creates a new GetVarAction that queries for the given local channel * variable. - * - * @param channel the name of the channel, for example "SIP/1234-9cd". + * + * @param channel the name of the channel, for example "SIP/1234-9cd". * @param variable the name of the variable to query. * @since 0.2 */ - public GetVarAction(String channel, String variable) - { + public GetVarAction(String channel, String variable) { this.channel = channel; this.variable = variable; } @@ -100,8 +96,7 @@ public GetVarAction(String channel, String variable) * Returns the name of this action, i.e. "GetVar". */ @Override - public String getAction() - { + public String getAction() { return "GetVar"; } @@ -109,36 +104,32 @@ public String getAction() * Returns the name of the channel if you query for a local channel variable * or null if it is a global variable. */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel if you query for a local channel variable. * Leave empty to query for a global variable. - * + * * @param channel the channel if you query for a local channel variable or - * null to query for a gloabl variable. + * null to query for a gloabl variable. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Retruns the name of the variable to query. */ - public String getVariable() - { + public String getVariable() { return variable; } /** * Sets the name of the variable to query. */ - public void setVariable(String variable) - { + public void setVariable(String variable) { this.variable = variable; } } diff --git a/src/main/java/org/asteriskjava/manager/action/HangupAction.java b/src/main/java/org/asteriskjava/manager/action/HangupAction.java index 180a509b1..2ea1fc3af 100644 --- a/src/main/java/org/asteriskjava/manager/action/HangupAction.java +++ b/src/main/java/org/asteriskjava/manager/action/HangupAction.java @@ -23,8 +23,7 @@ * @author srt * @version $Id$ */ -public class HangupAction extends AbstractManagerAction -{ +public class HangupAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -36,8 +35,7 @@ public class HangupAction extends AbstractManagerAction /** * Creates a new empty HangupAction. */ - public HangupAction() - { + public HangupAction() { } @@ -47,8 +45,7 @@ public HangupAction() * @param channel the name of the channel to hangup. * @since 0.2 */ - public HangupAction(String channel) - { + public HangupAction(String channel) { this.channel = channel; } @@ -59,8 +56,7 @@ public HangupAction(String channel) * @param cause the cause code. The cause code must be >= 0 and <= 127. * @since 1.0.0 */ - public HangupAction(String channel, int cause) - { + public HangupAction(String channel, int cause) { this.channel = channel; this.cause = cause; } @@ -69,8 +65,7 @@ public HangupAction(String channel, int cause) * Returns the name of this action, i.e. "Hangup". */ @Override - public String getAction() - { + public String getAction() { return "Hangup"; } @@ -79,8 +74,7 @@ public String getAction() * * @return the name of the channel to hangup. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -90,8 +84,7 @@ public String getChannel() * * @param channel the name of the channel to hangup. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -101,8 +94,7 @@ public void setChannel(String channel) * @return the hangup cause. * @since 1.0.0 */ - public Integer getCause() - { + public Integer getCause() { return cause; } @@ -113,8 +105,7 @@ public Integer getCause() * @param cause the hangup cause. * @since 1.0.0 */ - public void setCause(Integer cause) - { + public void setCause(Integer cause) { this.cause = cause; } } diff --git a/src/main/java/org/asteriskjava/manager/action/IaxPeerListAction.java b/src/main/java/org/asteriskjava/manager/action/IaxPeerListAction.java index 5bc5463ab..3463ce453 100644 --- a/src/main/java/org/asteriskjava/manager/action/IaxPeerListAction.java +++ b/src/main/java/org/asteriskjava/manager/action/IaxPeerListAction.java @@ -32,8 +32,7 @@ * @see org.asteriskjava.manager.event.PeerlistCompleteEvent * @since 1.0.0 */ -public class IaxPeerListAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class IaxPeerListAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serial version identifier. */ @@ -42,19 +41,16 @@ public class IaxPeerListAction extends AbstractManagerAction implements EventGen /** * Creates a new IaxPeersAction. */ - public IaxPeerListAction() - { + public IaxPeerListAction() { } @Override - public String getAction() - { + public String getAction() { return "IAXpeerlist"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return PeerlistCompleteEvent.class; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/JabberSendAction.java b/src/main/java/org/asteriskjava/manager/action/JabberSendAction.java index a90c42c9a..17bb9519f 100644 --- a/src/main/java/org/asteriskjava/manager/action/JabberSendAction.java +++ b/src/main/java/org/asteriskjava/manager/action/JabberSendAction.java @@ -24,8 +24,7 @@ * @version $Id$ * @since 1.0.0 */ -public class JabberSendAction extends AbstractManagerAction -{ +public class JabberSendAction extends AbstractManagerAction { private static final long serialVersionUID = 1L; private String jabber; @@ -35,8 +34,7 @@ public class JabberSendAction extends AbstractManagerAction /** * Creates a new JabberSendAction. */ - public JabberSendAction() - { + public JabberSendAction() { super(); } @@ -47,8 +45,7 @@ public JabberSendAction() * @param screenName the JID of the recipient. * @param message the message to send to the recipient. */ - public JabberSendAction(String jabber, String screenName, String message) - { + public JabberSendAction(String jabber, String screenName, String message) { this.jabber = jabber; this.screenName = screenName; this.message = message; @@ -58,13 +55,11 @@ public JabberSendAction(String jabber, String screenName, String message) * Returns the name of this action, i.e. "Ping". */ @Override - public String getAction() - { + public String getAction() { return "JabberSend"; } - public String getJabber() - { + public String getJabber() { return jabber; } @@ -73,13 +68,11 @@ public String getJabber() * * @param jabber the client or transport Asterisk uses to connect to Jabber. */ - public void setJabber(String jabber) - { + public void setJabber(String jabber) { this.jabber = jabber; } - public String getScreenName() - { + public String getScreenName() { return screenName; } @@ -88,13 +81,11 @@ public String getScreenName() * * @param screenName the JID of the recipient. */ - public void setScreenName(String screenName) - { + public void setScreenName(String screenName) { this.screenName = screenName; } - public String getMessage() - { + public String getMessage() { return message; } @@ -103,8 +94,7 @@ public String getMessage() * * @param message the message to send to the recipient. */ - public void setMessage(String message) - { + public void setMessage(String message) { this.message = message; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/ListCommandsAction.java b/src/main/java/org/asteriskjava/manager/action/ListCommandsAction.java index 2b55b4c7b..916324ff3 100644 --- a/src/main/java/org/asteriskjava/manager/action/ListCommandsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ListCommandsAction.java @@ -19,14 +19,13 @@ /** * The ListCommandsAction returns possible commands in the Manager interface. *

    - * Use the getAttributes method on the ManagerResponse for a map of commands and explanations. - * - * @see org.asteriskjava.manager.response.ManagerResponse#getAttributes() + * Use the getAttributes method on the ManagerResponse for a map of commands and explanations. + * * @author martins + * @see org.asteriskjava.manager.response.ManagerResponse#getAttributes() * @since 0.3 */ -public class ListCommandsAction extends AbstractManagerAction -{ +public class ListCommandsAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -35,8 +34,7 @@ public class ListCommandsAction extends AbstractManagerAction /** * Creates a new ListCommandsAction. */ - public ListCommandsAction() - { + public ListCommandsAction() { } @@ -44,8 +42,7 @@ public ListCommandsAction() * Returns the name of this action, i.e. "ListCommands". */ @Override - public String getAction() - { + public String getAction() { return "ListCommands"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/LocalOptimizeAwayAction.java b/src/main/java/org/asteriskjava/manager/action/LocalOptimizeAwayAction.java index b06a25bb6..d307c53d5 100644 --- a/src/main/java/org/asteriskjava/manager/action/LocalOptimizeAwayAction.java +++ b/src/main/java/org/asteriskjava/manager/action/LocalOptimizeAwayAction.java @@ -23,8 +23,7 @@ * * @author SYON Communications Inc. */ -public class LocalOptimizeAwayAction extends AbstractManagerAction -{ +public class LocalOptimizeAwayAction extends AbstractManagerAction { /** * Serializable version identifier. */ @@ -34,8 +33,7 @@ public class LocalOptimizeAwayAction extends AbstractManagerAction /** * Creates a new empty LocalOptimizeAwayAction. */ - public LocalOptimizeAwayAction() - { + public LocalOptimizeAwayAction() { } @@ -44,18 +42,16 @@ public LocalOptimizeAwayAction() * * @param channel Name of the channel for clears the flag. */ - public LocalOptimizeAwayAction(String channel) - { - this.channel = channel; + public LocalOptimizeAwayAction(String channel) { + this.channel = channel; } /** * Returns the name of this action, i.e. "LocalOptimizeAway". */ @Override - public String getAction() - { - return "LocalOptimizeAway"; + public String getAction() { + return "LocalOptimizeAway"; } /** @@ -63,9 +59,8 @@ public String getAction() * * @return Name of the channel for clears the flag. */ - public String getChannel() - { - return channel; + public String getChannel() { + return channel; } /** @@ -73,9 +68,8 @@ public String getChannel() * * @param channel Name of the channel for clears the flag. */ - public void setChannel(String channel) - { - this.channel = channel; + public void setChannel(String channel) { + this.channel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/action/LoginAction.java b/src/main/java/org/asteriskjava/manager/action/LoginAction.java index e7007544d..0a9f61f39 100644 --- a/src/main/java/org/asteriskjava/manager/action/LoginAction.java +++ b/src/main/java/org/asteriskjava/manager/action/LoginAction.java @@ -23,14 +23,13 @@ * An unsuccessful login results in an ManagerError being received from the * server with a message set to "Authentication failed" and the socket being * closed by Asterisk. - * - * @see org.asteriskjava.manager.action.ChallengeAction - * @see org.asteriskjava.manager.response.ManagerError + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.ChallengeAction + * @see org.asteriskjava.manager.response.ManagerError */ -public class LoginAction extends AbstractManagerAction -{ +public class LoginAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -45,40 +44,37 @@ public class LoginAction extends AbstractManagerAction /** * Creates a new empty LoginAction. */ - public LoginAction() - { - + public LoginAction() { + } - + /** * Creates a new LoginAction that performs a cleartext login.

    * You should not use cleartext login if you are concerned about security, * using {@link ChallengeAction} and login with a password hash instead. - * + * * @param username the username as configured in Asterisk's - * manager.conf - * @param secret the user's password as configured in Asterisk's - * manager.conf + * manager.conf + * @param secret the user's password as configured in Asterisk's + * manager.conf * @since 0.2 */ - public LoginAction(String username, String secret) - { + public LoginAction(String username, String secret) { this.username = username; this.secret = secret; } /** * Creates a new LoginAction that performs a login via challenge/response. - * + * * @param username the username as configured in Asterisk's - * manager.conf + * manager.conf * @param authType the digest alogrithm, must match the digest algorithm - * that was used with the corresponding ChallengeAction. - * @param key the hash of the user's password and the challenge + * that was used with the corresponding ChallengeAction. + * @param key the hash of the user's password and the challenge * @since 0.2 */ - public LoginAction(String username, String authType, String key) - { + public LoginAction(String username, String authType, String key) { this.username = username; this.authType = authType; this.key = key; @@ -86,21 +82,20 @@ public LoginAction(String username, String authType, String key) /** * Creates a new LoginAction that performs a login via challenge/response. - * + * * @param username the username as configured in Asterisk's - * manager.conf + * manager.conf * @param authType the digest alogrithm, must match the digest algorithm - * that was used with the corresponding ChallengeAction. - * @param key the hash of the user's password and the challenge - * @param events the event mask. Set to "on" if all events should be send, - * "off" if not events should be sent or a combination of - * "system", "call" and "log" (separated by ',') to specify what - * kind of events should be sent. + * that was used with the corresponding ChallengeAction. + * @param key the hash of the user's password and the challenge + * @param events the event mask. Set to "on" if all events should be send, + * "off" if not events should be sent or a combination of + * "system", "call" and "log" (separated by ',') to specify what + * kind of events should be sent. * @since 0.2 */ public LoginAction(String username, String authType, String key, - String events) - { + String events) { this.username = username; this.authType = authType; this.key = key; @@ -111,32 +106,28 @@ public LoginAction(String username, String authType, String key, * Returns the name of this action, i.e. "Login". */ @Override - public String getAction() - { + public String getAction() { return "Login"; } /** * Returns the username. */ - public String getUsername() - { + public String getUsername() { return username; } /** * Sets the username as configured in asterik's manager.conf. */ - public void setUsername(String username) - { + public void setUsername(String username) { this.username = username; } /** * Returns the secret. */ - public String getSecret() - { + public String getSecret() { return secret; } @@ -146,16 +137,14 @@ public String getSecret() * manager.conf.

    * The secret and key properties are mutually exclusive. */ - public void setSecret(String secret) - { + public void setSecret(String secret) { this.secret = secret; } /** * Returns the digest alogrithm when using challenge/response. */ - public String getAuthType() - { + public String getAuthType() { return authType; } @@ -165,47 +154,42 @@ public String getAuthType() * the user's password.

    * Currently Asterisk supports only "MD5". */ - public void setAuthType(String authType) - { + public void setAuthType(String authType) { this.authType = authType; } /** * @return Returns the key. */ - public String getKey() - { + public String getKey() { return key; } /** * @param key The key to set. */ - public void setKey(String key) - { + public void setKey(String key) { this.key = key; } /** * Returns the event mask. - * + * * @return the event mask. */ - public String getEvents() - { + public String getEvents() { return events; } /** * Sets the event mask. - * + * * @param events the event mask. Set to "on" if all events should be send, - * "off" if not events should be sent or a combination of - * "system", "call" and "log" (separated by ',') to specify what - * kind of events should be sent. + * "off" if not events should be sent or a combination of + * "system", "call" and "log" (separated by ',') to specify what + * kind of events should be sent. */ - public void setEvents(String events) - { + public void setEvents(String events) { this.events = events; } } diff --git a/src/main/java/org/asteriskjava/manager/action/LogoffAction.java b/src/main/java/org/asteriskjava/manager/action/LogoffAction.java index c71063013..a5ef175af 100644 --- a/src/main/java/org/asteriskjava/manager/action/LogoffAction.java +++ b/src/main/java/org/asteriskjava/manager/action/LogoffAction.java @@ -18,12 +18,11 @@ /** * The LogoffAction causes the server to close the connection. - * + * * @author srt * @version $Id$ */ -public class LogoffAction extends AbstractManagerAction -{ +public class LogoffAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -32,8 +31,7 @@ public class LogoffAction extends AbstractManagerAction /** * Creates a new LogoffAction. */ - public LogoffAction() - { + public LogoffAction() { } @@ -41,8 +39,7 @@ public LogoffAction() * Returns the name of this action, i.e. "Logoff". */ @Override - public String getAction() - { + public String getAction() { return "Logoff"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/MWIDeleteAction.java b/src/main/java/org/asteriskjava/manager/action/MWIDeleteAction.java index 8b459de19..646f95a4a 100644 --- a/src/main/java/org/asteriskjava/manager/action/MWIDeleteAction.java +++ b/src/main/java/org/asteriskjava/manager/action/MWIDeleteAction.java @@ -16,38 +16,32 @@ */ package org.asteriskjava.manager.action; -public class MWIDeleteAction extends AbstractManagerAction -{ +public class MWIDeleteAction extends AbstractManagerAction { static final long serialVersionUID = 1L; private String mailbox; /** * Creates a new MWIDeleteAction. */ - public MWIDeleteAction() - { + public MWIDeleteAction() { } - public MWIDeleteAction(String mailbox) - { + public MWIDeleteAction(String mailbox) { this.mailbox = mailbox; } - public String getMailbox() - { + public String getMailbox() { return mailbox; } - public void setMailbox(String mailbox) - { + public void setMailbox(String mailbox) { this.mailbox = mailbox; } @Override - public String getAction() - { + public String getAction() { return "MWIDelete"; } diff --git a/src/main/java/org/asteriskjava/manager/action/MWIUpdateAction.java b/src/main/java/org/asteriskjava/manager/action/MWIUpdateAction.java index cb2aa9ad6..a9adfe154 100644 --- a/src/main/java/org/asteriskjava/manager/action/MWIUpdateAction.java +++ b/src/main/java/org/asteriskjava/manager/action/MWIUpdateAction.java @@ -16,8 +16,7 @@ */ package org.asteriskjava.manager.action; -public class MWIUpdateAction extends AbstractManagerAction -{ +public class MWIUpdateAction extends AbstractManagerAction { static final long serialVersionUID = 1L; private String mailbox; private int oldMessages; @@ -26,52 +25,43 @@ public class MWIUpdateAction extends AbstractManagerAction /** * Creates a new MWIUpdateAction. */ - public MWIUpdateAction() - { + public MWIUpdateAction() { } - public MWIUpdateAction(String mailbox, int oldMessages, int newMessages) - { + public MWIUpdateAction(String mailbox, int oldMessages, int newMessages) { this.mailbox = mailbox; this.oldMessages = oldMessages; this.newMessages = newMessages; } - public String getMailbox() - { + public String getMailbox() { return mailbox; } - public void setMailbox(String mailbox) - { + public void setMailbox(String mailbox) { this.mailbox = mailbox; } - public int getOldMessages() - { + public int getOldMessages() { return oldMessages; } - public void setOldMessages(int oldMessages) - { + public void setOldMessages(int oldMessages) { this.oldMessages = oldMessages; } - public int getNewMessages() - { + public int getNewMessages() { return newMessages; } - public void setNewMessages(int newMessages) - { + public void setNewMessages(int newMessages) { this.newMessages = newMessages; } @Override - public String getAction() - { + public String getAction() { return "MWIUpdate"; } diff --git a/src/main/java/org/asteriskjava/manager/action/MailboxCountAction.java b/src/main/java/org/asteriskjava/manager/action/MailboxCountAction.java index 12fed592a..7a2bb7e84 100644 --- a/src/main/java/org/asteriskjava/manager/action/MailboxCountAction.java +++ b/src/main/java/org/asteriskjava/manager/action/MailboxCountAction.java @@ -18,8 +18,7 @@ * @see org.asteriskjava.manager.response.MailboxCountResponse */ @ExpectedResponse(MailboxCountResponse.class) -public class MailboxCountAction extends AbstractManagerAction -{ +public class MailboxCountAction extends AbstractManagerAction { static final long serialVersionUID = -6900421919824575941L; private String mailbox; @@ -27,8 +26,7 @@ public class MailboxCountAction extends AbstractManagerAction /** * Creates a new empty MailboxCountAction. */ - public MailboxCountAction() - { + public MailboxCountAction() { } @@ -42,8 +40,7 @@ public MailboxCountAction() * "default" is assumed. * @since 0.2 */ - public MailboxCountAction(String mailbox) - { + public MailboxCountAction(String mailbox) { this.mailbox = mailbox; } @@ -51,16 +48,14 @@ public MailboxCountAction(String mailbox) * Returns the name of this action, i.e. "MailboxCount". */ @Override - public String getAction() - { + public String getAction() { return "MailboxCount"; } /** * Returns the name of the mailbox to query. */ - public String getMailbox() - { + public String getMailbox() { return mailbox; } @@ -70,8 +65,7 @@ public String getMailbox() * mailboxnumber@context.If no context is specified "default" is assumed.

    * This property is mandatory. */ - public void setMailbox(String mailbox) - { + public void setMailbox(String mailbox) { this.mailbox = mailbox; } } diff --git a/src/main/java/org/asteriskjava/manager/action/MailboxStatusAction.java b/src/main/java/org/asteriskjava/manager/action/MailboxStatusAction.java index e567ae4fc..a9091058d 100644 --- a/src/main/java/org/asteriskjava/manager/action/MailboxStatusAction.java +++ b/src/main/java/org/asteriskjava/manager/action/MailboxStatusAction.java @@ -28,8 +28,7 @@ * @see org.asteriskjava.manager.response.MailboxStatusResponse */ @ExpectedResponse(MailboxStatusResponse.class) -public class MailboxStatusAction extends AbstractManagerAction -{ +public class MailboxStatusAction extends AbstractManagerAction { static final long serialVersionUID = -3845028207155711950L; private String mailbox; @@ -37,8 +36,7 @@ public class MailboxStatusAction extends AbstractManagerAction /** * Creates a new empty MailboxStatusAction. */ - public MailboxStatusAction() - { + public MailboxStatusAction() { } @@ -52,8 +50,7 @@ public MailboxStatusAction() * "default" is assumed. * @since 0.2 */ - public MailboxStatusAction(String mailbox) - { + public MailboxStatusAction(String mailbox) { this.mailbox = mailbox; } @@ -61,16 +58,14 @@ public MailboxStatusAction(String mailbox) * Returns the name of this action, i.e. "MailboxStatus". */ @Override - public String getAction() - { + public String getAction() { return "MailboxStatus"; } /** * Returns the name of the mailbox to query. */ - public String getMailbox() - { + public String getMailbox() { return mailbox; } @@ -84,8 +79,7 @@ public String getMailbox() * This property is mandatory.

    * Example: "1234,1235@mycontext" */ - public void setMailbox(String mailbox) - { + public void setMailbox(String mailbox) { this.mailbox = mailbox; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ManagerAction.java b/src/main/java/org/asteriskjava/manager/action/ManagerAction.java index 83ee2a6e6..93c578dab 100644 --- a/src/main/java/org/asteriskjava/manager/action/ManagerAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ManagerAction.java @@ -27,12 +27,11 @@ * engine.

    * There is one conrete subclass of ManagerAction per each supported Asterisk * Action. - * + * * @author srt * @version $Id$ */ -public interface ManagerAction extends Serializable -{ +public interface ManagerAction extends Serializable { /** * Returns the name of the action for example "Hangup". */ @@ -40,7 +39,7 @@ public interface ManagerAction extends Serializable /** * Returns the action id. - * + * * @return the user provied action id. */ String getActionId(); @@ -51,14 +50,14 @@ public interface ManagerAction extends Serializable * returned by the Asterisk server will include the same id. This way * the action id can be used to track actions and their corresponding * responses and response events.

    - * Note that Asterisk-Java uses its own internal action id to match + * Note that Asterisk-Java uses its own internal action id to match * actions with the corresponding responses and events. Though the internal - * action is never exposed to the application code. So if you want to + * action is never exposed to the application code. So if you want to * handle reponses or response events on your own your application must * set a unique action id using this method otherwise the action id of * the reponse and response event objects passed to your application * will be null. - * + * * @param actionId the user provided action id to set. * @see org.asteriskjava.manager.response.ManagerResponse#getActionId() * @see org.asteriskjava.manager.event.ResponseEvent#getActionId() diff --git a/src/main/java/org/asteriskjava/manager/action/MeetMeMuteAction.java b/src/main/java/org/asteriskjava/manager/action/MeetMeMuteAction.java index ff607beab..28ff55fbc 100644 --- a/src/main/java/org/asteriskjava/manager/action/MeetMeMuteAction.java +++ b/src/main/java/org/asteriskjava/manager/action/MeetMeMuteAction.java @@ -20,12 +20,11 @@ * The MeetMeMuteAction mutes a user in a conference.

    * Defined in apps/app_meetme.c

    * Available since Asterisk 1.4. - * + * * @author srt * @version $Id$ */ -public class MeetMeMuteAction extends AbstractMeetMeMuteAction -{ +public class MeetMeMuteAction extends AbstractMeetMeMuteAction { /** * Serializable version identifier */ @@ -34,19 +33,17 @@ public class MeetMeMuteAction extends AbstractMeetMeMuteAction /** * Creates a new empty MeetMeMuteAction. */ - public MeetMeMuteAction() - { + public MeetMeMuteAction() { super(); } /** * Creates a new MeetMeMuteAction. - * - * @param meetMe the conference number. + * + * @param meetMe the conference number. * @param userNum the index of the user in the conference. */ - public MeetMeMuteAction(String meetMe, Integer userNum) - { + public MeetMeMuteAction(String meetMe, Integer userNum) { super(meetMe, userNum); } @@ -54,8 +51,7 @@ public MeetMeMuteAction(String meetMe, Integer userNum) * Returns the name of this action, i.e. "MeetMeMute". */ @Override - public String getAction() - { + public String getAction() { return "MeetMeMute"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/MeetMeUnmuteAction.java b/src/main/java/org/asteriskjava/manager/action/MeetMeUnmuteAction.java index 6fa44a1f9..96137e241 100644 --- a/src/main/java/org/asteriskjava/manager/action/MeetMeUnmuteAction.java +++ b/src/main/java/org/asteriskjava/manager/action/MeetMeUnmuteAction.java @@ -20,12 +20,11 @@ * The MeetMeUnmuteAction unmutes a user in a conference.

    * Defined in apps/app_meetme.c

    * Available since Asterisk 1.4. - * + * * @author srt * @version $Id$ */ -public class MeetMeUnmuteAction extends AbstractMeetMeMuteAction -{ +public class MeetMeUnmuteAction extends AbstractMeetMeMuteAction { /** * Serializable version identifier */ @@ -34,19 +33,17 @@ public class MeetMeUnmuteAction extends AbstractMeetMeMuteAction /** * Creates a new empty MeetMeUnmuteAction. */ - public MeetMeUnmuteAction() - { + public MeetMeUnmuteAction() { super(); } /** * Creates a new MeetMeUnmuteAction. - * - * @param meetMe the conference number. + * + * @param meetMe the conference number. * @param userNum the index of the user in the conference. */ - public MeetMeUnmuteAction(String meetMe, Integer userNum) - { + public MeetMeUnmuteAction(String meetMe, Integer userNum) { super(meetMe, userNum); } @@ -54,8 +51,7 @@ public MeetMeUnmuteAction(String meetMe, Integer userNum) * Returns the name of this action, i.e. "MeetMeUnmute". */ @Override - public String getAction() - { + public String getAction() { return "MeetMeUnmute"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/MessageSendAction.java b/src/main/java/org/asteriskjava/manager/action/MessageSendAction.java index b9f65b78f..b13218c65 100644 --- a/src/main/java/org/asteriskjava/manager/action/MessageSendAction.java +++ b/src/main/java/org/asteriskjava/manager/action/MessageSendAction.java @@ -10,8 +10,7 @@ * @version $Id$ * @since 1.0.0 */ -public class MessageSendAction extends AbstractManagerAction -{ +public class MessageSendAction extends AbstractManagerAction { private static final long serialVersionUID = -6554282385166411723L; private String to; @@ -21,8 +20,7 @@ public class MessageSendAction extends AbstractManagerAction private Map variables; @Override - public String getAction() - { + public String getAction() { return "MessageSend"; } @@ -33,22 +31,19 @@ public String getAction() * value. * @since 1.0.0 */ - public Map getVariables() - { + public Map getVariables() { return variables; } /** * Sets an variable on the originated call. * - * @param name the name of the variable to set. + * @param name the name of the variable to set. * @param value the value of the variable to set. * @since 1.0.0 */ - public void setVariable(String name, String value) - { - if (variables == null) - { + public void setVariable(String name, String value) { + if (variables == null) { variables = new LinkedHashMap<>(); } @@ -57,91 +52,85 @@ public void setVariable(String name, String value) /** * Retrives destination of message - * + * * @return String in format like sip:userid */ - public String getTo() - { + public String getTo() { return to; } /** * Set destination of message - * + * * @param to String in format like sip:userid */ - public void setTo(String to) - { + public void setTo(String to) { this.to = to; } /** * get From String - * + * * @return String in form like sip:asterisk@server-ip */ - public String getFrom() - { + public String getFrom() { return from; } /** - * set From String + * set From String + * * @param String from in form like sip:asterisk@server-ip */ - public void setFrom(String from) - { + public void setFrom(String from) { this.from = from; } /** * Content of the message in plain text ascii * Please consider to use getBase64Body instead to avoid encoding problems - * + * * @return String with Message content */ - public String getBody() - { + public String getBody() { return body; } /** * Sets the content of the message * Please consider to use setBase64Body instead to avoid encoding problems - * + * * @param body String with plain ascii content */ - public void setBody(String body) - { + public void setBody(String body) { this.body = body; } /** * Retrieves content encoded in base64 - * - * @code new String(Base64.decode(getBase64body(), Formatting (for ex "UTF-8")) + * * @return Base64 encoded String + * @code new String(Base64.decode(getBase64body(), Formatting (for ex "UTF-8")) */ - public String getBase64body() - { + public String getBase64body() { return base64body; } /** * Sets the content of the message body encode in base64 - * + *

    * {@code MessageSendAction sipSendMessage = new MessageSendAction(); - * sipSendMessage.setTo("sip:phoneuserid"); - * sipSendMessage.setVariable("Content-Type", "text/plain"); - * sipSendMessage.setVariable("P-hint", "usrloc applied"); - * - * sipSendMessage.setActionId(UUID.randomUUID().toString()); - * sipSendMessage.setBase64body(new String(Base64.encodeBase64(message.getBytes("UTF-8")), "UTF-8")); + * sipSendMessage.setTo("sip:phoneuserid"); + * sipSendMessage.setVariable("Content-Type", "text/plain"); + * sipSendMessage.setVariable("P-hint", "usrloc applied"); + *

    + * sipSendMessage.setActionId(UUID.randomUUID().toString()); + * sipSendMessage.setBase64body(new String(Base64.encodeBase64(message.getBytes("UTF-8")), "UTF-8")); * } - * @param base64body + * + * @param base64body */ - public void setBase64body(String base64body) - { + public void setBase64body(String base64body) { this.base64body = base64body; } diff --git a/src/main/java/org/asteriskjava/manager/action/MixMonitorAction.java b/src/main/java/org/asteriskjava/manager/action/MixMonitorAction.java index a66023ff2..fa7bc94c5 100644 --- a/src/main/java/org/asteriskjava/manager/action/MixMonitorAction.java +++ b/src/main/java/org/asteriskjava/manager/action/MixMonitorAction.java @@ -21,7 +21,7 @@ /** * Start a MixMonitor on the specified channel. - * + *

    * Available since Asterisk 11 * * @see org.asteriskjava.manager.response.MixMonitorResponse @@ -30,8 +30,7 @@ * @see MixMonitorMuteAction */ @ExpectedResponse(MixMonitorResponse.class) -public class MixMonitorAction extends AbstractManagerAction -{ +public class MixMonitorAction extends AbstractManagerAction { private static final long serialVersionUID = 1L; private String channel; private String file; @@ -41,8 +40,7 @@ public class MixMonitorAction extends AbstractManagerAction /** * Creates a new empty MixMonitorAction */ - public MixMonitorAction() - { + public MixMonitorAction() { super(); } @@ -50,10 +48,9 @@ public MixMonitorAction() * Creates a new MixMonitorAction that starts monitoring the given channel * using a default filename. * - * @param channel the name of the channel to monitor + * @param channel the name of the channel to monitor */ - public MixMonitorAction(String channel) - { + public MixMonitorAction(String channel) { this(channel, null, null, null); } @@ -61,11 +58,10 @@ public MixMonitorAction(String channel) * Creates a new MixMonitorAction that starts monitoring the given channel * with the specified filename. * - * @param channel the name of the channel to monitor - * @param filename the filename to use for the recording + * @param channel the name of the channel to monitor + * @param filename the filename to use for the recording */ - public MixMonitorAction(String channel, String filename) - { + public MixMonitorAction(String channel, String filename) { this(channel, filename, null, null); } @@ -73,12 +69,11 @@ public MixMonitorAction(String channel, String filename) * Creates a new MixMonitorAction with options that starts monitoring the * given channel with the specified filename. * - * @param channel the name of the channel to monitor - * @param filename the filename to use for the recording - * @param options the MixMonitor options to use when starting the recording + * @param channel the name of the channel to monitor + * @param filename the filename to use for the recording + * @param options the MixMonitor options to use when starting the recording */ - public MixMonitorAction(String channel, String filename, String options) - { + public MixMonitorAction(String channel, String filename, String options) { this(channel, filename, options, null); } @@ -86,16 +81,15 @@ public MixMonitorAction(String channel, String filename, String options) * Creates a new MixMonitorAction with options that starts monitoring the * given channel with the specified filename. Also takes a command to * execute when the recording has ended. - * + *

    * The {@code command} option has been available since Asterisk 12 * - * @param channel the name of the channel to monitor - * @param filename the filename to use for the recording - * @param options the MixMonitor options to use when starting the recording - * @param command the command to execute when the recording is complete + * @param channel the name of the channel to monitor + * @param filename the filename to use for the recording + * @param options the MixMonitor options to use when starting the recording + * @param command the command to execute when the recording is complete */ - public MixMonitorAction(String channel, String filename, String options, String command) - { + public MixMonitorAction(String channel, String filename, String options, String command) { this.channel = channel; this.file = filename; this.options = options; @@ -108,8 +102,7 @@ public MixMonitorAction(String channel, String filename, String options, String * @return the name of the AMI action that this class implements */ @Override - public String getAction() - { + public String getAction() { return "MixMonitor"; } @@ -118,8 +111,7 @@ public String getAction() * * @return the Asterisk channel name */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -128,8 +120,7 @@ public String getChannel() * * @param channel the Asterisk channel name */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -138,8 +129,7 @@ public void setChannel(String channel) * * @return the recording filename */ - public String getFile() - { + public String getFile() { return file; } @@ -148,8 +138,7 @@ public String getFile() * * @param filename the recording filename */ - public void setFile(String filename) - { + public void setFile(String filename) { this.file = filename; } @@ -158,8 +147,7 @@ public void setFile(String filename) * * @return the MixMonitor options */ - public String getOptions() - { + public String getOptions() { return options; } @@ -170,34 +158,31 @@ public String getOptions() * * @param options the MixMonitor options */ - public void setOptions(String options) - { + public void setOptions(String options) { this.options = options; } /** * Get the command to be executed when the MixMonitor recording has * ended. - * + *

    * Available since Asterisk 12 * * @return the command to execute */ - public String getCommand() - { + public String getCommand() { return command; } /** * Sets the command to be executed when the MixMonitor recording has * ended. - * + *

    * Available since Asterisk 12 * * @param command the command to execute */ - public void setCommand(String command) - { + public void setCommand(String command) { this.command = command; } } diff --git a/src/main/java/org/asteriskjava/manager/action/MixMonitorMuteAction.java b/src/main/java/org/asteriskjava/manager/action/MixMonitorMuteAction.java index 0be1bc764..1110c239c 100644 --- a/src/main/java/org/asteriskjava/manager/action/MixMonitorMuteAction.java +++ b/src/main/java/org/asteriskjava/manager/action/MixMonitorMuteAction.java @@ -17,126 +17,128 @@ /** * MixMonitorMute can be used to mute and un-mute an existing recording. + * * @author Bob Wienholt * @version $Id$ */ -public class MixMonitorMuteAction extends AbstractManagerAction -{ - private static final long serialVersionUID = 1L; - private String channel; - private String direction; - private Integer state; +public class MixMonitorMuteAction extends AbstractManagerAction { + private static final long serialVersionUID = 1L; + private String channel; + private String direction; + private Integer state; + + /** + * Creates a new empty MixMonitorMuteAction + */ + public MixMonitorMuteAction() { + super(); + } + + /** + * Mutes the monitor on the given channel. + * + * @param channel + */ + public MixMonitorMuteAction(String channel) { + super(); + this.channel = channel; + } + + /** + * Mutes the monitor on the given channel for the given portion + * of the call. + * + * @param channel + * @param direction + */ + public MixMonitorMuteAction(String channel, String direction) { + super(); + this.channel = channel; + this.direction = direction; + } + + /** + * Either mutes or un-mutes the monitor on the given channel for + * the given portion of the call. + * + * @param channel + * @param direction + * @param state + */ + public MixMonitorMuteAction(String channel, String direction, Integer state) { + super(); + this.channel = channel; + this.direction = direction; + this.state = state; + } + + /** + * Either mutes or un-mutes the monitor on the given channel. + * + * @param channel + * @param state + */ + public MixMonitorMuteAction(String channel, Integer state) { + super(); + this.channel = channel; + this.state = state; + } + + /** + * Returns the name of this action. + */ + @Override + public String getAction() { + return "MixMonitorMute"; + } - /** - * Creates a new empty MixMonitorMuteAction - */ - public MixMonitorMuteAction() - { - super(); - } - - /** - * Mutes the monitor on the given channel. - * @param channel - */ - public MixMonitorMuteAction(String channel) - { - super(); - this.channel = channel; - } - - /** - * Mutes the monitor on the given channel for the given portion - * of the call. - * @param channel - * @param direction - */ - public MixMonitorMuteAction(String channel, String direction) - { - super(); - this.channel = channel; - this.direction = direction; - } - - /** - * Either mutes or un-mutes the monitor on the given channel for - * the given portion of the call. - * @param channel - * @param direction - * @param state - */ - public MixMonitorMuteAction(String channel, String direction, Integer state) - { - super(); - this.channel = channel; - this.direction = direction; - this.state = state; - } - - /** - * Either mutes or un-mutes the monitor on the given channel. - * @param channel - * @param state - */ - public MixMonitorMuteAction(String channel, Integer state) - { - super(); - this.channel = channel; - this.state = state; - } - - /** - * Returns the name of this action. - */ - @Override - public String getAction() { - return "MixMonitorMute"; - } + /** + * Returns the name of the channel to mute. + */ + public String getChannel() { + return channel; + } - /** - * Returns the name of the channel to mute. - */ - public String getChannel() { - return channel; - } + /** + * Sets the name of the channel to mute. + * + * @param channel + */ + public void setChannel(String channel) { + this.channel = channel; + } - /** - * Sets the name of the channel to mute. - * @param channel - */ - public void setChannel(String channel) { - this.channel = channel; - } + /** + * Gets the direction of the part of the recording to mute. + */ + public String getDirection() { + return direction; + } - /** - * Gets the direction of the part of the recording to mute. - */ - public String getDirection() { - return direction; - } + /** + * Sets the direction of the part of the recording to mute. + * Can be one of: read, write, or both. Defaults to both. + * + * @param direction + */ + public void setDirection(String direction) { + this.direction = direction; + } - /** - * Sets the direction of the part of the recording to mute. - * Can be one of: read, write, or both. Defaults to both. - * @param direction - */ - public void setDirection(String direction) { - this.direction = direction; - } + /** + * Gets the state of the mute. + */ + public Integer getState() { + return state; + } - /** - * Gets the state of the mute. - */ - public Integer getState() { - return state; - } + /** + * Sets the state of the mute operation. 1 = on, 0 = off. + * + * @param state + */ + public void setState(Integer state) { + this.state = state; + } - /** - * Sets the state of the mute operation. 1 = on, 0 = off. - * @param state - */ - public void setState(Integer state) { - this.state = state; - } - } diff --git a/src/main/java/org/asteriskjava/manager/action/ModuleCheckAction.java b/src/main/java/org/asteriskjava/manager/action/ModuleCheckAction.java index 8822b4582..3c368d3aa 100644 --- a/src/main/java/org/asteriskjava/manager/action/ModuleCheckAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ModuleCheckAction.java @@ -31,8 +31,7 @@ * @since 1.0.0 */ @ExpectedResponse(ModuleCheckResponse.class) -public class ModuleCheckAction extends AbstractManagerAction -{ +public class ModuleCheckAction extends AbstractManagerAction { static final long serialVersionUID = 1L; private String module; @@ -40,8 +39,7 @@ public class ModuleCheckAction extends AbstractManagerAction /** * Creates a new ModuleCheckAction. */ - public ModuleCheckAction() - { + public ModuleCheckAction() { } @@ -50,8 +48,7 @@ public ModuleCheckAction() * * @param module the name of the module (including or not including the ".so" extension). */ - public ModuleCheckAction(String module) - { + public ModuleCheckAction(String module) { this.module = module; } @@ -59,8 +56,7 @@ public ModuleCheckAction(String module) * Returns the name of this action, i.e. "ModuleLoad". */ @Override - public String getAction() - { + public String getAction() { return "ModuleCheck"; } @@ -69,8 +65,7 @@ public String getAction() * * @return the name of the module to check. */ - public String getModule() - { + public String getModule() { return module; } @@ -79,8 +74,7 @@ public String getModule() * * @param module the name of the module (including or not including the ".so" extension) to check. */ - public void setModule(String module) - { + public void setModule(String module) { this.module = module; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/ModuleLoadAction.java b/src/main/java/org/asteriskjava/manager/action/ModuleLoadAction.java index 0d92b99cf..632b28bff 100644 --- a/src/main/java/org/asteriskjava/manager/action/ModuleLoadAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ModuleLoadAction.java @@ -24,8 +24,7 @@ * @version $Id$ * @since 1.0.0 */ -public class ModuleLoadAction extends AbstractManagerAction -{ +public class ModuleLoadAction extends AbstractManagerAction { static final long serialVersionUID = 1L; public static final String SUBSYSTEM_CDR = "cdr"; @@ -46,8 +45,7 @@ public class ModuleLoadAction extends AbstractManagerAction /** * Creates a new ModuleLoadAction. */ - public ModuleLoadAction() - { + public ModuleLoadAction() { } @@ -59,8 +57,7 @@ public ModuleLoadAction() * to reload all modules. * @param loadType the operation to perform ("load", "unload" or "reload"). */ - public ModuleLoadAction(String module, String loadType) - { + public ModuleLoadAction(String module, String loadType) { this.module = module; this.loadType = loadType; } @@ -69,8 +66,7 @@ public ModuleLoadAction(String module, String loadType) * Returns the name of this action, i.e. "ModuleLoad". */ @Override - public String getAction() - { + public String getAction() { return "ModuleLoad"; } @@ -79,8 +75,7 @@ public String getAction() * * @return the name of the module or subsystem to perform the operation on. */ - public String getModule() - { + public String getModule() { return module; } @@ -99,8 +94,7 @@ public String getModule() * @see #SUBSYSTEM_RTP * @see #SUBSYSTEM_HTTP */ - public void setModule(String module) - { + public void setModule(String module) { this.module = module; } @@ -109,8 +103,7 @@ public void setModule(String module) * * @return the operation to perform. */ - public String getLoadType() - { + public String getLoadType() { return loadType; } @@ -122,8 +115,7 @@ public String getLoadType() * @see #LOAD_TYPE_UNLOAD * @see #LOAD_TYPE_RELOAD */ - public void setLoadType(String loadType) - { + public void setLoadType(String loadType) { this.loadType = loadType; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/MonitorAction.java b/src/main/java/org/asteriskjava/manager/action/MonitorAction.java index ba8416771..dfd47f6f2 100644 --- a/src/main/java/org/asteriskjava/manager/action/MonitorAction.java +++ b/src/main/java/org/asteriskjava/manager/action/MonitorAction.java @@ -19,12 +19,11 @@ /** * The MonitorAction starts monitoring (recording) a channel.

    * It is implemented in res/res_monitor.c - * + * * @author srt * @version $Id$ */ -public class MonitorAction extends AbstractManagerAction -{ +public class MonitorAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -37,8 +36,7 @@ public class MonitorAction extends AbstractManagerAction /** * Creates a new empty MonitorAction. */ - public MonitorAction() - { + public MonitorAction() { super(); } @@ -46,14 +44,13 @@ public MonitorAction() * Creates a new MonitorAction that starts monitoring the given channel and * writes voice data to the given files.

    * The format of the files is "wav", they are not mixed. - * + * * @param channel the name of the channel to monitor - * @param file the (base) name of the files to which the voice data is - * written + * @param file the (base) name of the files to which the voice data is + * written * @since 0.2 */ - public MonitorAction(String channel, String file) - { + public MonitorAction(String channel, String file) { super(); this.channel = channel; this.file = file; @@ -63,15 +60,14 @@ public MonitorAction(String channel, String file) * Creates a new MonitorAction that starts monitoring the given channel and * writes voice data to the given files.

    * The files are not mixed. - * + * * @param channel the name of the channel to monitor - * @param file the (base) name of the files to which the voice data is - * written - * @param format the format to use for encoding the voice files + * @param file the (base) name of the files to which the voice data is + * written + * @param format the format to use for encoding the voice files * @since 0.2 */ - public MonitorAction(String channel, String file, String format) - { + public MonitorAction(String channel, String file, String format) { super(); this.channel = channel; this.file = file; @@ -81,17 +77,16 @@ public MonitorAction(String channel, String file, String format) /** * Creates a new MonitorAction that starts monitoring the given channel and * writes voice data to the given file(s). - * + * * @param channel the name of the channel to monitor - * @param file the (base) name of the file(s) to which the voice data is - * written - * @param format the format to use for encoding the voice files - * @param mix true if the two voice files should be joined at the end of the - * call + * @param file the (base) name of the file(s) to which the voice data is + * written + * @param format the format to use for encoding the voice files + * @param mix true if the two voice files should be joined at the end of the + * call * @since 0.2 */ - public MonitorAction(String channel, String file, String format, Boolean mix) - { + public MonitorAction(String channel, String file, String format, Boolean mix) { super(); this.channel = channel; this.file = file; @@ -103,16 +98,14 @@ public MonitorAction(String channel, String file, String format, Boolean mix) * Returns the name of this action, i.e. "Monitor". */ @Override - public String getAction() - { + public String getAction() { return "Monitor"; } /** * Returns the name of the channel to monitor. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -120,16 +113,14 @@ public String getChannel() * Sets the name of the channel to monitor.

    * This property is mandatory. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the name of the file to which the voice data is written. */ - public String getFile() - { + public String getFile() { return file; } @@ -138,16 +129,14 @@ public String getFile() * If this property is not set it defaults to to the channel name as per CLI * with the '/' replaced by '-'. */ - public void setFile(String file) - { + public void setFile(String file) { this.file = file; } /** * Returns the format to use for encoding the voice files. */ - public String getFormat() - { + public String getFormat() { return format; } @@ -155,8 +144,7 @@ public String getFormat() * Sets the format to use for encoding the voice files.

    * If this property is not set it defaults to "wav". */ - public void setFormat(String format) - { + public void setFormat(String format) { this.format = format; } @@ -164,8 +152,7 @@ public void setFormat(String format) * Returns true if the two voice files should be joined at the end of the * call. */ - public Boolean getMix() - { + public Boolean getMix() { return mix; } @@ -173,8 +160,7 @@ public Boolean getMix() * Set to true if the two voice files should be joined at the end of the * call. */ - public void setMix(Boolean mix) - { + public void setMix(Boolean mix) { this.mix = mix; } } diff --git a/src/main/java/org/asteriskjava/manager/action/MuteAudioAction.java b/src/main/java/org/asteriskjava/manager/action/MuteAudioAction.java index e206fe345..0b49c16b0 100644 --- a/src/main/java/org/asteriskjava/manager/action/MuteAudioAction.java +++ b/src/main/java/org/asteriskjava/manager/action/MuteAudioAction.java @@ -22,129 +22,116 @@ * Variables: Channel: The channel you want to mute. Direction: in | out * |all The stream you want to mute. State: on | off Whether to turn mute on or * off. ActionID: Optional action ID for this AMI transaction. - * + *

    * It is defined in res/res_mutestream.c. *

    * Available since Asterisk 1.8 - * + * * @author sbs * @version $Id: MuteAction.java 938 2007-12-31 03:23:38Z srt $ * @since 1.0.0 */ -public class MuteAudioAction extends AbstractManagerAction -{ - /** - * Serializable version identifier. - */ - private static final long serialVersionUID = 0L; - - private String channel; - - /** The audio direct (relative to the pbx) which is to be muted. */ - public enum Direction - { - IN("in"), OUT("out"), ALL("all"); - - String value; - - Direction(String value) - { - this.value = value; - } - - public String toString() - { - return this.value; - } - } - - private Direction direction; - - /** Controls whether to mute (on) or unmute (off) the call **/ - public enum State - { - MUTE("on"), UNMUTE("off"); //$NON-NLS-1$//$NON-NLS-2$ - - String value; - - State(String value) - { - this.value = value; - } - - public String toString() - { - return this.value; - } - - } - - private State state; - - /** - * Creates a new empty MuteAction. - */ - public MuteAudioAction() - { - - } - - /** - * Creates a new MuteAction that Mutes or Unmutes the two given channel. - * - * @param channel - * the name of the channel to Mute. - * - * @param direction - * the audio direction which is to be muted/unmuted - * - * @param state controls whether we are muting or unmuting the channel. - */ - - public MuteAudioAction(String channel, Direction direction, State state) - { - this.channel = channel; - this.direction = direction; - this.state = state; - } - - /** - * Returns the name of this action, i.e. "MuteAudio". - */ - @Override - public String getAction() - { - return "MuteAudio"; //$NON-NLS-1$ - } - +public class MuteAudioAction extends AbstractManagerAction { + /** + * Serializable version identifier. + */ + private static final long serialVersionUID = 0L; + + private String channel; + + /** + * The audio direct (relative to the pbx) which is to be muted. + */ + public enum Direction { + IN("in"), OUT("out"), ALL("all"); + + String value; + + Direction(String value) { + this.value = value; + } + + public String toString() { + return this.value; + } + } + + private Direction direction; + + /** + * Controls whether to mute (on) or unmute (off) the call + **/ + public enum State { + MUTE("on"), UNMUTE("off"); //$NON-NLS-1$//$NON-NLS-2$ + + String value; + + State(String value) { + this.value = value; + } + + public String toString() { + return this.value; + } + + } + + private State state; + + /** + * Creates a new empty MuteAction. + */ + public MuteAudioAction() { + + } + + /** + * Creates a new MuteAction that Mutes or Unmutes the two given channel. + * + * @param channel the name of the channel to Mute. + * @param direction the audio direction which is to be muted/unmuted + * @param state controls whether we are muting or unmuting the channel. + */ + + public MuteAudioAction(String channel, Direction direction, State state) { + this.channel = channel; + this.direction = direction; + this.state = state; + } + + /** + * Returns the name of this action, i.e. "MuteAudio". + */ + @Override + public String getAction() { + return "MuteAudio"; //$NON-NLS-1$ + } + /** * Returns the name of the channel to monitor. - */ - public String getChannel() - { - return this.channel; - } - + */ + public String getChannel() { + return this.channel; + } + /** * Returns the audio direction which is to be muted/unmuted. - */ - public Direction getDirection() - { - return this.direction; - } - + */ + public Direction getDirection() { + return this.direction; + } + /** * Returns the state controls whether we are muting or unmuting the channel. - */ - public State getState() - { - return this.state; - } + */ + public State getState() { + return this.state; + } /** * Sets the name of the channel to monitor.

    * This property is mandatory. - */ + */ public void setChannel(String channel) { this.channel = channel; } @@ -152,7 +139,7 @@ public void setChannel(String channel) { /** * Sets the audio direction which is to be muted/unmuted.

    * This property is mandatory. - */ + */ public void setDirection(Direction direction) { this.direction = direction; } @@ -160,9 +147,9 @@ public void setDirection(Direction direction) { /** * Sets the state controls whether we are muting or unmuting the channel.

    * This property is mandatory. - */ + */ public void setState(State state) { this.state = state; - } + } } diff --git a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java index 4d3ab62c3..964e2b77e 100644 --- a/src/main/java/org/asteriskjava/manager/action/OriginateAction.java +++ b/src/main/java/org/asteriskjava/manager/action/OriginateAction.java @@ -16,19 +16,13 @@ */ package org.asteriskjava.manager.action; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; - import org.asteriskjava.manager.event.OriginateResponseEvent; import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.*; + /** * The OriginateAction generates an outgoing call to the extension in the given * context with the given priority or to a given application with optional @@ -52,8 +46,7 @@ * @version $Id$ * @see org.asteriskjava.manager.event.OriginateResponseEvent */ -public class OriginateAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class OriginateAction extends AbstractManagerAction implements EventGeneratingAction { private final Log logger = LogFactory.getLog(getClass()); @@ -90,8 +83,7 @@ public class OriginateAction extends AbstractManagerAction implements EventGener * @return the name of this action. */ @Override - public String getAction() - { + public String getAction() { return "Originate"; } @@ -100,8 +92,7 @@ public String getAction() * * @return the account code to use for the originated call. */ - public String getAccount() - { + public String getAccount() { return account; } @@ -113,16 +104,14 @@ public String getAccount() * * @param account the account code to use for the originated call. */ - public void setAccount(String account) - { + public void setAccount(String account) { this.account = account; } /** * Returns the caller id to set on the outgoing channel. */ - public String getCallerId() - { + public String getCallerId() { return callerId; } @@ -134,8 +123,7 @@ public String getCallerId() * * @param callerId the caller id to set on the outgoing channel. */ - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { this.callerId = callerId; } @@ -147,8 +135,7 @@ public void setCallerId(String callerId) * @return the calling presentation for the outgoing channel. * @see #setCallingPres(Integer) */ - public Integer getCallingPres() - { + public Integer getCallingPres() { return callingPres; } @@ -167,7 +154,7 @@ public Integer getCallingPres() *

    *
    * Presentation indicator (Bits 6 and 7): - * + * *

          * Bits Meaning
          *  7 6
    @@ -176,9 +163,9 @@ public Integer getCallingPres()
          *  1 0 Number not available due to interworking
          *  1 1 Reserved
          * 
    - * + *

    * Screening indicator (Bits 1 and 2): - * + * *

          * Bits Meaning
          *  2 1
    @@ -187,30 +174,28 @@ public Integer getCallingPres()
          *  1 0 User-provided, verified and failed
          *  1 1 Network provided
          * 
    - * + *

    * Examples for some general settings: - * + * *

          * Presentation Allowed, Network Provided: 3 (00000011)
          * Presentation Restricted, User-provided, not screened: 32 (00100000)
          * Presentation Restricted, User-provided, verified, and passed: 33 (00100001)
          * Presentation Restricted, Network Provided: 35 (00100011)
          * 
    - * + *

    * This property is only available on BRIstuffed Asterisk servers. * * @param callingPres the calling presentation for the outgoing channel. */ - public void setCallingPres(Integer callingPres) - { + public void setCallingPres(Integer callingPres) { this.callingPres = callingPres; } /** * Returns the name of the channel to connect to the outgoing call. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -219,16 +204,14 @@ public String getChannel() *

    * This property is mandatory. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the name of the context of the extension to connect to. */ - public String getContext() - { + public String getContext() { return context; } @@ -238,16 +221,14 @@ public String getContext() * If you set the context you also have to set the exten and priority * properties. */ - public void setContext(String context) - { + public void setContext(String context) { this.context = context; } /** * Returns the extension to connect to. */ - public String getExten() - { + public String getExten() { return exten; } @@ -257,16 +238,14 @@ public String getExten() * If you set the extension you also have to set the context and priority * properties. */ - public void setExten(String exten) - { + public void setExten(String exten) { this.exten = exten; } /** * Returns the priority of the extension to connect to. */ - public Integer getPriority() - { + public Integer getPriority() { return priority; } @@ -274,48 +253,42 @@ public Integer getPriority() * Sets the priority of the extension to connect to. If you set the priority * you also have to set the context and exten properties. */ - public void setPriority(Integer priority) - { + public void setPriority(Integer priority) { this.priority = priority; } /** * Returns the name of the application to connect to. */ - public String getApplication() - { + public String getApplication() { return application; } /** * Sets the name of the application to connect to. */ - public void setApplication(String application) - { + public void setApplication(String application) { this.application = application; } /** * Returns the parameters to pass to the application. */ - public String getData() - { + public String getData() { return data; } /** * Sets the parameters to pass to the application. */ - public void setData(String data) - { + public void setData(String data) { this.data = data; } /** * Returns the timeout for the origination. */ - public Long getTimeout() - { + public Long getTimeout() { return timeout; } @@ -331,23 +304,17 @@ public Long getTimeout() * @deprecated use {@link #setTimeout(Long)} instead. */ @Deprecated - public void setTimeout(Integer timeout) - { - if (timeout != null) - { - if (timeout < 1000) - { + public void setTimeout(Integer timeout) { + if (timeout != null) { + if (timeout < 1000) { logger.error("A timeout of 1000 will cause the originate to almost cretainly fail!"); } - if (timeout < 10000) - { + if (timeout < 10000) { logger.warn( "A timeout of less than 10000 will cause the originate to fail if not answered within 10 seconds!"); } this.timeout = timeout.longValue(); - } - else - { + } else { this.timeout = null; } } @@ -362,16 +329,12 @@ public void setTimeout(Integer timeout) * * @param timeout the timeout in milliseconds */ - public void setTimeout(Long timeout) - { - if (timeout != null) - { - if (timeout < 1000) - { + public void setTimeout(Long timeout) { + if (timeout != null) { + if (timeout < 1000) { logger.error("A timeout of 1000 will cause the originate to almost cretainly fail!"); } - if (timeout < 10000) - { + if (timeout < 10000) { logger.warn( "A timeout of less than 100000 will cause the originate to fail if not answered within 10 seconds!"); } @@ -391,29 +354,23 @@ public void setTimeout(Long timeout) * @deprecated use {@link #setVariables(Map)} instead. */ @Deprecated - public void setVariable(String variable) - { + public void setVariable(String variable) { final StringTokenizer st; - if (variable == null) - { + if (variable == null) { this.variables = null; return; } st = new StringTokenizer(variable, "|"); variables = new LinkedHashMap<>(); - while (st.hasMoreTokens()) - { + while (st.hasMoreTokens()) { String[] keyValue; keyValue = st.nextToken().split("=", 2); - if (keyValue.length < 2) - { + if (keyValue.length < 2) { variables.put(keyValue[0], null); - } - else - { + } else { variables.put(keyValue[0], keyValue[1]); } } @@ -422,14 +379,12 @@ public void setVariable(String variable) /** * Sets an variable on the originated call. * - * @param name the name of the variable to set. + * @param name the name of the variable to set. * @param value the value of the variable to set. * @since 0.3 */ - public void setVariable(String name, String value) - { - if (variables == null) - { + public void setVariable(String name, String value) { + if (variables == null) { variables = new LinkedHashMap<>(); } @@ -440,11 +395,10 @@ public void setVariable(String name, String value) * Returns the variables to set on the originated call. * * @return a Map containing the variable names as key and their values as - * value. + * value. * @since 0.2 */ - public Map getVariables() - { + public Map getVariables() { return variables; } @@ -452,17 +406,13 @@ public Map getVariables() * Sets the variables to set on the originated call. * * @param variables a Map containing the variable names as key and their - * values as value. + * values as value. * @since 0.2 */ - public void setVariables(Map variables) - { - if (this.variables != null) - { + public void setVariables(Map variables) { + if (this.variables != null) { this.variables.putAll(variables); - } - else - { + } else { this.variables = variables; } } @@ -470,8 +420,7 @@ public void setVariables(Map variables) /** * Returns true if this is a fast origination. */ - public Boolean getAsync() - { + public Boolean getAsync() { return async; } @@ -479,24 +428,21 @@ public Boolean getAsync() * Set to true for fast origination. Only with fast origination Asterisk * will send OriginateSuccess- and OriginateFailureEvents. */ - public void setAsync(Boolean async) - { + public void setAsync(Boolean async) { this.async = async; } /** * @param earlyMedia the earlyMedia to set */ - public void setEarlyMedia(Boolean earlyMedia) - { + public void setEarlyMedia(Boolean earlyMedia) { this.earlyMedia = earlyMedia; } /** * @return the earlyMedia */ - public Boolean getEarlyMedia() - { + public Boolean getEarlyMedia() { return earlyMedia; } @@ -506,8 +452,7 @@ public Boolean getEarlyMedia() * @return the codecs to use for the call. * @since 1.0.0 */ - public String getCodecs() - { + public String getCodecs() { return codecs; } @@ -519,8 +464,7 @@ public String getCodecs() * @param codecs comma separated list of codecs to use for the call. * @since 1.0.0 */ - public void setCodecs(String codecs) - { + public void setCodecs(String codecs) { this.codecs = codecs; } @@ -532,62 +476,47 @@ public void setCodecs(String codecs) * @param codecs list of codecs to use for the call. * @since 1.0.0 */ - public void setCodecs(List codecs) - { - if (codecs == null || codecs.isEmpty()) - { + public void setCodecs(List codecs) { + if (codecs == null || codecs.isEmpty()) { this.codecs = null; return; } Iterator iter = codecs.iterator(); StringBuilder buffer = new StringBuilder(iter.next()); - while (iter.hasNext()) - { + while (iter.hasNext()) { buffer.append(",").append(iter.next()); } this.codecs = buffer.toString(); } - public Class< ? extends ResponseEvent> getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return OriginateResponseEvent.class; } - public void addSipHeader(VariableInheritance inheritance, String header) - { - if (!preventDuplicateSipHeaders.contains(header)) - { + public void addSipHeader(VariableInheritance inheritance, String header) { + if (!preventDuplicateSipHeaders.contains(header)) { setVariable(inheritance.getPrefix() + "SIPADDHEADER" + (headerCounter++), header); preventDuplicateSipHeaders.add(header); - if (headerCounter > 50) - { + if (headerCounter > 50) { logger.warn("I think only 50 headers are allowed by asterisk?"); } - } - else - { + } else { logger.error("Already added the sip header " + header); } } - public void addPjSipHeader(VariableInheritance inheritance, String header) - { - if (header != null) - { + public void addPjSipHeader(VariableInheritance inheritance, String header) { + if (header != null) { String[] parts = header.split(":"); - if (parts.length == 2) - { + if (parts.length == 2) { String varName = "PJSIP_HEADER" + "(add," + parts[0] + ")"; String varValue = parts[1]; - if (!preventDuplicateSipHeaders.contains(header)) - { + if (!preventDuplicateSipHeaders.contains(header)) { setVariable(varName, varValue); preventDuplicateSipHeaders.add(header); - } - else - { + } else { logger.error("Already added the sip header " + header); } } @@ -596,26 +525,22 @@ public void addPjSipHeader(VariableInheritance inheritance, String header) /** * this will be the channels uniqueID - * + * * @param channelId */ - public void setChannelId(String channelId) - { + public void setChannelId(String channelId) { this.channelId = channelId; } - public String getChannelId() - { + public String getChannelId() { return channelId; } - public void setOtherChannelId(String otherChannelId) - { + public void setOtherChannelId(String otherChannelId) { this.otherChannelId = otherChannelId; } - public String getOtherChannelId() - { + public String getOtherChannelId() { return otherChannelId; } diff --git a/src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java b/src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java index 6c261dcb8..40dd386b8 100644 --- a/src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PJSIPNotifyAction.java @@ -27,122 +27,109 @@ *

    * See: https://wiki.asterisk.org/wiki/display/AST/Asterisk+15+ManagerAction_PJSIPNotify */ -public class PJSIPNotifyAction extends AbstractManagerAction implements ManagerAction -{ - private static final long serialVersionUID = 8198467461743334704L; - private String channel; - private String endpoint; - private String uri; - private Map variables; +public class PJSIPNotifyAction extends AbstractManagerAction implements ManagerAction { + private static final long serialVersionUID = 8198467461743334704L; + private String channel; + private String endpoint; + private String uri; + private Map variables; - public PJSIPNotifyAction() - { - super(); - } + public PJSIPNotifyAction() { + super(); + } - @Override - public String getAction() - { - return "PJSIPNotify"; - } + @Override + public String getAction() { + return "PJSIPNotify"; + } - /** - * Get the PJSIP channel to send the NOTIFY on. - * - * @return - */ - public String getChannel() - { - return this.channel; - } + /** + * Get the PJSIP channel to send the NOTIFY on. + * + * @return + */ + public String getChannel() { + return this.channel; + } - /** - * Get the PJSIP endpoint to which to send the NOTIFY. - * - * @return - */ - public String getEndpoint() - { - return this.endpoint; - } + /** + * Get the PJSIP endpoint to which to send the NOTIFY. + * + * @return + */ + public String getEndpoint() { + return this.endpoint; + } - /** - * Get the URI to which to send the NOTIFY. - * - * @return - */ - public String getUri() - { - return this.uri; - } + /** + * Get the URI to which to send the NOTIFY. + * + * @return + */ + public String getUri() { + return this.uri; + } - /** - * Set the PJSIP channel name to send the NOTIFY on. This must be a PJSIP channel, - * ie. start with "PJSIP/". - * - * @param channel - */ - public void setChannel(String channel) - { - this.channel = channel; - } + /** + * Set the PJSIP channel name to send the NOTIFY on. This must be a PJSIP channel, + * ie. start with "PJSIP/". + * + * @param channel + */ + public void setChannel(String channel) { + this.channel = channel; + } - /** - * Set the PJSIP endpoint to send to NOTIFY to. - * - * @param endpoint - */ - public void setEndpoint(String endpoint) - { - this.endpoint = endpoint; - } + /** + * Set the PJSIP endpoint to send to NOTIFY to. + * + * @param endpoint + */ + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } - /** - * Set an abritrary URI to send the NOTIFY to. - * - * @param uri - */ - public void setUri(String uri) - { - this.uri = uri; - } + /** + * Set an abritrary URI to send the NOTIFY to. + * + * @param uri + */ + public void setUri(String uri) { + this.uri = uri; + } - /** - * Add a variable. - *

    - * Use the 'content' variable to specify the NOTIFY body. - * - * @param name - * @param value - */ - public void setVariable(String name, String value) - { - if (this.variables == null) - { - this.variables = new LinkedHashMap<>(); - } + /** + * Add a variable. + *

    + * Use the 'content' variable to specify the NOTIFY body. + * + * @param name + * @param value + */ + public void setVariable(String name, String value) { + if (this.variables == null) { + this.variables = new LinkedHashMap<>(); + } - this.variables.put(name, value); - } + this.variables.put(name, value); + } - /** - * Set all variables. See {@link #setVariable(String, String)}. - * - * @param variables - */ - public void setVariables(Map variables) - { - this.variables = variables; - } + /** + * Set all variables. See {@link #setVariable(String, String)}. + * + * @param variables + */ + public void setVariables(Map variables) { + this.variables = variables; + } - /** - * Get the variables. - * - * @return - */ - public Map getVariables() - { - return this.variables; - } + /** + * Get the variables. + * + * @return + */ + public Map getVariables() { + return this.variables; + } } diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java index b902e2825..bc899dc48 100644 --- a/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowContactsAction.java @@ -34,8 +34,7 @@ * @see org.asteriskjava.manager.event.ContactListComplete * @since 0.2 */ -public class PJSipShowContactsAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class PJSipShowContactsAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serial version identifier. */ @@ -44,19 +43,16 @@ public class PJSipShowContactsAction extends AbstractManagerAction implements Ev /** * Creates a new SipPeersAction. */ - public PJSipShowContactsAction() - { + public PJSipShowContactsAction() { } @Override - public String getAction() - { + public String getAction() { return "PJSIPShowContacts"; } - public Class< ? extends ResponseEvent> getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return ContactListComplete.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java index 60b6bedb4..78c643be3 100644 --- a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointAction.java @@ -24,9 +24,9 @@ *

    * For the given endpoint, the call will return several events, including * EndpointDetail, AorDetail, AuthDetail, TransportDetail, ContactStatusDetail,and IdentifyDetail. - * + *

    * Some events may appear multiple times. - * + *

    * When all events have been reported an EndpointDetailComplete is * sent. *

    @@ -42,39 +42,35 @@ * @see org.asteriskjava.manager.event.EndpointDetailComplete * @since 12 */ -public class PJSipShowEndpointAction extends AbstractManagerAction implements EventGeneratingAction -{ - /** +public class PJSipShowEndpointAction extends AbstractManagerAction implements EventGeneratingAction { + /** * Serial version identifier. */ - private static final long serialVersionUID = -5508189961610900058L; - private String endpoint; - + private static final long serialVersionUID = -5508189961610900058L; + private String endpoint; - public String getEndpoint() { - return endpoint; - } - public void setEndpoint(String endpoint) { - this.endpoint = endpoint; - } + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } - /** + /** * Creates a new SipPeersAction. */ - public PJSipShowEndpointAction() - { + public PJSipShowEndpointAction() { } @Override - public String getAction() - { + public String getAction() { return "PJSIPShowEndpoint"; } - public Class< ? extends ResponseEvent> getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return EndpointDetailComplete.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java index d1acaa3f5..71c738724 100644 --- a/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PJSipShowEndpointsAction.java @@ -34,8 +34,7 @@ * @see org.asteriskjava.manager.event.PeerlistCompleteEvent * @since 12 */ -public class PJSipShowEndpointsAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class PJSipShowEndpointsAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serial version identifier. */ @@ -44,19 +43,16 @@ public class PJSipShowEndpointsAction extends AbstractManagerAction implements E /** * Creates a new SipPeersAction. */ - public PJSipShowEndpointsAction() - { + public PJSipShowEndpointsAction() { } @Override - public String getAction() - { + public String getAction() { return "PJSIPShowEndpoints"; } - public Class< ? extends ResponseEvent> getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return EndpointListComplete.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ParkAction.java b/src/main/java/org/asteriskjava/manager/action/ParkAction.java index 7693c097e..ed6d30855 100644 --- a/src/main/java/org/asteriskjava/manager/action/ParkAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ParkAction.java @@ -21,12 +21,11 @@ *

    * Defined in res/res_features.c

    * Available since Asterisk 1.4. - * + * * @author srt * @version $Id$ */ -public class ParkAction extends AbstractManagerAction -{ +public class ParkAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -39,20 +38,18 @@ public class ParkAction extends AbstractManagerAction /** * Creates a new empty ParkAction. */ - public ParkAction() - { + public ParkAction() { super(); } /** * Creates a new ParkAction. - * - * @param channel name of the channel to park. + * + * @param channel name of the channel to park. * @param channel2 name of the channel to announce park info to and return - * to on timeout. + * to on timeout. */ - public ParkAction(String channel, String channel2) - { + public ParkAction(String channel, String channel2) { super(); this.channel = channel; this.channel2 = channel2; @@ -60,14 +57,13 @@ public ParkAction(String channel, String channel2) /** * Creates a new ParkAction with a timeout. - * - * @param channel the name of the channel to park. + * + * @param channel the name of the channel to park. * @param channel2 the name of the channel to announce park info to and - * return to on timeout. - * @param timeout the timeout in seconds before callback. + * return to on timeout. + * @param timeout the timeout in seconds before callback. */ - public ParkAction(String channel, String channel2, Integer timeout) - { + public ParkAction(String channel, String channel2, Integer timeout) { super(); this.channel = channel; this.channel2 = channel2; @@ -78,41 +74,37 @@ public ParkAction(String channel, String channel2, Integer timeout) * Returns the name of this action, i.e. "Park". */ @Override - public String getAction() - { + public String getAction() { return "Park"; } /** * Returns the name of the channel to park. - * + * * @return the name of the channel to park. */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel to park.

    * This property is mandatory. - * + * * @param channel the name of the channel to park. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the name of the channel to announce park info to and return to on * timeout. - * + * * @return the name of the channel to announce park info to and return to on - * timeout. + * timeout. */ - public String getChannel2() - { + public String getChannel2() { return channel2; } @@ -120,32 +112,29 @@ public String getChannel2() * Sets the name of the channel to announce park info to and return to on * timeout.

    * This property is mandatory. - * + * * @param channel2 the name of the channel to announce park info to and - * return to on timeout. + * return to on timeout. */ - public void setChannel2(String channel2) - { + public void setChannel2(String channel2) { this.channel2 = channel2; } /** * Returns the timeout in seconds before callback. - * + * * @return the timeout in seconds before callback. */ - public Integer getTimeout() - { + public Integer getTimeout() { return timeout; } /** * Sets the timeout in seconds before callback. - * + * * @param timeout the timeout in seconds before callback. */ - public void setTimeout(Integer timeout) - { + public void setTimeout(Integer timeout) { this.timeout = timeout; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ParkedCallsAction.java b/src/main/java/org/asteriskjava/manager/action/ParkedCallsAction.java index 2ab3efb3f..0f519e0de 100644 --- a/src/main/java/org/asteriskjava/manager/action/ParkedCallsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ParkedCallsAction.java @@ -23,16 +23,15 @@ * The ParkedCallsAction requests a list of all currently parked calls.

    * For each active channel a ParkedCallEvent is generated. After all parked * calls have been reported a ParkedCallsCompleteEvent is generated. - * - * @see org.asteriskjava.manager.event.ParkedCallEvent - * @see org.asteriskjava.manager.event.ParkedCallsCompleteEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.ParkedCallEvent + * @see org.asteriskjava.manager.event.ParkedCallsCompleteEvent */ public class ParkedCallsAction extends AbstractManagerAction implements - EventGeneratingAction -{ + EventGeneratingAction { /** * Serializable version identifier */ @@ -41,8 +40,7 @@ public class ParkedCallsAction extends AbstractManagerAction /** * Creates a new ParkedCallsAction. */ - public ParkedCallsAction() - { + public ParkedCallsAction() { } @@ -50,13 +48,11 @@ public ParkedCallsAction() * Returns the name of this action, i.e. "ParkedCalls". */ @Override - public String getAction() - { + public String getAction() { return "ParkedCalls"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return ParkedCallsCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/PauseMixMonitorAction.java b/src/main/java/org/asteriskjava/manager/action/PauseMixMonitorAction.java index 501a09e0a..31992b30c 100644 --- a/src/main/java/org/asteriskjava/manager/action/PauseMixMonitorAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PauseMixMonitorAction.java @@ -16,63 +16,64 @@ */ package org.asteriskjava.manager.action; + /** * The PauseMixMonitorAction temporarily stop/start monitoring (recording) a/both channel(s). - * + *

    * Available since Asterisk 1.4. - * Channel - Used to specify the channel to mute. - * Direction - Which part of the recording to mute: read, write or both (from channel, to channel or both channels). - * State - Turn mute on or off : 1 to turn on, 0 to turn off. + * Channel - Used to specify the channel to mute. + * Direction - Which part of the recording to mute: read, write or both (from channel, to channel or both channels). + * State - Turn mute on or off : 1 to turn on, 0 to turn off. * * @author Adrian Videanu - * @since 0.3 * @version $Id$ + * @since 0.3 */ -public class PauseMixMonitorAction extends AbstractManagerAction{ - - private static final long serialVersionUID = -7438670441797420390L; - - private String channel; +public class PauseMixMonitorAction extends AbstractManagerAction { + + private static final long serialVersionUID = -7438670441797420390L; + + private String channel; private Integer state; private String direction; - + public PauseMixMonitorAction() { - super(); - } - - public PauseMixMonitorAction(String ch, Integer st,String dir) { + super(); + } + + public PauseMixMonitorAction(String ch, Integer st, String dir) { this.channel = ch; this.state = st; this.direction = dir; } - - @Override - public String getAction() { - return "MixMonitorMute"; - } - public String getChannel() { - return channel; - } + @Override + public String getAction() { + return "MixMonitorMute"; + } + + public String getChannel() { + return channel; + } - public void setChannel(String channel) { - this.channel = channel; - } + public void setChannel(String channel) { + this.channel = channel; + } - public Integer getState() { - return state; - } + public Integer getState() { + return state; + } - public void setState(Integer state) { - this.state = state; - } + public void setState(Integer state) { + this.state = state; + } - public String getDirection() { - return direction; - } + public String getDirection() { + return direction; + } - public void setDirection(String direction) { - this.direction = direction; - } + public void setDirection(String direction) { + this.direction = direction; + } } diff --git a/src/main/java/org/asteriskjava/manager/action/PauseMonitorAction.java b/src/main/java/org/asteriskjava/manager/action/PauseMonitorAction.java index e69600cc7..041ee56e3 100644 --- a/src/main/java/org/asteriskjava/manager/action/PauseMonitorAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PauseMonitorAction.java @@ -22,14 +22,13 @@ * It is implemented in res/res_monitor.c *

    * Available since Asterisk 1.4. - * - * @see UnpauseMonitorAction + * * @author srt - * @since 0.3 * @version $Id$ + * @see UnpauseMonitorAction + * @since 0.3 */ -public class PauseMonitorAction extends AbstractManagerAction -{ +public class PauseMonitorAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -43,40 +42,36 @@ public class PauseMonitorAction extends AbstractManagerAction /** * Creates a new empty PauseMonitorAction. */ - public PauseMonitorAction() - { + public PauseMonitorAction() { } /** * Creates a new PauseMonitorAction that temporarily stops monitoring the * given channel. - * + * * @param channel the name of the channel to temporarily stop monitoring. */ - public PauseMonitorAction(String channel) - { + public PauseMonitorAction(String channel) { this.channel = channel; } /** * Returns the name of this action, i.e. "PauseMonitor". - * + * * @return the name of this action. */ @Override - public String getAction() - { + public String getAction() { return "PauseMonitor"; } /** * Returns the name of the channel to temporarily stop monitoring. - * + * * @return the name of the channel to temporarily stop monitoring. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -84,11 +79,10 @@ public String getChannel() * Sets the name of the channel to temporarily stop monitoring. *

    * This property is mandatory. - * + * * @param channel the name of the channel to temporarily stop monitoring. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/action/PingAction.java b/src/main/java/org/asteriskjava/manager/action/PingAction.java index 36a907fa3..58be89a06 100644 --- a/src/main/java/org/asteriskjava/manager/action/PingAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PingAction.java @@ -23,13 +23,12 @@ * The PingAction is used to keep the manager connection open and performs no operation.

    * Asterisk versions prior to 1.6 send a "Pong" response, since Asterisk 1.6 a * "Success" response is sent with a "Ping" property set to "Pong". - * + * * @author srt * @version $Id$ */ @ExpectedResponse(PingResponse.class) -public class PingAction extends AbstractManagerAction -{ +public class PingAction extends AbstractManagerAction { /** * Serializable version identifier. */ @@ -38,8 +37,7 @@ public class PingAction extends AbstractManagerAction /** * Creates a new PingAction. */ - public PingAction() - { + public PingAction() { super(); } @@ -47,8 +45,7 @@ public PingAction() * Returns the name of this action, i.e. "Ping". */ @Override - public String getAction() - { + public String getAction() { return "Ping"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java b/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java index db4b9c175..f55efaa9a 100644 --- a/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java @@ -20,13 +20,12 @@ * The PlayDTMFAction plays a DTMF digit on the specified channel.

    * It is definied in apps/app_senddtmf.c.

    * Available since Asterisk 1.2.8 - * - * @since 0.3 + * * @author srt * @version $Id$ + * @since 0.3 */ -public class PlayDtmfAction extends AbstractManagerAction -{ +public class PlayDtmfAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -38,19 +37,17 @@ public class PlayDtmfAction extends AbstractManagerAction /** * Creates a new empty PlayDtmfAction. */ - public PlayDtmfAction() - { + public PlayDtmfAction() { } /** * Creates a new PlayDtmfAction that sends the given DTMF digit to the given channel. - * + * * @param channel the name of the channel to send the digit to. - * @param digit the DTML digit to play. + * @param digit the DTML digit to play. */ - public PlayDtmfAction(String channel, String digit) - { + public PlayDtmfAction(String channel, String digit) { this.channel = channel; this.digit = digit; } @@ -59,48 +56,43 @@ public PlayDtmfAction(String channel, String digit) * Returns the name of this action, i.e. "PlayDTMF". */ @Override - public String getAction() - { + public String getAction() { return "PlayDTMF"; } /** * Returns the name of the channel to send the digit to. - * + * * @return the name of the channel to send the digit to. */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel to send the digit to. - * + * * @param channel the name of the channel to send the digit to. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the DTMF digit to play. - * + * * @return the DTMF digit to play. */ - public String getDigit() - { + public String getDigit() { return digit; } /** * Sets the DTMF digit to play. - * + * * @param digit the DTMF digit to play. */ - public void setDigit(String digit) - { + public void setDigit(String digit) { this.digit = digit; } } diff --git a/src/main/java/org/asteriskjava/manager/action/QueueAddAction.java b/src/main/java/org/asteriskjava/manager/action/QueueAddAction.java index dcb2d84e1..61c394ec9 100644 --- a/src/main/java/org/asteriskjava/manager/action/QueueAddAction.java +++ b/src/main/java/org/asteriskjava/manager/action/QueueAddAction.java @@ -25,8 +25,7 @@ * @author srt * @version $Id$ */ -public class QueueAddAction extends AbstractManagerAction -{ +public class QueueAddAction extends AbstractManagerAction { private static final long serialVersionUID = 2L; private String queue; private String iface; @@ -38,8 +37,7 @@ public class QueueAddAction extends AbstractManagerAction /** * Creates a new empty QueueAddAction. */ - public QueueAddAction() - { + public QueueAddAction() { } @@ -52,8 +50,7 @@ public QueueAddAction() * use the channel name, e.g. "SIP/1234". * @since 0.2 */ - public QueueAddAction(String queue, String iface) - { + public QueueAddAction(String queue, String iface) { this.queue = queue; this.iface = iface; } @@ -70,8 +67,7 @@ public QueueAddAction(String queue, String iface) * distributed members with higher penalties are considered last. * @since 0.2 */ - public QueueAddAction(String queue, String iface, Integer penalty) - { + public QueueAddAction(String queue, String iface, Integer penalty) { this.queue = queue; this.iface = iface; this.penalty = penalty; @@ -81,8 +77,7 @@ public QueueAddAction(String queue, String iface, Integer penalty) * Returns the name of this action, i.e. "QueueAdd". */ @Override - public String getAction() - { + public String getAction() { return "QueueAdd"; } @@ -91,8 +86,7 @@ public String getAction() * * @return the name of the queue the new member will be added to. */ - public String getQueue() - { + public String getQueue() { return queue; } @@ -102,8 +96,7 @@ public String getQueue() * * @param queue the name of the queue the new member will be added to. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } @@ -112,8 +105,7 @@ public void setQueue(String queue) * * @return the name of the channel to dial to reach this member. */ - public String getInterface() - { + public String getInterface() { return iface; } @@ -123,8 +115,7 @@ public String getInterface() * * @param iface the name of the channel to dial to reach this member, e.g. "SIP/1234". */ - public void setInterface(String iface) - { + public void setInterface(String iface) { this.iface = iface; } @@ -133,8 +124,7 @@ public void setInterface(String iface) * * @return the penalty for this member. */ - public Integer getPenalty() - { + public Integer getPenalty() { return penalty; } @@ -147,8 +137,7 @@ public Integer getPenalty() * * @param penalty the penalty for this member. */ - public void setPenalty(Integer penalty) - { + public void setPenalty(Integer penalty) { this.penalty = penalty; } @@ -158,8 +147,7 @@ public void setPenalty(Integer penalty) * @return Boolean.TRUE if the queue member should be paused when added. * @since 0.2 */ - public Boolean getPaused() - { + public Boolean getPaused() { return paused; } @@ -170,8 +158,7 @@ public Boolean getPaused() * added. * @since 0.2 */ - public void setPaused(Boolean paused) - { + public void setPaused(Boolean paused) { this.paused = paused; } @@ -182,8 +169,7 @@ public void setPaused(Boolean paused) * @return the name of the queue memeber (agent name). * @since 1.0.0 */ - public String getMemberName() - { + public String getMemberName() { return memberName; } @@ -194,8 +180,7 @@ public String getMemberName() * @param memberName the name of the queue memeber (agent name). * @since 1.0.0 */ - public void setMemberName(String memberName) - { + public void setMemberName(String memberName) { this.memberName = memberName; } @@ -206,8 +191,7 @@ public void setMemberName(String memberName) * @return the name of the channel from which to read devicestate changes. * @since 1.0.0 */ - public String getStateInterface() - { + public String getStateInterface() { return stateInterface; } @@ -218,8 +202,7 @@ public String getStateInterface() * @param stateInterface the name of the channel from which to read devicestate changes. * @since 1.0.0 */ - public void setStateInterface(String stateInterface) - { + public void setStateInterface(String stateInterface) { this.stateInterface = stateInterface; } } diff --git a/src/main/java/org/asteriskjava/manager/action/QueueChangePriorityCallerAction.java b/src/main/java/org/asteriskjava/manager/action/QueueChangePriorityCallerAction.java index 1f94cbdd2..a0f0ac2e9 100644 --- a/src/main/java/org/asteriskjava/manager/action/QueueChangePriorityCallerAction.java +++ b/src/main/java/org/asteriskjava/manager/action/QueueChangePriorityCallerAction.java @@ -7,98 +7,105 @@ public class QueueChangePriorityCallerAction extends AbstractManagerAction { - /** - * Serializable version identifier - */ - - private final static long serialVersionUID = -1554562185648L; - - private String queue; - private String caller; - private Integer priority; - - /** - * Creates a new empty QueueChangePriorityCallerAction. - */ - - public QueueChangePriorityCallerAction() { - } - - /** - * Creates a new QueueChangePriorityCAllerAction with all required parameters. - * @param queue name of queue. - * @param caller caller channel name. - * @param priority priority value to set. - */ - - public QueueChangePriorityCallerAction(String queue, String caller, Integer priority) { - this.queue = queue; - this.caller = caller; - this.priority = priority; - } - - /** - * Returns the name of this action, i.e. "QueueChangePriorityCaller" - * @return String, name of action - */ - - @Override - public String getAction() { - return "QueueChangePriorityCaller"; - } - - /** - * Returns the queue that caller is inside. - * - * @return queue name - */ - - public String getQueue() { - return queue; - } - - /** - * Sets the queue filter. - * @param queue queue name - */ - - public void setQueue(String queue) { - this.queue = queue; - } - - /** - * Returns the caller to change priority. - * @return String caller name - */ - - public String getCaller() { - return caller; - } - - /** - * Sets the caller to change priority. If not sets then nothing changes. - * @param caller caller name - */ - - public void setCaller(String caller) { - this.caller = caller; - } - - /** - * Returns priority to set to given caller. - * @return integer priority value - */ - - public Integer getPriority() { - return priority; - } - - /** - * Sets priority to given caller. If nothing sets then nothing changes. - * @param priority priority value - */ - - public void setPriority(Integer priority) { - this.priority = priority; - } + /** + * Serializable version identifier + */ + + private final static long serialVersionUID = -1554562185648L; + + private String queue; + private String caller; + private Integer priority; + + /** + * Creates a new empty QueueChangePriorityCallerAction. + */ + + public QueueChangePriorityCallerAction() { + } + + /** + * Creates a new QueueChangePriorityCAllerAction with all required parameters. + * + * @param queue name of queue. + * @param caller caller channel name. + * @param priority priority value to set. + */ + + public QueueChangePriorityCallerAction(String queue, String caller, Integer priority) { + this.queue = queue; + this.caller = caller; + this.priority = priority; + } + + /** + * Returns the name of this action, i.e. "QueueChangePriorityCaller" + * + * @return String, name of action + */ + + @Override + public String getAction() { + return "QueueChangePriorityCaller"; + } + + /** + * Returns the queue that caller is inside. + * + * @return queue name + */ + + public String getQueue() { + return queue; + } + + /** + * Sets the queue filter. + * + * @param queue queue name + */ + + public void setQueue(String queue) { + this.queue = queue; + } + + /** + * Returns the caller to change priority. + * + * @return String caller name + */ + + public String getCaller() { + return caller; + } + + /** + * Sets the caller to change priority. If not sets then nothing changes. + * + * @param caller caller name + */ + + public void setCaller(String caller) { + this.caller = caller; + } + + /** + * Returns priority to set to given caller. + * + * @return integer priority value + */ + + public Integer getPriority() { + return priority; + } + + /** + * Sets priority to given caller. If nothing sets then nothing changes. + * + * @param priority priority value + */ + + public void setPriority(Integer priority) { + this.priority = priority; + } } diff --git a/src/main/java/org/asteriskjava/manager/action/QueueLogAction.java b/src/main/java/org/asteriskjava/manager/action/QueueLogAction.java index fa69f942b..ce72f7a4f 100644 --- a/src/main/java/org/asteriskjava/manager/action/QueueLogAction.java +++ b/src/main/java/org/asteriskjava/manager/action/QueueLogAction.java @@ -25,8 +25,7 @@ * @version $Id$ * @since 1.0.0 */ -public class QueueLogAction extends AbstractManagerAction -{ +public class QueueLogAction extends AbstractManagerAction { private static final long serialVersionUID = 1L; private String iface; @@ -38,8 +37,7 @@ public class QueueLogAction extends AbstractManagerAction /** * Creates a new empty QueueLogAction. */ - public QueueLogAction() - { + public QueueLogAction() { } @@ -49,8 +47,7 @@ public QueueLogAction() * @param queue the name of the queue to log the event for. * @param event the event to log. */ - public QueueLogAction(String queue, String event) - { + public QueueLogAction(String queue, String event) { this.queue = queue; this.event = event; } @@ -64,8 +61,7 @@ public QueueLogAction(String queue, String event) * @param iface the interface of the member to log the event for, may be null. * @param uniqueId the unique id of the channel to log the event for, may be null. */ - public QueueLogAction(String queue, String event, String message, String iface, String uniqueId) - { + public QueueLogAction(String queue, String event, String message, String iface, String uniqueId) { this.queue = queue; this.event = event; this.message = message; @@ -79,8 +75,7 @@ public QueueLogAction(String queue, String event, String message, String iface, * @return the name of this action. */ @Override - public String getAction() - { + public String getAction() { return "QueueLog"; } @@ -89,8 +84,7 @@ public String getAction() * * @return the interface of the member to log the event for. */ - public String getInterface() - { + public String getInterface() { return iface; } @@ -99,8 +93,7 @@ public String getInterface() * * @param iface the interface of the member to log the event for. */ - public void setInterface(String iface) - { + public void setInterface(String iface) { this.iface = iface; } @@ -109,8 +102,7 @@ public void setInterface(String iface) * * @return the name of the queue to log the event for. */ - public String getQueue() - { + public String getQueue() { return queue; } @@ -120,8 +112,7 @@ public String getQueue() * * @param queue the name of the queue to log the event for. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } @@ -130,8 +121,7 @@ public void setQueue(String queue) * * @return the unique id of the channel to log the event for. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } @@ -140,8 +130,7 @@ public String getUniqueId() * * @param uniqueId the unique id of the channel to log the event for. */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -150,8 +139,7 @@ public void setUniqueId(String uniqueId) * * @return the event to log. */ - public String getEvent() - { + public String getEvent() { return event; } @@ -161,8 +149,7 @@ public String getEvent() * * @param event the event to log. */ - public void setEvent(String event) - { + public void setEvent(String event) { this.event = event; } @@ -171,8 +158,7 @@ public void setEvent(String event) * * @return the message to log. */ - public String getMessage() - { + public String getMessage() { return message; } @@ -181,8 +167,7 @@ public String getMessage() * * @param message the message to log. */ - public void setMessage(String message) - { + public void setMessage(String message) { this.message = message; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/QueueMemberRingInUseAction.java b/src/main/java/org/asteriskjava/manager/action/QueueMemberRingInUseAction.java index 26278dc17..347ffbb74 100644 --- a/src/main/java/org/asteriskjava/manager/action/QueueMemberRingInUseAction.java +++ b/src/main/java/org/asteriskjava/manager/action/QueueMemberRingInUseAction.java @@ -6,113 +6,113 @@ public class QueueMemberRingInUseAction extends AbstractManagerAction { - /** - * Serializable version identifier - */ - - private final static long serialVersionUID = -1554562185640L; - - /** - * Queue name where member is located; - */ - - private String queue; - - /** - * RingInUse value. - */ - - private Boolean ringInUse; - - /** - * Interface where need to change RingInUse value; - */ - - private String iface; - - /** - * Creates a new empty QueueMemberRingInUseAction. - */ - - public QueueMemberRingInUseAction() { - } - - /** - * Creates a new QueueMemberRingInUseAction with mandatory properties queue, ringInUse and iface. - * - * @param queue queueName. - * @param ringInUse value to set. - * @param iface interface where to set ringInUse. - */ - - public QueueMemberRingInUseAction(String queue, Boolean ringInUse, String iface) { - this.queue = queue; - this.ringInUse = ringInUse; - this.iface = iface; - } - - @Override - public String getAction() { - return "QueueMemberRingInUse"; - } - - /** - * Returns queue name where interface is located. - * - * @return queue name; - */ - - public String getQueue() { - return queue; - } - - /** - * Sets queue name where interface is located. - * - * @param queue queue name; - */ - - public void setQueue(String queue) { - this.queue = queue; - } - - /** - * Returns RingInUse value of selected interface. - * - * @return ringInUse value; - */ - - public Boolean getRingInUse() { - return ringInUse; - } - - /** - * Sets RingInUse to selected interface. - * - * @param ringInUse value. - */ - - public void setRingInUse(Boolean ringInUse) { - this.ringInUse = ringInUse; - } - - /** - * Returns interface value eg. SIP/203. - * - * @return interface value. - */ - - public String getInterface() { - return iface; - } - - /** - * Sets interface value where RingInUse changes. - * - * @param iface name - */ - - public void setInterface(String iface) { - this.iface = iface; - } + /** + * Serializable version identifier + */ + + private final static long serialVersionUID = -1554562185640L; + + /** + * Queue name where member is located; + */ + + private String queue; + + /** + * RingInUse value. + */ + + private Boolean ringInUse; + + /** + * Interface where need to change RingInUse value; + */ + + private String iface; + + /** + * Creates a new empty QueueMemberRingInUseAction. + */ + + public QueueMemberRingInUseAction() { + } + + /** + * Creates a new QueueMemberRingInUseAction with mandatory properties queue, ringInUse and iface. + * + * @param queue queueName. + * @param ringInUse value to set. + * @param iface interface where to set ringInUse. + */ + + public QueueMemberRingInUseAction(String queue, Boolean ringInUse, String iface) { + this.queue = queue; + this.ringInUse = ringInUse; + this.iface = iface; + } + + @Override + public String getAction() { + return "QueueMemberRingInUse"; + } + + /** + * Returns queue name where interface is located. + * + * @return queue name; + */ + + public String getQueue() { + return queue; + } + + /** + * Sets queue name where interface is located. + * + * @param queue queue name; + */ + + public void setQueue(String queue) { + this.queue = queue; + } + + /** + * Returns RingInUse value of selected interface. + * + * @return ringInUse value; + */ + + public Boolean getRingInUse() { + return ringInUse; + } + + /** + * Sets RingInUse to selected interface. + * + * @param ringInUse value. + */ + + public void setRingInUse(Boolean ringInUse) { + this.ringInUse = ringInUse; + } + + /** + * Returns interface value eg. SIP/203. + * + * @return interface value. + */ + + public String getInterface() { + return iface; + } + + /** + * Sets interface value where RingInUse changes. + * + * @param iface name + */ + + public void setInterface(String iface) { + this.iface = iface; + } } diff --git a/src/main/java/org/asteriskjava/manager/action/QueuePauseAction.java b/src/main/java/org/asteriskjava/manager/action/QueuePauseAction.java index cda358b14..654d5520c 100644 --- a/src/main/java/org/asteriskjava/manager/action/QueuePauseAction.java +++ b/src/main/java/org/asteriskjava/manager/action/QueuePauseAction.java @@ -21,13 +21,12 @@ * available again).

    * It is implemented in apps/app_queue.c

    * Available since Asterisk 1.2. - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class QueuePauseAction extends AbstractManagerAction -{ +public class QueuePauseAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -41,19 +40,17 @@ public class QueuePauseAction extends AbstractManagerAction /** * Creates a new empty QueuePauseAction. */ - public QueuePauseAction() - { + public QueuePauseAction() { } /** * Creates a new QueuePauseAction that makes the member on the given * interface unavailable on all queues. - * + * * @param iface the interface of the member to make unavailable */ - public QueuePauseAction(String iface) - { + public QueuePauseAction(String iface) { this.iface = iface; this.paused = Boolean.TRUE; } @@ -61,12 +58,11 @@ public QueuePauseAction(String iface) /** * Creates a new QueuePauseAction that makes the member on the given * interface unavailable on the given queue. - * + * * @param iface the interface of the member to make unavailable * @param queue the queue the member is made unvailable on */ - public QueuePauseAction(String iface, String queue) - { + public QueuePauseAction(String iface, String queue) { this.iface = iface; this.queue = queue; this.paused = Boolean.TRUE; @@ -75,13 +71,12 @@ public QueuePauseAction(String iface, String queue) /** * Creates a new QueuePauseAction that makes the member on the given * interface available or unavailable on all queues. - * - * @param iface the interface of the member to make unavailable + * + * @param iface the interface of the member to make unavailable * @param paused Boolean.TRUE to make the member unavailbale, Boolean.FALSE - * to make the member available + * to make the member available */ - public QueuePauseAction(String iface, Boolean paused) - { + public QueuePauseAction(String iface, Boolean paused) { this.iface = iface; this.paused = paused; } @@ -89,14 +84,13 @@ public QueuePauseAction(String iface, Boolean paused) /** * Creates a new QueuePauseAction that makes the member on the given * interface unavailable on the given queue. - * - * @param iface the interface of the member to make unavailable - * @param queue the queue the member is made unvailable on + * + * @param iface the interface of the member to make unavailable + * @param queue the queue the member is made unvailable on * @param paused Boolean.TRUE to make the member unavailbale, Boolean.FALSE - * to make the member available + * to make the member available */ - public QueuePauseAction(String iface, String queue, Boolean paused) - { + public QueuePauseAction(String iface, String queue, Boolean paused) { this.iface = iface; this.queue = queue; this.paused = paused; @@ -104,81 +98,74 @@ public QueuePauseAction(String iface, String queue, Boolean paused) /** * Returns the name of this action, i.e. "QueuePause". - * + * * @return the name of this action. */ @Override - public String getAction() - { + public String getAction() { return "QueuePause"; } /** * Returns the interface of the member to make available or unavailable. - * + * * @return the interface of the member to make available or unavailable. */ - public String getInterface() - { + public String getInterface() { return iface; } /** * Sets the interface of the member to make available or unavailable.

    * This property is mandatory. - * + * * @param iface the interface of the member to make available or - * unavailable. + * unavailable. */ - public void setInterface(String iface) - { + public void setInterface(String iface) { this.iface = iface; } /** * Returns the name of the queue the member is made available or unavailable * on. - * + * * @return the name of the queue the member is made available or unavailable - * on or null for all queues. + * on or null for all queues. */ - public String getQueue() - { + public String getQueue() { return queue; } /** * Sets the name of the queue the member is made available or unavailable * on. - * + * * @param queue the name of the queue the member is made available or - * unavailable on or null for all queues. + * unavailable on or null for all queues. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } /** * Returns if the member is made available or unavailable. - * + * * @return Boolean.TRUE to make the member unavailbale, Boolean.FALSE to - * make the member available + * make the member available */ - public Boolean getPaused() - { + public Boolean getPaused() { return paused; } /** * Sets if the member is made available or unavailable.

    * This property is mandatory. - * + * * @param paused Boolean.TRUE to make the member unavailbale, Boolean.FALSE - * to make the member available + * to make the member available */ - public void setPaused(Boolean paused) - { + public void setPaused(Boolean paused) { this.paused = paused; } @@ -188,9 +175,8 @@ public void setPaused(Boolean paused) * * @return Name of the local reason for clears the flag. */ - public String getReason() - { - return reason; + public String getReason() { + return reason; } /** @@ -199,8 +185,7 @@ public String getReason() * * @param reason Name of the local reason for clears the flag. */ - public void setReason(String reason) - { - this.reason = reason; + public void setReason(String reason) { + this.reason = reason; } } diff --git a/src/main/java/org/asteriskjava/manager/action/QueuePenaltyAction.java b/src/main/java/org/asteriskjava/manager/action/QueuePenaltyAction.java index 8f6d91410..4d3405f16 100644 --- a/src/main/java/org/asteriskjava/manager/action/QueuePenaltyAction.java +++ b/src/main/java/org/asteriskjava/manager/action/QueuePenaltyAction.java @@ -25,8 +25,7 @@ * @version $Id$ * @since 1.0.0 */ -public class QueuePenaltyAction extends AbstractManagerAction -{ +public class QueuePenaltyAction extends AbstractManagerAction { /** * Serializable version identifier. */ @@ -39,8 +38,7 @@ public class QueuePenaltyAction extends AbstractManagerAction /** * Creates a new empty QueuePenaltyAction. */ - public QueuePenaltyAction() - { + public QueuePenaltyAction() { } @@ -51,8 +49,7 @@ public QueuePenaltyAction() * @param iface the interface of the member to set the penalty for * @param penalty new penalty value. */ - public QueuePenaltyAction(String iface, int penalty) - { + public QueuePenaltyAction(String iface, int penalty) { this.iface = iface; this.penalty = penalty; } @@ -65,8 +62,7 @@ public QueuePenaltyAction(String iface, int penalty) * @param penalty new penalty value. * @param queue the queue the member is assigned the penalty for */ - public QueuePenaltyAction(String iface, int penalty, String queue) - { + public QueuePenaltyAction(String iface, int penalty, String queue) { this.iface = iface; this.penalty = penalty; this.queue = queue; @@ -78,8 +74,7 @@ public QueuePenaltyAction(String iface, int penalty, String queue) * @return the name of this action. */ @Override - public String getAction() - { + public String getAction() { return "QueuePenalty"; } @@ -88,8 +83,7 @@ public String getAction() * * @return the interface of the member to to set the penalty for. */ - public String getInterface() - { + public String getInterface() { return iface; } @@ -99,8 +93,7 @@ public String getInterface() * * @param iface the interface of the member to to set the penalty for. */ - public void setInterface(String iface) - { + public void setInterface(String iface) { this.iface = iface; } @@ -109,8 +102,7 @@ public void setInterface(String iface) * * @return the new penalty. */ - public Integer getPenalty() - { + public Integer getPenalty() { return penalty; } @@ -120,8 +112,7 @@ public Integer getPenalty() * * @param penalty the new penalty. */ - public void setPenalty(Integer penalty) - { + public void setPenalty(Integer penalty) { this.penalty = penalty; } @@ -130,8 +121,7 @@ public void setPenalty(Integer penalty) * * @return the name of the queue. */ - public String getQueue() - { + public String getQueue() { return queue; } @@ -140,8 +130,7 @@ public String getQueue() * * @param queue the name of the queue or null for all queues. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/QueueRemoveAction.java b/src/main/java/org/asteriskjava/manager/action/QueueRemoveAction.java index 4f1ff5d60..b474715f2 100644 --- a/src/main/java/org/asteriskjava/manager/action/QueueRemoveAction.java +++ b/src/main/java/org/asteriskjava/manager/action/QueueRemoveAction.java @@ -19,12 +19,11 @@ /** * The QueueRemoveAction removes a member from a queue.

    * It is implemented in apps/app_queue.c - * + * * @author srt * @version $Id$ */ -public class QueueRemoveAction extends AbstractManagerAction -{ +public class QueueRemoveAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -39,62 +38,56 @@ public class QueueRemoveAction extends AbstractManagerAction /** * Creates a new empty QueueRemoveAction. */ - public QueueRemoveAction() - { + public QueueRemoveAction() { } /** * Creates a new QueueRemoveAction that removes the member on the given * interface from the given queue. - * + * * @param queue the name of the queue the member will be removed from * @param iface the interface of the member to remove * @since 0.2 */ - public QueueRemoveAction(String queue, String iface) - { + public QueueRemoveAction(String queue, String iface) { this.queue = queue; this.iface = iface; } /** * Returns the name of this action, i.e. "QueueRemove". - * + * * @return the name of this action. */ @Override - public String getAction() - { + public String getAction() { return "QueueRemove"; } /** * Returns the name of the queue the member will be removed from. - * + * * @return the name of the queue the member will be removed from. */ - public String getQueue() - { + public String getQueue() { return queue; } /** * Sets the name of the queue the member will be removed from.

    * This property is mandatory. - * + * * @param queue the name of the queue the member will be removed from. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } /** * Returns the interface to remove. */ - public String getInterface() - { + public String getInterface() { return iface; } @@ -102,8 +95,7 @@ public String getInterface() * Sets the interface to remove.

    * This property is mandatory. */ - public void setInterface(String iface) - { + public void setInterface(String iface) { this.iface = iface; } } diff --git a/src/main/java/org/asteriskjava/manager/action/QueueResetAction.java b/src/main/java/org/asteriskjava/manager/action/QueueResetAction.java index e602aadf3..c9158d1e3 100644 --- a/src/main/java/org/asteriskjava/manager/action/QueueResetAction.java +++ b/src/main/java/org/asteriskjava/manager/action/QueueResetAction.java @@ -24,8 +24,7 @@ * @author Sebastian * @since 1.0.0 */ -public class QueueResetAction extends AbstractManagerAction -{ +public class QueueResetAction extends AbstractManagerAction { private static final long serialVersionUID = 1L; private String queue; @@ -33,8 +32,7 @@ public class QueueResetAction extends AbstractManagerAction /** * Creates a new QueueResetAction that resets statistical data of all queues. */ - public QueueResetAction() - { + public QueueResetAction() { } /** @@ -42,14 +40,12 @@ public QueueResetAction() * * @param queue the name of the queue to reset. */ - public QueueResetAction(String queue) - { + public QueueResetAction(String queue) { this.queue = queue; } @Override - public String getAction() - { + public String getAction() { return "QueueReset"; } @@ -58,8 +54,7 @@ public String getAction() * * @return the name of the queue to reset or null for all queues. */ - public String getQueue() - { + public String getQueue() { return queue; } @@ -68,8 +63,7 @@ public String getQueue() * * @param queue the name of the queue to reset or null for all queues. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } } diff --git a/src/main/java/org/asteriskjava/manager/action/QueueStatusAction.java b/src/main/java/org/asteriskjava/manager/action/QueueStatusAction.java index 1d24cc397..d92958778 100644 --- a/src/main/java/org/asteriskjava/manager/action/QueueStatusAction.java +++ b/src/main/java/org/asteriskjava/manager/action/QueueStatusAction.java @@ -28,18 +28,17 @@ * Since Asterisk 1.2 a QueueStatusCompleteEvent is sent to denote the end of * the generated dump.

    * This action is implemented in apps/app_queue.c - * + * + * @author srt + * @version $Id$ * @see org.asteriskjava.manager.event.QueueParamsEvent * @see org.asteriskjava.manager.event.QueueMemberEvent * @see org.asteriskjava.manager.event.QueueEntryEvent * @see org.asteriskjava.manager.event.QueueStatusCompleteEvent - * @author srt - * @version $Id$ */ public class QueueStatusAction extends AbstractManagerAction implements - EventGeneratingAction -{ + EventGeneratingAction { /** * Serializable version identifier */ @@ -51,8 +50,7 @@ public class QueueStatusAction extends AbstractManagerAction /** * Creates a new QueueStatusAction. */ - public QueueStatusAction() - { + public QueueStatusAction() { } @@ -60,59 +58,53 @@ public QueueStatusAction() * Returns the name of this action, i.e. "QueueStatus". */ @Override - public String getAction() - { + public String getAction() { return "QueueStatus"; } /** * Returns the queue filter. - * + * * @return the queue filter. * @since 0.2 */ - public String getQueue() - { + public String getQueue() { return queue; } /** * Sets the queue filter. If set QueueParamEvents are only generated for the * given queue name. - * + * * @param queue the queue filter. * @since 0.2 */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } /** * Returns the member filter. - * + * * @return the member filter. * @since 0.2 */ - public String getMember() - { + public String getMember() { return member; } /** * Sets the member filter. If set QueueMemberEvents are only generated for the * given member name. - * + * * @param member the member filter. * @since 0.2 */ - public void setMember(String member) - { + public void setMember(String member) { this.member = member; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return QueueStatusCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/QueueSummaryAction.java b/src/main/java/org/asteriskjava/manager/action/QueueSummaryAction.java index 40dfff5d6..c1a5520ec 100644 --- a/src/main/java/org/asteriskjava/manager/action/QueueSummaryAction.java +++ b/src/main/java/org/asteriskjava/manager/action/QueueSummaryAction.java @@ -11,15 +11,14 @@ *

    * This action has been added by * http://bugs.digium.com/view.php?id=8035. - * - * @see QueueSummaryEvent - * @see QueueSummaryCompleteEvent + * * @author srt * @version $Id$ + * @see QueueSummaryEvent + * @see QueueSummaryCompleteEvent * @since 0.3 */ -public class QueueSummaryAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class QueueSummaryAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serial version identifier. */ @@ -30,52 +29,46 @@ public class QueueSummaryAction extends AbstractManagerAction implements EventGe * Creates a new QueueSummaryAction that retrieves the summary for all * queues. */ - public QueueSummaryAction() - { + public QueueSummaryAction() { } /** * Creates a new QueueSummaryAction that retrieves the summary for the given * queue. - * + * * @param queue name of the queue to retrieve the summary for. */ - public QueueSummaryAction(String queue) - { + public QueueSummaryAction(String queue) { this.queue = queue; } @Override - public String getAction() - { + public String getAction() { return "QueueSummary"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return QueueSummaryCompleteEvent.class; } /** * Returns the name of the queue to retrieve the summary for. - * + * * @return the name of the queue to retrieve the summary for or - * null to retrieve the summary for all queues. + * null to retrieve the summary for all queues. */ - public String getQueue() - { + public String getQueue() { return queue; } /** * Sets the name of the queue to retrieve the summary for. - * + * * @param queue the name of the queue to retrieve the summary for or - * null to retrieve the summary for all queues. + * null to retrieve the summary for all queues. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } } diff --git a/src/main/java/org/asteriskjava/manager/action/RedirectAction.java b/src/main/java/org/asteriskjava/manager/action/RedirectAction.java index c67d86c0d..0632ed4ec 100644 --- a/src/main/java/org/asteriskjava/manager/action/RedirectAction.java +++ b/src/main/java/org/asteriskjava/manager/action/RedirectAction.java @@ -29,12 +29,11 @@ * priority only for the first channel and extraContext, extraExtension, * extraPriority for the second channel. The standard version ignores the * extraContext, extraExtension, extraPriority properties. - * + * * @author srt * @version $Id$ */ -public class RedirectAction extends AbstractManagerAction -{ +public class RedirectAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -52,23 +51,21 @@ public class RedirectAction extends AbstractManagerAction /** * Creates a new empty RedirectAction. */ - public RedirectAction() - { + public RedirectAction() { } /** * Creates a new RedirectAction that redirects the given channel to the * given context, extension, priority triple. - * - * @param channel the name of the channel to redirect - * @param context the destination context - * @param exten the destination extension + * + * @param channel the name of the channel to redirect + * @param context the destination context + * @param exten the destination extension * @param priority the destination priority * @since 0.2 */ - public RedirectAction(String channel, String context, String exten, Integer priority) - { + public RedirectAction(String channel, String context, String exten, Integer priority) { this.channel = channel; this.context = context; this.exten = exten; @@ -83,16 +80,15 @@ public RedirectAction(String channel, String context, String exten, Integer prio * non-BRIstuffed versions. When used with a BRIstuffed version (and not * setting extraContext, extraExten and extraPriority) the second channel is * just hung up. - * - * @param channel the name of the first channel to redirect + * + * @param channel the name of the first channel to redirect * @param extraChannel the name of the second channel to redirect - * @param context the destination context - * @param exten the destination extension - * @param priority the destination priority + * @param context the destination context + * @param exten the destination extension + * @param priority the destination priority * @since 0.2 */ - public RedirectAction(String channel, String extraChannel, String context, String exten, Integer priority) - { + public RedirectAction(String channel, String extraChannel, String context, String exten, Integer priority) { this.channel = channel; this.extraChannel = extraChannel; this.context = context; @@ -107,20 +103,19 @@ public RedirectAction(String channel, String extraChannel, String context, Strin * This constructor works for BRIstuffed versions of Asterisk, if used with * a standard version the extraContext, extraExten and extraPriroity * attributes are ignored. - * - * @param channel the name of the first channel to redirect - * @param extraChannel the name of the second channel to redirect - * @param context the destination context for the first channel - * @param exten the destination extension for the first channel - * @param priority the destination priority for the first channel - * @param extraContext the destination context for the second channel - * @param extraExten the destination extension for the second channel + * + * @param channel the name of the first channel to redirect + * @param extraChannel the name of the second channel to redirect + * @param context the destination context for the first channel + * @param exten the destination extension for the first channel + * @param priority the destination priority for the first channel + * @param extraContext the destination context for the second channel + * @param extraExten the destination extension for the second channel * @param extraPriority the destination priority for the second channel * @since 0.3 */ public RedirectAction(String channel, String extraChannel, String context, String exten, Integer priority, - String extraContext, String extraExten, Integer extraPriority) - { + String extraContext, String extraExten, Integer extraPriority) { this.channel = channel; this.extraChannel = extraChannel; this.context = context; @@ -129,8 +124,7 @@ public RedirectAction(String channel, String extraChannel, String context, Strin this.extraContext = extraContext; this.extraExten = extraExten; this.extraPriority = extraPriority; - if (channel.equalsIgnoreCase(extraChannel)) - { + if (channel.equalsIgnoreCase(extraChannel)) { throw new RuntimeException("ExtraChannel = channel ... bad things will happen to asterisk"); } } @@ -139,112 +133,100 @@ public RedirectAction(String channel, String extraChannel, String context, Strin * Returns the name of this action, i.e. "Redirect". */ @Override - public String getAction() - { + public String getAction() { return "Redirect"; } /** * Returns name of the channel to redirect. - * + * * @return the name of the channel to redirect */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel to redirect. - * + * * @param channel the name of the channel to redirect */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the name of the additional channel to redirect. - * + * * @return the name of the additional channel to redirect */ - public String getExtraChannel() - { + public String getExtraChannel() { return extraChannel; } /** * Sets the name of the additional channel to redirect. - * + * * @param extraChannel the name of the additional channel to redirect */ - public void setExtraChannel(String extraChannel) - { + public void setExtraChannel(String extraChannel) { this.extraChannel = extraChannel; - if (channel.equalsIgnoreCase(extraChannel)) - { + if (channel.equalsIgnoreCase(extraChannel)) { throw new RuntimeException("ExtraChannel = channel ... bad things will happen to asterisk"); } } /** * Returns the destination context. - * + * * @return the destination context */ - public String getContext() - { + public String getContext() { return context; } /** * Sets the destination context. - * + * * @param context the destination context */ - public void setContext(String context) - { + public void setContext(String context) { this.context = context; } /** * Returns the destination extension. - * + * * @return the destination extension */ - public String getExten() - { + public String getExten() { return exten; } /** * Sets the destination extension. - * + * * @param exten the destination extension */ - public void setExten(String exten) - { + public void setExten(String exten) { this.exten = exten; } /** * Returns the destination priority. - * + * * @return the destination priority */ - public Integer getPriority() - { + public Integer getPriority() { return priority; } /** * Sets the destination priority. - * + * * @param priority the destination priority */ - public void setPriority(Integer priority) - { + public void setPriority(Integer priority) { this.priority = priority; } @@ -252,11 +234,10 @@ public void setPriority(Integer priority) * Returns the destination context for the additional channel. *

    * This property is only used by BRIstuffed Asterisk servers. - * + * * @return the destination context for the additional channel. */ - public String getExtraContext() - { + public String getExtraContext() { return extraContext; } @@ -264,11 +245,10 @@ public String getExtraContext() * Sets the destination context for the additional channel. *

    * This property is only used by BRIstuffed Asterisk servers. - * + * * @param extraContext the destination context for the additional channel. */ - public void setExtraContext(String extraContext) - { + public void setExtraContext(String extraContext) { this.extraContext = extraContext; } @@ -276,11 +256,10 @@ public void setExtraContext(String extraContext) * Sets the destination extension for the additional channel. *

    * This property is only used by BRIstuffed Asterisk servers. - * + * * @return the destination extension for the additional channel. */ - public String getExtraExten() - { + public String getExtraExten() { return extraExten; } @@ -288,11 +267,10 @@ public String getExtraExten() * Sets the destination extension for the additional channel. *

    * This property is only used by BRIstuffed Asterisk servers. - * + * * @param extraExten the destination extension for the additional channel. */ - public void setExtraExten(String extraExten) - { + public void setExtraExten(String extraExten) { this.extraExten = extraExten; } @@ -300,11 +278,10 @@ public void setExtraExten(String extraExten) * Returns the destination priority for the additional channel. *

    * This property is only used by BRIstuffed Asterisk servers. - * + * * @return the destination priority for the additional channel. */ - public Integer getExtraPriority() - { + public Integer getExtraPriority() { return extraPriority; } @@ -312,11 +289,10 @@ public Integer getExtraPriority() * Sets the destination priority for the additional channel. *

    * This property is only used by BRIstuffed Asterisk servers. - * + * * @param extraPriority the destination priority for the additional channel. */ - public void setExtraPriority(Integer extraPriority) - { + public void setExtraPriority(Integer extraPriority) { this.extraPriority = extraPriority; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SendTextAction.java b/src/main/java/org/asteriskjava/manager/action/SendTextAction.java index c2545e71b..8d9ea69d4 100644 --- a/src/main/java/org/asteriskjava/manager/action/SendTextAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SendTextAction.java @@ -26,8 +26,7 @@ * @version $Id$ * @since 1.0.0 */ -public class SendTextAction extends AbstractManagerAction -{ +public class SendTextAction extends AbstractManagerAction { private static final long serialVersionUID = 1L; private String channel; @@ -36,8 +35,7 @@ public class SendTextAction extends AbstractManagerAction /** * Creates a new empty SendTextAction. */ - public SendTextAction() - { + public SendTextAction() { super(); } @@ -47,8 +45,7 @@ public SendTextAction() * @param channel the name of the channel to send the message to. * @param message the message to send. */ - public SendTextAction(String channel, String message) - { + public SendTextAction(String channel, String message) { super(); this.channel = channel; this.message = message; @@ -58,8 +55,7 @@ public SendTextAction(String channel, String message) * Returns the name of this action, i.e. "SendText". */ @Override - public String getAction() - { + public String getAction() { return "SendText"; } @@ -68,8 +64,7 @@ public String getAction() * * @return the name of the channel to send the message to. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -78,8 +73,7 @@ public String getChannel() * * @param channel the name of the channel to send the message to. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -88,8 +82,7 @@ public void setChannel(String channel) * * @return the message to send. */ - public String getMessage() - { + public String getMessage() { return message; } @@ -98,8 +91,7 @@ public String getMessage() * * @param message the message to send. */ - public void setMessage(String message) - { + public void setMessage(String message) { this.message = message; - } + } } diff --git a/src/main/java/org/asteriskjava/manager/action/SetCdrUserFieldAction.java b/src/main/java/org/asteriskjava/manager/action/SetCdrUserFieldAction.java index 503393557..d9ffcb5e3 100644 --- a/src/main/java/org/asteriskjava/manager/action/SetCdrUserFieldAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SetCdrUserFieldAction.java @@ -23,12 +23,11 @@ * overwritten.

    * The SetCDRUserFieldAction is implemented in * apps/app_setcdruserfield.c - * + * * @author srt * @version $Id$ */ -public class SetCdrUserFieldAction extends AbstractManagerAction -{ +public class SetCdrUserFieldAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -40,21 +39,19 @@ public class SetCdrUserFieldAction extends AbstractManagerAction /** * Creates a new empty SetCdrUserFieldAction. */ - public SetCdrUserFieldAction() - { + public SetCdrUserFieldAction() { } /** * Creates a new SetCdrUserFieldAction that sets the user field of the call * detail record for the given channel to the given value. - * - * @param channel the name of the channel + * + * @param channel the name of the channel * @param userField the new value of the userfield * @since 0.2 */ - public SetCdrUserFieldAction(String channel, String userField) - { + public SetCdrUserFieldAction(String channel, String userField) { this.channel = channel; this.userField = userField; } @@ -62,16 +59,15 @@ public SetCdrUserFieldAction(String channel, String userField) /** * Creates a new SetCDRUserFieldAction that sets the user field of the call * detail record for the given channel to the given value. - * - * @param channel the name of the channel + * + * @param channel the name of the channel * @param userField the new value of the userfield - * @param append true to append the value to the cdr user field or false to - * overwrite + * @param append true to append the value to the cdr user field or false to + * overwrite * @since 0.2 */ public SetCdrUserFieldAction(String channel, String userField, - Boolean append) - { + Boolean append) { this.channel = channel; this.userField = userField; this.append = append; @@ -81,16 +77,14 @@ public SetCdrUserFieldAction(String channel, String userField, * Returns the name of the action, i.e. "SetCDRUserField". */ @Override - public String getAction() - { + public String getAction() { return "SetCDRUserField"; } /** * Returns the name of the channel to set the cdr user field on. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -98,16 +92,14 @@ public String getChannel() * Sets the name of the channel to set the cdr user field on.

    * This property is mandatory. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the value of the cdr user field to set or append. */ - public String getUserField() - { + public String getUserField() { return userField; } @@ -115,16 +107,14 @@ public String getUserField() * Sets the value of the cdr user field to set or append.

    * This property is mandatory. */ - public void setUserField(String userField) - { + public void setUserField(String userField) { this.userField = userField; } /** * Returns if the value of the cdr user field is appended or overwritten. */ - public Boolean getAppend() - { + public Boolean getAppend() { return append; } @@ -132,8 +122,7 @@ public Boolean getAppend() * Set to true to append the value to the cdr user field or false to * overwrite. */ - public void setAppend(Boolean append) - { + public void setAppend(Boolean append) { this.append = append; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SetVarAction.java b/src/main/java/org/asteriskjava/manager/action/SetVarAction.java index 0d222f447..120e996ac 100644 --- a/src/main/java/org/asteriskjava/manager/action/SetVarAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SetVarAction.java @@ -19,13 +19,12 @@ /** * The SetVarAction sets the value of a global or local channel variable.

    * Setting global variables is supported since Asterisk 1.2. - * + * * @author Asteria Solutions Group, Inc. http://www.asteriasgi.com * @author srt * @version $Id$ */ -public class SetVarAction extends AbstractManagerAction -{ +public class SetVarAction extends AbstractManagerAction { /** * Serial version identifier */ @@ -49,35 +48,32 @@ public class SetVarAction extends AbstractManagerAction /** * Creates a new empty SetVarAction. */ - public SetVarAction() - { + public SetVarAction() { } /** * Creates a new SetVarAction that sets the given global variable to a new value. - * + * * @param variable the name of the global variable to set - * @param value the new value + * @param value the new value * @since 0.2 */ - public SetVarAction(String variable, String value) - { + public SetVarAction(String variable, String value) { this.variable = variable; this.value = value; } - + /** * Creates a new SetVarAction that sets the given channel variable of the * given channel to a new value. - * - * @param channel the name of the channel to set the variable on + * + * @param channel the name of the channel to set the variable on * @param variable the name of the channel variable - * @param value the new value + * @param value the new value * @since 0.2 */ - public SetVarAction(String channel, String variable, String value) - { + public SetVarAction(String channel, String variable, String value) { this.channel = channel; this.variable = variable; this.value = value; @@ -85,72 +81,65 @@ public SetVarAction(String channel, String variable, String value) /** * Returns the name of this action, i.e. "SetVar". - * + * * @return the name of this action */ @Override - public String getAction() - { + public String getAction() { return "SetVar"; } /** * Returns the name of the channel. - * + * * @return the name of channel. */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel. - * + * * @param channel the name of the channel to set. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the name of the variable to set. - * + * * @return the name of the variable to set. */ - public String getVariable() - { + public String getVariable() { return variable; } /** * Sets the name of the variable to set. - * + * * @param variable the name of the variable to set. */ - public void setVariable(String variable) - { + public void setVariable(String variable) { this.variable = variable; } /** * Returns the value to store. - * + * * @return the value to store. */ - public String getValue() - { + public String getValue() { return value; } /** * Sets the value to store. - * + * * @param value the value to set. */ - public void setValue(String value) - { + public void setValue(String value) { this.value = value; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ShowDialplanAction.java b/src/main/java/org/asteriskjava/manager/action/ShowDialplanAction.java index 276c987f1..d7b96f85b 100644 --- a/src/main/java/org/asteriskjava/manager/action/ShowDialplanAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ShowDialplanAction.java @@ -32,26 +32,22 @@ * @see org.asteriskjava.manager.event.ShowDialplanCompleteEvent * @since 1.0.0 */ -public class ShowDialplanAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class ShowDialplanAction extends AbstractManagerAction implements EventGeneratingAction { private static final long serialVersionUID = 1L; /** * Creates a new ShowDialplanAction. */ - public ShowDialplanAction() - { + public ShowDialplanAction() { } @Override - public String getAction() - { + public String getAction() { return "ShowDialplan"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return ShowDialplanCompleteEvent.class; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/SipNotifyAction.java b/src/main/java/org/asteriskjava/manager/action/SipNotifyAction.java index e7d8ab04b..13cef02dc 100644 --- a/src/main/java/org/asteriskjava/manager/action/SipNotifyAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SipNotifyAction.java @@ -13,8 +13,7 @@ * @version $Id$ * @since 1.0.0 */ -public class SipNotifyAction extends AbstractManagerAction -{ +public class SipNotifyAction extends AbstractManagerAction { /** * Serializable version identifier. */ @@ -26,8 +25,7 @@ public class SipNotifyAction extends AbstractManagerAction /** * Creates a new SipNotifyAction. */ - public SipNotifyAction() - { + public SipNotifyAction() { super(); } @@ -36,8 +34,7 @@ public SipNotifyAction() * * @param channel the peer to send the notify to either "SIP/peer" or just "peer". */ - public SipNotifyAction(String channel) - { + public SipNotifyAction(String channel) { super(); this.channel = channel; } @@ -46,8 +43,7 @@ public SipNotifyAction(String channel) * Returns the name of this action, i.e. "SipNotify". */ @Override - public String getAction() - { + public String getAction() { return "SipNotify"; } @@ -56,8 +52,7 @@ public String getAction() * * @param channel peer to receive the notify to either "SIP/peer" or just "peer". */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -66,8 +61,7 @@ public void setChannel(String channel) * * @return peer */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -75,11 +69,10 @@ public String getChannel() * Returns the variables to set on the originated call. * * @return a Map containing the variable names as key and their - * values as value. + * values as value. * @since 1.0.0 */ - public Map getVariables() - { + public Map getVariables() { return variables; } @@ -90,10 +83,8 @@ public Map getVariables() * @param value the value of the variable to set. * @since 1.0.0 */ - public void setVariable(String name, String value) - { - if (variables == null) - { + public void setVariable(String name, String value) { + if (variables == null) { variables = new LinkedHashMap<>(); } @@ -107,8 +98,7 @@ public void setVariable(String name, String value) * values as value. * @since 1.0.0 */ - public void setVariables(Map variables) - { + public void setVariables(Map variables) { this.variables = variables; } diff --git a/src/main/java/org/asteriskjava/manager/action/SipPeersAction.java b/src/main/java/org/asteriskjava/manager/action/SipPeersAction.java index 47cfb2094..212ea7e89 100644 --- a/src/main/java/org/asteriskjava/manager/action/SipPeersAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SipPeersAction.java @@ -25,7 +25,7 @@ * the details. When all peers have been reported a PeerlistCompleteEvent is * sent.

    * Available since Asterisk 1.2 - * + *

    * Permission required: write=system * * @author srt @@ -34,8 +34,7 @@ * @see org.asteriskjava.manager.event.PeerlistCompleteEvent * @since 0.2 */ -public class SipPeersAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class SipPeersAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serial version identifier. */ @@ -44,19 +43,16 @@ public class SipPeersAction extends AbstractManagerAction implements EventGenera /** * Creates a new SipPeersAction. */ - public SipPeersAction() - { + public SipPeersAction() { } @Override - public String getAction() - { + public String getAction() { return "SIPPeers"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return PeerlistCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SipShowPeerAction.java b/src/main/java/org/asteriskjava/manager/action/SipShowPeerAction.java index 2551937d0..6c6428c3f 100644 --- a/src/main/java/org/asteriskjava/manager/action/SipShowPeerAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SipShowPeerAction.java @@ -26,16 +26,15 @@ * to retrieve the properties. Consider using {@link org.asteriskjava.manager.action.SipPeersAction} * instead.

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ - * @since 0.2 * @see org.asteriskjava.manager.action.SipPeersAction * @see org.asteriskjava.manager.response.SipShowPeerResponse + * @since 0.2 */ @ExpectedResponse(SipShowPeerResponse.class) -public class SipShowPeerAction extends AbstractManagerAction -{ +public class SipShowPeerAction extends AbstractManagerAction { /** * Serial version identifier. */ @@ -45,8 +44,7 @@ public class SipShowPeerAction extends AbstractManagerAction /** * Creates a new empty SipShowPeerAction. */ - public SipShowPeerAction() - { + public SipShowPeerAction() { } @@ -56,29 +54,26 @@ public SipShowPeerAction() *

    * This is just the peer name without the channel type prefix. For example * if your channel is called "SIP/john", the peer name is just "john". - * + * * @param peer the name of the SIP peer to retrieve details for. * @since 0.2 */ - public SipShowPeerAction(String peer) - { + public SipShowPeerAction(String peer) { this.peer = peer; } @Override - public String getAction() - { + public String getAction() { return "SIPShowPeer"; } /** * Returns the name of the peer to retrieve.

    * This parameter is mandatory. - * + * * @return the name of the peer to retrieve without the channel type prefix. */ - public String getPeer() - { + public String getPeer() { return peer; } @@ -89,11 +84,10 @@ public String getPeer() * if your channel is called "SIP/john", the peer name is just "john". *

    * This parameter is mandatory. - * + * * @param peer the name of the peer to retrieve without the channel type prefix. */ - public void setPeer(String peer) - { + public void setPeer(String peer) { this.peer = peer; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SipShowRegistryAction.java b/src/main/java/org/asteriskjava/manager/action/SipShowRegistryAction.java index 19ad7fa73..2809e83d4 100644 --- a/src/main/java/org/asteriskjava/manager/action/SipShowRegistryAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SipShowRegistryAction.java @@ -33,28 +33,24 @@ * @see RegistryEntryEvent * @since 1.0.0 */ -public class SipShowRegistryAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class SipShowRegistryAction extends AbstractManagerAction implements EventGeneratingAction { /** - * - */ - private static final long serialVersionUID = -4501597578392156556L; + * + */ + private static final long serialVersionUID = -4501597578392156556L; - /** + /** * Creates a new SipShowRegistryAction. */ - public SipShowRegistryAction() - { + public SipShowRegistryAction() { } @Override - public String getAction() - { + public String getAction() { return "SipShowRegistry"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return RegistrationsCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SkypeAccountPropertyAction.java b/src/main/java/org/asteriskjava/manager/action/SkypeAccountPropertyAction.java index 53eef2ad2..e3367485e 100644 --- a/src/main/java/org/asteriskjava/manager/action/SkypeAccountPropertyAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SkypeAccountPropertyAction.java @@ -25,8 +25,7 @@ * * @since 1.0.0 */ -public class SkypeAccountPropertyAction extends AbstractManagerAction -{ +public class SkypeAccountPropertyAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -48,8 +47,7 @@ public class SkypeAccountPropertyAction extends AbstractManagerAction /** * Creates a new SkypeAccountPropertyAction. */ - public SkypeAccountPropertyAction() - { + public SkypeAccountPropertyAction() { } @@ -60,8 +58,7 @@ public SkypeAccountPropertyAction() * @param user the Skype username of the user to add the buddy to. * @param variables the properties to set. Must not be null */ - public SkypeAccountPropertyAction(String user, Map variables) - { + public SkypeAccountPropertyAction(String user, Map variables) { this.user = user; setVariables(variables); } @@ -72,8 +69,7 @@ public SkypeAccountPropertyAction(String user, Map variables) * * @return the Skype username of the Skype for Asterisk user. */ - public String getUser() - { + public String getUser() { return user; } @@ -82,42 +78,34 @@ public String getUser() * * @param user the Skype username of the Skype for Asterisk user. */ - public void setUser(String user) - { + public void setUser(String user) { this.user = user; } - public Map getVariables() - { + public Map getVariables() { return new HashMap<>(variables); } - public void setVariables(Map variables) - { - if (variables == null) - { + public void setVariables(Map variables) { + if (variables == null) { throw new IllegalArgumentException("Variables cannot be null"); } this.variables = new HashMap<>(variables); } - public void setTimezone(String timezone) - { + public void setTimezone(String timezone) { variables.put(PROPERTY_TIMEZONE, timezone); } - public void setSkypename(String skypename) - { + public void setSkypename(String skypename) { variables.put(PROPERTY_SKYPENAME, skypename); } - public void setAvailability(String availability) - { + public void setAvailability(String availability) { variables.put(PROPERTY_AVAILABILITY, availability); } - public void setFullname(String fullname) - { + public void setFullname(String fullname) { variables.put(PROPERTY_FULLNAME, fullname); } @@ -126,8 +114,7 @@ public void setFullname(String fullname) * * @param language the ISO language code. */ - public void setLanguage(String language) - { + public void setLanguage(String language) { variables.put(PROPERTY_LANGUAGE, language); } @@ -136,28 +123,23 @@ public void setLanguage(String language) * * @param country the country code. */ - public void setCountry(String country) - { + public void setCountry(String country) { variables.put(PROPERTY_COUNTRY, country); } - public void setPhoneHome(String phoneHome) - { + public void setPhoneHome(String phoneHome) { variables.put(PROPERTY_PHONE_HOME, phoneHome); } - public void setPhoneOffice(String phoneOffice) - { + public void setPhoneOffice(String phoneOffice) { variables.put(PROPERTY_PHONE_OFFICE, phoneOffice); } - public void setPhoneMobile(String phoneMobile) - { + public void setPhoneMobile(String phoneMobile) { variables.put(PROPERTY_PHONE_MOBILE, phoneMobile); } - public void setAbout(String about) - { + public void setAbout(String about) { variables.put(PROPERTY_ABOUT, about); } @@ -165,8 +147,7 @@ public void setAbout(String about) * Returns the name of this action, i.e. "SkypeAccountProperty". */ @Override - public String getAction() - { + public String getAction() { return "SkypeAccountProperty"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SkypeAddBuddyAction.java b/src/main/java/org/asteriskjava/manager/action/SkypeAddBuddyAction.java index 5a9490323..dacea3a9f 100644 --- a/src/main/java/org/asteriskjava/manager/action/SkypeAddBuddyAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SkypeAddBuddyAction.java @@ -22,8 +22,7 @@ * * @since 1.0.0 */ -public class SkypeAddBuddyAction extends AbstractManagerAction -{ +public class SkypeAddBuddyAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -35,8 +34,7 @@ public class SkypeAddBuddyAction extends AbstractManagerAction /** * Creates a new SkypeAddBuddyAction. */ - public SkypeAddBuddyAction() - { + public SkypeAddBuddyAction() { } @@ -47,8 +45,7 @@ public SkypeAddBuddyAction() * @param user the Skype username of the user to add the buddy to. * @param buddy the Skype username of the buddy. */ - public SkypeAddBuddyAction(String user, String buddy) - { + public SkypeAddBuddyAction(String user, String buddy) { this.user = user; this.buddy = buddy; } @@ -61,8 +58,7 @@ public SkypeAddBuddyAction(String user, String buddy) * @param buddy the Skype username of the buddy. * @param authMsg the auth message. */ - public SkypeAddBuddyAction(String user, String buddy, String authMsg) - { + public SkypeAddBuddyAction(String user, String buddy, String authMsg) { this.user = user; this.buddy = buddy; this.authMsg = authMsg; @@ -74,8 +70,7 @@ public SkypeAddBuddyAction(String user, String buddy, String authMsg) * * @return the Skype username of the Skype for Asterisk user. */ - public String getUser() - { + public String getUser() { return user; } @@ -84,8 +79,7 @@ public String getUser() * * @param user the Skype username of the Skype for Asterisk user. */ - public void setUser(String user) - { + public void setUser(String user) { this.user = user; } @@ -94,8 +88,7 @@ public void setUser(String user) * * @return the Skype username of the buddy. */ - public String getBuddy() - { + public String getBuddy() { return buddy; } @@ -105,8 +98,7 @@ public String getBuddy() * * @param buddy the Skype username of the buddy. */ - public void setBuddy(String buddy) - { + public void setBuddy(String buddy) { this.buddy = buddy; } @@ -115,8 +107,7 @@ public void setBuddy(String buddy) * * @return the auth message. */ - public String getAuthMsg() - { + public String getAuthMsg() { return authMsg; } @@ -125,8 +116,7 @@ public String getAuthMsg() * * @param authMsg the auth message. */ - public void setAuthMsg(String authMsg) - { + public void setAuthMsg(String authMsg) { this.authMsg = authMsg; } @@ -134,8 +124,7 @@ public void setAuthMsg(String authMsg) * Returns the name of this action, i.e. "SkypeAddBuddy". */ @Override - public String getAction() - { + public String getAction() { return "SkypeAddBuddy"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SkypeBuddiesAction.java b/src/main/java/org/asteriskjava/manager/action/SkypeBuddiesAction.java index 60946992a..f7610ba07 100644 --- a/src/main/java/org/asteriskjava/manager/action/SkypeBuddiesAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SkypeBuddiesAction.java @@ -30,8 +30,7 @@ * @see org.asteriskjava.manager.event.SkypeBuddyListCompleteEvent * @since 1.0.0 */ -public class SkypeBuddiesAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class SkypeBuddiesAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serializable version identifier */ @@ -41,8 +40,7 @@ public class SkypeBuddiesAction extends AbstractManagerAction implements EventGe /** * Creates a new SkypeBuddiesAction. */ - public SkypeBuddiesAction() - { + public SkypeBuddiesAction() { } @@ -51,8 +49,7 @@ public SkypeBuddiesAction() * * @param user the Skype username of the user to retrieve the buddy list for. */ - public SkypeBuddiesAction(String user) - { + public SkypeBuddiesAction(String user) { this.user = user; } @@ -62,8 +59,7 @@ public SkypeBuddiesAction(String user) * * @return the Skype username of the user to retrieve the buddy list for. */ - public String getUser() - { + public String getUser() { return user; } @@ -72,8 +68,7 @@ public String getUser() * * @param user the Skype username of the user to retrieve the buddy list for. */ - public void setUser(String user) - { + public void setUser(String user) { this.user = user; } @@ -81,13 +76,11 @@ public void setUser(String user) * Returns the name of this action, i.e. "SkypeBuddies". */ @Override - public String getAction() - { + public String getAction() { return "SkypeBuddies"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return SkypeBuddyListCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SkypeBuddyAction.java b/src/main/java/org/asteriskjava/manager/action/SkypeBuddyAction.java index 738fc9019..a45acc1f2 100644 --- a/src/main/java/org/asteriskjava/manager/action/SkypeBuddyAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SkypeBuddyAction.java @@ -26,8 +26,7 @@ * @since 1.0.0 */ @ExpectedResponse(SkypeBuddyResponse.class) -public class SkypeBuddyAction extends AbstractManagerAction -{ +public class SkypeBuddyAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -38,8 +37,7 @@ public class SkypeBuddyAction extends AbstractManagerAction /** * Creates a new SkypeBuddiesAction. */ - public SkypeBuddyAction() - { + public SkypeBuddyAction() { } @@ -49,8 +47,7 @@ public SkypeBuddyAction() * @param user the Skype username of the user to retrieve the buddy details for. * @param buddy the Skype username of the buddy. */ - public SkypeBuddyAction(String user, String buddy) - { + public SkypeBuddyAction(String user, String buddy) { this.user = user; this.buddy = buddy; } @@ -61,8 +58,7 @@ public SkypeBuddyAction(String user, String buddy) * * @return the Skype username of the Skype for Asterisk user. */ - public String getUser() - { + public String getUser() { return user; } @@ -71,8 +67,7 @@ public String getUser() * * @param user the Skype username of the Skype for Asterisk user. */ - public void setUser(String user) - { + public void setUser(String user) { this.user = user; } @@ -81,8 +76,7 @@ public void setUser(String user) * * @return the Skype username of the buddy. */ - public String getBuddy() - { + public String getBuddy() { return buddy; } @@ -92,8 +86,7 @@ public String getBuddy() * * @param buddy the Skype username of the buddy. */ - public void setBuddy(String buddy) - { + public void setBuddy(String buddy) { this.buddy = buddy; } @@ -101,8 +94,7 @@ public void setBuddy(String buddy) * Returns the name of this action, i.e. "SkypeBuddy". */ @Override - public String getAction() - { + public String getAction() { return "SkypeBuddy"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SkypeChatSendAction.java b/src/main/java/org/asteriskjava/manager/action/SkypeChatSendAction.java index 956b6bdd8..76a961bd0 100644 --- a/src/main/java/org/asteriskjava/manager/action/SkypeChatSendAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SkypeChatSendAction.java @@ -22,8 +22,7 @@ * * @since 1.0.0 */ -public class SkypeChatSendAction extends AbstractManagerAction -{ +public class SkypeChatSendAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -35,20 +34,18 @@ public class SkypeChatSendAction extends AbstractManagerAction /** * Creates a new SkypeAddBuddyAction. */ - public SkypeChatSendAction() - { + public SkypeChatSendAction() { } /** * Creates a new SkypeChatSendAction with the given parameters. * - * @param user the Skype username of the sender of this chat message. + * @param user the Skype username of the sender of this chat message. * @param skypename the Skype username of the recipient of this chat message. - * @param message the message to send. Must not contain newlines but you can use "\r". + * @param message the message to send. Must not contain newlines but you can use "\r". */ - public SkypeChatSendAction(String user, String skypename, String message) - { + public SkypeChatSendAction(String user, String skypename, String message) { this.user = user; this.skypename = skypename; this.message = message; @@ -59,8 +56,7 @@ public SkypeChatSendAction(String user, String skypename, String message) * * @return the Skype username of the recipient of this chat message. */ - public String getSkypename() - { + public String getSkypename() { return skypename; } @@ -69,8 +65,7 @@ public String getSkypename() * * @param skypename the Skype username of the recipient of this chat message. */ - public void setSkypename(String skypename) - { + public void setSkypename(String skypename) { this.skypename = skypename; } @@ -79,8 +74,7 @@ public void setSkypename(String skypename) * * @return the Skype username of the sender of this chat message. */ - public String getUser() - { + public String getUser() { return user; } @@ -89,8 +83,7 @@ public String getUser() * * @param user the Skype username of the sender of this chat message. */ - public void setUser(String user) - { + public void setUser(String user) { this.user = user; } @@ -99,8 +92,7 @@ public void setUser(String user) * * @return the message to send. */ - public String getMessage() - { + public String getMessage() { return message; } @@ -109,8 +101,7 @@ public String getMessage() * * @param message the message to send. */ - public void setMessage(String message) - { + public void setMessage(String message) { this.message = message; } @@ -118,8 +109,7 @@ public void setMessage(String message) * Returns the name of this action, i.e. "SkypeChatSend". */ @Override - public String getAction() - { + public String getAction() { return "SkypeChatSend"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SkypeLicenseListAction.java b/src/main/java/org/asteriskjava/manager/action/SkypeLicenseListAction.java index a81fca4b1..c8787a7e3 100644 --- a/src/main/java/org/asteriskjava/manager/action/SkypeLicenseListAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SkypeLicenseListAction.java @@ -30,8 +30,7 @@ * @see org.asteriskjava.manager.event.SkypeLicenseListCompleteEvent * @since 1.0.0 */ -public class SkypeLicenseListAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class SkypeLicenseListAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serializable version identifier */ @@ -40,8 +39,7 @@ public class SkypeLicenseListAction extends AbstractManagerAction implements Eve /** * Creates a new SkypeLicenseListAction. */ - public SkypeLicenseListAction() - { + public SkypeLicenseListAction() { } @@ -49,13 +47,11 @@ public SkypeLicenseListAction() * Returns the name of this action, i.e. "SkypeLicenseList". */ @Override - public String getAction() - { + public String getAction() { return "SkypeLicenseList"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return SkypeBuddyListCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SkypeLicenseStatusAction.java b/src/main/java/org/asteriskjava/manager/action/SkypeLicenseStatusAction.java index 476d02948..87aff086c 100644 --- a/src/main/java/org/asteriskjava/manager/action/SkypeLicenseStatusAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SkypeLicenseStatusAction.java @@ -26,8 +26,7 @@ * @since 1.0.0 */ @ExpectedResponse(SkypeLicenseStatusResponse.class) -public class SkypeLicenseStatusAction extends AbstractManagerAction -{ +public class SkypeLicenseStatusAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -36,8 +35,7 @@ public class SkypeLicenseStatusAction extends AbstractManagerAction /** * Creates a new SkypeLicenseStatusAction. */ - public SkypeLicenseStatusAction() - { + public SkypeLicenseStatusAction() { } @@ -45,8 +43,7 @@ public SkypeLicenseStatusAction() * Returns the name of this action, i.e. "SkypeLicenseStatus". */ @Override - public String getAction() - { + public String getAction() { return "SkypeLicenseStatus"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/SkypeRemoveBuddyAction.java b/src/main/java/org/asteriskjava/manager/action/SkypeRemoveBuddyAction.java index 94e15d2b0..80fce7212 100644 --- a/src/main/java/org/asteriskjava/manager/action/SkypeRemoveBuddyAction.java +++ b/src/main/java/org/asteriskjava/manager/action/SkypeRemoveBuddyAction.java @@ -22,8 +22,7 @@ * * @since 1.0.0 */ -public class SkypeRemoveBuddyAction extends AbstractManagerAction -{ +public class SkypeRemoveBuddyAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -34,8 +33,7 @@ public class SkypeRemoveBuddyAction extends AbstractManagerAction /** * Creates a new SkypeRemoveBuddyAction. */ - public SkypeRemoveBuddyAction() - { + public SkypeRemoveBuddyAction() { } @@ -46,8 +44,7 @@ public SkypeRemoveBuddyAction() * @param user the Skype username of the user to add the buddy to. * @param buddy the Skype username of the buddy. */ - public SkypeRemoveBuddyAction(String user, String buddy) - { + public SkypeRemoveBuddyAction(String user, String buddy) { this.user = user; this.buddy = buddy; } @@ -58,8 +55,7 @@ public SkypeRemoveBuddyAction(String user, String buddy) * * @return the Skype username of the Skype for Asterisk user. */ - public String getUser() - { + public String getUser() { return user; } @@ -68,8 +64,7 @@ public String getUser() * * @param user the Skype username of the Skype for Asterisk user. */ - public void setUser(String user) - { + public void setUser(String user) { this.user = user; } @@ -78,8 +73,7 @@ public void setUser(String user) * * @return the Skype username of the buddy. */ - public String getBuddy() - { + public String getBuddy() { return buddy; } @@ -89,8 +83,7 @@ public String getBuddy() * * @param buddy the Skype username of the buddy. */ - public void setBuddy(String buddy) - { + public void setBuddy(String buddy) { this.buddy = buddy; } @@ -98,8 +91,7 @@ public void setBuddy(String buddy) * Returns the name of this action, i.e. "SkypeRemoveBuddy". */ @Override - public String getAction() - { + public String getAction() { return "SkypeRemoveBuddy"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/StatusAction.java b/src/main/java/org/asteriskjava/manager/action/StatusAction.java index b32b85e9e..a3e728d58 100644 --- a/src/main/java/org/asteriskjava/manager/action/StatusAction.java +++ b/src/main/java/org/asteriskjava/manager/action/StatusAction.java @@ -16,12 +16,12 @@ */ package org.asteriskjava.manager.action; -import java.util.Iterator; -import java.util.List; - import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.manager.event.StatusCompleteEvent; +import java.util.Iterator; +import java.util.List; + /** * The StatusAction requests the state of all active channels. Alternativly (as of Asterisk 1.6) * you can also pass a channel name to only retrive the status of one specific channel.

    @@ -33,8 +33,7 @@ * @see org.asteriskjava.manager.event.StatusEvent * @see org.asteriskjava.manager.event.StatusCompleteEvent */ -public class StatusAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class StatusAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serializable version identifier. */ @@ -46,8 +45,7 @@ public class StatusAction extends AbstractManagerAction implements EventGenerati /** * Creates a new StatusAction that retrieves the status of all channels. */ - public StatusAction() - { + public StatusAction() { } @@ -58,8 +56,7 @@ public StatusAction() * @param channel name of the channel. * @since 1.0.0 */ - public StatusAction(String channel) - { + public StatusAction(String channel) { this.channel = channel; } @@ -67,13 +64,11 @@ public StatusAction(String channel) * Returns the name of this action, i.e. "Status". */ @Override - public String getAction() - { + public String getAction() { return "Status"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return StatusCompleteEvent.class; } @@ -84,8 +79,7 @@ public Class getActionCompleteEventClass() * @return the name of the channel or null for all channels. * @since 1.0.0 */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -96,13 +90,11 @@ public String getChannel() * @param channel the name of the channel or null for all channels. * @since 1.0.0 */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } - public String getVariables() - { + public String getVariables() { return variables; } @@ -111,11 +103,10 @@ public String getVariables() * Available since Asterisk 1.6. * * @param variables comma separated list of variables to return for each reported channel. - * @see org.asteriskjava.manager.event.StatusEvent#getVariables() + * @see org.asteriskjava.manager.event.StatusEvent#getVariables() * @since 1.0.0 */ - public void setVariables(String variables) - { + public void setVariables(String variables) { this.variables = variables; } @@ -127,18 +118,15 @@ public void setVariables(String variables) * @see org.asteriskjava.manager.event.StatusEvent#getVariables() * @since 1.0.0 */ - public void setVariables(List variables) - { - if (variables == null || variables.isEmpty()) - { + public void setVariables(List variables) { + if (variables == null || variables.isEmpty()) { this.variables = null; return; } Iterator iter = variables.iterator(); StringBuilder buffer = new StringBuilder(iter.next()); - while (iter.hasNext()) - { + while (iter.hasNext()) { buffer.append(",").append(iter.next()); } this.variables = buffer.toString(); diff --git a/src/main/java/org/asteriskjava/manager/action/StopMixMonitorAction.java b/src/main/java/org/asteriskjava/manager/action/StopMixMonitorAction.java index 79d172279..5e5047f19 100644 --- a/src/main/java/org/asteriskjava/manager/action/StopMixMonitorAction.java +++ b/src/main/java/org/asteriskjava/manager/action/StopMixMonitorAction.java @@ -18,15 +18,14 @@ /** * Stop the specified MixMonitor on the specified channel. - * + *

    * Available since Asterisk 11 * * @see MixMonitorAction * @see PauseMixMonitorAction * @see MixMonitorMuteAction */ -public class StopMixMonitorAction extends AbstractManagerAction -{ +public class StopMixMonitorAction extends AbstractManagerAction { private static final long serialVersionUID = 1L; private String channel; private String mixMonitorId; @@ -34,8 +33,7 @@ public class StopMixMonitorAction extends AbstractManagerAction /** * Creates a new empty StopMixMonitorAction */ - public StopMixMonitorAction() - { + public StopMixMonitorAction() { super(); } @@ -43,10 +41,9 @@ public StopMixMonitorAction() * Creates a StopMixMonitorAction that stops all MixMonitors on the * specified channel. * - * @param channel the name of the channel + * @param channel the name of the channel */ - public StopMixMonitorAction(String channel) - { + public StopMixMonitorAction(String channel) { this(channel, null); } @@ -54,11 +51,10 @@ public StopMixMonitorAction(String channel) * Creates a StopMixMonitorAction that stops the specified MixMonitor on * the specified channel. * - * @param channel the name of the channel - * @param mixMonitorId the ID of the MixMonitor to stop + * @param channel the name of the channel + * @param mixMonitorId the ID of the MixMonitor to stop */ - public StopMixMonitorAction(String channel, String mixMonitorId) - { + public StopMixMonitorAction(String channel, String mixMonitorId) { this.channel = channel; this.mixMonitorId = mixMonitorId; } @@ -69,8 +65,7 @@ public StopMixMonitorAction(String channel, String mixMonitorId) * @return the name of the AMI action that this class implements */ @Override - public String getAction() - { + public String getAction() { return "StopMixMonitor"; } @@ -79,8 +74,7 @@ public String getAction() * * @return the Asterisk channel name */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -89,8 +83,7 @@ public String getChannel() * * @param channel the Asterisk channel name */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -99,8 +92,7 @@ public void setChannel(String channel) * * @return the MixMonitor ID */ - public String getMixMonitorId() - { + public String getMixMonitorId() { return mixMonitorId; } @@ -109,8 +101,7 @@ public String getMixMonitorId() * * @param mixMonitorId the MixMonitor ID */ - public void setMixMonitorId(String mixMonitorId) - { + public void setMixMonitorId(String mixMonitorId) { this.mixMonitorId = mixMonitorId; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/StopMonitorAction.java b/src/main/java/org/asteriskjava/manager/action/StopMonitorAction.java index cca664936..5e5ca8c37 100644 --- a/src/main/java/org/asteriskjava/manager/action/StopMonitorAction.java +++ b/src/main/java/org/asteriskjava/manager/action/StopMonitorAction.java @@ -19,12 +19,11 @@ /** * The StopMonitorAction ends monitoring (recording) a channel.

    * It is implemented in res/res_monitor.c - * + * * @author srt * @version $Id$ */ -public class StopMonitorAction extends AbstractManagerAction -{ +public class StopMonitorAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -38,52 +37,47 @@ public class StopMonitorAction extends AbstractManagerAction /** * Creates a new empty StopMonitorAction. */ - public StopMonitorAction() - { + public StopMonitorAction() { } /** * Creates a new StopMonitorAction that ends monitoring of the given * channel. - * + * * @param channel the name of the channel to stop monitoring. * @since 0.2 */ - public StopMonitorAction(String channel) - { + public StopMonitorAction(String channel) { this.channel = channel; } /** * Returns the name of this action, i.e. "StopMonitor". - * + * * @return the name of this action. */ @Override - public String getAction() - { + public String getAction() { return "StopMonitor"; } /** * Returns the name of the channel to end monitoring. - * + * * @return the name of the channel to end monitoring. */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel to end monitoring.

    * This property is mandatory. - * + * * @param channel the name of the channel to end monitoring. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/action/UnpauseMonitorAction.java b/src/main/java/org/asteriskjava/manager/action/UnpauseMonitorAction.java index 964d1bf76..62821291d 100644 --- a/src/main/java/org/asteriskjava/manager/action/UnpauseMonitorAction.java +++ b/src/main/java/org/asteriskjava/manager/action/UnpauseMonitorAction.java @@ -23,14 +23,13 @@ * It is implemented in res/res_monitor.c *

    * Available since Asterisk 1.4. - * - * @see PauseMonitorAction + * * @author srt - * @since 0.3 * @version $Id$ + * @see PauseMonitorAction + * @since 0.3 */ -public class UnpauseMonitorAction extends AbstractManagerAction -{ +public class UnpauseMonitorAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -44,40 +43,36 @@ public class UnpauseMonitorAction extends AbstractManagerAction /** * Creates a new empty UnpauseMonitorAction. */ - public UnpauseMonitorAction() - { + public UnpauseMonitorAction() { } /** * Creates a new UnpauseMonitorAction that re-enables monitoring the given * channel. - * + * * @param channel the name of the channel re-enable monitoring. */ - public UnpauseMonitorAction(String channel) - { + public UnpauseMonitorAction(String channel) { this.channel = channel; } /** * Returns the name of this action, i.e. "UnpauseMonitor". - * + * * @return the name of this action. */ @Override - public String getAction() - { + public String getAction() { return "UnpauseMonitor"; } /** * Returns the name of the channel to re-enable monitoring. - * + * * @return the name of the channel to re-enable monitoring. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -85,11 +80,10 @@ public String getChannel() * Sets the name of the channel to re-enable monitoring. *

    * This property is mandatory. - * + * * @param channel the name of the channel to re-enable monitoring. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/action/UpdateConfigAction.java b/src/main/java/org/asteriskjava/manager/action/UpdateConfigAction.java index 057eabd71..f3fd0ad43 100644 --- a/src/main/java/org/asteriskjava/manager/action/UpdateConfigAction.java +++ b/src/main/java/org/asteriskjava/manager/action/UpdateConfigAction.java @@ -35,14 +35,13 @@ * Cat-XXXXXX: Category to operate on Var-XXXXXX: Variable to work on * Value-XXXXXX: Value to work on Match-XXXXXX: Extra match required to match * line - * + * + * @author martins * @see org.asteriskjava.manager.response.GetConfigResponse * @see org.asteriskjava.manager.action.UpdateConfigAction#addCommand - * @author martins * @since 0.3 */ -public class UpdateConfigAction extends AbstractManagerAction -{ +public class UpdateConfigAction extends AbstractManagerAction { /** * Serializable version identifier. */ @@ -58,7 +57,7 @@ public class UpdateConfigAction extends AbstractManagerAction public static final String ACTION_UPDATE = "Update"; public static final String ACTION_DELETE = "Delete"; public static final String ACTION_APPEND = "Append"; - + protected String srcFilename; protected String dstFilename; protected String reload; @@ -69,19 +68,17 @@ public class UpdateConfigAction extends AbstractManagerAction /** * Creates a new UpdateConfigAction. */ - public UpdateConfigAction() - { + public UpdateConfigAction() { this.actionCounter = 0; actions = new HashMap<>(); } /** * Creates a new UpdateConfigAction with the given parameters. - * + * * @param srcFilename the name of the file to get. */ - public UpdateConfigAction(String srcFilename, String dstFilename, boolean reload) - { + public UpdateConfigAction(String srcFilename, String dstFilename, boolean reload) { this.actionCounter = 0; this.srcFilename = srcFilename; this.dstFilename = dstFilename; @@ -95,42 +92,36 @@ public UpdateConfigAction(String srcFilename, String dstFilename, boolean reload * sections, provide a null value to this method. The command index will be * incremented even if you supply a null for all parameters, though the map * will be unaffected. - * + * * @param action Action to Take - * (NewCat,RenameCat,DelCat,Update,Delete,Append), see static - * fields - * @param cat Category to operate on - * @param var Variable to work on - * @param value Value to work on - * @param match Extra match required to match line + * (NewCat,RenameCat,DelCat,Update,Delete,Append), see static + * fields + * @param cat Category to operate on + * @param var Variable to work on + * @param value Value to work on + * @param match Extra match required to match line */ - public void addCommand(String action, String cat, String var, String value, String match) - { + public void addCommand(String action, String cat, String var, String value, String match) { // for convienence of reference, shorter! final String stringCounter = String.format("%06d", this.actionCounter); - if (action != null) - { + if (action != null) { actions.put("Action-" + stringCounter, action); } - if (cat != null) - { + if (cat != null) { actions.put("Cat-" + stringCounter, cat); } - if (var != null) - { + if (var != null) { actions.put("Var-" + stringCounter, var); } - if (value != null) - { + if (value != null) { actions.put("Value-" + stringCounter, value); } - if (match != null) - { + if (match != null) { actions.put("Match-" + stringCounter, match); } @@ -141,73 +132,65 @@ public void addCommand(String action, String cat, String var, String value, Stri * Returns the name of this action, i.e. "UpdateConfig". */ @Override - public String getAction() - { + public String getAction() { return "UpdateConfig"; } /** * Returns the source filename. */ - public String getSrcFilename() - { + public String getSrcFilename() { return srcFilename; } /** * Sets the source filename. */ - public void setSrcFilename(String filename) - { + public void setSrcFilename(String filename) { this.srcFilename = filename; } /** * Returns the destination filename. */ - public String getDstFilename() - { + public String getDstFilename() { return dstFilename; } /** * Sets the source filename. */ - public void setDstFilename(String filename) - { + public void setDstFilename(String filename) { this.dstFilename = filename; } /** * @return should Asterisk reload, or the name of a specific module to - * reload + * reload */ - public String getReload() - { + public String getReload() { return reload; } /** * Sets the reload behavior of this action, or sets a specific module to be * reloaded - * + * * @param reload the reload parameter to set * @see org.asteriskjava.manager.action.UpdateConfigAction#setReload(boolean) */ - public void setReload(String reload) - { + public void setReload(String reload) { this.reload = reload; } /** * Sets the reload behavior of this action. If you don't know what string to * feed Asterisk, this method will provide the appropriate one. - * + * * @param reload the reload parameter to set * @see org.asteriskjava.manager.action.UpdateConfigAction#setReload(String) */ - public void setReload(boolean reload) - { + public void setReload(boolean reload) { this.reload = reload ? UpdateConfigAction.RELOAD_STRING_YES : UpdateConfigAction.RELOAD_STRING_NO; } @@ -217,12 +200,11 @@ public void setReload(boolean reload) * contain the values for those keys. This method will typically only be * used by the ActionBuilder to generate the actual strings to be sent to * the manager interface. - * - * @see org.asteriskjava.manager.action.UpdateConfigAction#addCommand + * * @return a Map of the actions that should be taken + * @see org.asteriskjava.manager.action.UpdateConfigAction#addCommand */ - public Map getAttributes() - { + public Map getAttributes() { return actions; } @@ -231,12 +213,11 @@ public Map getAttributes() * key,value pairs that you would like to send for this command. Setting * your own map will reset the command index to the number of keys in the * Map - * - * @see org.asteriskjava.manager.action.UpdateConfigAction#addCommand + * * @param actions the actions to set + * @see org.asteriskjava.manager.action.UpdateConfigAction#addCommand */ - public void setAttributes(Map actions) - { + public void setAttributes(Map actions) { this.actions = actions; this.actionCounter = actions.keySet().size(); } diff --git a/src/main/java/org/asteriskjava/manager/action/UserEventAction.java b/src/main/java/org/asteriskjava/manager/action/UserEventAction.java index 52167a7fb..f9131a5f7 100644 --- a/src/main/java/org/asteriskjava/manager/action/UserEventAction.java +++ b/src/main/java/org/asteriskjava/manager/action/UserEventAction.java @@ -7,13 +7,12 @@ * This is equivalent to using the UserEvent application in your * dial plan. Before you send this event, you must register your * event class with the registerUserEventClass method of the ManagerConnection. - * + * + * @author Martin * @see org.asteriskjava.manager.event.UserEvent * @see org.asteriskjava.manager.ManagerConnection#registerUserEventClass(Class) - * @author Martin */ -public class UserEventAction extends AbstractManagerAction -{ +public class UserEventAction extends AbstractManagerAction { /** * Serial version identifier */ @@ -24,18 +23,16 @@ public class UserEventAction extends AbstractManagerAction */ private UserEvent userEvent; - public UserEventAction() - { + public UserEventAction() { super(); } /** * Create the userevent action with userEvent as the event it will send - * + * * @param userEvent the subclass representing a custom event */ - public UserEventAction(UserEvent userEvent) - { + public UserEventAction(UserEvent userEvent) { this.userEvent = userEvent; } @@ -43,16 +40,14 @@ public UserEventAction(UserEvent userEvent) * Get the name of this action */ @Override - public String getAction() - { + public String getAction() { return "UserEvent"; } /** * @return the userEvent */ - public UserEvent getUserEvent() - { + public UserEvent getUserEvent() { return userEvent; } @@ -60,8 +55,7 @@ public UserEvent getUserEvent() * @param userEvent the userEvent to set * @see org.asteriskjava.manager.event.UserEvent */ - public void setUserEvent(UserEvent userEvent) - { + public void setUserEvent(UserEvent userEvent) { this.userEvent = userEvent; } } diff --git a/src/main/java/org/asteriskjava/manager/action/VariableInheritance.java b/src/main/java/org/asteriskjava/manager/action/VariableInheritance.java index 369f439e1..27c233b86 100644 --- a/src/main/java/org/asteriskjava/manager/action/VariableInheritance.java +++ b/src/main/java/org/asteriskjava/manager/action/VariableInheritance.java @@ -1,18 +1,15 @@ package org.asteriskjava.manager.action; -public enum VariableInheritance -{ +public enum VariableInheritance { NONE(""), SINGLE("_"), DOUBLE("__"); private String prefix; - VariableInheritance(String prefix) - { + VariableInheritance(String prefix) { this.prefix = prefix; } - String getPrefix() - { + String getPrefix() { return prefix; } } diff --git a/src/main/java/org/asteriskjava/manager/action/VoicemailUsersListAction.java b/src/main/java/org/asteriskjava/manager/action/VoicemailUsersListAction.java index 1b896995e..247c97350 100644 --- a/src/main/java/org/asteriskjava/manager/action/VoicemailUsersListAction.java +++ b/src/main/java/org/asteriskjava/manager/action/VoicemailUsersListAction.java @@ -34,8 +34,7 @@ * @see org.asteriskjava.manager.event.VoicemailUserEntryCompleteEvent * @since 1.0.0 */ -public class VoicemailUsersListAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class VoicemailUsersListAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serial version identifier. */ @@ -44,19 +43,16 @@ public class VoicemailUsersListAction extends AbstractManagerAction implements E /** * Creates a new VoicemailUsersListAction. */ - public VoicemailUsersListAction() - { + public VoicemailUsersListAction() { } @Override - public String getAction() - { + public String getAction() { return "VoicemailUsersList"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return VoicemailUserEntryCompleteEvent.class; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/action/ZapDialOffhookAction.java b/src/main/java/org/asteriskjava/manager/action/ZapDialOffhookAction.java index 961d54de3..d561a0a3c 100644 --- a/src/main/java/org/asteriskjava/manager/action/ZapDialOffhookAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ZapDialOffhookAction.java @@ -18,12 +18,11 @@ /** * The ZapDialOffhookAction dials a number on a zap channel while offhook. - * + * * @author srt * @version $Id$ */ -public class ZapDialOffhookAction extends AbstractManagerAction -{ +public class ZapDialOffhookAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -34,21 +33,19 @@ public class ZapDialOffhookAction extends AbstractManagerAction /** * Creates a new empty ZapDialOffhookAction. */ - public ZapDialOffhookAction() - { + public ZapDialOffhookAction() { } /** * Creates a new ZapDialOffhookAction that dials the given number on the * given zap channel. - * + * * @param zapChannel the number of the zap channel - * @param number the number to dial + * @param number the number to dial * @since 0.2 */ - public ZapDialOffhookAction(Integer zapChannel, String number) - { + public ZapDialOffhookAction(Integer zapChannel, String number) { this.zapChannel = zapChannel; this.number = number; } @@ -57,16 +54,14 @@ public ZapDialOffhookAction(Integer zapChannel, String number) * Returns the name of this action, i.e. "ZapDialOffhook". */ @Override - public String getAction() - { + public String getAction() { return "ZapDialOffhook"; } /** * Returns the number of the zap channel. */ - public Integer getZapChannel() - { + public Integer getZapChannel() { return zapChannel; } @@ -74,16 +69,14 @@ public Integer getZapChannel() * Sets the number of the zap channel.

    * This property is mandatory. */ - public void setZapChannel(Integer channel) - { + public void setZapChannel(Integer channel) { this.zapChannel = channel; } /** * Returns the number to dial. */ - public String getNumber() - { + public String getNumber() { return number; } @@ -91,8 +84,7 @@ public String getNumber() * Sets the number to dial.

    * This property is mandatory. */ - public void setNumber(String number) - { + public void setNumber(String number) { this.number = number; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ZapDndOffAction.java b/src/main/java/org/asteriskjava/manager/action/ZapDndOffAction.java index 18e320f9c..4cfb4f386 100644 --- a/src/main/java/org/asteriskjava/manager/action/ZapDndOffAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ZapDndOffAction.java @@ -18,12 +18,11 @@ /** * The ZapDNDOnAction switches a zap channel "Do Not Disturb" status off. - * + * * @author srt * @version $Id$ */ -public class ZapDndOffAction extends AbstractManagerAction -{ +public class ZapDndOffAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -33,20 +32,18 @@ public class ZapDndOffAction extends AbstractManagerAction /** * Creates a new empty ZapDndOffAction. */ - public ZapDndOffAction() - { + public ZapDndOffAction() { } /** * Creates a new ZapDndOffAction that disables "Do Not Disturb" status for * the given zap channel. - * + * * @param zapChannel the number of the zap channel * @since 0.2 */ - public ZapDndOffAction(Integer zapChannel) - { + public ZapDndOffAction(Integer zapChannel) { this.zapChannel = zapChannel; } @@ -54,16 +51,14 @@ public ZapDndOffAction(Integer zapChannel) * Returns the name of this action, i.e. "ZapDNDOff". */ @Override - public String getAction() - { + public String getAction() { return "ZapDNDOff"; } /** * Returns the number of the zap channel to switch to dnd off. */ - public Integer getZapChannel() - { + public Integer getZapChannel() { return zapChannel; } @@ -71,8 +66,7 @@ public Integer getZapChannel() * Sets the number of the zap channel to switch to dnd off.

    * This property is mandatory. */ - public void setZapChannel(Integer channel) - { + public void setZapChannel(Integer channel) { this.zapChannel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ZapDndOnAction.java b/src/main/java/org/asteriskjava/manager/action/ZapDndOnAction.java index f18beba34..f1c87c33b 100644 --- a/src/main/java/org/asteriskjava/manager/action/ZapDndOnAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ZapDndOnAction.java @@ -18,12 +18,11 @@ /** * The ZapDNDOnAction switches a zap channel "Do Not Disturb" status on. - * + * * @author srt * @version $Id$ */ -public class ZapDndOnAction extends AbstractManagerAction -{ +public class ZapDndOnAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -33,37 +32,33 @@ public class ZapDndOnAction extends AbstractManagerAction /** * Creates a new empty ZapDndOnAction. */ - public ZapDndOnAction() - { + public ZapDndOnAction() { } /** * Creates a new ZapDndOnAction that enables "Do Not Disturb" status for * the given zap channel. - * + * * @param zapChannel the number of the zap channel * @since 0.2 */ - public ZapDndOnAction(Integer zapChannel) - { + public ZapDndOnAction(Integer zapChannel) { this.zapChannel = zapChannel; } - + /** * Returns the name of this action, i.e. "ZapDNDOn". */ @Override - public String getAction() - { + public String getAction() { return "ZapDNDOn"; } /** * Returns the number of the zap channel to switch to dnd on. */ - public Integer getZapChannel() - { + public Integer getZapChannel() { return zapChannel; } @@ -71,8 +66,7 @@ public Integer getZapChannel() * Sets the number of the zap channel to switch to dnd on.

    * This property is mandatory. */ - public void setZapChannel(Integer channel) - { + public void setZapChannel(Integer channel) { this.zapChannel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ZapHangupAction.java b/src/main/java/org/asteriskjava/manager/action/ZapHangupAction.java index 0d1484f5e..ee1a4a15f 100644 --- a/src/main/java/org/asteriskjava/manager/action/ZapHangupAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ZapHangupAction.java @@ -18,12 +18,11 @@ /** * The ZapHangupAction hangs up a zap channel. - * + * * @author srt * @version $Id$ */ -public class ZapHangupAction extends AbstractManagerAction -{ +public class ZapHangupAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -33,19 +32,17 @@ public class ZapHangupAction extends AbstractManagerAction /** * Creates a new empty ZapHangupAction. */ - public ZapHangupAction() - { + public ZapHangupAction() { } /** * Creates a new ZapHangupAction that hangs up the given zap channel. - * + * * @param zapChannel the number of the zap channel to hang up * @since 0.2 */ - public ZapHangupAction(Integer zapChannel) - { + public ZapHangupAction(Integer zapChannel) { this.zapChannel = zapChannel; } @@ -53,16 +50,14 @@ public ZapHangupAction(Integer zapChannel) * Returns the name of this action, i.e. "ZapHangup". */ @Override - public String getAction() - { + public String getAction() { return "ZapHangup"; } /** * Returns the number of the zap channel to hangup. */ - public Integer getZapChannel() - { + public Integer getZapChannel() { return zapChannel; } @@ -70,8 +65,7 @@ public Integer getZapChannel() * Sets the number of the zap channel to hangup.

    * This property is mandatory. */ - public void setZapChannel(Integer channel) - { + public void setZapChannel(Integer channel) { this.zapChannel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ZapRestartAction.java b/src/main/java/org/asteriskjava/manager/action/ZapRestartAction.java index 395b88c6c..30c3ee96a 100644 --- a/src/main/java/org/asteriskjava/manager/action/ZapRestartAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ZapRestartAction.java @@ -5,13 +5,12 @@ * interfaces. *

    * Available since Asterisk 1.4. - * + * * @author srt - * @since 0.3 * @version $Id$ + * @since 0.3 */ -public class ZapRestartAction extends AbstractManagerAction -{ +public class ZapRestartAction extends AbstractManagerAction { /** * Serial version identifier. */ @@ -20,14 +19,12 @@ public class ZapRestartAction extends AbstractManagerAction /** * Creates a new ZapRestartAction. */ - public ZapRestartAction() - { + public ZapRestartAction() { } @Override - public String getAction() - { + public String getAction() { return "ZapRestart"; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ZapShowChannelsAction.java b/src/main/java/org/asteriskjava/manager/action/ZapShowChannelsAction.java index 181513d28..9ba259fc9 100644 --- a/src/main/java/org/asteriskjava/manager/action/ZapShowChannelsAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ZapShowChannelsAction.java @@ -23,16 +23,15 @@ * The ZapShowChannelsAction requests the state of all zap channels.

    * For each zap channel a ZapShowChannelsEvent is generated. After all zap * channels have been listed a ZapShowChannelsCompleteEvent is generated. - * - * @see org.asteriskjava.manager.event.ZapShowChannelsEvent - * @see org.asteriskjava.manager.event.ZapShowChannelsCompleteEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.ZapShowChannelsEvent + * @see org.asteriskjava.manager.event.ZapShowChannelsCompleteEvent */ public class ZapShowChannelsAction extends AbstractManagerAction implements - EventGeneratingAction -{ + EventGeneratingAction { /** * Serializable version identifier */ @@ -41,8 +40,7 @@ public class ZapShowChannelsAction extends AbstractManagerAction /** * Creates a new ZapShowChannelsAction. */ - public ZapShowChannelsAction() - { + public ZapShowChannelsAction() { } @@ -50,13 +48,11 @@ public ZapShowChannelsAction() * Returns the name of this action, i.e. "ZapShowChannels". */ @Override - public String getAction() - { + public String getAction() { return "ZapShowChannels"; } - public Class getActionCompleteEventClass() - { + public Class getActionCompleteEventClass() { return ZapShowChannelsCompleteEvent.class; } } diff --git a/src/main/java/org/asteriskjava/manager/action/ZapTransferAction.java b/src/main/java/org/asteriskjava/manager/action/ZapTransferAction.java index 7286a0dd7..e34ceb3dd 100644 --- a/src/main/java/org/asteriskjava/manager/action/ZapTransferAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ZapTransferAction.java @@ -18,12 +18,11 @@ /** * The ZapTransferAction transfers a zap channel. - * + * * @author srt * @version $Id$ */ -public class ZapTransferAction extends AbstractManagerAction -{ +public class ZapTransferAction extends AbstractManagerAction { /** * Serializable version identifier */ @@ -34,16 +33,14 @@ public class ZapTransferAction extends AbstractManagerAction * Returns the name of this action, i.e. "ZapTransfer". */ @Override - public String getAction() - { + public String getAction() { return "ZapTransfer"; } /** * Returns the number of the zap channel to transfer. */ - public Integer getZapChannel() - { + public Integer getZapChannel() { return zapChannel; } @@ -51,8 +48,7 @@ public Integer getZapChannel() * Sets the number of the zap channel to transfer.

    * This property is mandatory. */ - public void setZapChannel(Integer channel) - { + public void setZapChannel(Integer channel) { this.zapChannel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/action/package.html b/src/main/java/org/asteriskjava/manager/action/package.html index fcaac1bb6..7ec28a0e6 100644 --- a/src/main/java/org/asteriskjava/manager/action/package.html +++ b/src/main/java/org/asteriskjava/manager/action/package.html @@ -1,28 +1,28 @@ - +

    Provides classes that represent the standard actions that can be sent - to an Asterisk server via the Manager API.

    + to an Asterisk server via the Manager API.

    - \ No newline at end of file + diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractAgentEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractAgentEvent.java index 2d6a6a6b2..e6519e4a3 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractAgentEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractAgentEvent.java @@ -26,8 +26,7 @@ * @version $Id$ * @since 0.2 */ -public abstract class AbstractAgentEvent extends ManagerEvent -{ +public abstract class AbstractAgentEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private String channel; private String uniqueId; @@ -36,8 +35,7 @@ public abstract class AbstractAgentEvent extends ManagerEvent private String memberName; private Map variables; - protected AbstractAgentEvent(Object source) - { + protected AbstractAgentEvent(Object source) { super(source); } @@ -46,13 +44,11 @@ protected AbstractAgentEvent(Object source) * * @return the name of the channel. */ - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -61,13 +57,11 @@ public void setChannel(String channel) * * @return the unique id of the channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -76,13 +70,11 @@ public void setUniqueId(String uniqueId) * * @return the name of the queue. */ - public String getQueue() - { + public String getQueue() { return queue; } - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } @@ -91,13 +83,11 @@ public void setQueue(String queue) * * @return the name of the member's interface. */ - public String getMember() - { + public String getMember() { return member; } - public void setMember(String member) - { + public void setMember(String member) { this.member = member; } @@ -108,13 +98,11 @@ public void setMember(String member) * * @return the member name supplied for logging when the member is added. */ - public String getMemberName() - { + public String getMemberName() { return memberName; } - public void setMemberName(String memberName) - { + public void setMemberName(String memberName) { this.memberName = memberName; } @@ -126,8 +114,7 @@ public void setMemberName(String memberName) * @return the channel variables. * @since 1.0.0 */ - public Map getVariables() - { + public Map getVariables() { return variables; } @@ -138,8 +125,7 @@ public Map getVariables() * @param variables the channel variables. * @since 1.0.0 */ - public void setVariables(Map variables) - { + public void setVariables(Map variables) { this.variables = variables; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java index a727ea969..58f9fcf42 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java @@ -3,10 +3,9 @@ /** * Created by Alexander Polakov on 1/26/15. */ -public abstract class AbstractBridgeEvent extends ManagerEvent -{ +public abstract class AbstractBridgeEvent extends ManagerEvent { /** - * + * */ private static final long serialVersionUID = 1L; private String bridgeUniqueId; @@ -18,88 +17,71 @@ public abstract class AbstractBridgeEvent extends ManagerEvent private String accountCode; private String bridgevideosourcemode; - AbstractBridgeEvent(Object source) - { + AbstractBridgeEvent(Object source) { super(source); } - public String getBridgeUniqueId() - { + public String getBridgeUniqueId() { return bridgeUniqueId; } - public void setBridgeUniqueId(String bridgeUniqueId) - { + public void setBridgeUniqueId(String bridgeUniqueId) { this.bridgeUniqueId = bridgeUniqueId; } - public String getBridgeType() - { + public String getBridgeType() { return bridgeType; } - public void setBridgeType(String bridgeType) - { + public void setBridgeType(String bridgeType) { this.bridgeType = bridgeType; } - public Integer getBridgeNumChannels() - { + public Integer getBridgeNumChannels() { return bridgeNumChannels; } - public void setBridgeNumChannels(Integer bridgeNumChannels) - { + public void setBridgeNumChannels(Integer bridgeNumChannels) { this.bridgeNumChannels = bridgeNumChannels; } - public String getBridgeCreator() - { + public String getBridgeCreator() { return bridgeCreator; } - public void setBridgeCreator(String bridgeCreator) - { + public void setBridgeCreator(String bridgeCreator) { this.bridgeCreator = bridgeCreator; } - public String getBridgeName() - { + public String getBridgeName() { return bridgeName; } - public void setBridgeName(String bridgeName) - { + public void setBridgeName(String bridgeName) { this.bridgeName = bridgeName; } - public String getBridgeTechnology() - { + public String getBridgeTechnology() { return bridgeTechnology; } - public void setBridgeTechnology(String bridgeTechnology) - { + public void setBridgeTechnology(String bridgeTechnology) { this.bridgeTechnology = bridgeTechnology; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - public String getBridgevideosourcemode() - { + public String getBridgevideosourcemode() { return bridgevideosourcemode; } - public void setBridgevideosourcemode(String bridgevideosourcemode) - { + public void setBridgevideosourcemode(String bridgevideosourcemode) { this.bridgevideosourcemode = bridgevideosourcemode; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java index f31bfc45e..198991978 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java @@ -18,12 +18,11 @@ /** * Abstract base class providing common properties channel related events. - * + * * @author srt * @version $Id$ */ -public abstract class AbstractChannelEvent extends ManagerEvent -{ +public abstract class AbstractChannelEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -41,38 +40,33 @@ public abstract class AbstractChannelEvent extends ManagerEvent */ protected String uniqueId; - protected AbstractChannelEvent(Object source) - { + protected AbstractChannelEvent(Object source) { super(source); } /** * Returns the name of the channel. - * + * * @return the name of the channel. */ - public final String getChannel() - { + public final String getChannel() { return channel; } - public final void setChannel(String channel) - { + public final void setChannel(String channel) { this.channel = channel; } /** * Returns the unique id of the channel. - * + * * @return the unique id of the channel. */ - public final String getUniqueId() - { + public final String getUniqueId() { return uniqueId; } - public final void setUniqueId(String uniqueId) - { + public final void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -81,24 +75,22 @@ public final void setUniqueId(String uniqueId) * has been set. * * @return the Caller*ID - * @deprecated * @see #getCallerIdNum() + * @deprecated */ @Deprecated - public final String getCallerId() - { + public final String getCallerId() { return getCallerIdNum(); } /** * Sets the Caller*ID of the channel. - * + * * @param callerId the Caller*ID of the channel. * @deprecated */ @Deprecated - public final void setCallerId(String callerId) - { + public final void setCallerId(String callerId) { setCallerIdNum(callerId); } @@ -109,39 +101,33 @@ public final void setCallerId(String callerId) * @return the Caller*ID number * @since 0.3 */ - public final String getCallerIdNum() - { + public final String getCallerIdNum() { return callerIdNum; } - public final void setCallerIdNum(String callerIdNum) - { + public final void setCallerIdNum(String callerIdNum) { this.callerIdNum = callerIdNum; } /** * Returns the Caller*ID Name of the channel if set or null if * none has been set. - * + * * @return the Caller*ID Name of the channel. */ - public final String getCallerIdName() - { + public final String getCallerIdName() { return callerIdName; } - public final void setCallerIdName(String callerIdName) - { + public final void setCallerIdName(String callerIdName) { this.callerIdName = callerIdName; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractChannelStateEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractChannelStateEvent.java index abb46d710..b441be2f5 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractChannelStateEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractChannelStateEvent.java @@ -23,15 +23,13 @@ * @author srt * @version $Id$ */ -public abstract class AbstractChannelStateEvent extends AbstractChannelEvent -{ +public abstract class AbstractChannelStateEvent extends AbstractChannelEvent { /** * Serializable version identifier. */ static final long serialVersionUID = 0L; - protected AbstractChannelStateEvent(Object source) - { + protected AbstractChannelStateEvent(Object source) { super(source); } @@ -41,12 +39,11 @@ protected AbstractChannelStateEvent(Object source) * * @return the new state of the channel as a descriptive text. * @deprecated as of 1.0.0, use {@link #getChannelStateDesc()} instead or - * even better switch to numeric values as returned by - * {@link #getChannelState()}. + * even better switch to numeric values as returned by + * {@link #getChannelState()}. */ @Deprecated - public String getState() - { + public String getState() { return getChannelStateDesc(); } @@ -57,8 +54,7 @@ public String getState() * * @param state the new state of the channel as a descriptive text. */ - public void setState(String state) - { + public void setState(String state) { setChannelStateDesc(state); } } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractConfbridgeEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractConfbridgeEvent.java index 0240e90a2..c9a3c82f8 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractConfbridgeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractConfbridgeEvent.java @@ -1,7 +1,6 @@ package org.asteriskjava.manager.event; -public abstract class AbstractConfbridgeEvent extends AbstractChannelEvent -{ +public abstract class AbstractConfbridgeEvent extends AbstractChannelEvent { private static final long serialVersionUID = 3893862793876858636L; private String bridgeType; private String bridgeNumChannels; @@ -16,120 +15,105 @@ public abstract class AbstractConfbridgeEvent extends AbstractChannelEvent String admin; - public AbstractConfbridgeEvent(Object source) - { + public AbstractConfbridgeEvent(Object source) { super(source); } /** * @return the admin */ - public String getAdmin() - { + public String getAdmin() { return admin; } /** * @param admin the admin to set */ - public void setAdmin(String admin) - { + public void setAdmin(String admin) { this.admin = admin; } /** * @return the bridgeType */ - public String getBridgeType() - { + public String getBridgeType() { return bridgeType; } /** * @param bridgeType the bridgeType to set */ - public void setBridgeType(String bridgeType) - { + public void setBridgeType(String bridgeType) { this.bridgeType = bridgeType; } /** * @return the bridgeNumChannels */ - public String getBridgeNumChannels() - { + public String getBridgeNumChannels() { return bridgeNumChannels; } /** * @param bridgeNumChannels the bridgeNumChannels to set */ - public void setBridgeNumChannels(String bridgeNumChannels) - { + public void setBridgeNumChannels(String bridgeNumChannels) { this.bridgeNumChannels = bridgeNumChannels; } /** * @return the bridgeUniqueId */ - public String getBridgeUniqueId() - { + public String getBridgeUniqueId() { return bridgeUniqueId; } /** * @param bridgeUniqueId the bridgeUniqueId to set */ - public void setBridgeUniqueId(String bridgeUniqueId) - { + public void setBridgeUniqueId(String bridgeUniqueId) { this.bridgeUniqueId = bridgeUniqueId; } /** * @return the bridgeTechnology */ - public String getBridgeTechnology() - { + public String getBridgeTechnology() { return bridgeTechnology; } /** * @param bridgeTechnology the bridgeTechnology to set */ - public void setBridgeTechnology(String bridgeTechnology) - { + public void setBridgeTechnology(String bridgeTechnology) { this.bridgeTechnology = bridgeTechnology; } /** * @return the bridgeName */ - public String getBridgeName() - { + public String getBridgeName() { return bridgeName; } /** * @param bridgeName the bridgeName to set */ - public void setBridgeName(String bridgeName) - { + public void setBridgeName(String bridgeName) { this.bridgeName = bridgeName; } /** * @return the bridgeCreator */ - public String getBridgeCreator() - { + public String getBridgeCreator() { return bridgeCreator; } /** * @param bridgeCreator the bridgeCreator to set */ - public void setBridgeCreator(String bridgeCreator) - { + public void setBridgeCreator(String bridgeCreator) { this.bridgeCreator = bridgeCreator; } @@ -138,8 +122,7 @@ public void setBridgeCreator(String bridgeCreator) * * @param conference the id of the conference the participant left. */ - public final void setConference(String conference) - { + public final void setConference(String conference) { this.conference = conference; } @@ -148,38 +131,31 @@ public final void setConference(String conference) * * @return the id of the conference the participant left. */ - public final String getConference() - { + public final String getConference() { return conference; } - public String getBridgeVideoSourceMode() - { + public String getBridgeVideoSourceMode() { return bridgeVideoSourceMode; } - public void setBridgeVideoSourceMode(String bridgeVideoSourceMode) - { + public void setBridgeVideoSourceMode(String bridgeVideoSourceMode) { this.bridgeVideoSourceMode = bridgeVideoSourceMode; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractFaxEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractFaxEvent.java index df89296ce..0e33dff41 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractFaxEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractFaxEvent.java @@ -19,8 +19,7 @@ /** * An AbstractFaxEvent is a base class for fax related events */ -public class AbstractFaxEvent extends ManagerEvent -{ +public class AbstractFaxEvent extends ManagerEvent { /** * Serial version identifier. */ @@ -28,8 +27,7 @@ public class AbstractFaxEvent extends ManagerEvent private String channel; private Integer faxSession; - public AbstractFaxEvent(Object source) - { + public AbstractFaxEvent(Object source) { super(source); } @@ -37,8 +35,7 @@ public AbstractFaxEvent(Object source) /** * @return the channel */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -46,8 +43,7 @@ public String getChannel() /** * @param channel the channel to set */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -55,8 +51,7 @@ public void setChannel(String channel) /** * @return the faxSession */ - public Integer getFaxSession() - { + public Integer getFaxSession() { return faxSession; } @@ -64,8 +59,7 @@ public Integer getFaxSession() /** * @param faxSession the faxSession to set */ - public void setFaxSession(Integer faxSession) - { + public void setFaxSession(Integer faxSession) { this.faxSession = faxSession; } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractHoldEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractHoldEvent.java index 7b8b8c93a..8ab2e517c 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractHoldEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractHoldEvent.java @@ -16,8 +16,7 @@ * @version $Id$ * @since 1.0.0.10 */ -public class AbstractHoldEvent extends ManagerEvent -{ +public class AbstractHoldEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -36,18 +35,17 @@ public class AbstractHoldEvent extends ManagerEvent private String uniqueId; private Boolean status; - + private String linkedId; private String language; - + /** * Creates a new HoldEvent. * * @param source */ - public AbstractHoldEvent(Object source) - { + public AbstractHoldEvent(Object source) { super(source); } @@ -56,8 +54,7 @@ public AbstractHoldEvent(Object source) * * @return channel the name of the channel. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -66,8 +63,7 @@ public String getChannel() * * @param channel the name of the channel. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -76,8 +72,7 @@ public void setChannel(String channel) * * @return the unique id of the channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } @@ -86,8 +81,7 @@ public String getUniqueId() * * @param uniqueId the unique id of the channel. */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -95,11 +89,10 @@ public void setUniqueId(String uniqueId) * Returns whether this is a hold or unhold event. * * @return true if this a hold event, false if - * it's an unhold event. + * it's an unhold event. * @since 1.0.0 */ - public Boolean getStatus() - { + public Boolean getStatus() { return status; } @@ -107,11 +100,10 @@ public Boolean getStatus() * Returns whether this is a hold or unhold event. * * @param status true if this a hold event, false - * if it's an unhold event. + * if it's an unhold event. * @since 1.0.0 */ - public void setStatus(Boolean status) - { + public void setStatus(Boolean status) { this.status = status; } @@ -119,11 +111,10 @@ public void setStatus(Boolean status) * Returns whether this is a hold event. * * @return true if this a hold event, false if - * it's an unhold event. + * it's an unhold event. * @since 1.0.0 */ - public boolean isHold() - { + public boolean isHold() { return status != null && status; } @@ -131,41 +122,34 @@ public boolean isHold() * Returns whether this is an unhold event. * * @return true if this an unhold event, false if - * it's a hold event. + * it's a hold event. * @since 1.0.0 */ - public boolean isUnhold() - { + public boolean isUnhold() { return status != null && !status; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java index 9a5efd0b6..0a2bcbdce 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java @@ -21,12 +21,11 @@ * conference system) events. *

    * MeetMe events are implemented in apps/app_meetme.c - * + * * @author srt * @version $Id$ */ -public abstract class AbstractMeetMeEvent extends ManagerEvent -{ +public abstract class AbstractMeetMeEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private String channel; private String uniqueId; @@ -36,8 +35,7 @@ public abstract class AbstractMeetMeEvent extends ManagerEvent /** * @param source */ - protected AbstractMeetMeEvent(Object source) - { + protected AbstractMeetMeEvent(Object source) { super(source); } @@ -45,11 +43,10 @@ protected AbstractMeetMeEvent(Object source) * Returns the name of the channel. *

    * This property is available since Asterisk 1.4. - * + * * @return the name of the channel. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -57,11 +54,10 @@ public String getChannel() * Sets the name of the channel. *

    * This property is available since Asterisk 1.4. - * + * * @param channel the name of the channel. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -69,11 +65,10 @@ public void setChannel(String channel) * Returns the unique id of the channel. *

    * This property is available since Asterisk 1.4. - * + * * @return the unique id of the channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } @@ -81,31 +76,28 @@ public String getUniqueId() * Sets the unique id of the channel. *

    * This property is available since Asterisk 1.4. - * + * * @param uniqueId the unique id of the channel. */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } /** * Returns the conference number. - * + * * @return the conference number. */ - public String getMeetMe() - { + public String getMeetMe() { return meetMe; } /** * Sets the conference number. - * + * * @param meetMe the conference number. */ - public void setMeetMe(String meetMe) - { + public void setMeetMe(String meetMe) { this.meetMe = meetMe; } @@ -114,23 +106,21 @@ public void setMeetMe(String meetMe) *

    * This can be used for the "meetme (mute|unmute|kick)" commands. use * getUser() instead - * + * * @return the index of the user in the conference. */ @Deprecated - public Integer getUserNum() - { + public Integer getUserNum() { return getUser(); } /** * Sets the index of the user in the conference. - * + * * @param userNum the index of the user in the conference. */ @Deprecated - public void setUserNum(Integer userNum) - { + public void setUserNum(Integer userNum) { this.setUser(userNum); } @@ -138,21 +128,19 @@ public void setUserNum(Integer userNum) * Returns the index of the user in the conference. *

    * This can be used for the "meetme (mute|unmute|kick)" commands. - * + * * @return the index of the user in the conference. */ - public Integer getUser() - { + public Integer getUser() { return user; } /** * Sets the index of the user in the conference. - * + * * @param userNum the index of the user in the conference. */ - public void setUser(Integer userNum) - { + public void setUser(Integer userNum) { this.user = userNum; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractMixMonitorEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractMixMonitorEvent.java index 1faf62441..28dca2d3c 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractMixMonitorEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractMixMonitorEvent.java @@ -6,57 +6,55 @@ * @version $Id$ * @since 3.13.0 */ -public abstract class AbstractMixMonitorEvent extends ManagerEvent -{ - private static final long serialVersionUID = 1L; - private String accountCode; - private String channel; - private String language; - private String linkedId; - private String uniqueId; - - protected AbstractMixMonitorEvent(Object source) - { - super(source); - } - - public String getChannel() { - return channel; - } - - public void setChannel(String channel) { - this.channel = channel; - } - - public String getUniqueId() { - return uniqueId; - } - - public void setUniqueId(String uniqueId) { - this.uniqueId = uniqueId; - } - - public String getAccountCode() { - return accountCode; - } - - public void setAccountCode(String accountCode) { - this.accountCode = accountCode; - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - public String getLinkedId() { - return linkedId; - } - - public void setLinkedId(String linkedId) { - this.linkedId = linkedId; - } +public abstract class AbstractMixMonitorEvent extends ManagerEvent { + private static final long serialVersionUID = 1L; + private String accountCode; + private String channel; + private String language; + private String linkedId; + private String uniqueId; + + protected AbstractMixMonitorEvent(Object source) { + super(source); + } + + public String getChannel() { + return channel; + } + + public void setChannel(String channel) { + this.channel = channel; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } + + public String getAccountCode() { + return accountCode; + } + + public void setAccountCode(String accountCode) { + this.accountCode = accountCode; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getLinkedId() { + return linkedId; + } + + public void setLinkedId(String linkedId) { + this.linkedId = linkedId; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractMonitorEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractMonitorEvent.java index cb8cf6afc..0a85054ee 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractMonitorEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractMonitorEvent.java @@ -24,17 +24,15 @@ * @version $Id$ * @since 1.0.0 */ -public abstract class AbstractMonitorEvent extends ManagerEvent -{ - private static final long serialVersionUID = 1L; - private String channel; +public abstract class AbstractMonitorEvent extends ManagerEvent { + private static final long serialVersionUID = 1L; + private String channel; private String uniqueId; /** * @param source */ - protected AbstractMonitorEvent(Object source) - { + protected AbstractMonitorEvent(Object source) { super(source); } @@ -43,13 +41,11 @@ protected AbstractMonitorEvent(Object source) * * @return the name of the channel. */ - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -58,13 +54,11 @@ public void setChannel(String channel) * * @return the unique id of the channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java index 502e53eb6..2460aadc3 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java @@ -23,8 +23,7 @@ * @version $Id$ * @since 0.2 */ -public abstract class AbstractParkedCallEvent extends ManagerEvent -{ +public abstract class AbstractParkedCallEvent extends ManagerEvent { private static final long serialVersionUID = 0L; private String uniqueId; // Previously: Channel @@ -51,8 +50,7 @@ public abstract class AbstractParkedCallEvent extends ManagerEvent private Long parkingTimeout; private Long parkingDuration; - protected AbstractParkedCallEvent(Object source) - { + protected AbstractParkedCallEvent(Object source) { super(source); } @@ -61,8 +59,7 @@ protected AbstractParkedCallEvent(Object source) * getParkerDialString() instead */ @Deprecated - public String getFrom() - { + public String getFrom() { return getParkerDialString(); } @@ -70,8 +67,7 @@ public String getFrom() * Sets the name of the channel that parked the call. */ @Deprecated - public void setFrom(String from) - { + public void setFrom(String from) { this.setParkerDialString(from); } @@ -83,8 +79,7 @@ public void setFrom(String from) * @return the parking lot. * @since 1.0.0 */ - public String getParkingLot() - { + public String getParkingLot() { return parkingLot; } @@ -93,8 +88,7 @@ public String getParkingLot() * * @param parkingLot the parking lot. */ - public void setParkingLot(String parkingLot) - { + public void setParkingLot(String parkingLot) { this.parkingLot = parkingLot; } @@ -110,222 +104,180 @@ public void setParkingLot(String parkingLot) * * @return the unique id of the parked channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @Deprecated - public void setChannel(String channel) - { + public void setChannel(String channel) { this.setParkeeChannel(channel); } /** * use getParkeeChannel() instead - * + * * @return */ @Deprecated - public String getChannel() - { + public String getChannel() { return this.getParkeeChannel(); } - public String getParkeeChannel() - { + public String getParkeeChannel() { return parkeeChannel; } - public void setParkeeChannel(String parkeeChannel) - { + public void setParkeeChannel(String parkeeChannel) { this.parkeeChannel = parkeeChannel; } - public Integer getParkeeChannelState() - { + public Integer getParkeeChannelState() { return parkeeChannelState; } - public void setParkeeChannelState(Integer parkeeChannelState) - { + public void setParkeeChannelState(Integer parkeeChannelState) { this.parkeeChannelState = parkeeChannelState; } - public String getParkeeChannelStateDesc() - { + public String getParkeeChannelStateDesc() { return parkeeChannelStateDesc; } - public void setParkeeChannelStateDesc(String parkeeChannelStateDesc) - { + public void setParkeeChannelStateDesc(String parkeeChannelStateDesc) { this.parkeeChannelStateDesc = parkeeChannelStateDesc; } - public String getParkeeCallerIDNum() - { + public String getParkeeCallerIDNum() { return parkeeCallerIDNum; } - public void setParkeeCallerIDNum(String parkeeCallerIDNum) - { + public void setParkeeCallerIDNum(String parkeeCallerIDNum) { this.parkeeCallerIDNum = parkeeCallerIDNum; } - public String getParkeeCallerIDName() - { + public String getParkeeCallerIDName() { return parkeeCallerIDName; } - public void setParkeeCallerIDName(String parkeeCallerIDName) - { + public void setParkeeCallerIDName(String parkeeCallerIDName) { this.parkeeCallerIDName = parkeeCallerIDName; } - public String getParkeeConnectedLineNum() - { + public String getParkeeConnectedLineNum() { return parkeeConnectedLineNum; } - public void setParkeeConnectedLineNum(String parkeeConnectedLineNum) - { + public void setParkeeConnectedLineNum(String parkeeConnectedLineNum) { this.parkeeConnectedLineNum = parkeeConnectedLineNum; } - public String getParkeeConnectedLineName() - { + public String getParkeeConnectedLineName() { return parkeeConnectedLineName; } - public void setParkeeConnectedLineName(String parkeeConnectedLineName) - { + public void setParkeeConnectedLineName(String parkeeConnectedLineName) { this.parkeeConnectedLineName = parkeeConnectedLineName; } - public String getParkeeLanguage() - { + public String getParkeeLanguage() { return parkeeLanguage; } - public void setParkeeLanguage(String parkeeLanguage) - { + public void setParkeeLanguage(String parkeeLanguage) { this.parkeeLanguage = parkeeLanguage; } - public String getParkeeAccountCode() - { + public String getParkeeAccountCode() { return parkeeAccountCode; } - public void setParkeeAccountCode(String parkeeAccountCode) - { + public void setParkeeAccountCode(String parkeeAccountCode) { this.parkeeAccountCode = parkeeAccountCode; } - public String getParkeeContext() - { + public String getParkeeContext() { return parkeeContext; } - public void setParkeeContext(String parkeeContext) - { + public void setParkeeContext(String parkeeContext) { this.parkeeContext = parkeeContext; } - public String getParkeeExten() - { + public String getParkeeExten() { return parkeeExten; } - public void setParkeeExten(String parkeeExten) - { + public void setParkeeExten(String parkeeExten) { this.parkeeExten = parkeeExten; } - public Integer getParkeePriority() - { + public Integer getParkeePriority() { return parkeePriority; } - public void setParkeePriority(Integer parkeePriority) - { + public void setParkeePriority(Integer parkeePriority) { this.parkeePriority = parkeePriority; } - public String getParkeeUniqueid() - { + public String getParkeeUniqueid() { return parkeeUniqueid; } - public void setParkeeUniqueid(String parkeeUniqueid) - { + public void setParkeeUniqueid(String parkeeUniqueid) { this.parkeeUniqueid = parkeeUniqueid; } - public String getParkerDialString() - { + public String getParkerDialString() { return parkerDialString; } - public void setParkerDialString(String parkerDialString) - { + public void setParkerDialString(String parkerDialString) { this.parkerDialString = parkerDialString; } - public String getParkinglot() - { + public String getParkinglot() { return parkingLot; } - public void setParkinglot(String parkinglot) - { + public void setParkinglot(String parkinglot) { this.parkingLot = parkinglot; } - public String getParkingSpace() - { + public String getParkingSpace() { return parkingSpace; } - public void setParkingSpace(String parkingSpace) - { + public void setParkingSpace(String parkingSpace) { this.parkingSpace = parkingSpace; } - public Long getParkingTimeout() - { + public Long getParkingTimeout() { return parkingTimeout; } - public void setParkingTimeout(Long parkingTimeout) - { + public void setParkingTimeout(Long parkingTimeout) { this.parkingTimeout = parkingTimeout; } - public Long getParkingDuration() - { + public Long getParkingDuration() { return parkingDuration; } - public void setParkingDuration(Long parkingDuration) - { + public void setParkingDuration(Long parkingDuration) { this.parkingDuration = parkingDuration; } @Deprecated - public String getCallerId() - { + public String getCallerId() { return getParkeeCallerIDNum(); } @Deprecated - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { setParkeeCallerIDNum(callerId); } } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractQueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractQueueMemberEvent.java index 3ad13f6c9..b03360fab 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractQueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractQueueMemberEvent.java @@ -18,13 +18,12 @@ /** * Abstract base class for several queue member related events. - * + * * @author srt * @version $Id$ * @since 0.2 */ -public abstract class AbstractQueueMemberEvent extends ManagerEvent -{ +public abstract class AbstractQueueMemberEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -38,49 +37,44 @@ public abstract class AbstractQueueMemberEvent extends ManagerEvent /** * @param source */ - protected AbstractQueueMemberEvent(Object source) - { + protected AbstractQueueMemberEvent(Object source) { super(source); } /** * Returns the name of the queue. - * + * * @return the name of the queue. */ - public String getQueue() - { + public String getQueue() { return queue; } /** * Sets the name of the queue. - * + * * @param queue the name of the queue. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } /** * Returns the name of the member's interface.

    * E.g. the channel name or agent group. - * + * * @return the name of the member's interface. */ - final public String getInterface() - { + final public String getInterface() { return _interface; } /** * Sets the name of the member's interface. - * + * * @param member the name of the member's interface. */ - final public void setInterface(String _interface) - { + final public void setInterface(String _interface) { this._interface = _interface; } @@ -88,28 +82,23 @@ final public void setInterface(String _interface) * Returns the name of the member's interface.

    * E.g. the channel name or agent group. * - * @deprecated since Asterisk 12 - * * @return the name of the member's interface. + * @deprecated since Asterisk 12 */ @Deprecated - final public String getLocation() - { + final public String getLocation() { return _interface; } /** * Sets the name of the member's interface. * - * @deprecated since Asterisk 12 - * * @param member the name of the member's interface. + * @deprecated since Asterisk 12 */ @Deprecated - final public void setLocation(String _interface) - { - if ((_interface != null) && (!"null".equals(_interface))) - { // Location is not in use since asterisk 12 + final public void setLocation(String _interface) { + if ((_interface != null) && (!"null".equals(_interface))) { // Location is not in use since asterisk 12 this._interface = _interface; } } @@ -118,12 +107,11 @@ final public void setLocation(String _interface) * Retruns the name of the queue member. *

    * Available since Asterisk 1.4 - * + * * @return the name of the queue member. * @since 0.3 */ - public String getMemberName() - { + public String getMemberName() { return memberName; } @@ -131,32 +119,27 @@ public String getMemberName() * Sets the name of the queue member. *

    * Available since Asterisk 1.4 - * + * * @param memberName the name of the queue member. * @since 0.3 */ - public void setMemberName(String memberName) - { + public void setMemberName(String memberName) { this.memberName = memberName; } - public String getPausedReason() - { + public String getPausedReason() { return pausedReason; } - public void setPausedReason(String pausedReason) - { + public void setPausedReason(String pausedReason) { this.pausedReason = pausedReason; } - public String getInCall() - { + public String getInCall() { return inCall; } - public void setInCall(String inCall) - { + public void setInCall(String inCall) { this.inCall = inCall; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java index 482e209f5..7e137214d 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractRtcpEvent.java @@ -27,16 +27,14 @@ * @version $Id$ * @since 1.0.0 */ -public abstract class AbstractRtcpEvent extends ManagerEvent -{ +public abstract class AbstractRtcpEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private Long fractionLost; private Double dlSr; private Double iaJitter; - public AbstractRtcpEvent(Object source) - { + public AbstractRtcpEvent(Object source) { super(source); } @@ -46,13 +44,11 @@ public AbstractRtcpEvent(Object source) * * @return the short term loss ratio. */ - public Long getFractionLost() - { + public Long getFractionLost() { return fractionLost; } - public void setFractionLost(Long fractionLost) - { + public void setFractionLost(Long fractionLost) { this.fractionLost = fractionLost; } @@ -61,13 +57,11 @@ public void setFractionLost(Long fractionLost) * * @return the interarrival jitter. */ - public Double getIaJitter() - { + public Double getIaJitter() { return iaJitter; } - public void setIaJitter(Double iaJitter) - { + public void setIaJitter(Double iaJitter) { this.iaJitter = iaJitter; } @@ -76,94 +70,72 @@ public void setIaJitter(Double iaJitter) * * @return the delay since the last SR in seconds. */ - public Double getDlSr() - { + public Double getDlSr() { return dlSr; } - public void setDlSr(String dlSrString) - { + public void setDlSr(String dlSrString) { this.dlSr = secStringToDouble(dlSrString); } - protected Long secStringToLong(String s) - { - if (s == null || s.length() == 0) - { + protected Long secStringToLong(String s) { + if (s == null || s.length() == 0) { return null; } - + //things like RTT can be float/double in the event message in newer asterisk versions - if(s.contains(".")) - { + if (s.contains(".")) { return secStringToDouble(s).longValue(); } - if (s.endsWith("(sec)")) - { + if (s.endsWith("(sec)")) { return Long.parseLong(s.substring(0, s.length() - "(sec)".length())); } return Long.parseLong(s); } - protected Double secStringToDouble(String s) - { - if (s == null || s.length() == 0) - { + protected Double secStringToDouble(String s) { + if (s == null || s.length() == 0) { return null; } - if (s.endsWith("(sec)")) - { + if (s.endsWith("(sec)")) { return Double.parseDouble(s.substring(0, s.length() - "(sec)".length())); } return Double.parseDouble(s); } - protected InetAddress stringToAddress(String addressWithPort) - { + protected InetAddress stringToAddress(String addressWithPort) { final String address; - if (addressWithPort == null || addressWithPort.length() == 0) - { + if (addressWithPort == null || addressWithPort.length() == 0) { return null; } - if (addressWithPort.lastIndexOf(':') > 0) - { + if (addressWithPort.lastIndexOf(':') > 0) { address = addressWithPort.substring(0, addressWithPort.lastIndexOf(':')); - } - else - { + } else { address = addressWithPort; } - try - { + try { return InetAddress.getByName(address); - } - catch (UnknownHostException e) - { + } catch (UnknownHostException e) { // should not happen as we supply a textual IP address throw new IllegalArgumentException("Unable to convert " + addressWithPort + " to InetAddress", e); } } - protected Integer stringToPort(String addressWithPort) - { + protected Integer stringToPort(String addressWithPort) { final String port; - if (addressWithPort == null || addressWithPort.length() == 0) - { + if (addressWithPort == null || addressWithPort.length() == 0) { return null; } - if (addressWithPort.lastIndexOf(':') > 0) - { + if (addressWithPort.lastIndexOf(':') > 0) { port = addressWithPort.substring(addressWithPort.lastIndexOf(':') + 1); - } - else - { + } else { return null; } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractRtpStatEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractRtpStatEvent.java index 8987c3324..a98746143 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractRtpStatEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractRtpStatEvent.java @@ -23,16 +23,14 @@ * @version $Id$ * @since 1.0.0 */ -public abstract class AbstractRtpStatEvent extends ManagerEvent -{ +public abstract class AbstractRtpStatEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private Long ssrc; private Long lostPackets; private Double jitter; - public AbstractRtpStatEvent(Object source) - { + public AbstractRtpStatEvent(Object source) { super(source); } @@ -41,13 +39,11 @@ public AbstractRtpStatEvent(Object source) * * @return the synchronization source identifier. */ - public Long getSsrc() - { + public Long getSsrc() { return ssrc; } - public void setSsrc(Long ssrc) - { + public void setSsrc(Long ssrc) { this.ssrc = ssrc; } @@ -56,23 +52,19 @@ public void setSsrc(Long ssrc) * * @return the number of lost packets. */ - public Long getLostPackets() - { + public Long getLostPackets() { return lostPackets; } - public void setLostPackets(Long lostPackets) - { + public void setLostPackets(Long lostPackets) { this.lostPackets = lostPackets; } - public Double getJitter() - { + public Double getJitter() { return jitter; } - public void setJitter(Double jitter) - { + public void setJitter(Double jitter) { this.jitter = jitter; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractUnParkedEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractUnParkedEvent.java index d62a092b2..61cb00f85 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractUnParkedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractUnParkedEvent.java @@ -19,8 +19,7 @@ /** * Enro 2015-03: Asterisk 13 Support */ -public class AbstractUnParkedEvent extends AbstractParkedCallEvent -{ +public class AbstractUnParkedEvent extends AbstractParkedCallEvent { /** * Serializable version identifier */ @@ -42,128 +41,103 @@ public class AbstractUnParkedEvent extends AbstractParkedCallEvent /** * @param source */ - public AbstractUnParkedEvent(Object source) - { + public AbstractUnParkedEvent(Object source) { super(source); } - public String getParkerChannel() - { + public String getParkerChannel() { return parkerChannel; } - public void setParkerChannel(String parkerChannel) - { + public void setParkerChannel(String parkerChannel) { this.parkerChannel = parkerChannel; } - public Integer getParkerChannelState() - { + public Integer getParkerChannelState() { return parkerChannelState; } - public void setParkerChannelState(Integer parkerChannelState) - { + public void setParkerChannelState(Integer parkerChannelState) { this.parkerChannelState = parkerChannelState; } - public String getParkerChannelStateDesc() - { + public String getParkerChannelStateDesc() { return parkerChannelStateDesc; } - public void setParkerChannelStateDesc(String parkerChannelStateDesc) - { + public void setParkerChannelStateDesc(String parkerChannelStateDesc) { this.parkerChannelStateDesc = parkerChannelStateDesc; } - public String getParkerCallerIDNum() - { + public String getParkerCallerIDNum() { return parkerCallerIDNum; } - public void setParkerCallerIDNum(String parkerCallerIDNum) - { + public void setParkerCallerIDNum(String parkerCallerIDNum) { this.parkerCallerIDNum = parkerCallerIDNum; } - public String getParkerCallerIDName() - { + public String getParkerCallerIDName() { return parkerCallerIDName; } - public void setParkerCallerIDName(String parkerCallerIDName) - { + public void setParkerCallerIDName(String parkerCallerIDName) { this.parkerCallerIDName = parkerCallerIDName; } - public String getParkerConnectedLineNum() - { + public String getParkerConnectedLineNum() { return parkerConnectedLineNum; } - public void setParkerConnectedLineNum(String parkerConnectedLineNum) - { + public void setParkerConnectedLineNum(String parkerConnectedLineNum) { this.parkerConnectedLineNum = parkerConnectedLineNum; } - public String getParkerConnectedLineName() - { + public String getParkerConnectedLineName() { return parkerConnectedLineName; } - public void setParkerConnectedLineName(String parkerConnectedLineName) - { + public void setParkerConnectedLineName(String parkerConnectedLineName) { this.parkerConnectedLineName = parkerConnectedLineName; } - public String getParkerAccountCode() - { + public String getParkerAccountCode() { return parkerAccountCode; } - public void setParkerAccountCode(String parkerAccountCode) - { + public void setParkerAccountCode(String parkerAccountCode) { this.parkerAccountCode = parkerAccountCode; } - public String getParkerContext() - { + public String getParkerContext() { return parkerContext; } - public void setParkerContext(String parkerContext) - { + public void setParkerContext(String parkerContext) { this.parkerContext = parkerContext; } - public String getParkerExten() - { + public String getParkerExten() { return parkerExten; } - public void setParkerExten(String parkerExten) - { + public void setParkerExten(String parkerExten) { this.parkerExten = parkerExten; } - public String getParkerPriority() - { + public String getParkerPriority() { return parkerPriority; } - public void setParkerPriority(String parkerPriority) - { + public void setParkerPriority(String parkerPriority) { this.parkerPriority = parkerPriority; } - public String getParkerUniqueid() - { + public String getParkerUniqueid() { return parkerUniqueid; } - public void setParkerUniqueid(String parkerUniqueid) - { + public void setParkerUniqueid(String parkerUniqueid) { this.parkerUniqueid = parkerUniqueid; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentCallbackLoginEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentCallbackLoginEvent.java index 08a27f6ec..578a9e047 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentCallbackLoginEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentCallbackLoginEvent.java @@ -20,13 +20,12 @@ * An AgentCallbackLoginEvent is triggered when an agent is successfully logged in using * AgentCallbackLogin.

    * It is implemented in channels/chan_agent.c - * - * @see org.asteriskjava.manager.event.AgentCallbackLogoffEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.AgentCallbackLogoffEvent */ -public class AgentCallbackLoginEvent extends ManagerEvent -{ +public class AgentCallbackLoginEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -38,44 +37,37 @@ public class AgentCallbackLoginEvent extends ManagerEvent /** * @param source */ - public AgentCallbackLoginEvent(Object source) - { + public AgentCallbackLoginEvent(Object source) { super(source); } /** * Returns the name of the agent that logged in. */ - public String getAgent() - { + public String getAgent() { return agent; } /** * Sets the name of the agent that logged in. */ - public void setAgent(String agent) - { + public void setAgent(String agent) { this.agent = agent; } - public String getLoginChan() - { + public String getLoginChan() { return loginChan; } - public void setLoginChan(String loginChan) - { + public void setLoginChan(String loginChan) { this.loginChan = loginChan; } - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentCallbackLogoffEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentCallbackLogoffEvent.java index e95189a83..ab67d0835 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentCallbackLogoffEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentCallbackLogoffEvent.java @@ -21,13 +21,12 @@ * AgentCallbackLogin is logged of. *

    * It is implemented in channels/chan_agent.c - * - * @see org.asteriskjava.manager.event.AgentCallbackLoginEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.AgentCallbackLoginEvent */ -public class AgentCallbackLogoffEvent extends ManagerEvent -{ +public class AgentCallbackLogoffEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -41,44 +40,37 @@ public class AgentCallbackLogoffEvent extends ManagerEvent /** * @param source */ - public AgentCallbackLogoffEvent(Object source) - { + public AgentCallbackLogoffEvent(Object source) { super(source); } /** * Returns the name of the agent that logged off. */ - public String getAgent() - { + public String getAgent() { return agent; } /** * Sets the name of the agent that logged off. */ - public void setAgent(String agent) - { + public void setAgent(String agent) { this.agent = agent; } - public String getLoginChan() - { + public String getLoginChan() { return loginChan; } - public void setLoginChan(String loginChan) - { + public void setLoginChan(String loginChan) { this.loginChan = loginChan; } - public Long getLoginTime() - { + public Long getLoginTime() { return loginTime; } - public void setLoginTime(Long loginTime) - { + public void setLoginTime(Long loginTime) { this.loginTime = loginTime; } @@ -87,26 +79,22 @@ public void setLoginTime(Long loginTime) * logged off due to not answering the phone in time. Autologoff is configured by setting * autologoff to the appropriate number of seconds in agents.conf. */ - public String getReason() - { + public String getReason() { return reason; } /** * Sets the reason for the logoff. */ - public void setReason(String reason) - { + public void setReason(String reason) { this.reason = reason; } - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentCalledEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentCalledEvent.java index 8b9fde797..29b863d29 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentCalledEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentCalledEvent.java @@ -27,13 +27,12 @@ * @author srt * @version $Id$ */ -public class AgentCalledEvent extends ManagerEvent -{ +public class AgentCalledEvent extends ManagerEvent { /** * Serializable version identifier. */ private static final long serialVersionUID = 2L; - + private String queue; private String agentCalled; private String channelCalling; @@ -56,21 +55,20 @@ public class AgentCalledEvent extends ManagerEvent private String destChannelState; private String iface; private String channel; - + private String destAccountCode; private String language; private String destLanguage; private String linkedId; private String destLinkedId; - + private String accountcode; - + /** * @param source */ - public AgentCalledEvent(Object source) - { + public AgentCalledEvent(Object source) { super(source); } @@ -82,13 +80,11 @@ public AgentCalledEvent(Object source) * @return the name of the queue. * @since 1.0.0 */ - public String getQueue() - { + public String getQueue() { return queue; } - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } @@ -98,8 +94,7 @@ public void setQueue(String queue) * @return the member interface of the agent that has been called. * @see QueueMemberEvent#getLocation() */ - public String getAgentCalled() - { + public String getAgentCalled() { return agentCalled; } @@ -107,10 +102,9 @@ public String getAgentCalled() * Sets the member interface of the agent that has been called. * * @param agentCalled the member interface of the agent that has been - * called. + * called. */ - public void setAgentCalled(String agentCalled) - { + public void setAgentCalled(String agentCalled) { this.agentCalled = agentCalled; } @@ -124,14 +118,12 @@ public void setAgentCalled(String agentCalled) * @deprecated use {@lkink #getMemberName()} instead (asterisk 13) */ @Deprecated - public String getAgentName() - { + public String getAgentName() { return memberName; } @Deprecated - public void setAgentName(String agentName) - { + public void setAgentName(String agentName) { this.memberName = agentName; } @@ -141,8 +133,7 @@ public void setAgentName(String agentName) * * @return the name of the caller's channel. */ - public String getChannelCalling() - { + public String getChannelCalling() { return channelCalling; } @@ -151,8 +142,7 @@ public String getChannelCalling() * * @param channelCalling the name of the caller's channel. */ - public void setChannelCalling(String channelCalling) - { + public void setChannelCalling(String channelCalling) { this.channelCalling = channelCalling; } @@ -164,13 +154,11 @@ public void setChannelCalling(String channelCalling) * @return the name of the channel calling the agent. * @since 1.0.0 */ - public String getDestinationChannel() - { + public String getDestinationChannel() { return destinationChannel; } - public void setDestinationChannel(String destinationChannel) - { + public void setDestinationChannel(String destinationChannel) { this.destinationChannel = destinationChannel; } @@ -181,8 +169,7 @@ public void setDestinationChannel(String destinationChannel) * @deprecated as of 1.0.0, use {@link #getCallerIdNum()} instead. */ @Deprecated - public String getCallerId() - { + public String getCallerId() { return callerIdNum; } @@ -191,18 +178,15 @@ public String getCallerId() * * @param callerId the Caller ID number of the caller's channel. */ - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { this.callerIdNum = callerId; } - public String getExtension() - { + public String getExtension() { return exten; } - public void setExtension(String extension) - { + public void setExtension(String extension) { this.exten = extension; } @@ -215,13 +199,11 @@ public void setExtension(String extension) * @return the unique id of the caller's channel. * @since 1.0.0 */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -231,13 +213,11 @@ public void setUniqueId(String uniqueId) * Available since Asterisk 13 replace agentName *

    */ - public String getMemberName() - { + public String getMemberName() { return memberName; } - public void setMemberName(String memberName) - { + public void setMemberName(String memberName) { this.memberName = memberName; } @@ -250,8 +230,7 @@ public void setMemberName(String memberName) * @return the channel variables. * @since 1.0.0 */ - public Map getVariables() - { + public Map getVariables() { return variables; } @@ -263,276 +242,237 @@ public Map getVariables() * @param variables the channel variables. * @since 1.0.0 */ - public void setVariables(Map variables) - { + public void setVariables(Map variables) { this.variables = variables; } /** * @return the destExten */ - public String getDestExten() - { + public String getDestExten() { return destExten; } /** * @param destExten the destExten to set */ - public void setDestExten(String destExten) - { + public void setDestExten(String destExten) { this.destExten = destExten; } /** * @return the destChannelStateDesc */ - public String getDestChannelStateDesc() - { + public String getDestChannelStateDesc() { return destChannelStateDesc; } /** * @param destChannelStateDesc the destChannelStateDesc to set */ - public void setDestChannelStateDesc(String destChannelStateDesc) - { + public void setDestChannelStateDesc(String destChannelStateDesc) { this.destChannelStateDesc = destChannelStateDesc; } /** * @return the destUniqueId */ - public String getDestUniqueId() - { + public String getDestUniqueId() { return destUniqueId; } /** * @param destUniqueId the destUniqueId to set */ - public void setDestUniqueId(String destUniqueId) - { + public void setDestUniqueId(String destUniqueId) { this.destUniqueId = destUniqueId; } /** * @return the destConnectedLineNum */ - public String getDestConnectedLineNum() - { + public String getDestConnectedLineNum() { return destConnectedLineNum; } /** * @param destConnectedLineNum the destConnectedLineNum to set */ - public void setDestConnectedLineNum(String destConnectedLineNum) - { + public void setDestConnectedLineNum(String destConnectedLineNum) { this.destConnectedLineNum = destConnectedLineNum; } /** * @return the destCallerIdName */ - public String getDestCallerIdName() - { + public String getDestCallerIdName() { return destCallerIdName; } /** * @param destCallerIdName the destCallerIdName to set */ - public void setDestCallerIdName(String destCallerIdName) - { + public void setDestCallerIdName(String destCallerIdName) { this.destCallerIdName = destCallerIdName; } /** * @return the destCallerIdNum */ - public String getDestCallerIdNum() - { + public String getDestCallerIdNum() { return destCallerIdNum; } /** * @param destCallerIdNum the destCallerIdNum to set */ - public void setDestCallerIdNum(String destCallerIdNum) - { + public void setDestCallerIdNum(String destCallerIdNum) { this.destCallerIdNum = destCallerIdNum; } /** * @return the destContext */ - public String getDestContext() - { + public String getDestContext() { return destContext; } /** * @param destContext the destContext to set */ - public void setDestContext(String destContext) - { + public void setDestContext(String destContext) { this.destContext = destContext; } /** * @return the destPriority */ - public String getDestPriority() - { + public String getDestPriority() { return destPriority; } /** * @param destPriority the destPriority to set */ - public void setDestPriority(String destPriority) - { + public void setDestPriority(String destPriority) { this.destPriority = destPriority; } /** * @return the destChannel */ - public String getDestChannel() - { + public String getDestChannel() { return destChannel; } /** * @param destChannel the destChannel to set */ - public void setDestChannel(String destChannel) - { + public void setDestChannel(String destChannel) { this.destChannel = destChannel; } /** * @return the destChannelState */ - public String getDestChannelState() - { + public String getDestChannelState() { return destChannelState; } /** * @param destChannelState the destChannelState to set */ - public void setDestChannelState(String destChannelState) - { + public void setDestChannelState(String destChannelState) { this.destChannelState = destChannelState; } /** * @return the iface */ - public String getInterface() - { + public String getInterface() { return iface; } /** * @param iface the iface to set */ - public void setInterface(String iface) - { + public void setInterface(String iface) { this.iface = iface; } /** * @return the channel */ - public String getChannel() - { + public String getChannel() { return channel; } /** * @param channel the channel to set */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * @return the destConnectedLineName */ - public String getDestConnectedLineName() - { + public String getDestConnectedLineName() { return destConnectedLineName; } /** * @param destConnectedLineName the destConnectedLineName to set */ - public void setDestConnectedLineName(String destConnectedLineName) - { + public void setDestConnectedLineName(String destConnectedLineName) { this.destConnectedLineName = destConnectedLineName; } - public String getDestAccountCode() - { + public String getDestAccountCode() { return destAccountCode; } - public void setDestAccountCode(String destAccountCode) - { + public void setDestAccountCode(String destAccountCode) { this.destAccountCode = destAccountCode; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getDestLanguage() - { + public String getDestLanguage() { return destLanguage; } - public void setDestLanguage(String destLanguage) - { + public void setDestLanguage(String destLanguage) { this.destLanguage = destLanguage; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getDestLinkedId() - { + public String getDestLinkedId() { return destLinkedId; } - public void setDestLinkedId(String destLinkedId) - { + public void setDestLinkedId(String destLinkedId) { this.destLinkedId = destLinkedId; } - public String getAccountcode() - { - return accountcode; - } + public String getAccountcode() { + return accountcode; + } - public void setAccountcode(String accountcode) - { - this.accountcode = accountcode; - } + public void setAccountcode(String accountcode) { + this.accountcode = accountcode; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentCompleteEvent.java index 22b0c925e..77521f8e6 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentCompleteEvent.java @@ -23,13 +23,12 @@ * It is implemented in apps/app_queue.c. *

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class AgentCompleteEvent extends AbstractAgentEvent -{ +public class AgentCompleteEvent extends AbstractAgentEvent { /** * Serial version identifier. */ @@ -51,7 +50,7 @@ public class AgentCompleteEvent extends AbstractAgentEvent private String destChannel; private String destChannelState; private String iface; - + private String destAccountCode; private String language; private String destLanguage; @@ -59,323 +58,280 @@ public class AgentCompleteEvent extends AbstractAgentEvent private String destLinkedId; private String accountCode; - public AgentCompleteEvent(Object source) - { + public AgentCompleteEvent(Object source) { super(source); } /** * Returns the amount of time the caller was on hold. - * + * * @return the amount of time the caller was on hold in seconds. */ - public Long getHoldTime() - { + public Long getHoldTime() { return holdTime; } /** * Sets the amount of time the caller was on hold. - * + * * @param holdtime the amount of time the caller was on hold in seconds. */ - public void setHoldTime(Long holdtime) - { + public void setHoldTime(Long holdtime) { this.holdTime = holdtime; } /** * Returns the amount of time the caller talked to the agent. - * + * * @return the amount of time the caller talked to the agent in seconds. */ - public Long getTalkTime() - { + public Long getTalkTime() { return talkTime; } /** * Sets the amount of time the caller talked to the agent. - * + * * @param talkTime the amount of time the caller talked to the agent in - * seconds. + * seconds. */ - public void setTalkTime(Long talkTime) - { + public void setTalkTime(Long talkTime) { this.talkTime = talkTime; } /** * Returns if the agent or the caller terminated the call. - * + * * @return "agent" if the agent terminated the call, "caller" if the caller - * terminated the call. + * terminated the call. */ - public String getReason() - { + public String getReason() { return reason; } /** * Sets if the agent or the caller terminated the call. - * + * * @param reason "agent" if the agent terminated the call, "caller" if the - * caller terminated the call. + * caller terminated the call. */ - public void setReason(String reason) - { + public void setReason(String reason) { this.reason = reason; } /** * @return the destExten */ - public String getDestExten() - { + public String getDestExten() { return destExten; } /** * @param destExten the destExten to set */ - public void setDestExten(String destExten) - { + public void setDestExten(String destExten) { this.destExten = destExten; } /** * @return the destChannelStateDesc */ - public String getDestChannelStateDesc() - { + public String getDestChannelStateDesc() { return destChannelStateDesc; } /** * @param destChannelStateDesc the destChannelStateDesc to set */ - public void setDestChannelStateDesc(String destChannelStateDesc) - { + public void setDestChannelStateDesc(String destChannelStateDesc) { this.destChannelStateDesc = destChannelStateDesc; } /** * @return the destUniqueId */ - public String getDestUniqueId() - { + public String getDestUniqueId() { return destUniqueId; } /** * @param destUniqueId the destUniqueId to set */ - public void setDestUniqueId(String destUniqueId) - { + public void setDestUniqueId(String destUniqueId) { this.destUniqueId = destUniqueId; } /** * @return the destConnectedLineNum */ - public String getDestConnectedLineNum() - { + public String getDestConnectedLineNum() { return destConnectedLineNum; } /** * @param destConnectedLineNum the destConnectedLineNum to set */ - public void setDestConnectedLineNum(String destConnectedLineNum) - { + public void setDestConnectedLineNum(String destConnectedLineNum) { this.destConnectedLineNum = destConnectedLineNum; } /** * @return the destConnectedLineName */ - public String getDestConnectedLineName() - { + public String getDestConnectedLineName() { return destConnectedLineName; } /** * @param destConnectedLineName the destConnectedLineName to set */ - public void setDestConnectedLineName(String destConnectedLineName) - { + public void setDestConnectedLineName(String destConnectedLineName) { this.destConnectedLineName = destConnectedLineName; } /** * @return the destCallerIdName */ - public String getDestCallerIdName() - { + public String getDestCallerIdName() { return destCallerIdName; } /** * @param destCallerIdName the destCallerIdName to set */ - public void setDestCallerIdName(String destCallerIdName) - { + public void setDestCallerIdName(String destCallerIdName) { this.destCallerIdName = destCallerIdName; } /** * @return the destCallerIdNum */ - public String getDestCallerIdNum() - { + public String getDestCallerIdNum() { return destCallerIdNum; } /** * @param destCallerIdNum the destCallerIdNum to set */ - public void setDestCallerIdNum(String destCallerIdNum) - { + public void setDestCallerIdNum(String destCallerIdNum) { this.destCallerIdNum = destCallerIdNum; } /** * @return the destContext */ - public String getDestContext() - { + public String getDestContext() { return destContext; } /** * @param destContext the destContext to set */ - public void setDestContext(String destContext) - { + public void setDestContext(String destContext) { this.destContext = destContext; } /** * @return the destPriority */ - public String getDestPriority() - { + public String getDestPriority() { return destPriority; } /** * @param destPriority the destPriority to set */ - public void setDestPriority(String destPriority) - { + public void setDestPriority(String destPriority) { this.destPriority = destPriority; } /** * @return the destChannel */ - public String getDestChannel() - { + public String getDestChannel() { return destChannel; } /** * @param destChannel the destChannel to set */ - public void setDestChannel(String destChannel) - { + public void setDestChannel(String destChannel) { this.destChannel = destChannel; } /** * @return the destChannelState */ - public String getDestChannelState() - { + public String getDestChannelState() { return destChannelState; } /** * @param destChannelState the destChannelState to set */ - public void setDestChannelState(String destChannelState) - { + public void setDestChannelState(String destChannelState) { this.destChannelState = destChannelState; } /** * @return the iface */ - public String getInterface() - { + public String getInterface() { return iface; } /** * @param iface the iface to set */ - public void setInterface(String iface) - { + public void setInterface(String iface) { this.iface = iface; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getDestAccountCode() - { + public String getDestAccountCode() { return destAccountCode; } - public void setDestAccountCode(String destAccountCode) - { + public void setDestAccountCode(String destAccountCode) { this.destAccountCode = destAccountCode; } - public String getDestLanguage() - { + public String getDestLanguage() { return destLanguage; } - public void setDestLanguage(String destLanguage) - { + public void setDestLanguage(String destLanguage) { this.destLanguage = destLanguage; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getDestLinkedId() - { + public String getDestLinkedId() { return destLinkedId; } - public void setDestLinkedId(String destLinkedId) - { + public void setDestLinkedId(String destLinkedId) { this.destLinkedId = destLinkedId; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentConnectEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentConnectEvent.java index 7cb712b16..1611041b6 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentConnectEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentConnectEvent.java @@ -22,13 +22,12 @@ * It is implemented in apps/app_queue.c. *

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class AgentConnectEvent extends AbstractAgentEvent -{ +public class AgentConnectEvent extends AbstractAgentEvent { /** * Serial version identifier. */ @@ -55,31 +54,28 @@ public class AgentConnectEvent extends AbstractAgentEvent private String destLinkedId; private String destLanguage; private String language; - + private String accountcode; - public AgentConnectEvent(Object source) - { + public AgentConnectEvent(Object source) { super(source); } /** * Returns the amount of time the caller was on hold. - * + * * @return the amount of time the caller was on hold in seconds. */ - public Long getHoldTime() - { + public Long getHoldTime() { return holdTime; } /** * Sets the amount of time the caller was on hold. - * + * * @param holdtime the amount of time the caller was on hold in seconds. */ - public void setHoldTime(Long holdtime) - { + public void setHoldTime(Long holdtime) { this.holdTime = holdtime; } @@ -89,23 +85,21 @@ public void setHoldTime(Long holdtime) * particular call from the queue. *

    * Available since Asterisk 1.4. - * + * * @return the unique ID of the queue member channel that is taking the - * call. + * call. */ - public String getBridgedChannel() - { + public String getBridgedChannel() { return bridgedChannel; } /** * Sets the unique ID of the queue member channel that is taking the call. - * + * * @param bridgedChannel the unique ID of the queue member channel that is - * taking the call. + * taking the call. */ - public void setBridgedChannel(String bridgedChannel) - { + public void setBridgedChannel(String bridgedChannel) { this.bridgedChannel = bridgedChannel; } @@ -116,268 +110,230 @@ public void setBridgedChannel(String bridgedChannel) * Available since Asterisk 1.6. * * @return the amount of time the agent's channel was ringing before - * answered in seconds. + * answered in seconds. * @since 1.0.0 */ - public Long getRingtime() - { + public Long getRingtime() { return ringtime; } - public void setRingtime(Long ringtime) - { + public void setRingtime(Long ringtime) { this.ringtime = ringtime; } /** * @return the destExten */ - public String getDestExten() - { + public String getDestExten() { return destExten; } /** * @param destExten the destExten to set */ - public void setDestExten(String destExten) - { + public void setDestExten(String destExten) { this.destExten = destExten; } /** * @return the destChannelStateDesc */ - public String getDestChannelStateDesc() - { + public String getDestChannelStateDesc() { return destChannelStateDesc; } /** * @param destChannelStateDesc the destChannelStateDesc to set */ - public void setDestChannelStateDesc(String destChannelStateDesc) - { + public void setDestChannelStateDesc(String destChannelStateDesc) { this.destChannelStateDesc = destChannelStateDesc; } /** * @return the destUniqueId */ - public String getDestUniqueId() - { + public String getDestUniqueId() { return destUniqueId; } /** * @param destUniqueId the destUniqueId to set */ - public void setDestUniqueId(String destUniqueId) - { + public void setDestUniqueId(String destUniqueId) { this.destUniqueId = destUniqueId; } /** * @return the destConnectedLineNum */ - public String getDestConnectedLineNum() - { + public String getDestConnectedLineNum() { return destConnectedLineNum; } /** * @param destConnectedLineNum the destConnectedLineNum to set */ - public void setDestConnectedLineNum(String destConnectedLineNum) - { + public void setDestConnectedLineNum(String destConnectedLineNum) { this.destConnectedLineNum = destConnectedLineNum; } /** * @return the destConnectedLineName */ - public String getDestConnectedLineName() - { + public String getDestConnectedLineName() { return destConnectedLineName; } /** * @param destConnectedLineName the destConnectedLineName to set */ - public void setDestConnectedLineName(String destConnectedLineName) - { + public void setDestConnectedLineName(String destConnectedLineName) { this.destConnectedLineName = destConnectedLineName; } /** * @return the destCallerIdName */ - public String getDestCallerIdName() - { + public String getDestCallerIdName() { return destCallerIdName; } /** * @param destCallerIdName the destCallerIdName to set */ - public void setDestCallerIdName(String destCallerIdName) - { + public void setDestCallerIdName(String destCallerIdName) { this.destCallerIdName = destCallerIdName; } /** * @return the destCallerIdNum */ - public String getDestCallerIdNum() - { + public String getDestCallerIdNum() { return destCallerIdNum; } /** * @param destCallerIdNum the destCallerIdNum to set */ - public void setDestCallerIdNum(String destCallerIdNum) - { + public void setDestCallerIdNum(String destCallerIdNum) { this.destCallerIdNum = destCallerIdNum; } /** * @return the destContext */ - public String getDestContext() - { + public String getDestContext() { return destContext; } /** * @param destContext the destContext to set */ - public void setDestContext(String destContext) - { + public void setDestContext(String destContext) { this.destContext = destContext; } /** * @return the destPriority */ - public String getDestPriority() - { + public String getDestPriority() { return destPriority; } /** * @param destPriority the destPriority to set */ - public void setDestPriority(String destPriority) - { + public void setDestPriority(String destPriority) { this.destPriority = destPriority; } /** * @return the destChannel */ - public String getDestChannel() - { + public String getDestChannel() { return destChannel; } /** * @param destChannel the destChannel to set */ - public void setDestChannel(String destChannel) - { + public void setDestChannel(String destChannel) { this.destChannel = destChannel; } /** * @return the destChannelState */ - public String getDestChannelState() - { + public String getDestChannelState() { return destChannelState; } /** * @param destChannelState the destChannelState to set */ - public void setDestChannelState(String destChannelState) - { + public void setDestChannelState(String destChannelState) { this.destChannelState = destChannelState; } /** * @return the iface */ - public String getInterface() - { + public String getInterface() { return iface; } /** * @param iface the iface to set */ - public void setInterface(String iface) - { + public void setInterface(String iface) { this.iface = iface; } - - public String getDestAccountCode() - { + + public String getDestAccountCode() { return destAccountCode; } - public void setDestAccountCode(String destAccountCode) - { + public void setDestAccountCode(String destAccountCode) { this.destAccountCode = destAccountCode; } - - public String getLinkedId() - { + + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getDestLinkedId() - { + public String getDestLinkedId() { return destLinkedId; } - public void setDestLinkedId(String destLinkedId) - { + public void setDestLinkedId(String destLinkedId) { this.destLinkedId = destLinkedId; } - public String getDestLanguage() - { + public String getDestLanguage() { return destLanguage; } - public void setDestLanguage(String destLanguage) - { + public void setDestLanguage(String destLanguage) { this.destLanguage = destLanguage; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getAccountcode() - { - return accountcode; - } + public String getAccountcode() { + return accountcode; + } - public void setAccountcode(String accountcode) - { - this.accountcode = accountcode; - } + public void setAccountcode(String accountcode) { + this.accountcode = accountcode; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentDumpEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentDumpEvent.java index 11b075879..f44301988 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentDumpEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentDumpEvent.java @@ -21,20 +21,18 @@ * to the queue announcement.

    * It is implemented in apps/app_queue.c.

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class AgentDumpEvent extends AbstractAgentEvent -{ +public class AgentDumpEvent extends AbstractAgentEvent { /** * Serial version identifier. */ private static final long serialVersionUID = 2108033737226142194L; - public AgentDumpEvent(Object source) - { + public AgentDumpEvent(Object source) { super(source); } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentLoginEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentLoginEvent.java index bbedc1e5e..08dfcf3ce 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentLoginEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentLoginEvent.java @@ -19,13 +19,12 @@ /** * An AgentLoginEvent is triggered when an agent is successfully logged in using AgentLogin.

    * It is implemented in channels/chan_agent.c - * - * @see org.asteriskjava.manager.event.AgentLogoffEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.AgentLogoffEvent */ -public class AgentLoginEvent extends ManagerEvent -{ +public class AgentLoginEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -37,76 +36,69 @@ public class AgentLoginEvent extends ManagerEvent /** * @param source */ - public AgentLoginEvent(Object source) - { + public AgentLoginEvent(Object source) { super(source); } /** * Returns the name of the agent that logged in. */ - public String getAgent() - { + public String getAgent() { return agent; } /** * Sets the name of the agent that logged in. */ - public void setAgent(String agent) - { + public void setAgent(String agent) { this.agent = agent; } /** * Returns the name of the channel associated with the logged in agent. - * + * * @deprecated use {@link #getChannel()} instead. */ - @Deprecated public String getLoginChan() - { + @Deprecated + public String getLoginChan() { return channel; } /** * Returns the name of the channel associated with the logged in agent. - * + * * @return the name of the channel associated with the logged in agent. * @since 0.3 */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel associated with the logged in agent. - * + * * @param channel the name of the channel associated with the logged in agent. * @since 0.3 */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the unique id of the channel associated with the logged in agent. - * + * * @return the unique id of the channel associated with the logged in agent. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } /** * Sets the unique id of the channel associated with the logged in agent. - * + * * @param uniqueId the unique id of the channel associated with the logged in agent. */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentLogoffEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentLogoffEvent.java index 2c4b8dc8d..e5e699a83 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentLogoffEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentLogoffEvent.java @@ -20,13 +20,12 @@ * An AgentCallbackLogoffEvent is triggered when an agent that previously logged in using AgentLogin * is logged of.

    * It is implemented in channels/chan_agent.c - * - * @see org.asteriskjava.manager.event.AgentLoginEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.AgentLoginEvent */ -public class AgentLogoffEvent extends ManagerEvent -{ +public class AgentLogoffEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -42,48 +41,41 @@ public class AgentLogoffEvent extends ManagerEvent /** * @param source */ - public AgentLogoffEvent(Object source) - { + public AgentLogoffEvent(Object source) { super(source); } /** * Returns the name of the agent that logged off. - * + * * @return the name of the agent that logged off. */ - public String getAgent() - { + public String getAgent() { return agent; } /** * Sets the name of the agent that logged off. - * + * * @param agent the name of the agent that logged off. */ - public void setAgent(String agent) - { + public void setAgent(String agent) { this.agent = agent; } - public String getLoginTime() - { + public String getLoginTime() { return loginTime; } - public void setLoginTime(String loginTime) - { + public void setLoginTime(String loginTime) { this.loginTime = loginTime; } - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentRingNoAnswerEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentRingNoAnswerEvent.java index ca946236f..d34f4c3a7 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentRingNoAnswerEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentRingNoAnswerEvent.java @@ -28,8 +28,7 @@ * @version $Id$ * @since 1.0.0 */ -public class AgentRingNoAnswerEvent extends AbstractAgentEvent -{ +public class AgentRingNoAnswerEvent extends AbstractAgentEvent { private static final long serialVersionUID = 2L; private Long ringtime; @@ -46,17 +45,16 @@ public class AgentRingNoAnswerEvent extends AbstractAgentEvent private String destChannel; private String destChannelState; private String iface; - + private String destAccountCode; private String language; private String destLanguage; private String linkedId; private String destLinkedId; - + private String accountcode; - - public AgentRingNoAnswerEvent(Object source) - { + + public AgentRingNoAnswerEvent(Object source) { super(source); } @@ -65,267 +63,229 @@ public AgentRingNoAnswerEvent(Object source) * * @return the amount of time the agent's channel was ringing in seconds. */ - public Long getRingtime() - { + public Long getRingtime() { return ringtime; } - public void setRingtime(Long ringtime) - { + public void setRingtime(Long ringtime) { this.ringtime = ringtime; } /** * @return the destExten */ - public String getDestExten() - { + public String getDestExten() { return destExten; } /** * @param destExten the destExten to set */ - public void setDestExten(String destExten) - { + public void setDestExten(String destExten) { this.destExten = destExten; } /** * @return the destChannelStateDesc */ - public String getDestChannelStateDesc() - { + public String getDestChannelStateDesc() { return destChannelStateDesc; } /** * @param destChannelStateDesc the destChannelStateDesc to set */ - public void setDestChannelStateDesc(String destChannelStateDesc) - { + public void setDestChannelStateDesc(String destChannelStateDesc) { this.destChannelStateDesc = destChannelStateDesc; } /** * @return the destUniqueId */ - public String getDestUniqueId() - { + public String getDestUniqueId() { return destUniqueId; } /** * @param destUniqueId the destUniqueId to set */ - public void setDestUniqueId(String destUniqueId) - { + public void setDestUniqueId(String destUniqueId) { this.destUniqueId = destUniqueId; } /** * @return the destConnectedLineNum */ - public String getDestConnectedLineNum() - { + public String getDestConnectedLineNum() { return destConnectedLineNum; } /** * @param destConnectedLineNum the destConnectedLineNum to set */ - public void setDestConnectedLineNum(String destConnectedLineNum) - { + public void setDestConnectedLineNum(String destConnectedLineNum) { this.destConnectedLineNum = destConnectedLineNum; } /** * @return the destConnectedLineName */ - public String getDestConnectedLineName() - { + public String getDestConnectedLineName() { return destConnectedLineName; } /** * @param destConnectedLineName the destConnectedLineName to set */ - public void setDestConnectedLineName(String destConnectedLineName) - { + public void setDestConnectedLineName(String destConnectedLineName) { this.destConnectedLineName = destConnectedLineName; } /** * @return the destCallerIdName */ - public String getDestCallerIdName() - { + public String getDestCallerIdName() { return destCallerIdName; } /** * @param destCallerIdName the destCallerIdName to set */ - public void setDestCallerIdName(String destCallerIdName) - { + public void setDestCallerIdName(String destCallerIdName) { this.destCallerIdName = destCallerIdName; } /** * @return the destCallerIdNum */ - public String getDestCallerIdNum() - { + public String getDestCallerIdNum() { return destCallerIdNum; } /** * @param destCallerIdNum the destCallerIdNum to set */ - public void setDestCallerIdNum(String destCallerIdNum) - { + public void setDestCallerIdNum(String destCallerIdNum) { this.destCallerIdNum = destCallerIdNum; } /** * @return the destContext */ - public String getDestContext() - { + public String getDestContext() { return destContext; } /** * @param destContext the destContext to set */ - public void setDestContext(String destContext) - { + public void setDestContext(String destContext) { this.destContext = destContext; } /** * @return the destPriority */ - public String getDestPriority() - { + public String getDestPriority() { return destPriority; } /** * @param destPriority the destPriority to set */ - public void setDestPriority(String destPriority) - { + public void setDestPriority(String destPriority) { this.destPriority = destPriority; } /** * @return the destChannel */ - public String getDestChannel() - { + public String getDestChannel() { return destChannel; } /** * @param destChannel the destChannel to set */ - public void setDestChannel(String destChannel) - { + public void setDestChannel(String destChannel) { this.destChannel = destChannel; } /** * @return the destChannelState */ - public String getDestChannelState() - { + public String getDestChannelState() { return destChannelState; } /** * @param destChannelState the destChannelState to set */ - public void setDestChannelState(String destChannelState) - { + public void setDestChannelState(String destChannelState) { this.destChannelState = destChannelState; } /** * @return the iface */ - public String getInterface() - { + public String getInterface() { return iface; } /** * @param iface the iface to set */ - public void setInterface(String iface) - { + public void setInterface(String iface) { this.iface = iface; } - public String getDestAccountCode() - { + public String getDestAccountCode() { return destAccountCode; } - public void setDestAccountCode(String destAccountCode) - { + public void setDestAccountCode(String destAccountCode) { this.destAccountCode = destAccountCode; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getDestLanguage() - { + public String getDestLanguage() { return destLanguage; } - public void setDestLanguage(String destLanguage) - { + public void setDestLanguage(String destLanguage) { this.destLanguage = destLanguage; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getDestLinkedId() - { + public String getDestLinkedId() { return destLinkedId; } - public void setDestLinkedId(String destLinkedId) - { + public void setDestLinkedId(String destLinkedId) { this.destLinkedId = destLinkedId; } - public String getAccountcode() - { - return accountcode; - } + public String getAccountcode() { + return accountcode; + } + + public void setAccountcode(String accountcode) { + this.accountcode = accountcode; + } + - public void setAccountcode(String accountcode) - { - this.accountcode = accountcode; - } - - } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentsCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentsCompleteEvent.java index b48cde5bd..c4ab8553b 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentsCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentsCompleteEvent.java @@ -20,14 +20,13 @@ * An AgentsCompleteEvent is triggered after the state of all agents has been * reported in response to an AgentsAction.

    * Available since Asterisk 1.2 - * - * @see org.asteriskjava.manager.action.AgentsAction + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.AgentsAction * @since 0.2 */ -public class AgentsCompleteEvent extends ResponseEvent -{ +public class AgentsCompleteEvent extends ResponseEvent { /** * Serial version identifier */ @@ -35,33 +34,28 @@ public class AgentsCompleteEvent extends ResponseEvent private Integer listItems; private String eventList; - + /** * @param source */ - public AgentsCompleteEvent(Object source) - { + public AgentsCompleteEvent(Object source) { super(source); } - public Integer getListItems() - { + public Integer getListItems() { return listItems; } - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } - public String getEventList() - { + public String getEventList() { return eventList; } - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } - + } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentsEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentsEvent.java index 1447be3ee..cbb2b0379 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentsEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentsEvent.java @@ -20,14 +20,13 @@ * An AgentsEvent is triggered for each agent in response to an AgentsAction. *

    * Available since Asterisk 1.2 - * - * @see org.asteriskjava.manager.action.AgentsAction + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.AgentsAction * @since 0.2 */ -public class AgentsEvent extends ResponseEvent -{ +public class AgentsEvent extends ResponseEvent { /** * Serial version identifier */ @@ -64,44 +63,39 @@ public class AgentsEvent extends ResponseEvent /** * @param source */ - public AgentsEvent(Object source) - { + public AgentsEvent(Object source) { super(source); } /** * Returns the agentid. */ - public String getAgent() - { + public String getAgent() { return agent; } /** * Sets the agentid. */ - public void setAgent(String agent) - { + public void setAgent(String agent) { this.agent = agent; } /** * Returns the name of this agent. - * + * * @return the name of this agent */ - public String getName() - { + public String getName() { return name; } /** * Sets the name of this agent. - * + * * @param name the name of this agent */ - public void setName(String name) - { + public void setName(String name) { this.name = name; } @@ -119,106 +113,96 @@ public void setName(String name) *

    "AGENT_UNKNOWN"
    *
    Don't know anything about agent. Shouldn't ever get this.
    * - * + * * @return the status of this agent * @see #AGENT_STATUS_LOGGEDOFF * @see #AGENT_STATUS_IDLE * @see #AGENT_STATUS_ONCALL * @see #AGENT_STATUS_UNKNOWN */ - public String getStatus() - { + public String getStatus() { return status; } /** * Sets the status of this agent. - * + * * @param status the status of this agent */ - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } /** * Returns the name of channel this agent logged in from. - * + * * @return the name of the channel this agent logged in from or "n/a" if the - * agent is not logged in. + * agent is not logged in. */ - public String getLoggedInChan() - { + public String getLoggedInChan() { return loggedInChan; } /** * Sets the name of channel this agent logged in from. - * + * * @param loggedInChan the name of channel this agent logged in from */ - public void setLoggedInChan(String loggedInChan) - { + public void setLoggedInChan(String loggedInChan) { this.loggedInChan = loggedInChan; } /** * Returns the time (in seconds since 01/01/1970) when the agent logged in. - * + * * @return the time when the agent logged in or 0 if the user is not logged - * in. + * in. */ - public Long getLoggedInTime() - { + public Long getLoggedInTime() { return loggedInTime; } /** * Sets the time when the agent logged in. - * + * * @param loggedInTime the time when the agent logged in */ - public void setLoggedInTime(Long loggedInTime) - { + public void setLoggedInTime(Long loggedInTime) { this.loggedInTime = loggedInTime; } /** * Returns the numerical Caller*ID of the channel this agent is talking to. - * + * * @return the numerical Caller*ID of the channel this agent is talking to - * or "n/a" if this agent is talking to nobody. + * or "n/a" if this agent is talking to nobody. */ - public String getTalkingTo() - { + public String getTalkingTo() { return talkingTo; } /** * Sets the numerical Caller*ID of the channel this agent is talking to. - * + * * @param talkingTo the numerical Caller*ID of the channel this agent is - * talking to + * talking to */ - public void setTalkingTo(String talkingTo) - { + public void setTalkingTo(String talkingTo) { this.talkingTo = talkingTo; } /** * Returns the name of the channel this agent is talking to.

    * Available since Asterisk 1.6. - * + * * @return the name of the channel this agent is talking to. * @since 1.0.0 */ - public String getTalkingToChan() - { + public String getTalkingToChan() { return talkingToChan; } - public void setTalkingToChan(String talkingToChan) - { + public void setTalkingToChan(String talkingToChan) { this.talkingToChan = talkingToChan; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgiExecEndEvent.java b/src/main/java/org/asteriskjava/manager/event/AgiExecEndEvent.java index 2981876c4..5a2910883 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgiExecEndEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgiExecEndEvent.java @@ -3,36 +3,34 @@ /** * Created by plhk on 1/15/15. */ -public class AgiExecEndEvent extends AgiExecEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; - - private String linkedid; - - private String language; - - public AgiExecEndEvent(Object source) - { - super(source); - setSubEvent(SUB_EVENT_END); - } - - public String getLinkedid() { - return linkedid; - } - - public void setLinkedid(String linkedid) { - this.linkedid = linkedid; - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } +public class AgiExecEndEvent extends AgiExecEvent { + /** + * + */ + private static final long serialVersionUID = 1L; + + private String linkedid; + + private String language; + + public AgiExecEndEvent(Object source) { + super(source); + setSubEvent(SUB_EVENT_END); + } + + public String getLinkedid() { + return linkedid; + } + + public void setLinkedid(String linkedid) { + this.linkedid = linkedid; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgiExecEvent.java b/src/main/java/org/asteriskjava/manager/event/AgiExecEvent.java index 4fc78bf87..aa44573e3 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgiExecEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgiExecEvent.java @@ -17,228 +17,207 @@ * @version $Id$ * @since 1.0.0 */ -public class AgiExecEvent extends ManagerEvent -{ - /** - * Serializable version identifier. - */ - static final long serialVersionUID = 0L; - - /** - * Execution of an AGI command has started. - */ - public static final String SUB_EVENT_START = "Start"; - - /** - * Execution of an AGI command has finished. - */ - public static final String SUB_EVENT_END = "End"; - - private String channel; - private String subEvent; - private String commandId; - private String command; - private Integer resultCode; - private String result; - private String accountCode; - - public String getUniqueId() - { - return uniqueId; - } - - public void setUniqueId(String uniqueId) - { - this.uniqueId = uniqueId; - } - - private String uniqueId; - - /** - * Creates a new AgiExecEvent. - * - * @param source - */ - public AgiExecEvent(Object source) - { - super(source); - } - - /** - * Returns the name of the channel this event occurred on. - * - * @return the name of the channel this event occurred on. - */ - public String getChannel() - { - return channel; - } - - /** - * Sets the name of the channel this event occurred on. - * - * @param channel the name of the channel this event occurred on. - */ - public void setChannel(String channel) - { - this.channel = channel; - } - - /** - * Returns the sub event type. This is either "Start" or "End". - * - * @return the sub event type. - * @see #SUB_EVENT_START - * @see #SUB_EVENT_END - */ - public String getSubEvent() - { - return subEvent; - } - - /** - * Sets the sub event type. - * - * @param subEvent the sub event type. - */ - public void setSubEvent(String subEvent) - { - this.subEvent = subEvent; - } - - /** - * Returns the command id. The command is a random number generated by Asterisk that allows matching the "End" sub event with the corresponding "Start" sub event. - * - * @return the command id. - */ - public String getCommandId() - { - return commandId; - } - - /** - * Sets the command id. - * - * @param commandId the command id. - */ - public void setCommandId(String commandId) - { - this.commandId = commandId; - } - - /** - * Returns the AGI command. - * - * @return the AGI command. - */ - public String getCommand() - { - return command; - } - - /** - * Sets the AGI command. - * - * @param command the AGI command. - */ - public void setCommand(String command) - { - this.command = command; - } - - /** - * Returns the result code. - * - * @return the result code. - */ - public Integer getResultCode() - { - return resultCode; - } - - /** - * Sets the result code. - * - * @param resultCode the result code. - */ - public void setResultCode(Integer resultCode) - { - this.resultCode = resultCode; - } - - /** - * Returns the result as a string.

    - * They correspond to the numeric values returned by {@link #getResultCode()}. Usually you will want to stick with the numeric values.

    - * Possible values are: - *

      - *
    • Failure (corresponds to result code -1)
    • - *
    • Success (corresponds to result code 200)
    • - *
    • KeepAlive (corresponds to result code 210)
    • - *
    • Command not permitted on a dead channel (corresponds to result code 511)
    • - *
    • Usage (corresponds to result code 520)
    • - *
    - * - * @return a string respresentation of the result. - */ - public String getResult() - { - return result; - } - - /** - * Sets the string respresentation of the result. - * - * @param result a string respresentation of the result. - */ - public void setResult(String result) - { - this.result = result; - } - - /** - * Returns the account code set for CDR. - * - * @return string - */ - public String getAccountCode() - { - return accountCode; - } - - /** - * Sets the account code used for billing in the CDR. - *
    - * This will be the filename asterisk stores the billing informations in, so it should only use lowercase letters, numbers, hyphen and underscore. - * - * @param accountCode - */ - public void setAccountCode(String accountCode) - { - this.accountCode = accountCode; - } - - /** - * Checks is this a start sub event. - * - * @return true if this is a "Start" sub event, false otherwise. - */ - public boolean isStart() - { - return isSubEvent(SUB_EVENT_START); - } - - /** - * Checks is this an end sub event. - * - * @return true if this is an "End" sub event, false otherwise. - */ - public boolean isEnd() - { - return isSubEvent(SUB_EVENT_END); - } - - private boolean isSubEvent(String subEvent) - { - return this.subEvent != null && this.subEvent.equalsIgnoreCase(subEvent); - } +public class AgiExecEvent extends ManagerEvent { + /** + * Serializable version identifier. + */ + static final long serialVersionUID = 0L; + + /** + * Execution of an AGI command has started. + */ + public static final String SUB_EVENT_START = "Start"; + + /** + * Execution of an AGI command has finished. + */ + public static final String SUB_EVENT_END = "End"; + + private String channel; + private String subEvent; + private String commandId; + private String command; + private Integer resultCode; + private String result; + private String accountCode; + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } + + private String uniqueId; + + /** + * Creates a new AgiExecEvent. + * + * @param source + */ + public AgiExecEvent(Object source) { + super(source); + } + + /** + * Returns the name of the channel this event occurred on. + * + * @return the name of the channel this event occurred on. + */ + public String getChannel() { + return channel; + } + + /** + * Sets the name of the channel this event occurred on. + * + * @param channel the name of the channel this event occurred on. + */ + public void setChannel(String channel) { + this.channel = channel; + } + + /** + * Returns the sub event type. This is either "Start" or "End". + * + * @return the sub event type. + * @see #SUB_EVENT_START + * @see #SUB_EVENT_END + */ + public String getSubEvent() { + return subEvent; + } + + /** + * Sets the sub event type. + * + * @param subEvent the sub event type. + */ + public void setSubEvent(String subEvent) { + this.subEvent = subEvent; + } + + /** + * Returns the command id. The command is a random number generated by Asterisk that allows matching the "End" sub event with the corresponding "Start" sub event. + * + * @return the command id. + */ + public String getCommandId() { + return commandId; + } + + /** + * Sets the command id. + * + * @param commandId the command id. + */ + public void setCommandId(String commandId) { + this.commandId = commandId; + } + + /** + * Returns the AGI command. + * + * @return the AGI command. + */ + public String getCommand() { + return command; + } + + /** + * Sets the AGI command. + * + * @param command the AGI command. + */ + public void setCommand(String command) { + this.command = command; + } + + /** + * Returns the result code. + * + * @return the result code. + */ + public Integer getResultCode() { + return resultCode; + } + + /** + * Sets the result code. + * + * @param resultCode the result code. + */ + public void setResultCode(Integer resultCode) { + this.resultCode = resultCode; + } + + /** + * Returns the result as a string.

    + * They correspond to the numeric values returned by {@link #getResultCode()}. Usually you will want to stick with the numeric values.

    + * Possible values are: + *

      + *
    • Failure (corresponds to result code -1)
    • + *
    • Success (corresponds to result code 200)
    • + *
    • KeepAlive (corresponds to result code 210)
    • + *
    • Command not permitted on a dead channel (corresponds to result code 511)
    • + *
    • Usage (corresponds to result code 520)
    • + *
    + * + * @return a string respresentation of the result. + */ + public String getResult() { + return result; + } + + /** + * Sets the string respresentation of the result. + * + * @param result a string respresentation of the result. + */ + public void setResult(String result) { + this.result = result; + } + + /** + * Returns the account code set for CDR. + * + * @return string + */ + public String getAccountCode() { + return accountCode; + } + + /** + * Sets the account code used for billing in the CDR. + *
    + * This will be the filename asterisk stores the billing informations in, so it should only use lowercase letters, numbers, hyphen and underscore. + * + * @param accountCode + */ + public void setAccountCode(String accountCode) { + this.accountCode = accountCode; + } + + /** + * Checks is this a start sub event. + * + * @return true if this is a "Start" sub event, false otherwise. + */ + public boolean isStart() { + return isSubEvent(SUB_EVENT_START); + } + + /** + * Checks is this an end sub event. + * + * @return true if this is an "End" sub event, false otherwise. + */ + public boolean isEnd() { + return isSubEvent(SUB_EVENT_END); + } + + private boolean isSubEvent(String subEvent) { + return this.subEvent != null && this.subEvent.equalsIgnoreCase(subEvent); + } } diff --git a/src/main/java/org/asteriskjava/manager/event/AgiExecStartEvent.java b/src/main/java/org/asteriskjava/manager/event/AgiExecStartEvent.java index 525c1692c..6b2a4e5a9 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgiExecStartEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgiExecStartEvent.java @@ -3,36 +3,34 @@ /** * Created by plhk on 1/15/15. */ -public class AgiExecStartEvent extends AgiExecEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; - - private String linkedid; - - private String language; - - public AgiExecStartEvent(Object source) - { - super(source); - setSubEvent(SUB_EVENT_START); - } - - public String getLinkedid() { - return linkedid; - } - - public void setLinkedid(String linkedid) { - this.linkedid = linkedid; - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } +public class AgiExecStartEvent extends AgiExecEvent { + /** + * + */ + private static final long serialVersionUID = 1L; + + private String linkedid; + + private String language; + + public AgiExecStartEvent(Object source) { + super(source); + setSubEvent(SUB_EVENT_START); + } + + public String getLinkedid() { + return linkedid; + } + + public void setLinkedid(String linkedid) { + this.linkedid = linkedid; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/AlarmClearEvent.java b/src/main/java/org/asteriskjava/manager/event/AlarmClearEvent.java index a0be33356..2b8eee9a8 100644 --- a/src/main/java/org/asteriskjava/manager/event/AlarmClearEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AlarmClearEvent.java @@ -19,12 +19,11 @@ /** * An AlarmEvent is triggered when a Zap channel leaves alarm state.

    * It is implemented in channels/chan_zap.c - * + * * @author srt * @version $Id$ */ -public class AlarmClearEvent extends ManagerEvent -{ +public class AlarmClearEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -38,28 +37,25 @@ public class AlarmClearEvent extends ManagerEvent /** * @param source */ - public AlarmClearEvent(Object source) - { + public AlarmClearEvent(Object source) { super(source); } /** * Returns the number of the zap channel that left alarm state. - * + * * @return the number of the zap channel that left alarm state. */ - public Integer getChannel() - { + public Integer getChannel() { return channel; } /** * Sets the number of the zap channel that left alarm state. - * + * * @param channel the number of the zap channel that left alarm state. */ - public void setChannel(Integer channel) - { + public void setChannel(Integer channel) { this.channel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AlarmEvent.java b/src/main/java/org/asteriskjava/manager/event/AlarmEvent.java index 1f490e9bc..7a1c7ed6d 100644 --- a/src/main/java/org/asteriskjava/manager/event/AlarmEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AlarmEvent.java @@ -19,12 +19,11 @@ /** * An AlarmEvent is triggered when a Zap channel enters or changes alarm state.

    * It is implemented in channels/chan_zap.c - * + * * @author srt * @version $Id$ */ -public class AlarmEvent extends ManagerEvent -{ +public class AlarmEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -35,8 +34,7 @@ public class AlarmEvent extends ManagerEvent /** * @param source */ - public AlarmEvent(Object source) - { + public AlarmEvent(Object source) { super(source); } @@ -52,32 +50,28 @@ public AlarmEvent(Object source) *

  • Not Open
  • * */ - public String getAlarm() - { + public String getAlarm() { return alarm; } /** * Sets the kind of alarm that happened. */ - public void setAlarm(String alarm) - { + public void setAlarm(String alarm) { this.alarm = alarm; } /** * Returns the number of the channel the alarm occured on. */ - public Integer getChannel() - { + public Integer getChannel() { return channel; } /** * Sets the number of the channel the alarm occured on. */ - public void setChannel(Integer channel) - { + public void setChannel(Integer channel) { this.channel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/event/AntennaLevelEvent.java b/src/main/java/org/asteriskjava/manager/event/AntennaLevelEvent.java index bdf91332c..537eb4ced 100644 --- a/src/main/java/org/asteriskjava/manager/event/AntennaLevelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AntennaLevelEvent.java @@ -2,23 +2,23 @@ public class AntennaLevelEvent extends AbstractChannelEvent { - /** - * - */ - private static final long serialVersionUID = 7687745700915865011L; + /** + * + */ + private static final long serialVersionUID = 7687745700915865011L; - private String signal; - - public AntennaLevelEvent(Object source) { - super(source); - } + private String signal; - public String getSignal() { - return signal; - } + public AntennaLevelEvent(Object source) { + super(source); + } - public void setSignal(String signal) { - this.signal = signal; - } + public String getSignal() { + return signal; + } + + public void setSignal(String signal) { + this.signal = signal; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/AorDetail.java b/src/main/java/org/asteriskjava/manager/event/AorDetail.java index ee6401364..fa8f8cd8a 100644 --- a/src/main/java/org/asteriskjava/manager/event/AorDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/AorDetail.java @@ -11,16 +11,14 @@ * @since 12 */ -public class AorDetail extends ResponseEvent -{ +public class AorDetail extends ResponseEvent { /** * Serial version identifier. */ private static final long serialVersionUID = 2634171854313358591L; - public AorDetail(Object source) - { + public AorDetail(Object source) { super(source); } @@ -43,183 +41,147 @@ public AorDetail(Object source) private int contactsRegistered; private String endpointName; - public String getObjectType() - { + public String getObjectType() { return objectType; } - public void setObjectType(String objectType) - { + public void setObjectType(String objectType) { this.objectType = objectType; } - public String getObjectName() - { + public String getObjectName() { return objectName; } - public void setObjectName(String objectName) - { + public void setObjectName(String objectName) { this.objectName = objectName; } - public int getMinimumExpiration() - { + public int getMinimumExpiration() { return minimumExpiration; } - public void setMinimumExpiration(int minimumExpiration) - { + public void setMinimumExpiration(int minimumExpiration) { this.minimumExpiration = minimumExpiration; } - public int getDefaultExpiration() - { + public int getDefaultExpiration() { return defaultExpiration; } - public void setDefaultExpiration(int defaultExpiration) - { + public void setDefaultExpiration(int defaultExpiration) { this.defaultExpiration = defaultExpiration; } - public Float getQualifyTimeout() - { + public Float getQualifyTimeout() { return qualifyTimeout; } - public void setQualifyTimeout(Float qualifyTimeout) - { + public void setQualifyTimeout(Float qualifyTimeout) { this.qualifyTimeout = qualifyTimeout; } - public String getMailboxes() - { + public String getMailboxes() { return mailboxes; } - public void setMailboxes(String mailboxes) - { + public void setMailboxes(String mailboxes) { this.mailboxes = mailboxes; } - public Boolean isSupportPath() - { + public Boolean isSupportPath() { return supportPath; } - public void setSupportPath(Boolean supportPath) - { + public void setSupportPath(Boolean supportPath) { this.supportPath = supportPath; } - public String getVoicemailExtension() - { + public String getVoicemailExtension() { return voicemailExtension; } - public void setVoicemailExtension(String voicemailExtension) - { + public void setVoicemailExtension(String voicemailExtension) { this.voicemailExtension = voicemailExtension; } - public int getMaxContacts() - { + public int getMaxContacts() { return maxContacts; } - public void setMaxContacts(int maxContacts) - { + public void setMaxContacts(int maxContacts) { this.maxContacts = maxContacts; } - public Boolean isAuthenticateQualify() - { + public Boolean isAuthenticateQualify() { return authenticateQualify; } - public void setAuthenticateQualify(Boolean authenticateQualify) - { + public void setAuthenticateQualify(Boolean authenticateQualify) { this.authenticateQualify = authenticateQualify; } - public String getContacts() - { + public String getContacts() { return contacts; } - public void setContacts(String contacts) - { + public void setContacts(String contacts) { this.contacts = contacts; } - public int getMaximumExpiration() - { + public int getMaximumExpiration() { return maximumExpiration; } - public void setMaximumExpiration(int maximumExpiration) - { + public void setMaximumExpiration(int maximumExpiration) { this.maximumExpiration = maximumExpiration; } - public int getQualifyFrequency() - { + public int getQualifyFrequency() { return qualifyFrequency; } - public void setQualifyFrequency(int qualifyFrequency) - { + public void setQualifyFrequency(int qualifyFrequency) { this.qualifyFrequency = qualifyFrequency; } - public Boolean isRemoveExisting() - { + public Boolean isRemoveExisting() { return removeExisting; } - public void setRemoveExisting(Boolean removeExisting) - { + public void setRemoveExisting(Boolean removeExisting) { this.removeExisting = removeExisting; } - public String getOutboundProxy() - { + public String getOutboundProxy() { return outboundProxy; } - public void setOutboundProxy(String outboundProxy) - { + public void setOutboundProxy(String outboundProxy) { this.outboundProxy = outboundProxy; } - public int getTotalContacts() - { + public int getTotalContacts() { return totalContacts; } - public void setTotalContacts(int totalContacts) - { + public void setTotalContacts(int totalContacts) { this.totalContacts = totalContacts; } - public int getContactsRegistered() - { + public int getContactsRegistered() { return contactsRegistered; } - public void setContactsRegistered(int contactsRegistered) - { + public void setContactsRegistered(int contactsRegistered) { this.contactsRegistered = contactsRegistered; } - public String getEndpointName() - { + public String getEndpointName() { return endpointName; } - public void setEndpointName(String endpointName) - { + public void setEndpointName(String endpointName) { this.endpointName = endpointName; } diff --git a/src/main/java/org/asteriskjava/manager/event/AsyncAgiEndEvent.java b/src/main/java/org/asteriskjava/manager/event/AsyncAgiEndEvent.java index 944f79340..070394dad 100644 --- a/src/main/java/org/asteriskjava/manager/event/AsyncAgiEndEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AsyncAgiEndEvent.java @@ -3,16 +3,14 @@ /** * Created by plhk on 1/15/15. */ -public class AsyncAgiEndEvent extends AsyncAgiEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; +public class AsyncAgiEndEvent extends AsyncAgiEvent { + /** + * + */ + private static final long serialVersionUID = 1L; - public AsyncAgiEndEvent(Object source) - { - super(source); - setSubEvent(SUB_EVENT_END); - } + public AsyncAgiEndEvent(Object source) { + super(source); + setSubEvent(SUB_EVENT_END); + } } diff --git a/src/main/java/org/asteriskjava/manager/event/AsyncAgiEvent.java b/src/main/java/org/asteriskjava/manager/event/AsyncAgiEvent.java index ac25a9be2..deeff2bf8 100644 --- a/src/main/java/org/asteriskjava/manager/event/AsyncAgiEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AsyncAgiEvent.java @@ -7,7 +7,6 @@ import java.util.List; /** - * * The following sub events are reported: *
      *
    • Start: A channel has started the AGI("agi:async") application and is awaiting Async AGI commands.
    • @@ -24,8 +23,7 @@ * @see org.asteriskjava.manager.action.AgiAction * @since 1.0.0 */ -public class AsyncAgiEvent extends ResponseEvent -{ +public class AsyncAgiEvent extends ResponseEvent { /** * Serializable version identifier. */ @@ -55,8 +53,7 @@ public void setUniqueId(String uniqueId) { * * @param source */ - public AsyncAgiEvent(Object source) - { + public AsyncAgiEvent(Object source) { super(source); } @@ -65,8 +62,7 @@ public AsyncAgiEvent(Object source) * * @return the name of the channel this event occurred on. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -75,8 +71,7 @@ public String getChannel() * * @param channel the name of the channel this event occurred on. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -85,8 +80,7 @@ public void setChannel(String channel) * * @return the sub event type. */ - public String getSubEvent() - { + public String getSubEvent() { return subEvent; } @@ -95,8 +89,7 @@ public String getSubEvent() * * @param subEvent the sub event type. */ - public void setSubEvent(String subEvent) - { + public void setSubEvent(String subEvent) { this.subEvent = subEvent; } @@ -107,8 +100,7 @@ public void setSubEvent(String subEvent) * @return the command id. * @see org.asteriskjava.manager.action.AgiAction#setCommandId(String) */ - public String getCommandId() - { + public String getCommandId() { return commandId; } @@ -117,8 +109,7 @@ public String getCommandId() * * @param commandId the command id. */ - public void setCommandId(String commandId) - { + public void setCommandId(String commandId) { this.commandId = commandId; } @@ -134,8 +125,7 @@ public void setCommandId(String commandId) * * @return the URL encoded result. */ - public String getResult() - { + public String getResult() { return result; } @@ -144,8 +134,7 @@ public String getResult() * * @return the decoded result. */ - public List decodeResult() - { + public List decodeResult() { return decode(getResult()); } @@ -154,8 +143,7 @@ public List decodeResult() * * @param result the URL encoded result. */ - public void setResult(String result) - { + public void setResult(String result) { this.result = result; } @@ -177,8 +165,7 @@ public void setResult(String result) * * @return the URL encoded AGI environment. */ - public String getEnv() - { + public String getEnv() { return env; } @@ -186,30 +173,24 @@ public String getEnv() * Decodes the AGI environment and returns a list of lines. * * @return The decoded AGI environment or an empty list if the environment is not available (that is - * if {@link #getEnv()} returns null). + * if {@link #getEnv()} returns null). * @see #getEnv() */ - public List decodeEnv() - { + public List decodeEnv() { return decode(getEnv()); } - private List decode(String s) - { + private List decode(String s) { final List result = new ArrayList<>(); - if (s == null) - { + if (s == null) { return result; } - try - { + try { final String decodedString = URLDecoder.decode(s, "UTF-8"); result.addAll(Arrays.asList(decodedString.split("\n"))); - } - catch (UnsupportedEncodingException e) - { + } catch (UnsupportedEncodingException e) { throw new RuntimeException("This JDK does not support UTF-8 encoding", e); } @@ -221,8 +202,7 @@ private List decode(String s) * * @param env the URL encoded AGI environment. */ - public void setEnv(String env) - { + public void setEnv(String env) { this.env = env; } @@ -231,8 +211,7 @@ public void setEnv(String env) * * @return true if this is a "Start" sub event, false otherwise. */ - public boolean isStart() - { + public boolean isStart() { return isSubEvent(SUB_EVENT_START); } @@ -241,8 +220,7 @@ public boolean isStart() * * @return true if this is an "Exec" sub event, false otherwise. */ - public boolean isExec() - { + public boolean isExec() { return isSubEvent(SUB_EVENT_EXEC); } @@ -251,13 +229,11 @@ public boolean isExec() * * @return true if this is an "End" sub event, false otherwise. */ - public boolean isEnd() - { + public boolean isEnd() { return isSubEvent(SUB_EVENT_END); } - protected boolean isSubEvent(String subEvent) - { + protected boolean isSubEvent(String subEvent) { return this.subEvent != null && this.subEvent.equalsIgnoreCase(subEvent); } } diff --git a/src/main/java/org/asteriskjava/manager/event/AsyncAgiExecEvent.java b/src/main/java/org/asteriskjava/manager/event/AsyncAgiExecEvent.java index adde1cca7..161188d73 100644 --- a/src/main/java/org/asteriskjava/manager/event/AsyncAgiExecEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AsyncAgiExecEvent.java @@ -3,16 +3,14 @@ /** * Created by plhk on 1/15/15. */ -public class AsyncAgiExecEvent extends AsyncAgiEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; +public class AsyncAgiExecEvent extends AsyncAgiEvent { + /** + * + */ + private static final long serialVersionUID = 1L; - public AsyncAgiExecEvent(Object source) - { - super(source); - setSubEvent(SUB_EVENT_EXEC); - } + public AsyncAgiExecEvent(Object source) { + super(source); + setSubEvent(SUB_EVENT_EXEC); + } } diff --git a/src/main/java/org/asteriskjava/manager/event/AsyncAgiStartEvent.java b/src/main/java/org/asteriskjava/manager/event/AsyncAgiStartEvent.java index 1e924079a..fabfd4575 100644 --- a/src/main/java/org/asteriskjava/manager/event/AsyncAgiStartEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AsyncAgiStartEvent.java @@ -3,16 +3,14 @@ /** * Created by plhk on 1/15/15. */ -public class AsyncAgiStartEvent extends AsyncAgiEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; +public class AsyncAgiStartEvent extends AsyncAgiEvent { + /** + * + */ + private static final long serialVersionUID = 1L; - public AsyncAgiStartEvent(Object source) - { - super(source); - setSubEvent(SUB_EVENT_START); - } + public AsyncAgiStartEvent(Object source) { + super(source); + setSubEvent(SUB_EVENT_START); + } } diff --git a/src/main/java/org/asteriskjava/manager/event/AttendedTransferEvent.java b/src/main/java/org/asteriskjava/manager/event/AttendedTransferEvent.java index 07778bf76..a5a9b31ac 100644 --- a/src/main/java/org/asteriskjava/manager/event/AttendedTransferEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AttendedTransferEvent.java @@ -2,7 +2,7 @@ /** * Raised when attended transfer is complete - * + *

      * https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+ManagerEvent_AttendedTransfer */ public class AttendedTransferEvent extends AbstractBridgeEvent { @@ -112,1008 +112,807 @@ public class AttendedTransferEvent extends AbstractBridgeEvent { private String secondTransfererLinkedId; private String origTransfererLanguage; - public AttendedTransferEvent(Object source) - { + public AttendedTransferEvent(Object source) { super(source); } - public String getOrigTransfererChannel() - { + public String getOrigTransfererChannel() { return origTransfererChannel; } - public void setOrigTransfererChannel(String origTransfererChannel) - { + public void setOrigTransfererChannel(String origTransfererChannel) { this.origTransfererChannel = origTransfererChannel; } - public String getOrigTransfererChannelState() - { + public String getOrigTransfererChannelState() { return origTransfererChannelState; } - public void setOrigTransfererChannelState(String origTransfererChannelState) - { + public void setOrigTransfererChannelState(String origTransfererChannelState) { this.origTransfererChannelState = origTransfererChannelState; } - public String getOrigTransfererChannelStateDesc() - { + public String getOrigTransfererChannelStateDesc() { return origTransfererChannelStateDesc; } - public void setOrigTransfererChannelStateDesc(String origTransfererChannelStateDesc) - { + public void setOrigTransfererChannelStateDesc(String origTransfererChannelStateDesc) { this.origTransfererChannelStateDesc = origTransfererChannelStateDesc; } - public String getOrigTransfererCallerIDNum() - { + public String getOrigTransfererCallerIDNum() { return origTransfererCallerIDNum; } - public void setOrigTransfererCallerIDNum(String origTransfererCallerIDNum) - { + public void setOrigTransfererCallerIDNum(String origTransfererCallerIDNum) { this.origTransfererCallerIDNum = origTransfererCallerIDNum; } - public String getOrigTransfererCallerIDName() - { + public String getOrigTransfererCallerIDName() { return origTransfererCallerIDName; } - public void setOrigTransfererCallerIDName(String origTransfererCallerIDName) - { + public void setOrigTransfererCallerIDName(String origTransfererCallerIDName) { this.origTransfererCallerIDName = origTransfererCallerIDName; } - public String getOrigTransfererConnectedLineNum() - { + public String getOrigTransfererConnectedLineNum() { return origTransfererConnectedLineNum; } - public void setOrigTransfererConnectedLineNum(String origTransfererConnectedLineNum) - { + public void setOrigTransfererConnectedLineNum(String origTransfererConnectedLineNum) { this.origTransfererConnectedLineNum = origTransfererConnectedLineNum; } - public String getOrigTransfererConnectedLineName() - { + public String getOrigTransfererConnectedLineName() { return origTransfererConnectedLineName; } - public void setOrigTransfererConnectedLineName(String origTransfererConnectedLineName) - { + public void setOrigTransfererConnectedLineName(String origTransfererConnectedLineName) { this.origTransfererConnectedLineName = origTransfererConnectedLineName; } - public String getOrigTransfererAccountCode() - { + public String getOrigTransfererAccountCode() { return origTransfererAccountCode; } - public void setOrigTransfererAccountCode(String origTransfererAccountCode) - { + public void setOrigTransfererAccountCode(String origTransfererAccountCode) { this.origTransfererAccountCode = origTransfererAccountCode; } - public String getOrigTransfererContext() - { + public String getOrigTransfererContext() { return origTransfererContext; } - public void setOrigTransfererContext(String origTransfererContext) - { + public void setOrigTransfererContext(String origTransfererContext) { this.origTransfererContext = origTransfererContext; } - public String getOrigTransfererExten() - { + public String getOrigTransfererExten() { return origTransfererExten; } - public void setOrigTransfererExten(String origTransfererExten) - { + public void setOrigTransfererExten(String origTransfererExten) { this.origTransfererExten = origTransfererExten; } - public String getOrigTransfererPriority() - { + public String getOrigTransfererPriority() { return origTransfererPriority; } - public void setOrigTransfererPriority(String origTransfererPriority) - { + public void setOrigTransfererPriority(String origTransfererPriority) { this.origTransfererPriority = origTransfererPriority; } - public String getOrigTransfererUniqueid() - { + public String getOrigTransfererUniqueid() { return origTransfererUniqueid; } - public void setOrigTransfererUniqueid(String origTransfererUniqueid) - { + public void setOrigTransfererUniqueid(String origTransfererUniqueid) { this.origTransfererUniqueid = origTransfererUniqueid; } - public String getOrigBridgeUniqueid() - { + public String getOrigBridgeUniqueid() { return origBridgeUniqueid; } - public void setOrigBridgeUniqueid(String origBridgeUniqueid) - { + public void setOrigBridgeUniqueid(String origBridgeUniqueid) { this.origBridgeUniqueid = origBridgeUniqueid; } - public String getOrigBridgeType() - { + public String getOrigBridgeType() { return origBridgeType; } - public void setOrigBridgeType(String origBridgeType) - { + public void setOrigBridgeType(String origBridgeType) { this.origBridgeType = origBridgeType; } - public String getOrigBridgeTechnology() - { + public String getOrigBridgeTechnology() { return origBridgeTechnology; } - public void setOrigBridgeTechnology(String origBridgeTechnology) - { + public void setOrigBridgeTechnology(String origBridgeTechnology) { this.origBridgeTechnology = origBridgeTechnology; } - public String getOrigBridgeCreator() - { + public String getOrigBridgeCreator() { return origBridgeCreator; } - public void setOrigBridgeCreator(String origBridgeCreator) - { + public void setOrigBridgeCreator(String origBridgeCreator) { this.origBridgeCreator = origBridgeCreator; } - public String getOrigBridgeName() - { + public String getOrigBridgeName() { return origBridgeName; } - public void setOrigBridgeName(String origBridgeName) - { + public void setOrigBridgeName(String origBridgeName) { this.origBridgeName = origBridgeName; } - public String getOrigBridgeNumChannels() - { + public String getOrigBridgeNumChannels() { return origBridgeNumChannels; } - public void setOrigBridgeNumChannels(String origBridgeNumChannels) - { + public void setOrigBridgeNumChannels(String origBridgeNumChannels) { this.origBridgeNumChannels = origBridgeNumChannels; } - public String getSecondTransfererChannel() - { + public String getSecondTransfererChannel() { return secondTransfererChannel; } - public void setSecondTransfererChannel(String secondTransfererChannel) - { + public void setSecondTransfererChannel(String secondTransfererChannel) { this.secondTransfererChannel = secondTransfererChannel; } - public String getSecondTransfererChannelState() - { + public String getSecondTransfererChannelState() { return secondTransfererChannelState; } - public void setSecondTransfererChannelState(String secondTransfererChannelState) - { + public void setSecondTransfererChannelState(String secondTransfererChannelState) { this.secondTransfererChannelState = secondTransfererChannelState; } - public String getSecondTransfererChannelStateDesc() - { + public String getSecondTransfererChannelStateDesc() { return secondTransfererChannelStateDesc; } - public void setSecondTransfererChannelStateDesc(String secondTransfererChannelStateDesc) - { + public void setSecondTransfererChannelStateDesc(String secondTransfererChannelStateDesc) { this.secondTransfererChannelStateDesc = secondTransfererChannelStateDesc; } - public String getSecondTransfererCallerIDNum() - { + public String getSecondTransfererCallerIDNum() { return secondTransfererCallerIDNum; } - public void setSecondTransfererCallerIDNum(String secondTransfererCallerIDNum) - { + public void setSecondTransfererCallerIDNum(String secondTransfererCallerIDNum) { this.secondTransfererCallerIDNum = secondTransfererCallerIDNum; } - public String getSecondTransfererCallerIDName() - { + public String getSecondTransfererCallerIDName() { return secondTransfererCallerIDName; } - public void setSecondTransfererCallerIDName(String secondTransfererCallerIDName) - { + public void setSecondTransfererCallerIDName(String secondTransfererCallerIDName) { this.secondTransfererCallerIDName = secondTransfererCallerIDName; } - public String getSecondTransfererConnectedLineNum() - { + public String getSecondTransfererConnectedLineNum() { return secondTransfererConnectedLineNum; } - public void setSecondTransfererConnectedLineNum(String secondTransfererConnectedLineNum) - { + public void setSecondTransfererConnectedLineNum(String secondTransfererConnectedLineNum) { this.secondTransfererConnectedLineNum = secondTransfererConnectedLineNum; } - public String getSecondTransfererConnectedLineName() - { + public String getSecondTransfererConnectedLineName() { return secondTransfererConnectedLineName; } - public void setSecondTransfererConnectedLineName(String secondTransfererConnectedLineName) - { + public void setSecondTransfererConnectedLineName(String secondTransfererConnectedLineName) { this.secondTransfererConnectedLineName = secondTransfererConnectedLineName; } - public String getSecondTransfererAccountCode() - { + public String getSecondTransfererAccountCode() { return secondTransfererAccountCode; } - public void setSecondTransfererAccountCode(String secondTransfererAccountCode) - { + public void setSecondTransfererAccountCode(String secondTransfererAccountCode) { this.secondTransfererAccountCode = secondTransfererAccountCode; } - public String getSecondTransfererContext() - { + public String getSecondTransfererContext() { return secondTransfererContext; } - public void setSecondTransfererContext(String secondTransfererContext) - { + public void setSecondTransfererContext(String secondTransfererContext) { this.secondTransfererContext = secondTransfererContext; } - public String getSecondTransfererExten() - { + public String getSecondTransfererExten() { return secondTransfererExten; } - public void setSecondTransfererExten(String secondTransfererExten) - { + public void setSecondTransfererExten(String secondTransfererExten) { this.secondTransfererExten = secondTransfererExten; } - public String getSecondTransfererPriority() - { + public String getSecondTransfererPriority() { return secondTransfererPriority; } - public void setSecondTransfererPriority(String secondTransfererPriority) - { + public void setSecondTransfererPriority(String secondTransfererPriority) { this.secondTransfererPriority = secondTransfererPriority; } - public String getSecondTransfererUniqueid() - { + public String getSecondTransfererUniqueid() { return secondTransfererUniqueid; } - public void setSecondTransfererUniqueid(String secondTransfererUniqueid) - { + public void setSecondTransfererUniqueid(String secondTransfererUniqueid) { this.secondTransfererUniqueid = secondTransfererUniqueid; } - public String getSecondBridgeUniqueid() - { + public String getSecondBridgeUniqueid() { return secondBridgeUniqueid; } - public void setSecondBridgeUniqueid(String secondBridgeUniqueid) - { + public void setSecondBridgeUniqueid(String secondBridgeUniqueid) { this.secondBridgeUniqueid = secondBridgeUniqueid; } - public String getSecondBridgeType() - { + public String getSecondBridgeType() { return secondBridgeType; } - public void setSecondBridgeType(String secondBridgeType) - { + public void setSecondBridgeType(String secondBridgeType) { this.secondBridgeType = secondBridgeType; } - public String getSecondBridgeTechnology() - { + public String getSecondBridgeTechnology() { return secondBridgeTechnology; } - public void setSecondBridgeTechnology(String secondBridgeTechnology) - { + public void setSecondBridgeTechnology(String secondBridgeTechnology) { this.secondBridgeTechnology = secondBridgeTechnology; } - public String getSecondBridgeCreator() - { + public String getSecondBridgeCreator() { return secondBridgeCreator; } - public void setSecondBridgeCreator(String secondBridgeCreator) - { + public void setSecondBridgeCreator(String secondBridgeCreator) { this.secondBridgeCreator = secondBridgeCreator; } - public String getSecondBridgeName() - { + public String getSecondBridgeName() { return secondBridgeName; } - public void setSecondBridgeName(String secondBridgeName) - { + public void setSecondBridgeName(String secondBridgeName) { this.secondBridgeName = secondBridgeName; } - public String getSecondBridgeNumChannels() - { + public String getSecondBridgeNumChannels() { return secondBridgeNumChannels; } - public void setSecondBridgeNumChannels(String secondBridgeNumChannels) - { + public void setSecondBridgeNumChannels(String secondBridgeNumChannels) { this.secondBridgeNumChannels = secondBridgeNumChannels; } - public String getDestType() - { + public String getDestType() { return destType; } - public void setDestType(String destType) - { + public void setDestType(String destType) { this.destType = destType; } - public String getDestBridgeUniqueid() - { + public String getDestBridgeUniqueid() { return destBridgeUniqueid; } - public void setDestBridgeUniqueid(String destBridgeUniqueid) - { + public void setDestBridgeUniqueid(String destBridgeUniqueid) { this.destBridgeUniqueid = destBridgeUniqueid; } - public String getDestApp() - { + public String getDestApp() { return destApp; } - public void setDestApp(String destApp) - { + public void setDestApp(String destApp) { this.destApp = destApp; } - public String getLocalOneChannel() - { + public String getLocalOneChannel() { return localOneChannel; } - public void setLocalOneChannel(String localOneChannel) - { + public void setLocalOneChannel(String localOneChannel) { this.localOneChannel = localOneChannel; } - public String getLocalOneChannelState() - { + public String getLocalOneChannelState() { return localOneChannelState; } - public void setLocalOneChannelState(String localOneChannelState) - { + public void setLocalOneChannelState(String localOneChannelState) { this.localOneChannelState = localOneChannelState; } - public String getLocalOneChannelStateDesc() - { + public String getLocalOneChannelStateDesc() { return localOneChannelStateDesc; } - public void setLocalOneChannelStateDesc(String localOneChannelStateDesc) - { + public void setLocalOneChannelStateDesc(String localOneChannelStateDesc) { this.localOneChannelStateDesc = localOneChannelStateDesc; } - public String getLocalOneCallerIDNum() - { + public String getLocalOneCallerIDNum() { return localOneCallerIDNum; } - public void setLocalOneCallerIDNum(String localOneCallerIDNum) - { + public void setLocalOneCallerIDNum(String localOneCallerIDNum) { this.localOneCallerIDNum = localOneCallerIDNum; } - public String getLocalOneCallerIDName() - { + public String getLocalOneCallerIDName() { return localOneCallerIDName; } - public void setLocalOneCallerIDName(String localOneCallerIDName) - { + public void setLocalOneCallerIDName(String localOneCallerIDName) { this.localOneCallerIDName = localOneCallerIDName; } - public String getLocalOneConnectedLineNum() - { + public String getLocalOneConnectedLineNum() { return localOneConnectedLineNum; } - public void setLocalOneConnectedLineNum(String localOneConnectedLineNum) - { + public void setLocalOneConnectedLineNum(String localOneConnectedLineNum) { this.localOneConnectedLineNum = localOneConnectedLineNum; } - public String getLocalOneConnectedLineName() - { + public String getLocalOneConnectedLineName() { return localOneConnectedLineName; } - public void setLocalOneConnectedLineName(String localOneConnectedLineName) - { + public void setLocalOneConnectedLineName(String localOneConnectedLineName) { this.localOneConnectedLineName = localOneConnectedLineName; } - public String getLocalOneAccountCode() - { + public String getLocalOneAccountCode() { return localOneAccountCode; } - public void setLocalOneAccountCode(String localOneAccountCode) - { + public void setLocalOneAccountCode(String localOneAccountCode) { this.localOneAccountCode = localOneAccountCode; } - public String getLocalOneContext() - { + public String getLocalOneContext() { return localOneContext; } - public void setLocalOneContext(String localOneContext) - { + public void setLocalOneContext(String localOneContext) { this.localOneContext = localOneContext; } - public String getLocalOneExten() - { + public String getLocalOneExten() { return localOneExten; } - public void setLocalOneExten(String localOneExten) - { + public void setLocalOneExten(String localOneExten) { this.localOneExten = localOneExten; } - public String getLocalOnePriority() - { + public String getLocalOnePriority() { return localOnePriority; } - public void setLocalOnePriority(String localOnePriority) - { + public void setLocalOnePriority(String localOnePriority) { this.localOnePriority = localOnePriority; } - public String getLocalOneUniqueid() - { + public String getLocalOneUniqueid() { return localOneUniqueid; } - public void setLocalOneUniqueid(String localOneUniqueid) - { + public void setLocalOneUniqueid(String localOneUniqueid) { this.localOneUniqueid = localOneUniqueid; } - public String getLocalTwoChannel() - { + public String getLocalTwoChannel() { return localTwoChannel; } - public void setLocalTwoChannel(String localTwoChannel) - { + public void setLocalTwoChannel(String localTwoChannel) { this.localTwoChannel = localTwoChannel; } - public String getLocalTwoChannelState() - { + public String getLocalTwoChannelState() { return localTwoChannelState; } - public void setLocalTwoChannelState(String localTwoChannelState) - { + public void setLocalTwoChannelState(String localTwoChannelState) { this.localTwoChannelState = localTwoChannelState; } - public String getLocalTwoChannelStateDesc() - { + public String getLocalTwoChannelStateDesc() { return localTwoChannelStateDesc; } - public void setLocalTwoChannelStateDesc(String localTwoChannelStateDesc) - { + public void setLocalTwoChannelStateDesc(String localTwoChannelStateDesc) { this.localTwoChannelStateDesc = localTwoChannelStateDesc; } - public String getLocalTwoCallerIDNum() - { + public String getLocalTwoCallerIDNum() { return localTwoCallerIDNum; } - public void setLocalTwoCallerIDNum(String localTwoCallerIDNum) - { + public void setLocalTwoCallerIDNum(String localTwoCallerIDNum) { this.localTwoCallerIDNum = localTwoCallerIDNum; } - public String getLocalTwoCallerIDName() - { + public String getLocalTwoCallerIDName() { return localTwoCallerIDName; } - public void setLocalTwoCallerIDName(String localTwoCallerIDName) - { + public void setLocalTwoCallerIDName(String localTwoCallerIDName) { this.localTwoCallerIDName = localTwoCallerIDName; } - public String getLocalTwoConnectedLineNum() - { + public String getLocalTwoConnectedLineNum() { return localTwoConnectedLineNum; } - public void setLocalTwoConnectedLineNum(String localTwoConnectedLineNum) - { + public void setLocalTwoConnectedLineNum(String localTwoConnectedLineNum) { this.localTwoConnectedLineNum = localTwoConnectedLineNum; } - public String getLocalTwoConnectedLineName() - { + public String getLocalTwoConnectedLineName() { return localTwoConnectedLineName; } - public void setLocalTwoConnectedLineName(String localTwoConnectedLineName) - { + public void setLocalTwoConnectedLineName(String localTwoConnectedLineName) { this.localTwoConnectedLineName = localTwoConnectedLineName; } - public String getLocalTwoAccountCode() - { + public String getLocalTwoAccountCode() { return localTwoAccountCode; } - public void setLocalTwoAccountCode(String localTwoAccountCode) - { + public void setLocalTwoAccountCode(String localTwoAccountCode) { this.localTwoAccountCode = localTwoAccountCode; } - public String getLocalTwoContext() - { + public String getLocalTwoContext() { return localTwoContext; } - public void setLocalTwoContext(String localTwoContext) - { + public void setLocalTwoContext(String localTwoContext) { this.localTwoContext = localTwoContext; } - public String getLocalTwoExten() - { + public String getLocalTwoExten() { return localTwoExten; } - public void setLocalTwoExten(String localTwoExten) - { + public void setLocalTwoExten(String localTwoExten) { this.localTwoExten = localTwoExten; } - public String getLocalTwoPriority() - { + public String getLocalTwoPriority() { return localTwoPriority; } - public void setLocalTwoPriority(String localTwoPriority) - { + public void setLocalTwoPriority(String localTwoPriority) { this.localTwoPriority = localTwoPriority; } - public String getLocalTwoUniqueid() - { + public String getLocalTwoUniqueid() { return localTwoUniqueid; } - public void setLocalTwoUniqueid(String localTwoUniqueid) - { + public void setLocalTwoUniqueid(String localTwoUniqueid) { this.localTwoUniqueid = localTwoUniqueid; } - public String getDestTransfererChannel() - { + public String getDestTransfererChannel() { return destTransfererChannel; } - public void setDestTransfererChannel(String destTransfererChannel) - { + public void setDestTransfererChannel(String destTransfererChannel) { this.destTransfererChannel = destTransfererChannel; } - public String getTransfereeChannel() - { + public String getTransfereeChannel() { return transfereeChannel; } - public void setTransfereeChannel(String transfereeChannel) - { + public void setTransfereeChannel(String transfereeChannel) { this.transfereeChannel = transfereeChannel; } - public String getTransfereeChannelState() - { + public String getTransfereeChannelState() { return transfereeChannelState; } - public void setTransfereeChannelState(String transfereeChannelState) - { + public void setTransfereeChannelState(String transfereeChannelState) { this.transfereeChannelState = transfereeChannelState; } - public String getTransfereeChannelStateDesc() - { + public String getTransfereeChannelStateDesc() { return transfereeChannelStateDesc; } - public void setTransfereeChannelStateDesc(String transfereeChannelStateDesc) - { + public void setTransfereeChannelStateDesc(String transfereeChannelStateDesc) { this.transfereeChannelStateDesc = transfereeChannelStateDesc; } - public String getTransfereeCallerIDNum() - { + public String getTransfereeCallerIDNum() { return transfereeCallerIDNum; } - public void setTransfereeCallerIDNum(String transfereeCallerIDNum) - { + public void setTransfereeCallerIDNum(String transfereeCallerIDNum) { this.transfereeCallerIDNum = transfereeCallerIDNum; } - public String getTransfereeCallerIDName() - { + public String getTransfereeCallerIDName() { return transfereeCallerIDName; } - public void setTransfereeCallerIDName(String transfereeCallerIDName) - { + public void setTransfereeCallerIDName(String transfereeCallerIDName) { this.transfereeCallerIDName = transfereeCallerIDName; } - public String getTransfereeConnectedLineNum() - { + public String getTransfereeConnectedLineNum() { return transfereeConnectedLineNum; } - public void setTransfereeConnectedLineNum(String transfereeConnectedLineNum) - { + public void setTransfereeConnectedLineNum(String transfereeConnectedLineNum) { this.transfereeConnectedLineNum = transfereeConnectedLineNum; } - public String getTransfereeConnectedLineName() - { + public String getTransfereeConnectedLineName() { return transfereeConnectedLineName; } - public void setTransfereeConnectedLineName(String transfereeConnectedLineName) - { + public void setTransfereeConnectedLineName(String transfereeConnectedLineName) { this.transfereeConnectedLineName = transfereeConnectedLineName; } - public String getTransfereeAccountCode() - { + public String getTransfereeAccountCode() { return transfereeAccountCode; } - public void setTransfereeAccountCode(String transfereeAccountCode) - { + public void setTransfereeAccountCode(String transfereeAccountCode) { this.transfereeAccountCode = transfereeAccountCode; } - public String getTransfereeContext() - { + public String getTransfereeContext() { return transfereeContext; } - public void setTransfereeContext(String transfereeContext) - { + public void setTransfereeContext(String transfereeContext) { this.transfereeContext = transfereeContext; } - public String getTransfereeExten() - { + public String getTransfereeExten() { return transfereeExten; } - public void setTransfereeExten(String transfereeExten) - { + public void setTransfereeExten(String transfereeExten) { this.transfereeExten = transfereeExten; } - public String getTransfereePriority() - { + public String getTransfereePriority() { return transfereePriority; } - public void setTransfereePriority(String transfereePriority) - { + public void setTransfereePriority(String transfereePriority) { this.transfereePriority = transfereePriority; } - public String getTransfereeUniqueid() - { + public String getTransfereeUniqueid() { return transfereeUniqueid; } - public void setTransfereeUniqueid(String transfereeUniqueid) - { + public void setTransfereeUniqueid(String transfereeUniqueid) { this.transfereeUniqueid = transfereeUniqueid; } - public String getTransfereeLinkedId() - { + public String getTransfereeLinkedId() { return transfereeLinkedId; } - public void setTransfereeLinkedId(String transfereeLinkedId) - { + public void setTransfereeLinkedId(String transfereeLinkedId) { this.transfereeLinkedId = transfereeLinkedId; } - public String getTransfereeLanguage() - { + public String getTransfereeLanguage() { return transfereeLanguage; } - public void setTransfereeLanguage(String transfereeLanguage) - { + public void setTransfereeLanguage(String transfereeLanguage) { this.transfereeLanguage = transfereeLanguage; } - public String getOrigTransfererLinkedId() - { + public String getOrigTransfererLinkedId() { return origTransfererLinkedId; } - public void setOrigTransfererLinkedId(String origTransfererLinkedId) - { + public void setOrigTransfererLinkedId(String origTransfererLinkedId) { this.origTransfererLinkedId = origTransfererLinkedId; } - public String getSecondTransfererLanguage() - { + public String getSecondTransfererLanguage() { return secondTransfererLanguage; } - public void setSecondTransfererLanguage(String secondTransfererLanguage) - { + public void setSecondTransfererLanguage(String secondTransfererLanguage) { this.secondTransfererLanguage = secondTransfererLanguage; } - public String getIsexternal() - { + public String getIsexternal() { return isexternal; } - public void setIsexternal(String isexternal) - { + public void setIsexternal(String isexternal) { this.isexternal = isexternal; } - public String getResult() - { + public String getResult() { return result; } - public void setResult(String result) - { + public void setResult(String result) { this.result = result; } - public String getSecondTransfererLinkedId() - { + public String getSecondTransfererLinkedId() { return secondTransfererLinkedId; } - public void setSecondTransfererLinkedId(String secondTransfererLinkedId) - { + public void setSecondTransfererLinkedId(String secondTransfererLinkedId) { this.secondTransfererLinkedId = secondTransfererLinkedId; } - public String getOrigTransfererLanguage() - { + public String getOrigTransfererLanguage() { return origTransfererLanguage; } - public void setOrigTransfererLanguage(String origTransfererLanguage) - { + public void setOrigTransfererLanguage(String origTransfererLanguage) { this.origTransfererLanguage = origTransfererLanguage; } - public String getTransferTargetUniqueID() - { + public String getTransferTargetUniqueID() { return transferTargetUniqueID; } - public void setTransferTargetUniqueID(String transferTargetUniqueID) - { + public void setTransferTargetUniqueID(String transferTargetUniqueID) { this.transferTargetUniqueID = transferTargetUniqueID; } - public String getTransferTargetCallerIDName() - { + public String getTransferTargetCallerIDName() { return transferTargetCallerIDName; } - public void setTransferTargetCallerIDName(String transferTargetCallerIDName) - { + public void setTransferTargetCallerIDName(String transferTargetCallerIDName) { this.transferTargetCallerIDName = transferTargetCallerIDName; } - public String getSecondBridgeVideoSourceMode() - { + public String getSecondBridgeVideoSourceMode() { return secondBridgeVideoSourceMode; } - public void setSecondBridgeVideoSourceMode(String secondBridgeVideoSourceMode) - { + public void setSecondBridgeVideoSourceMode(String secondBridgeVideoSourceMode) { this.secondBridgeVideoSourceMode = secondBridgeVideoSourceMode; } - public String getTransferTargetLinkedID() - { + public String getTransferTargetLinkedID() { return transferTargetLinkedID; } - public void setTransferTargetLinkedID(String transferTargetLinkedID) - { + public void setTransferTargetLinkedID(String transferTargetLinkedID) { this.transferTargetLinkedID = transferTargetLinkedID; } - public String getTransferTargetPriority() - { + public String getTransferTargetPriority() { return transferTargetPriority; } - public void setTransferTargetPriority(String transferTargetPriority) - { + public void setTransferTargetPriority(String transferTargetPriority) { this.transferTargetPriority = transferTargetPriority; } - public String getTransferTargetCallerIDNum() - { + public String getTransferTargetCallerIDNum() { return transferTargetCallerIDNum; } - public void setTransferTargetCallerIDNum(String transferTargetCallerIDNum) - { + public void setTransferTargetCallerIDNum(String transferTargetCallerIDNum) { this.transferTargetCallerIDNum = transferTargetCallerIDNum; } - public String getOrigBridgeVideoSourceMode() - { + public String getOrigBridgeVideoSourceMode() { return origBridgeVideoSourceMode; } - public void setOrigBridgeVideoSourceMode(String origBridgeVideoSourceMode) - { + public void setOrigBridgeVideoSourceMode(String origBridgeVideoSourceMode) { this.origBridgeVideoSourceMode = origBridgeVideoSourceMode; } - public String getTransferTargetConnectedLineNum() - { + public String getTransferTargetConnectedLineNum() { return transferTargetConnectedLineNum; } - public void setTransferTargetConnectedLineNum(String transferTargetConnectedLineNum) - { + public void setTransferTargetConnectedLineNum(String transferTargetConnectedLineNum) { this.transferTargetConnectedLineNum = transferTargetConnectedLineNum; } - public String getTransferTargetChannel() - { + public String getTransferTargetChannel() { return transferTargetChannel; } - public void setTransferTargetChannel(String transferTargetChannel) - { + public void setTransferTargetChannel(String transferTargetChannel) { this.transferTargetChannel = transferTargetChannel; } - public String getTransferTargetContext() - { + public String getTransferTargetContext() { return transferTargetContext; } - public void setTransferTargetContext(String transferTargetContext) - { + public void setTransferTargetContext(String transferTargetContext) { this.transferTargetContext = transferTargetContext; } - public String getTransferTargetConnectedLineName() - { + public String getTransferTargetConnectedLineName() { return transferTargetConnectedLineName; } - public void setTransferTargetConnectedLineName(String transferTargetConnectedLineName) - { + public void setTransferTargetConnectedLineName(String transferTargetConnectedLineName) { this.transferTargetConnectedLineName = transferTargetConnectedLineName; } - public String getTransferTargetExten() - { + public String getTransferTargetExten() { return transferTargetExten; } - public void setTransferTargetExten(String transferTargetExten) - { + public void setTransferTargetExten(String transferTargetExten) { this.transferTargetExten = transferTargetExten; } - public String getTransferTargetChannelState() - { + public String getTransferTargetChannelState() { return transferTargetChannelState; } - public void setTransferTargetChannelState(String transferTargetChannelState) - { + public void setTransferTargetChannelState(String transferTargetChannelState) { this.transferTargetChannelState = transferTargetChannelState; } - public String getTransferTargetLanguage() - { + public String getTransferTargetLanguage() { return transferTargetLanguage; } - public void setTransferTargetLanguage(String transferTargetLanguage) - { + public void setTransferTargetLanguage(String transferTargetLanguage) { this.transferTargetLanguage = transferTargetLanguage; } - public String getTransferTargetAccountCode() - { + public String getTransferTargetAccountCode() { return transferTargetAccountCode; } - public void setTransferTargetAccountCode(String transferTargetAccountCode) - { + public void setTransferTargetAccountCode(String transferTargetAccountCode) { this.transferTargetAccountCode = transferTargetAccountCode; } - public String getTransferTargetChannelStateDesc() - { + public String getTransferTargetChannelStateDesc() { return transferTargetChannelStateDesc; } - public void setTransferTargetChannelStateDesc(String transferTargetChannelStateDesc) - { + public void setTransferTargetChannelStateDesc(String transferTargetChannelStateDesc) { this.transferTargetChannelStateDesc = transferTargetChannelStateDesc; } diff --git a/src/main/java/org/asteriskjava/manager/event/AuthDetail.java b/src/main/java/org/asteriskjava/manager/event/AuthDetail.java index fd0c174ad..b9cf5cb66 100644 --- a/src/main/java/org/asteriskjava/manager/event/AuthDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/AuthDetail.java @@ -14,108 +14,105 @@ public class AuthDetail extends ResponseEvent { - /** + /** * Serial version identifier. */ - private static final long serialVersionUID = -4998727723768836212L; + private static final long serialVersionUID = -4998727723768836212L; - private String event; - private String objectType; - private String objectName; - private String username; - private String password; - private String md5Cred; - private String realm; - private int nonceLifetime; - private String authType; - private String EndpointName; + private String event; + private String objectType; + private String objectName; + private String username; + private String password; + private String md5Cred; + private String realm; + private int nonceLifetime; + private String authType; + private String EndpointName; - public AuthDetail(Object source) { - super(source); - } + public AuthDetail(Object source) { + super(source); + } - public String getEvent() { - return event; - } + public String getEvent() { + return event; + } - public void setEvent(String event) { - this.event = event; - } + public void setEvent(String event) { + this.event = event; + } - public String getObjectType() { - return objectType; - } + public String getObjectType() { + return objectType; + } - public void setObjectType(String objectType) { - this.objectType = objectType; - } + public void setObjectType(String objectType) { + this.objectType = objectType; + } - public String getObjectName() { - return objectName; - } + public String getObjectName() { + return objectName; + } - public void setObjectName(String objectName) { - this.objectName = objectName; - } + public void setObjectName(String objectName) { + this.objectName = objectName; + } - public String getUsername() { - return username; - } + public String getUsername() { + return username; + } - public void setUsername(String username) { - this.username = username; - } + public void setUsername(String username) { + this.username = username; + } - public String getPassword() { - return password; - } + public String getPassword() { + return password; + } - public void setPassword(String password) { - this.password = password; - } + public void setPassword(String password) { + this.password = password; + } - public String getMd5Cred() { - return md5Cred; - } + public String getMd5Cred() { + return md5Cred; + } - public void setMd5Cred(String md5Cred) { - this.md5Cred = md5Cred; - } + public void setMd5Cred(String md5Cred) { + this.md5Cred = md5Cred; + } - public String getRealm() { - return realm; - } + public String getRealm() { + return realm; + } - public void setRealm(String realm) { - this.realm = realm; - } + public void setRealm(String realm) { + this.realm = realm; + } - public int getNonceLifetime() { - return nonceLifetime; - } + public int getNonceLifetime() { + return nonceLifetime; + } - public void setNonceLifetime(int nonceLifetime) { - this.nonceLifetime = nonceLifetime; - } + public void setNonceLifetime(int nonceLifetime) { + this.nonceLifetime = nonceLifetime; + } - public String getAuthType() { - return authType; - } + public String getAuthType() { + return authType; + } - public void setAuthType(String authType) { - this.authType = authType; - } + public void setAuthType(String authType) { + this.authType = authType; + } - public String getEndpointName() { - return EndpointName; - } + public String getEndpointName() { + return EndpointName; + } - public void setEndpointName(String endpointName) { - EndpointName = endpointName; - } + public void setEndpointName(String endpointName) { + EndpointName = endpointName; + } - - - } diff --git a/src/main/java/org/asteriskjava/manager/event/BlindTransferEvent.java b/src/main/java/org/asteriskjava/manager/event/BlindTransferEvent.java index c5da2e206..2375944ed 100644 --- a/src/main/java/org/asteriskjava/manager/event/BlindTransferEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BlindTransferEvent.java @@ -3,10 +3,9 @@ /** * Created by Alexander Polakov on 1/26/15. */ -public class BlindTransferEvent extends AbstractBridgeEvent -{ +public class BlindTransferEvent extends AbstractBridgeEvent { /** - * + * */ private static final long serialVersionUID = 1L; private String transfererUniqueId; @@ -44,318 +43,255 @@ public class BlindTransferEvent extends AbstractBridgeEvent private String transfereeLanguage; private String transfereeaccountcode; - public BlindTransferEvent(Object source) - { + public BlindTransferEvent(Object source) { super(source); } - public String getTransfererUniqueId() - { + public String getTransfererUniqueId() { return transfererUniqueId; } - public void setTransfererUniqueId(String transfererUniqueId) - { + public void setTransfererUniqueId(String transfererUniqueId) { this.transfererUniqueId = transfererUniqueId; } - public String getTransfererConnectedLineNum() - { + public String getTransfererConnectedLineNum() { return transfererConnectedLineNum; } - public void setTransfererConnectedLineNum(String transfererConnectedLineNum) - { + public void setTransfererConnectedLineNum(String transfererConnectedLineNum) { this.transfererConnectedLineNum = transfererConnectedLineNum; } - public String getTransfererConnectedLineName() - { + public String getTransfererConnectedLineName() { return transfererConnectedLineName; } - public void setTransfererConnectedLineName(String transfererConnectedLineName) - { + public void setTransfererConnectedLineName(String transfererConnectedLineName) { this.transfererConnectedLineName = transfererConnectedLineName; } - public String getTransfererCallerIdName() - { + public String getTransfererCallerIdName() { return transfererCallerIdName; } - public void setTransfererCallerIdName(String transfererCallerIdName) - { + public void setTransfererCallerIdName(String transfererCallerIdName) { this.transfererCallerIdName = transfererCallerIdName; } - public String getTransfererCallerIdNum() - { + public String getTransfererCallerIdNum() { return transfererCallerIdNum; } - public void setTransfererCallerIdNum(String transfererCallerIdNum) - { + public void setTransfererCallerIdNum(String transfererCallerIdNum) { this.transfererCallerIdNum = transfererCallerIdNum; } - public String getTransfererChannel() - { + public String getTransfererChannel() { return transfererChannel; } - public void setTransfererChannel(String transfererChannel) - { + public void setTransfererChannel(String transfererChannel) { this.transfererChannel = transfererChannel; } - public String getTransfererChannelState() - { + public String getTransfererChannelState() { return transfererChannelState; } - public void setTransfererChannelState(String transfererChannelState) - { + public void setTransfererChannelState(String transfererChannelState) { this.transfererChannelState = transfererChannelState; } - public String getTransfererChannelStateDesc() - { + public String getTransfererChannelStateDesc() { return transfererChannelStateDesc; } - public void setTransfererChannelStateDesc(String transfererChannelStateDesc) - { + public void setTransfererChannelStateDesc(String transfererChannelStateDesc) { this.transfererChannelStateDesc = transfererChannelStateDesc; } - public Integer getTransfererPriority() - { + public Integer getTransfererPriority() { return transfererPriority; } - public void setTransfererPriority(Integer transfererPriority) - { + public void setTransfererPriority(Integer transfererPriority) { this.transfererPriority = transfererPriority; } - public String getTransfererContext() - { + public String getTransfererContext() { return transfererContext; } - public void setTransfererContext(String transfererContext) - { + public void setTransfererContext(String transfererContext) { this.transfererContext = transfererContext; } - public String getTransfereeUniqueId() - { + public String getTransfereeUniqueId() { return transfereeUniqueId; } - public void setTransfereeUniqueId(String transfereeUniqueId) - { + public void setTransfereeUniqueId(String transfereeUniqueId) { this.transfereeUniqueId = transfereeUniqueId; } - public String getTransfereeConnectedLineNum() - { + public String getTransfereeConnectedLineNum() { return transfereeConnectedLineNum; } - public void setTransfereeConnectedLineNum(String transfereeConnectedLineNum) - { + public void setTransfereeConnectedLineNum(String transfereeConnectedLineNum) { this.transfereeConnectedLineNum = transfereeConnectedLineNum; } - public String getTransfereeConnectedLineName() - { + public String getTransfereeConnectedLineName() { return transfereeConnectedLineName; } - public void setTransfereeConnectedLineName(String transfereeConnectedLineName) - { + public void setTransfereeConnectedLineName(String transfereeConnectedLineName) { this.transfereeConnectedLineName = transfereeConnectedLineName; } - public String getTransfereeCallerIdName() - { + public String getTransfereeCallerIdName() { return transfereeCallerIdName; } - public void setTransfereeCallerIdName(String transfereeCallerIdName) - { + public void setTransfereeCallerIdName(String transfereeCallerIdName) { this.transfereeCallerIdName = transfereeCallerIdName; } - public String getTransfereeCallerIdNum() - { + public String getTransfereeCallerIdNum() { return transfereeCallerIdNum; } - public void setTransfereeCallerIdNum(String transfereeCallerIdNum) - { + public void setTransfereeCallerIdNum(String transfereeCallerIdNum) { this.transfereeCallerIdNum = transfereeCallerIdNum; } - public String getTransfereeChannel() - { + public String getTransfereeChannel() { return transfereeChannel; } - public void setTransfereeChannel(String transfereeChannel) - { + public void setTransfereeChannel(String transfereeChannel) { this.transfereeChannel = transfereeChannel; } - public String getTransfereeChannelState() - { + public String getTransfereeChannelState() { return transfereeChannelState; } - public void setTransfereeChannelState(String transfereeChannelState) - { + public void setTransfereeChannelState(String transfereeChannelState) { this.transfereeChannelState = transfereeChannelState; } - public String getTransfereeChannelStateDesc() - { + public String getTransfereeChannelStateDesc() { return transfereeChannelStateDesc; } - public void setTransfereeChannelStateDesc(String transfereeChannelStateDesc) - { + public void setTransfereeChannelStateDesc(String transfereeChannelStateDesc) { this.transfereeChannelStateDesc = transfereeChannelStateDesc; } - public Integer getTransfereePriority() - { + public Integer getTransfereePriority() { return transfereePriority; } - public void setTransfereePriority(Integer transfereePriority) - { + public void setTransfereePriority(Integer transfereePriority) { this.transfereePriority = transfereePriority; } - public String getTransfereeContext() - { + public String getTransfereeContext() { return transfereeContext; } - public void setTransfereeContext(String transfereeContext) - { + public void setTransfereeContext(String transfereeContext) { this.transfereeContext = transfereeContext; } - public String getExtension() - { + public String getExtension() { return extension; } - public void setExtension(String extension) - { + public void setExtension(String extension) { this.extension = extension; } - public String getIsexternal() - { + public String getIsexternal() { return isexternal; } - public void setIsexternal(String isexternal) - { + public void setIsexternal(String isexternal) { this.isexternal = isexternal; } - public String getResult() - { + public String getResult() { return result; } - public void setResult(String result) - { + public void setResult(String result) { this.result = result; } - public String getTransfereeExten() - { + public String getTransfereeExten() { return transfereeExten; } - public void setTransfereeExten(String transfereeExten) - { + public void setTransfereeExten(String transfereeExten) { this.transfereeExten = transfereeExten; } - public String getTransfereeLinkedId() - { + public String getTransfereeLinkedId() { return transfereeLinkedId; } - public void setTransfereeLinkedId(String transfereeLinkedId) - { + public void setTransfereeLinkedId(String transfereeLinkedId) { this.transfereeLinkedId = transfereeLinkedId; } - public String getTransfererAccountCode() - { + public String getTransfererAccountCode() { return transfererAccountCode; } - public void setTransfererAccountCode(String transfererAccountCode) - { + public void setTransfererAccountCode(String transfererAccountCode) { this.transfererAccountCode = transfererAccountCode; } - public String getTransfererExten() - { + public String getTransfererExten() { return transfererExten; } - public void setTransfererExten(String transfererExten) - { + public void setTransfererExten(String transfererExten) { this.transfererExten = transfererExten; } - public String getTransfererLanguage() - { + public String getTransfererLanguage() { return transfererLanguage; } - public void setTransfererLanguage(String transfererLanguage) - { + public void setTransfererLanguage(String transfererLanguage) { this.transfererLanguage = transfererLanguage; } - public String getTransfererLinkedId() - { + public String getTransfererLinkedId() { return transfererLinkedId; } - public void setTransfererLinkedId(String transfererLinkedId) - { + public void setTransfererLinkedId(String transfererLinkedId) { this.transfererLinkedId = transfererLinkedId; } - public String getTransfereeLanguage() - { + public String getTransfereeLanguage() { return transfereeLanguage; } - public void setTransfereeLanguage(String transfereeLanguage) - { + public void setTransfereeLanguage(String transfereeLanguage) { this.transfereeLanguage = transfereeLanguage; } - public void setTransfereeaccountcode(String transfereeaccountcode) - { + public void setTransfereeaccountcode(String transfereeaccountcode) { this.transfereeaccountcode = transfereeaccountcode; } - public String getTransfereeaccountcode() - { + public String getTransfereeaccountcode() { return transfereeaccountcode; } diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeCreateEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeCreateEvent.java index 89ad67840..b6ada6b54 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeCreateEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeCreateEvent.java @@ -3,30 +3,28 @@ /** * Created by Alexander Polakov on 1/26/15. */ -public class BridgeCreateEvent extends AbstractBridgeEvent -{ - private String bridgevideosourcemode; +public class BridgeCreateEvent extends AbstractBridgeEvent { + private String bridgevideosourcemode; - /** - * @param bridgevideosourcemode the bridgevideosourcemode to set - */ - public void setBridgevideosourcemode(String bridgevideosourcemode) { - this.bridgevideosourcemode = bridgevideosourcemode; - } + /** + * @param bridgevideosourcemode the bridgevideosourcemode to set + */ + public void setBridgevideosourcemode(String bridgevideosourcemode) { + this.bridgevideosourcemode = bridgevideosourcemode; + } - /** - * @return the bridgevideosourcemode - */ - public String getBridgevideosourcemode() { - return bridgevideosourcemode; - } + /** + * @return the bridgevideosourcemode + */ + public String getBridgevideosourcemode() { + return bridgevideosourcemode; + } - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; + + public BridgeCreateEvent(Object source) { + super(source); + } - public BridgeCreateEvent(Object source) - { - super(source); - } - } diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeDestroyEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeDestroyEvent.java index c7de172e2..06c2d0a9d 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeDestroyEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeDestroyEvent.java @@ -3,15 +3,13 @@ /** * Created by Alexander Polakov on 1/26/15. */ -public class BridgeDestroyEvent extends AbstractBridgeEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; +public class BridgeDestroyEvent extends AbstractBridgeEvent { + /** + * + */ + private static final long serialVersionUID = 1L; - public BridgeDestroyEvent(Object source) - { - super(source); - } + public BridgeDestroyEvent(Object source) { + super(source); + } } diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeEnterEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeEnterEvent.java index 6128aff73..6596eaae2 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeEnterEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeEnterEvent.java @@ -3,10 +3,9 @@ /** * Created by Alexander Polakov on 1/26/15. */ -public class BridgeEnterEvent extends AbstractBridgeEvent -{ +public class BridgeEnterEvent extends AbstractBridgeEvent { /** - * + * */ private static final long serialVersionUID = 2L; private String uniqueId; @@ -16,58 +15,47 @@ public class BridgeEnterEvent extends AbstractBridgeEvent private String swapuniqueid; - public BridgeEnterEvent(Object source) - { + public BridgeEnterEvent(Object source) { super(source); } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getSwapuniqueid() - { + public String getSwapuniqueid() { return swapuniqueid; } - public void setSwapuniqueid(String swapuniqueid) - { + public void setSwapuniqueid(String swapuniqueid) { this.swapuniqueid = swapuniqueid; } diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeEvent.java index 872e6b9d9..c9067c4d9 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeEvent.java @@ -29,8 +29,7 @@ * @author srt * @version $Id$ */ -public class BridgeEvent extends ManagerEvent -{ +public class BridgeEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -68,8 +67,7 @@ public class BridgeEvent extends ManagerEvent private String callerId1; private String callerId2; - public BridgeEvent(Object source) - { + public BridgeEvent(Object source) { super(source); } @@ -81,8 +79,7 @@ public BridgeEvent(Object source) * @see #BRIDGE_STATE_UNLINK * @since 1.0.0 */ - public String getBridgeState() - { + public String getBridgeState() { return bridgeState; } @@ -92,8 +89,7 @@ public String getBridgeState() * @param bridgeState "Link" if the two channels have been linked, "Unlink" if they have been unlinked. * @since 1.0.0 */ - public void setBridgeState(String bridgeState) - { + public void setBridgeState(String bridgeState) { this.bridgeState = bridgeState; } @@ -108,8 +104,7 @@ public void setBridgeState(String bridgeState) * @see #BRIDGE_TYPE_RTP_REMOTE * @since 1.0.0 */ - public String getBridgeType() - { + public String getBridgeType() { return bridgeType; } @@ -119,8 +114,7 @@ public String getBridgeType() * @param bridgeType the bridge type. * @since 1.0.0 */ - public void setBridgeType(String bridgeType) - { + public void setBridgeType(String bridgeType) { this.bridgeType = bridgeType; } @@ -129,8 +123,7 @@ public void setBridgeType(String bridgeType) * * @return the unique id of the first channel. */ - public String getUniqueId1() - { + public String getUniqueId1() { return uniqueId1; } @@ -139,8 +132,7 @@ public String getUniqueId1() * * @param uniqueId1 the unique id of the first channel. */ - public void setUniqueId1(String uniqueId1) - { + public void setUniqueId1(String uniqueId1) { this.uniqueId1 = uniqueId1; } @@ -149,8 +141,7 @@ public void setUniqueId1(String uniqueId1) * * @return the unique id of the second channel. */ - public String getUniqueId2() - { + public String getUniqueId2() { return uniqueId2; } @@ -159,8 +150,7 @@ public String getUniqueId2() * * @param uniqueId2 the unique id of the second channel. */ - public void setUniqueId2(String uniqueId2) - { + public void setUniqueId2(String uniqueId2) { this.uniqueId2 = uniqueId2; } @@ -169,8 +159,7 @@ public void setUniqueId2(String uniqueId2) * * @return the name of the first channel. */ - public String getChannel1() - { + public String getChannel1() { return channel1; } @@ -179,8 +168,7 @@ public String getChannel1() * * @param channel1 the name of the first channel. */ - public void setChannel1(String channel1) - { + public void setChannel1(String channel1) { this.channel1 = channel1; } @@ -189,8 +177,7 @@ public void setChannel1(String channel1) * * @return the name of the second channel. */ - public String getChannel2() - { + public String getChannel2() { return channel2; } @@ -199,8 +186,7 @@ public String getChannel2() * * @param channel2 the name of the second channel. */ - public void setChannel2(String channel2) - { + public void setChannel2(String channel2) { this.channel2 = channel2; } @@ -210,8 +196,7 @@ public void setChannel2(String channel2) * @return the Caller*Id number of the first channel. * @since 0.2 */ - public String getCallerId1() - { + public String getCallerId1() { return callerId1; } @@ -221,8 +206,7 @@ public String getCallerId1() * @param callerId1 the Caller*Id number of the first channel. * @since 0.2 */ - public void setCallerId1(String callerId1) - { + public void setCallerId1(String callerId1) { this.callerId1 = callerId1; } @@ -232,8 +216,7 @@ public void setCallerId1(String callerId1) * @return the Caller*Id number of the second channel. * @since 0.2 */ - public String getCallerId2() - { + public String getCallerId2() { return callerId2; } @@ -243,8 +226,7 @@ public String getCallerId2() * @param callerId2 the Caller*Id number of the second channel. * @since 0.2 */ - public void setCallerId2(String callerId2) - { + public void setCallerId2(String callerId2) { this.callerId2 = callerId2; } @@ -254,8 +236,7 @@ public void setCallerId2(String callerId2) * @return true the two channels have been linked, false if they have been unlinked. * @since 1.0.0 */ - public boolean isLink() - { + public boolean isLink() { return BRIDGE_STATE_LINK.equalsIgnoreCase(bridgeState); } @@ -265,8 +246,7 @@ public boolean isLink() * @return true the two channels have been unlinked, false if they have been linked. * @since 1.0.0 */ - public boolean isUnlink() - { + public boolean isUnlink() { return BRIDGE_STATE_UNLINK.equalsIgnoreCase(bridgeState); } } diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeExecEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeExecEvent.java index 2e1c1a1ba..b6b316c4d 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeExecEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeExecEvent.java @@ -25,8 +25,7 @@ * @version $Id$ * @since 1.0.0 */ -public class BridgeExecEvent extends ManagerEvent -{ +public class BridgeExecEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -40,8 +39,7 @@ public class BridgeExecEvent extends ManagerEvent private String channel1; private String channel2; - public BridgeExecEvent(Object source) - { + public BridgeExecEvent(Object source) { super(source); } @@ -56,13 +54,11 @@ public BridgeExecEvent(Object source) * @see #RESPONSE_FAILED * @see #RESPONSE_SUCCESS */ - public String getResponse() - { + public String getResponse() { return response; } - public void setResponse(String response) - { + public void setResponse(String response) { this.response = response; } @@ -77,13 +73,11 @@ public void setResponse(String response) * * @return the reason for failure or null on success. */ - public String getReason() - { + public String getReason() { return reason; } - public void setReason(String reason) - { + public void setReason(String reason) { this.reason = reason; } @@ -92,13 +86,11 @@ public void setReason(String reason) * * @return name of the first channel. */ - public String getChannel1() - { + public String getChannel1() { return channel1; } - public void setChannel1(String channel1) - { + public void setChannel1(String channel1) { this.channel1 = channel1; } @@ -107,13 +99,11 @@ public void setChannel1(String channel1) * * @return name of the second channel. */ - public String getChannel2() - { + public String getChannel2() { return channel2; } - public void setChannel2(String channel2) - { + public void setChannel2(String channel2) { this.channel2 = channel2; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java index 386c26e4d..62cccf771 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeLeaveEvent.java @@ -3,8 +3,7 @@ /** * Created by Alexander Polakov on 1/26/15. */ -public class BridgeLeaveEvent extends AbstractBridgeEvent -{ +public class BridgeLeaveEvent extends AbstractBridgeEvent { /** * */ @@ -14,48 +13,39 @@ public class BridgeLeaveEvent extends AbstractBridgeEvent private String language; private String linkedId; - public BridgeLeaveEvent(Object source) - { + public BridgeLeaveEvent(Object source) { super(source); } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeMergeEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeMergeEvent.java index 6be462537..54c45d967 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeMergeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeMergeEvent.java @@ -1,124 +1,121 @@ package org.asteriskjava.manager.event; -public class BridgeMergeEvent extends ManagerEvent -{ +public class BridgeMergeEvent extends ManagerEvent { private static final long serialVersionUID = 1L; - public BridgeMergeEvent(Object source) - { + public BridgeMergeEvent(Object source) { super(source); } - - private Integer fromBridgeNumChannels; - private Integer toBridgeNumChannels; - private String fromBridgeName; + + private Integer fromBridgeNumChannels; + private Integer toBridgeNumChannels; + private String fromBridgeName; private String fromBridgeUniqueId; - private String fromBridgeCreator; - private String toBridgeName; - private String fromBridgeTechnology; - private String toBridgeUniqueId; - private String toBridgeTechnology; - private String fromBridgeType; - private String toBridgeType; + private String fromBridgeCreator; + private String toBridgeName; + private String fromBridgeTechnology; + private String toBridgeUniqueId; + private String toBridgeTechnology; + private String fromBridgeType; + private String toBridgeType; private String toBridgeCreator; - public Integer getFromBridgeNumChannels() - { + public Integer getFromBridgeNumChannels() { return fromBridgeNumChannels; } - public void setFromBridgeNumChannels(Integer fromBridgeNumChannels) - { + + public void setFromBridgeNumChannels(Integer fromBridgeNumChannels) { this.fromBridgeNumChannels = fromBridgeNumChannels; } - public Integer getToBridgeNumChannels() - { + + public Integer getToBridgeNumChannels() { return toBridgeNumChannels; } - public void setToBridgeNumChannels(Integer toBridgeNumChannels) - { + + public void setToBridgeNumChannels(Integer toBridgeNumChannels) { this.toBridgeNumChannels = toBridgeNumChannels; } - public String getFromBridgeName() - { + + public String getFromBridgeName() { return fromBridgeName; } - public void setFromBridgeName(String fromBridgeName) - { + + public void setFromBridgeName(String fromBridgeName) { this.fromBridgeName = fromBridgeName; } - public String getFromBridgeUniqueId() - { + + public String getFromBridgeUniqueId() { return fromBridgeUniqueId; } - public void setFromBridgeUniqueId(String fromBridgeUniqueId) - { + + public void setFromBridgeUniqueId(String fromBridgeUniqueId) { this.fromBridgeUniqueId = fromBridgeUniqueId; } - public String getFromBridgeCreator() - { + + public String getFromBridgeCreator() { return fromBridgeCreator; } - public void setFromBridgeCreator(String fromBridgeCreator) - { + + public void setFromBridgeCreator(String fromBridgeCreator) { this.fromBridgeCreator = fromBridgeCreator; } - public String getToBridgeName() - { + + public String getToBridgeName() { return toBridgeName; } - public void setToBridgeName(String toBridgeName) - { + + public void setToBridgeName(String toBridgeName) { this.toBridgeName = toBridgeName; } - public String getFromBridgeTechnology() - { + + public String getFromBridgeTechnology() { return fromBridgeTechnology; } - public void setFromBridgeTechnology(String fromBridgeTechnology) - { + + public void setFromBridgeTechnology(String fromBridgeTechnology) { this.fromBridgeTechnology = fromBridgeTechnology; } - public String getToBridgeUniqueId() - { + + public String getToBridgeUniqueId() { return toBridgeUniqueId; } - public void setToBridgeUniqueId(String toBridgeUniqueId) - { + + public void setToBridgeUniqueId(String toBridgeUniqueId) { this.toBridgeUniqueId = toBridgeUniqueId; } - public String getToBridgeTechnology() - { + + public String getToBridgeTechnology() { return toBridgeTechnology; } - public void setToBridgeTechnology(String toBridgeTechnology) - { + + public void setToBridgeTechnology(String toBridgeTechnology) { this.toBridgeTechnology = toBridgeTechnology; } - public String getFromBridgeType() - { + + public String getFromBridgeType() { return fromBridgeType; } - public void setFromBridgeType(String fromBridgeType) - { + + public void setFromBridgeType(String fromBridgeType) { this.fromBridgeType = fromBridgeType; } - public String getToBridgeType() - { + + public String getToBridgeType() { return toBridgeType; } - public void setToBridgeType(String toBridgeType) - { + + public void setToBridgeType(String toBridgeType) { this.toBridgeType = toBridgeType; } - public String getToBridgeCreator() - { + + public String getToBridgeCreator() { return toBridgeCreator; } - public void setToBridgeCreator(String toBridgeCreator) - { + + public void setToBridgeCreator(String toBridgeCreator) { this.toBridgeCreator = toBridgeCreator; } - - + + } diff --git a/src/main/java/org/asteriskjava/manager/event/CdrEvent.java b/src/main/java/org/asteriskjava/manager/event/CdrEvent.java index da30ae41e..7dc374750 100644 --- a/src/main/java/org/asteriskjava/manager/event/CdrEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/CdrEvent.java @@ -16,11 +16,11 @@ */ package org.asteriskjava.manager.event; +import org.asteriskjava.util.DateUtil; + import java.util.Date; import java.util.TimeZone; -import org.asteriskjava.util.DateUtil; - /** * A CdrEvent is triggered when a call detail record is generated, usually at the end of a call.

      * To enable CdrEvents you have to add enabled = yes to the general section in @@ -30,8 +30,7 @@ * @author srt * @version $Id$ */ -public class CdrEvent extends ManagerEvent -{ +public class CdrEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -71,8 +70,7 @@ public class CdrEvent extends ManagerEvent /** * @param source */ - public CdrEvent(Object source) - { + public CdrEvent(Object source) { super(source); } @@ -82,8 +80,7 @@ public CdrEvent(Object source) * * @return the account number. */ - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } @@ -92,8 +89,7 @@ public String getAccountCode() * * @param accountCode the account number. */ - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } @@ -103,8 +99,7 @@ public void setAccountCode(String accountCode) * * @return the Caller*ID number. */ - public String getSrc() - { + public String getSrc() { return src; } @@ -113,8 +108,7 @@ public String getSrc() * * @param source the Caller*ID number. */ - public void setSrc(String source) - { + public void setSrc(String source) { this.src = source; } @@ -124,8 +118,7 @@ public void setSrc(String source) * * @return the destination extension. */ - public String getDestination() - { + public String getDestination() { return destination; } @@ -134,8 +127,7 @@ public String getDestination() * * @param destination the destination extension. */ - public void setDestination(String destination) - { + public void setDestination(String destination) { this.destination = destination; } @@ -145,8 +137,7 @@ public void setDestination(String destination) * * @return the destination context. */ - public String getDestinationContext() - { + public String getDestinationContext() { return destinationContext; } @@ -155,8 +146,7 @@ public String getDestinationContext() * * @param destinationContext the destination context. */ - public void setDestinationContext(String destinationContext) - { + public void setDestinationContext(String destinationContext) { this.destinationContext = destinationContext; } @@ -166,8 +156,7 @@ public void setDestinationContext(String destinationContext) * * @return the Caller*ID with text */ - public String getCallerId() - { + public String getCallerId() { return callerId; } @@ -176,8 +165,7 @@ public String getCallerId() * * @param callerId the Caller*ID with text. */ - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { this.callerId = callerId; } @@ -187,8 +175,7 @@ public void setCallerId(String callerId) * * @return the name of the channel. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -197,8 +184,7 @@ public String getChannel() * * @param channel the name of the channel. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -208,8 +194,7 @@ public void setChannel(String channel) * * @return the name of the destination channel or null if not available. */ - public String getDestinationChannel() - { + public String getDestinationChannel() { return destinationChannel; } @@ -218,8 +203,7 @@ public String getDestinationChannel() * * @param destinationChannel the name of the destination channel. */ - public void setDestinationChannel(String destinationChannel) - { + public void setDestinationChannel(String destinationChannel) { this.destinationChannel = destinationChannel; } @@ -229,8 +213,7 @@ public void setDestinationChannel(String destinationChannel) * * @return the last application or null if not avaialble. */ - public String getLastApplication() - { + public String getLastApplication() { return lastApplication; } @@ -239,8 +222,7 @@ public String getLastApplication() * * @param lastApplication the last application. */ - public void setLastApplication(String lastApplication) - { + public void setLastApplication(String lastApplication) { this.lastApplication = lastApplication; } @@ -250,8 +232,7 @@ public void setLastApplication(String lastApplication) * * @return the last application's data or null if not avaialble. */ - public String getLastData() - { + public String getLastData() { return lastData; } @@ -260,8 +241,7 @@ public String getLastData() * * @param lastData the last application's data. */ - public void setLastData(String lastData) - { + public void setLastData(String lastData) { this.lastData = lastData; } @@ -272,8 +252,7 @@ public void setLastData(String lastData) * @return A string of the format "%Y-%m-%d %T" (strftime(3)) representing the date/time the * call has started, for example "2006-05-19 11:54:48". */ - public String getStartTime() - { + public String getStartTime() { return startTime; } @@ -285,8 +264,7 @@ public String getStartTime() * @return the start time as Date object. * @since 0.3 */ - public Date getStartTimeAsDate() - { + public Date getStartTimeAsDate() { return DateUtil.parseDateTime(startTime); } @@ -297,8 +275,7 @@ public Date getStartTimeAsDate() * @return the start time as Date object. * @since 0.3 */ - public Date getStartTimeAsDate(TimeZone tz) - { + public Date getStartTimeAsDate(TimeZone tz) { return DateUtil.parseDateTime(startTime, tz); } @@ -307,8 +284,7 @@ public Date getStartTimeAsDate(TimeZone tz) * * @param startTime the date/time when the call has started. */ - public void setStartTime(String startTime) - { + public void setStartTime(String startTime) { this.startTime = startTime; } @@ -319,8 +295,7 @@ public void setStartTime(String startTime) * @return A string of the format "%Y-%m-%d %T" (strftime(3)) representing the date/time the * call was answered, for example "2006-05-19 11:55:01" */ - public String getAnswerTime() - { + public String getAnswerTime() { return answerTime; } @@ -332,8 +307,7 @@ public String getAnswerTime() * @return the answer time as Date object. * @since 0.3 */ - public Date getAnswerTimeAsDate() - { + public Date getAnswerTimeAsDate() { return DateUtil.parseDateTime(answerTime); } @@ -344,8 +318,7 @@ public Date getAnswerTimeAsDate() * @return the answer time as Date object. * @since 0.3 */ - public Date getAnswerTimeAsDate(TimeZone tz) - { + public Date getAnswerTimeAsDate(TimeZone tz) { return DateUtil.parseDateTime(answerTime, tz); } @@ -354,8 +327,7 @@ public Date getAnswerTimeAsDate(TimeZone tz) * * @param answerTime the date/time when the call was answered. */ - public void setAnswerTime(String answerTime) - { + public void setAnswerTime(String answerTime) { this.answerTime = answerTime; } @@ -366,8 +338,7 @@ public void setAnswerTime(String answerTime) * @return A string of the format "%Y-%m-%d %T" (strftime(3)) representing the date/time the * call has ended, for example "2006-05-19 11:58:21" */ - public String getEndTime() - { + public String getEndTime() { return endTime; } @@ -379,8 +350,7 @@ public String getEndTime() * @return the end time as Date object. * @since 0.3 */ - public Date getEndTimeAsDate() - { + public Date getEndTimeAsDate() { return DateUtil.parseDateTime(endTime); } @@ -391,8 +361,7 @@ public Date getEndTimeAsDate() * @return the end time as Date object. * @since 0.3 */ - public Date getEndTimeAsDate(TimeZone tz) - { + public Date getEndTimeAsDate(TimeZone tz) { return DateUtil.parseDateTime(endTime, tz); } @@ -401,8 +370,7 @@ public Date getEndTimeAsDate(TimeZone tz) * * @param endTime the date/time when the call has ended. */ - public void setEndTime(String endTime) - { + public void setEndTime(String endTime) { this.endTime = endTime; } @@ -412,8 +380,7 @@ public void setEndTime(String endTime) * * @return the total time in system in seconds. */ - public Integer getDuration() - { + public Integer getDuration() { return duration; } @@ -422,8 +389,7 @@ public Integer getDuration() * * @param duration total time in system in seconds. */ - public void setDuration(Integer duration) - { + public void setDuration(Integer duration) { this.duration = duration; } @@ -433,8 +399,7 @@ public void setDuration(Integer duration) * * @return the total time in call in seconds. */ - public Integer getBillableSeconds() - { + public Integer getBillableSeconds() { return billableSeconds; } @@ -443,8 +408,7 @@ public Integer getBillableSeconds() * * @param billableSeconds the total time in call in seconds. */ - public void setBillableSeconds(Integer billableSeconds) - { + public void setBillableSeconds(Integer billableSeconds) { this.billableSeconds = billableSeconds; } @@ -462,8 +426,7 @@ public void setBillableSeconds(Integer billableSeconds) * * @return the disposition. */ - public String getDisposition() - { + public String getDisposition() { return disposition; } @@ -472,8 +435,7 @@ public String getDisposition() * * @param disposition the disposition. */ - public void setDisposition(String disposition) - { + public void setDisposition(String disposition) { this.disposition = disposition; } @@ -490,8 +452,7 @@ public void setDisposition(String disposition) * * @return the AMA flags. */ - public String getAmaFlags() - { + public String getAmaFlags() { return amaFlags; } @@ -500,8 +461,7 @@ public String getAmaFlags() * * @param amaFlags the AMA (Automated Message Accounting) flags. */ - public void setAmaFlags(String amaFlags) - { + public void setAmaFlags(String amaFlags) { this.amaFlags = amaFlags; } @@ -510,8 +470,7 @@ public void setAmaFlags(String amaFlags) * * @return the unique id of the channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } @@ -520,8 +479,7 @@ public String getUniqueId() * * @param uniqueId the unique id of the channel. */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -531,8 +489,7 @@ public void setUniqueId(String uniqueId) * * @return the user-defined field. */ - public String getUserField() - { + public String getUserField() { return userField; } @@ -541,27 +498,27 @@ public String getUserField() * * @param userField the user-defined field */ - public void setUserField(String userField) - { + public void setUserField(String userField) { this.userField = userField; } - /** - * Returns record filename. - * @return record filename. - */ + /** + * Returns record filename. + * + * @return record filename. + */ - public String getRecordfile() { - return recordfile; - } + public String getRecordfile() { + return recordfile; + } - /** - * Sets record filename. - * - * @param recordfile record filename. - */ + /** + * Sets record filename. + * + * @param recordfile record filename. + */ - public void setRecordfile(String recordfile) { - this.recordfile = recordfile; - } + public void setRecordfile(String recordfile) { + this.recordfile = recordfile; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/CelEvent.java b/src/main/java/org/asteriskjava/manager/event/CelEvent.java index af872505c..e8e25cacd 100644 --- a/src/main/java/org/asteriskjava/manager/event/CelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/CelEvent.java @@ -1,10 +1,10 @@ package org.asteriskjava.manager.event; + /** * Raised when a Channel Event Log is generated for a channel. * https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+ManagerEvent_CEL */ -public class CelEvent extends ManagerEvent -{ +public class CelEvent extends ManagerEvent { private static final long serialVersionUID = 1L; public static final String CEL_EVENT_CHAN_START = "CHAN_START"; public static final String CEL_EVENT_CHAN_END = "CHAN_END"; @@ -41,168 +41,135 @@ public class CelEvent extends ManagerEvent private String extra; private String channel; - public CelEvent(Object source) - { + public CelEvent(Object source) { super(source); } - public String getEventName() - { + public String getEventName() { return eventName; } - public void setEventName(String eventName) - { + public void setEventName(String eventName) { this.eventName = eventName; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; - } + } - public String getCallerIDani() - { + public String getCallerIDani() { return callerIDani; } - public void setCallerIDani(String callerIDani) - { + public void setCallerIDani(String callerIDani) { this.callerIDani = callerIDani; } - public String getCallerIDrdnis() - { + public String getCallerIDrdnis() { return callerIDrdnis; } - public void setCallerIDrdnis(String callerIDrdnis) - { + public void setCallerIDrdnis(String callerIDrdnis) { this.callerIDrdnis = callerIDrdnis; } - public String getCallerIDdnid() - { + public String getCallerIDdnid() { return callerIDdnid; } - public void setCallerIDdnid(String callerIDdnid) - { + public void setCallerIDdnid(String callerIDdnid) { this.callerIDdnid = callerIDdnid; } - public String getApplication() - { + public String getApplication() { return application; } - public void setApplication(String application) - { + public void setApplication(String application) { this.application = application; } - public String getAppData() - { + public String getAppData() { return appData; } - public void setAppData(String appData) - { + public void setAppData(String appData) { this.appData = appData; } - public String getEventTime() - { + public String getEventTime() { return eventTime; } - public void setEventTime(String eventTime) - { + public void setEventTime(String eventTime) { this.eventTime = eventTime; } - public String getAmaFlags() - { + public String getAmaFlags() { return amaFlags; } - public void setAmaFlags(String amaFlags) - { + public void setAmaFlags(String amaFlags) { this.amaFlags = amaFlags; } - public String getUniqueID() - { + public String getUniqueID() { return uniqueID; } - public void setUniqueID(String uniqueID) - { + public void setUniqueID(String uniqueID) { this.uniqueID = uniqueID; } - public String getLinkedID() - { + public String getLinkedID() { return linkedID; } - public void setLinkedID(String linkedID) - { + public void setLinkedID(String linkedID) { this.linkedID = linkedID; } - public String getUserField() - { + public String getUserField() { return userField; } - public void setUserField(String userField) - { + public void setUserField(String userField) { this.userField = userField; } - public String getPeer() - { + public String getPeer() { return peer; } - public void setPeer(String peer) - { + public void setPeer(String peer) { this.peer = peer; } - public String getPeerAccount() - { + public String getPeerAccount() { return peerAccount; } - public void setPeerAccount(String peerAccount) - { + public void setPeerAccount(String peerAccount) { this.peerAccount = peerAccount; } - public String getExtra() - { + public String getExtra() { return extra; } - public void setExtra(String extra) - { + public void setExtra(String extra) { this.extra = extra; } - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/event/ChallengeResponseFailedEvent.java b/src/main/java/org/asteriskjava/manager/event/ChallengeResponseFailedEvent.java index 96e13050a..3c88d838a 100644 --- a/src/main/java/org/asteriskjava/manager/event/ChallengeResponseFailedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ChallengeResponseFailedEvent.java @@ -5,8 +5,8 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; -public class ChallengeResponseFailedEvent extends ManagerEvent -{ + +public class ChallengeResponseFailedEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -21,69 +21,60 @@ public class ChallengeResponseFailedEvent extends ManagerEvent /** * @param source */ - public ChallengeResponseFailedEvent(Object source) { - super(source); - } + public ChallengeResponseFailedEvent(Object source) { + super(source); + } - public String getSeverity() - { + public String getSeverity() { return severity; } - public void setSeverity(String severity) - { + + public void setSeverity(String severity) { this.severity = severity; } - public String getEventversion() - { + public String getEventversion() { return eventversion; } - public void setEventversion(String eventversion) - { + + public void setEventversion(String eventversion) { this.eventversion = eventversion; } - - - public String getService() - { + + + public String getService() { return service; } - public void setService(String service) - { + + public void setService(String service) { this.service = service; } - public String getRemoteAddress() - { + public String getRemoteAddress() { return remoteaddress; } - public void setRemoteAddress(String remoteaddress) - { + + public void setRemoteAddress(String remoteaddress) { this.remoteaddress = remoteaddress; } - public String getLocalAddress() - { + public String getLocalAddress() { return localaddress; } - public void setLocalAddress(String localaddress) - { + + public void setLocalAddress(String localaddress) { this.localaddress = localaddress; } - public void setEventtv(String eventv) - { + public void setEventtv(String eventv) { DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.ENGLISH); Long t = 0L; - try - { - Date date = format.parse(eventv); - t = date.getTime(); - } - catch (ParseException ex){} - finally - { - this.setTimestamp(t.doubleValue()); + try { + Date date = format.parse(eventv); + t = date.getTime(); + } catch (ParseException ex) { + } finally { + this.setTimestamp(t.doubleValue()); } } } diff --git a/src/main/java/org/asteriskjava/manager/event/ChallengeSentEvent.java b/src/main/java/org/asteriskjava/manager/event/ChallengeSentEvent.java index 348e35923..c924266e9 100644 --- a/src/main/java/org/asteriskjava/manager/event/ChallengeSentEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ChallengeSentEvent.java @@ -3,114 +3,94 @@ /** * Created by plhk on 1/15/15. */ -public class ChallengeSentEvent extends ManagerEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; - private String severity; - private Integer eventVersion; - private String accountId; - private String service; - private String eventtv; - private String remoteAddress; - private String localAddress; - private String challenge; - private String sessionId; - - public ChallengeSentEvent(Object source) - { - super(source); - } - - public String getSeverity() - { - return severity; - } - - public void setSeverity(String severity) - { - this.severity = severity; - } - - public Integer getEventVersion() - { - return eventVersion; - } - - public void setEventVersion(Integer eventVersion) - { - this.eventVersion = eventVersion; - } - - public String getAccountId() - { - return accountId; - } - - public void setAccountId(String accountId) - { - this.accountId = accountId; - } - - public String getService() - { - return service; - } - - public void setService(String service) - { - this.service = service; - } - - public String getEventtv() - { - return eventtv; - } - - public void setEventtv(String eventtv) - { - this.eventtv = eventtv; - } - - public String getRemoteAddress() - { - return remoteAddress; - } - - public void setRemoteAddress(String remoteAddress) - { - this.remoteAddress = remoteAddress; - } - - public String getLocalAddress() - { - return localAddress; - } - - public void setLocalAddress(String localAddress) - { - this.localAddress = localAddress; - } - - public String getChallenge() - { - return challenge; - } - - public void setChallenge(String challenge) - { - this.challenge = challenge; - } - - public String getSessionId() - { - return sessionId; - } - - public void setSessionId(String sessionId) - { - this.sessionId = sessionId; - } +public class ChallengeSentEvent extends ManagerEvent { + /** + * + */ + private static final long serialVersionUID = 1L; + private String severity; + private Integer eventVersion; + private String accountId; + private String service; + private String eventtv; + private String remoteAddress; + private String localAddress; + private String challenge; + private String sessionId; + + public ChallengeSentEvent(Object source) { + super(source); + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public Integer getEventVersion() { + return eventVersion; + } + + public void setEventVersion(Integer eventVersion) { + this.eventVersion = eventVersion; + } + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public String getEventtv() { + return eventtv; + } + + public void setEventtv(String eventtv) { + this.eventtv = eventtv; + } + + public String getRemoteAddress() { + return remoteAddress; + } + + public void setRemoteAddress(String remoteAddress) { + this.remoteAddress = remoteAddress; + } + + public String getLocalAddress() { + return localAddress; + } + + public void setLocalAddress(String localAddress) { + this.localAddress = localAddress; + } + + public String getChallenge() { + return challenge; + } + + public void setChallenge(String challenge) { + this.challenge = challenge; + } + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/ChanSpyStartEvent.java b/src/main/java/org/asteriskjava/manager/event/ChanSpyStartEvent.java index 63bbcfd5f..bfe0bc7e8 100644 --- a/src/main/java/org/asteriskjava/manager/event/ChanSpyStartEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ChanSpyStartEvent.java @@ -17,8 +17,7 @@ package org.asteriskjava.manager.event; -public class ChanSpyStartEvent extends ManagerEvent -{ +public class ChanSpyStartEvent extends ManagerEvent { /** * Serial version identifier */ @@ -26,7 +25,7 @@ public class ChanSpyStartEvent extends ManagerEvent private String spyeeChannel; private String spyerChannel; - + private Integer spyeeChannelState; private String spyeeLinkedId; private String spyeeUniqueId; @@ -41,423 +40,305 @@ public class ChanSpyStartEvent extends ManagerEvent private String spyeeAccountCode; private Integer spyeePriority; private String spyeeCallerIdName; - - + + private String spyerUniqueId; private String spyerLinkedId; private Integer spyerChannelState; private Integer spyerPriority; - private String spyerContext; + private String spyerContext; private String spyerLanguage; - private String spyerChannelStateDesc; + private String spyerChannelStateDesc; private String spyerExten; private String spyerCallerIdNum; private String spyerConnectedLineNum; - private String spyerConnectedLineName; + private String spyerConnectedLineName; private String spyerCallerIdName; - - - public ChanSpyStartEvent(Object source) - { + + public ChanSpyStartEvent(Object source) { super(source); } - - public String getSpyeeChannel() - { + public String getSpyeeChannel() { return spyeeChannel; } - - public void setSpyeeChannel(String spyeeChannel) - { + public void setSpyeeChannel(String spyeeChannel) { this.spyeeChannel = spyeeChannel; } - - public String getSpyerChannel() - { + public String getSpyerChannel() { return spyerChannel; } - - public void setSpyerChannel(String spyerChannel) - { + public void setSpyerChannel(String spyerChannel) { this.spyerChannel = spyerChannel; } - - public Integer getSpyeeChannelState() - { + public Integer getSpyeeChannelState() { return spyeeChannelState; } - - public void setSpyeeChannelState(Integer spyeeChannelState) - { + public void setSpyeeChannelState(Integer spyeeChannelState) { this.spyeeChannelState = spyeeChannelState; } - - public String getSpyeeLinkedId() - { + public String getSpyeeLinkedId() { return spyeeLinkedId; } - - public void setSpyeeLinkedId(String spyeeLinkedId) - { + public void setSpyeeLinkedId(String spyeeLinkedId) { this.spyeeLinkedId = spyeeLinkedId; } - - public String getSpyeeUniqueId() - { + public String getSpyeeUniqueId() { return spyeeUniqueId; } - - public void setSpyeeUniqueId(String spyeeUniqueId) - { + public void setSpyeeUniqueId(String spyeeUniqueId) { this.spyeeUniqueId = spyeeUniqueId; } - - public String getSpyeeCallerIdNum() - { + public String getSpyeeCallerIdNum() { return spyeeCallerIdNum; } - - public void setSpyeeCallerIdNum(String spyeeCallerIdNum) - { + public void setSpyeeCallerIdNum(String spyeeCallerIdNum) { this.spyeeCallerIdNum = spyeeCallerIdNum; } - - public String getSpyeeConnectedLineName() - { + public String getSpyeeConnectedLineName() { return spyeeConnectedLineName; } - - public void setSpyeeConnectedLineName(String spyeeConnectedLineName) - { + public void setSpyeeConnectedLineName(String spyeeConnectedLineName) { this.spyeeConnectedLineName = spyeeConnectedLineName; } - - public String getSpyeeLanguage() - { + public String getSpyeeLanguage() { return spyeeLanguage; } - - public void setSpyeeLanguage(String spyeeLanguage) - { + public void setSpyeeLanguage(String spyeeLanguage) { this.spyeeLanguage = spyeeLanguage; } - - public String getSpyeeContext() - { + public String getSpyeeContext() { return spyeeContext; } - - public void setSpyeeContext(String spyeeContext) - { + public void setSpyeeContext(String spyeeContext) { this.spyeeContext = spyeeContext; } - - public String getSpyeeConnectedLineNum() - { + public String getSpyeeConnectedLineNum() { return spyeeConnectedLineNum; } - - public void setSpyeeConnectedLineNum(String spyeeConnectedLineNum) - { + public void setSpyeeConnectedLineNum(String spyeeConnectedLineNum) { this.spyeeConnectedLineNum = spyeeConnectedLineNum; } - - public String getSpyeeChannelStateDesc() - { + public String getSpyeeChannelStateDesc() { return spyeeChannelStateDesc; } - - public void setSpyeeChannelStateDesc(String spyeeChannelStateDesc) - { + public void setSpyeeChannelStateDesc(String spyeeChannelStateDesc) { this.spyeeChannelStateDesc = spyeeChannelStateDesc; } - - public String getSpyeeExten() - { + public String getSpyeeExten() { return spyeeExten; } - - public void setSpyeeExten(String spyeeExten) - { + public void setSpyeeExten(String spyeeExten) { this.spyeeExten = spyeeExten; } - - public Integer getSpyeeChannelstate() - { + public Integer getSpyeeChannelstate() { return spyeeChannelstate; } - - public void setSpyeeChannelstate(Integer spyeeChannelstate) - { + public void setSpyeeChannelstate(Integer spyeeChannelstate) { this.spyeeChannelstate = spyeeChannelstate; } - - public String getSpyeeAccountCode() - { + public String getSpyeeAccountCode() { return spyeeAccountCode; } - - public void setSpyeeAccountCode(String spyeeAccountCode) - { + public void setSpyeeAccountCode(String spyeeAccountCode) { this.spyeeAccountCode = spyeeAccountCode; } - - public Integer getSpyeePriority() - { + public Integer getSpyeePriority() { return spyeePriority; } - - public void setSpyeePriority(Integer spyeePriority) - { + public void setSpyeePriority(Integer spyeePriority) { this.spyeePriority = spyeePriority; } - - public String getSpyeeCallerIdName() - { + public String getSpyeeCallerIdName() { return spyeeCallerIdName; } - - public void setSpyeeCallerIdName(String spyeeCallerIdName) - { + public void setSpyeeCallerIdName(String spyeeCallerIdName) { this.spyeeCallerIdName = spyeeCallerIdName; } - - public String getSpyerUniqueId() - { + public String getSpyerUniqueId() { return spyerUniqueId; } - - public void setSpyerUniqueId(String spyerUniqueId) - { + public void setSpyerUniqueId(String spyerUniqueId) { this.spyerUniqueId = spyerUniqueId; } - - public String getSpyerLinkedId() - { + public String getSpyerLinkedId() { return spyerLinkedId; } - - public void setSpyerLinkedId(String spyerLinkedId) - { + public void setSpyerLinkedId(String spyerLinkedId) { this.spyerLinkedId = spyerLinkedId; } - - public Integer getSpyerChannelState() - { + public Integer getSpyerChannelState() { return spyerChannelState; } - - public void setSpyerChannelState(Integer spyerChannelState) - { + public void setSpyerChannelState(Integer spyerChannelState) { this.spyerChannelState = spyerChannelState; } - - public Integer getSpyerPriority() - { + public Integer getSpyerPriority() { return spyerPriority; } - - public void setSpyerPriority(Integer spyerPriority) - { + public void setSpyerPriority(Integer spyerPriority) { this.spyerPriority = spyerPriority; } - - public String getSpyerContext() - { + public String getSpyerContext() { return spyerContext; } - - public void setSpyerContext(String spyerContext) - { + public void setSpyerContext(String spyerContext) { this.spyerContext = spyerContext; } - - public String getSpyerLanguage() - { + public String getSpyerLanguage() { return spyerLanguage; } - - public void setSpyerLanguage(String spyerLanguage) - { + public void setSpyerLanguage(String spyerLanguage) { this.spyerLanguage = spyerLanguage; } - - public String getSpyerChannelStateDesc() - { + public String getSpyerChannelStateDesc() { return spyerChannelStateDesc; } - - public void setSpyerChannelStateDesc(String spyerChannelStateDesc) - { + public void setSpyerChannelStateDesc(String spyerChannelStateDesc) { this.spyerChannelStateDesc = spyerChannelStateDesc; } - - public String getSpyerExten() - { + public String getSpyerExten() { return spyerExten; } - - public void setSpyerExten(String spyerExten) - { + public void setSpyerExten(String spyerExten) { this.spyerExten = spyerExten; } - - public String getSpyerCallerIdNum() - { + public String getSpyerCallerIdNum() { return spyerCallerIdNum; } - - public void setSpyerCallerIdNum(String spyerCallerIdNum) - { + public void setSpyerCallerIdNum(String spyerCallerIdNum) { this.spyerCallerIdNum = spyerCallerIdNum; } - - public String getSpyerConnectedLineNum() - { + public String getSpyerConnectedLineNum() { return spyerConnectedLineNum; } - - public void setSpyerConnectedLineNum(String spyerConnectedLineNum) - { + public void setSpyerConnectedLineNum(String spyerConnectedLineNum) { this.spyerConnectedLineNum = spyerConnectedLineNum; } - - public String getSpyerConnectedLineName() - { + public String getSpyerConnectedLineName() { return spyerConnectedLineName; } - - public void setSpyerConnectedLineName(String spyerConnectedLineName) - { + public void setSpyerConnectedLineName(String spyerConnectedLineName) { this.spyerConnectedLineName = spyerConnectedLineName; } - - public String getSpyerCallerIdName() - { + public String getSpyerCallerIdName() { return spyerCallerIdName; } - - public void setSpyerCallerIdName(String spyerCallerIdName) - { + public void setSpyerCallerIdName(String spyerCallerIdName) { this.spyerCallerIdName = spyerCallerIdName; } - - - - - + } diff --git a/src/main/java/org/asteriskjava/manager/event/ChanSpyStopEvent.java b/src/main/java/org/asteriskjava/manager/event/ChanSpyStopEvent.java index 7b9e9a19b..e6ee38d8e 100644 --- a/src/main/java/org/asteriskjava/manager/event/ChanSpyStopEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ChanSpyStopEvent.java @@ -17,8 +17,7 @@ package org.asteriskjava.manager.event; -public class ChanSpyStopEvent extends ManagerEvent -{ +public class ChanSpyStopEvent extends ManagerEvent { /** * Serial version identifier */ @@ -33,201 +32,169 @@ public class ChanSpyStopEvent extends ManagerEvent private String spyerLinkedId; private Integer spyerChannelState; private Integer spyerPriority; - private String spyerContext; + private String spyerContext; private String spyerLanguage; - private String spyerChannelStateDesc; + private String spyerChannelStateDesc; private String spyerExten; private String spyerCallerIdNum; private String spyerConnectedLineNum; - private String spyerConnectedLineName; + private String spyerConnectedLineName; private String spyerCallerIdName; private String spyerChannel; - - public ChanSpyStopEvent(Object source) - { + + public ChanSpyStopEvent(Object source) { super(source); } - - public String getSpyeeChannel() - { + + public String getSpyeeChannel() { return spyeechannel; } - public void setSpyeeChannel(String channel) - { + public void setSpyeeChannel(String channel) { this.spyeechannel = channel; } - public String getSpyeechannel() - { + public String getSpyeechannel() { return spyeechannel; } - public void setSpyeechannel(String spyeechannel) - { + public void setSpyeechannel(String spyeechannel) { this.spyeechannel = spyeechannel; } - public String getSpyerUniqueId() - { + public String getSpyerUniqueId() { return spyerUniqueId; } - public void setSpyerUniqueId(String spyerUniqueId) - { + public void setSpyerUniqueId(String spyerUniqueId) { this.spyerUniqueId = spyerUniqueId; } - public String getSpyerLinkedId() - { + public String getSpyerLinkedId() { return spyerLinkedId; } - public void setSpyerLinkedId(String spyerLinkedId) - { + public void setSpyerLinkedId(String spyerLinkedId) { this.spyerLinkedId = spyerLinkedId; } - public Integer getSpyerChannelState() - { + public Integer getSpyerChannelState() { return spyerChannelState; } - public void setSpyerChannelState(Integer spyerChannelState) - { + public void setSpyerChannelState(Integer spyerChannelState) { this.spyerChannelState = spyerChannelState; } - public Integer getSpyerPriority() - { + public Integer getSpyerPriority() { return spyerPriority; } - public void setSpyerPriority(Integer spyerPriority) - { + public void setSpyerPriority(Integer spyerPriority) { this.spyerPriority = spyerPriority; } - public String getSpyerContext() - { + public String getSpyerContext() { return spyerContext; } - public void setSpyerContext(String spyerContext) - { + public void setSpyerContext(String spyerContext) { this.spyerContext = spyerContext; } - public String getSpyerLanguage() - { + public String getSpyerLanguage() { return spyerLanguage; } - public void setSpyerLanguage(String spyerLanguage) - { + public void setSpyerLanguage(String spyerLanguage) { this.spyerLanguage = spyerLanguage; } - public String getSpyerChannelStateDesc() - { + public String getSpyerChannelStateDesc() { return spyerChannelStateDesc; } - public void setSpyerChannelStateDesc(String spyerChannelStateDesc) - { + public void setSpyerChannelStateDesc(String spyerChannelStateDesc) { this.spyerChannelStateDesc = spyerChannelStateDesc; } - public String getSpyerExten() - { + public String getSpyerExten() { return spyerExten; } - public void setSpyerExten(String spyerExten) - { + public void setSpyerExten(String spyerExten) { this.spyerExten = spyerExten; } - public String getSpyerCallerIdNum() - { + public String getSpyerCallerIdNum() { return spyerCallerIdNum; } - public void setSpyerCallerIdNum(String spyerCallerIdNum) - { + public void setSpyerCallerIdNum(String spyerCallerIdNum) { this.spyerCallerIdNum = spyerCallerIdNum; } - public String getSpyerConnectedLineNum() - { + public String getSpyerConnectedLineNum() { return spyerConnectedLineNum; } - public void setSpyerConnectedLineNum(String spyerConnectedLineNum) - { + public void setSpyerConnectedLineNum(String spyerConnectedLineNum) { this.spyerConnectedLineNum = spyerConnectedLineNum; } - public String getSpyerConnectedLineName() - { + public String getSpyerConnectedLineName() { return spyerConnectedLineName; } - public void setSpyerConnectedLineName(String spyerConnectedLineName) - { + public void setSpyerConnectedLineName(String spyerConnectedLineName) { this.spyerConnectedLineName = spyerConnectedLineName; } - public String getSpyerCallerIdName() - { + public String getSpyerCallerIdName() { return spyerCallerIdName; } - public void setSpyerCallerIdName(String spyerCallerIdName) - { + public void setSpyerCallerIdName(String spyerCallerIdName) { this.spyerCallerIdName = spyerCallerIdName; } - public String getSpyerChannel() - { + public String getSpyerChannel() { return spyerChannel; } - public void setSpyerChannel(String spyerChannel) - { + public void setSpyerChannel(String spyerChannel) { this.spyerChannel = spyerChannel; } - - + } diff --git a/src/main/java/org/asteriskjava/manager/event/ChannelReloadEvent.java b/src/main/java/org/asteriskjava/manager/event/ChannelReloadEvent.java index fc5cab85d..d3a6b998e 100644 --- a/src/main/java/org/asteriskjava/manager/event/ChannelReloadEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ChannelReloadEvent.java @@ -34,8 +34,7 @@ * * @author martins */ -public class ChannelReloadEvent extends ManagerEvent -{ +public class ChannelReloadEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -102,8 +101,7 @@ public class ChannelReloadEvent extends ManagerEvent /** * @param source */ - public ChannelReloadEvent(Object source) - { + public ChannelReloadEvent(Object source) { super(source); } @@ -113,13 +111,11 @@ public ChannelReloadEvent(Object source) * @return the type of channel that was reloaded (e.g. SIP) * @since 1.0.0 */ - public String getChannelType() - { + public String getChannelType() { return channelType; } - public void setChannelType(String channelType) - { + public void setChannelType(String channelType) { this.channelType = channelType; } @@ -130,13 +126,12 @@ public void setChannelType(String channelType) * @return the type of channel that was reloaded (e.g. SIP) * @deprecated use {@link #getChannelType()} instead. */ - @Deprecated public String getChannel() - { + @Deprecated + public String getChannel() { return channelType; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channelType = channel; } @@ -145,10 +140,9 @@ public void setChannel(String channel) * channel (e.g. sip peer definitions). * * @return the number of peers defined during the configuration of this - * channel (e.g. sip peer definitions) + * channel (e.g. sip peer definitions) */ - public Integer getPeerCount() - { + public Integer getPeerCount() { return peerCount; } @@ -156,17 +150,15 @@ public Integer getPeerCount() * @param peerCount the number of peers defined during the configuration of * this channel (e.g. sip peer definitions) */ - public void setPeerCount(Integer peerCount) - { + public void setPeerCount(Integer peerCount) { this.peerCount = peerCount; } /** * @return the number of registrations with other channels (e.g. - * registrations with other sip proxies) + * registrations with other sip proxies) */ - public Integer getRegistryCount() - { + public Integer getRegistryCount() { return registryCount; } @@ -174,8 +166,7 @@ public Integer getRegistryCount() * @param registryCount the number of registrations with other channels * (e.g. registrations with other sip proxies) */ - public void setRegistryCount(Integer registryCount) - { + public void setRegistryCount(Integer registryCount) { this.registryCount = registryCount; } @@ -189,8 +180,7 @@ public void setRegistryCount(Integer registryCount) * @see #getReloadReasonCode() * @see #getReloadReasonDescription() */ - public String getReloadReason() - { + public String getReloadReason() { return reloadReason; } @@ -200,19 +190,16 @@ public String getReloadReason() * * @param reloadReason the reason that this channel was reloaded */ - public void setReloadReason(String reloadReason) - { + public void setReloadReason(String reloadReason) { Matcher matcher; this.reloadReason = reloadReason; - if (reloadReason == null) - { + if (reloadReason == null) { return; } matcher = REASON_PATTERN.matcher(reloadReason); - if (matcher.matches()) - { + if (matcher.matches()) { reloadReasonCode = matcher.group(1); reloadReasonDescription = matcher.group(2); } @@ -234,8 +221,7 @@ public void setReloadReason(String reloadReason) * @see org.asteriskjava.manager.event.ChannelReloadEvent#REASON_RELOAD * @see org.asteriskjava.manager.event.ChannelReloadEvent#REASON_MANAGER_RELOAD */ - public String getReloadReasonCode() - { + public String getReloadReasonCode() { return reloadReasonCode; } @@ -245,17 +231,15 @@ public String getReloadReasonCode() * * @return the descriptive version of the reason for the reload. */ - public String getReloadReasonDescription() - { + public String getReloadReasonDescription() { return reloadReasonDescription; } /** * @return the number of users defined during the configuration of this - * channel (e.g. sip user definitions) + * channel (e.g. sip user definitions) */ - public Integer getUserCount() - { + public Integer getUserCount() { return userCount; } @@ -263,8 +247,7 @@ public Integer getUserCount() * @param userCount the number of users defined during the configuration of * this channel (e.g. sip user definitions) */ - public void setUserCount(Integer userCount) - { + public void setUserCount(Integer userCount) { this.userCount = userCount; } } diff --git a/src/main/java/org/asteriskjava/manager/event/ChannelUpdateEvent.java b/src/main/java/org/asteriskjava/manager/event/ChannelUpdateEvent.java index 15d250d74..1b8b78184 100644 --- a/src/main/java/org/asteriskjava/manager/event/ChannelUpdateEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ChannelUpdateEvent.java @@ -27,8 +27,7 @@ * @version $Id$ * @since 1.0.0 */ -public class ChannelUpdateEvent extends ManagerEvent -{ +public class ChannelUpdateEvent extends ManagerEvent { private static final long serialVersionUID = 3141630567125429466L; private String channelType; private String channel; @@ -47,12 +46,11 @@ public class ChannelUpdateEvent extends ManagerEvent /** * @param source */ - public ChannelUpdateEvent(Object source) - { + public ChannelUpdateEvent(Object source) { super(source); } - + /** * Returns the type of channel, that is "IAX2" for an IAX2 * channel or "SIP" for a SIP channel.
      @@ -60,13 +58,11 @@ public ChannelUpdateEvent(Object source) * * @return the type of channel that is registered. */ - public String getChannelType() - { + public String getChannelType() { return channelType; } - public void setChannelType(String channelType) - { + public void setChannelType(String channelType) { this.channelType = channelType; } @@ -75,13 +71,11 @@ public void setChannelType(String channelType) * * @return the name of the channel. */ - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -90,83 +84,67 @@ public void setChannel(String channel) * * @return the unique id of the channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } - public String getSipCallId() - { + public String getSipCallId() { return sipCallId; } - public void setSipCallId(String sipCallId) - { + public void setSipCallId(String sipCallId) { this.sipCallId = sipCallId; } - public String getSipFullContact() - { + public String getSipFullContact() { return sipFullContact; } - public void setSipFullContact(String sipFullContact) - { + public void setSipFullContact(String sipFullContact) { this.sipFullContact = sipFullContact; } - public String getPeerName() - { + public String getPeerName() { return peerName; } - public void setPeerName(String peerName) - { + public void setPeerName(String peerName) { this.peerName = peerName; } - public String getGtalkSid() - { + public String getGtalkSid() { return gtalkSid; } - public void setGtalkSid(String gtalkSid) - { + public void setGtalkSid(String gtalkSid) { this.gtalkSid = gtalkSid; } - public String getIax2CallNoLocal() - { + public String getIax2CallNoLocal() { return iax2CallNoLocal; } - public void setIax2CallNoLocal(String iax2CallNoLocal) - { + public void setIax2CallNoLocal(String iax2CallNoLocal) { this.iax2CallNoLocal = iax2CallNoLocal; } - public String getIax2CallNoRemote() - { + public String getIax2CallNoRemote() { return iax2CallNoRemote; } - public void setIax2CallNoRemote(String iax2CallNoRemote) - { + public void setIax2CallNoRemote(String iax2CallNoRemote) { this.iax2CallNoRemote = iax2CallNoRemote; } - public String getIax2Peer() - { + public String getIax2Peer() { return iax2Peer; } - public void setIax2Peer(String iax2Peer) - { + public void setIax2Peer(String iax2Peer) { this.iax2Peer = iax2Peer; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeEndEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeEndEvent.java index 16b97b27d..e5d0edd6c 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeEndEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeEndEvent.java @@ -6,16 +6,14 @@ * * @since 1.0.0 */ -public class ConfbridgeEndEvent extends AbstractConfbridgeEvent -{ +public class ConfbridgeEndEvent extends AbstractConfbridgeEvent { /** * Serializable version identifier */ private static final long serialVersionUID = -8973512592594074108L; - public ConfbridgeEndEvent(Object source) - { + public ConfbridgeEndEvent(Object source) { super(source); } diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeJoinEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeJoinEvent.java index f4111f1c7..228283784 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeJoinEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeJoinEvent.java @@ -6,8 +6,7 @@ * * @since 1.0.0 */ -public class ConfbridgeJoinEvent extends AbstractConfbridgeEvent -{ +public class ConfbridgeJoinEvent extends AbstractConfbridgeEvent { /** * Serializable version identifier */ @@ -15,18 +14,15 @@ public class ConfbridgeJoinEvent extends AbstractConfbridgeEvent String muted; - public ConfbridgeJoinEvent(Object source) - { + public ConfbridgeJoinEvent(Object source) { super(source); } - public String getMuted() - { + public String getMuted() { return muted; } - public void setMuted(String muted) - { + public void setMuted(String muted) { this.muted = muted; } diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeLeaveEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeLeaveEvent.java index 2116a5a5f..7abbe5460 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeLeaveEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeLeaveEvent.java @@ -5,15 +5,13 @@ * * @since 1.0.0 */ -public class ConfbridgeLeaveEvent extends AbstractConfbridgeEvent -{ +public class ConfbridgeLeaveEvent extends AbstractConfbridgeEvent { /** * Serializable version identifier */ private static final long serialVersionUID = 1L; - public ConfbridgeLeaveEvent(Object source) - { + public ConfbridgeLeaveEvent(Object source) { super(source); } diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListCompleteEvent.java index e446f617b..82f4ea5a7 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListCompleteEvent.java @@ -1,7 +1,6 @@ package org.asteriskjava.manager.event; -public class ConfbridgeListCompleteEvent extends ResponseEvent -{ +public class ConfbridgeListCompleteEvent extends ResponseEvent { /** * Serializable version identifier */ @@ -13,40 +12,35 @@ public class ConfbridgeListCompleteEvent extends ResponseEvent /** * @param source */ - public ConfbridgeListCompleteEvent(Object source) - { + public ConfbridgeListCompleteEvent(Object source) { super(source); } /** * Sets the status of the list e.g. complete. */ - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } /** * Returns the status of the list e.g. complete. */ - public String getEventList() - { + public String getEventList() { return eventList; } /** * Sets the number listitems. */ - public void setListItems(String listItems) - { + public void setListItems(String listItems) { this.listItems = listItems; } /** * Returns the number listitems. */ - public String getListItems() - { + public String getListItems() { return listItems; } } diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListEvent.java index 380aa8c46..dc76b41fe 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListEvent.java @@ -6,8 +6,7 @@ * @see org.asteriskjava.manager.action.ConfbridgeListAction * @since 1.0.0 */ -public class ConfbridgeListEvent extends ResponseEvent -{ +public class ConfbridgeListEvent extends ResponseEvent { /** * Serializable version identifier */ @@ -28,8 +27,7 @@ public class ConfbridgeListEvent extends ResponseEvent private String endmarked; private String accountcode; - public ConfbridgeListEvent(Object source) - { + public ConfbridgeListEvent(Object source) { super(source); } @@ -38,8 +36,7 @@ public ConfbridgeListEvent(Object source) * * @param conference the id of the conference to be listed. */ - public void setConference(String conference) - { + public void setConference(String conference) { this.conference = conference; } @@ -48,8 +45,7 @@ public void setConference(String conference) * * @return the id of the conference to be listed. */ - public String getConference() - { + public String getConference() { return conference; } @@ -58,10 +54,9 @@ public String getConference() * conference. * * @param admin = yes or no the role of the caller in the list of the - * conference. + * conference. */ - public void setAdmin(Boolean admin) - { + public void setAdmin(Boolean admin) { this.admin = admin; } @@ -70,136 +65,111 @@ public void setAdmin(Boolean admin) * conference. * * @return the role of the caller in the list admin = yes or no of the - * conference. + * conference. */ - public Boolean getAdmin() - { + public Boolean getAdmin() { return admin; } - public void setMarkedUser(Boolean markedUser) - { + public void setMarkedUser(Boolean markedUser) { this.markedUser = markedUser; } - public Boolean getMarkedUser() - { + public Boolean getMarkedUser() { return markedUser; } /** * Sets the name of the channel in the list. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the name of the channel in the list. */ - public String getChannel() - { + public String getChannel() { return channel; } - public String getLinkedid() - { + public String getLinkedid() { return linkedid; } - public void setLinkedid(String linkedid) - { + public void setLinkedid(String linkedid) { this.linkedid = linkedid; } - public String getWaiting() - { + public String getWaiting() { return waiting; } - public void setWaiting(String waiting) - { + public void setWaiting(String waiting) { this.waiting = waiting; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getTalking() - { + public String getTalking() { return talking; } - public void setTalking(String talking) - { + public void setTalking(String talking) { this.talking = talking; } - public String getMuted() - { + public String getMuted() { return muted; } - public void setMuted(String muted) - { + public void setMuted(String muted) { this.muted = muted; } - public String getUniqueid() - { + public String getUniqueid() { return uniqueid; } - public void setUniqueid(String uniqueid) - { + public void setUniqueid(String uniqueid) { this.uniqueid = uniqueid; } - public int getAnsweredtime() - { + public int getAnsweredtime() { return answeredtime; } - public void setAnsweredtime(int answeredtime) - { + public void setAnsweredtime(int answeredtime) { this.answeredtime = answeredtime; } - public String getWaitmarked() - { + public String getWaitmarked() { return waitmarked; } - public void setWaitmarked(String waitmarked) - { + public void setWaitmarked(String waitmarked) { this.waitmarked = waitmarked; } - public String getEndmarked() - { + public String getEndmarked() { return endmarked; } - public void setEndmarked(String endmarked) - { + public void setEndmarked(String endmarked) { this.endmarked = endmarked; } - public String getAccountcode() - { + public String getAccountcode() { return accountcode; } - public void setAccountcode(String accountcode) - { + public void setAccountcode(String accountcode) { this.accountcode = accountcode; } } diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsCompleteEvent.java index 62c863a8d..2b7a24c6e 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsCompleteEvent.java @@ -1,7 +1,6 @@ package org.asteriskjava.manager.event; -public class ConfbridgeListRoomsCompleteEvent extends ResponseEvent -{ +public class ConfbridgeListRoomsCompleteEvent extends ResponseEvent { /** * Serializable version identifier */ @@ -10,24 +9,21 @@ public class ConfbridgeListRoomsCompleteEvent extends ResponseEvent private String eventList; private String listItems; - public ConfbridgeListRoomsCompleteEvent(Object source) - { + public ConfbridgeListRoomsCompleteEvent(Object source) { super(source); } /** * Sets the status of the list that is always "Complete". */ - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } /** * Returns the status of the list that is always "Complete". */ - public String getEventList() - { + public String getEventList() { return eventList; } @@ -36,8 +32,7 @@ public String getEventList() * * @param listItems the number items returned. */ - public void setListItems(String listItems) - { + public void setListItems(String listItems) { this.listItems = listItems; } @@ -46,8 +41,7 @@ public void setListItems(String listItems) * * @return the number items returned. */ - public String getListItems() - { + public String getListItems() { return listItems; } } diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsEvent.java index d748b6df7..22a91649e 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeListRoomsEvent.java @@ -1,7 +1,6 @@ package org.asteriskjava.manager.event; -public class ConfbridgeListRoomsEvent extends ResponseEvent -{ +public class ConfbridgeListRoomsEvent extends ResponseEvent { /** * Serializable version identifier */ @@ -13,24 +12,21 @@ public class ConfbridgeListRoomsEvent extends ResponseEvent private Boolean locked; private String muted; - public ConfbridgeListRoomsEvent(Object source) - { + public ConfbridgeListRoomsEvent(Object source) { super(source); } /** * Sets the id of the conference to be listed. */ - public void setConference(String conference) - { + public void setConference(String conference) { this.conference = conference; } /** * Returns the id of the conference to be listed. */ - public String getConference() - { + public String getConference() { return conference; } @@ -39,8 +35,7 @@ public String getConference() * * @param parties the number of participants in this conference. */ - public void setParties(Integer parties) - { + public void setParties(Integer parties) { this.parties = parties; } @@ -49,8 +44,7 @@ public void setParties(Integer parties) * * @return the number of participants in this conference. */ - public Integer getParties() - { + public Integer getParties() { return parties; } @@ -59,8 +53,7 @@ public Integer getParties() * * @param marked the number of marked participants in this conference. */ - public void setMarked(Integer marked) - { + public void setMarked(Integer marked) { this.marked = marked; } @@ -69,28 +62,23 @@ public void setMarked(Integer marked) * * @return the number of marked participants in this conference. */ - public Integer getMarked() - { + public Integer getMarked() { return marked; } - public void setLocked(Boolean locked) - { + public void setLocked(Boolean locked) { this.locked = locked; } - public Boolean getLocked() - { + public Boolean getLocked() { return locked; } - public String getMuted() - { + public String getMuted() { return muted; } - public void setMuted(String muted) - { + public void setMuted(String muted) { this.muted = muted; } } diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeStartEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeStartEvent.java index bd001c754..1368f0915 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeStartEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeStartEvent.java @@ -6,8 +6,7 @@ * * @since 1.0.0 */ -public class ConfbridgeStartEvent extends AbstractConfbridgeEvent -{ +public class ConfbridgeStartEvent extends AbstractConfbridgeEvent { /** * Serializable version identifier */ @@ -16,8 +15,7 @@ public class ConfbridgeStartEvent extends AbstractConfbridgeEvent @SuppressWarnings("unused") private String conference; - public ConfbridgeStartEvent(Object source) - { + public ConfbridgeStartEvent(Object source) { super(source); } diff --git a/src/main/java/org/asteriskjava/manager/event/ConfbridgeTalkingEvent.java b/src/main/java/org/asteriskjava/manager/event/ConfbridgeTalkingEvent.java index 4ce4fba72..960ad1ed2 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConfbridgeTalkingEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConfbridgeTalkingEvent.java @@ -6,17 +6,15 @@ * * @since 1.0.0 */ -public class ConfbridgeTalkingEvent extends AbstractConfbridgeEvent -{ +public class ConfbridgeTalkingEvent extends AbstractConfbridgeEvent { /** * Serializable version identifier */ private static final long serialVersionUID = 1L; private Boolean talkingStatus; - - public ConfbridgeTalkingEvent(Object source) - { + + public ConfbridgeTalkingEvent(Object source) { super(source); } @@ -25,8 +23,7 @@ public ConfbridgeTalkingEvent(Object source) * * @param talkingStatus the talking status */ - public void setTalkingStatus(Boolean talkingStatus) - { + public void setTalkingStatus(Boolean talkingStatus) { this.talkingStatus = talkingStatus; } @@ -34,11 +31,10 @@ public void setTalkingStatus(Boolean talkingStatus) * Returns the talking status. * * @return true if the participant started talking, - * false if the participant stopped talking. + * false if the participant stopped talking. */ - public Boolean getTalkingStatus() - { + public Boolean getTalkingStatus() { return talkingStatus; } - + } diff --git a/src/main/java/org/asteriskjava/manager/event/ConnectEvent.java b/src/main/java/org/asteriskjava/manager/event/ConnectEvent.java index a1cbd0593..20a3589a6 100644 --- a/src/main/java/org/asteriskjava/manager/event/ConnectEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ConnectEvent.java @@ -19,13 +19,12 @@ /** * A ConnectEvent is triggered after successful login to the Asterisk server.

      * It is a pseudo event not directly related to an Asterisk generated event. - * + * * @author srt * @version $Id$ * @see org.asteriskjava.manager.event.DisconnectEvent */ -public class ConnectEvent extends ManagerEvent -{ +public class ConnectEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -39,13 +38,11 @@ public class ConnectEvent extends ManagerEvent /** * @param source */ - public ConnectEvent(Object source) - { + public ConnectEvent(Object source) { super(source); } - - public ConnectEvent(Object source, String protocolIdentifier) - { + + public ConnectEvent(Object source, String protocolIdentifier) { this(source); this.protocolIdentifier = protocolIdentifier; } @@ -53,21 +50,19 @@ public ConnectEvent(Object source, String protocolIdentifier) /** * Returns the version of the protocol. For example "Asterisk Call Manager/1.0" for Asterisk up to 1.4 and * "Asterisk Call Manager/1.1" for Asterisk 1.6. - * + * * @return the version of the protocol. */ - public String getProtocolIdentifier() - { + public String getProtocolIdentifier() { return protocolIdentifier; } /** * Sets the version of the protocol. - * + * * @param protocolIdentifier the version of the protocol. */ - public void setProtocolIdentifier(String protocolIdentifier) - { + public void setProtocolIdentifier(String protocolIdentifier) { this.protocolIdentifier = protocolIdentifier; } } diff --git a/src/main/java/org/asteriskjava/manager/event/ContactList.java b/src/main/java/org/asteriskjava/manager/event/ContactList.java index 752597af6..8d23aca21 100644 --- a/src/main/java/org/asteriskjava/manager/event/ContactList.java +++ b/src/main/java/org/asteriskjava/manager/event/ContactList.java @@ -21,13 +21,12 @@ * been reported in response to an PJSipShowContactsAction. *

      * Available since Asterisk 16? - * + * * @author srt * @version $Id$ * @since 3.0 */ -public class ContactList extends ResponseEvent -{ +public class ContactList extends ResponseEvent { /** * Serial version identifier. */ @@ -58,203 +57,164 @@ public class ContactList extends ResponseEvent /** * Creates a new instance. - * + * * @param source */ - public ContactList(Object source) - { + public ContactList(Object source) { super(source); } - public double getQualifyTimeout() - { + public double getQualifyTimeout() { return qualifyTimeout; } - public void setQualifyTimeout(double qualifyTimeout) - { + public void setQualifyTimeout(double qualifyTimeout) { this.qualifyTimeout = qualifyTimeout; } - public String getCallid() - { + public String getCallid() { return callid; } - public void setCallid(String callid) - { + public void setCallid(String callid) { this.callid = callid; } - public String getRegserver() - { + public String getRegserver() { return regserver; } - public void setRegserver(String regserver) - { + public void setRegserver(String regserver) { this.regserver = regserver; } - public String getRoundtripusec() - { + public String getRoundtripusec() { return roundtripusec; } - public void setRoundtripusec(String roundtripusec) - { + public void setRoundtripusec(String roundtripusec) { this.roundtripusec = roundtripusec; } - public long getExpirationtime() - { + public long getExpirationtime() { return expirationtime; } - public void setExpirationtime(long expirationtime) - { + public void setExpirationtime(long expirationtime) { this.expirationtime = expirationtime; } - public String getAuthenticatequalify() - { + public String getAuthenticatequalify() { return authenticatequalify; } - public void setAuthenticatequalify(String authenticatequalify) - { + public void setAuthenticatequalify(String authenticatequalify) { this.authenticatequalify = authenticatequalify; } - public String getObjectname() - { + public String getObjectname() { return objectname; } - public void setObjectname(String objectname) - { + public void setObjectname(String objectname) { this.objectname = objectname; } - public String getUseragent() - { + public String getUseragent() { return useragent; } - public void setUseragent(String useragent) - { + public void setUseragent(String useragent) { this.useragent = useragent; } - public String getUri() - { + public String getUri() { return uri; } - public void setUri(String uri) - { + public void setUri(String uri) { this.uri = uri; } - public String getViaaddr() - { + public String getViaaddr() { return viaaddr; } - public void setViaaddr(String viaaddr) - { + public void setViaaddr(String viaaddr) { this.viaaddr = viaaddr; } - public long getQualifyfrequency() - { + public long getQualifyfrequency() { return qualifyfrequency; } - public void setQualifyfrequency(Long qualifyfrequency) - { + public void setQualifyfrequency(Long qualifyfrequency) { this.qualifyfrequency = qualifyfrequency; } - public String getPath() - { + public String getPath() { return path; } - public void setPath(String path) - { + public void setPath(String path) { this.path = path; } - public String getEndpoint() - { + public String getEndpoint() { return endpoint; } - public void setEndpoint(String endpoint) - { + public void setEndpoint(String endpoint) { this.endpoint = endpoint; } - public String getViaport() - { + public String getViaport() { return viaport; } - public void setViaport(String viaport) - { + public void setViaport(String viaport) { this.viaport = viaport; } - public String getOutboundproxy() - { + public String getOutboundproxy() { return outboundproxy; } - public void setOutboundproxy(String outboundproxy) - { + public void setOutboundproxy(String outboundproxy) { this.outboundproxy = outboundproxy; } - public String getObjecttype() - { + public String getObjecttype() { return objecttype; } - public void setObjecttype(String objecttype) - { + public void setObjecttype(String objecttype) { this.objecttype = objecttype; } - public String getPruneonboot() - { + public String getPruneonboot() { return pruneonboot; } - public void setPruneonboot(String pruneonboot) - { + public void setPruneonboot(String pruneonboot) { this.pruneonboot = pruneonboot; } - public ContactStatusEnum getStatus() - { + public ContactStatusEnum getStatus() { return status; } - public void setStatus(String status) - { + public void setStatus(String status) { this.status = ContactStatusEnum.UNKNOWN; - if (status != null && status.length() > 0) - { + if (status != null && status.length() > 0) { this.status = ContactStatusEnum.valueOf(status.toUpperCase()); } } @Override - public String toString() - { + public String toString() { return "ContactList [qualifyTimeout=" + qualifyTimeout + ", callid=" + callid + ", regserver=" + regserver + ", roundtripusec=" + roundtripusec + ", expirationtime=" + expirationtime + ", authenticatequalify=" + authenticatequalify + ", objectname=" + objectname + ", useragent=" + useragent + ", uri=" + uri diff --git a/src/main/java/org/asteriskjava/manager/event/ContactListComplete.java b/src/main/java/org/asteriskjava/manager/event/ContactListComplete.java index 08cea4cdb..13fb427fd 100644 --- a/src/main/java/org/asteriskjava/manager/event/ContactListComplete.java +++ b/src/main/java/org/asteriskjava/manager/event/ContactListComplete.java @@ -21,16 +21,15 @@ * reported in response to an SIPPeersAction or SIPShowPeerAction. *

      * Available since Asterisk 1.2 - * + * + * @author srt + * @version $Id$ * @see org.asteriskjava.manager.event.PeerEntryEvent * @see org.asteriskjava.manager.action.SipPeersAction * @see org.asteriskjava.manager.action.SipShowPeerAction - * @author srt - * @version $Id$ * @since 0.2 */ -public class ContactListComplete extends ResponseEvent -{ +public class ContactListComplete extends ResponseEvent { /** * Serial version identifier. */ @@ -40,31 +39,28 @@ public class ContactListComplete extends ResponseEvent /** * Creates a new instance. - * + * * @param source */ - public ContactListComplete(Object source) - { + public ContactListComplete(Object source) { super(source); } /** * Returns the number of PeerEvents that have been reported. - * + * * @return the number of PeerEvents that have been reported. */ - public Integer getListItems() - { + public Integer getListItems() { return listItems; } /** * Sets the number of PeerEvents that have been reported. - * + * * @param listItems the number of PeerEvents that have been reported. */ - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } @@ -74,16 +70,14 @@ public void setListItems(Integer listItems) * Available since Asterisk 1.6. * * @return always returns "Complete" confirming that all PeerEntry events - * have been sent. + * have been sent. * @since 1.0.0 */ - public String getEventList() - { + public String getEventList() { return eventList; } - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } } diff --git a/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java index f95839392..efdb18a78 100644 --- a/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java @@ -11,8 +11,7 @@ * @since 12 */ -public class ContactStatusDetail extends ResponseEvent -{ +public class ContactStatusDetail extends ResponseEvent { /** * Serial version identifier. @@ -36,163 +35,131 @@ public class ContactStatusDetail extends ResponseEvent private int qualifyFrequency; private Float qualifyTimeout; - public String getAor() - { + public String getAor() { return aor; } - public void setAor(String aor) - { + public void setAor(String aor) { this.aor = aor; } - public String getStatus() - { + public String getStatus() { return status; } - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } - public String getUri() - { + public String getUri() { return uri; } - public void setUri(String uri) - { + public void setUri(String uri) { this.uri = uri; } - public String getUserAgent() - { + public String getUserAgent() { return userAgent; } - public void setUserAgent(String userAgent) - { + public void setUserAgent(String userAgent) { this.userAgent = userAgent; } - public long getRegExpire() - { + public long getRegExpire() { return regExpire; } - public void setRegExpire(long regExpire) - { + public void setRegExpire(long regExpire) { this.regExpire = regExpire; } - public String getViaAddress() - { + public String getViaAddress() { return viaAddress; } - public void setViaAddress(String viaAddress) - { + public void setViaAddress(String viaAddress) { this.viaAddress = viaAddress; } - public String getCallID() - { + public String getCallID() { return callID; } - public void setCallID(String callID) - { + public void setCallID(String callID) { this.callID = callID; } - public String getEndpointName() - { + public String getEndpointName() { return endpointName; } - public void setEndpointName(String endpointName) - { + public void setEndpointName(String endpointName) { this.endpointName = endpointName; } - public String getId() - { + public String getId() { return id; } - public void setId(String id) - { + public void setId(String id) { this.id = id; } - public Boolean isAuthenticateQualify() - { + public Boolean isAuthenticateQualify() { return authenticateQualify; } - public void setAuthenticateQualify(Boolean authenticateQualify) - { + public void setAuthenticateQualify(Boolean authenticateQualify) { this.authenticateQualify = authenticateQualify; } - public String getOutboundProxy() - { + public String getOutboundProxy() { return outboundProxy; } - public void setOutboundProxy(String outboundProxy) - { + public void setOutboundProxy(String outboundProxy) { this.outboundProxy = outboundProxy; } - public String getPath() - { + public String getPath() { return path; } - public void setPath(String path) - { + public void setPath(String path) { this.path = path; } - public int getQualifyFrequency() - { + public int getQualifyFrequency() { return qualifyFrequency; } - public void setQualifyFrequency(int qualifyFrequency) - { + public void setQualifyFrequency(int qualifyFrequency) { this.qualifyFrequency = qualifyFrequency; } - public Float getQualifyTimeout() - { + public Float getQualifyTimeout() { return qualifyTimeout; } - public void setQualifyTimeout(Float qualifyTimeout) - { + public void setQualifyTimeout(Float qualifyTimeout) { this.qualifyTimeout = qualifyTimeout; } - public void setQualifyTimeout(String qualifyTimeout) - { + public void setQualifyTimeout(String qualifyTimeout) { this.qualifyTimeout = Float.parseFloat(qualifyTimeout); } - public ContactStatusDetail(Object source) - { + public ContactStatusDetail(Object source) { super(source); } - public String getRoundtripUsec() - { + public String getRoundtripUsec() { return roundtripUsec; } - public void setRoundtripUsec(String roundtripUsec) - { + public void setRoundtripUsec(String roundtripUsec) { this.roundtripUsec = roundtripUsec; } diff --git a/src/main/java/org/asteriskjava/manager/event/ContactStatusEnum.java b/src/main/java/org/asteriskjava/manager/event/ContactStatusEnum.java index c7d421529..84443bceb 100644 --- a/src/main/java/org/asteriskjava/manager/event/ContactStatusEnum.java +++ b/src/main/java/org/asteriskjava/manager/event/ContactStatusEnum.java @@ -1,7 +1,6 @@ package org.asteriskjava.manager.event; -public enum ContactStatusEnum -{ +public enum ContactStatusEnum { REACHABLE, UNREACHABLE, NONQUALIFIED, UNKNOWN } diff --git a/src/main/java/org/asteriskjava/manager/event/ContactStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/ContactStatusEvent.java index a2ef9ca1a..eb0b9e463 100644 --- a/src/main/java/org/asteriskjava/manager/event/ContactStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ContactStatusEvent.java @@ -18,19 +18,18 @@ /** * Raised when the state of a contact changes. - * + *

      * Available since Asterisk 13 */ -public class ContactStatusEvent extends ManagerEvent -{ +public class ContactStatusEvent extends ManagerEvent { private static final long serialVersionUID = 0L; - public static final String STATUS_CREATED = "Created"; - public static final String STATUS_REACHABLE = "Reachable"; - public static final String STATUS_REMOVED = "Removed"; - public static final String STATUS_UNKNOWN = "Unknown"; + public static final String STATUS_CREATED = "Created"; + public static final String STATUS_REACHABLE = "Reachable"; + public static final String STATUS_REMOVED = "Removed"; + public static final String STATUS_UNKNOWN = "Unknown"; public static final String STATUS_UNREACHABLE = "Unreachable"; - public static final String STATUS_UPDATED = "Updated"; + public static final String STATUS_UPDATED = "Updated"; private String uri; private String contactStatus; @@ -42,98 +41,79 @@ public class ContactStatusEvent extends ManagerEvent private String viaAddress; private String callID; - public ContactStatusEvent(Object source) - { + public ContactStatusEvent(Object source) { super(source); } - public String getUri() - { + public String getUri() { return uri; } - public void setUri(String value) - { + public void setUri(String value) { this.uri = value; } - public String getContactStatus() - { + public String getContactStatus() { return contactStatus; } - public void setContactStatus(String value) - { + public void setContactStatus(String value) { this.contactStatus = value; } - public String getAor() - { + public String getAor() { return aor; } - public void setAor(String value) - { + public void setAor(String value) { this.aor = value; } - public String getEndpointName() - { + public String getEndpointName() { return endpointName; } - public void setEndpointName(String value) - { + public void setEndpointName(String value) { this.endpointName = value; } - public String getRoundtripUsec() - { + public String getRoundtripUsec() { return roundtripUsec; } - public void setRoundtripUsec(String value) - { + public void setRoundtripUsec(String value) { this.roundtripUsec = value; } - public String getUserAgent() - { + public String getUserAgent() { return userAgent; } - public void setUserAgent(String value) - { + public void setUserAgent(String value) { this.userAgent = value; } - public String getRegExpire() - { + public String getRegExpire() { return regExpire; } - public void setRegExpire(String value) - { + public void setRegExpire(String value) { this.regExpire = value; } - public String getViaAddress() - { + public String getViaAddress() { return viaAddress; } - public void setViaAddress(String value) - { + public void setViaAddress(String value) { this.viaAddress = value; } - public String getCallID() - { + public String getCallID() { return callID; } - public void setCallID(String callID) - { + public void setCallID(String callID) { this.callID = callID; } } diff --git a/src/main/java/org/asteriskjava/manager/event/CoreShowChannelEvent.java b/src/main/java/org/asteriskjava/manager/event/CoreShowChannelEvent.java index c401b272f..3c8ee2225 100644 --- a/src/main/java/org/asteriskjava/manager/event/CoreShowChannelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/CoreShowChannelEvent.java @@ -1,12 +1,12 @@ /* * Copyright 2009 Sebastian. - * + * * 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. @@ -25,8 +25,7 @@ * @see org.asteriskjava.manager.action.CoreShowChannelsAction * @since 1.0.0 */ -public class CoreShowChannelEvent extends ResponseEvent -{ +public class CoreShowChannelEvent extends ResponseEvent { /** * Serializable version identifier. */ @@ -45,8 +44,7 @@ public class CoreShowChannelEvent extends ResponseEvent private String language; - public CoreShowChannelEvent(Object source) - { + public CoreShowChannelEvent(Object source) { super(source); } @@ -61,13 +59,11 @@ public CoreShowChannelEvent(Object source) * * @return accountcode */ - public String getAccountcode() - { + public String getAccountcode() { return accountcode; } - public void setAccountcode(String accountcode) - { + public void setAccountcode(String accountcode) { this.accountcode = accountcode; } @@ -76,13 +72,11 @@ public void setAccountcode(String accountcode) * * @return aplication name */ - public String getApplication() - { + public String getApplication() { return application; } - public void setApplication(String application) - { + public void setApplication(String application) { this.application = application; } @@ -92,13 +86,11 @@ public void setApplication(String application) * * @return aplication data */ - public String getApplicationdata() - { + public String getApplicationdata() { return applicationdata; } - public void setApplicationdata(String applicationdata) - { + public void setApplicationdata(String applicationdata) { this.applicationdata = applicationdata; } @@ -107,13 +99,11 @@ public void setApplicationdata(String applicationdata) * * @return Channel name */ - public String getBridgedChannel() - { + public String getBridgedChannel() { return bridgedChannel; } - public void setBridgedChannel(String bridgedChannel) - { + public void setBridgedChannel(String bridgedChannel) { this.bridgedChannel = bridgedChannel; } @@ -123,14 +113,12 @@ public void setBridgedChannel(String bridgedChannel) * @return uniqueid */ @Deprecated - public String getBridgeduniqueid() - { + public String getBridgeduniqueid() { return bridgeid; } @Deprecated - public void setBridgeduniqueid(String bridgeduniqueid) - { + public void setBridgeduniqueid(String bridgeduniqueid) { this.bridgeid = bridgeduniqueid; } @@ -139,13 +127,11 @@ public void setBridgeduniqueid(String bridgeduniqueid) * * @return uniqueid */ - public String getBridgeid() - { + public String getBridgeid() { return bridgeid; } - public void setBridgeid(String bridgeid) - { + public void setBridgeid(String bridgeid) { this.bridgeid = bridgeid; } @@ -154,13 +140,11 @@ public void setBridgeid(String bridgeid) * * @return Channel name */ - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -169,13 +153,11 @@ public void setChannel(String channel) * * @return duration */ - public String getDuration() - { + public String getDuration() { return duration; } - public void setDuration(String duration) - { + public void setDuration(String duration) { this.duration = duration; } @@ -184,13 +166,11 @@ public void setDuration(String duration) * * @return extension */ - public String getExtension() - { + public String getExtension() { return extension; } - public void setExtension(String extension) - { + public void setExtension(String extension) { this.extension = extension; } @@ -199,13 +179,11 @@ public void setExtension(String extension) * * @return uniqueid */ - public String getUniqueid() - { + public String getUniqueid() { return uniqueid; } - public void setUniqueid(String uniqueid) - { + public void setUniqueid(String uniqueid) { this.uniqueid = uniqueid; } diff --git a/src/main/java/org/asteriskjava/manager/event/CoreShowChannelsCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/CoreShowChannelsCompleteEvent.java index 8bab60ebe..c4276e9c4 100644 --- a/src/main/java/org/asteriskjava/manager/event/CoreShowChannelsCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/CoreShowChannelsCompleteEvent.java @@ -1,12 +1,12 @@ /* * Copyright 2009 Sebastian. - * + * * 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. @@ -26,8 +26,7 @@ * @see org.asteriskjava.manager.event.CoreShowChannelEvent * @since 1.0.0 */ -public class CoreShowChannelsCompleteEvent extends ResponseEvent -{ +public class CoreShowChannelsCompleteEvent extends ResponseEvent { /** * Serial version identifier. @@ -37,8 +36,7 @@ public class CoreShowChannelsCompleteEvent extends ResponseEvent private Integer listitems; private String eventlist; - public CoreShowChannelsCompleteEvent(Object source) - { + public CoreShowChannelsCompleteEvent(Object source) { super(source); } @@ -48,13 +46,11 @@ public CoreShowChannelsCompleteEvent(Object source) * @return the status of the list. * @since 1.0.0 */ - public String getEventlist() - { + public String getEventlist() { return eventlist; } - public void setEventlist(String eventlist) - { + public void setEventlist(String eventlist) { this.eventlist = eventlist; } @@ -63,8 +59,7 @@ public void setEventlist(String eventlist) * * @return the number of channels reported. */ - public Integer getListitems() - { + public Integer getListitems() { return listitems; } @@ -73,8 +68,7 @@ public Integer getListitems() * * @param listitems the number of channels reported. */ - public void setListitems(Integer listitems) - { + public void setListitems(Integer listitems) { this.listitems = listitems; } diff --git a/src/main/java/org/asteriskjava/manager/event/DAHDIChannelEvent.java b/src/main/java/org/asteriskjava/manager/event/DAHDIChannelEvent.java index 2c8a139f4..72134b028 100644 --- a/src/main/java/org/asteriskjava/manager/event/DAHDIChannelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DAHDIChannelEvent.java @@ -1,14 +1,12 @@ - package org.asteriskjava.manager.event; /** * @author Sebastian */ -public class DAHDIChannelEvent extends ManagerEvent -{ +public class DAHDIChannelEvent extends ManagerEvent { /** - * + * */ private static final long serialVersionUID = 1L; private String dahdichannel; @@ -16,48 +14,39 @@ public class DAHDIChannelEvent extends ManagerEvent private String uniqueid; private String channel; - public String getDahdichannel() - { + public String getDahdichannel() { return dahdichannel; } - public void setDahdichannel(String dahdichannel) - { + public void setDahdichannel(String dahdichannel) { this.dahdichannel = dahdichannel; } - public String getDahdispan() - { + public String getDahdispan() { return dahdispan; } - public void setDahdispan(String dahdispan) - { + public void setDahdispan(String dahdispan) { this.dahdispan = dahdispan; } - public String getUniqueid() - { + public String getUniqueid() { return uniqueid; } - public void setUniqueid(String uniqueid) - { + public void setUniqueid(String uniqueid) { this.uniqueid = uniqueid; } - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } - public DAHDIChannelEvent(Object source) - { + public DAHDIChannelEvent(Object source) { super(source); } diff --git a/src/main/java/org/asteriskjava/manager/event/DahdiShowChannelsCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/DahdiShowChannelsCompleteEvent.java index 5945f2fed..8053e1e4e 100644 --- a/src/main/java/org/asteriskjava/manager/event/DahdiShowChannelsCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DahdiShowChannelsCompleteEvent.java @@ -19,15 +19,13 @@ /** * A DahdiShowChannelsCompleteEvent is triggered after the state of all Dahdi channels has been reported * in response to a DahdiShowChannelsAction. - * - * @see org.asteriskjava.manager.action.DahdiShowChannelsAction - * @see org.asteriskjava.manager.event.DahdiShowChannelsEvent - * + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.DahdiShowChannelsAction + * @see org.asteriskjava.manager.event.DahdiShowChannelsEvent */ -public class DahdiShowChannelsCompleteEvent extends ResponseEvent -{ +public class DahdiShowChannelsCompleteEvent extends ResponseEvent { /** * Serial version identifier */ @@ -44,28 +42,25 @@ public Integer getItems() { public void setItems(Integer items) { this.items = items; } - + /** * @param source */ - public DahdiShowChannelsCompleteEvent(Object source) - { + public DahdiShowChannelsCompleteEvent(Object source) { super(source); } - /** + /** * Returns if the status of the eventlist (should be Complete).

      * * @return the status of the list. * @since 1.0.0 */ - public String getEventlist() - { + public String getEventlist() { return eventlist; } - public void setEventlist(String eventlist) - { + public void setEventlist(String eventlist) { this.eventlist = eventlist; } @@ -74,8 +69,7 @@ public void setEventlist(String eventlist) * * @return the number of channels reported. */ - public Integer getListitems() - { + public Integer getListitems() { return listitems; } @@ -84,8 +78,7 @@ public Integer getListitems() * * @param listitems the number of channels reported. */ - public void setListitems(Integer listitems) - { + public void setListitems(Integer listitems) { this.listitems = listitems; } diff --git a/src/main/java/org/asteriskjava/manager/event/DahdiShowChannelsEvent.java b/src/main/java/org/asteriskjava/manager/event/DahdiShowChannelsEvent.java index e878df7b6..38035de39 100644 --- a/src/main/java/org/asteriskjava/manager/event/DahdiShowChannelsEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DahdiShowChannelsEvent.java @@ -19,14 +19,12 @@ /** * A DahdiShowChannelsEvent is triggered in response to a DahdiShowChannelsAction and shows the state of * a Dahdi channel. - * - * @see org.asteriskjava.manager.action.DahdiShowChannelsAction - * + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.DahdiShowChannelsAction */ -public class DahdiShowChannelsEvent extends ResponseEvent -{ +public class DahdiShowChannelsEvent extends ResponseEvent { /** * Serial version identifier */ @@ -81,17 +79,14 @@ public void setUniqueid(String uniqueid) { } - - /** * @param source */ - public DahdiShowChannelsEvent(Object source) - { + public DahdiShowChannelsEvent(Object source) { super(source); } - + /** * Returns the signalling of this Dahdi channel.

      * Possible values are: @@ -121,39 +116,35 @@ public DahdiShowChannelsEvent(Object source) *

    • Pseudo Signalling
    • *
    */ - public String getSignalling() - { + public String getSignalling() { return signalling; } /** * Sets the signalling of this Dahdi channel. */ - public void setSignalling(String signalling) - { + public void setSignalling(String signalling) { this.signalling = signalling; } /** * Returns whether dnd (do not disturb) is enabled for this Dahdi channel. - * + * * @return Boolean.TRUE if dnd is enabled, Boolean.FALSE if it is disabled, - * null if not set. + * null if not set. * @since 0.3 */ - public Boolean getDnd() - { + public Boolean getDnd() { return dnd; } /** * Sets whether dnd (do not disturb) is enabled for this Dahdi channel. - * + * * @param dnd Boolean.TRUE if dnd is enabled, Boolean.FALSE if it is disabled. * @since 0.3 */ - public void setDnd(Boolean dnd) - { + public void setDnd(Boolean dnd) { this.dnd = dnd; } @@ -170,16 +161,14 @@ public void setDnd(Boolean dnd) *
  • No Alarm
  • * */ - public String getAlarm() - { + public String getAlarm() { return alarm; } /** * Sets the alarm state of this Dahdi channel. */ - public void setAlarm(String alarm) - { + public void setAlarm(String alarm) { this.alarm = alarm; } } diff --git a/src/main/java/org/asteriskjava/manager/event/DbGetResponseEvent.java b/src/main/java/org/asteriskjava/manager/event/DbGetResponseEvent.java index b1fdbb3c9..fdd74b35f 100644 --- a/src/main/java/org/asteriskjava/manager/event/DbGetResponseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DbGetResponseEvent.java @@ -20,14 +20,13 @@ * A DBGetResponseEvent is sent in response to a DBGetAction and contains the * entry that was queried.

    * Available since Asterisk 1.2 - * - * @see org.asteriskjava.manager.action.DbGetAction + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.DbGetAction * @since 0.2 */ -public class DbGetResponseEvent extends ResponseEvent -{ +public class DbGetResponseEvent extends ResponseEvent { private String family; private String key; private String val; @@ -40,80 +39,72 @@ public class DbGetResponseEvent extends ResponseEvent /** * @param source */ - public DbGetResponseEvent(Object source) - { + public DbGetResponseEvent(Object source) { super(source); } /** * Returns the family of the database entry that was queried. - * + * * @return the family of the database entry that was queried. */ - public String getFamily() - { + public String getFamily() { return family; } /** * Sets the family of the database entry that was queried. - * + * * @param family the family of the database entry that was queried. */ - public void setFamily(String family) - { + public void setFamily(String family) { this.family = family; } /** * Returns the key of the database entry that was queried. - * + * * @return the key of the database entry that was queried. */ - public String getKey() - { + public String getKey() { return key; } /** * Sets the key of the database entry that was queried. - * + * * @param key the key of the database entry that was queried. */ - public void setKey(String key) - { + public void setKey(String key) { this.key = key; } /** * Returns the value of the database entry that was queried. - * + * * @return the value of the database entry that was queried. */ - public String getVal() - { + public String getVal() { return val; } /** * Sets the value of the database entry that was queried. - * + * * @param val the value of the database entry that was queried. */ - public void setVal(String val) - { + public void setVal(String val) { this.val = val; } - + /** * Sets the value of the database entry that was queried. * It seems that in ast 1.2 ( 1.2.9 +BRIStuff ? ) at least the key is * not val anymore but value. - * + * * @param val the value of the database entry that was queried. */ - public void setValue(String val) - { + public void setValue(String val) { this.val = val; } } diff --git a/src/main/java/org/asteriskjava/manager/event/DeviceStateChangeEvent.java b/src/main/java/org/asteriskjava/manager/event/DeviceStateChangeEvent.java index b4d31d8f9..841a25be4 100644 --- a/src/main/java/org/asteriskjava/manager/event/DeviceStateChangeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DeviceStateChangeEvent.java @@ -1,36 +1,30 @@ package org.asteriskjava.manager.event; -public class DeviceStateChangeEvent extends ManagerEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; - private String state; - private String device; +public class DeviceStateChangeEvent extends ManagerEvent { + /** + * + */ + private static final long serialVersionUID = 1L; + private String state; + private String device; - public String getState() - { - return state; - } + public String getState() { + return state; + } - public void setState(String state) - { - this.state = state; - } + public void setState(String state) { + this.state = state; + } - public String getDevice() - { - return device; - } + public String getDevice() { + return device; + } - public void setDevice(String device) - { - this.device = device; - } + public void setDevice(String device) { + this.device = device; + } - public DeviceStateChangeEvent(Object source) - { - super(source); - } + public DeviceStateChangeEvent(Object source) { + super(source); + } } diff --git a/src/main/java/org/asteriskjava/manager/event/DialBeginEvent.java b/src/main/java/org/asteriskjava/manager/event/DialBeginEvent.java index 09e998455..bba22d876 100644 --- a/src/main/java/org/asteriskjava/manager/event/DialBeginEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DialBeginEvent.java @@ -1,10 +1,9 @@ package org.asteriskjava.manager.event; -public class DialBeginEvent extends DialEvent -{ +public class DialBeginEvent extends DialEvent { /** - * + * */ private static final long serialVersionUID = 1L; private String language; @@ -15,74 +14,60 @@ public class DialBeginEvent extends DialEvent private String accountcode; - public DialBeginEvent(Object source) - { + public DialBeginEvent(Object source) { super(source); setSubEvent(SUBEVENT_BEGIN); } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getDestLanguage() - { + public String getDestLanguage() { return destlanguage; } - public void setDestLanguage(String destlanguage) - { + public void setDestLanguage(String destlanguage) { this.destlanguage = destlanguage; } - public String getDestAccountCode() - { + public String getDestAccountCode() { return destAccountCode; } - public void setDestAccountCode(String destAccountCode) - { + public void setDestAccountCode(String destAccountCode) { this.destAccountCode = destAccountCode; } - public String getDestlanguage() - { + public String getDestlanguage() { return destlanguage; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getDestLinkedId() - { + public String getDestLinkedId() { return destLinkedId; } - public void setDestLinkedId(String destLinkedId) - { + public void setDestLinkedId(String destLinkedId) { this.destLinkedId = destLinkedId; } - public String getAccountcode() - { + public String getAccountcode() { return accountcode; } - public void setAccountcode(String accountcode) - { + public void setAccountcode(String accountcode) { this.accountcode = accountcode; } diff --git a/src/main/java/org/asteriskjava/manager/event/DialEndEvent.java b/src/main/java/org/asteriskjava/manager/event/DialEndEvent.java index 39b459ae9..dcb5be717 100644 --- a/src/main/java/org/asteriskjava/manager/event/DialEndEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DialEndEvent.java @@ -1,9 +1,8 @@ package org.asteriskjava.manager.event; -public class DialEndEvent extends DialEvent -{ +public class DialEndEvent extends DialEvent { /** - * + * */ private static final long serialVersionUID = 1L; private String language; @@ -14,79 +13,64 @@ public class DialEndEvent extends DialEvent private String linkedId; private String forward; - public DialEndEvent(Object source) - { + public DialEndEvent(Object source) { super(source); setSubEvent(SUBEVENT_END); } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getDestLanguage() - { + public String getDestLanguage() { return destLanguage; } - public void setDestLanguage(String destLanguage) - { + public void setDestLanguage(String destLanguage) { this.destLanguage = destLanguage; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - public String getDestAccountCode() - { + public String getDestAccountCode() { return destAccountCode; } - public void setDestAccountCode(String destAccountCode) - { + public void setDestAccountCode(String destAccountCode) { this.destAccountCode = destAccountCode; } - public String getDestLinkedId() - { + public String getDestLinkedId() { return destLinkedId; } - public void setDestLinkedId(String destLinkedId) - { + public void setDestLinkedId(String destLinkedId) { this.destLinkedId = destLinkedId; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getForward() - { + public String getForward() { return forward; } - public void setForward(String forward) - { + public void setForward(String forward) { this.forward = forward; } diff --git a/src/main/java/org/asteriskjava/manager/event/DialEvent.java b/src/main/java/org/asteriskjava/manager/event/DialEvent.java index 7c1c7f0b6..4af7c5e6f 100644 --- a/src/main/java/org/asteriskjava/manager/event/DialEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DialEvent.java @@ -27,8 +27,7 @@ * @version $Id$ * @since 0.2 */ -public class DialEvent extends ManagerEvent -{ +public class DialEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -90,8 +89,7 @@ public class DialEvent extends ManagerEvent private String dialString; private String dialStatus; - public DialEvent(Object source) - { + public DialEvent(Object source) { super(source); } @@ -99,8 +97,7 @@ public DialEvent(Object source) * Enro 2015-03 Workaround to build legacy DialEvent (unsupported in * Asterisk 13) from new DialBeginEvent Asterisk 13. */ - public DialEvent(DialBeginEvent dialBeginEvent) - { + public DialEvent(DialBeginEvent dialBeginEvent) { this(dialBeginEvent.getSource()); setDateReceived(dialBeginEvent.getDateReceived()); setTimestamp(dialBeginEvent.getTimestamp()); @@ -125,16 +122,14 @@ public DialEvent(DialBeginEvent dialBeginEvent) * available except for the dial status. * * @return "Begin" or "End" for Asterisk since 1.6, "Begin" for Asterisk - * prior to 1.6. + * prior to 1.6. * @since 1.0.0 */ - public String getSubEvent() - { + public String getSubEvent() { return subEvent; } - public void setSubEvent(String subEvent) - { + public void setSubEvent(String subEvent) { this.subEvent = subEvent; } @@ -144,8 +139,7 @@ public void setSubEvent(String subEvent) * @return the name of the source channel. * @since 1.0.0 */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -155,8 +149,7 @@ public String getChannel() * @param channel the name of the source channel. * @since 1.0.0 */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -167,8 +160,7 @@ public void setChannel(String channel) * @deprecated as of 1.0.0, use {@link #getChannel()} instead. */ @Deprecated - public String getSrc() - { + public String getSrc() { return channel; } @@ -180,8 +172,7 @@ public String getSrc() * * @param src the name of the source channel. */ - public void setSrc(String src) - { + public void setSrc(String src) { this.channel = src; } @@ -190,13 +181,11 @@ public void setSrc(String src) * * @return the name of the destination channel. */ - public String getDestination() - { + public String getDestination() { return destination; } - public String getDestChannel() - { + public String getDestChannel() { return getDestination(); } @@ -205,13 +194,11 @@ public String getDestChannel() * * @param destination the name of the destination channel. */ - public void setDestination(String destination) - { + public void setDestination(String destination) { this.destination = destination; } - public void setDestChannel(String destination) - { + public void setDestChannel(String destination) { setDestination(destination); } @@ -222,8 +209,7 @@ public void setDestChannel(String destination) * @deprecated as of 1.0.0, use {@link #getCallerIdNum()} instead. */ @Deprecated - public String getCallerId() - { + public String getCallerId() { return getCallerIdNum(); } @@ -234,8 +220,7 @@ public String getCallerId() * @deprecated as of 1.0.0, use {@link #setCallerIdNum()} instead. */ @Deprecated - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { setCallerIdNum(callerId); } @@ -245,8 +230,7 @@ public void setCallerId(String callerId) * @return the unique ID of the source channel. * @since 1.0.0 */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } @@ -256,8 +240,7 @@ public String getUniqueId() * @param srcUniqueId the unique ID of the source channel. * @since 1.0.0 */ - public void setUniqueId(String srcUniqueId) - { + public void setUniqueId(String srcUniqueId) { this.uniqueId = srcUniqueId; } @@ -268,8 +251,7 @@ public void setUniqueId(String srcUniqueId) * @deprecated as of 1.0.0, use {@link #getUniqueId()} instead. */ @Deprecated - public String getSrcUniqueId() - { + public String getSrcUniqueId() { return uniqueId; } @@ -281,8 +263,7 @@ public String getSrcUniqueId() * * @param srcUniqueId the unique ID of the source channel. */ - public void setSrcUniqueId(String srcUniqueId) - { + public void setSrcUniqueId(String srcUniqueId) { this.uniqueId = srcUniqueId; } @@ -291,8 +272,7 @@ public void setSrcUniqueId(String srcUniqueId) * * @return the unique ID of the destination channel. */ - public String getDestUniqueId() - { + public String getDestUniqueId() { return destUniqueId; } @@ -301,8 +281,7 @@ public String getDestUniqueId() * * @param destUniqueId the unique ID of the destination channel. */ - public void setDestUniqueId(String destUniqueId) - { + public void setDestUniqueId(String destUniqueId) { this.destUniqueId = destUniqueId; } @@ -314,8 +293,7 @@ public void setDestUniqueId(String destUniqueId) * @return the dial string passed to the Dial application. * @since 1.0.0 */ - public String getDialString() - { + public String getDialString() { return dialString; } @@ -325,8 +303,7 @@ public String getDialString() * @param dialString the dial string passed to the Dial application. * @since 1.0.0 */ - public void setDialString(String dialString) - { + public void setDialString(String dialString) { this.dialString = dialString; } @@ -352,19 +329,16 @@ public void setDialString(String dialString) * @return the completion status of the dial application. * @since 1.0.0 */ - public String getDialStatus() - { + public String getDialStatus() { return dialStatus; } - public void setDialStatus(String dialStatus) - { + public void setDialStatus(String dialStatus) { this.dialStatus = dialStatus; } @Override - public String toString() - { + public String toString() { StringBuilder builder = new StringBuilder(); builder.append("DialEvent [subEvent="); builder.append(subEvent); @@ -392,93 +366,75 @@ public String toString() return builder.toString(); } - public Integer getDestChannelState() - { + public Integer getDestChannelState() { return destChannelState; } - public void setDestChannelState(Integer destChannelState) - { + public void setDestChannelState(Integer destChannelState) { this.destChannelState = destChannelState; } - public String getDestContext() - { + public String getDestContext() { return destContext; } - public void setDestContext(String destContext) - { + public void setDestContext(String destContext) { this.destContext = destContext; } - public Integer getDestPriority() - { + public Integer getDestPriority() { return destPriority; } - public void setDestPriority(Integer destPriority) - { + public void setDestPriority(Integer destPriority) { this.destPriority = destPriority; } - public String getDestChannelStateDesc() - { + public String getDestChannelStateDesc() { return destChannelStateDesc; } - public void setDestChannelStateDesc(String destChannelStateDesc) - { + public void setDestChannelStateDesc(String destChannelStateDesc) { this.destChannelStateDesc = destChannelStateDesc; } - public String getDestExten() - { + public String getDestExten() { return destExten; } - public void setDestExten(String destExten) - { + public void setDestExten(String destExten) { this.destExten = destExten; } - public String getDestConnectedLineName() - { + public String getDestConnectedLineName() { return destConnectedLineName; } - public void setDestConnectedLineName(String destConnectedLineName) - { + public void setDestConnectedLineName(String destConnectedLineName) { this.destConnectedLineName = destConnectedLineName; } - public String getDestConnectedLineNum() - { + public String getDestConnectedLineNum() { return destConnectedLineNum; } - public void setDestConnectedLineNum(String destConnectedLineNum) - { + public void setDestConnectedLineNum(String destConnectedLineNum) { this.destConnectedLineNum = destConnectedLineNum; } - public String getDestCallerIdName() - { + public String getDestCallerIdName() { return destCallerIdName; } - public void setDestCallerIdName(String destCallerIdName) - { + public void setDestCallerIdName(String destCallerIdName) { this.destCallerIdName = destCallerIdName; } - public String getDestCallerIdNum() - { + public String getDestCallerIdNum() { return destCallerIdNum; } - public void setDestCallerIdNum(String destCallerIdNum) - { + public void setDestCallerIdNum(String destCallerIdNum) { this.destCallerIdNum = destCallerIdNum; } } diff --git a/src/main/java/org/asteriskjava/manager/event/DialStateEvent.java b/src/main/java/org/asteriskjava/manager/event/DialStateEvent.java index ed22a173e..7e6ce09c6 100644 --- a/src/main/java/org/asteriskjava/manager/event/DialStateEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DialStateEvent.java @@ -16,8 +16,7 @@ */ package org.asteriskjava.manager.event; -public class DialStateEvent extends ManagerEvent -{ +public class DialStateEvent extends ManagerEvent { private static final long serialVersionUID = 1L; String destAccountCode; @@ -42,218 +41,175 @@ public class DialStateEvent extends ManagerEvent String language; String channel; - public DialStateEvent(Object source) - { + public DialStateEvent(Object source) { super(source); } - public String getDestAccountCode() - { + public String getDestAccountCode() { return destAccountCode; } - public void setDestAccountCode(String destAccountCode) - { + public void setDestAccountCode(String destAccountCode) { this.destAccountCode = destAccountCode; } - public String getDestCallerIdName() - { + public String getDestCallerIdName() { return destCallerIdName; } - public void setDestCallerIdName(String destCallerIdName) - { + public void setDestCallerIdName(String destCallerIdName) { this.destCallerIdName = destCallerIdName; } - public String getDestCallerIdNum() - { + public String getDestCallerIdNum() { return destCallerIdNum; } - public void setDestCallerIdNum(String destCallerIdNum) - { + public void setDestCallerIdNum(String destCallerIdNum) { this.destCallerIdNum = destCallerIdNum; } - public String getDestChannel() - { + public String getDestChannel() { return destChannel; } - public void setDestChannel(String destChannel) - { + public void setDestChannel(String destChannel) { this.destChannel = destChannel; } - public String getDestChannelState() - { + public String getDestChannelState() { return destChannelState; } - public void setDestChannelState(String destChannelState) - { + public void setDestChannelState(String destChannelState) { this.destChannelState = destChannelState; } - public String getDestChannelStateDesc() - { + public String getDestChannelStateDesc() { return destChannelStateDesc; } - public void setDestChannelStateDesc(String destChannelStateDesc) - { + public void setDestChannelStateDesc(String destChannelStateDesc) { this.destChannelStateDesc = destChannelStateDesc; } - public String getDestConnectedLineName() - { + public String getDestConnectedLineName() { return destConnectedLineName; } - public void setDestConnectedLineName(String destConnectedLineName) - { + public void setDestConnectedLineName(String destConnectedLineName) { this.destConnectedLineName = destConnectedLineName; } - public String getDestConnectedLineNum() - { + public String getDestConnectedLineNum() { return destConnectedLineNum; } - public void setDestConnectedLineNum(String destConnectedLineNum) - { + public void setDestConnectedLineNum(String destConnectedLineNum) { this.destConnectedLineNum = destConnectedLineNum; } - public String getDestContext() - { + public String getDestContext() { return destContext; } - public void setDestContext(String destContext) - { + public void setDestContext(String destContext) { this.destContext = destContext; } - public String getDestExten() - { + public String getDestExten() { return destExten; } - public void setDestExten(String destExten) - { + public void setDestExten(String destExten) { this.destExten = destExten; } - public String getDestLanguage() - { + public String getDestLanguage() { return destLanguage; } - public void setDestLanguage(String destLanguage) - { + public void setDestLanguage(String destLanguage) { this.destLanguage = destLanguage; } - public String getDestLinkedId() - { + public String getDestLinkedId() { return destLinkedId; } - public void setDestLinkedId(String destLinkedId) - { + public void setDestLinkedId(String destLinkedId) { this.destLinkedId = destLinkedId; } - public String getDestPriority() - { + public String getDestPriority() { return destPriority; } - public void setDestPriority(String destPriority) - { + public void setDestPriority(String destPriority) { this.destPriority = destPriority; } - public String getDestUniqueId() - { + public String getDestUniqueId() { return destUniqueId; } - public void setDestUniqueId(String destUniqueId) - { + public void setDestUniqueId(String destUniqueId) { this.destUniqueId = destUniqueId; } - public String getDialStatus() - { + public String getDialStatus() { return dialStatus; } - public void setDialStatus(String dialStatus) - { + public void setDialStatus(String dialStatus) { this.dialStatus = dialStatus; } - public String getPrivilege() - { + public String getPrivilege() { return privilege; } - public void setPrivilege(String privilege) - { + public void setPrivilege(String privilege) { this.privilege = privilege; } - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } } diff --git a/src/main/java/org/asteriskjava/manager/event/DisconnectEvent.java b/src/main/java/org/asteriskjava/manager/event/DisconnectEvent.java index 129490d26..7ce68e4f3 100644 --- a/src/main/java/org/asteriskjava/manager/event/DisconnectEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DisconnectEvent.java @@ -19,13 +19,12 @@ /** * A DisconnectEvent is triggered when the connection to the asterisk server is lost.

    * It is a pseudo event not directly related to an Asterisk generated event. - * + * * @author srt * @version $Id$ * @see org.asteriskjava.manager.event.ConnectEvent */ -public class DisconnectEvent extends ManagerEvent -{ +public class DisconnectEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -34,8 +33,7 @@ public class DisconnectEvent extends ManagerEvent /** * @param source */ - public DisconnectEvent(Object source) - { + public DisconnectEvent(Object source) { super(source); } } diff --git a/src/main/java/org/asteriskjava/manager/event/DndStateEvent.java b/src/main/java/org/asteriskjava/manager/event/DndStateEvent.java index 7af8b31e2..1e4e4bccf 100644 --- a/src/main/java/org/asteriskjava/manager/event/DndStateEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DndStateEvent.java @@ -21,13 +21,12 @@ * or leaves DND (do not disturb) state.

    * It is implemented in channels/chan_zap.c.

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class DndStateEvent extends ManagerEvent -{ +public class DndStateEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -45,11 +44,10 @@ public class DndStateEvent extends ManagerEvent /** * Creates a new DNDStateEvent. - * + * * @param source */ - public DndStateEvent(Object source) - { + public DndStateEvent(Object source) { super(source); } @@ -57,34 +55,30 @@ public DndStateEvent(Object source) * Returns the name of the channel. The channel name is of the form * "Zap/<channel number>". */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns DND state of the channel. - * + * * @return Boolean.TRUE if do not disturb is on, Boolean.FALSE if it is off. */ - public Boolean getState() - { + public Boolean getState() { return state; } /** * Sets the DND state of the channel. */ - public void setState(Boolean state) - { + public void setState(Boolean state) { this.state = state; } } diff --git a/src/main/java/org/asteriskjava/manager/event/DongleCENDEvent.java b/src/main/java/org/asteriskjava/manager/event/DongleCENDEvent.java index 6d8382908..4911a06f1 100644 --- a/src/main/java/org/asteriskjava/manager/event/DongleCENDEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DongleCENDEvent.java @@ -1,28 +1,25 @@ package org.asteriskjava.manager.event; -public class DongleCENDEvent extends ManagerEvent -{ - private static final long serialVersionUID = 3257845467831284784L; - private String device; - private String endstatus; - private String cccause; - private String duration; - private String callidx; - - - - public DongleCENDEvent(Object source) - { - super(source); - } - - public String getDevice() { - return this.device; - } - - public void setDevice(String device) { - this.device = device; - } +public class DongleCENDEvent extends ManagerEvent { + private static final long serialVersionUID = 3257845467831284784L; + private String device; + private String endstatus; + private String cccause; + private String duration; + private String callidx; + + + public DongleCENDEvent(Object source) { + super(source); + } + + public String getDevice() { + return this.device; + } + + public void setDevice(String device) { + this.device = device; + } public String getCallidx() { return callidx; @@ -56,8 +53,5 @@ public void setEndstatus(String endstatus) { this.endstatus = endstatus; } - - - -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/DongleCallStateChangeEvent.java b/src/main/java/org/asteriskjava/manager/event/DongleCallStateChangeEvent.java index 59e16e263..1c32b334d 100644 --- a/src/main/java/org/asteriskjava/manager/event/DongleCallStateChangeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DongleCallStateChangeEvent.java @@ -1,24 +1,22 @@ package org.asteriskjava.manager.event; -public class DongleCallStateChangeEvent extends ManagerEvent -{ - private static final long serialVersionUID = 3257845467831284784L; - private String device; - private String callidx; - private String newstate; - - public DongleCallStateChangeEvent(Object source) - { - super(source); - } - - public String getDevice() { - return this.device; - } - - public void setDevice(String device) { - this.device = device; - } +public class DongleCallStateChangeEvent extends ManagerEvent { + private static final long serialVersionUID = 3257845467831284784L; + private String device; + private String callidx; + private String newstate; + + public DongleCallStateChangeEvent(Object source) { + super(source); + } + + public String getDevice() { + return this.device; + } + + public void setDevice(String device) { + this.device = device; + } public String getCallidx() { return callidx; @@ -36,6 +34,5 @@ public void setNewstate(String newstate) { this.newstate = newstate; } - -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/DongleDeviceEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/DongleDeviceEntryEvent.java index 1ef740d86..08020c101 100644 --- a/src/main/java/org/asteriskjava/manager/event/DongleDeviceEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DongleDeviceEntryEvent.java @@ -1,10 +1,9 @@ package org.asteriskjava.manager.event; -public class DongleDeviceEntryEvent extends ResponseEvent -{ +public class DongleDeviceEntryEvent extends ResponseEvent { /** - * + * */ private static final long serialVersionUID = 1L; private String Device; @@ -65,568 +64,455 @@ public class DongleDeviceEntryEvent extends ResponseEvent private String Releasing; private String Initializing; - public DongleDeviceEntryEvent(Object source) - { + public DongleDeviceEntryEvent(Object source) { super(source); } - public String getDevice() - { + public String getDevice() { return Device; } - public void setDevice(String Device) - { + public void setDevice(String Device) { this.Device = Device; } - public String getAudioSetting() - { + public String getAudioSetting() { return AudioSetting; } - public void setAudioSetting(String AudioSetting) - { + public void setAudioSetting(String AudioSetting) { this.AudioSetting = AudioSetting; } - public String getDataSetting() - { + public String getDataSetting() { return DataSetting; } - public void setDataSetting(String DataSetting) - { + public void setDataSetting(String DataSetting) { this.DataSetting = DataSetting; } - public String getIMEISetting() - { + public String getIMEISetting() { return IMEISetting; } - public void setIMEISetting(String IMEISetting) - { + public void setIMEISetting(String IMEISetting) { this.IMEISetting = IMEISetting; } - public String getIMSISetting() - { + public String getIMSISetting() { return IMSISetting; } - public void setIMSISetting(String IMSISetting) - { + public void setIMSISetting(String IMSISetting) { this.IMSISetting = IMSISetting; } - public String getChannelLanguage() - { + public String getChannelLanguage() { return ChannelLanguage; } - public void setChannelLanguage(String ChannelLanguage) - { + public void setChannelLanguage(String ChannelLanguage) { this.ChannelLanguage = ChannelLanguage; } - public String getGroup() - { + public String getGroup() { return Group; } - public void setGroup(String Group) - { + public void setGroup(String Group) { this.Group = Group; } - public String getRXGain() - { + public String getRXGain() { return RXGain; } - public void setRXGain(String RXGain) - { + public void setRXGain(String RXGain) { this.RXGain = RXGain; } - public String getTXGain() - { + public String getTXGain() { return TXGain; } - public void setTXGain(String TXGain) - { + public void setTXGain(String TXGain) { this.TXGain = TXGain; } - public String getU2DIAG() - { + public String getU2DIAG() { return U2DIAG; } - public void setU2DIAG(String U2DIAG) - { + public void setU2DIAG(String U2DIAG) { this.U2DIAG = U2DIAG; } - public String getUseCallingPres() - { + public String getUseCallingPres() { return UseCallingPres; } - public void setUseCallingPres(String UseCallingPres) - { + public void setUseCallingPres(String UseCallingPres) { this.UseCallingPres = UseCallingPres; } - public String getDefaultCallingPres() - { + public String getDefaultCallingPres() { return DefaultCallingPres; } - public void setDefaultCallingPres(String DefaultCallingPres) - { + public void setDefaultCallingPres(String DefaultCallingPres) { this.DefaultCallingPres = DefaultCallingPres; } - public String getAutoDeleteSMS() - { + public String getAutoDeleteSMS() { return AutoDeleteSMS; } - public void setAutoDeleteSMS(String AutoDeleteSMS) - { + public void setAutoDeleteSMS(String AutoDeleteSMS) { this.AutoDeleteSMS = AutoDeleteSMS; } - public String getDisableSMS() - { + public String getDisableSMS() { return DisableSMS; } - public void setDisableSMS(String DisableSMS) - { + public void setDisableSMS(String DisableSMS) { this.DisableSMS = DisableSMS; } - public String getResetDongle() - { + public String getResetDongle() { return ResetDongle; } - public void setResetDongle(String ResetDongle) - { + public void setResetDongle(String ResetDongle) { this.ResetDongle = ResetDongle; } - public String getSMSPDU() - { + public String getSMSPDU() { return SMSPDU; } - public void setSMSPDU(String SMSPDU) - { + public void setSMSPDU(String SMSPDU) { this.SMSPDU = SMSPDU; } - public String getCallWaitingSetting() - { + public String getCallWaitingSetting() { return CallWaitingSetting; } - public void setCallWaitingSetting(String CallWaitingSetting) - { + public void setCallWaitingSetting(String CallWaitingSetting) { this.CallWaitingSetting = CallWaitingSetting; } - public String getDTMF() - { + public String getDTMF() { return DTMF; } - public void setDTMF(String DTMF) - { + public void setDTMF(String DTMF) { this.DTMF = DTMF; } - public String getMinimalDTMFGap() - { + public String getMinimalDTMFGap() { return MinimalDTMFGap; } - public void setMinimalDTMFGap(String MinimalDTMFGap) - { + public void setMinimalDTMFGap(String MinimalDTMFGap) { this.MinimalDTMFGap = MinimalDTMFGap; } - public String getMinimalDTMFDuration() - { + public String getMinimalDTMFDuration() { return MinimalDTMFDuration; } - public void setMinimalDTMFDuration(String MinimalDTMFDuration) - { + public void setMinimalDTMFDuration(String MinimalDTMFDuration) { this.MinimalDTMFDuration = MinimalDTMFDuration; } - public String getMinimalDTMFInterval() - { + public String getMinimalDTMFInterval() { return MinimalDTMFInterval; } - public void setMinimalDTMFInterval(String MinimalDTMFInterval) - { + public void setMinimalDTMFInterval(String MinimalDTMFInterval) { this.MinimalDTMFInterval = MinimalDTMFInterval; } - public String getState() - { + public String getState() { return State; } - public void setState(String State) - { + public void setState(String State) { this.State = State; } - public String getAudioState() - { + public String getAudioState() { return AudioState; } - public void setAudioState(String AudioState) - { + public void setAudioState(String AudioState) { this.AudioState = AudioState; } - public String getDataState() - { + public String getDataState() { return DataState; } - public void setDataState(String DataState) - { + public void setDataState(String DataState) { this.DataState = DataState; } - public String getVoice() - { + public String getVoice() { return Voice; } - public void setVoice(String Voice) - { + public void setVoice(String Voice) { this.Voice = Voice; } - public String getSMS() - { + public String getSMS() { return SMS; } - public void setSMS(String SMS) - { + public void setSMS(String SMS) { this.SMS = SMS; } - public String getManufacturer() - { + public String getManufacturer() { return Manufacturer; } - public void setManufacturer(String Manufacturer) - { + public void setManufacturer(String Manufacturer) { this.Manufacturer = Manufacturer; } - public String getModel() - { + public String getModel() { return Model; } - public void setModel(String Model) - { + public void setModel(String Model) { this.Model = Model; } - public String getFirmware() - { + public String getFirmware() { return Firmware; } - public void setFirmware(String Firmware) - { + public void setFirmware(String Firmware) { this.Firmware = Firmware; } - public String getIMEIState() - { + public String getIMEIState() { return IMEIState; } - public void setIMEIState(String IMEIState) - { + public void setIMEIState(String IMEIState) { this.IMEIState = IMEIState; } - public String getGSMRegistrationStatus() - { + public String getGSMRegistrationStatus() { return GSMRegistrationStatus; } - public void setGSMRegistrationStatus(String GSMRegistrationStatus) - { + public void setGSMRegistrationStatus(String GSMRegistrationStatus) { this.GSMRegistrationStatus = GSMRegistrationStatus; } - public String getRSSI() - { + public String getRSSI() { return RSSI; } - public void setRSSI(String RSSI) - { + public void setRSSI(String RSSI) { this.RSSI = RSSI; } - public String getMode() - { + public String getMode() { return Mode; } - public void setMode(String Mode) - { + public void setMode(String Mode) { this.Mode = Mode; } - public String getSubmode() - { + public String getSubmode() { return Submode; } - public void setSubmode(String Submode) - { + public void setSubmode(String Submode) { this.Submode = Submode; } - public String getProviderName() - { + public String getProviderName() { return ProviderName; } - public void setProviderName(String ProviderName) - { + public void setProviderName(String ProviderName) { this.ProviderName = ProviderName; } - public String getLocationAreaCode() - { + public String getLocationAreaCode() { return LocationAreaCode; } - public void setLocationAreaCode(String LocationAreaCode) - { + public void setLocationAreaCode(String LocationAreaCode) { this.LocationAreaCode = LocationAreaCode; } - public String getCellID() - { + public String getCellID() { return CellID; } - public void setCellID(String CellID) - { + public void setCellID(String CellID) { this.CellID = CellID; } - public String getSubscriberNumber() - { + public String getSubscriberNumber() { return SubscriberNumber; } - public void setSubscriberNumber(String SubscriberNumber) - { + public void setSubscriberNumber(String SubscriberNumber) { this.SubscriberNumber = SubscriberNumber; } - public String getSMSServiceCenter() - { + public String getSMSServiceCenter() { return SMSServiceCenter; } - public void setSMSServiceCenter(String SMSServiceCenter) - { + public void setSMSServiceCenter(String SMSServiceCenter) { this.SMSServiceCenter = SMSServiceCenter; } - public String getUseUCS2Encoding() - { + public String getUseUCS2Encoding() { return UseUCS2Encoding; } - public void setUseUCS2Encoding(String UseUCS2Encoding) - { + public void setUseUCS2Encoding(String UseUCS2Encoding) { this.UseUCS2Encoding = UseUCS2Encoding; } - public String getUSSDUse7BitEncoding() - { + public String getUSSDUse7BitEncoding() { return USSDUse7BitEncoding; } - public void setUSSDUse7BitEncoding(String USSDUse7BitEncoding) - { + public void setUSSDUse7BitEncoding(String USSDUse7BitEncoding) { this.USSDUse7BitEncoding = USSDUse7BitEncoding; } - public String getUSSDUseUCS2Decoding() - { + public String getUSSDUseUCS2Decoding() { return USSDUseUCS2Decoding; } - public void setUSSDUseUCS2Decoding(String USSDUseUCS2Decoding) - { + public void setUSSDUseUCS2Decoding(String USSDUseUCS2Decoding) { this.USSDUseUCS2Decoding = USSDUseUCS2Decoding; } - public String getTasksInQueue() - { + public String getTasksInQueue() { return TasksInQueue; } - public void setTasksInQueue(String TasksInQueue) - { + public void setTasksInQueue(String TasksInQueue) { this.TasksInQueue = TasksInQueue; } - public String getCommandsInQueue() - { + public String getCommandsInQueue() { return CommandsInQueue; } - public void setCommandsInQueue(String CommandsInQueue) - { + public void setCommandsInQueue(String CommandsInQueue) { this.CommandsInQueue = CommandsInQueue; } - public String getCallWaitingState() - { + public String getCallWaitingState() { return CallWaitingState; } - public void setCallWaitingState(String CallWaitingState) - { + public void setCallWaitingState(String CallWaitingState) { this.CallWaitingState = CallWaitingState; } - public String getCurrentDeviceState() - { + public String getCurrentDeviceState() { return CurrentDeviceState; } - public void setCurrentDeviceState(String CurrentDeviceState) - { + public void setCurrentDeviceState(String CurrentDeviceState) { this.CurrentDeviceState = CurrentDeviceState; } - public String getDesiredDeviceState() - { + public String getDesiredDeviceState() { return DesiredDeviceState; } - public void setDesiredDeviceState(String DesiredDeviceState) - { + public void setDesiredDeviceState(String DesiredDeviceState) { this.DesiredDeviceState = DesiredDeviceState; } - public String getCallsChannels() - { + public String getCallsChannels() { return CallsChannels; } - public void setCallsChannels(String CallsChannels) - { + public void setCallsChannels(String CallsChannels) { this.CallsChannels = CallsChannels; } - public String getActive() - { + public String getActive() { return Active; } - public void setActive(String Active) - { + public void setActive(String Active) { this.Active = Active; } - public String getHeld() - { + public String getHeld() { return Held; } - public void setHeld(String Held) - { + public void setHeld(String Held) { this.Held = Held; } - public String getDialing() - { + public String getDialing() { return Dialing; } - public void setDialing(String Dialing) - { + public void setDialing(String Dialing) { this.Dialing = Dialing; } - public String getAlerting() - { + public String getAlerting() { return Alerting; } - public void setAlerting(String Alerting) - { + public void setAlerting(String Alerting) { this.Alerting = Alerting; } - public String getIncoming() - { + public String getIncoming() { return Incoming; } - public void setIncoming(String Incoming) - { + public void setIncoming(String Incoming) { this.Incoming = Incoming; } - public String getWaiting() - { + public String getWaiting() { return Waiting; } - public void setWaiting(String Waiting) - { + public void setWaiting(String Waiting) { this.Waiting = Waiting; } - public String getReleasing() - { + public String getReleasing() { return Releasing; } - public void setReleasing(String Releasing) - { + public void setReleasing(String Releasing) { this.Releasing = Releasing; } - public String getInitializing() - { + public String getInitializing() { return Initializing; } - public void setInitializing(String Initializing) - { + public void setInitializing(String Initializing) { this.Initializing = Initializing; } diff --git a/src/main/java/org/asteriskjava/manager/event/DongleNewCMGREvent.java b/src/main/java/org/asteriskjava/manager/event/DongleNewCMGREvent.java index 6f58b2d70..cbc3d457a 100644 --- a/src/main/java/org/asteriskjava/manager/event/DongleNewCMGREvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DongleNewCMGREvent.java @@ -1,22 +1,18 @@ package org.asteriskjava.manager.event; -public class DongleNewCMGREvent extends ManagerEvent -{ +public class DongleNewCMGREvent extends ManagerEvent { private static final long serialVersionUID = 3257845467831284784L; private String device; - public DongleNewCMGREvent(Object source) - { + public DongleNewCMGREvent(Object source) { super(source); } - public String getDevice() - { + public String getDevice() { return this.device; } - public void setDevice(String device) - { + public void setDevice(String device) { this.device = device; } diff --git a/src/main/java/org/asteriskjava/manager/event/DongleNewSMSBase64Event.java b/src/main/java/org/asteriskjava/manager/event/DongleNewSMSBase64Event.java index 9f1535cdb..ba794e9e3 100644 --- a/src/main/java/org/asteriskjava/manager/event/DongleNewSMSBase64Event.java +++ b/src/main/java/org/asteriskjava/manager/event/DongleNewSMSBase64Event.java @@ -1,38 +1,36 @@ package org.asteriskjava.manager.event; -public class DongleNewSMSBase64Event extends ManagerEvent -{ - private static final long serialVersionUID = 3257845467831284784L; - private String from; - private String message; - private String device; - - public DongleNewSMSBase64Event(Object source) - { - super(source); - } - - public String getDevice() { - return this.device; - } - - public void setDevice(String device) { - this.device = device; - } - - public String getFrom() { - return this.from; - } - - public void setFrom(String from) { - this.from = from; - } - - public String getMessage() { - return this.message; - } - - public void setMessage(String message) { - this.message = message; - } -} \ No newline at end of file +public class DongleNewSMSBase64Event extends ManagerEvent { + private static final long serialVersionUID = 3257845467831284784L; + private String from; + private String message; + private String device; + + public DongleNewSMSBase64Event(Object source) { + super(source); + } + + public String getDevice() { + return this.device; + } + + public void setDevice(String device) { + this.device = device; + } + + public String getFrom() { + return this.from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getMessage() { + return this.message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/DongleNewSMSEvent.java b/src/main/java/org/asteriskjava/manager/event/DongleNewSMSEvent.java index 81fce3390..b6d07b1f0 100644 --- a/src/main/java/org/asteriskjava/manager/event/DongleNewSMSEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DongleNewSMSEvent.java @@ -1,34 +1,32 @@ package org.asteriskjava.manager.event; -public class DongleNewSMSEvent extends ManagerEvent -{ - private static final long serialVersionUID = 3257845467831284784L; - private String from; - private String messageline0; - private String device; - private String linecount; - - - public DongleNewSMSEvent(Object source) - { - super(source); - } - - public String getDevice() { - return this.device; - } - - public void setDevice(String device) { - this.device = device; - } - - public String getFrom() { - return this.from; - } - - public void setFrom(String from) { - this.from = from; - } +public class DongleNewSMSEvent extends ManagerEvent { + private static final long serialVersionUID = 3257845467831284784L; + private String from; + private String messageline0; + private String device; + private String linecount; + + + public DongleNewSMSEvent(Object source) { + super(source); + } + + public String getDevice() { + return this.device; + } + + public void setDevice(String device) { + this.device = device; + } + + public String getFrom() { + return this.from; + } + + public void setFrom(String from) { + this.from = from; + } public String getLinecount() { return linecount; @@ -47,4 +45,4 @@ public void setMessageline0(String messageline0) { } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/DongleShowDevicesCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/DongleShowDevicesCompleteEvent.java index 45b3f0de1..c61e690ea 100644 --- a/src/main/java/org/asteriskjava/manager/event/DongleShowDevicesCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DongleShowDevicesCompleteEvent.java @@ -19,15 +19,13 @@ /** * A DahdiShowChannelsCompleteEvent is triggered after the state of all Dahdi channels has been reported * in response to a DahdiShowChannelsAction. - * - * @see org.asteriskjava.manager.action.DahdiShowChannelsAction - * @see org.asteriskjava.manager.event.DahdiShowChannelsEvent - * + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.DahdiShowChannelsAction + * @see org.asteriskjava.manager.event.DahdiShowChannelsEvent */ -public class DongleShowDevicesCompleteEvent extends ResponseEvent -{ +public class DongleShowDevicesCompleteEvent extends ResponseEvent { /** * Serial version identifier */ @@ -44,28 +42,25 @@ public Integer getItems() { public void setItems(Integer items) { this.items = items; } - + /** * @param source */ - public DongleShowDevicesCompleteEvent(Object source) - { + public DongleShowDevicesCompleteEvent(Object source) { super(source); } - /** + /** * Returns if the status of the eventlist (should be Complete).

    * * @return the status of the list. * @since 1.0.0 */ - public String getEventlist() - { + public String getEventlist() { return eventlist; } - public void setEventlist(String eventlist) - { + public void setEventlist(String eventlist) { this.eventlist = eventlist; } @@ -74,8 +69,7 @@ public void setEventlist(String eventlist) * * @return the number of channels reported. */ - public Integer getListitems() - { + public Integer getListitems() { return listitems; } @@ -84,8 +78,7 @@ public Integer getListitems() * * @param listitems the number of channels reported. */ - public void setListitems(Integer listitems) - { + public void setListitems(Integer listitems) { this.listitems = listitems; } diff --git a/src/main/java/org/asteriskjava/manager/event/DongleStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/DongleStatusEvent.java index 622087aea..6ea1c24d6 100644 --- a/src/main/java/org/asteriskjava/manager/event/DongleStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DongleStatusEvent.java @@ -1,23 +1,21 @@ package org.asteriskjava.manager.event; -public class DongleStatusEvent extends ManagerEvent -{ - private static final long serialVersionUID = 3257845467831284784L; - private String device; - private String status; +public class DongleStatusEvent extends ManagerEvent { + private static final long serialVersionUID = 3257845467831284784L; + private String device; + private String status; - public DongleStatusEvent(Object source) - { - super(source); - } + public DongleStatusEvent(Object source) { + super(source); + } - public String getDevice() { - return this.device; - } + public String getDevice() { + return this.device; + } - public void setDevice(String device) { - this.device = device; - } + public void setDevice(String device) { + this.device = device; + } public String getStatus() { return status; @@ -27,6 +25,5 @@ public void setStatus(String status) { this.status = status; } - -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/DtmfBeginEvent.java b/src/main/java/org/asteriskjava/manager/event/DtmfBeginEvent.java index 31808823b..eee04cc48 100644 --- a/src/main/java/org/asteriskjava/manager/event/DtmfBeginEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DtmfBeginEvent.java @@ -3,17 +3,15 @@ /** * Created by Alexander Polakov on 1/26/15. */ -public class DtmfBeginEvent extends DtmfEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; +public class DtmfBeginEvent extends DtmfEvent { + /** + * + */ + private static final long serialVersionUID = 1L; - public DtmfBeginEvent(Object source) - { - super(source); - setBegin(true); - setEnd(false); - } + public DtmfBeginEvent(Object source) { + super(source); + setBegin(true); + setEnd(false); + } } diff --git a/src/main/java/org/asteriskjava/manager/event/DtmfEndEvent.java b/src/main/java/org/asteriskjava/manager/event/DtmfEndEvent.java index a92633dfc..245847d22 100644 --- a/src/main/java/org/asteriskjava/manager/event/DtmfEndEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DtmfEndEvent.java @@ -3,28 +3,24 @@ /** * Created by Alexander Polakov on 1/26/15. */ -public class DtmfEndEvent extends DtmfEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; - private Integer durationMs; +public class DtmfEndEvent extends DtmfEvent { + /** + * + */ + private static final long serialVersionUID = 1L; + private Integer durationMs; - public DtmfEndEvent(Object source) - { - super(source); - setBegin(false); - setEnd(true); - } + public DtmfEndEvent(Object source) { + super(source); + setBegin(false); + setEnd(true); + } - public Integer getDurationMs() - { - return durationMs; - } + public Integer getDurationMs() { + return durationMs; + } - public void setDurationMs(Integer durationMs) - { - this.durationMs = durationMs; - } + public void setDurationMs(Integer durationMs) { + this.durationMs = durationMs; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/DtmfEvent.java b/src/main/java/org/asteriskjava/manager/event/DtmfEvent.java index 329328b43..14b107a8c 100644 --- a/src/main/java/org/asteriskjava/manager/event/DtmfEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DtmfEvent.java @@ -39,8 +39,7 @@ * @version $Id$ * @since 1.0.0 */ -public class DtmfEvent extends ManagerEvent -{ +public class DtmfEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -55,7 +54,7 @@ public class DtmfEvent extends ManagerEvent private String direction; private Boolean begin; private Boolean end; - + private String language; private String linkedId; private String accountCode; @@ -65,8 +64,7 @@ public class DtmfEvent extends ManagerEvent * * @param source */ - public DtmfEvent(Object source) - { + public DtmfEvent(Object source) { super(source); } @@ -76,8 +74,7 @@ public DtmfEvent(Object source) * * @return the channel name. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -86,8 +83,7 @@ public String getChannel() * * @param channel the channel name. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -96,8 +92,7 @@ public void setChannel(String channel) * * @return the unique id of the channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } @@ -106,8 +101,7 @@ public String getUniqueId() * * @param uniqueId the unique id of the the channel. */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -116,8 +110,7 @@ public void setUniqueId(String uniqueId) * * @return the DTMF digit that was sent or received. */ - public String getDigit() - { + public String getDigit() { return digit; } @@ -126,8 +119,7 @@ public String getDigit() * * @param digit the DTMF digit that was sent or received. */ - public void setDigit(String digit) - { + public void setDigit(String digit) { this.digit = digit; } @@ -140,12 +132,11 @@ public void setDigit(String digit) * * * @return "Reveived" if the DTMF was received (sent from the device to Asterisk) or "Sent" if the DTMF - * digit was sent (sent from Asterisk to the device). + * digit was sent (sent from Asterisk to the device). * @see #DIRECTION_RECEIVED * @see #DIRECTION_SENT */ - public String getDirection() - { + public String getDirection() { return direction; } @@ -154,8 +145,7 @@ public String getDirection() * * @param direction "Received" or "Sent". */ - public void setDirection(String direction) - { + public void setDirection(String direction) { this.direction = direction; } @@ -168,10 +158,9 @@ public void setDirection(String direction) * DTMF. * * @return true if this is a DTMF begin event (key pressed), - * false otherwise. + * false otherwise. */ - public Boolean isBegin() - { + public Boolean isBegin() { return begin != null && begin; } @@ -181,8 +170,7 @@ public Boolean isBegin() * @param begin true if this is a DTMF begin event (key pressed), * false otherwise. */ - public void setBegin(Boolean begin) - { + public void setBegin(Boolean begin) { this.begin = begin; } @@ -192,10 +180,9 @@ public void setBegin(Boolean begin) * DTMF you will only see DTMF end events. * * @return true if this is a DTMF end event (key released), - * false otherwise. + * false otherwise. */ - public boolean isEnd() - { + public boolean isEnd() { return end != null && end; } @@ -205,8 +192,7 @@ public boolean isEnd() * @param end true if this is a DTMF end event (key released), * false otherwise. */ - public void setEnd(Boolean end) - { + public void setEnd(Boolean end) { this.end = end; } @@ -214,11 +200,10 @@ public void setEnd(Boolean end) * Returns whether the DTMF digit was received by Asterisk (sent from the device to Asterisk). * * @return true if the DTMF digit was received by Asterisk, - * false otherwise. + * false otherwise. * @see #getDirection() */ - public boolean isReceived() - { + public boolean isReceived() { return DIRECTION_RECEIVED.equalsIgnoreCase(direction); } @@ -226,43 +211,36 @@ public boolean isReceived() * Returns whether the DTMF digit was sent from Asterisk to the device. * * @return true if the DTMF digit was sent from Asterisk to the device, - * false otherwise. + * false otherwise. * @see #getDirection() */ - public boolean isSent() - { + public boolean isSent() { return DIRECTION_SENT.equalsIgnoreCase(direction); } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - - -} \ No newline at end of file + + +} diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java b/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java index b8b8cd53e..b2aa6408f 100644 --- a/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/EndpointDetail.java @@ -11,8 +11,7 @@ * @since 12 */ -public class EndpointDetail extends ResponseEvent -{ +public class EndpointDetail extends ResponseEvent { /** * Serial version identifier. @@ -21,23 +20,19 @@ public class EndpointDetail extends ResponseEvent private Integer listItems; private String eventList; - public Integer getListItems() - { + public Integer getListItems() { return listItems; } - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } - public String getEventList() - { + public String getEventList() { return eventList; } - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } @@ -163,1218 +158,975 @@ public void setEventList(String eventList) private String activeChannels; private Boolean ignore183withoutsdp; - public int getMaxVideoStreams() - { + public int getMaxVideoStreams() { return maxVideoStreams; } - public void setMaxVideoStreams(int maxVideoStreams) - { + public void setMaxVideoStreams(int maxVideoStreams) { this.maxVideoStreams = maxVideoStreams; } - public String getObjectName() - { + public String getObjectName() { return objectName; } - public void setObjectName(String objectName) - { + public void setObjectName(String objectName) { this.objectName = objectName; } - public String getObjectType() - { + public String getObjectType() { return objectType; } - public void setObjectType(String objectType) - { + public void setObjectType(String objectType) { this.objectType = objectType; } - public Boolean isRpidImmediate() - { + public Boolean isRpidImmediate() { return rpidImmediate; } - public void setRpidImmediate(Boolean rpidImmediate) - { + public void setRpidImmediate(Boolean rpidImmediate) { this.rpidImmediate = rpidImmediate; } - public Boolean isWebrtc() - { + public Boolean isWebrtc() { return webrtc; } - public void setWebrtc(Boolean webrtc) - { + public void setWebrtc(Boolean webrtc) { this.webrtc = webrtc; } - public Boolean isIgnorel83WithoutSdp() - { + public Boolean isIgnorel83WithoutSdp() { return ignorel83WithoutSdp; } - public void setIgnorel83WithoutSdp(Boolean ignorel83WithoutSdp) - { + public void setIgnorel83WithoutSdp(Boolean ignorel83WithoutSdp) { this.ignorel83WithoutSdp = ignorel83WithoutSdp; } - public int getDeviceStateBusyAt() - { + public int getDeviceStateBusyAt() { return deviceStateBusyAt; } - public void setDeviceStateBusyAt(int deviceStateBusyAt) - { + public void setDeviceStateBusyAt(int deviceStateBusyAt) { this.deviceStateBusyAt = deviceStateBusyAt; } - public int getT38UdptlMaxdatagram() - { + public int getT38UdptlMaxdatagram() { return t38UdptlMaxdatagram; } - public void setT38UdptlMaxdatagram(int t38UdptlMaxdatagram) - { + public void setT38UdptlMaxdatagram(int t38UdptlMaxdatagram) { this.t38UdptlMaxdatagram = t38UdptlMaxdatagram; } - public int getDtlsRekey() - { + public int getDtlsRekey() { return dtlsRekey; } - public void setDtlsRekey(int dtlsRekey) - { + public void setDtlsRekey(int dtlsRekey) { this.dtlsRekey = dtlsRekey; } - public String getNamedPickupGroup() - { + public String getNamedPickupGroup() { return namedPickupGroup; } - public void setNamedPickupGroup(String namedPickupGroup) - { + public void setNamedPickupGroup(String namedPickupGroup) { this.namedPickupGroup = namedPickupGroup; } - public String getDirectMediaMethod() - { + public String getDirectMediaMethod() { return directMediaMethod; } - public void setDirectMediaMethod(String directMediaMethod) - { + public void setDirectMediaMethod(String directMediaMethod) { this.directMediaMethod = directMediaMethod; } - public Boolean isSendRpid() - { + public Boolean isSendRpid() { return sendRpid; } - public void setSendRpid(Boolean sendRpid) - { + public void setSendRpid(Boolean sendRpid) { this.sendRpid = sendRpid; } - public String getPickupGroup() - { + public String getPickupGroup() { return pickupGroup; } - public void setPickupGroup(String pickupGroup) - { + public void setPickupGroup(String pickupGroup) { this.pickupGroup = pickupGroup; } - public String getSdpSession() - { + public String getSdpSession() { return sdpSession; } - public void setSdpSession(String sdpSession) - { + public void setSdpSession(String sdpSession) { this.sdpSession = sdpSession; } - public String getDtlsVerify() - { + public String getDtlsVerify() { return dtlsVerify; } - public void setDtlsVerify(String dtlsVerify) - { + public void setDtlsVerify(String dtlsVerify) { this.dtlsVerify = dtlsVerify; } - public String getMessageContext() - { + public String getMessageContext() { return messageContext; } - public void setMessageContext(String messageContext) - { + public void setMessageContext(String messageContext) { this.messageContext = messageContext; } - public String getMailboxes() - { + public String getMailboxes() { return mailboxes; } - public void setMailboxes(String mailboxes) - { + public void setMailboxes(String mailboxes) { this.mailboxes = mailboxes; } - public String getRecordOnFeature() - { + public String getRecordOnFeature() { return recordOnFeature; } - public void setRecordOnFeature(String recordOnFeature) - { + public void setRecordOnFeature(String recordOnFeature) { this.recordOnFeature = recordOnFeature; } - public String getDtlsPrivateKey() - { + public String getDtlsPrivateKey() { return dtlsPrivateKey; } - public void setDtlsPrivateKey(String dtlsPrivateKey) - { + public void setDtlsPrivateKey(String dtlsPrivateKey) { this.dtlsPrivateKey = dtlsPrivateKey; } - public String getDtlsFingerprint() - { + public String getDtlsFingerprint() { return dtlsFingerprint; } - public void setDtlsFingerprint(String dtlsFingerprint) - { + public void setDtlsFingerprint(String dtlsFingerprint) { this.dtlsFingerprint = dtlsFingerprint; } - public String getFromDomain() - { + public String getFromDomain() { return fromDomain; } - public void setFromDomain(String fromDomain) - { + public void setFromDomain(String fromDomain) { this.fromDomain = fromDomain; } - public int getTimersSessExpires() - { + public int getTimersSessExpires() { return timersSessExpires; } - public void setTimersSessExpires(int timersSessExpires) - { + public void setTimersSessExpires(int timersSessExpires) { this.timersSessExpires = timersSessExpires; } - public String getNamedCallGroup() - { + public String getNamedCallGroup() { return namedCallGroup; } - public void setNamedCallGroup(String namedCallGroup) - { + public void setNamedCallGroup(String namedCallGroup) { this.namedCallGroup = namedCallGroup; } - public String getDtlsCipher() - { + public String getDtlsCipher() { return dtlsCipher; } - public void setDtlsCipher(String dtlsCipher) - { + public void setDtlsCipher(String dtlsCipher) { this.dtlsCipher = dtlsCipher; } - public Boolean isMediaEncryptionOptimistic() - { + public Boolean isMediaEncryptionOptimistic() { return mediaEncryptionOptimistic; } - public void setMediaEncryptionOptimistic(Boolean mediaEncryptionOptimistic) - { + public void setMediaEncryptionOptimistic(Boolean mediaEncryptionOptimistic) { this.mediaEncryptionOptimistic = mediaEncryptionOptimistic; } - public Boolean isSuppressQ850ReasonHeaders() - { + public Boolean isSuppressQ850ReasonHeaders() { return suppressQ850ReasonHeaders; } - public void setSuppressQ850ReasonHeaders(Boolean suppressQ850ReasonHeaders) - { + public void setSuppressQ850ReasonHeaders(Boolean suppressQ850ReasonHeaders) { this.suppressQ850ReasonHeaders = suppressQ850ReasonHeaders; } - public String getAors() - { + public String getAors() { return aors; } - public void setAors(String aors) - { + public void setAors(String aors) { this.aors = aors; } - public String getIdentifyBy() - { + public String getIdentifyBy() { return identifyBy; } - public void setIdentifyBy(String identifyBy) - { + public void setIdentifyBy(String identifyBy) { this.identifyBy = identifyBy; } - public String getCalleridPrivacy() - { + public String getCalleridPrivacy() { return calleridPrivacy; } - public void setCalleridPrivacy(String calleridPrivacy) - { + public void setCalleridPrivacy(String calleridPrivacy) { this.calleridPrivacy = calleridPrivacy; } - public String getMwiSubscribeReplacesUnsolicited() - { + public String getMwiSubscribeReplacesUnsolicited() { return mwiSubscribeReplacesUnsolicited; } - public void setMwiSubscribeReplacesUnsolicited(String mwiSubscribeReplacesUnsolicited) - { + public void setMwiSubscribeReplacesUnsolicited(String mwiSubscribeReplacesUnsolicited) { this.mwiSubscribeReplacesUnsolicited = mwiSubscribeReplacesUnsolicited; } - public Boolean isFollowEarlyMediaFork() - { + public Boolean isFollowEarlyMediaFork() { return followEarlyMediaFork; } - public void setFollowEarlyMediaFork(Boolean followEarlyMediaFork) - { + public void setFollowEarlyMediaFork(Boolean followEarlyMediaFork) { this.followEarlyMediaFork = followEarlyMediaFork; } - public String getContext() - { + public String getContext() { return context; } - public void setContext(String context) - { + public void setContext(String context) { this.context = context; } - public Boolean isRtpSymmetric() - { + public Boolean isRtpSymmetric() { return rtpSymmetric; } - public void setRtpSymmetric(Boolean rtpSymmetric) - { + public void setRtpSymmetric(Boolean rtpSymmetric) { this.rtpSymmetric = rtpSymmetric; } - public String getTransport() - { + public String getTransport() { return transport; } - public void setTransport(String transport) - { + public void setTransport(String transport) { this.transport = transport; } - public String getMohSuggest() - { + public String getMohSuggest() { return mohSuggest; } - public void setMohSuggest(String mohSuggest) - { + public void setMohSuggest(String mohSuggest) { this.mohSuggest = mohSuggest; } - public Boolean isT38Udptl() - { + public Boolean isT38Udptl() { return t38Udptl; } - public void setT38Udptl(Boolean t38Udptl) - { + public void setT38Udptl(Boolean t38Udptl) { this.t38Udptl = t38Udptl; } - public Boolean isFaxDetect() - { + public Boolean isFaxDetect() { return faxDetect; } - public void setFaxDetect(Boolean faxDetect) - { + public void setFaxDetect(Boolean faxDetect) { this.faxDetect = faxDetect; } - public Boolean getSrtpTag32() - { + public Boolean getSrtpTag32() { return srtpTag32; } - public void setSrtpTag32(Boolean srtpTag32) - { + public void setSrtpTag32(Boolean srtpTag32) { this.srtpTag32 = srtpTag32; } - public Boolean isReferBlindProgress() - { + public Boolean isReferBlindProgress() { return referBlindProgress; } - public void setReferBlindProgress(Boolean referBlindProgress) - { + public void setReferBlindProgress(Boolean referBlindProgress) { this.referBlindProgress = referBlindProgress; } - public int getMaxAudioStreams() - { + public int getMaxAudioStreams() { return maxAudioStreams; } - public void setMaxAudioStreams(int maxAudioStreams) - { + public void setMaxAudioStreams(int maxAudioStreams) { this.maxAudioStreams = maxAudioStreams; } - public Boolean isBundle() - { + public Boolean isBundle() { return bundle; } - public void setBundle(Boolean bundle) - { + public void setBundle(Boolean bundle) { this.bundle = bundle; } - public Boolean isUseAvpf() - { + public Boolean isUseAvpf() { return useAvpf; } - public void setUseAvpf(Boolean useAvpf) - { + public void setUseAvpf(Boolean useAvpf) { this.useAvpf = useAvpf; } - public String getCallGroup() - { + public String getCallGroup() { return callGroup; } - public void setCallGroup(String callGroup) - { + public void setCallGroup(String callGroup) { this.callGroup = callGroup; } - public Boolean isSendConnectedLine() - { + public Boolean isSendConnectedLine() { return sendConnectedLine; } - public void setSendConnectedLine(Boolean sendConnectedLine) - { + public void setSendConnectedLine(Boolean sendConnectedLine) { this.sendConnectedLine = sendConnectedLine; } - public int getFaxDetectTimeout() - { + public int getFaxDetectTimeout() { return faxDetectTimeout; } - public void setFaxDetectTimeout(int faxDetectTimeout) - { + public void setFaxDetectTimeout(int faxDetectTimeout) { this.faxDetectTimeout = faxDetectTimeout; } - public String getSdpOwner() - { + public String getSdpOwner() { return sdpOwner; } - public void setSdpOwner(String sdpOwner) - { + public void setSdpOwner(String sdpOwner) { this.sdpOwner = sdpOwner; } - public Boolean isForceRport() - { + public Boolean isForceRport() { return forceRport; } - public void setForceRport(Boolean forceRport) - { + public void setForceRport(Boolean forceRport) { this.forceRport = forceRport; } - public String getCalleridTag() - { + public String getCalleridTag() { return calleridTag; } - public void setCalleridTag(String calleridTag) - { + public void setCalleridTag(String calleridTag) { this.calleridTag = calleridTag; } - public int getRtpTimeoutHold() - { + public int getRtpTimeoutHold() { return rtpTimeoutHold; } - public void setRtpTimeoutHold(int rtpTimeoutHold) - { + public void setRtpTimeoutHold(int rtpTimeoutHold) { this.rtpTimeoutHold = rtpTimeoutHold; } - public Boolean isUsePtime() - { + public Boolean isUsePtime() { return usePtime; } - public void setUsePtime(Boolean usePtime) - { + public void setUsePtime(Boolean usePtime) { this.usePtime = usePtime; } - public String getMediaAddress() - { + public String getMediaAddress() { return mediaAddress; } - public void setMediaAddress(String mediaAddress) - { + public void setMediaAddress(String mediaAddress) { this.mediaAddress = mediaAddress; } - public String getVoicemailExtension() - { + public String getVoicemailExtension() { return voicemailExtension; } - public void setVoicemailExtension(String voicemailExtension) - { + public void setVoicemailExtension(String voicemailExtension) { this.voicemailExtension = voicemailExtension; } - public int getRtpTimeout() - { + public int getRtpTimeout() { return rtpTimeout; } - public void setRtpTimeout(int rtpTimeout) - { + public void setRtpTimeout(int rtpTimeout) { this.rtpTimeout = rtpTimeout; } - public String getSetVar() - { + public String getSetVar() { return setVar; } - public void setSetVar(String setVar) - { + public void setSetVar(String setVar) { this.setVar = setVar; } - public String getContactAcl() - { + public String getContactAcl() { return contactAcl; } - public void setContactAcl(String contactAcl) - { + public void setContactAcl(String contactAcl) { this.contactAcl = contactAcl; } - public Boolean isPreferredCodecOnly() - { + public Boolean isPreferredCodecOnly() { return preferredCodecOnly; } - public void setPreferredCodecOnly(Boolean preferredCodecOnly) - { + public void setPreferredCodecOnly(Boolean preferredCodecOnly) { this.preferredCodecOnly = preferredCodecOnly; } - public Boolean isForceAvp() - { + public Boolean isForceAvp() { return forceAvp; } - public void setForceAvp(Boolean forceAvp) - { + public void setForceAvp(Boolean forceAvp) { this.forceAvp = forceAvp; } - public String getRecordOffFeature() - { + public String getRecordOffFeature() { return recordOffFeature; } - public void setRecordOffFeature(String recordOffFeature) - { + public void setRecordOffFeature(String recordOffFeature) { this.recordOffFeature = recordOffFeature; } - public String getFromUser() - { + public String getFromUser() { return fromUser; } - public void setFromUser(String fromUser) - { + public void setFromUser(String fromUser) { this.fromUser = fromUser; } - public Boolean isSendDiversion() - { + public Boolean isSendDiversion() { return sendDiversion; } - public void setSendDiversion(Boolean sendDiversion) - { + public void setSendDiversion(Boolean sendDiversion) { this.sendDiversion = sendDiversion; } - public Boolean isT38UdptlIpv6() - { + public Boolean isT38UdptlIpv6() { return t38UdptlIpv6; } - public void setT38UdptlIpv6(Boolean t38UdptlIpv6) - { + public void setT38UdptlIpv6(Boolean t38UdptlIpv6) { this.t38UdptlIpv6 = t38UdptlIpv6; } - public String getToneZone() - { + public String getToneZone() { return toneZone; } - public void setToneZone(String toneZone) - { + public void setToneZone(String toneZone) { this.toneZone = toneZone; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public Boolean isAllowSubscribe() - { + public Boolean isAllowSubscribe() { return allowSubscribe; } - public void setAllowSubscribe(Boolean allowSubscribe) - { + public void setAllowSubscribe(Boolean allowSubscribe) { this.allowSubscribe = allowSubscribe; } - public Boolean isRtpIpv6() - { + public Boolean isRtpIpv6() { return rtpIpv6; } - public void setRtpIpv6(Boolean rtpIpv6) - { + public void setRtpIpv6(Boolean rtpIpv6) { this.rtpIpv6 = rtpIpv6; } - public String getCallerid() - { + public String getCallerid() { return callerid; } - public void setCallerid(String callerid) - { + public void setCallerid(String callerid) { this.callerid = callerid; } - public Boolean isMohPassthrough() - { + public Boolean isMohPassthrough() { return mohPassthrough; } - public void setMohPassthrough(Boolean mohPassthrough) - { + public void setMohPassthrough(Boolean mohPassthrough) { this.mohPassthrough = mohPassthrough; } - public String getCosAudio() - { + public String getCosAudio() { return cosAudio; } - public void setCosAudio(String cosAudio) - { + public void setCosAudio(String cosAudio) { this.cosAudio = cosAudio; } - public String getCosVideo() - { + public String getCosVideo() { return cosVideo; } - public void setCosVideo(String cosVideo) - { + public void setCosVideo(String cosVideo) { this.cosVideo = cosVideo; } - public String getDtlsAutoGenerateCert() - { + public String getDtlsAutoGenerateCert() { return dtlsAutoGenerateCert; } - public void setDtlsAutoGenerateCert(String dtlsAutoGenerateCert) - { + public void setDtlsAutoGenerateCert(String dtlsAutoGenerateCert) { this.dtlsAutoGenerateCert = dtlsAutoGenerateCert; } - public Boolean isAsymmetricRtpCodec() - { + public Boolean isAsymmetricRtpCodec() { return asymmetricRtpCodec; } - public void setAsymmetricRtpCodec(Boolean asymmetricRtpCodec) - { + public void setAsymmetricRtpCodec(Boolean asymmetricRtpCodec) { this.asymmetricRtpCodec = asymmetricRtpCodec; } - public Boolean isIceSupport() - { + public Boolean isIceSupport() { return iceSupport; } - public void setIceSupport(Boolean iceSupport) - { + public void setIceSupport(Boolean iceSupport) { this.iceSupport = iceSupport; } - public Boolean isAggregateMwi() - { + public Boolean isAggregateMwi() { return aggregateMwi; } - public void setAggregateMwi(Boolean aggregateMwi) - { + public void setAggregateMwi(Boolean aggregateMwi) { this.aggregateMwi = aggregateMwi; } - public Boolean isOneTouchRecording() - { + public Boolean isOneTouchRecording() { return oneTouchRecording; } - public void setOneTouchRecording(Boolean oneTouchRecording) - { + public void setOneTouchRecording(Boolean oneTouchRecording) { this.oneTouchRecording = oneTouchRecording; } - public String getMwiFromUser() - { + public String getMwiFromUser() { return mwiFromUser; } - public void setMwiFromUser(String mwiFromUser) - { + public void setMwiFromUser(String mwiFromUser) { this.mwiFromUser = mwiFromUser; } - public String getAccountcode() - { + public String getAccountcode() { return accountcode; } - public void setAccountcode(String accountcode) - { + public void setAccountcode(String accountcode) { this.accountcode = accountcode; } - public String getAllow() - { + public String getAllow() { return allow; } - public void setAllow(String allow) - { + public void setAllow(String allow) { this.allow = allow; } - public Boolean isRewriteContact() - { + public Boolean isRewriteContact() { return rewriteContact; } - public void setRewriteContact(Boolean rewriteContact) - { + public void setRewriteContact(Boolean rewriteContact) { this.rewriteContact = rewriteContact; } - public Boolean isUserEqPhone() - { + public Boolean isUserEqPhone() { return userEqPhone; } - public void setUserEqPhone(Boolean userEqPhone) - { + public void setUserEqPhone(Boolean userEqPhone) { this.userEqPhone = userEqPhone; } - public String getRtpEngine() - { + public String getRtpEngine() { return rtpEngine; } - public void setRtpEngine(String rtpEngine) - { + public void setRtpEngine(String rtpEngine) { this.rtpEngine = rtpEngine; } - public String getSubscribeContext() - { + public String getSubscribeContext() { return subscribeContext; } - public void setSubscribeContext(String subscribeContext) - { + public void setSubscribeContext(String subscribeContext) { this.subscribeContext = subscribeContext; } - public Boolean isNotifyEarlyInuseRinging() - { + public Boolean isNotifyEarlyInuseRinging() { return notifyEarlyInuseRinging; } - public void setNotifyEarlyInuseRinging(Boolean notifyEarlyInuseRinging) - { + public void setNotifyEarlyInuseRinging(Boolean notifyEarlyInuseRinging) { this.notifyEarlyInuseRinging = notifyEarlyInuseRinging; } - public String getIncomingMwiMailbox() - { + public String getIncomingMwiMailbox() { return incomingMwiMailbox; } - public void setIncomingMwiMailbox(String incomingMwiMailbox) - { + public void setIncomingMwiMailbox(String incomingMwiMailbox) { this.incomingMwiMailbox = incomingMwiMailbox; } - public String getAuth() - { + public String getAuth() { return auth; } - public void setAuth(String auth) - { + public void setAuth(String auth) { this.auth = auth; } - public String getDirectMediaGlareMitigation() - { + public String getDirectMediaGlareMitigation() { return directMediaGlareMitigation; } - public void setDirectMediaGlareMitigation(String directMediaGlareMitigation) - { + public void setDirectMediaGlareMitigation(String directMediaGlareMitigation) { this.directMediaGlareMitigation = directMediaGlareMitigation; } - public Boolean isTrustIdInbound() - { + public Boolean isTrustIdInbound() { return trustIdInbound; } - public void setTrustIdInbound(Boolean trustIdInbound) - { + public void setTrustIdInbound(Boolean trustIdInbound) { this.trustIdInbound = trustIdInbound; } - public Boolean isBindRtpToMediaAddress() - { + public Boolean isBindRtpToMediaAddress() { return bindRtpToMediaAddress; } - public void setBindRtpToMediaAddress(Boolean bindRtpToMediaAddress) - { + public void setBindRtpToMediaAddress(Boolean bindRtpToMediaAddress) { this.bindRtpToMediaAddress = bindRtpToMediaAddress; } - public Boolean isDisableDirectMediaOnNat() - { + public Boolean isDisableDirectMediaOnNat() { return disableDirectMediaOnNat; } - public void setDisableDirectMediaOnNat(Boolean disableDirectMediaOnNat) - { + public void setDisableDirectMediaOnNat(Boolean disableDirectMediaOnNat) { this.disableDirectMediaOnNat = disableDirectMediaOnNat; } - public Boolean isMediaEncryption() - { + public Boolean isMediaEncryption() { return mediaEncryption; } - public void setMediaEncryption(Boolean mediaEncryption) - { + public void setMediaEncryption(Boolean mediaEncryption) { this.mediaEncryption = mediaEncryption; } - public Boolean isMediaUseReceivedTransport() - { + public Boolean isMediaUseReceivedTransport() { return mediaUseReceivedTransport; } - public void setMediaUseReceivedTransport(Boolean mediaUseReceivedTransport) - { + public void setMediaUseReceivedTransport(Boolean mediaUseReceivedTransport) { this.mediaUseReceivedTransport = mediaUseReceivedTransport; } - public Boolean isAllowOverlap() - { + public Boolean isAllowOverlap() { return allowOverlap; } - public void setAllowOverlap(Boolean allowOverlap) - { + public void setAllowOverlap(Boolean allowOverlap) { this.allowOverlap = allowOverlap; } - public String getDtmfMode() - { + public String getDtmfMode() { return dtmfMode; } - public void setDtmfMode(String dtmfMode) - { + public void setDtmfMode(String dtmfMode) { this.dtmfMode = dtmfMode; } - public String getOutboundAuth() - { + public String getOutboundAuth() { return outboundAuth; } - public void setOutboundAuth(String outboundAuth) - { + public void setOutboundAuth(String outboundAuth) { this.outboundAuth = outboundAuth; } - public String getTosVideo() - { + public String getTosVideo() { return tosVideo; } - public void setTosVideo(String tosVideo) - { + public void setTosVideo(String tosVideo) { this.tosVideo = tosVideo; } - public String getTosAudio() - { + public String getTosAudio() { return tosAudio; } - public void setTosAudio(String tosAudio) - { + public void setTosAudio(String tosAudio) { this.tosAudio = tosAudio; } - public String getDtlsCertFile() - { + public String getDtlsCertFile() { return dtlsCertFile; } - public void setDtlsCertFile(String dtlsCertFile) - { + public void setDtlsCertFile(String dtlsCertFile) { this.dtlsCertFile = dtlsCertFile; } - public String getDtlsCaPath() - { + public String getDtlsCaPath() { return dtlsCaPath; } - public void setDtlsCaPath(String dtlsCaPath) - { + public void setDtlsCaPath(String dtlsCaPath) { this.dtlsCaPath = dtlsCaPath; } - public String getDtlsSetup() - { + public String getDtlsSetup() { return dtlsSetup; } - public void setDtlsSetup(String dtlsSetup) - { + public void setDtlsSetup(String dtlsSetup) { this.dtlsSetup = dtlsSetup; } - public String getConnectedLineMethod() - { + public String getConnectedLineMethod() { return connectedLineMethod; } - public void setConnectedLineMethod(String connectedLineMethod) - { + public void setConnectedLineMethod(String connectedLineMethod) { this.connectedLineMethod = connectedLineMethod; } - public Boolean isG726NonStandard() - { + public Boolean isG726NonStandard() { return g726NonStandard; } - public void setG726NonStandard(Boolean g726NonStandard) - { + public void setG726NonStandard(Boolean g726NonStandard) { this.g726NonStandard = g726NonStandard; } - public String get100rel() - { + public String get100rel() { return _100rel; } - public void set100rel(String _100rel) - { + public void set100rel(String _100rel) { this._100rel = _100rel; } - public String getTimers() - { + public String getTimers() { return timers; } - public void setTimers(String timers) - { + public void setTimers(String timers) { this.timers = timers; } - public Boolean isDirectMedia() - { + public Boolean isDirectMedia() { return directMedia; } - public void setDirectMedia(Boolean directMedia) - { + public void setDirectMedia(Boolean directMedia) { this.directMedia = directMedia; } - public String getAcl() - { + public String getAcl() { return acl; } - public void setAcl(String acl) - { + public void setAcl(String acl) { this.acl = acl; } - public int getTimersMinSe() - { + public int getTimersMinSe() { return timersMinSe; } - public void setTimersMinSe(int timersMinSe) - { + public void setTimersMinSe(int timersMinSe) { this.timersMinSe = timersMinSe; } - public Boolean isTrustIdOutbound() - { + public Boolean isTrustIdOutbound() { return trustIdOutbound; } - public void setTrustIdOutbound(Boolean trustIdOutbound) - { + public void setTrustIdOutbound(Boolean trustIdOutbound) { this.trustIdOutbound = trustIdOutbound; } - public int getSubMinExpiry() - { + public int getSubMinExpiry() { return subMinExpiry; } - public void setSubMinExpiry(int subMinExpiry) - { + public void setSubMinExpiry(int subMinExpiry) { this.subMinExpiry = subMinExpiry; } - public Boolean isRtcpMux() - { + public Boolean isRtcpMux() { return rtcpMux; } - public void setRtcpMux(Boolean rtcpMux) - { + public void setRtcpMux(Boolean rtcpMux) { this.rtcpMux = rtcpMux; } - public Boolean isAcceptMultipleSdpAnswers() - { + public Boolean isAcceptMultipleSdpAnswers() { return acceptMultipleSdpAnswers; } - public void setAcceptMultipleSdpAnswers(Boolean acceptMultipleSdpAnswers) - { + public void setAcceptMultipleSdpAnswers(Boolean acceptMultipleSdpAnswers) { this.acceptMultipleSdpAnswers = acceptMultipleSdpAnswers; } - public Boolean isTrustConnectedLine() - { + public Boolean isTrustConnectedLine() { return trustConnectedLine; } - public void setTrustConnectedLine(Boolean trustConnectedLine) - { + public void setTrustConnectedLine(Boolean trustConnectedLine) { this.trustConnectedLine = trustConnectedLine; } - public Boolean isSendPai() - { + public Boolean isSendPai() { return sendPai; } - public void setSendPai(Boolean sendPai) - { + public void setSendPai(Boolean sendPai) { this.sendPai = sendPai; } - public int getRtpKeepalive() - { + public int getRtpKeepalive() { return rtpKeepalive; } - public void setRtpKeepalive(int rtpKeepalive) - { + public void setRtpKeepalive(int rtpKeepalive) { this.rtpKeepalive = rtpKeepalive; } - public String getT38UdptlEc() - { + public String getT38UdptlEc() { return t38UdptlEc; } - public void setT38UdptlEc(String t38UdptlEc) - { + public void setT38UdptlEc(String t38UdptlEc) { this.t38UdptlEc = t38UdptlEc; } - public Boolean isT38UdptlNat() - { + public Boolean isT38UdptlNat() { return t38UdptlNat; } - public void setT38UdptlNat(Boolean t38UdptlNat) - { + public void setT38UdptlNat(Boolean t38UdptlNat) { this.t38UdptlNat = t38UdptlNat; } - public Boolean isAllowTransfer() - { + public Boolean isAllowTransfer() { return allowTransfer; } - public void setAllowTransfer(Boolean allowTransfer) - { + public void setAllowTransfer(Boolean allowTransfer) { this.allowTransfer = allowTransfer; } - public String getDtlsCaFile() - { + public String getDtlsCaFile() { return dtlsCaFile; } - public void setDtlsCaFile(String dtlsCaFile) - { + public void setDtlsCaFile(String dtlsCaFile) { this.dtlsCaFile = dtlsCaFile; } - public String getOutboundProxy() - { + public String getOutboundProxy() { return outboundProxy; } - public void setOutboundProxy(String outboundProxy) - { + public void setOutboundProxy(String outboundProxy) { this.outboundProxy = outboundProxy; } - public Boolean isInbandProgress() - { + public Boolean isInbandProgress() { return inbandProgress; } - public void setInbandProgress(Boolean inbandProgress) - { + public void setInbandProgress(Boolean inbandProgress) { this.inbandProgress = inbandProgress; } - public String getDeviceState() - { + public String getDeviceState() { return deviceState; } - public void setDeviceState(String deviceState) - { + public void setDeviceState(String deviceState) { this.deviceState = deviceState; } - public String getActiveChannels() - { + public String getActiveChannels() { return activeChannels; } - public void setActiveChannels(String activeChannels) - { + public void setActiveChannels(String activeChannels) { this.activeChannels = activeChannels; } - public EndpointDetail(Object source) - { + public EndpointDetail(Object source) { super(source); } - public Boolean getIgnore183withoutsdp() - { + public Boolean getIgnore183withoutsdp() { return ignore183withoutsdp; } - public void setIgnore183withoutsdp(Boolean ignore183withoutsdp) - { + public void setIgnore183withoutsdp(Boolean ignore183withoutsdp) { this.ignore183withoutsdp = ignore183withoutsdp; } diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java b/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java index 43f0cf1f0..f1c07eac2 100644 --- a/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java +++ b/src/main/java/org/asteriskjava/manager/event/EndpointDetailComplete.java @@ -21,14 +21,13 @@ * reported in response to a PJSIPShowEndpoint *

    * Available since Asterisk 12 - * - * @see org.asteriskjava.manager.event.PJSIpShowEndpoint + * * @author Steve Sether * @version $Id$ + * @see org.asteriskjava.manager.event.PJSIpShowEndpoint * @since 12 */ -public class EndpointDetailComplete extends ResponseEvent -{ +public class EndpointDetailComplete extends ResponseEvent { /** * Serial version identifier. */ @@ -38,31 +37,28 @@ public class EndpointDetailComplete extends ResponseEvent /** * Creates a new instance. - * + * * @param source */ - public EndpointDetailComplete(Object source) - { + public EndpointDetailComplete(Object source) { super(source); } /** * Returns the number of EndpointDetail events that have been reported. - * + * * @return the number of EndpointDetail events that have been reported. */ - public Integer getListItems() - { + public Integer getListItems() { return listItems; } /** * Sets the number of EndpointDetail events that have been reported. - * + * * @param listItems the number of EndpointDetail events that have been reported. */ - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } @@ -72,16 +68,14 @@ public void setListItems(Integer listItems) * Available since Asterisk 12. * * @return always returns "Complete" confirming that all EndpointDetail events have - * been sent. + * been sent. * @since 12 */ - public String getEventList() - { + public String getEventList() { return eventList; } - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } } diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointList.java b/src/main/java/org/asteriskjava/manager/event/EndpointList.java index 723027f02..3781a4cf1 100644 --- a/src/main/java/org/asteriskjava/manager/event/EndpointList.java +++ b/src/main/java/org/asteriskjava/manager/event/EndpointList.java @@ -21,16 +21,15 @@ * reported in response to an SIPPeersAction or SIPShowPeerAction. *

    * Available since Asterisk 1.2 - * + * + * @author srt + * @version $Id$ * @see org.asteriskjava.manager.event.PeerEntryEvent * @see org.asteriskjava.manager.action.SipPeersAction * @see org.asteriskjava.manager.action.SipShowPeerAction - * @author srt - * @version $Id$ * @since 0.2 */ -public class EndpointList extends ResponseEvent -{ +public class EndpointList extends ResponseEvent { /** * Serial version identifier. */ @@ -51,31 +50,28 @@ public class EndpointList extends ResponseEvent /** * Creates a new instance. - * + * * @param source */ - public EndpointList(Object source) - { + public EndpointList(Object source) { super(source); } /** * Returns the number of PeerEvents that have been reported. - * + * * @return the number of PeerEvents that have been reported. */ - public Integer getListItems() - { + public Integer getListItems() { return listItems; } /** * Sets the number of PeerEvents that have been reported. - * + * * @param listItems the number of PeerEvents that have been reported. */ - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } @@ -85,116 +81,94 @@ public void setListItems(Integer listItems) * Available since Asterisk 1.6. * * @return always returns "Complete" confirming that all PeerEntry events have - * been sent. + * been sent. * @since 1.0.0 */ - public String getEventList() - { + public String getEventList() { return eventList; } - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } - public String getAor() - { + public String getAor() { return aor; } - public void setAor(String aor) - { + public void setAor(String aor) { this.aor = aor; } - public String getAuths() - { + public String getAuths() { return auths; } - public void setAuths(String auths) - { + public void setAuths(String auths) { this.auths = auths; } - public String getObjectName() - { + public String getObjectName() { return objectName; } - public void setObjectName(String objectName) - { + public void setObjectName(String objectName) { this.objectName = objectName; } - public String getTransport() - { + public String getTransport() { return transport; } - public void setTransport(String transport) - { + public void setTransport(String transport) { this.transport = transport; } - public String getOutboundAuths() - { + public String getOutboundAuths() { return outboundAuths; } - public void setOutboundAuths(String outboundAuths) - { + public void setOutboundAuths(String outboundAuths) { this.outboundAuths = outboundAuths; } - public String getDevicestate() - { + public String getDevicestate() { return devicestate; } - public void setDevicestate(String devicestate) - { + public void setDevicestate(String devicestate) { this.devicestate = devicestate; } - public String getEvent() - { + public String getEvent() { return event; } - public void setEvent(String event) - { + public void setEvent(String event) { this.event = event; } - public String getObjectType() - { + public String getObjectType() { return objectType; } - public void setObjectType(String objectType) - { + public void setObjectType(String objectType) { this.objectType = objectType; } - public String getContacts() - { + public String getContacts() { return contacts; } - public void setContacts(String contacts) - { + public void setContacts(String contacts) { this.contacts = contacts; } - public String getActiveChannels() - { + public String getActiveChannels() { return activeChannels; } - public void setActiveChannels(String activeChannels) - { + public void setActiveChannels(String activeChannels) { this.activeChannels = activeChannels; } } diff --git a/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java b/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java index 5337b94e1..432a2de94 100644 --- a/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java +++ b/src/main/java/org/asteriskjava/manager/event/EndpointListComplete.java @@ -21,14 +21,13 @@ * reported in response to a PJSIPShowEndpoints event. *

    * Available since Asterisk 12 - * - * @see org.asteriskjava.manager.event.PJSipShowEndpoints + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.PJSipShowEndpoints * @since 12 */ -public class EndpointListComplete extends ResponseEvent -{ +public class EndpointListComplete extends ResponseEvent { /** * Serial version identifier. */ @@ -38,31 +37,28 @@ public class EndpointListComplete extends ResponseEvent /** * Creates a new instance. - * + * * @param source */ - public EndpointListComplete(Object source) - { + public EndpointListComplete(Object source) { super(source); } /** * Returns the number of Endpoints that have been reported. - * + * * @return the number of Endpoints that have been reported. */ - public Integer getListItems() - { + public Integer getListItems() { return listItems; } /** * Sets the number of Endpoints that have been reported. - * + * * @param listItems the number of PeerEvents that have been reported. */ - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } @@ -72,16 +68,14 @@ public void setListItems(Integer listItems) * Available since Asterisk 1.6. * * @return always returns "Complete" confirming that all PeerEntry events have - * been sent. + * been sent. * @since 1.0.0 */ - public String getEventList() - { + public String getEventList() { return eventList; } - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } } diff --git a/src/main/java/org/asteriskjava/manager/event/ExtensionStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/ExtensionStatusEvent.java index 185760c2a..037d273a1 100644 --- a/src/main/java/org/asteriskjava/manager/event/ExtensionStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ExtensionStatusEvent.java @@ -33,8 +33,7 @@ * @author srt * @version $Id$ */ -public class ExtensionStatusEvent extends ManagerEvent -{ +public class ExtensionStatusEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -70,9 +69,8 @@ public class ExtensionStatusEvent extends ManagerEvent private String callerId; private String statustext; - - public ExtensionStatusEvent(Object source) - { + + public ExtensionStatusEvent(Object source) { super(source); } @@ -84,13 +82,11 @@ public ExtensionStatusEvent(Object source) * @return the hint (channel name) assigned to the extension. * @since 1.0.0 */ - public String getHint() - { + public String getHint() { return hint; } - public void setHint(String hint) - { + public void setHint(String hint) { this.hint = hint; } @@ -106,16 +102,14 @@ public void setHint(String hint) *

  • UNAVAILABLE
  • * */ - public Integer getStatus() - { + public Integer getStatus() { return status; } /** * Sets the state of the extension. */ - public void setStatus(Integer status) - { + public void setStatus(Integer status) { this.status = status; } @@ -127,8 +121,7 @@ public void setStatus(Integer status) * @return the Caller*ID. * @since 0.3 */ - public String getCallerId() - { + public String getCallerId() { return callerId; } @@ -138,19 +131,16 @@ public String getCallerId() * @param callerId the Caller*ID. * @since 0.3 */ - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { this.callerId = callerId; } - - public String getStatustext() - { - return statustext; - } - - public void setStatustext(String statustext) - { - this.statustext = statustext; - } + + public String getStatustext() { + return statustext; + } + + public void setStatustext(String statustext) { + this.statustext = statustext; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/FaxDocumentStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/FaxDocumentStatusEvent.java index 74754b27c..0df1d28a6 100644 --- a/src/main/java/org/asteriskjava/manager/event/FaxDocumentStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/FaxDocumentStatusEvent.java @@ -19,8 +19,7 @@ /** * A FaxDocumentStatusEvent is an event of Digium's Fax For Asterisk add-on. */ -public class FaxDocumentStatusEvent extends AbstractFaxEvent -{ +public class FaxDocumentStatusEvent extends AbstractFaxEvent { /** * Serial version identifier. */ @@ -43,8 +42,7 @@ public class FaxDocumentStatusEvent extends AbstractFaxEvent private String remoteDis; - public FaxDocumentStatusEvent(Object source) - { + public FaxDocumentStatusEvent(Object source) { super(source); } @@ -52,8 +50,7 @@ public FaxDocumentStatusEvent(Object source) /** * @return the documentNumber */ - public Integer getDocumentNumber() - { + public Integer getDocumentNumber() { return documentNumber; } @@ -61,8 +58,7 @@ public Integer getDocumentNumber() /** * @param documentNumber the documentNumber to set */ - public void setDocumentNumber(Integer documentNumber) - { + public void setDocumentNumber(Integer documentNumber) { this.documentNumber = documentNumber; } @@ -70,8 +66,7 @@ public void setDocumentNumber(Integer documentNumber) /** * @return the lastError */ - public Integer getLastError() - { + public Integer getLastError() { return lastError; } @@ -79,8 +74,7 @@ public Integer getLastError() /** * @param lastError the lastError to set */ - public void setLastError(Integer lastError) - { + public void setLastError(Integer lastError) { this.lastError = lastError; } @@ -88,8 +82,7 @@ public void setLastError(Integer lastError) /** * @return the pageCount */ - public Integer getPageCount() - { + public Integer getPageCount() { return pageCount; } @@ -97,8 +90,7 @@ public Integer getPageCount() /** * @param pageCount the pageCount to set */ - public void setPageCount(Integer pageCount) - { + public void setPageCount(Integer pageCount) { this.pageCount = pageCount; } @@ -106,8 +98,7 @@ public void setPageCount(Integer pageCount) /** * @return the startPage */ - public Integer getStartPage() - { + public Integer getStartPage() { return startPage; } @@ -115,8 +106,7 @@ public Integer getStartPage() /** * @param startPage the startPage to set */ - public void setStartPage(Integer startPage) - { + public void setStartPage(Integer startPage) { this.startPage = startPage; } @@ -124,8 +114,7 @@ public void setStartPage(Integer startPage) /** * @return the lastPageProcessed */ - public Integer getLastPageProcessed() - { + public Integer getLastPageProcessed() { return lastPageProcessed; } @@ -133,8 +122,7 @@ public Integer getLastPageProcessed() /** * @param lastPageProcessed the lastPageProcessed to set */ - public void setLastPageProcessed(Integer lastPageProcessed) - { + public void setLastPageProcessed(Integer lastPageProcessed) { this.lastPageProcessed = lastPageProcessed; } @@ -142,8 +130,7 @@ public void setLastPageProcessed(Integer lastPageProcessed) /** * @return the retransmitCount */ - public Integer getRetransmitCount() - { + public Integer getRetransmitCount() { return retransmitCount; } @@ -151,8 +138,7 @@ public Integer getRetransmitCount() /** * @param retransmitCount the retransmitCount to set */ - public void setRetransmitCount(Integer retransmitCount) - { + public void setRetransmitCount(Integer retransmitCount) { this.retransmitCount = retransmitCount; } @@ -160,8 +146,7 @@ public void setRetransmitCount(Integer retransmitCount) /** * @return the transferPels */ - public Integer getTransferPels() - { + public Integer getTransferPels() { return transferPels; } @@ -169,8 +154,7 @@ public Integer getTransferPels() /** * @param transferPels the transferPels to set */ - public void setTransferPels(Integer transferPels) - { + public void setTransferPels(Integer transferPels) { this.transferPels = transferPels; } @@ -178,8 +162,7 @@ public void setTransferPels(Integer transferPels) /** * @return the transferRate */ - public Integer getTransferRate() - { + public Integer getTransferRate() { return transferRate; } @@ -187,8 +170,7 @@ public Integer getTransferRate() /** * @param transferRate the transferRate to set */ - public void setTransferRate(Integer transferRate) - { + public void setTransferRate(Integer transferRate) { this.transferRate = transferRate; } @@ -196,8 +178,7 @@ public void setTransferRate(Integer transferRate) /** * @return the transferDuration */ - public String getTransferDuration() - { + public String getTransferDuration() { return transferDuration; } @@ -205,8 +186,7 @@ public String getTransferDuration() /** * @param transferDuration the transferDuration to set */ - public void setTransferDuration(String transferDuration) - { + public void setTransferDuration(String transferDuration) { this.transferDuration = transferDuration; } @@ -214,8 +194,7 @@ public void setTransferDuration(String transferDuration) /** * @return the badLineCount */ - public Integer getBadLineCount() - { + public Integer getBadLineCount() { return badLineCount; } @@ -223,8 +202,7 @@ public Integer getBadLineCount() /** * @param badLineCount the badLineCount to set */ - public void setBadLineCount(Integer badLineCount) - { + public void setBadLineCount(Integer badLineCount) { this.badLineCount = badLineCount; } @@ -232,8 +210,7 @@ public void setBadLineCount(Integer badLineCount) /** * @return the processedStatus */ - public String getProcessedStatus() - { + public String getProcessedStatus() { return processedStatus; } @@ -241,8 +218,7 @@ public String getProcessedStatus() /** * @param processedStatus the processedStatus to set */ - public void setProcessedStatus(String processedStatus) - { + public void setProcessedStatus(String processedStatus) { this.processedStatus = processedStatus; } @@ -250,8 +226,7 @@ public void setProcessedStatus(String processedStatus) /** * @return the documentTime */ - public String getDocumentTime() - { + public String getDocumentTime() { return documentTime; } @@ -259,8 +234,7 @@ public String getDocumentTime() /** * @param documentTime the documentTime to set */ - public void setDocumentTime(String documentTime) - { + public void setDocumentTime(String documentTime) { this.documentTime = documentTime; } @@ -268,8 +242,7 @@ public void setDocumentTime(String documentTime) /** * @return the localSid */ - public String getLocalSid() - { + public String getLocalSid() { return localSid; } @@ -277,8 +250,7 @@ public String getLocalSid() /** * @param localSid the localSid to set */ - public void setLocalSid(String localSid) - { + public void setLocalSid(String localSid) { this.localSid = localSid; } @@ -286,8 +258,7 @@ public void setLocalSid(String localSid) /** * @return the localDis */ - public String getLocalDis() - { + public String getLocalDis() { return localDis; } @@ -295,8 +266,7 @@ public String getLocalDis() /** * @param localDis the localDis to set */ - public void setLocalDis(String localDis) - { + public void setLocalDis(String localDis) { this.localDis = localDis; } @@ -304,8 +274,7 @@ public void setLocalDis(String localDis) /** * @return the remoteSid */ - public String getRemoteSid() - { + public String getRemoteSid() { return remoteSid; } @@ -313,8 +282,7 @@ public String getRemoteSid() /** * @param remoteSid the remoteSid to set */ - public void setRemoteSid(String remoteSid) - { + public void setRemoteSid(String remoteSid) { this.remoteSid = remoteSid; } @@ -322,8 +290,7 @@ public void setRemoteSid(String remoteSid) /** * @return the remoteDis */ - public String getRemoteDis() - { + public String getRemoteDis() { return remoteDis; } @@ -331,8 +298,7 @@ public String getRemoteDis() /** * @param remoteDis the remoteDis to set */ - public void setRemoteDis(String remoteDis) - { + public void setRemoteDis(String remoteDis) { this.remoteDis = remoteDis; } diff --git a/src/main/java/org/asteriskjava/manager/event/FaxReceivedEvent.java b/src/main/java/org/asteriskjava/manager/event/FaxReceivedEvent.java index 4d3ae442e..3becf967b 100644 --- a/src/main/java/org/asteriskjava/manager/event/FaxReceivedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/FaxReceivedEvent.java @@ -24,13 +24,12 @@ * See http://soft-switch.org/installing-spandsp.html for details. *

    * Implemented in apps/app_rxfax.c. - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class FaxReceivedEvent extends AbstractFaxEvent -{ +public class FaxReceivedEvent extends AbstractFaxEvent { /** * Serial version identifier. */ @@ -44,150 +43,135 @@ public class FaxReceivedEvent extends AbstractFaxEvent private Integer transferRate; private String filename; - public FaxReceivedEvent(Object source) - { + public FaxReceivedEvent(Object source) { super(source); } /** * Returns the Caller*ID of the calling party or an empty string if none is * available. - * + * * @return the Caller*ID of the calling party. */ - public String getCallerId() - { + public String getCallerId() { return callerId; } /** * Sets the Caller*ID of the calling party. - * + * * @param callerId the Caller*ID of the calling party. */ - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { this.callerId = callerId; } /** * Retruns the identifier of the remote fax station. - * + * * @return the identifier of the remote fax station. */ - public String getRemoteStationId() - { + public String getRemoteStationId() { return remoteStationId; } /** * Sets the identifier of the remote fax station. - * + * * @param remoteStationId the identifier of the remote fax station. */ - public void setRemoteStationId(String remoteStationId) - { + public void setRemoteStationId(String remoteStationId) { this.remoteStationId = remoteStationId; } /** * Returns the identifier of the local fax station. - * + * * @return the identifier of the local fax station. */ - public String getLocalStationId() - { + public String getLocalStationId() { return localStationId; } /** * Sets the identifier of the local fax station. - * + * * @param localStationId the identifier of the local fax station. */ - public void setLocalStationId(String localStationId) - { + public void setLocalStationId(String localStationId) { this.localStationId = localStationId; } /** * Returns the number of pages transferred. - * + * * @return the number of pages transferred. */ - public Integer getPagesTransferred() - { + public Integer getPagesTransferred() { return pagesTransferred; } /** * Sets the number of pages transferred. - * + * * @param pagesTransferred the number of pages transferred. */ - public void setPagesTransferred(Integer pagesTransferred) - { + public void setPagesTransferred(Integer pagesTransferred) { this.pagesTransferred = pagesTransferred; } /** * Returns the row resolution of the received fax. - * + * * @return the row resolution of the received fax. */ - public Integer getResolution() - { + public Integer getResolution() { return resolution; } /** * Sets the row resolution of the received fax. - * + * * @param resolution the row resolution of the received fax. */ - public void setResolution(Integer resolution) - { + public void setResolution(Integer resolution) { this.resolution = resolution; } /** * Returns the transfer rate in bits/s. - * + * * @return the transfer rate in bits/s. */ - public Integer getTransferRate() - { + public Integer getTransferRate() { return transferRate; } /** * Sets the transfer rate in bits/s. - * + * * @param transferRate the transfer rate in bits/s. */ - public void setTransferRate(Integer transferRate) - { + public void setTransferRate(Integer transferRate) { this.transferRate = transferRate; } /** * Returns the filename of the received fax including its full path on the * Asterisk server. - * + * * @return the filename of the received fax */ - public String getFilename() - { + public String getFilename() { return filename; } /** * Sets the filename of the received fax. - * + * * @param filename the filename of the received fax */ - public void setFilename(String filename) - { + public void setFilename(String filename) { this.filename = filename; } } diff --git a/src/main/java/org/asteriskjava/manager/event/FaxStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/FaxStatusEvent.java index d80a6f2ab..76aa6e8b4 100644 --- a/src/main/java/org/asteriskjava/manager/event/FaxStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/FaxStatusEvent.java @@ -19,8 +19,7 @@ /** * A FaxDocumentStatusEvent is an event of Digium's Fax For Asterisk add-on. */ -public class FaxStatusEvent extends AbstractFaxEvent -{ +public class FaxStatusEvent extends AbstractFaxEvent { /** * Serial version identifier. */ @@ -57,8 +56,7 @@ public class FaxStatusEvent extends AbstractFaxEvent private String status; private String operation; - public FaxStatusEvent(Object source) - { + public FaxStatusEvent(Object source) { super(source); } @@ -66,496 +64,434 @@ public FaxStatusEvent(Object source) /** * @return the operatingMode */ - public String getOperatingMode() - { + public String getOperatingMode() { return operatingMode; } /** * @param operatingMode the operatingMode to set */ - public void setOperatingMode(String operatingMode) - { + public void setOperatingMode(String operatingMode) { this.operatingMode = operatingMode; } /** * @return the result */ - public String getResult() - { + public String getResult() { return result; } /** * @param result the result to set */ - public void setResult(String result) - { + public void setResult(String result) { this.result = result; } /** * @return the error */ - public String getError() - { + public String getError() { return error; } /** * @param error the error to set */ - public void setError(String error) - { + public void setError(String error) { this.error = error; } /** * @return the callDuration */ - public Double getCallDuration() - { + public Double getCallDuration() { return callDuration; } /** * @param callDuration the callDuration to set */ - public void setCallDuration(Double callDuration) - { + public void setCallDuration(Double callDuration) { this.callDuration = callDuration; } /** * @return the ecmMode */ - public String getEcmMode() - { + public String getEcmMode() { return ecmMode; } /** * @param ecmMode the ecmMode to set */ - public void setEcmMode(String ecmMode) - { + public void setEcmMode(String ecmMode) { this.ecmMode = ecmMode; } /** * @return the dataRate */ - public Integer getDataRate() - { + public Integer getDataRate() { return dataRate; } /** * @param dataRate the dataRate to set */ - public void setDataRate(Integer dataRate) - { + public void setDataRate(Integer dataRate) { this.dataRate = dataRate; } /** * @return the imageResolution */ - public String getImageResolution() - { + public String getImageResolution() { return imageResolution; } /** * @param imageResolution the imageResolution to set */ - public void setImageResolution(String imageResolution) - { + public void setImageResolution(String imageResolution) { this.imageResolution = imageResolution; } /** * @return the imageEncoding */ - public String getImageEncoding() - { + public String getImageEncoding() { return imageEncoding; } /** * @param imageEncoding the imageEncoding to set */ - public void setImageEncoding(String imageEncoding) - { + public void setImageEncoding(String imageEncoding) { this.imageEncoding = imageEncoding; } /** * @return the pageSize */ - public String getPageSize() - { + public String getPageSize() { return pageSize; } /** * @param pageSize the pageSize to set */ - public void setPageSize(String pageSize) - { + public void setPageSize(String pageSize) { this.pageSize = pageSize; } /** * @return the documentNumber */ - public Integer getDocumentNumber() - { + public Integer getDocumentNumber() { return documentNumber; } /** * @param documentNumber the documentNumber to set */ - public void setDocumentNumber(Integer documentNumber) - { + public void setDocumentNumber(Integer documentNumber) { this.documentNumber = documentNumber; } /** * @return the pageNumber */ - public Integer getPageNumber() - { + public Integer getPageNumber() { return pageNumber; } /** * @param pageNumber the pageNumber to set */ - public void setPageNumber(Integer pageNumber) - { + public void setPageNumber(Integer pageNumber) { this.pageNumber = pageNumber; } /** * @return the fileName */ - public String getFileName() - { + public String getFileName() { return fileName; } /** * @param fileName the fileName to set */ - public void setFileName(String fileName) - { + public void setFileName(String fileName) { this.fileName = fileName; } /** * @return the txPages */ - public Integer getTxPages() - { + public Integer getTxPages() { return txPages; } /** * @param txPages the txPages to set */ - public void setTxPages(Integer txPages) - { + public void setTxPages(Integer txPages) { this.txPages = txPages; } /** * @return the txBytes */ - public Integer getTxBytes() - { + public Integer getTxBytes() { return txBytes; } /** * @param txBytes the txBytes to set */ - public void setTxBytes(Integer txBytes) - { + public void setTxBytes(Integer txBytes) { this.txBytes = txBytes; } /** * @return the totalTxLines */ - public Integer getTotalTxLines() - { + public Integer getTotalTxLines() { return totalTxLines; } /** * @param totalTxLines the totalTxLines to set */ - public void setTotalTxLines(Integer totalTxLines) - { + public void setTotalTxLines(Integer totalTxLines) { this.totalTxLines = totalTxLines; } /** * @return the rxPages */ - public Integer getRxPages() - { + public Integer getRxPages() { return rxPages; } /** * @param rxPages the rxPages to set */ - public void setRxPages(Integer rxPages) - { + public void setRxPages(Integer rxPages) { this.rxPages = rxPages; } /** * @return the rxBytes */ - public Integer getRxBytes() - { + public Integer getRxBytes() { return rxBytes; } /** * @param rxBytes the rxBytes to set */ - public void setRxBytes(Integer rxBytes) - { + public void setRxBytes(Integer rxBytes) { this.rxBytes = rxBytes; } /** * @return the totalRxLines */ - public Integer getTotalRxLines() - { + public Integer getTotalRxLines() { return totalRxLines; } /** * @param totalRxLines the totalRxLines to set */ - public void setTotalRxLines(Integer totalRxLines) - { + public void setTotalRxLines(Integer totalRxLines) { this.totalRxLines = totalRxLines; } /** * @return the totalBadLines */ - public Integer getTotalBadLines() - { + public Integer getTotalBadLines() { return totalBadLines; } /** * @param totalBadLines the totalBadLines to set */ - public void setTotalBadLines(Integer totalBadLines) - { + public void setTotalBadLines(Integer totalBadLines) { this.totalBadLines = totalBadLines; } /** * @return the disDcsDtcCtcCount */ - public Integer getDisDcsDtcCtcCount() - { + public Integer getDisDcsDtcCtcCount() { return disDcsDtcCtcCount; } /** * @param disDcsDtcCtcCount the disDcsDtcCtcCount to set */ - public void setDisDcsDtcCtcCount(Integer disDcsDtcCtcCount) - { + public void setDisDcsDtcCtcCount(Integer disDcsDtcCtcCount) { this.disDcsDtcCtcCount = disDcsDtcCtcCount; } /** * @return the cfrCount */ - public Integer getCfrCount() - { + public Integer getCfrCount() { return cfrCount; } /** * @param cfrCount the cfrCount to set */ - public void setCfrCount(Integer cfrCount) - { + public void setCfrCount(Integer cfrCount) { this.cfrCount = cfrCount; } /** * @return the fttCount */ - public Integer getFttCount() - { + public Integer getFttCount() { return fttCount; } /** * @param fttCount the fttCount to set */ - public void setFttCount(Integer fttCount) - { + public void setFttCount(Integer fttCount) { this.fttCount = fttCount; } /** * @return the mcfCount */ - public Integer getMcfCount() - { + public Integer getMcfCount() { return mcfCount; } /** * @param mcfCount the mcfCount to set */ - public void setMcfCount(Integer mcfCount) - { + public void setMcfCount(Integer mcfCount) { this.mcfCount = mcfCount; } /** * @return the pprCount */ - public Integer getPprCount() - { + public Integer getPprCount() { return pprCount; } /** * @param pprCount the pprCount to set */ - public void setPprCount(Integer pprCount) - { + public void setPprCount(Integer pprCount) { this.pprCount = pprCount; } /** * @return the rtnCount */ - public Integer getRtnCount() - { + public Integer getRtnCount() { return rtnCount; } /** * @param rtnCount the rtnCount to set */ - public void setRtnCount(Integer rtnCount) - { + public void setRtnCount(Integer rtnCount) { this.rtnCount = rtnCount; } /** * @return the dcnCount */ - public Integer getDcnCount() - { + public Integer getDcnCount() { return dcnCount; } /** * @param dcnCount the dcnCount to set */ - public void setDcnCount(Integer dcnCount) - { + public void setDcnCount(Integer dcnCount) { this.dcnCount = dcnCount; } /** * @return the remoteStationId */ - public String getRemoteStationId() - { + public String getRemoteStationId() { return remoteStationId; } /** * @param remoteStationId the remoteStationId to set */ - public void setRemoteStationId(String remoteStationId) - { + public void setRemoteStationId(String remoteStationId) { this.remoteStationId = remoteStationId; } /** * @return the localStationId */ - public String getLocalStationId() - { + public String getLocalStationId() { return localStationId; } /** * @param localStationId the localStationId to set */ - public void setLocalStationId(String localStationId) - { + public void setLocalStationId(String localStationId) { this.localStationId = localStationId; } /** * @return the callerId */ - public String getCallerId() - { + public String getCallerId() { return callerId; } /** * @param callerId the callerId to set */ - public void setCallerId(String callerid) - { + public void setCallerId(String callerid) { this.callerId = callerid; } /** * @return the status */ - public String getStatus() - { + public String getStatus() { return status; } /** * @param status the status to set */ - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } /** * @return the operation */ - public String getOperation() - { + public String getOperation() { return operation; } /** * @param context the context to set */ - public void setOperation(String operation) - { + public void setOperation(String operation) { this.operation = operation; } } diff --git a/src/main/java/org/asteriskjava/manager/event/FullyBootedEvent.java b/src/main/java/org/asteriskjava/manager/event/FullyBootedEvent.java index 84e220f45..3577e22b7 100644 --- a/src/main/java/org/asteriskjava/manager/event/FullyBootedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/FullyBootedEvent.java @@ -14,15 +14,13 @@ * It is implemented in main/asterisk.c and manager.c.
    * Available since Asterisk 1.8 */ -public class FullyBootedEvent extends ManagerEvent -{ +public class FullyBootedEvent extends ManagerEvent { private static final long serialVersionUID = 0L; private String status; private String lastreload; private Integer uptime; - public FullyBootedEvent(Object source) - { + public FullyBootedEvent(Object source) { super(source); } @@ -31,8 +29,7 @@ public FullyBootedEvent(Object source) * * @return the status. */ - public String getStatus() - { + public String getStatus() { return status; } @@ -41,24 +38,23 @@ public String getStatus() * * @param status the status. */ - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } - public String getLastreload() { - return lastreload; - } + public String getLastreload() { + return lastreload; + } - public void setLastreload(String lastreload) { - this.lastreload = lastreload; - } + public void setLastreload(String lastreload) { + this.lastreload = lastreload; + } - public Integer getUptime() { - return uptime; - } + public Integer getUptime() { + return uptime; + } - public void setUptime(Integer uptime) { - this.uptime = uptime; - } + public void setUptime(Integer uptime) { + this.uptime = uptime; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/HangupEvent.java b/src/main/java/org/asteriskjava/manager/event/HangupEvent.java index cccacb909..214dae62b 100644 --- a/src/main/java/org/asteriskjava/manager/event/HangupEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/HangupEvent.java @@ -24,8 +24,7 @@ * @author srt * @version $Id$ */ -public class HangupEvent extends AbstractChannelStateEvent -{ +public class HangupEvent extends AbstractChannelStateEvent { /** * Serializable version identifier. */ @@ -36,18 +35,15 @@ public class HangupEvent extends AbstractChannelStateEvent private String language; private String linkedId; - public HangupEvent(Object source) - { + public HangupEvent(Object source) { super(source); } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } @@ -57,8 +53,7 @@ public void setLanguage(String language) * @return the hangup cause. * @see org.asteriskjava.live.HangupCause */ - public Integer getCause() - { + public Integer getCause() { return cause; } @@ -67,8 +62,7 @@ public Integer getCause() * * @param cause the hangup cause. */ - public void setCause(Integer cause) - { + public void setCause(Integer cause) { this.cause = cause; } @@ -78,8 +72,7 @@ public void setCause(Integer cause) * @return the textual representation of the hangup cause. * @since 0.2 */ - public String getCauseTxt() - { + public String getCauseTxt() { return causeTxt; } @@ -89,24 +82,20 @@ public String getCauseTxt() * @param causeTxt the textual representation of the hangup cause. * @since 0.2 */ - public void setCauseTxt(String causeTxt) - { + public void setCauseTxt(String causeTxt) { this.causeTxt = causeTxt; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } @Override - public String toString() - { + public String toString() { StringBuilder builder = new StringBuilder(); builder.append("HangupEvent [cause="); builder.append(cause); diff --git a/src/main/java/org/asteriskjava/manager/event/HangupRequestEvent.java b/src/main/java/org/asteriskjava/manager/event/HangupRequestEvent.java index 3852045be..6ebf0a036 100644 --- a/src/main/java/org/asteriskjava/manager/event/HangupRequestEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/HangupRequestEvent.java @@ -21,8 +21,7 @@ *

    * It is implemented in channel.c */ -public class HangupRequestEvent extends AbstractChannelEvent -{ +public class HangupRequestEvent extends AbstractChannelEvent { /** * Serializable version identifier. */ @@ -32,18 +31,15 @@ public class HangupRequestEvent extends AbstractChannelEvent private String language; private String linkedId; - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public HangupRequestEvent(Object source) - { + public HangupRequestEvent(Object source) { super(source); } @@ -53,8 +49,7 @@ public HangupRequestEvent(Object source) * @return the hangup cause. * @see org.asteriskjava.live.HangupCause */ - public Integer getCause() - { + public Integer getCause() { return cause; } @@ -63,18 +58,15 @@ public Integer getCause() * * @param cause the hangup cause. */ - public void setCause(Integer cause) - { + public void setCause(Integer cause) { this.cause = cause; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } diff --git a/src/main/java/org/asteriskjava/manager/event/HoldEvent.java b/src/main/java/org/asteriskjava/manager/event/HoldEvent.java index 6c2b40435..ad3d21065 100644 --- a/src/main/java/org/asteriskjava/manager/event/HoldEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/HoldEvent.java @@ -32,22 +32,20 @@ * @version $Id$ * @since 0.2 */ -public class HoldEvent extends AbstractHoldEvent -{ +public class HoldEvent extends AbstractHoldEvent { /** * Serializable version identifier. */ private static final long serialVersionUID = 0L; private String musicClass; - + /** * Creates a new HoldEvent. * * @param source */ - public HoldEvent(Object source) - { + public HoldEvent(Object source) { super(source); /* * Asterisk prior to 1.6 and after 11 uses Hold and Unhold events @@ -58,14 +56,12 @@ public HoldEvent(Object source) setStatus(true); } - public String getMusicClass() - { + public String getMusicClass() { return musicClass; } - public void setMusicClass(String musicClass) - { + public void setMusicClass(String musicClass) { this.musicClass = musicClass; } - + } diff --git a/src/main/java/org/asteriskjava/manager/event/HoldedCallEvent.java b/src/main/java/org/asteriskjava/manager/event/HoldedCallEvent.java index 53e904019..0aff8ed1a 100644 --- a/src/main/java/org/asteriskjava/manager/event/HoldedCallEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/HoldedCallEvent.java @@ -19,12 +19,11 @@ /** * A HoldedCallEvent is triggered when a channel is put on hold.

    * It is implemented in res/res_features.c - * + * * @author srt * @version $Id$ */ -public class HoldedCallEvent extends ManagerEvent -{ +public class HoldedCallEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -37,72 +36,63 @@ public class HoldedCallEvent extends ManagerEvent /** * @param source */ - public HoldedCallEvent(Object source) - { + public HoldedCallEvent(Object source) { super(source); } /** * Returns the unique id of the channel that put the other channel on hold. */ - public String getUniqueId1() - { + public String getUniqueId1() { return uniqueId1; } /** * Sets the unique id of the channel that put the other channel on hold. */ - public void setUniqueId1(String uniqueId1) - { + public void setUniqueId1(String uniqueId1) { this.uniqueId1 = uniqueId1; } /** * Returns the unique id of the channel that has been put on hold. */ - public String getUniqueId2() - { + public String getUniqueId2() { return uniqueId2; } /** * Sets the unique id of the channel that has been put on hold. */ - public void setUniqueId2(String uniqueId2) - { + public void setUniqueId2(String uniqueId2) { this.uniqueId2 = uniqueId2; } /** * Returns the name of the channel that put the other channel on hold. */ - public String getChannel1() - { + public String getChannel1() { return channel1; } /** * Sets the name of the channel that put the other channel on hold. */ - public void setChannel1(String channel1) - { + public void setChannel1(String channel1) { this.channel1 = channel1; } /** * Returns the name of the channel that has been put on hold. */ - public String getChannel2() - { + public String getChannel2() { return channel2; } /** * Sets the name of the channel that has been put on hold. */ - public void setChannel2(String channel2) - { + public void setChannel2(String channel2) { this.channel2 = channel2; } diff --git a/src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java b/src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java index 7cc43affd..be7bbe4c1 100644 --- a/src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java +++ b/src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java @@ -6,95 +6,97 @@ */ public class InvalidAccountId extends ManagerEvent { - /** - * - */ - private static final long serialVersionUID = 1L; - private String severity; - private Integer eventVersion; - private String eventtv; - private String sessionId; - private String localAddress; - private String accountId; - private String service; - private String remoteAddress; - private String event; - - public InvalidAccountId(Object source) { super(source); } - - public static long getSerialVersionUID() { - return serialVersionUID; - } - - public String getSeverity() { - return severity; - } - - public void setSeverity(String severity) { - this.severity = severity; - } - - public Integer getEventVersion() { - return eventVersion; - } - - public void setEventVersion(Integer eventVersion) { - this.eventVersion = eventVersion; - } - - public String getEventtv() { - return eventtv; - } - - public void setEventtv(String eventtv) { - this.eventtv = eventtv; - } - - public String getSessionId() { - return sessionId; - } - - public void setSessionId(String sessionId) { - this.sessionId = sessionId; - } - - public String getLocalAddress() { - return localAddress; - } - - public void setLocalAddress(String localAddress) { - this.localAddress = localAddress; - } - - public String getAccountId() { - return accountId; - } - - public void setAccountId(String accountId) { - this.accountId = accountId; - } - - public String getService() { - return service; - } - - public void setService(String service) { - this.service = service; - } - - public String getRemoteAddress() { - return remoteAddress; - } - - public void setRemoteAddress(String remoteAddress) { - this.remoteAddress = remoteAddress; - } - - public String getEvent() { - return event; - } - - public void setEvent(String event) { - this.event = event; - } + /** + * + */ + private static final long serialVersionUID = 1L; + private String severity; + private Integer eventVersion; + private String eventtv; + private String sessionId; + private String localAddress; + private String accountId; + private String service; + private String remoteAddress; + private String event; + + public InvalidAccountId(Object source) { + super(source); + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public Integer getEventVersion() { + return eventVersion; + } + + public void setEventVersion(Integer eventVersion) { + this.eventVersion = eventVersion; + } + + public String getEventtv() { + return eventtv; + } + + public void setEventtv(String eventtv) { + this.eventtv = eventtv; + } + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + public String getLocalAddress() { + return localAddress; + } + + public void setLocalAddress(String localAddress) { + this.localAddress = localAddress; + } + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public String getRemoteAddress() { + return remoteAddress; + } + + public void setRemoteAddress(String remoteAddress) { + this.remoteAddress = remoteAddress; + } + + public String getEvent() { + return event; + } + + public void setEvent(String event) { + this.event = event; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/InvalidPasswordEvent.java b/src/main/java/org/asteriskjava/manager/event/InvalidPasswordEvent.java index e478e3544..c0a9090a1 100644 --- a/src/main/java/org/asteriskjava/manager/event/InvalidPasswordEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/InvalidPasswordEvent.java @@ -3,136 +3,112 @@ /** * Created by Alexander Polakov on 1/23/15. */ -public class InvalidPasswordEvent extends ManagerEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; - private String severity; - private Integer eventVersion; - private String eventtv; - private String sessionid; - private String receivedHash; - private String localaddress; - private String accountId; - private String receivedChallenge; - private String service; - private String remoteAddress; - private String challenge; - - public InvalidPasswordEvent(Object source) - { - super(source); - } - - public String getSeverity() - { - return severity; - } - - public void setSeverity(String severity) - { - this.severity = severity; - } - - public Integer getEventVersion() - { - return eventVersion; - } - - public void setEventVersion(Integer eventVersion) - { - this.eventVersion = eventVersion; - } - - public String getEventtv() - { - return eventtv; - } - - public void setEventtv(String eventtv) - { - this.eventtv = eventtv; - } - - public String getSessionid() - { - return sessionid; - } - - public void setSessionid(String sessionid) - { - this.sessionid = sessionid; - } - - public String getReceivedHash() - { - return receivedHash; - } - - public void setReceivedHash(String receivedHash) - { - this.receivedHash = receivedHash; - } - - public String getLocaladdress() - { - return localaddress; - } - - public void setLocaladdress(String localaddress) - { - this.localaddress = localaddress; - } - - public String getAccountId() - { - return accountId; - } - - public void setAccountId(String accountId) - { - this.accountId = accountId; - } - - public String getReceivedChallenge() - { - return receivedChallenge; - } - - public void setReceivedChallenge(String receivedChallenge) - { - this.receivedChallenge = receivedChallenge; - } - - public String getService() - { - return service; - } - - public void setService(String service) - { - this.service = service; - } - - public String getRemoteAddress() - { - return remoteAddress; - } - - public void setRemoteAddress(String remoteAddress) - { - this.remoteAddress = remoteAddress; - } - - public String getChallenge() - { - return challenge; - } - - public void setChallenge(String challenge) - { - this.challenge = challenge; - } +public class InvalidPasswordEvent extends ManagerEvent { + /** + * + */ + private static final long serialVersionUID = 1L; + private String severity; + private Integer eventVersion; + private String eventtv; + private String sessionid; + private String receivedHash; + private String localaddress; + private String accountId; + private String receivedChallenge; + private String service; + private String remoteAddress; + private String challenge; + + public InvalidPasswordEvent(Object source) { + super(source); + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public Integer getEventVersion() { + return eventVersion; + } + + public void setEventVersion(Integer eventVersion) { + this.eventVersion = eventVersion; + } + + public String getEventtv() { + return eventtv; + } + + public void setEventtv(String eventtv) { + this.eventtv = eventtv; + } + + public String getSessionid() { + return sessionid; + } + + public void setSessionid(String sessionid) { + this.sessionid = sessionid; + } + + public String getReceivedHash() { + return receivedHash; + } + + public void setReceivedHash(String receivedHash) { + this.receivedHash = receivedHash; + } + + public String getLocaladdress() { + return localaddress; + } + + public void setLocaladdress(String localaddress) { + this.localaddress = localaddress; + } + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public String getReceivedChallenge() { + return receivedChallenge; + } + + public void setReceivedChallenge(String receivedChallenge) { + this.receivedChallenge = receivedChallenge; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public String getRemoteAddress() { + return remoteAddress; + } + + public void setRemoteAddress(String remoteAddress) { + this.remoteAddress = remoteAddress; + } + + public String getChallenge() { + return challenge; + } + + public void setChallenge(String challenge) { + this.challenge = challenge; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/JabberEventEvent.java b/src/main/java/org/asteriskjava/manager/event/JabberEventEvent.java index 0daf07591..0e78da0af 100644 --- a/src/main/java/org/asteriskjava/manager/event/JabberEventEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/JabberEventEvent.java @@ -25,35 +25,29 @@ * @version $Id$ * @since 1.0.0 */ -public class JabberEventEvent extends ManagerEvent -{ +public class JabberEventEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private String account; private String packet; - public JabberEventEvent(Object source) - { + public JabberEventEvent(Object source) { super(source); } - public String getAccount() - { + public String getAccount() { return account; } - public void setAccount(String account) - { + public void setAccount(String account) { this.account = account; } - public String getPacket() - { + public String getPacket() { return packet; } - public void setPacket(String packet) - { + public void setPacket(String packet) { this.packet = packet; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/JitterBufStatsEvent.java b/src/main/java/org/asteriskjava/manager/event/JitterBufStatsEvent.java index f321811b8..daf0f6531 100644 --- a/src/main/java/org/asteriskjava/manager/event/JitterBufStatsEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/JitterBufStatsEvent.java @@ -26,8 +26,7 @@ * @version $Id$ * @since 1.0.0 */ -public class JitterBufStatsEvent extends ManagerEvent -{ +public class JitterBufStatsEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private String owner; @@ -47,8 +46,7 @@ public class JitterBufStatsEvent extends ManagerEvent private Integer remoteooo; private Integer remoteReceived; - public JitterBufStatsEvent(Object source) - { + public JitterBufStatsEvent(Object source) { super(source); } @@ -57,163 +55,131 @@ public JitterBufStatsEvent(Object source) * * @return channel the name of the channel. */ - public String getOwner() - { + public String getOwner() { return owner; } - public void setOwner(String owner) - { + public void setOwner(String owner) { this.owner = owner; } - public Integer getPing() - { + public Integer getPing() { return ping; } - public void setPing(Integer ping) - { + public void setPing(Integer ping) { this.ping = ping; } - public Integer getLocalJitter() - { + public Integer getLocalJitter() { return localJitter; } - public void setLocalJitter(Integer localJitter) - { + public void setLocalJitter(Integer localJitter) { this.localJitter = localJitter; } - public Integer getLocalJbDelay() - { + public Integer getLocalJbDelay() { return localJbDelay; } - public void setLocalJbDelay(Integer localJbDelay) - { + public void setLocalJbDelay(Integer localJbDelay) { this.localJbDelay = localJbDelay; } - public Integer getLocalTotalLost() - { + public Integer getLocalTotalLost() { return localTotalLost; } - public void setLocalTotalLost(Integer localTotalLost) - { + public void setLocalTotalLost(Integer localTotalLost) { this.localTotalLost = localTotalLost; } - public Integer getLocalLossPercent() - { + public Integer getLocalLossPercent() { return localLossPercent; } - public void setLocalLossPercent(Integer localLossPercent) - { + public void setLocalLossPercent(Integer localLossPercent) { this.localLossPercent = localLossPercent; } - public Integer getLocalDropped() - { + public Integer getLocalDropped() { return localDropped; } - public void setLocalDropped(Integer localDropped) - { + public void setLocalDropped(Integer localDropped) { this.localDropped = localDropped; } - public Integer getLocalooo() - { + public Integer getLocalooo() { return localooo; } - public void setLocalooo(Integer localooo) - { + public void setLocalooo(Integer localooo) { this.localooo = localooo; } - public Integer getLocalReceived() - { + public Integer getLocalReceived() { return localReceived; } - public void setLocalReceived(Integer localReceived) - { + public void setLocalReceived(Integer localReceived) { this.localReceived = localReceived; } - public Integer getRemoteJitter() - { + public Integer getRemoteJitter() { return remoteJitter; } - public void setRemoteJitter(Integer remoteJitter) - { + public void setRemoteJitter(Integer remoteJitter) { this.remoteJitter = remoteJitter; } - public Integer getRemoteJbDelay() - { + public Integer getRemoteJbDelay() { return remoteJbDelay; } - public void setRemoteJbDelay(Integer remoteJbDelay) - { + public void setRemoteJbDelay(Integer remoteJbDelay) { this.remoteJbDelay = remoteJbDelay; } - public Integer getRemoteTotalLost() - { + public Integer getRemoteTotalLost() { return remoteTotalLost; } - public void setRemoteTotalLost(Integer remoteTotalLost) - { + public void setRemoteTotalLost(Integer remoteTotalLost) { this.remoteTotalLost = remoteTotalLost; } - public Integer getRemoteLossPercent() - { + public Integer getRemoteLossPercent() { return remoteLossPercent; } - public void setRemoteLossPercent(Integer remoteLossPercent) - { + public void setRemoteLossPercent(Integer remoteLossPercent) { this.remoteLossPercent = remoteLossPercent; } - public Integer getRemoteDropped() - { + public Integer getRemoteDropped() { return remoteDropped; } - public void setRemoteDropped(Integer remoteDropped) - { + public void setRemoteDropped(Integer remoteDropped) { this.remoteDropped = remoteDropped; } - public Integer getRemoteooo() - { + public Integer getRemoteooo() { return remoteooo; } - public void setRemoteooo(Integer remoteooo) - { + public void setRemoteooo(Integer remoteooo) { this.remoteooo = remoteooo; } - public Integer getRemoteReceived() - { + public Integer getRemoteReceived() { return remoteReceived; } - public void setRemoteReceived(Integer remoteReceived) - { + public void setRemoteReceived(Integer remoteReceived) { this.remoteReceived = remoteReceived; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/JoinEvent.java b/src/main/java/org/asteriskjava/manager/event/JoinEvent.java index b626dcbaa..22c355ef2 100644 --- a/src/main/java/org/asteriskjava/manager/event/JoinEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/JoinEvent.java @@ -23,8 +23,7 @@ * * @author srt */ -public class JoinEvent extends QueueEvent -{ +public class JoinEvent extends QueueEvent { /** * Serializable version identifier. */ @@ -33,8 +32,7 @@ public class JoinEvent extends QueueEvent protected String callerIdName; protected Integer position; - public JoinEvent(Object source) - { + public JoinEvent(Object source) { super(source); } @@ -46,8 +44,7 @@ public JoinEvent(Object source) * @deprecated since 1.0.0, use {@link #getCallerIdNum()} instead. */ @Deprecated - public String getCallerId() - { + public String getCallerId() { return callerIdNum; } @@ -55,26 +52,23 @@ public String getCallerId() * Sets the Caller*ID number of the channel that joined the queue. * * @param callerId the Caller*ID number of the channel that joined the - * queue. + * queue. */ - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { this.callerIdNum = callerId; } /** * Returns the position of the joined channel in the queue. */ - public Integer getPosition() - { + public Integer getPosition() { return position; } /** * Sets the position of the joined channel in the queue. */ - public void setPosition(Integer position) - { + public void setPosition(Integer position) { this.position = position; } diff --git a/src/main/java/org/asteriskjava/manager/event/LeaveEvent.java b/src/main/java/org/asteriskjava/manager/event/LeaveEvent.java index ac069e286..c6eada661 100644 --- a/src/main/java/org/asteriskjava/manager/event/LeaveEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/LeaveEvent.java @@ -19,11 +19,10 @@ /** * A LeaveEvent is triggered when a channel leaves a queue.

    * It is implemented in apps/app_queue.c - * + * * @author srt */ -public class LeaveEvent extends QueueEvent -{ +public class LeaveEvent extends QueueEvent { /** * Serializable version identifier */ @@ -34,21 +33,18 @@ public class LeaveEvent extends QueueEvent /** * @param source */ - public LeaveEvent(Object source) - { + public LeaveEvent(Object source) { super(source); } /** * @return the position of the caller at the time they leave the queue */ - public Integer getPosition() - { + public Integer getPosition() { return position; } - public void setPosition(Integer position) - { + public void setPosition(Integer position) { this.position = position; } } diff --git a/src/main/java/org/asteriskjava/manager/event/LinkEvent.java b/src/main/java/org/asteriskjava/manager/event/LinkEvent.java index c0614ed57..6547be706 100644 --- a/src/main/java/org/asteriskjava/manager/event/LinkEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/LinkEvent.java @@ -27,17 +27,16 @@ * @author srt * @version $Id$ * @deprecated as of 1.0.0, use {@link org.asteriskjava.manager.event.BridgeEvent} and - * {@link BridgeEvent#isLink()} instead + * {@link BridgeEvent#isLink()} instead */ -@Deprecated public class LinkEvent extends BridgeEvent -{ +@Deprecated +public class LinkEvent extends BridgeEvent { /** * Serializable version identifier. */ static final long serialVersionUID = -4023240534975776225L; - public LinkEvent(Object source) - { + public LinkEvent(Object source) { super(source); setBridgeState(BRIDGE_STATE_LINK); } diff --git a/src/main/java/org/asteriskjava/manager/event/ListDialplanEvent.java b/src/main/java/org/asteriskjava/manager/event/ListDialplanEvent.java index 1f8ceea49..e3fdae6b3 100644 --- a/src/main/java/org/asteriskjava/manager/event/ListDialplanEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ListDialplanEvent.java @@ -12,8 +12,7 @@ * @see ShowDialplanCompleteEvent * @since 1.0.0 */ -public class ListDialplanEvent extends ResponseEvent -{ +public class ListDialplanEvent extends ResponseEvent { private static final long serialVersionUID = 1L; private static final String PRIORITY_HINT = "hint"; @@ -25,8 +24,7 @@ public class ListDialplanEvent extends ResponseEvent private String appData; private String registrar; - public ListDialplanEvent(Object source) - { + public ListDialplanEvent(Object source) { super(source); } @@ -35,54 +33,46 @@ public ListDialplanEvent(Object source) * * @return the extension or extension pattern. */ - public String getExtension() - { + public String getExtension() { return extension; } - public void setExtension(String extension) - { + public void setExtension(String extension) { this.extension = extension; } /** * Returns the extension label. + * * @return the extension label or null if none. */ - public String getExtensionLabel() - { + public String getExtensionLabel() { return extensionLabel; } - public void setExtensionLabel(String extensionLabel) - { + public void setExtensionLabel(String extensionLabel) { this.extensionLabel = extensionLabel; } /** * Checks whether this is a hint. + * * @return true if this is a hint, false otherwise. */ - public boolean isHint() - { + public boolean isHint() { return hint; } - public void setPriority(String priorityString) - { - if (priorityString == null) - { + public void setPriority(String priorityString) { + if (priorityString == null) { this.priority = null; return; } - if (PRIORITY_HINT.equals(priorityString)) - { + if (PRIORITY_HINT.equals(priorityString)) { hint = true; this.priority = null; - } - else - { + } else { this.priority = Integer.parseInt(priorityString); } } @@ -92,13 +82,11 @@ public void setPriority(String priorityString) * * @return the application configured to handle this priority. */ - public String getApplication() - { + public String getApplication() { return application; } - public void setApplication(String application) - { + public void setApplication(String application) { this.application = application; } @@ -106,33 +94,29 @@ public void setApplication(String application) * Returns the parameters of the application configured to handle this priority. * * @return the parameters of the application configured to handle this priority - * or null if none. + * or null if none. */ - public String getAppData() - { + public String getAppData() { return appData; } - public void setAppData(String appData) - { + public void setAppData(String appData) { this.appData = appData; } /** * Returns the registrar that registered this priority.

    * Typical values are "features" for the parkedcalls context, "pbx_config" for priorities - * defined in extensions.conf or "app_dial" for the + * defined in extensions.conf or "app_dial" for the * app_dial_gosub_virtual_context context. * * @return the registrar that registered this priority. */ - public String getRegistrar() - { + public String getRegistrar() { return registrar; } - public void setRegistrar(String registrar) - { + public void setRegistrar(String registrar) { this.registrar = registrar; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/LocalBridgeEvent.java b/src/main/java/org/asteriskjava/manager/event/LocalBridgeEvent.java index 51e0cc9d3..45dd94ba5 100644 --- a/src/main/java/org/asteriskjava/manager/event/LocalBridgeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/LocalBridgeEvent.java @@ -19,14 +19,13 @@ /** * https://wiki.asterisk.org/wiki/display/AST/Asterisk+11+ManagerEvent_LocalBridge * Triggered when 2 halves of a local channels are bridged - * + *

    * It is implemented in channels/chan_local.c * * @author jylebleu * @version $Id$ */ -public class LocalBridgeEvent extends ManagerEvent -{ +public class LocalBridgeEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -63,14 +62,13 @@ public class LocalBridgeEvent extends ManagerEvent private String localOneCalleridNum; private String localTwoConnectedLineName; private String localTwoConnectedLineNum; - + private String localTwoLinkedid; private String localOneLinkedid; private String localOneAccountCode; private String localTwoAccountCode; - public LocalBridgeEvent(Object source) - { + public LocalBridgeEvent(Object source) { super(source); } @@ -134,9 +132,9 @@ public void setCallerId2(String callerId2) { /** * Local optimization values - * - * Yes - * No + *

    + * Yes + * No * * @return Local optimization */ @@ -149,283 +147,227 @@ public void setLocalOptimization(String localOptimization) { this.localOptimization = localOptimization; } - public String getLocalOneCalleridName() - { + public String getLocalOneCalleridName() { return localOneCalleridName; } - public void setLocalOneCalleridName(String localOneCalleridName) - { + public void setLocalOneCalleridName(String localOneCalleridName) { this.localOneCalleridName = localOneCalleridName; } - public String getLocalTwoChannel() - { + public String getLocalTwoChannel() { return localTwoChannel; } - public void setLocalTwoChannel(String localTwoChannel) - { + public void setLocalTwoChannel(String localTwoChannel) { this.localTwoChannel = localTwoChannel; } - public String getLocalTwoLanguage() - { + public String getLocalTwoLanguage() { return localTwoLanguage; } - public void setLocalTwoLanguage(String localTwoLanguage) - { + public void setLocalTwoLanguage(String localTwoLanguage) { this.localTwoLanguage = localTwoLanguage; } - public String getLocalTwoExten() - { + public String getLocalTwoExten() { return localTwoExten; } - public void setLocalTwoExten(String localTwoExten) - { + public void setLocalTwoExten(String localTwoExten) { this.localTwoExten = localTwoExten; } - public String getLocalOneChannel() - { + public String getLocalOneChannel() { return localOneChannel; } - public void setLocalOneChannel(String localOneChannel) - { + public void setLocalOneChannel(String localOneChannel) { this.localOneChannel = localOneChannel; } - public String getLocalOneContext() - { + public String getLocalOneContext() { return localOneContext; } - public void setLocalOneContext(String localOneContext) - { + public void setLocalOneContext(String localOneContext) { this.localOneContext = localOneContext; } - public String getLocalOneConnectedLineNum() - { + public String getLocalOneConnectedLineNum() { return localOneConnectedLineNum; } - public void setLocalOneConnectedLineNum(String localOneConnectedLineNum) - { + public void setLocalOneConnectedLineNum(String localOneConnectedLineNum) { this.localOneConnectedLineNum = localOneConnectedLineNum; } - public String getLocalOneConnectedLineName() - { + public String getLocalOneConnectedLineName() { return localOneConnectedLineName; } - public void setLocalOneConnectedLineName(String localOneConnectedLineName) - { + public void setLocalOneConnectedLineName(String localOneConnectedLineName) { this.localOneConnectedLineName = localOneConnectedLineName; } - public String getLocalOneChannelStateDesc() - { + public String getLocalOneChannelStateDesc() { return localOneChannelStateDesc; } - public void setLocalOneChannelStateDesc(String localOneChannelStateDesc) - { + public void setLocalOneChannelStateDesc(String localOneChannelStateDesc) { this.localOneChannelStateDesc = localOneChannelStateDesc; } - public String getLocalOneChannelState() - { + public String getLocalOneChannelState() { return localOneChannelState; } - public void setLocalOneChannelState(String localOneChannelState) - { + public void setLocalOneChannelState(String localOneChannelState) { this.localOneChannelState = localOneChannelState; } - public String getLocalOneExten() - { + public String getLocalOneExten() { return localOneExten; } - public void setLocalOneExten(String localOneExten) - { + public void setLocalOneExten(String localOneExten) { this.localOneExten = localOneExten; } - public String getLocalOneLanguage() - { + public String getLocalOneLanguage() { return localOneLanguage; } - public void setLocalOneLanguage(String localOneLanguage) - { + public void setLocalOneLanguage(String localOneLanguage) { this.localOneLanguage = localOneLanguage; } - public String getLocalOnePriority() - { + public String getLocalOnePriority() { return localOnePriority; } - public void setLocalOnePriority(String localOnePriority) - { + public void setLocalOnePriority(String localOnePriority) { this.localOnePriority = localOnePriority; } - public String getLocalOneUniqueId() - { + public String getLocalOneUniqueId() { return localOneUniqueId; } - public void setLocalOneUniqueId(String localOneUniqueId) - { + public void setLocalOneUniqueId(String localOneUniqueId) { this.localOneUniqueId = localOneUniqueId; } - public String getLocalTwochannelState() - { + public String getLocalTwochannelState() { return localTwochannelState; } - public void setLocalTwochannelState(String localTwochannelState) - { + public void setLocalTwochannelState(String localTwochannelState) { this.localTwochannelState = localTwochannelState; } - public String getLocalTwoChannelStateDesc() - { + public String getLocalTwoChannelStateDesc() { return localTwoChannelStateDesc; } - public void setLocalTwoChannelStateDesc(String localTwoChannelStateDesc) - { + public void setLocalTwoChannelStateDesc(String localTwoChannelStateDesc) { this.localTwoChannelStateDesc = localTwoChannelStateDesc; } - public String getLocalTwoPriority() - { + public String getLocalTwoPriority() { return localTwoPriority; } - public void setLocalTwoPriority(String localTwoPriority) - { + public void setLocalTwoPriority(String localTwoPriority) { this.localTwoPriority = localTwoPriority; } - public String getLocalTwoContext() - { + public String getLocalTwoContext() { return localTwoContext; } - public void setLocalTwoContext(String localTwoContext) - { + public void setLocalTwoContext(String localTwoContext) { this.localTwoContext = localTwoContext; } - public String getLocalTwoCalleridNum() - { + public String getLocalTwoCalleridNum() { return localTwoCalleridNum; } - public void setLocalTwoCalleridNum(String localTwoCalleridNum) - { + public void setLocalTwoCalleridNum(String localTwoCalleridNum) { this.localTwoCalleridNum = localTwoCalleridNum; } - public String getLocalTwoCalleridName() - { + public String getLocalTwoCalleridName() { return localTwoCalleridName; } - public void setLocalTwoCalleridName(String localTwoCalleridName) - { + public void setLocalTwoCalleridName(String localTwoCalleridName) { this.localTwoCalleridName = localTwoCalleridName; } - public String getLocalTwoUniqueid() - { + public String getLocalTwoUniqueid() { return localTwoUniqueid; } - public void setLocalTwoUniqueid(String localTwoUniqueid) - { + public void setLocalTwoUniqueid(String localTwoUniqueid) { this.localTwoUniqueid = localTwoUniqueid; } - public String getLocalOneCalleridNum() - { + public String getLocalOneCalleridNum() { return localOneCalleridNum; } - public void setLocalOneCalleridNum(String localOneCalleridNum) - { + public void setLocalOneCalleridNum(String localOneCalleridNum) { this.localOneCalleridNum = localOneCalleridNum; } - public String getLocalTwoConnectedLineName() - { + public String getLocalTwoConnectedLineName() { return localTwoConnectedLineName; } - public void setLocalTwoConnectedLineName(String localTwoConnectedLineName) - { + public void setLocalTwoConnectedLineName(String localTwoConnectedLineName) { this.localTwoConnectedLineName = localTwoConnectedLineName; } - public String getLocalTwoConnectedLineNum() - { + public String getLocalTwoConnectedLineNum() { return localTwoConnectedLineNum; } - public void setLocalTwoConnectedLineNum(String localTwoConnectedLineNum) - { + public void setLocalTwoConnectedLineNum(String localTwoConnectedLineNum) { this.localTwoConnectedLineNum = localTwoConnectedLineNum; } - public String getLocalTwoLinkedid() - { + public String getLocalTwoLinkedid() { return localTwoLinkedid; } - public void setLocalTwoLinkedid(String localTwoLinkedid) - { + public void setLocalTwoLinkedid(String localTwoLinkedid) { this.localTwoLinkedid = localTwoLinkedid; } - public String getLocalOneLinkedid() - { + public String getLocalOneLinkedid() { return localOneLinkedid; } - public void setLocalOneLinkedid(String localOneLinkedid) - { + public void setLocalOneLinkedid(String localOneLinkedid) { this.localOneLinkedid = localOneLinkedid; } - public String getLocalOneAccountCode() - { + public String getLocalOneAccountCode() { return localOneAccountCode; } - public void setLocalOneAccountCode(String localOneAccountCode) - { + public void setLocalOneAccountCode(String localOneAccountCode) { this.localOneAccountCode = localOneAccountCode; } - public String getLocalTwoAccountCode() - { + public String getLocalTwoAccountCode() { return localTwoAccountCode; } - public void setLocalTwoAccountCode(String localTwoAccountCode) - { + public void setLocalTwoAccountCode(String localTwoAccountCode) { this.localTwoAccountCode = localTwoAccountCode; } } diff --git a/src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java index a05baf9ae..aa815f099 100644 --- a/src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationBeginEvent.java @@ -20,8 +20,7 @@ * Raised when two halves of a Local Channel begin to optimize themselves out of * the media path. Available since Asterisk 12 */ -public class LocalOptimizationBeginEvent extends ManagerEvent -{ +public class LocalOptimizationBeginEvent extends ManagerEvent { private static final long serialVersionUID = 0L; private Integer id; @@ -73,448 +72,359 @@ public class LocalOptimizationBeginEvent extends ManagerEvent private String localOneLanguage; private String sourceLanguage; - public LocalOptimizationBeginEvent(Object source) - { + public LocalOptimizationBeginEvent(Object source) { super(source); } - public Integer getId() - { + public Integer getId() { return this.id; } - public void setId(Integer value) - { + public void setId(Integer value) { this.id = value; } - public String getDestUniqueId() - { + public String getDestUniqueId() { return this.destUniqueId; } - public void setDestUniqueId(String value) - { + public void setDestUniqueId(String value) { this.destUniqueId = value; } - public String getLocalOneChannel() - { + public String getLocalOneChannel() { return this.localOneChannel; } - public void setLocalOneChannel(String value) - { + public void setLocalOneChannel(String value) { this.localOneChannel = value; } - public String getLocalOneChannelState() - { + public String getLocalOneChannelState() { return this.localOneChannelState; } - public void setLocalOneChannelState(String value) - { + public void setLocalOneChannelState(String value) { this.localOneChannelState = value; } - public String getLocalOneChannelStateDesc() - { + public String getLocalOneChannelStateDesc() { return this.localOneChannelStateDesc; } - public void setLocalOneChannelStateDesc(String value) - { + public void setLocalOneChannelStateDesc(String value) { this.localOneChannelStateDesc = value; } - public String getLocalOneCallerIDNum() - { + public String getLocalOneCallerIDNum() { return this.localOneCallerIDNum; } - public void setLocalOneCallerIDNum(String value) - { + public void setLocalOneCallerIDNum(String value) { this.localOneCallerIDNum = value; } - public String getLocalOneCallerIDName() - { + public String getLocalOneCallerIDName() { return this.localOneCallerIDName; } - public void setLocalOneCallerIDName(String value) - { + public void setLocalOneCallerIDName(String value) { this.localOneCallerIDName = value; } - public String getLocalOneConnectedLineNum() - { + public String getLocalOneConnectedLineNum() { return this.localOneConnectedLineNum; } - public void setLocalOneConnectedLineNum(String value) - { + public void setLocalOneConnectedLineNum(String value) { this.localOneConnectedLineNum = value; } - public String getLocalOneConnectedLineName() - { + public String getLocalOneConnectedLineName() { return this.localOneConnectedLineName; } - public void setLocalOneConnectedLineName(String value) - { + public void setLocalOneConnectedLineName(String value) { this.localOneConnectedLineName = value; } - public String getLocalOneAccountCode() - { + public String getLocalOneAccountCode() { return this.localOneAccountCode; } - public void setLocalOneAccountCode(String value) - { + public void setLocalOneAccountCode(String value) { this.localOneAccountCode = value; } - public String getLocalOneContext() - { + public String getLocalOneContext() { return this.localOneContext; } - public void setLocalOneContext(String value) - { + public void setLocalOneContext(String value) { this.localOneContext = value; } - public String getLocalOneExten() - { + public String getLocalOneExten() { return this.localOneExten; } - public void setLocalOneExten(String value) - { + public void setLocalOneExten(String value) { this.localOneExten = value; } - public Integer getLocalOnePriority() - { + public Integer getLocalOnePriority() { return this.localOnePriority; } - public void setLocalOnePriority(Integer value) - { + public void setLocalOnePriority(Integer value) { this.localOnePriority = value; } - public String getLocalOneUniqueid() - { + public String getLocalOneUniqueid() { return this.localOneUniqueid; } - public void setLocalOneUniqueid(String value) - { + public void setLocalOneUniqueid(String value) { this.localOneUniqueid = value; } - public String getLocalOneLinkedid() - { + public String getLocalOneLinkedid() { return this.localOneLinkedid; } - public void setLocalOneLinkedid(String value) - { + public void setLocalOneLinkedid(String value) { this.localOneLinkedid = value; } - public String getLocalTwoChannel() - { + public String getLocalTwoChannel() { return this.localTwoChannel; } - public void setLocalTwoChannel(String value) - { + public void setLocalTwoChannel(String value) { this.localTwoChannel = value; } - public String getLocalTwoChannelState() - { + public String getLocalTwoChannelState() { return this.localTwoChannelState; } - public void setLocalTwoChannelState(String value) - { + public void setLocalTwoChannelState(String value) { this.localTwoChannelState = value; } - public String getLocalTwoChannelStateDesc() - { + public String getLocalTwoChannelStateDesc() { return this.localTwoChannelStateDesc; } - public void setLocalTwoChannelStateDesc(String value) - { + public void setLocalTwoChannelStateDesc(String value) { this.localTwoChannelStateDesc = value; } - public String getLocalTwoCallerIDNum() - { + public String getLocalTwoCallerIDNum() { return this.localTwoCallerIDNum; } - public void setLocalTwoCallerIDNum(String value) - { + public void setLocalTwoCallerIDNum(String value) { this.localTwoCallerIDNum = value; } - public String getLocalTwoCallerIDName() - { + public String getLocalTwoCallerIDName() { return this.localTwoCallerIDName; } - public void setLocalTwoCallerIDName(String value) - { + public void setLocalTwoCallerIDName(String value) { this.localTwoCallerIDName = value; } - public String getLocalTwoConnectedLineNum() - { + public String getLocalTwoConnectedLineNum() { return this.localTwoConnectedLineNum; } - public void setLocalTwoConnectedLineNum(String value) - { + public void setLocalTwoConnectedLineNum(String value) { this.localTwoConnectedLineNum = value; } - public String getLocalTwoConnectedLineName() - { + public String getLocalTwoConnectedLineName() { return this.localTwoConnectedLineName; } - public void setLocalTwoConnectedLineName(String value) - { + public void setLocalTwoConnectedLineName(String value) { this.localTwoConnectedLineName = value; } - public String getLocalTwoAccountCode() - { + public String getLocalTwoAccountCode() { return this.localTwoAccountCode; } - public void setLocalTwoAccountCode(String value) - { + public void setLocalTwoAccountCode(String value) { this.localTwoAccountCode = value; } - public String getLocalTwoContext() - { + public String getLocalTwoContext() { return this.localTwoContext; } - public void setLocalTwoContext(String value) - { + public void setLocalTwoContext(String value) { this.localTwoContext = value; } - public String getLocalTwoExten() - { + public String getLocalTwoExten() { return this.localTwoExten; } - public void setLocalTwoExten(String value) - { + public void setLocalTwoExten(String value) { this.localTwoExten = value; } - public Integer getLocalTwoPriority() - { + public Integer getLocalTwoPriority() { return this.localTwoPriority; } - public void setLocalTwoPriority(Integer value) - { + public void setLocalTwoPriority(Integer value) { this.localTwoPriority = value; } - public String getLocalTwoUniqueid() - { + public String getLocalTwoUniqueid() { return this.localTwoUniqueid; } - public void setLocalTwoUniqueid(String value) - { + public void setLocalTwoUniqueid(String value) { this.localTwoUniqueid = value; } - public String getLocalTwoLinkedid() - { + public String getLocalTwoLinkedid() { return this.localTwoLinkedid; } - public void setLocalTwoLinkedid(String value) - { + public void setLocalTwoLinkedid(String value) { this.localTwoLinkedid = value; } - public String getSourceChannel() - { + public String getSourceChannel() { return this.sourceChannel; } - public void setSourceChannel(String value) - { + public void setSourceChannel(String value) { this.sourceChannel = value; } - public String getSourceChannelState() - { + public String getSourceChannelState() { return this.sourceChannelState; } - public void setSourceChannelState(String value) - { + public void setSourceChannelState(String value) { this.sourceChannelState = value; } - public String getSourceChannelStateDesc() - { + public String getSourceChannelStateDesc() { return this.sourceChannelStateDesc; } - public void setSourceChannelStateDesc(String value) - { + public void setSourceChannelStateDesc(String value) { this.sourceChannelStateDesc = value; } - public String getSourceCallerIDNum() - { + public String getSourceCallerIDNum() { return this.sourceCallerIDNum; } - public void setSourceCallerIDNum(String value) - { + public void setSourceCallerIDNum(String value) { this.sourceCallerIDNum = value; } - public String getSourceCallerIDName() - { + public String getSourceCallerIDName() { return this.sourceCallerIDName; } - public void setSourceCallerIDName(String value) - { + public void setSourceCallerIDName(String value) { this.sourceCallerIDName = value; } - public String getSourceConnectedLineNum() - { + public String getSourceConnectedLineNum() { return this.sourceConnectedLineNum; } - public void setSourceConnectedLineNum(String value) - { + public void setSourceConnectedLineNum(String value) { this.sourceConnectedLineNum = value; } - public String getSourceConnectedLineName() - { + public String getSourceConnectedLineName() { return this.sourceConnectedLineName; } - public void setSourceConnectedLineName(String value) - { + public void setSourceConnectedLineName(String value) { this.sourceConnectedLineName = value; } - public String getSourceAccountCode() - { + public String getSourceAccountCode() { return this.sourceAccountCode; } - public void setSourceAccountCode(String value) - { + public void setSourceAccountCode(String value) { this.sourceAccountCode = value; } - public String getSourceContext() - { + public String getSourceContext() { return this.sourceContext; } - public void setSourceContext(String value) - { + public void setSourceContext(String value) { this.sourceContext = value; } - public String getSourceExten() - { + public String getSourceExten() { return this.sourceExten; } - public void setSourceExten(String value) - { + public void setSourceExten(String value) { this.sourceExten = value; } - public Integer getSourcePriority() - { + public Integer getSourcePriority() { return this.sourcePriority; } - public void setSourcePriority(Integer value) - { + public void setSourcePriority(Integer value) { this.sourcePriority = value; } - public String getSourceUniqueid() - { + public String getSourceUniqueid() { return this.sourceUniqueid; } - public void setSourceUniqueid(String value) - { + public void setSourceUniqueid(String value) { this.sourceUniqueid = value; } - public String getSourceLinkedid() - { + public String getSourceLinkedid() { return this.sourceLinkedid; } - public void setSourceLinkedid(String value) - { + public void setSourceLinkedid(String value) { this.sourceLinkedid = value; } - public String getLocalTwoLanguage() - { + public String getLocalTwoLanguage() { return localTwoLanguage; } - public void setLocalTwoLanguage(String localTwoLanguage) - { + public void setLocalTwoLanguage(String localTwoLanguage) { this.localTwoLanguage = localTwoLanguage; } - public String getLocalOneLanguage() - { + public String getLocalOneLanguage() { return localOneLanguage; } - public void setLocalOneLanguage(String localOneLanguage) - { + public void setLocalOneLanguage(String localOneLanguage) { this.localOneLanguage = localOneLanguage; } - public String getSourceLanguage() - { + public String getSourceLanguage() { return sourceLanguage; } - public void setSourceLanguage(String sourceLanguage) - { + public void setSourceLanguage(String sourceLanguage) { this.sourceLanguage = sourceLanguage; } } diff --git a/src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java index 1407bec13..4d4f20d88 100644 --- a/src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/LocalOptimizationEndEvent.java @@ -20,8 +20,7 @@ * Raised when two halves of a Local Channel have finished optimizing themselves * out of the media path. Available since Asterisk 12 */ -public class LocalOptimizationEndEvent extends ManagerEvent -{ +public class LocalOptimizationEndEvent extends ManagerEvent { private static final long serialVersionUID = 0L; private Integer id; @@ -58,308 +57,247 @@ public class LocalOptimizationEndEvent extends ManagerEvent private String localTwoLanguage; private String localOneLanguage; - public LocalOptimizationEndEvent(Object source) - { + public LocalOptimizationEndEvent(Object source) { super(source); } - public Integer getId() - { + public Integer getId() { return this.id; } - public void setId(Integer value) - { + public void setId(Integer value) { this.id = value; } - public Boolean getSuccess() - { + public Boolean getSuccess() { return this.success; } - public void setSuccess(Boolean success) - { + public void setSuccess(Boolean success) { this.success = success; } - public String getLocalOneChannel() - { + public String getLocalOneChannel() { return this.localOneChannel; } - public void setLocalOneChannel(String value) - { + public void setLocalOneChannel(String value) { this.localOneChannel = value; } - public String getLocalOneChannelState() - { + public String getLocalOneChannelState() { return this.localOneChannelState; } - public void setLocalOneChannelState(String value) - { + public void setLocalOneChannelState(String value) { this.localOneChannelState = value; } - public String getLocalOneChannelStateDesc() - { + public String getLocalOneChannelStateDesc() { return this.localOneChannelStateDesc; } - public void setLocalOneChannelStateDesc(String value) - { + public void setLocalOneChannelStateDesc(String value) { this.localOneChannelStateDesc = value; } - public String getLocalOneCallerIDNum() - { + public String getLocalOneCallerIDNum() { return this.localOneCallerIDNum; } - public void setLocalOneCallerIDNum(String value) - { + public void setLocalOneCallerIDNum(String value) { this.localOneCallerIDNum = value; } - public String getLocalOneCallerIDName() - { + public String getLocalOneCallerIDName() { return this.localOneCallerIDName; } - public void setLocalOneCallerIDName(String value) - { + public void setLocalOneCallerIDName(String value) { this.localOneCallerIDName = value; } - public String getLocalOneConnectedLineNum() - { + public String getLocalOneConnectedLineNum() { return this.localOneConnectedLineNum; } - public void setLocalOneConnectedLineNum(String value) - { + public void setLocalOneConnectedLineNum(String value) { this.localOneConnectedLineNum = value; } - public String getLocalOneConnectedLineName() - { + public String getLocalOneConnectedLineName() { return this.localOneConnectedLineName; } - public void setLocalOneConnectedLineName(String value) - { + public void setLocalOneConnectedLineName(String value) { this.localOneConnectedLineName = value; } - public String getLocalOneAccountCode() - { + public String getLocalOneAccountCode() { return this.localOneAccountCode; } - public void setLocalOneAccountCode(String value) - { + public void setLocalOneAccountCode(String value) { this.localOneAccountCode = value; } - public String getLocalOneContext() - { + public String getLocalOneContext() { return this.localOneContext; } - public void setLocalOneContext(String value) - { + public void setLocalOneContext(String value) { this.localOneContext = value; } - public String getLocalOneExten() - { + public String getLocalOneExten() { return this.localOneExten; } - public void setLocalOneExten(String value) - { + public void setLocalOneExten(String value) { this.localOneExten = value; } - public Integer getLocalOnePriority() - { + public Integer getLocalOnePriority() { return this.localOnePriority; } - public void setLocalOnePriority(Integer value) - { + public void setLocalOnePriority(Integer value) { this.localOnePriority = value; } - public String getLocalOneUniqueid() - { + public String getLocalOneUniqueid() { return this.localOneUniqueid; } - public void setLocalOneUniqueid(String value) - { + public void setLocalOneUniqueid(String value) { this.localOneUniqueid = value; } - public String getLocalOneLinkedid() - { + public String getLocalOneLinkedid() { return this.localOneLinkedid; } - public void setLocalOneLinkedid(String value) - { + public void setLocalOneLinkedid(String value) { this.localOneLinkedid = value; } - public String getLocalTwoChannel() - { + public String getLocalTwoChannel() { return this.localTwoChannel; } - public void setLocalTwoChannel(String value) - { + public void setLocalTwoChannel(String value) { this.localTwoChannel = value; } - public String getLocalTwoChannelState() - { + public String getLocalTwoChannelState() { return this.localTwoChannelState; } - public void setLocalTwoChannelState(String value) - { + public void setLocalTwoChannelState(String value) { this.localTwoChannelState = value; } - public String getLocalTwoChannelStateDesc() - { + public String getLocalTwoChannelStateDesc() { return this.localTwoChannelStateDesc; } - public void setLocalTwoChannelStateDesc(String value) - { + public void setLocalTwoChannelStateDesc(String value) { this.localTwoChannelStateDesc = value; } - public String getLocalTwoCallerIDNum() - { + public String getLocalTwoCallerIDNum() { return this.localTwoCallerIDNum; } - public void setLocalTwoCallerIDNum(String value) - { + public void setLocalTwoCallerIDNum(String value) { this.localTwoCallerIDNum = value; } - public String getLocalTwoCallerIDName() - { + public String getLocalTwoCallerIDName() { return this.localTwoCallerIDName; } - public void setLocalTwoCallerIDName(String value) - { + public void setLocalTwoCallerIDName(String value) { this.localTwoCallerIDName = value; } - public String getLocalTwoConnectedLineNum() - { + public String getLocalTwoConnectedLineNum() { return this.localTwoConnectedLineNum; } - public void setLocalTwoConnectedLineNum(String value) - { + public void setLocalTwoConnectedLineNum(String value) { this.localTwoConnectedLineNum = value; } - public String getLocalTwoConnectedLineName() - { + public String getLocalTwoConnectedLineName() { return this.localTwoConnectedLineName; } - public void setLocalTwoConnectedLineName(String value) - { + public void setLocalTwoConnectedLineName(String value) { this.localTwoConnectedLineName = value; } - public String getLocalTwoAccountCode() - { + public String getLocalTwoAccountCode() { return this.localTwoAccountCode; } - public void setLocalTwoAccountCode(String value) - { + public void setLocalTwoAccountCode(String value) { this.localTwoAccountCode = value; } - public String getLocalTwoContext() - { + public String getLocalTwoContext() { return this.localTwoContext; } - public void setLocalTwoContext(String value) - { + public void setLocalTwoContext(String value) { this.localTwoContext = value; } - public String getLocalTwoExten() - { + public String getLocalTwoExten() { return this.localTwoExten; } - public void setLocalTwoExten(String value) - { + public void setLocalTwoExten(String value) { this.localTwoExten = value; } - public Integer getLocalTwoPriority() - { + public Integer getLocalTwoPriority() { return this.localTwoPriority; } - public void setLocalTwoPriority(Integer value) - { + public void setLocalTwoPriority(Integer value) { this.localTwoPriority = value; } - public String getLocalTwoUniqueid() - { + public String getLocalTwoUniqueid() { return this.localTwoUniqueid; } - public void setLocalTwoUniqueid(String value) - { + public void setLocalTwoUniqueid(String value) { this.localTwoUniqueid = value; } - public String getLocalTwoLinkedid() - { + public String getLocalTwoLinkedid() { return this.localTwoLinkedid; } - public void setLocalTwoLinkedid(String value) - { + public void setLocalTwoLinkedid(String value) { this.localTwoLinkedid = value; } - public String getLocalTwoLanguage() - { + public String getLocalTwoLanguage() { return localTwoLanguage; } - public void setLocalTwoLanguage(String localTwoLanguage) - { + public void setLocalTwoLanguage(String localTwoLanguage) { this.localTwoLanguage = localTwoLanguage; } - public String getLocalOneLanguage() - { + public String getLocalOneLanguage() { return localOneLanguage; } - public void setLocalOneLanguage(String localOneLanguage) - { + public void setLocalOneLanguage(String localOneLanguage) { this.localOneLanguage = localOneLanguage; } diff --git a/src/main/java/org/asteriskjava/manager/event/LogChannelEvent.java b/src/main/java/org/asteriskjava/manager/event/LogChannelEvent.java index f2c3a7ad1..c3c924f94 100644 --- a/src/main/java/org/asteriskjava/manager/event/LogChannelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/LogChannelEvent.java @@ -20,13 +20,12 @@ * A LogChannelEvent is triggered when logging is turned on or off.

    * It is implemented in logger.c

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class LogChannelEvent extends ManagerEvent -{ +public class LogChannelEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -40,104 +39,90 @@ public class LogChannelEvent extends ManagerEvent /** * @param source */ - public LogChannelEvent(Object source) - { + public LogChannelEvent(Object source) { super(source); } /** * Returns the name of the log channel. - * + * * @return the name of the log channel. */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the log channel. - * + * * @param channel the name of the log channel. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns if logging has been enabled or disabled. - * + * * @return Boolean.TRUE if logging has been enabled, Boolean.FALSE if it has - * been disabled. + * been disabled. */ - public Boolean getEnabled() - { + public Boolean getEnabled() { return enabled; } /** * Sets if logging has been enabled or disabled. - * + * * @param enabled Boolean.TRUE if logging has been enabled, Boolean.FALSE if - * it has been disabled. + * it has been disabled. */ - public void setEnabled(Boolean enabled) - { + public void setEnabled(Boolean enabled) { this.enabled = enabled; } /** * Returns the reason code for disabling logging. - * + * * @return the reason code for disabling logging. */ - public Integer getReason() - { + public Integer getReason() { return reason; } /** * Returns the textual representation of the reason for disabling logging. - * + * * @return the textual representation of the reason for disabling logging. */ - public String getReasonTxt() - { + public String getReasonTxt() { return reasonTxt; } /** * Sets the reason for disabling logging. - * + * * @param s the reason in the form "%d - %s". */ - public void setReason(String s) - { + public void setReason(String s) { int spaceIdx; - if (s == null) - { + if (s == null) { return; } spaceIdx = s.indexOf(' '); - if (spaceIdx <= 0) - { + if (spaceIdx <= 0) { spaceIdx = s.length(); } - try - { + try { this.reason = Integer.valueOf(s.substring(0, spaceIdx)); - } - catch (NumberFormatException e) - { + } catch (NumberFormatException e) { return; } - if (s.length() > spaceIdx + 3) - { + if (s.length() > spaceIdx + 3) { this.reasonTxt = s.substring(spaceIdx + 3, s.length()); } } diff --git a/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java b/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java index 58e7f654b..13cce6f3d 100644 --- a/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java @@ -16,16 +16,12 @@ */ package org.asteriskjava.manager.event; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Date; -import java.util.EventObject; -import java.util.List; -import java.util.Map; - import org.asteriskjava.util.AstState; import org.asteriskjava.util.ReflectionUtil; +import java.lang.reflect.Method; +import java.util.*; + /** * Abstract base class for all Events that can be received from the Asterisk * server.
    @@ -37,8 +33,7 @@ * @author srt * @version $Id$ */ -public abstract class ManagerEvent extends EventObject -{ +public abstract class ManagerEvent extends EventObject { /** * Serializable version identifier. */ @@ -56,97 +51,79 @@ public abstract class ManagerEvent extends EventObject * Returns the Caller ID name of the caller's channel. * * @return the Caller ID name of the caller's channel or "unknown" if none - * has been set. + * has been set. * @since 0.2 */ - public String getCallerIdName() - { + public String getCallerIdName() { return callerIdName; } - public void setCallerIdName(String callerIdName) - { + public void setCallerIdName(String callerIdName) { this.callerIdName = callerIdName; } - public String getConnectedLineNum() - { + public String getConnectedLineNum() { return connectedLineNum; } - public void setConnectedLineNum(String connectedLineNum) - { + public void setConnectedLineNum(String connectedLineNum) { this.connectedLineNum = connectedLineNum; } - public String getConnectedLineName() - { + public String getConnectedLineName() { return connectedLineName; } - public void setConnectedLineName(String connectedLineName) - { + public void setConnectedLineName(String connectedLineName) { this.connectedLineName = connectedLineName; } - public Integer getPriority() - { + public Integer getPriority() { return priority; } - public void setPriority(Integer priority) - { + public void setPriority(Integer priority) { this.priority = priority; } - public Integer getChannelState() - { + public Integer getChannelState() { return channelState == null ? AstState.str2state(channelStateDesc) : channelState; } - public void setChannelState(Integer channelState) - { + public void setChannelState(Integer channelState) { this.channelState = channelState; } - public String getChannelStateDesc() - { + public String getChannelStateDesc() { return channelStateDesc; } - public void setChannelStateDesc(String channelStateDesc) - { + public void setChannelStateDesc(String channelStateDesc) { this.channelStateDesc = channelStateDesc; } - public String getExten() - { + public String getExten() { return exten; } - public void setExten(String exten) - { + public void setExten(String exten) { this.exten = exten; } - public String getCallerIdNum() - { + public String getCallerIdNum() { return callerIdNum; } - public void setCallerIdNum(String callerIdNum) - { + public void setCallerIdNum(String callerIdNum) { this.callerIdNum = callerIdNum; } - public String getContext() - { + public String getContext() { return context; } - public void setContext(String context) - { + public void setContext(String context) { this.context = context; } @@ -178,8 +155,7 @@ public void setContext(String context) private String func; private Integer sequenceNumber; - public ManagerEvent(Object source) - { + public ManagerEvent(Object source) { super(source); } @@ -191,16 +167,14 @@ public ManagerEvent(Object source) * (for example ConnectEvent and DisconnectEvent) may return * null. */ - public Date getDateReceived() - { + public Date getDateReceived() { return dateReceived; } /** * Sets the point in time this event was received from the asterisk server. */ - public void setDateReceived(Date dateReceived) - { + public void setDateReceived(Date dateReceived) { this.dateReceived = dateReceived; } @@ -212,8 +186,7 @@ public void setDateReceived(Date dateReceived) * * @since 0.2 */ - public String getPrivilege() - { + public String getPrivilege() { return privilege; } @@ -222,8 +195,7 @@ public String getPrivilege() * * @since 0.2 */ - public void setPrivilege(String privilege) - { + public void setPrivilege(String privilege) { this.privilege = privilege; } @@ -239,8 +211,7 @@ public void setPrivilege(String privilege) * @return the timestamp for this event. * @since 0.3 */ - public final Double getTimestamp() - { + public final Double getTimestamp() { return timestamp; } @@ -250,8 +221,7 @@ public final Double getTimestamp() * @param timestamp the timestamp to set. * @since 0.3 */ - public final void setTimestamp(Double timestamp) - { + public final void setTimestamp(Double timestamp) { this.timestamp = timestamp; } @@ -261,12 +231,11 @@ public final void setTimestamp(Double timestamp) * This property is only available when using to AstManProxy. * * @return the name of the Asterisk server from which this event has been - * received or null when directly connected to an - * Asterisk server instead of AstManProxy. + * received or null when directly connected to an + * Asterisk server instead of AstManProxy. * @since 1.0.0 */ - public final String getServer() - { + public final String getServer() { return server; } @@ -275,21 +244,18 @@ public final String getServer() * received. * * @param server the name of the Asterisk server from which this event has - * been received. + * been received. * @since 1.0.0 */ - public final void setServer(String server) - { + public final void setServer(String server) { this.server = server; } - public String getSystemName() - { + public String getSystemName() { return systemName; } - public void setSystemName(String systemName) - { + public void setSystemName(String systemName) { this.systemName = systemName; } @@ -304,18 +270,16 @@ public void setSystemName(String systemName) * This feature is availble in Asterisk since 1.6.0. * * @return the name of the file in that triggered this event or - * null if debgging is turned off. + * null if debgging is turned off. * @see #getFunc() * @see #getLine() * @since 1.0.0 */ - public String getFile() - { + public String getFile() { return file; } - public void setFile(String file) - { + public void setFile(String file) { this.file = file; } @@ -330,18 +294,16 @@ public void setFile(String file) * This feature is availble in Asterisk since 1.6.0. * * @return the line number where this event was triggered or - * null if debgging is turned off. + * null if debgging is turned off. * @see #getFile() * @see #getFunc() * @since 1.0.0 */ - public Integer getLine() - { + public Integer getLine() { return line; } - public void setLine(Integer line) - { + public void setLine(Integer line) { this.line = line; } @@ -356,18 +318,16 @@ public void setLine(Integer line) * This feature is availble in Asterisk since 1.6.0. * * @return the name of the C function that triggered this event or - * null if debgging is turned off. + * null if debgging is turned off. * @see #getFile() * @see #getLine() * @since 1.0.0 */ - public String getFunc() - { + public String getFunc() { return func; } - public void setFunc(String func) - { + public void setFunc(String func) { this.func = func; } @@ -382,24 +342,21 @@ public void setFunc(String func) * This feature is availble in Asterisk since 1.6.0. * * @return the sequence number of this event or null if - * debgging is turned off. + * debgging is turned off. * @see #getFile() * @see #getLine() * @since 1.0.0 */ - public Integer getSequenceNumber() - { + public Integer getSequenceNumber() { return sequenceNumber; } - public void setSequenceNumber(Integer sequenceNumber) - { + public void setSequenceNumber(Integer sequenceNumber) { this.sequenceNumber = sequenceNumber; } @Override - public String toString() - { + public String toString() { final List ignoredProperties = Arrays.asList("file", "func", "line", "sequenceNumber", "datereceived", "privilege", "source", "class"); final StringBuilder sb = new StringBuilder(getClass().getName() + "["); @@ -411,20 +368,16 @@ public String toString() appendPropertyIfNotNull(sb, "privilege", getPrivilege()); final Map getters = ReflectionUtil.getGetters(getClass()); - for (Map.Entry entry : getters.entrySet()) - { + for (Map.Entry entry : getters.entrySet()) { final String property = entry.getKey(); - if (ignoredProperties.contains(property)) - { + if (ignoredProperties.contains(property)) { continue; } - try - { + try { final Object value = entry.getValue().invoke(this); appendProperty(sb, property, value); - } - catch (Exception e) // NOPMD + } catch (Exception e) // NOPMD { // swallow } @@ -435,23 +388,17 @@ public String toString() return sb.toString(); } - protected void appendPropertyIfNotNull(StringBuilder sb, String property, Object value) - { - if (value != null) - { + protected void appendPropertyIfNotNull(StringBuilder sb, String property, Object value) { + if (value != null) { appendProperty(sb, property, value); } } - private void appendProperty(StringBuilder sb, String property, Object value) - { + private void appendProperty(StringBuilder sb, String property, Object value) { sb.append(property).append("="); - if (value == null) - { + if (value == null) { sb.append("null"); - } - else - { + } else { sb.append("'").append(value).append("'"); } sb.append(","); diff --git a/src/main/java/org/asteriskjava/manager/event/MasqueradeEvent.java b/src/main/java/org/asteriskjava/manager/event/MasqueradeEvent.java index 264fcec49..1f2513daf 100644 --- a/src/main/java/org/asteriskjava/manager/event/MasqueradeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MasqueradeEvent.java @@ -27,8 +27,7 @@ * @version $Id$ * @since 1.0.0 */ -public class MasqueradeEvent extends ManagerEvent -{ +public class MasqueradeEvent extends ManagerEvent { static final long serialVersionUID = 1L; private String clone; @@ -36,8 +35,7 @@ public class MasqueradeEvent extends ManagerEvent private String original; private String originalStateDesc; - public MasqueradeEvent(Object source) - { + public MasqueradeEvent(Object source) { super(source); } @@ -46,13 +44,11 @@ public MasqueradeEvent(Object source) * * @return the name of the clone channel. */ - public String getClone() - { + public String getClone() { return clone; } - public void setClone(String clone) - { + public void setClone(String clone) { this.clone = clone; } @@ -62,8 +58,7 @@ public void setClone(String clone) * @return the state of the clone channel. * @see org.asteriskjava.util.AstState */ - public Integer getCloneState() - { + public Integer getCloneState() { return AstState.str2state(cloneStateDesc); } @@ -72,13 +67,11 @@ public Integer getCloneState() * * @return the state of the clone channel as a descriptive text. */ - public String getCloneStateDesc() - { + public String getCloneStateDesc() { return cloneStateDesc; } - public void setCloneState(String cloneState) - { + public void setCloneState(String cloneState) { this.cloneStateDesc = cloneState; } @@ -87,13 +80,11 @@ public void setCloneState(String cloneState) * * @return the name of the original channel. */ - public String getOriginal() - { + public String getOriginal() { return original; } - public void setOriginal(String original) - { + public void setOriginal(String original) { this.original = original; } @@ -103,8 +94,7 @@ public void setOriginal(String original) * @return the state of the original channel. * @see org.asteriskjava.util.AstState */ - public Integer getOriginalState() - { + public Integer getOriginalState() { return AstState.str2state(originalStateDesc); } @@ -113,13 +103,11 @@ public Integer getOriginalState() * * @return the state of the original channel as a descriptive text. */ - public String getOriginalStateDesc() - { + public String getOriginalStateDesc() { return originalStateDesc; } - public void setOriginalState(String originalState) - { + public void setOriginalState(String originalState) { this.originalStateDesc = originalState; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeEndEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeEndEvent.java index a305b4f7c..aefb5819f 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeEndEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeEndEvent.java @@ -25,16 +25,14 @@ * @version $Id$ * @since 1.0.0 */ -public class MeetMeEndEvent extends ManagerEvent -{ +public class MeetMeEndEvent extends ManagerEvent { private static final long serialVersionUID = 510266716726148586L; private String meetMe; /** * @param source */ - public MeetMeEndEvent(Object source) - { + public MeetMeEndEvent(Object source) { super(source); } @@ -43,13 +41,11 @@ public MeetMeEndEvent(Object source) * * @return the conference number. */ - public String getMeetMe() - { + public String getMeetMe() { return meetMe; } - public void setMeetMe(String meetMe) - { + public void setMeetMe(String meetMe) { this.meetMe = meetMe; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeJoinEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeJoinEvent.java index 5b7f16815..360b4dd74 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeJoinEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeJoinEvent.java @@ -27,8 +27,7 @@ * @author srt * @version $Id$ */ -public class MeetMeJoinEvent extends AbstractMeetMeEvent -{ +public class MeetMeJoinEvent extends AbstractMeetMeEvent { /** * Serializable version identifier. */ @@ -37,8 +36,7 @@ public class MeetMeJoinEvent extends AbstractMeetMeEvent /** * @param source */ - public MeetMeJoinEvent(Object source) - { + public MeetMeJoinEvent(Object source) { super(source); } } diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeLeaveEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeLeaveEvent.java index 517a21cb1..aa6aa748d 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeLeaveEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeLeaveEvent.java @@ -23,12 +23,11 @@ * 1.0. *

    * It is implemented in apps/app_meetme.c - * + * * @author srt * @version $Id$ */ -public class MeetMeLeaveEvent extends AbstractMeetMeEvent -{ +public class MeetMeLeaveEvent extends AbstractMeetMeEvent { /** * Serializable version identifier. */ @@ -39,8 +38,7 @@ public class MeetMeLeaveEvent extends AbstractMeetMeEvent /** * @param source */ - public MeetMeLeaveEvent(Object source) - { + public MeetMeLeaveEvent(Object source) { super(source); } @@ -48,21 +46,19 @@ public MeetMeLeaveEvent(Object source) * Returns how long the user spent in the conference. *

    * This property is available since Asterisk 1.4. - * + * * @return the duration in seconds the user spent in the conference. */ - public Long getDuration() - { + public Long getDuration() { return duration; } /** * Sets how long the user spent in the conference. - * + * * @param duration the duration in seconds the user spent in the conference. */ - public void setDuration(Long duration) - { + public void setDuration(Long duration) { this.duration = duration; } } diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeMuteEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeMuteEvent.java index 9c723b45f..bb14c8242 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeMuteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeMuteEvent.java @@ -21,12 +21,11 @@ * unmuted.

    * It is implemented in apps/app_meetme.c

    * Available since Asterisk 1.4. - * + * * @author srt * @version $Id$ */ -public class MeetMeMuteEvent extends AbstractMeetMeEvent -{ +public class MeetMeMuteEvent extends AbstractMeetMeEvent { /** * Serializable version identifier. */ @@ -37,30 +36,27 @@ public class MeetMeMuteEvent extends AbstractMeetMeEvent /** * @param source */ - public MeetMeMuteEvent(Object source) - { + public MeetMeMuteEvent(Object source) { super(source); } /** * Returns whether the user was muted or unmuted. - * + * * @return true if ther user was muted, - * false if the user was unmuted. + * false if the user was unmuted. */ - public Boolean getStatus() - { + public Boolean getStatus() { return status; } /** * Sets whether the user was muted or unmuted. - * - * @param status true if ther user was muted, + * + * @param status true if ther user was muted, * false if the user was unmuted. */ - public void setStatus(Boolean status) - { + public void setStatus(Boolean status) { this.status = status; } } diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeStopTalkingEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeStopTalkingEvent.java index 448b30622..11b08d74e 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeStopTalkingEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeStopTalkingEvent.java @@ -30,17 +30,16 @@ * @see org.asteriskjava.manager.event.MeetMeTalkingEvent * @since 0.2 * @deprecated as of 1.0.0, use {@link org.asteriskjava.manager.event.MeetMeTalkingEvent} instead and check for - * {@link MeetMeTalkingEvent#getStatus()}. + * {@link MeetMeTalkingEvent#getStatus()}. */ -@Deprecated public class MeetMeStopTalkingEvent extends MeetMeTalkingEvent -{ +@Deprecated +public class MeetMeStopTalkingEvent extends MeetMeTalkingEvent { /** * Serializable version identifier. */ private static final long serialVersionUID = 1L; - public MeetMeStopTalkingEvent(Object source) - { + public MeetMeStopTalkingEvent(Object source) { super(source); this.status = Boolean.FALSE; } diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingEvent.java index e6080190d..d37dafcd9 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingEvent.java @@ -22,14 +22,13 @@ * To enable talker detection you must pass the option 'T' to the MeetMe application.

    * It is implemented in apps/app_meetme.c

    * Available since Asterisk 1.2 - * - * @see org.asteriskjava.manager.event.MeetMeStopTalkingEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.MeetMeStopTalkingEvent * @since 0.2 */ -public class MeetMeTalkingEvent extends AbstractMeetMeEvent -{ +public class MeetMeTalkingEvent extends AbstractMeetMeEvent { /** * Serializable version identifier. */ @@ -37,8 +36,7 @@ public class MeetMeTalkingEvent extends AbstractMeetMeEvent protected Boolean status = Boolean.TRUE; - public MeetMeTalkingEvent(Object source) - { + public MeetMeTalkingEvent(Object source) { super(source); } @@ -51,18 +49,16 @@ public MeetMeTalkingEvent(Object source) * start and stop. For backwards compatibility this property defaults to * true so when used with version 1.2 of Asterisk you get * true. - * + * * @return true if ther user has started talking, - * false if the user has stopped talking. + * false if the user has stopped talking. * @since 0.3 */ - public Boolean getStatus() - { + public Boolean getStatus() { return status; } - public void setStatus(Boolean status) - { + public void setStatus(Boolean status) { this.status = status; } } diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java index 4a968b3d2..ea1ad63ed 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java @@ -27,8 +27,7 @@ * @version $Id$ * @since 1.0.0 */ -public class MeetMeTalkingRequestEvent extends AbstractMeetMeEvent -{ +public class MeetMeTalkingRequestEvent extends AbstractMeetMeEvent { /** * Serializable version identifier. */ @@ -39,8 +38,7 @@ public class MeetMeTalkingRequestEvent extends AbstractMeetMeEvent /** * @param source */ - public MeetMeTalkingRequestEvent(Object source) - { + public MeetMeTalkingRequestEvent(Object source) { super(source); } @@ -50,15 +48,13 @@ public MeetMeTalkingRequestEvent(Object source) * Returns whether the user has started or stopped requesting talking. * * @return true if ther user has started requesting talking, - * false if the user has stopped requesting talking. + * false if the user has stopped requesting talking. */ - public Boolean getStatus() - { + public Boolean getStatus() { return status; } - public void setStatus(Boolean status) - { + public void setStatus(Boolean status) { this.status = status; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/MessageWaitingEvent.java b/src/main/java/org/asteriskjava/manager/event/MessageWaitingEvent.java index 2e8910722..f2a9bb532 100644 --- a/src/main/java/org/asteriskjava/manager/event/MessageWaitingEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MessageWaitingEvent.java @@ -19,12 +19,11 @@ /** * A MessageWaitingEvent is triggered when someone leaves voicemail.

    * It is implemented in apps/app_voicemail.c - * + * * @author srt * @version $Id$ */ -public class MessageWaitingEvent extends ManagerEvent -{ +public class MessageWaitingEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -37,8 +36,7 @@ public class MessageWaitingEvent extends ManagerEvent /** * @param source */ - public MessageWaitingEvent(Object source) - { + public MessageWaitingEvent(Object source) { super(source); } @@ -46,81 +44,77 @@ public MessageWaitingEvent(Object source) * Returns the name of the mailbox that has waiting messages.

    * The name of the mailbox is of the form numberOfMailbox@context, e.g. * 1234@default. - * + * * @return the name of the mailbox that has waiting messages */ - public String getMailbox() - { + public String getMailbox() { return mailbox; } /** * Sets the name of the mailbox that has waiting messages. - * + * * @param mailbox the name of the mailbox that has waiting messages */ - public void setMailbox(String mailbox) - { + public void setMailbox(String mailbox) { this.mailbox = mailbox; } /** * Returns the number of new messages in the mailbox. - * + * * @return the number of new messages in the mailbox */ - public Integer getWaiting() - { + public Integer getWaiting() { return waiting; } /** * Sets the number of new messages in the mailbox. - * + * * @param waiting the number of new messages in the mailbox */ - public void setWaiting(Integer waiting) - { + public void setWaiting(Integer waiting) { this.waiting = waiting; } /** * Returns the number of new messages in this mailbox. + * * @return the number of new messages in this mailbox. * @since 0.2 */ - public Integer getNew() - { + public Integer getNew() { return newMessages; } /** * Sets the number of new messages in this mailbox. + * * @param newMessages the number of new messages in this mailbox. * @since 0.2 */ - public void setNew(Integer newMessages) - { + public void setNew(Integer newMessages) { this.newMessages = newMessages; } /** * Returns the number of old messages in this mailbox. + * * @return the number of old messages in this mailbox. * @since 0.2 */ - public Integer getOld() - { + public Integer getOld() { return oldMessages; } /** * Sets the number of old messages in this mailbox. + * * @param oldMessages the number of old messages in this mailbox. * @since 0.2 */ - public void setOld(Integer oldMessages) - { + public void setOld(Integer oldMessages) { this.oldMessages = oldMessages; } } diff --git a/src/main/java/org/asteriskjava/manager/event/MixMonitorStartEvent.java b/src/main/java/org/asteriskjava/manager/event/MixMonitorStartEvent.java index dab79b443..10129d513 100644 --- a/src/main/java/org/asteriskjava/manager/event/MixMonitorStartEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MixMonitorStartEvent.java @@ -3,15 +3,13 @@ /** * A MixMonitorStartEvent indicates that monitoring was started on a channel.

    * - * @since 3.13.0 * @see org.asteriskjava.manager.event.MixMonitorStopEvent + * @since 3.13.0 */ -public class MixMonitorStartEvent extends AbstractMixMonitorEvent -{ - private static final long serialVersionUID = 1L; +public class MixMonitorStartEvent extends AbstractMixMonitorEvent { + private static final long serialVersionUID = 1L; - public MixMonitorStartEvent(Object source) - { - super(source); - } + public MixMonitorStartEvent(Object source) { + super(source); + } } diff --git a/src/main/java/org/asteriskjava/manager/event/MixMonitorStopEvent.java b/src/main/java/org/asteriskjava/manager/event/MixMonitorStopEvent.java index 54f59b072..8a138390a 100644 --- a/src/main/java/org/asteriskjava/manager/event/MixMonitorStopEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MixMonitorStopEvent.java @@ -3,15 +3,13 @@ /** * A MixMonitorStopEvent indicates that monitoring was stopped on a channel.

    * - * @since 3.13.0 * @see org.asteriskjava.manager.event.MixMonitorStartEvent + * @since 3.13.0 */ -public class MixMonitorStopEvent extends AbstractMixMonitorEvent -{ - private static final long serialVersionUID = 1L; +public class MixMonitorStopEvent extends AbstractMixMonitorEvent { + private static final long serialVersionUID = 1L; - public MixMonitorStopEvent(Object source) - { - super(source); - } + public MixMonitorStopEvent(Object source) { + super(source); + } } diff --git a/src/main/java/org/asteriskjava/manager/event/ModuleLoadReportEvent.java b/src/main/java/org/asteriskjava/manager/event/ModuleLoadReportEvent.java index 9dfe7e87b..0ec7547ce 100644 --- a/src/main/java/org/asteriskjava/manager/event/ModuleLoadReportEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ModuleLoadReportEvent.java @@ -24,8 +24,7 @@ * @version $Id$ * @since 1.0.0 */ -public class ModuleLoadReportEvent extends ManagerEvent -{ +public class ModuleLoadReportEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -40,8 +39,7 @@ public class ModuleLoadReportEvent extends ManagerEvent private String moduleSelection; private Integer moduleCount; - public ModuleLoadReportEvent(Object source) - { + public ModuleLoadReportEvent(Object source) { super(source); } @@ -51,41 +49,35 @@ public ModuleLoadReportEvent(Object source) * @return the load status. * @see #MODULE_LOAD_STATUS_DONE */ - public String getModuleLoadStatus() - { + public String getModuleLoadStatus() { return moduleLoadStatus; } - public void setModuleLoadStatus(String moduleLoadStatus) - { + public void setModuleLoadStatus(String moduleLoadStatus) { this.moduleLoadStatus = moduleLoadStatus; } /** * Returns whether loading the pre-load modules has been completed or all modules - * have been loaded. + * have been loaded. * * @return "Preload" or "All" * @see #MODULE_SELECTION_PRELOAD * @see #MODULE_SELECTION_ALL */ - public String getModuleSelection() - { + public String getModuleSelection() { return moduleSelection; } - public boolean isPreload() - { + public boolean isPreload() { return MODULE_SELECTION_PRELOAD.equals(moduleSelection); } - public boolean isAll() - { + public boolean isAll() { return MODULE_SELECTION_ALL.equals(moduleSelection); } - public void setModuleSelection(String moduleSelection) - { + public void setModuleSelection(String moduleSelection) { this.moduleSelection = moduleSelection; } @@ -94,13 +86,11 @@ public void setModuleSelection(String moduleSelection) * * @return the number of modules that have been loaded. */ - public Integer getModuleCount() - { + public Integer getModuleCount() { return moduleCount; } - public void setModuleCount(Integer moduleCount) - { + public void setModuleCount(Integer moduleCount) { this.moduleCount = moduleCount; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/MonitorStartEvent.java b/src/main/java/org/asteriskjava/manager/event/MonitorStartEvent.java index 60ca3aefe..79a9261fd 100644 --- a/src/main/java/org/asteriskjava/manager/event/MonitorStartEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MonitorStartEvent.java @@ -23,14 +23,13 @@ * * @author srt * @version $Id$ - * @since 1.0.0 * @see org.asteriskjava.manager.event.MonitorStopEvent + * @since 1.0.0 */ -public class MonitorStartEvent extends AbstractMonitorEvent -{ +public class MonitorStartEvent extends AbstractMonitorEvent { private static final long serialVersionUID = 253533286571341499L; - public MonitorStartEvent(Object source) - { + + public MonitorStartEvent(Object source) { super(source); } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/MonitorStopEvent.java b/src/main/java/org/asteriskjava/manager/event/MonitorStopEvent.java index 61cbfd846..ca6ec377a 100644 --- a/src/main/java/org/asteriskjava/manager/event/MonitorStopEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MonitorStopEvent.java @@ -23,14 +23,13 @@ * * @author srt * @version $Id$ - * @since 1.0.0 * @see org.asteriskjava.manager.event.MonitorStartEvent + * @since 1.0.0 */ -public class MonitorStopEvent extends AbstractMonitorEvent -{ +public class MonitorStopEvent extends AbstractMonitorEvent { private static final long serialVersionUID = -2605389608972504362L; - public MonitorStopEvent(Object source) - { + + public MonitorStopEvent(Object source) { super(source); } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/MusicOnHoldEvent.java b/src/main/java/org/asteriskjava/manager/event/MusicOnHoldEvent.java index a4ac71629..ffeb20d57 100644 --- a/src/main/java/org/asteriskjava/manager/event/MusicOnHoldEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MusicOnHoldEvent.java @@ -27,8 +27,7 @@ * @author srt * @since 1.0.0 */ -public class MusicOnHoldEvent extends ManagerEvent -{ +public class MusicOnHoldEvent extends ManagerEvent { private static final long serialVersionUID = 1L; public static final String STATE_START = "Start"; @@ -42,8 +41,7 @@ public class MusicOnHoldEvent extends ManagerEvent private String linkedId; private String language; - public MusicOnHoldEvent(Object source) - { + public MusicOnHoldEvent(Object source) { super(source); } @@ -52,8 +50,7 @@ public MusicOnHoldEvent(Object source) * * @return channel the name of the channel. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -62,18 +59,15 @@ public String getChannel() * * @param channel the name of the channel. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } - public String getClassName() - { + public String getClassName() { return this.className; } - public void setClazz(String className) - { + public void setClazz(String className) { this.className = className; } @@ -82,8 +76,7 @@ public void setClazz(String className) * * @return the unique id of the channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } @@ -92,8 +85,7 @@ public String getUniqueId() * * @param uniqueId the unique id of the channel. */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -102,19 +94,17 @@ public void setUniqueId(String uniqueId) * music on hold started or stopped on the channel. * * @return "Start" if music on hold started or "Stop" if music on hold - * stopped on the channel. + * stopped on the channel. * @see #STATE_START * @see #STATE_STOP * @see #isStart() * @see #isStop() */ - public String getState() - { + public String getState() { return state; } - public void setState(String state) - { + public void setState(String state) { this.state = state; } @@ -122,10 +112,9 @@ public void setState(String state) * Returns whether this is a start event. * * @return true if this a start event, false - * otherwise. + * otherwise. */ - public boolean isStart() - { + public boolean isStart() { return STATE_START.equals(state); } @@ -133,41 +122,34 @@ public boolean isStart() * Returns whether this is a stop event. * * @return true if this an stop event, false - * otherwise. + * otherwise. */ - public boolean isStop() - { + public boolean isStop() { return STATE_STOP.equals(state); } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - - public String getLinkedId() - { + + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - + } diff --git a/src/main/java/org/asteriskjava/manager/event/MusicOnHoldStartEvent.java b/src/main/java/org/asteriskjava/manager/event/MusicOnHoldStartEvent.java index 68e0e002a..82d88f2b2 100644 --- a/src/main/java/org/asteriskjava/manager/event/MusicOnHoldStartEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MusicOnHoldStartEvent.java @@ -3,16 +3,14 @@ /** * Created by Alexander Polakov on 1/26/15. */ -public class MusicOnHoldStartEvent extends MusicOnHoldEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; +public class MusicOnHoldStartEvent extends MusicOnHoldEvent { + /** + * + */ + private static final long serialVersionUID = 1L; - public MusicOnHoldStartEvent(Object source) - { - super(source); - setState(STATE_START); - } + public MusicOnHoldStartEvent(Object source) { + super(source); + setState(STATE_START); + } } diff --git a/src/main/java/org/asteriskjava/manager/event/MusicOnHoldStopEvent.java b/src/main/java/org/asteriskjava/manager/event/MusicOnHoldStopEvent.java index f25f9d4a5..fd49673ba 100644 --- a/src/main/java/org/asteriskjava/manager/event/MusicOnHoldStopEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MusicOnHoldStopEvent.java @@ -3,16 +3,14 @@ /** * Created by Alexander Polakov on 1/26/15. */ -public class MusicOnHoldStopEvent extends MusicOnHoldEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; +public class MusicOnHoldStopEvent extends MusicOnHoldEvent { + /** + * + */ + private static final long serialVersionUID = 1L; - public MusicOnHoldStopEvent(Object source) - { - super(source); - setState(STATE_STOP); - } + public MusicOnHoldStopEvent(Object source) { + super(source); + setState(STATE_STOP); + } } diff --git a/src/main/java/org/asteriskjava/manager/event/NewAccountCodeEvent.java b/src/main/java/org/asteriskjava/manager/event/NewAccountCodeEvent.java index cb6e80aee..58d6fb41f 100644 --- a/src/main/java/org/asteriskjava/manager/event/NewAccountCodeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/NewAccountCodeEvent.java @@ -26,8 +26,7 @@ * @version $Id$ * @since 1.0.0 */ -public class NewAccountCodeEvent extends ManagerEvent -{ +public class NewAccountCodeEvent extends ManagerEvent { private static final long serialVersionUID = -1786512014173534223L; private String channel; private String uniqueId; @@ -39,8 +38,7 @@ public class NewAccountCodeEvent extends ManagerEvent /** * @param source */ - public NewAccountCodeEvent(Object source) - { + public NewAccountCodeEvent(Object source) { super(source); } @@ -49,13 +47,11 @@ public NewAccountCodeEvent(Object source) * * @return the name of the channel. */ - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -64,13 +60,11 @@ public void setChannel(String channel) * * @return the unique id of the channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -79,13 +73,11 @@ public void setUniqueId(String uniqueId) * * @return the new account code. */ - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } @@ -94,35 +86,29 @@ public void setAccountCode(String accountCode) * * @return the old account code. */ - public String getOldAccountCode() - { + public String getOldAccountCode() { return oldAccountCode; } - public void setOldAccountCode(String oldAccountCode) - { + public void setOldAccountCode(String oldAccountCode) { this.oldAccountCode = oldAccountCode; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - - -} \ No newline at end of file + + +} diff --git a/src/main/java/org/asteriskjava/manager/event/NewCallerIdEvent.java b/src/main/java/org/asteriskjava/manager/event/NewCallerIdEvent.java index a840dce92..e7e8a3a08 100644 --- a/src/main/java/org/asteriskjava/manager/event/NewCallerIdEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/NewCallerIdEvent.java @@ -20,12 +20,11 @@ /** * A NewCallerIdEvent is triggered when the caller id of a channel changes.

    * It is implemented in channel.c - * + * * @author srt * @version $Id$ */ -public class NewCallerIdEvent extends AbstractChannelEvent -{ +public class NewCallerIdEvent extends AbstractChannelEvent { /** * Serializable version identifier. */ @@ -39,86 +38,72 @@ public class NewCallerIdEvent extends AbstractChannelEvent private String language; private String linkedId; - public NewCallerIdEvent(Object source) - { + public NewCallerIdEvent(Object source) { super(source); } - public String getLanguage() - { - return language; + public String getLanguage() { + return language; } - - public void setLanguage(String language) - { - this.language = language; + + public void setLanguage(String language) { + this.language = language; } - + /** * Returns the CallerId presentation/screening. - * + * * @return the CallerId presentation/screening. * @since 0.2 */ - public Integer getCidCallingPres() - { + public Integer getCidCallingPres() { return cidCallingPres; } /** * Returns the textual respresentation of the CallerId presentation/screening. - * + * * @return the textual respresentation of the CallerId presentation/screening. * @since 0.2 */ - public String getCidCallingPresTxt() - { + public String getCidCallingPresTxt() { return cidCallingPresTxt; } /** * Sets the CallerId presentation/screening in the form "%d (%s)". - * + * * @param s the CallerId presentation/screening in the form "%d (%s)". * @since 0.2 */ - public void setCidCallingPres(String s) - { + public void setCidCallingPres(String s) { int spaceIdx; - if (s == null) - { + if (s == null) { return; } spaceIdx = s.indexOf(' '); - if (spaceIdx <= 0) - { + if (spaceIdx <= 0) { spaceIdx = s.length(); } - try - { + try { this.cidCallingPres = Integer.valueOf(s.substring(0, spaceIdx)); - } - catch (NumberFormatException e) - { + } catch (NumberFormatException e) { return; } - if (s.length() > spaceIdx + 3) - { + if (s.length() > spaceIdx + 3) { this.cidCallingPresTxt = s.substring(spaceIdx + 2, s.length() - 1); } } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } } diff --git a/src/main/java/org/asteriskjava/manager/event/NewChannelEvent.java b/src/main/java/org/asteriskjava/manager/event/NewChannelEvent.java index e731dbdaf..b57e74e17 100644 --- a/src/main/java/org/asteriskjava/manager/event/NewChannelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/NewChannelEvent.java @@ -24,8 +24,7 @@ * @author srt * @version $Id$ */ -public class NewChannelEvent extends AbstractChannelStateEvent -{ +public class NewChannelEvent extends AbstractChannelStateEvent { /** * Serializable version identifier. */ @@ -33,30 +32,25 @@ public class NewChannelEvent extends AbstractChannelStateEvent private String language; private String linkedid; - public NewChannelEvent(Object source) - { + public NewChannelEvent(Object source) { super(source); } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getLinkedid() - { + public String getLinkedid() { return linkedid; } - public void setLinkedid(String linkedid) - { + public void setLinkedid(String linkedid) { this.linkedid = linkedid; } - - + + } diff --git a/src/main/java/org/asteriskjava/manager/event/NewConnectedLineEvent.java b/src/main/java/org/asteriskjava/manager/event/NewConnectedLineEvent.java index 4274e2d33..c145f5c76 100644 --- a/src/main/java/org/asteriskjava/manager/event/NewConnectedLineEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/NewConnectedLineEvent.java @@ -3,10 +3,9 @@ /** * Created by plhk on 1/15/15. */ -public class NewConnectedLineEvent extends ManagerEvent -{ +public class NewConnectedLineEvent extends ManagerEvent { /** - * + * */ private static final long serialVersionUID = 1L; private String channel; @@ -15,60 +14,49 @@ public class NewConnectedLineEvent extends ManagerEvent private String accountCode; private String linkedId; - public NewConnectedLineEvent(Object source) - { + public NewConnectedLineEvent(Object source) { super(source); } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - + } diff --git a/src/main/java/org/asteriskjava/manager/event/NewExtenEvent.java b/src/main/java/org/asteriskjava/manager/event/NewExtenEvent.java index 9997b9152..ddf71a982 100644 --- a/src/main/java/org/asteriskjava/manager/event/NewExtenEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/NewExtenEvent.java @@ -20,12 +20,11 @@ * A NewExtenEvent is triggered when a channel is connected to a new extension. *

    * It is implemented in pbx.c - * + * * @author srt * @version $Id$ */ -public class NewExtenEvent extends ManagerEvent -{ +public class NewExtenEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -43,50 +42,43 @@ public class NewExtenEvent extends ManagerEvent /** * @param source */ - public NewExtenEvent(Object source) - { + public NewExtenEvent(Object source) { super(source); } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } /** * Returns the unique id of the channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } /** * Sets the unique id of the channel. */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } /** * Returns the name of the application that is executed. */ - public String getApplication() - { + public String getApplication() { return application; } /** * Sets the name of the application that is executed. */ - public void setApplication(String application) - { + public void setApplication(String application) { this.application = application; } @@ -94,69 +86,59 @@ public void setApplication(String application) * Returns the parameters passed to the application that is executed. The * parameters are separated by a '|' character. */ - public String getAppData() - { + public String getAppData() { return appData; } /** * Sets the parameters passed to the application that is executed. */ - public void setAppData(String appData) - { + public void setAppData(String appData) { this.appData = appData; } /** * Returns the name of the channel. */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the extension. */ - public String getExtension() - { + public String getExtension() { return extension; } /** * Sets the extension. */ - public void setExtension(String extension) - { + public void setExtension(String extension) { this.extension = extension; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - + } diff --git a/src/main/java/org/asteriskjava/manager/event/NewStateEvent.java b/src/main/java/org/asteriskjava/manager/event/NewStateEvent.java index 275146b31..b6f71f738 100644 --- a/src/main/java/org/asteriskjava/manager/event/NewStateEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/NewStateEvent.java @@ -19,12 +19,11 @@ /** * A NewStateEvent is triggered when the state of a channel has changed.

    * It is implemented in channel.c - * + * * @author srt * @version $Id$ */ -public class NewStateEvent extends AbstractChannelStateEvent -{ +public class NewStateEvent extends AbstractChannelStateEvent { /** * Serializable version identifier. */ @@ -32,28 +31,23 @@ public class NewStateEvent extends AbstractChannelStateEvent private String language; private String linkedId; - public NewStateEvent(Object source) - { + public NewStateEvent(Object source) { super(source); } - - public String getLanguage() - { - return language; + + public String getLanguage() { + return language; } - - public void setLanguage(String language) - { - this.language = language; + + public void setLanguage(String language) { + this.language = language; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } } diff --git a/src/main/java/org/asteriskjava/manager/event/OriginateFailureEvent.java b/src/main/java/org/asteriskjava/manager/event/OriginateFailureEvent.java index f18af74c5..57cb93493 100644 --- a/src/main/java/org/asteriskjava/manager/event/OriginateFailureEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/OriginateFailureEvent.java @@ -20,15 +20,15 @@ * An OriginateFailureEvent is triggered when the execution of an * OriginateAction failed.

    * Deprecated since Asterisk 1.4. - * + * + * @author srt + * @version $Id$ * @see org.asteriskjava.manager.action.OriginateAction * @see OriginateResponseEvent * @deprecated - * @author srt - * @version $Id$ */ -@Deprecated public class OriginateFailureEvent extends OriginateResponseEvent -{ +@Deprecated +public class OriginateFailureEvent extends OriginateResponseEvent { /** * Serializable version identifier */ @@ -37,8 +37,7 @@ /** * @param source */ - public OriginateFailureEvent(Object source) - { + public OriginateFailureEvent(Object source) { super(source); setResponse("Failure"); } diff --git a/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java b/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java index 33ce8cb00..93bf466ee 100644 --- a/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/OriginateResponseEvent.java @@ -18,13 +18,12 @@ /** * Response to an OriginateAction. - * - * @see org.asteriskjava.manager.action.OriginateAction + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.OriginateAction */ -public class OriginateResponseEvent extends ResponseEvent -{ +public class OriginateResponseEvent extends ResponseEvent { /** * Serial version identifier. */ @@ -39,104 +38,88 @@ public class OriginateResponseEvent extends ResponseEvent /** * @param source */ - public OriginateResponseEvent(Object source) - { + public OriginateResponseEvent(Object source) { super(source); } /** * Returns the result of the corresponding Originate action. - * + * * @return "Success" or "Failure" */ - public String getResponse() - { + public String getResponse() { return response; } /** * Sets the result of the corresponding Originate action. - * + * * @param response "Success" or "Failure" */ - public void setResponse(String response) - { + public void setResponse(String response) { this.response = response; } - - public boolean isSuccess() - { + + public boolean isSuccess() { return "Success".equalsIgnoreCase(response); } /** * Returns the name of the channel to connect to the outgoing call. */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel to connect to the outgoing call. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } - public Integer getReason() - { + public Integer getReason() { return reason; } - public void setReason(Integer reason) - { + public void setReason(Integer reason) { this.reason = reason; } /** * Returns the unique id of the originated channel. - * + * * @return the unique id of the originated channel or "<null>" if none - * is available. + * is available. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } // for backward compatibility only - public void setCallerId(String callerId) - { - if (getCallerIdNum() == null) - { + public void setCallerId(String callerId) { + if (getCallerIdNum() == null) { setCallerIdNum(callerId); } } - public String getData() - { + public String getData() { return data; } - public void setData(String data) - { + public void setData(String data) { this.data = data; } - public String getApplication() - { + public String getApplication() { return application; } - public void setApplication(String application) - { + public void setApplication(String application) { this.application = application; } } diff --git a/src/main/java/org/asteriskjava/manager/event/OriginateSuccessEvent.java b/src/main/java/org/asteriskjava/manager/event/OriginateSuccessEvent.java index d3f92c4aa..7bfea6206 100644 --- a/src/main/java/org/asteriskjava/manager/event/OriginateSuccessEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/OriginateSuccessEvent.java @@ -20,15 +20,15 @@ * An OriginateSuccessEvent is triggered when the execution of an * OriginateAction succeeded.

    * Deprecated since Asterisk 1.4. - * + * + * @author srt + * @version $Id$ * @see org.asteriskjava.manager.action.OriginateAction * @see OriginateResponseEvent * @deprecated - * @author srt - * @version $Id$ */ -@Deprecated public class OriginateSuccessEvent extends OriginateResponseEvent -{ +@Deprecated +public class OriginateSuccessEvent extends OriginateResponseEvent { /** * Serializable version identifier */ @@ -37,8 +37,7 @@ /** * @param source */ - public OriginateSuccessEvent(Object source) - { + public OriginateSuccessEvent(Object source) { super(source); setResponse("Success"); } diff --git a/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java b/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java index b8c681d08..aef32c1d1 100644 --- a/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ParkedCallEvent.java @@ -21,13 +21,12 @@ * action id is set) and in response to a ParkedCallsAction. *

    * It is implemented in res/res_features.c - * - * @see org.asteriskjava.manager.action.ParkedCallsAction + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.ParkedCallsAction */ -public class ParkedCallEvent extends AbstractParkedCallEvent -{ +public class ParkedCallEvent extends AbstractParkedCallEvent { /** * Serializable version identifier */ @@ -39,8 +38,7 @@ public class ParkedCallEvent extends AbstractParkedCallEvent /** * @param source */ - public ParkedCallEvent(Object source) - { + public ParkedCallEvent(Object source) { super(source); } @@ -50,16 +48,14 @@ public ParkedCallEvent(Object source) * This corresponds to the parkingtime option in * features.conf. */ - public Integer getTimeout() - { + public Integer getTimeout() { return timeout; } /** * Sets the number of seconds this call will be parked. */ - public void setTimeout(Integer timeout) - { + public void setTimeout(Integer timeout) { this.timeout = timeout; } @@ -67,24 +63,21 @@ public void setTimeout(Integer timeout) * Sets the unique id of the parked channel as a workaround for a typo in * asterisk manager event. */ - public void setUnqiueId(String unqiueId) - { + public void setUnqiueId(String unqiueId) { setUniqueId(unqiueId); } /** * @param parkeelinkedid the parkeelinkedid to set */ - public void setParkeelinkedid(String parkeelinkedid) - { + public void setParkeelinkedid(String parkeelinkedid) { this.parkeelinkedid = parkeelinkedid; } /** * @return the parkeelinkedid */ - public String getParkeelinkedid() - { + public String getParkeelinkedid() { return parkeelinkedid; } diff --git a/src/main/java/org/asteriskjava/manager/event/ParkedCallGiveUpEvent.java b/src/main/java/org/asteriskjava/manager/event/ParkedCallGiveUpEvent.java index 1c4a456e5..1d0e998ef 100644 --- a/src/main/java/org/asteriskjava/manager/event/ParkedCallGiveUpEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ParkedCallGiveUpEvent.java @@ -23,13 +23,12 @@ * It is implemented in res/res_features.c *

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class ParkedCallGiveUpEvent extends AbstractUnParkedEvent -{ +public class ParkedCallGiveUpEvent extends AbstractUnParkedEvent { /** * Serializable version identifier */ @@ -38,8 +37,7 @@ public class ParkedCallGiveUpEvent extends AbstractUnParkedEvent /** * @param source */ - public ParkedCallGiveUpEvent(Object source) - { + public ParkedCallGiveUpEvent(Object source) { super(source); } } diff --git a/src/main/java/org/asteriskjava/manager/event/ParkedCallTimeOutEvent.java b/src/main/java/org/asteriskjava/manager/event/ParkedCallTimeOutEvent.java index c258ba4af..644b6dd0f 100644 --- a/src/main/java/org/asteriskjava/manager/event/ParkedCallTimeOutEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ParkedCallTimeOutEvent.java @@ -23,13 +23,12 @@ * It is implemented in res/res_features.c *

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class ParkedCallTimeOutEvent extends AbstractUnParkedEvent -{ +public class ParkedCallTimeOutEvent extends AbstractUnParkedEvent { /** * Serializable version identifier */ @@ -38,8 +37,7 @@ public class ParkedCallTimeOutEvent extends AbstractUnParkedEvent /** * @param source */ - public ParkedCallTimeOutEvent(Object source) - { + public ParkedCallTimeOutEvent(Object source) { super(source); } } diff --git a/src/main/java/org/asteriskjava/manager/event/ParkedCallsCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/ParkedCallsCompleteEvent.java index 263df0c59..a00d9e10f 100644 --- a/src/main/java/org/asteriskjava/manager/event/ParkedCallsCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ParkedCallsCompleteEvent.java @@ -19,14 +19,13 @@ /** * A ParkedCallsCompleteEvent is triggered after all parked calls have been * reported in response to a ParkedCallsAction. - * - * @see org.asteriskjava.manager.action.ParkedCallsAction - * @see org.asteriskjava.manager.event.ParkedCallEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.ParkedCallsAction + * @see org.asteriskjava.manager.event.ParkedCallEvent */ -public class ParkedCallsCompleteEvent extends ResponseEvent -{ +public class ParkedCallsCompleteEvent extends ResponseEvent { /** * Serializable version identifier */ @@ -35,8 +34,7 @@ public class ParkedCallsCompleteEvent extends ResponseEvent /** * @param source */ - public ParkedCallsCompleteEvent(Object source) - { + public ParkedCallsCompleteEvent(Object source) { super(source); } } diff --git a/src/main/java/org/asteriskjava/manager/event/PausedEvent.java b/src/main/java/org/asteriskjava/manager/event/PausedEvent.java index efa0dbe83..b073f8a03 100644 --- a/src/main/java/org/asteriskjava/manager/event/PausedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PausedEvent.java @@ -2,34 +2,34 @@ public class PausedEvent extends UserEvent { - public PausedEvent(Object source) { - super(source); - } - - /** - * - */ - private static final long serialVersionUID = 7181269530090027203L; - - private String header; - - private String extension; - - public String getHeader() { - return header; - } - - public void setHeader(String header) { - this.header = header; - } - - public String getExtension() { - return extension; - } - - public void setExtension(String extension) { - this.extension = extension; - } - - + public PausedEvent(Object source) { + super(source); + } + + /** + * + */ + private static final long serialVersionUID = 7181269530090027203L; + + private String header; + + private String extension; + + public String getHeader() { + return header; + } + + public void setHeader(String header) { + this.header = header; + } + + public String getExtension() { + return extension; + } + + public void setExtension(String extension) { + this.extension = extension; + } + + } diff --git a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java index 0e8b9b64e..45244f669 100644 --- a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java @@ -30,8 +30,7 @@ * @version $Id$ * @since 0.2 */ -public class PeerEntryEvent extends ResponseEvent -{ +public class PeerEntryEvent extends ResponseEvent { /** * Serial version identifier. */ @@ -67,8 +66,7 @@ public class PeerEntryEvent extends ResponseEvent * * @param source */ - public PeerEntryEvent(Object source) - { + public PeerEntryEvent(Object source) { super(source); } @@ -79,23 +77,19 @@ public PeerEntryEvent(Object source) * @see #CHANNEL_TYPE_SIP * @see #CHANNEL_TYPE_IAX */ - public String getChannelType() - { + public String getChannelType() { return channelType; } - public void setChannelType(String channelType) - { + public void setChannelType(String channelType) { this.channelType = channelType; } - public String getObjectName() - { + public String getObjectName() { return objectName; } - public void setObjectName(String objectName) - { + public void setObjectName(String objectName) { this.objectName = objectName; } @@ -103,13 +97,11 @@ public void setObjectName(String objectName) * @return * @since 1.0.0 */ - public String getObjectUserName() - { + public String getObjectUserName() { return objectUserName; } - public void setObjectUserName(String objectUserName) - { + public void setObjectUserName(String objectUserName) { this.objectUserName = objectUserName; } @@ -118,13 +110,11 @@ public void setObjectUserName(String objectUserName) * * @return "peer" or "user". */ - public String getChanObjectType() - { + public String getChanObjectType() { return chanObjectType; } - public void setChanObjectType(String chanObjectType) - { + public void setChanObjectType(String chanObjectType) { this.chanObjectType = chanObjectType; } @@ -133,8 +123,7 @@ public void setChanObjectType(String chanObjectType) * * @return the IP address of the peer or "-none-" if none is available. */ - public String getIpAddress() - { + public String getIpAddress() { return ipAddress; } @@ -143,8 +132,7 @@ public String getIpAddress() * * @param ipAddress the IP address of the peer. */ - public void setIpAddress(String ipAddress) - { + public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; } @@ -155,13 +143,11 @@ public void setIpAddress(String ipAddress) * @deprecated since 1.0.0, use {@link #getPort()} instead. */ @Deprecated - public Integer getIpPort() - { + public Integer getIpPort() { return port; } - public void setIpPort(Integer ipPort) - { + public void setIpPort(Integer ipPort) { this.port = ipPort; } @@ -171,33 +157,27 @@ public void setIpPort(Integer ipPort) * @return the port of the peer. * @since 1.0.0 */ - public Integer getPort() - { + public Integer getPort() { return port; } - public void setPort(Integer port) - { + public void setPort(Integer port) { this.port = port; } - public Boolean getDynamic() - { + public Boolean getDynamic() { return dynamic; } - public void setDynamic(Boolean dynamic) - { + public void setDynamic(Boolean dynamic) { this.dynamic = dynamic; } - public Boolean getNatSupport() - { + public Boolean getNatSupport() { return natSupport; } - public void setNatSupport(Boolean natSupport) - { + public void setNatSupport(Boolean natSupport) { this.natSupport = natSupport; } @@ -206,16 +186,14 @@ public void setNatSupport(Boolean natSupport) * Available since Asterisk 1.8 * * @return true if the nat option is set to - * force_rport, false otherwise or - * null if not supported by Asterisk. + * force_rport, false otherwise or + * null if not supported by Asterisk. */ - public Boolean getForceRport() - { + public Boolean getForceRport() { return forceRport; } - public void setForceRport(Boolean forceRport) - { + public void setForceRport(Boolean forceRport) { this.forceRport = forceRport; } @@ -224,8 +202,7 @@ public void setForceRport(Boolean forceRport) * * @since 0.3 */ - public Boolean getVideoSupport() - { + public Boolean getVideoSupport() { return videoSupport; } @@ -234,8 +211,7 @@ public Boolean getVideoSupport() * * @since 0.3 */ - public void setVideoSupport(Boolean videoSupport) - { + public void setVideoSupport(Boolean videoSupport) { this.videoSupport = videoSupport; } @@ -245,27 +221,23 @@ public void setVideoSupport(Boolean videoSupport) * Available since Asterisk 1.6. * * @return true if the peer supports text messages, - * false otherwise or null if the property - * is not set (i.e. for Asterisk prior to 1.6). + * false otherwise or null if the property + * is not set (i.e. for Asterisk prior to 1.6). * @since 1.0.0 */ - public Boolean getTextSupport() - { + public Boolean getTextSupport() { return textSupport; } - public void setTextSupport(Boolean textSupport) - { + public void setTextSupport(Boolean textSupport) { this.textSupport = textSupport; } - public Boolean getAcl() - { + public Boolean getAcl() { return acl; } - public void setAcl(Boolean acl) - { + public void setAcl(Boolean acl) { this.acl = acl; } @@ -288,8 +260,7 @@ public void setAcl(Boolean acl) * * @return the status of this peer. */ - public String getStatus() - { + public String getStatus() { return status; } @@ -298,8 +269,7 @@ public String getStatus() * * @param status the status of this peer. */ - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } @@ -308,8 +278,7 @@ public void setStatus(String status) * * @since 0.3 */ - public String getRealtimeDevice() - { + public String getRealtimeDevice() { return realtimeDevice; } @@ -318,8 +287,7 @@ public String getRealtimeDevice() * * @since 0.3 */ - public void setRealtimeDevice(String realtimeDevice) - { + public void setRealtimeDevice(String realtimeDevice) { this.realtimeDevice = realtimeDevice; } @@ -329,106 +297,92 @@ public void setRealtimeDevice(String realtimeDevice) * Available since Asterisk 1.6. * * @return true if trunking is used, false if not - * or null if not set. + * or null if not set. * @since 1.0.0 */ - public Boolean getTrunk() - { + public Boolean getTrunk() { return trunk; } - public void setTrunk(Boolean trunk) - { + public void setTrunk(Boolean trunk) { this.trunk = trunk; } - public String getEncryption() - { + public String getEncryption() { return encryption; } - public void setEncryption(String encryption) - { + public void setEncryption(String encryption) { this.encryption = encryption; } /** * @return the autoComedia */ - public String getAutoComedia() - { + public String getAutoComedia() { return autoComedia; } /** * @param autoComedia the autoComedia to set */ - public void setAutoComedia(String autoComedia) - { + public void setAutoComedia(String autoComedia) { this.autoComedia = autoComedia; } /** * @return the autoForcerport */ - public String getAutoForcerport() - { + public String getAutoForcerport() { return autoForcerport; } /** * @param autoForcerport the autoForcerport to set */ - public void setAutoForcerport(String autoForcerport) - { + public void setAutoForcerport(String autoForcerport) { this.autoForcerport = autoForcerport; } /** * @return the comedia */ - public String getComedia() - { + public String getComedia() { return comedia; } /** * @param comedia the comedia to set */ - public void setComedia(String comedia) - { + public void setComedia(String comedia) { this.comedia = comedia; } /** * @return the description */ - public String getDescription() - { + public String getDescription() { return description; } /** * @param the description to set */ - public void setDescription(String description) - { + public void setDescription(String description) { this.description = description; } /** * @return the accountcode */ - public String getAccountcode() - { + public String getAccountcode() { return accountcode; } /** * @param the accountcode to set */ - public void setAccountcode(String accountcode) - { + public void setAccountcode(String accountcode) { this.accountcode = accountcode; } diff --git a/src/main/java/org/asteriskjava/manager/event/PeerStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/PeerStatusEvent.java index 200de7a54..3fd689d25 100644 --- a/src/main/java/org/asteriskjava/manager/event/PeerStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PeerStatusEvent.java @@ -25,8 +25,7 @@ * @author srt * @version $Id$ */ -public class PeerStatusEvent extends ManagerEvent -{ +public class PeerStatusEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -50,8 +49,7 @@ public class PeerStatusEvent extends ManagerEvent /** * @param source */ - public PeerStatusEvent(Object source) - { + public PeerStatusEvent(Object source) { super(source); } @@ -63,8 +61,7 @@ public PeerStatusEvent(Object source) * @return the type of channel that registers. * @since 1.0.0 */ - public String getChannelType() - { + public String getChannelType() { return channelType; } @@ -74,8 +71,7 @@ public String getChannelType() * @param channelType the type of channel that registers * @since 1.0.0 */ - public void setChannelType(String channelType) - { + public void setChannelType(String channelType) { this.channelType = channelType; } @@ -88,16 +84,14 @@ public void setChannelType(String channelType) * * @return the peer's name including the channel type. */ - public String getPeer() - { + public String getPeer() { return peer; } /** * Sets the name of the peer that registered. */ - public void setPeer(String peer) - { + public void setPeer(String peer) { this.peer = peer; } @@ -113,16 +107,14 @@ public void setPeer(String peer) *

  • Rejected (IAX only)
  • * */ - public String getPeerStatus() - { + public String getPeerStatus() { return peerStatus; } /** * Sets the registration state. */ - public void setPeerStatus(String peerStatus) - { + public void setPeerStatus(String peerStatus) { this.peerStatus = peerStatus; } @@ -134,16 +126,14 @@ public void setPeerStatus(String peerStatus) * * @return the cause of a rejection or unregistration. */ - public String getCause() - { + public String getCause() { return cause; } /** * Sets the cause of the rejection or unregistration. */ - public void setCause(String cause) - { + public void setCause(String cause) { this.cause = cause; } @@ -152,13 +142,11 @@ public void setCause(String cause) * equals "Unreachable" it returns how long the last response took (in ms) for IAX peers or -1 * for SIP peers. */ - public Integer getTime() - { + public Integer getTime() { return time; } - public void setTime(Integer time) - { + public void setTime(Integer time) { this.time = time; } @@ -169,13 +157,11 @@ public void setTime(Integer time) * @return the IP address of the peer that registered or null if not available. * @since 1.0.0 */ - public String getAddress() - { + public String getAddress() { return address; } - public void setAddress(String address) - { + public void setAddress(String address) { this.address = address; } @@ -186,13 +172,11 @@ public void setAddress(String address) * @return the port of the peer that registered or null if not available. * @since 1.0.0 */ - public Integer getPort() - { + public Integer getPort() { return port; } - public void setPort(Integer port) - { + public void setPort(Integer port) { this.port = port; } } diff --git a/src/main/java/org/asteriskjava/manager/event/PeerlistCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/PeerlistCompleteEvent.java index c98e42ace..f81453328 100644 --- a/src/main/java/org/asteriskjava/manager/event/PeerlistCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PeerlistCompleteEvent.java @@ -20,16 +20,15 @@ * A PeerlistCompleteEvent is triggered after the details of all peers has been reported in response * to an SIPPeersAction or SIPShowPeerAction.

    * Available since Asterisk 1.2 - * + * + * @author srt + * @version $Id$ * @see org.asteriskjava.manager.event.PeerEntryEvent * @see org.asteriskjava.manager.action.SipPeersAction * @see org.asteriskjava.manager.action.SipShowPeerAction - * @author srt - * @version $Id$ * @since 0.2 */ -public class PeerlistCompleteEvent extends ResponseEvent -{ +public class PeerlistCompleteEvent extends ResponseEvent { /** * Serial version identifier. */ @@ -39,31 +38,28 @@ public class PeerlistCompleteEvent extends ResponseEvent /** * Creates a new instance. - * + * * @param source */ - public PeerlistCompleteEvent(Object source) - { + public PeerlistCompleteEvent(Object source) { super(source); } /** * Returns the number of PeerEvents that have been reported. - * + * * @return the number of PeerEvents that have been reported. */ - public Integer getListItems() - { + public Integer getListItems() { return listItems; } /** * Sets the number of PeerEvents that have been reported. - * + * * @param listItems the number of PeerEvents that have been reported. */ - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } @@ -74,13 +70,11 @@ public void setListItems(Integer listItems) * @return always returns "Complete" confirming that all PeerEntry events have been sent. * @since 1.0.0 */ - public String getEventList() - { + public String getEventList() { return eventList; } - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } } diff --git a/src/main/java/org/asteriskjava/manager/event/PeersEvent.java b/src/main/java/org/asteriskjava/manager/event/PeersEvent.java index 2e1692d9c..5a4ed9f11 100644 --- a/src/main/java/org/asteriskjava/manager/event/PeersEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PeersEvent.java @@ -28,8 +28,7 @@ * @version $Id$ * @since 0.2 */ -public class PeersEvent extends ResponseEvent -{ +public class PeersEvent extends ResponseEvent { /** * Serial version identifier. */ @@ -45,18 +44,15 @@ public class PeersEvent extends ResponseEvent * * @param source */ - public PeersEvent( Object source ) - { + public PeersEvent(Object source) { super(source); } - public List getChildEvents() - { + public List getChildEvents() { return childEvents; } - public void setChildEvents( List childEvents ) - { + public void setChildEvents(List childEvents) { this.childEvents = childEvents; } } diff --git a/src/main/java/org/asteriskjava/manager/event/PickupEvent.java b/src/main/java/org/asteriskjava/manager/event/PickupEvent.java index 9ba8eaf91..13e47466e 100644 --- a/src/main/java/org/asteriskjava/manager/event/PickupEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PickupEvent.java @@ -1,9 +1,8 @@ package org.asteriskjava.manager.event; -public class PickupEvent extends ManagerEvent -{ +public class PickupEvent extends ManagerEvent { /** - * + * */ private static final long serialVersionUID = 1L; private String accountcode; @@ -26,198 +25,159 @@ public class PickupEvent extends ManagerEvent private String targetuniqueid; private String uniqueid; - public PickupEvent(Object source) - { + public PickupEvent(Object source) { super(source); } - public String getAccountcode() - { + public String getAccountcode() { return accountcode; } - public String getChannel() - { + public String getChannel() { return channel; } - public String getLanguage() - { + public String getLanguage() { return language; } - public String getLinkedid() - { + public String getLinkedid() { return linkedid; } - public String getTargetaccountcode() - { + public String getTargetaccountcode() { return targetaccountcode; } - public String getTargetcalleridname() - { + public String getTargetcalleridname() { return targetcalleridname; } - public String getTargetcalleridnum() - { + public String getTargetcalleridnum() { return targetcalleridnum; } - public String getTargetchannel() - { + public String getTargetchannel() { return targetchannel; } - public String getTargetchannelstate() - { + public String getTargetchannelstate() { return targetchannelstate; } - public String getTargetchannelstatedesc() - { + public String getTargetchannelstatedesc() { return targetchannelstatedesc; } - public String getTargetconnectedlinename() - { + public String getTargetconnectedlinename() { return targetconnectedlinename; } - public String getTargetconnectedlinenum() - { + public String getTargetconnectedlinenum() { return targetconnectedlinenum; } - public String getTargetcontext() - { + public String getTargetcontext() { return targetcontext; } - public String getTargetexten() - { + public String getTargetexten() { return targetexten; } - public String getTargetlanguage() - { + public String getTargetlanguage() { return targetlanguage; } - public String getTargetlinkedid() - { + public String getTargetlinkedid() { return targetlinkedid; } - public String getTargetpriority() - { + public String getTargetpriority() { return targetpriority; } - public String getTargetuniqueid() - { + public String getTargetuniqueid() { return targetuniqueid; } - public String getUniqueid() - { + public String getUniqueid() { return uniqueid; } - public void setAccountcode(String accountcode) - { + public void setAccountcode(String accountcode) { this.accountcode = accountcode; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public void setLinkedid(String linkedid) - { + public void setLinkedid(String linkedid) { this.linkedid = linkedid; } - public void setTargetaccountcode(String targetaccountcode) - { + public void setTargetaccountcode(String targetaccountcode) { this.targetaccountcode = targetaccountcode; } - public void setTargetcalleridname(String targetcalleridname) - { + public void setTargetcalleridname(String targetcalleridname) { this.targetcalleridname = targetcalleridname; } - public void setTargetcalleridnum(String targetcalleridnum) - { + public void setTargetcalleridnum(String targetcalleridnum) { this.targetcalleridnum = targetcalleridnum; } - public void setTargetchannel(String targetchannel) - { + public void setTargetchannel(String targetchannel) { this.targetchannel = targetchannel; } - public void setTargetchannelstate(String targetchannelstate) - { + public void setTargetchannelstate(String targetchannelstate) { this.targetchannelstate = targetchannelstate; } - public void setTargetchannelstatedesc(String targetchannelstatedesc) - { + public void setTargetchannelstatedesc(String targetchannelstatedesc) { this.targetchannelstatedesc = targetchannelstatedesc; } - public void setTargetconnectedlinename(String targetconnectedlinename) - { + public void setTargetconnectedlinename(String targetconnectedlinename) { this.targetconnectedlinename = targetconnectedlinename; } - public void setTargetconnectedlinenum(String targetconnectedlinenum) - { + public void setTargetconnectedlinenum(String targetconnectedlinenum) { this.targetconnectedlinenum = targetconnectedlinenum; } - public void setTargetcontext(String targetcontext) - { + public void setTargetcontext(String targetcontext) { this.targetcontext = targetcontext; } - public void setTargetexten(String targetexten) - { + public void setTargetexten(String targetexten) { this.targetexten = targetexten; } - public void setTargetlanguage(String targetlanguage) - { + public void setTargetlanguage(String targetlanguage) { this.targetlanguage = targetlanguage; } - public void setTargetlinkedid(String targetlinkedid) - { + public void setTargetlinkedid(String targetlinkedid) { this.targetlinkedid = targetlinkedid; } - public void setTargetpriority(String targetpriority) - { + public void setTargetpriority(String targetpriority) { this.targetpriority = targetpriority; } - public void setTargetuniqueid(String targetuniqueid) - { + public void setTargetuniqueid(String targetuniqueid) { this.targetuniqueid = targetuniqueid; } - public void setUniqueid(String uniqueid) - { + public void setUniqueid(String uniqueid) { this.uniqueid = uniqueid; } diff --git a/src/main/java/org/asteriskjava/manager/event/PriEventEvent.java b/src/main/java/org/asteriskjava/manager/event/PriEventEvent.java index 3b82cc4ba..47908969e 100644 --- a/src/main/java/org/asteriskjava/manager/event/PriEventEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PriEventEvent.java @@ -8,16 +8,14 @@ * @version $Id$ * @since 1.0.0 */ -public class PriEventEvent extends ManagerEvent -{ - private static final long serialVersionUID = 3257069450639290810L; - private String priEvent; +public class PriEventEvent extends ManagerEvent { + private static final long serialVersionUID = 3257069450639290810L; + private String priEvent; private Integer priEventCode; private String dChannel; private Integer span; - public PriEventEvent(Object source) - { + public PriEventEvent(Object source) { super(source); } @@ -48,13 +46,11 @@ public PriEventEvent(Object source) * @return the textual representation of the event code. * @see #getPriEventCode() */ - public String getPriEvent() - { + public String getPriEvent() { return priEvent; } - public void setPriEvent(String priEvent) - { + public void setPriEvent(String priEvent) { this.priEvent = priEvent; } @@ -64,13 +60,11 @@ public void setPriEvent(String priEvent) * @return the numerical pri event code. * @see #getPriEvent() */ - public Integer getPriEventCode() - { + public Integer getPriEventCode() { return priEventCode; } - public void setPriEventCode(Integer priEventCode) - { + public void setPriEventCode(Integer priEventCode) { this.priEventCode = priEventCode; } @@ -79,13 +73,11 @@ public void setPriEventCode(Integer priEventCode) * * @return the D-Channel the event occurred on. */ - public String getDChannel() - { + public String getDChannel() { return dChannel; } - public void setDChannel(String dChannel) - { + public void setDChannel(String dChannel) { this.dChannel = dChannel; } @@ -94,13 +86,11 @@ public void setDChannel(String dChannel) * * @return the span the event occurred on. */ - public Integer getSpan() - { + public Integer getSpan() { return span; } - public void setSpan(Integer span) - { + public void setSpan(Integer span) { this.span = span; } } diff --git a/src/main/java/org/asteriskjava/manager/event/ProtocolIdentifierReceivedEvent.java b/src/main/java/org/asteriskjava/manager/event/ProtocolIdentifierReceivedEvent.java index fa45bf69f..381f3960d 100644 --- a/src/main/java/org/asteriskjava/manager/event/ProtocolIdentifierReceivedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ProtocolIdentifierReceivedEvent.java @@ -17,17 +17,16 @@ package org.asteriskjava.manager.event; /** - * A ProtocolIdentifierReceivedEvent is triggered when the network connection to the Asterisk + * A ProtocolIdentifierReceivedEvent is triggered when the network connection to the Asterisk * server has been established and the protocol identifier has been sent.

    * It is a pseudo event not directly related to an Asterisk generated event.

    * The ProtocolIdentifierReceivedEvent is not dispatched to clients so you will * probably never see it. - * + * * @author srt * @version $Id$ */ -public class ProtocolIdentifierReceivedEvent extends ManagerEvent -{ +public class ProtocolIdentifierReceivedEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -41,28 +40,25 @@ public class ProtocolIdentifierReceivedEvent extends ManagerEvent /** * @param source */ - public ProtocolIdentifierReceivedEvent(Object source) - { + public ProtocolIdentifierReceivedEvent(Object source) { super(source); } /** * Returns the version of the protocol. - * + * * @return the version of the protocol. */ - public String getProtocolIdentifier() - { + public String getProtocolIdentifier() { return protocolIdentifier; } /** * Sets the version of the protocol. - * + * * @param protocolIdentifier the version of the protocol. */ - public void setProtocolIdentifier(String protocolIdentifier) - { + public void setProtocolIdentifier(String protocolIdentifier) { this.protocolIdentifier = protocolIdentifier; } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueCallerAbandonEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueCallerAbandonEvent.java index 58d189a73..56780e21b 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueCallerAbandonEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueCallerAbandonEvent.java @@ -23,11 +23,10 @@ * It is implemented in apps/app_queue.c *

    * Available since Asterisk 1.4. - * + * * @author martins */ -public class QueueCallerAbandonEvent extends QueueEvent -{ +public class QueueCallerAbandonEvent extends QueueEvent { /** * Serializable version identifier */ @@ -38,93 +37,80 @@ public class QueueCallerAbandonEvent extends QueueEvent private Integer holdTime; private String linkedId; private String language; - + private String accountcode; - + /** * @param source */ - public QueueCallerAbandonEvent(Object source) - { + public QueueCallerAbandonEvent(Object source) { super(source); } /** * @return the amount of time in seconds the caller was on hold */ - public Integer getHoldTime() - { + public Integer getHoldTime() { return holdTime; } /** * @param holdTime the amount of time in seconds the caller was on hold */ - public void setHoldTime(Integer holdTime) - { + public void setHoldTime(Integer holdTime) { this.holdTime = holdTime; } /** * @return the original position of the caller in the queue */ - public Integer getOriginalPosition() - { + public Integer getOriginalPosition() { return originalPosition; } /** * @param originalPosition the original position of the caller in the queue */ - public void setOriginalPosition(Integer originalPosition) - { + public void setOriginalPosition(Integer originalPosition) { this.originalPosition = originalPosition; } /** * @return the position of the caller at the time they abandoned the queue */ - public Integer getPosition() - { + public Integer getPosition() { return position; } /** * @param position the position of the caller at the time they abandoned the - * queue + * queue */ - public void setPosition(Integer position) - { + public void setPosition(Integer position) { this.position = position; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getAccountcode() - { - return accountcode; - } + public String getAccountcode() { + return accountcode; + } - public void setAccountcode(String accountcode) - { - this.accountcode = accountcode; - } + public void setAccountcode(String accountcode) { + this.accountcode = accountcode; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueCallerJoinEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueCallerJoinEvent.java index 204390119..121df3ff5 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueCallerJoinEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueCallerJoinEvent.java @@ -26,8 +26,7 @@ * * @author Leonardo de Souza */ -public class QueueCallerJoinEvent extends QueueEvent -{ +public class QueueCallerJoinEvent extends QueueEvent { /** * Serializable version identifier @@ -42,57 +41,48 @@ public class QueueCallerJoinEvent extends QueueEvent /** * @param source */ - public QueueCallerJoinEvent(Object source) - { + public QueueCallerJoinEvent(Object source) { super(source); } /** * @return the position of the caller at the time they abandoned the queue */ - public Integer getPosition() - { + public Integer getPosition() { return position; } /** * @param position the position of the caller at the time they abandoned the - * queue + * queue */ - public void setPosition(Integer position) - { + public void setPosition(Integer position) { this.position = position; } - - public String getLanguage() - { + + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getAccountcode() - { - return accountcode; - } + public String getAccountcode() { + return accountcode; + } + + public void setAccountcode(String accountcode) { + this.accountcode = accountcode; + } - public void setAccountcode(String accountcode) - { - this.accountcode = accountcode; - } - } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueCallerLeaveEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueCallerLeaveEvent.java index 77538b0d5..56e8862cf 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueCallerLeaveEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueCallerLeaveEvent.java @@ -26,8 +26,7 @@ * * @author Leonardo de Souza */ -public class QueueCallerLeaveEvent extends QueueEvent -{ +public class QueueCallerLeaveEvent extends QueueEvent { /** * Serializable version identifier @@ -37,61 +36,52 @@ public class QueueCallerLeaveEvent extends QueueEvent private Integer position; private String language; private String linkedId; - + private String accountcode; /** * @param source */ - public QueueCallerLeaveEvent(Object source) - { + public QueueCallerLeaveEvent(Object source) { super(source); } /** * @return the position of the caller at the time they abandoned the queue */ - public Integer getPosition() - { + public Integer getPosition() { return position; } /** * @param position the position of the caller at the time they abandoned the - * queue + * queue */ - public void setPosition(Integer position) - { + public void setPosition(Integer position) { this.position = position; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getAccountcode() - { - return accountcode; - } + public String getAccountcode() { + return accountcode; + } - public void setAccountcode(String accountcode) - { - this.accountcode = accountcode; - } + public void setAccountcode(String accountcode) { + this.accountcode = accountcode; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueEntryEvent.java index 840e105ed..b48c923e4 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueEntryEvent.java @@ -26,8 +26,7 @@ * @version $Id: QueueEntryEvent.java 1360 2009-09-04 01:08:57Z srt $ * @see org.asteriskjava.manager.action.QueueStatusAction */ -public class QueueEntryEvent extends ResponseEvent -{ +public class QueueEntryEvent extends ResponseEvent { /** * Serializable version identifier */ @@ -42,48 +41,42 @@ public class QueueEntryEvent extends ResponseEvent /** * @param source */ - public QueueEntryEvent(Object source) - { + public QueueEntryEvent(Object source) { super(source); } /** * Returns the name of the queue that contains this entry. */ - public String getQueue() - { + public String getQueue() { return queue; } /** * Sets the name of the queue that contains this entry. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } /** * Returns the position of this entry in the queue. */ - public Integer getPosition() - { + public Integer getPosition() { return position; } /** * Sets the position of this entry in the queue. */ - public void setPosition(Integer position) - { + public void setPosition(Integer position) { this.position = position; } /** * Returns the name of the channel of this entry. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -95,13 +88,11 @@ public String getChannel() * @return the unique id of the channel of this entry. * @since 1.0.0 */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -110,8 +101,7 @@ public void setUniqueId(String uniqueId) * * @param channel the name of the channel of this entry. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -120,8 +110,7 @@ public void setChannel(String channel) * * @return the the Caller*ID number of this entry. */ - public String getCallerId() - { + public String getCallerId() { return callerId; } @@ -130,24 +119,21 @@ public String getCallerId() * * @param callerId the the Caller*ID number of this entry. */ - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { this.callerId = callerId; } /** * Returns the number of seconds this entry has spent in the queue. */ - public Long getWait() - { + public Long getWait() { return wait; } /** * Sets the number of seconds this entry has spent in the queue. */ - public void setWait(Long wait) - { + public void setWait(Long wait) { this.wait = wait; } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueEvent.java index 862c6ca1a..c733fc0a4 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueEvent.java @@ -18,12 +18,11 @@ /** * Abstract base class providing common properties for JoinEvent and LeaveEvent. - * + * * @author srt * @version $Id$ */ -public abstract class QueueEvent extends ManagerEvent -{ +public abstract class QueueEvent extends ManagerEvent { /** * Serializable version identifier */ @@ -37,8 +36,7 @@ public abstract class QueueEvent extends ManagerEvent /** * @param source */ - public QueueEvent(Object source) - { + public QueueEvent(Object source) { super(source); } @@ -47,40 +45,36 @@ public QueueEvent(Object source) * This property is only available since Asterisk 1.4. Up to Asterisk 1.2 * this method always returns null.

    * See Asterisk issues 6458 and 7002. - * + * * @return the unique id of the channel that joines or leaves the queue or - * null if not supported by your Asterisk server. + * null if not supported by your Asterisk server. * @since 0.3 */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } /** * Sets the unique id of the channel that joines or leaves the queue. - * + * * @param uniqueId the unique id of the channel that joines or leaves the queue. * @since 0.3 */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } /** * Returns the name of the channel that joines or leaves the queue. */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel that joines or leaves the queue. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -88,32 +82,28 @@ public void setChannel(String channel) * Returns the number of elements in the queue, i.e. the number of calls waiting to be answered * by an agent. */ - public Integer getCount() - { + public Integer getCount() { return count; } /** * Sets the number of elements in the queue. */ - public void setCount(Integer count) - { + public void setCount(Integer count) { this.count = count; } /** * Returns the name of the queue. */ - public String getQueue() - { + public String getQueue() { return queue; } /** * Sets the name of the queue. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java index 090f6a5c4..b4644cc14 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java @@ -20,13 +20,12 @@ * A QueueMemberAddedEvent is triggered when a queue member is added to a queue.

    * It is implemented in apps/app_queue.c.

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class QueueMemberAddedEvent extends AbstractQueueMemberEvent -{ +public class QueueMemberAddedEvent extends AbstractQueueMemberEvent { /** * Serial version identifier. */ @@ -38,99 +37,90 @@ public class QueueMemberAddedEvent extends AbstractQueueMemberEvent private Long lastCall; private Integer status; private Boolean paused; - + private String stateinterface; private Boolean ringinuse; - public QueueMemberAddedEvent(Object source) - { + public QueueMemberAddedEvent(Object source) { super(source); } /** * Returns if the added member is a dynamic or static queue member. - * + * * @return "dynamic" if the added member is a dynamic queue member, "static" - * if the added member is a static queue member. + * if the added member is a static queue member. */ - public String getMembership() - { + public String getMembership() { return membership; } /** * Sets if the added member is a dynamic or static queue member. - * + * * @param membership "dynamic" if the added member is a dynamic queue - * member, "static" if the added member is a static queue member. + * member, "static" if the added member is a static queue member. */ - public void setMembership(String membership) - { + public void setMembership(String membership) { this.membership = membership; } /** * Returns the penalty for the added member. When calls are distributed * members with higher penalties are considered last. - * + * * @return the penalty for the added member. */ - public Integer getPenalty() - { + public Integer getPenalty() { return penalty; } /** * Sets the penalty for this member. - * + * * @param penalty the penalty for this member. */ - public void setPenalty(Integer penalty) - { + public void setPenalty(Integer penalty) { this.penalty = penalty; } /** * Returns the number of calls answered by the member. - * + * * @return the number of calls answered by the member. */ - public Integer getCallsTaken() - { + public Integer getCallsTaken() { return callsTaken; } /** * Sets the number of calls answered by the added member. - * + * * @param callsTaken the number of calls answered by the added member. */ - public void setCallsTaken(Integer callsTaken) - { + public void setCallsTaken(Integer callsTaken) { this.callsTaken = callsTaken; } /** * Returns the time the last successful call answered by the added member * was hungup. - * + * * @return the time (in seconds since 01/01/1970) the last successful call - * answered by the added member was hungup. + * answered by the added member was hungup. */ - public Long getLastCall() - { + public Long getLastCall() { return lastCall; } /** * Sets the time the last successful call answered by this member was * hungup. - * + * * @param lastCall the time (in seconds since 01/01/1970) the last - * successful call answered by the added member was hungup. + * successful call answered by the added member was hungup. */ - public void setLastCall(Long lastCall) - { + public void setLastCall(Long lastCall) { this.lastCall = lastCall; } @@ -151,63 +141,55 @@ public void setLastCall(Long lastCall) *

    AST_DEVICE_UNAVAILABLE (5)
    *
    ?
    * - * + * * @return the status of this queue member. */ - public Integer getStatus() - { + public Integer getStatus() { return status; } /** * Sets the status of this queue member. - * + * * @param status the status of this queue member */ - public void setStatus(Integer status) - { + public void setStatus(Integer status) { this.status = status; } /** * Returns if this queue member is paused (not accepting calls).

    - * + * * @return Boolean.TRUE if this member has been paused or - * Boolean.FALSE if not. + * Boolean.FALSE if not. */ - public Boolean getPaused() - { + public Boolean getPaused() { return paused; } /** * Sets if this member is paused. - * + * * @param paused Boolean.TRUE if this member has been paused - * or Boolean.FALSE if not. + * or Boolean.FALSE if not. */ - public void setPaused(Boolean paused) - { + public void setPaused(Boolean paused) { this.paused = paused; } - public String getStateinterface() - { - return stateinterface; - } + public String getStateinterface() { + return stateinterface; + } - public void setStateinterface(String stateinterface) - { - this.stateinterface = stateinterface; + public void setStateinterface(String stateinterface) { + this.stateinterface = stateinterface; } - public Boolean getRinginuse() - { - return ringinuse; - } + public Boolean getRinginuse() { + return ringinuse; + } - public void setRinginuse(Boolean ringinuse) - { - this.ringinuse = ringinuse; - } + public void setRinginuse(Boolean ringinuse) { + this.ringinuse = ringinuse; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java index 2aef06cb5..eb1ca075b 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java @@ -22,12 +22,11 @@ *

    * It is implemented in apps/app_queue.c * - * @see org.asteriskjava.manager.action.QueueStatusAction * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.QueueStatusAction */ -public class QueueMemberEvent extends ResponseEvent -{ +public class QueueMemberEvent extends ResponseEvent { public static final int AST_DEVICE_UNKNOWN = 0; /** @@ -63,14 +62,13 @@ public class QueueMemberEvent extends ResponseEvent private String stateinterface; private Integer incall; private String pausedreason; - private Integer wrapuptime; + private Integer wrapuptime; private String _interface; /** * @param source */ - public QueueMemberEvent(Object source) - { + public QueueMemberEvent(Object source) { super(source); } @@ -79,8 +77,7 @@ public QueueMemberEvent(Object source) * * @return the name of the queue. */ - public String getQueue() - { + public String getQueue() { return queue; } @@ -89,8 +86,7 @@ public String getQueue() * * @param queue the name of the queue. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } @@ -101,8 +97,7 @@ public void setQueue(String queue) * * @return the name of the member's interface. */ - final public String getInterface() - { + final public String getInterface() { return _interface; } @@ -111,8 +106,7 @@ final public String getInterface() * * @param member the name of the member's interface. */ - final public void setInterface(String _interface) - { + final public void setInterface(String _interface) { this._interface = _interface; } @@ -121,26 +115,23 @@ final public void setInterface(String _interface) *

    * E.g. the channel name or agent group. * - * @deprecated since Asterisk 12 * @return the name of the member's interface. + * @deprecated since Asterisk 12 */ @Deprecated - final public String getLocation() - { + final public String getLocation() { return _interface; } /** * Sets the name of the member's interface. * - * @deprecated since Asterisk 12 * @param member the name of the member's interface. + * @deprecated since Asterisk 12 */ @Deprecated - final public void setLocation(String _interface) - { - if ((_interface != null) && (!"null".equals(_interface))) - { // Location is not in use since asterisk 12 + final public void setLocation(String _interface) { + if ((_interface != null) && (!"null".equals(_interface))) { // Location is not in use since asterisk 12 this._interface = _interface; } } @@ -151,10 +142,9 @@ final public void setLocation(String _interface) * statically defined in queues.conf. * * @return "dynamic" if the added member is a dynamic queue member, "static" - * if the added member is a static queue member. + * if the added member is a static queue member. */ - public String getMembership() - { + public String getMembership() { return membership; } @@ -163,11 +153,10 @@ public String getMembership() * defined in queues.conf. * * @return true if this member has been statically defined in - * queues.conf, false otherwise. + * queues.conf, false otherwise. * @since 0.3 */ - public boolean isStatic() - { + public boolean isStatic() { return MEMBERSHIP_STATIC.equals(membership); } @@ -176,11 +165,10 @@ public boolean isStatic() * added by the QueueAdd command. * * @return true if this member has been dynamically added by - * the QueueAdd command, false otherwise. + * the QueueAdd command, false otherwise. * @since 0.3 */ - public boolean isDynamic() - { + public boolean isDynamic() { return MEMBERSHIP_DYNAMIC.equals(membership); } @@ -188,10 +176,9 @@ public boolean isDynamic() * Sets if this member has been dynamically or statically added. * * @param membership "dynamic" if the added member is a dynamic queue - * member, "static" if the added member is a static queue member. + * member, "static" if the added member is a static queue member. */ - public void setMembership(String membership) - { + public void setMembership(String membership) { this.membership = membership; } @@ -201,8 +188,7 @@ public void setMembership(String membership) * * @return the penalty for the added member. */ - public Integer getPenalty() - { + public Integer getPenalty() { return penalty; } @@ -211,8 +197,7 @@ public Integer getPenalty() * * @param penalty the penalty for this member. */ - public void setPenalty(Integer penalty) - { + public void setPenalty(Integer penalty) { this.penalty = penalty; } @@ -221,8 +206,7 @@ public void setPenalty(Integer penalty) * * @return the number of calls answered by the member. */ - public Integer getCallsTaken() - { + public Integer getCallsTaken() { return callsTaken; } @@ -231,8 +215,7 @@ public Integer getCallsTaken() * * @param callsTaken the number of calls answered by the added member. */ - public void setCallsTaken(Integer callsTaken) - { + public void setCallsTaken(Integer callsTaken) { this.callsTaken = callsTaken; } @@ -241,10 +224,9 @@ public void setCallsTaken(Integer callsTaken) * was hungup. * * @return the time (in seconds since 01/01/1970) the last successful call - * answered by the added member was hungup. + * answered by the added member was hungup. */ - public Long getLastCall() - { + public Long getLastCall() { return lastCall; } @@ -253,10 +235,9 @@ public Long getLastCall() * hungup. * * @param lastCall the time (in seconds since 01/01/1970) the last - * successful call answered by the added member was hungup. + * successful call answered by the added member was hungup. */ - public void setLastCall(Long lastCall) - { + public void setLastCall(Long lastCall) { this.lastCall = lastCall; } @@ -265,17 +246,16 @@ public void setLastCall(Long lastCall) * * @return the time (in seconds since 01/01/1970) */ - public Long getLastPause() - { + public Long getLastPause() { return lastPause; } /** * Sets the time when started last pause for queue member. + * * @param lastPause the time (in seconds since 01/01/1970) */ - public void setLastPause(Long lastPause) - { + public void setLastPause(Long lastPause) { this.lastPause = lastPause; } @@ -307,11 +287,10 @@ public void setLastPause(Long lastPause) * * * @return the status of this queue member or null if this - * attribute is not supported by your version of Asterisk. + * attribute is not supported by your version of Asterisk. * @since 0.2 */ - public Integer getStatus() - { + public Integer getStatus() { return status; } @@ -321,8 +300,7 @@ public Integer getStatus() * @param status the status of this queue member * @since 0.2 */ - public void setStatus(Integer status) - { + public void setStatus(Integer status) { this.status = status; } @@ -332,12 +310,11 @@ public void setStatus(Integer status) * Available since Asterisk 1.2. * * @return Boolean.TRUE if this member has been paused, - * Boolean.FALSE if not or null if pausing - * is not supported by your version of Asterisk. + * Boolean.FALSE if not or null if pausing + * is not supported by your version of Asterisk. * @since 0.2 */ - public Boolean getPaused() - { + public Boolean getPaused() { return paused; } @@ -346,8 +323,7 @@ public Boolean getPaused() * * @since 0.2 */ - public void setPaused(Boolean paused) - { + public void setPaused(Boolean paused) { this.paused = paused; } @@ -355,16 +331,14 @@ public void setPaused(Boolean paused) * Returns the name of the member. * * @return the name of the member supplied for logging when the member is - * added + * added * @since 1.0.0 */ - public String getName() - { + public String getName() { return name; } - public void setName(String name) - { + public void setName(String name) { this.name = name; } @@ -372,62 +346,54 @@ public void setName(String name) * Returns the name of the member. * * @return the name of the member supplied for logging when the member is - * added + * added * @deprecated since 1.0.0. Use {@link #getName()} instead. */ @Deprecated - public String getMemberName() - { + public String getMemberName() { return name; } // Renamed to "name" in Asterisk 1.6 - public void setMemberName(String memberName) - { + public void setMemberName(String memberName) { this.name = memberName; } /** * @return Name of the interface where device state is taken from. */ - public String getStateinterface() - { + public String getStateinterface() { return stateinterface; } - public void setStateinterface(String stateinterface) - { + public void setStateinterface(String stateinterface) { this.stateinterface = stateinterface; } /** * @return 1 if is incall 0 if not */ - public Integer getIncall() - { + public Integer getIncall() { return incall; } - public void setIncall(Integer incall) - { + public void setIncall(Integer incall) { this.incall = incall; } - public String getPausedreason() - { + public String getPausedreason() { return pausedreason; } - public void setPausedreason(String pausedreason) - { + public void setPausedreason(String pausedreason) { this.pausedreason = pausedreason; } - public Integer getWrapuptime() { - return wrapuptime; - } + public Integer getWrapuptime() { + return wrapuptime; + } - public void setWrapuptime(Integer wrapuptime) { - this.wrapuptime = wrapuptime; - } + public void setWrapuptime(Integer wrapuptime) { + this.wrapuptime = wrapuptime; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java index 7758854c1..c39ab200e 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java @@ -1,7 +1,6 @@ package org.asteriskjava.manager.event; -public class QueueMemberPauseEvent extends QueueMemberPausedEvent -{ +public class QueueMemberPauseEvent extends QueueMemberPausedEvent { private static final long serialVersionUID = 58564514209197321L; // Logger logger = LogManager.getLogger(); @@ -16,8 +15,7 @@ public class QueueMemberPauseEvent extends QueueMemberPausedEvent Integer incall; String pausedreason; - public QueueMemberPauseEvent(Object source) - { + public QueueMemberPauseEvent(Object source) { super(source); // TODO Auto-generated constructor stub } @@ -25,112 +23,98 @@ public QueueMemberPauseEvent(Object source) /** * @return the membership */ - public String getMembership() - { + public String getMembership() { return membership; } /** * @param membership the membership to set */ - public void setMembership(String membership) - { + public void setMembership(String membership) { this.membership = membership; } /** * @return the lastcall */ - public Long getLastcall() - { + public Long getLastcall() { return lastcall; } /** * @param lastcall the lastcall to set */ - public void setLastcall(Long lastcall) - { + public void setLastcall(Long lastcall) { this.lastcall = lastcall; } /** * @return the lastpause time in seconds */ - public Long getLastpause() - { + public Long getLastpause() { return lastpause; } /** * @param lastpause the lastpause time in seconds to set */ - public void setLastpause(Long lastpause) - { + public void setLastpause(Long lastpause) { this.lastpause = lastpause; } /** * @return the callsTaken */ - public Integer getCallsTaken() - { + public Integer getCallsTaken() { return callsTaken; } /** * @param callsTaken the callsTaken to set */ - public void setCallsTaken(Integer callsTaken) - { + public void setCallsTaken(Integer callsTaken) { this.callsTaken = callsTaken; } /** * @return the penalty */ - public Integer getPenalty() - { + public Integer getPenalty() { return penalty; } /** * @param penalty the penalty to set */ - public void setPenalty(Integer penalty) - { + public void setPenalty(Integer penalty) { this.penalty = penalty; } /** * @return the status */ - public Integer getStatus() - { + public Integer getStatus() { return status; } /** * @param status the status to set */ - public void setStatus(Integer status) - { + public void setStatus(Integer status) { this.status = status; } /** * @return the ringinuse */ - public Boolean getRinginuse() - { + public Boolean getRinginuse() { return ringinuse; } /** * @param ringinuse the ringinuse to set */ - public void setRinginuse(Boolean ringinuse) - { + public void setRinginuse(Boolean ringinuse) { this.ringinuse = ringinuse; } @@ -138,42 +122,36 @@ public void setRinginuse(Boolean ringinuse) /** * @return the stateInterface */ - public String getStateInterface() - { + public String getStateInterface() { return stateInterface; } /** * @param stateInterface the stateInterface to set */ - public void setStateInterface(String stateInterface) - { + public void setStateInterface(String stateInterface) { this.stateInterface = stateInterface; } /** * @return get Incall */ - public Integer getIncall() - { + public Integer getIncall() { return incall; } /** * @param setIncall the incall to set */ - public void setIncall(Integer incall) - { + public void setIncall(Integer incall) { this.incall = incall; } - public String getPausedreason() - { + public String getPausedreason() { return pausedreason; } - public void setPausedreason(String pausedreason) - { + public void setPausedreason(String pausedreason) { this.pausedreason = pausedreason; } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPausedEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPausedEvent.java index 66b0e5ec3..694117f29 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPausedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPausedEvent.java @@ -26,8 +26,7 @@ * @version $Id$ * @since 0.2 */ -public class QueueMemberPausedEvent extends AbstractQueueMemberEvent -{ +public class QueueMemberPausedEvent extends AbstractQueueMemberEvent { /** * Serial version identifier. */ @@ -40,8 +39,7 @@ public class QueueMemberPausedEvent extends AbstractQueueMemberEvent */ private String reason; - public QueueMemberPausedEvent(Object source) - { + public QueueMemberPausedEvent(Object source) { super(source); } @@ -49,10 +47,9 @@ public QueueMemberPausedEvent(Object source) * Returns if this queue member is paused (not accepting calls).

    * * @return Boolean.TRUE if this member has been paused or - * Boolean.FALSE if not. + * Boolean.FALSE if not. */ - public Boolean getPaused() - { + public Boolean getPaused() { return paused; } @@ -62,8 +59,7 @@ public Boolean getPaused() * @param paused Boolean.TRUE if this member has been paused * or Boolean.FALSE if not. */ - public void setPaused(Boolean paused) - { + public void setPaused(Boolean paused) { this.paused = paused; } @@ -74,8 +70,7 @@ public void setPaused(Boolean paused) * * @return the reason specified for the pause. */ - public String getReason() - { + public String getReason() { return reason; } @@ -84,8 +79,7 @@ public String getReason() * * @param reason the reason why the queue member has been paused. */ - public void setReason(String reason) - { + public void setReason(String reason) { this.reason = reason; } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java index 6ac91dbc1..e77d943d0 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java @@ -26,8 +26,7 @@ * @version $Id$ * @since 1.0.0 */ -public class QueueMemberPenaltyEvent extends ManagerEvent -{ +public class QueueMemberPenaltyEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -35,7 +34,7 @@ public class QueueMemberPenaltyEvent extends ManagerEvent private String queue; private String location; private Integer penalty; - private Boolean paused; + private Boolean paused; private Integer wrapuptime; private Integer lastpause; private String stateinterface; @@ -54,251 +53,251 @@ public class QueueMemberPenaltyEvent extends ManagerEvent * * @param source */ - public QueueMemberPenaltyEvent(Object source) - { + public QueueMemberPenaltyEvent(Object source) { super(source); } - /** - * Returns if the member is pause - * - * @return if the member is pause - */ - public Boolean getPaused() { - return paused; - } - - /** - * Sets if member is paused or not - * - * @param paused if paused - */ - public void setPaused(Boolean paused) { - this.paused = paused; - } - - /** - * Returns wrapuptime - * - * @return Returns wrapuptime - */ - public Integer getWrapuptime() { - return wrapuptime; - } - - /** - * Sets wrapuptime - * - * @param wrapuptime the wrapuptime - */ - public void setWrapuptime(Integer wrapuptime) { - this.wrapuptime = wrapuptime; - } - - /** - * Returns time in seconds when started last paused the queue member - * - * @return Returns time in seconds when started last paused the queue member - */ - public Integer getLastpause() { - return lastpause; - } - - /** - * Sets time in seconds when started last paused the queue member - * - * @param lastpause time in seconds when started last paused the queue member - */ - public void setLastpause(Integer lastpause) { - this.lastpause = lastpause; - } - - /** - * Returns the queue member's tech or location state - * - * @return the queue member's tech or location state - */ - public String getStateinterface() { - return stateinterface; - } - - /** - * Sets channel technology or location from which the member device changed - * - * @param stateinterface channel technology or location from which the member device changed - */ - public void setStateinterface(String stateinterface) { - this.stateinterface = stateinterface; - } - - /** - * Returns reason if set when paused - * - * @return reason if set when paused - */ - public String getPausedreason() { - return pausedreason; - } - - /** - * Sets reason if set when paused - * - * @param pausedreason reason if set when paused - */ - public void setPausedreason(String pausedreason) { - this.pausedreason = pausedreason; - } - - /** - * Returns if member is in call when event is raised - * - * @return if member is in call when event is raised - */ - public Integer getIncall() { - return incall; - } - - /** - * Sets if member is in call when event is raised - * - * @param incall if member is in call when event is raised - */ - public void setIncall(Integer incall) { - this.incall = incall; - } - - /** - * Returns membership in queue - * E.g. dynamic, realtime, static - * - * @return membership in queue - */ - public String getMembership() { - return membership; - } - - /** - * Sets membership in queue - * - * @param membership membership in queue - */ - public void setMembership(String membership) { - this.membership = membership; - } - - /** - * Returns queue member's tech or location name - * - * @return queue member's tech or location name - */ - public String getInterface() { - return _interface; - } - - /** - * Sets queue member's tech or location name - * - * @param _interface queue member's tech or location name - */ - public void setInterface(String _interface) { - this._interface = _interface; - } - - /** - * Returns number of calls this queue member has serviced - * - * @return number of calls this queue member has serviced - */ - public Integer getCallstaken() { - return callstaken; - } - - /** - * Sets number of calls this queue member has serviced - * - * @param callstaken number of calls this queue member has serviced - */ - public void setCallstaken(Integer callstaken) { - this.callstaken = callstaken; - } - - /** - * Returns member's ring in use setup - * - * @return member's ring in use setup - */ - public Integer getRinginuse() { - return ringinuse; - } - - /** - * Sets member's ring in use setup - * - * @param ringinuse member's ring in use setup - */ - public void setRinginuse(Integer ringinuse) { - this.ringinuse = ringinuse; - } - - /** - * Returns time this member last took a call, expressed in seconds - * - * @return time this member last took a call, expressed in seconds - */ - public Integer getLastcall() { - return lastcall; - } - - /** - * Sets time this member last took a call, expressed in seconds - * - * @param lastcall time this member last took a call, expressed in seconds - */ - public void setLastcall(Integer lastcall) { - this.lastcall = lastcall; - } - - /** - * Returns name of the queue member. - * - * @return name of the queue member. - */ - public String getMembername() { - return membername; - } - - /** - * Sets name of the queue member. - * - * @param membername name of the queue member. - */ - public void setMembername(String membername) { - this.membername = membername; - } - - /** - * Returns numeric device state status of the queue member - * - * @return numeric device state status of the queue member - */ - public Integer getStatus() { return status; } - - /** - * Sets numeric device state status of the queue member - * - * @param status numeric device state status of the queue member - */ - public void setStatus(Integer status) { - this.status = status; - } + /** + * Returns if the member is pause + * + * @return if the member is pause + */ + public Boolean getPaused() { + return paused; + } + + /** + * Sets if member is paused or not + * + * @param paused if paused + */ + public void setPaused(Boolean paused) { + this.paused = paused; + } + + /** + * Returns wrapuptime + * + * @return Returns wrapuptime + */ + public Integer getWrapuptime() { + return wrapuptime; + } + + /** + * Sets wrapuptime + * + * @param wrapuptime the wrapuptime + */ + public void setWrapuptime(Integer wrapuptime) { + this.wrapuptime = wrapuptime; + } + + /** + * Returns time in seconds when started last paused the queue member + * + * @return Returns time in seconds when started last paused the queue member + */ + public Integer getLastpause() { + return lastpause; + } + + /** + * Sets time in seconds when started last paused the queue member + * + * @param lastpause time in seconds when started last paused the queue member + */ + public void setLastpause(Integer lastpause) { + this.lastpause = lastpause; + } + + /** + * Returns the queue member's tech or location state + * + * @return the queue member's tech or location state + */ + public String getStateinterface() { + return stateinterface; + } + + /** + * Sets channel technology or location from which the member device changed + * + * @param stateinterface channel technology or location from which the member device changed + */ + public void setStateinterface(String stateinterface) { + this.stateinterface = stateinterface; + } + + /** + * Returns reason if set when paused + * + * @return reason if set when paused + */ + public String getPausedreason() { + return pausedreason; + } + + /** + * Sets reason if set when paused + * + * @param pausedreason reason if set when paused + */ + public void setPausedreason(String pausedreason) { + this.pausedreason = pausedreason; + } + + /** + * Returns if member is in call when event is raised + * + * @return if member is in call when event is raised + */ + public Integer getIncall() { + return incall; + } + + /** + * Sets if member is in call when event is raised + * + * @param incall if member is in call when event is raised + */ + public void setIncall(Integer incall) { + this.incall = incall; + } + + /** + * Returns membership in queue + * E.g. dynamic, realtime, static + * + * @return membership in queue + */ + public String getMembership() { + return membership; + } + + /** + * Sets membership in queue + * + * @param membership membership in queue + */ + public void setMembership(String membership) { + this.membership = membership; + } + + /** + * Returns queue member's tech or location name + * + * @return queue member's tech or location name + */ + public String getInterface() { + return _interface; + } + + /** + * Sets queue member's tech or location name + * + * @param _interface queue member's tech or location name + */ + public void setInterface(String _interface) { + this._interface = _interface; + } + + /** + * Returns number of calls this queue member has serviced + * + * @return number of calls this queue member has serviced + */ + public Integer getCallstaken() { + return callstaken; + } + + /** + * Sets number of calls this queue member has serviced + * + * @param callstaken number of calls this queue member has serviced + */ + public void setCallstaken(Integer callstaken) { + this.callstaken = callstaken; + } + + /** + * Returns member's ring in use setup + * + * @return member's ring in use setup + */ + public Integer getRinginuse() { + return ringinuse; + } + + /** + * Sets member's ring in use setup + * + * @param ringinuse member's ring in use setup + */ + public void setRinginuse(Integer ringinuse) { + this.ringinuse = ringinuse; + } + + /** + * Returns time this member last took a call, expressed in seconds + * + * @return time this member last took a call, expressed in seconds + */ + public Integer getLastcall() { + return lastcall; + } + + /** + * Sets time this member last took a call, expressed in seconds + * + * @param lastcall time this member last took a call, expressed in seconds + */ + public void setLastcall(Integer lastcall) { + this.lastcall = lastcall; + } + + /** + * Returns name of the queue member. + * + * @return name of the queue member. + */ + public String getMembername() { + return membername; + } + + /** + * Sets name of the queue member. + * + * @param membername name of the queue member. + */ + public void setMembername(String membername) { + this.membername = membername; + } + + /** + * Returns numeric device state status of the queue member + * + * @return numeric device state status of the queue member + */ + public Integer getStatus() { + return status; + } + + /** + * Sets numeric device state status of the queue member + * + * @param status numeric device state status of the queue member + */ + public void setStatus(Integer status) { + this.status = status; + } /** * Returns the name of the queue. * * @return the name of the queue. */ - public String getQueue() - { + public String getQueue() { return queue; } @@ -307,8 +306,7 @@ public String getQueue() * * @param queue the name of the queue. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } @@ -318,8 +316,7 @@ public void setQueue(String queue) * * @return the name of the member's interface. */ - public String getLocation() - { + public String getLocation() { return location; } @@ -328,8 +325,7 @@ public String getLocation() * * @param member the name of the member's interface. */ - public void setLocation(String member) - { + public void setLocation(String member) { this.location = member; } @@ -338,8 +334,7 @@ public void setLocation(String member) * * @return the new penalty. */ - public Integer getPenalty() - { + public Integer getPenalty() { return penalty; } @@ -348,8 +343,7 @@ public Integer getPenalty() * * @param penalty the new penalty. */ - public void setPenalty(Integer penalty) - { + public void setPenalty(Integer penalty) { this.penalty = penalty; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java index 3b61e9907..d03a4e88b 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java @@ -21,18 +21,17 @@ * queue.

    * It is implemented in apps/app_queue.c.

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class QueueMemberRemovedEvent extends AbstractQueueMemberEvent -{ +public class QueueMemberRemovedEvent extends AbstractQueueMemberEvent { /** * Serial version identifier. */ private static final long serialVersionUID = 2108033737226142194L; - + Boolean paused; Integer penalty; String stateinterface; @@ -41,105 +40,88 @@ public class QueueMemberRemovedEvent extends AbstractQueueMemberEvent Boolean ringinuse; Long lastcall; Integer status; - - public QueueMemberRemovedEvent(Object source) - { + + public QueueMemberRemovedEvent(Object source) { super(source); } - public Boolean getPaused() - { - return paused; - } + public Boolean getPaused() { + return paused; + } - public void setPaused(Boolean paused) - { - this.paused = paused; - } + public void setPaused(Boolean paused) { + this.paused = paused; + } - public Integer getPenalty() - { - return penalty; - } + public Integer getPenalty() { + return penalty; + } - public void setPenalty(Integer penalty) - { - this.penalty = penalty; - } + public void setPenalty(Integer penalty) { + this.penalty = penalty; + } - public String getStateinterface() - { - return stateinterface; - } + public String getStateinterface() { + return stateinterface; + } - public void setStateinterface(String stateinterface) - { - this.stateinterface = stateinterface; - } + public void setStateinterface(String stateinterface) { + this.stateinterface = stateinterface; + } - public String getMembership() - { - return membership; - } + public String getMembership() { + return membership; + } - public void setMembership(String membership) - { - this.membership = membership; + public void setMembership(String membership) { + this.membership = membership; } - public Long getCallstaken() - { - return callstaken; - } + public Long getCallstaken() { + return callstaken; + } - public void setCallstaken(Long callstaken) - { - this.callstaken = callstaken; - } + public void setCallstaken(Long callstaken) { + this.callstaken = callstaken; + } - public Boolean getRinginuse() - { - return ringinuse; - } + public Boolean getRinginuse() { + return ringinuse; + } - public void setRinginuse(Boolean ringinuse) - { - this.ringinuse = ringinuse; - } + public void setRinginuse(Boolean ringinuse) { + this.ringinuse = ringinuse; + } - public Long getLastcall() - { - return lastcall; - } + public Long getLastcall() { + return lastcall; + } - public void setLastcall(Long lastcall) - { - this.lastcall = lastcall; - } + public void setLastcall(Long lastcall) { + this.lastcall = lastcall; + } - public Integer getStatus() - { - return status; - } + public Integer getStatus() { + return status; + } - public void setStatus(Integer status) - { - this.status = status; - } + public void setStatus(Integer status) { + this.status = status; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java index f70dd6b67..1529654c1 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberStatusEvent.java @@ -18,12 +18,11 @@ /** * A QueueMemberStatusEvent shows the status of a QueueMemberEvent - * + * * @author Asteria Solutions Group, Inc. http://www.asteriasgi.com/ * @version $Id$ */ -public class QueueMemberStatusEvent extends QueueMemberEvent -{ +public class QueueMemberStatusEvent extends QueueMemberEvent { /** * Serializable version identifier */ @@ -35,34 +34,29 @@ public class QueueMemberStatusEvent extends QueueMemberEvent /** * @param source */ - public QueueMemberStatusEvent(Object source) - { + public QueueMemberStatusEvent(Object source) { super(source); } /** * @return the ringinuse */ - public String getRinginuse() - { + public String getRinginuse() { return ringinuse; } /** * @param ringinuse the ringinuse to set */ - public void setRinginuse(String ringinuse) - { + public void setRinginuse(String ringinuse) { this.ringinuse = ringinuse; } - public Integer getWrapuptime() - { + public Integer getWrapuptime() { return wrapuptime; } - public void setWrapuptime(Integer wrapuptime) - { + public void setWrapuptime(Integer wrapuptime) { this.wrapuptime = wrapuptime; } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueParamsEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueParamsEvent.java index 504dc3e83..bca9afffe 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueParamsEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueParamsEvent.java @@ -25,8 +25,7 @@ * @version $Id$ * @see org.asteriskjava.manager.action.QueueStatusAction */ -public class QueueParamsEvent extends ResponseEvent -{ +public class QueueParamsEvent extends ResponseEvent { /** * Serializable version identifier. */ @@ -44,8 +43,7 @@ public class QueueParamsEvent extends ResponseEvent private Double serviceLevelPerf2; private Integer weight; - public QueueParamsEvent(Object source) - { + public QueueParamsEvent(Object source) { super(source); } @@ -55,8 +53,7 @@ public QueueParamsEvent(Object source) * * @return the name of the queue. */ - public String getQueue() - { + public String getQueue() { return queue; } @@ -65,8 +62,7 @@ public String getQueue() * * @param queue the name of the queue. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } @@ -76,8 +72,7 @@ public void setQueue(String queue) * * @return the maximum number of people waiting in the queue or 0 for unlimited. */ - public Integer getMax() - { + public Integer getMax() { return max; } @@ -86,8 +81,7 @@ public Integer getMax() * * @param max the maximum number of people waiting in the queue or 0 for unlimited. */ - public void setMax(Integer max) - { + public void setMax(Integer max) { this.max = max; } @@ -107,8 +101,7 @@ public void setMax(Integer max) * @return the strategy used for this queue. * @since 1.0.0 */ - public String getStrategy() - { + public String getStrategy() { return strategy; } @@ -118,8 +111,7 @@ public String getStrategy() * @param strategy the strategy used for this queue. * @since 1.0.0 */ - public void setStrategy(String strategy) - { + public void setStrategy(String strategy) { this.strategy = strategy; } @@ -128,8 +120,7 @@ public void setStrategy(String strategy) * * @return the number of calls currently waiting in the queue. */ - public Integer getCalls() - { + public Integer getCalls() { return calls; } @@ -138,8 +129,7 @@ public Integer getCalls() * * @param calls the number of calls currently waiting in the queue. */ - public void setCalls(Integer calls) - { + public void setCalls(Integer calls) { this.calls = calls; } @@ -148,8 +138,7 @@ public void setCalls(Integer calls) * * @return the current average holdtime for this queue (in seconds). */ - public Integer getHoldTime() - { + public Integer getHoldTime() { return holdTime; } @@ -158,8 +147,7 @@ public Integer getHoldTime() * * @param holdTime the current average holdtime for this queue (in seconds). */ - public void setHoldTime(Integer holdTime) - { + public void setHoldTime(Integer holdTime) { this.holdTime = holdTime; } @@ -169,8 +157,7 @@ public void setHoldTime(Integer holdTime) * @return the current avarage talk time for this queue. * @since 1.0.0 */ - public Integer getTalkTime() - { + public Integer getTalkTime() { return talkTime; } @@ -180,8 +167,7 @@ public Integer getTalkTime() * @param talkTime the current avarage talk time for this queue. * @since 1.0.0 */ - public void setTalkTime(Integer talkTime) - { + public void setTalkTime(Integer talkTime) { this.talkTime = talkTime; } @@ -190,8 +176,7 @@ public void setTalkTime(Integer talkTime) * * @return the number of completed calls. */ - public Integer getCompleted() - { + public Integer getCompleted() { return completed; } @@ -200,8 +185,7 @@ public Integer getCompleted() * * @param complete the number of completed calls. */ - public void setCompleted(Integer complete) - { + public void setCompleted(Integer complete) { this.completed = complete; } @@ -210,8 +194,7 @@ public void setCompleted(Integer complete) * * @return the number of abandoned calls. */ - public Integer getAbandoned() - { + public Integer getAbandoned() { return abandoned; } @@ -220,8 +203,7 @@ public Integer getAbandoned() * * @param abandoned the number of abandoned calls. */ - public void setAbandoned(Integer abandoned) - { + public void setAbandoned(Integer abandoned) { this.abandoned = abandoned; } @@ -231,8 +213,7 @@ public void setAbandoned(Integer abandoned) * * @return the service level (in seconds). */ - public Integer getServiceLevel() - { + public Integer getServiceLevel() { return serviceLevel; } @@ -241,8 +222,7 @@ public Integer getServiceLevel() * * @param serviceLevel the service level (in seconds). */ - public void setServiceLevel(Integer serviceLevel) - { + public void setServiceLevel(Integer serviceLevel) { this.serviceLevel = serviceLevel; } @@ -251,10 +231,9 @@ public void setServiceLevel(Integer serviceLevel) * calls (in percent). * * @return the ratio of calls answered within the specified service level per total completed - * calls (in percent). + * calls (in percent). */ - public Double getServiceLevelPerf() - { + public Double getServiceLevelPerf() { return serviceLevelPerf; } @@ -265,8 +244,7 @@ public Double getServiceLevelPerf() * @param serviceLevelPerf the ratio of calls answered within the specified service level per total completed * calls (in percent). */ - public void setServiceLevelPerf(Double serviceLevelPerf) - { + public void setServiceLevelPerf(Double serviceLevelPerf) { this.serviceLevelPerf = serviceLevelPerf; } @@ -279,11 +257,10 @@ public void setServiceLevelPerf(Double serviceLevelPerf) * Available since Asterisk 1.2 * * @return the weight of this queue or null if not - * supported by your version of Asterisk + * supported by your version of Asterisk * @since 0.2 */ - public Integer getWeight() - { + public Integer getWeight() { return weight; } @@ -293,8 +270,7 @@ public Integer getWeight() * @param weight the weight of this queue * @since 0.2 */ - public void setWeight(Integer weight) - { + public void setWeight(Integer weight) { this.weight = weight; } @@ -307,5 +283,4 @@ public void setServiceLevelPerf2(Double serviceLevelPerf2) { } - } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueStatusCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueStatusCompleteEvent.java index 5783bc7a1..44ab073e8 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueStatusCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueStatusCompleteEvent.java @@ -20,49 +20,42 @@ * A QueueStatusCompleteEvent is triggered after the state of all queues has been reported in response * to a QueueStatusAction.

    * Since Asterisk 1.2 - * - * @see org.asteriskjava.manager.action.QueueStatusAction - * + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.QueueStatusAction * @since 0.2 */ -public class QueueStatusCompleteEvent extends ResponseEvent -{ +public class QueueStatusCompleteEvent extends ResponseEvent { /** * Serial version identifier */ private static final long serialVersionUID = -1177773673509373297L; - + private Integer listItems; private String eventList; /** * @param source */ - public QueueStatusCompleteEvent(Object source) - { + public QueueStatusCompleteEvent(Object source) { super(source); } - public Integer getListItems() - { + public Integer getListItems() { return listItems; } - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } - public String getEventList() - { + public String getEventList() { return eventList; } - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } - + } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueSummaryCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueSummaryCompleteEvent.java index 65025a813..2c2e72d66 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueSummaryCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueSummaryCompleteEvent.java @@ -13,62 +13,62 @@ * @since 0.3 */ public class QueueSummaryCompleteEvent extends ResponseEvent { - /** - * Serial version identifier. - */ - private static final long serialVersionUID = -5044247858568827143L; + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -5044247858568827143L; - /** - * ?? - */ - private String eventList; + /** + * ?? + */ + private String eventList; - /** - * The number of listed items from queueSummaryAction. - */ - private Integer listItems; + /** + * The number of listed items from queueSummaryAction. + */ + private Integer listItems; - public QueueSummaryCompleteEvent(Object source) { - super(source); - } + public QueueSummaryCompleteEvent(Object source) { + super(source); + } - /** - * Returns eventList variable. - * - * @return String value. - */ + /** + * Returns eventList variable. + * + * @return String value. + */ - public String getEventlist() { - return eventList; - } + public String getEventlist() { + return eventList; + } - /** - * Sets eventList variable. - * - * @param eventList variable - */ + /** + * Sets eventList variable. + * + * @param eventList variable + */ - public void setEventlist(String eventList) { - this.eventList = eventList; - } + public void setEventlist(String eventList) { + this.eventList = eventList; + } - /** - * Returns the number of listed items. - * - * @return listItems size. - */ + /** + * Returns the number of listed items. + * + * @return listItems size. + */ - public Integer getListitems() { - return listItems; - } + public Integer getListitems() { + return listItems; + } - /** - * Sets the returnItems value. - * - * @param listItems variable. - */ + /** + * Sets the returnItems value. + * + * @param listItems variable. + */ - public void setListitems(Integer listItems) { - this.listItems = listItems; - } + public void setListitems(Integer listItems) { + this.listItems = listItems; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueSummaryEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueSummaryEvent.java index dad4cab15..723c51aab 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueSummaryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueSummaryEvent.java @@ -16,8 +16,7 @@ * @see QueueSummaryAction * @since 0.3 */ -public class QueueSummaryEvent extends ResponseEvent -{ +public class QueueSummaryEvent extends ResponseEvent { /** * Serial version identifier. */ @@ -30,8 +29,7 @@ public class QueueSummaryEvent extends ResponseEvent private Integer talkTime; private Integer longestHoldTime; - public QueueSummaryEvent(Object source) - { + public QueueSummaryEvent(Object source) { super(source); } @@ -40,8 +38,7 @@ public QueueSummaryEvent(Object source) * * @return the name of queue. */ - public String getQueue() - { + public String getQueue() { return queue; } @@ -50,8 +47,7 @@ public String getQueue() * * @param queue the name of queue. */ - public void setQueue(String queue) - { + public void setQueue(String queue) { this.queue = queue; } @@ -60,8 +56,7 @@ public void setQueue(String queue) * * @return the number of members logged in. */ - public Integer getLoggedIn() - { + public Integer getLoggedIn() { return loggedIn; } @@ -70,8 +65,7 @@ public Integer getLoggedIn() * * @param loggedIn the number of members logged in. */ - public void setLoggedIn(Integer loggedIn) - { + public void setLoggedIn(Integer loggedIn) { this.loggedIn = loggedIn; } @@ -82,8 +76,7 @@ public void setLoggedIn(Integer loggedIn) * * @return the number of members logged in and not in a call. */ - public Integer getAvailable() - { + public Integer getAvailable() { return available; } @@ -92,8 +85,7 @@ public Integer getAvailable() * * @param available the number of members logged in and not in a call. */ - public void setAvailable(Integer available) - { + public void setAvailable(Integer available) { this.available = available; } @@ -102,8 +94,7 @@ public void setAvailable(Integer available) * * @return the number of callers currently waiting in the queue. */ - public Integer getCallers() - { + public Integer getCallers() { return callers; } @@ -112,8 +103,7 @@ public Integer getCallers() * * @param callers the number of callers currently waiting in the queue. */ - public void setCallers(Integer callers) - { + public void setCallers(Integer callers) { this.callers = callers; } @@ -122,8 +112,7 @@ public void setCallers(Integer callers) * * @return the current avarage hold time for this queue. */ - public Integer getHoldTime() - { + public Integer getHoldTime() { return holdTime; } @@ -132,8 +121,7 @@ public Integer getHoldTime() * * @param holdTime the current avarage hold time for this queue. */ - public void setHoldTime(Integer holdTime) - { + public void setHoldTime(Integer holdTime) { this.holdTime = holdTime; } @@ -143,8 +131,7 @@ public void setHoldTime(Integer holdTime) * @return the current avarage talk time for this queue. * @since 1.0.0 */ - public Integer getTalkTime() - { + public Integer getTalkTime() { return talkTime; } @@ -154,8 +141,7 @@ public Integer getTalkTime() * @param talkTime the current avarage talk time for this queue. * @since 1.0.0 */ - public void setTalkTime(Integer talkTime) - { + public void setTalkTime(Integer talkTime) { this.talkTime = talkTime; } @@ -165,8 +151,7 @@ public void setTalkTime(Integer talkTime) * @return the longest hold time of the a queue entry currently in the queue. * @since 1.0.0 */ - public Integer getLongestHoldTime() - { + public Integer getLongestHoldTime() { return longestHoldTime; } @@ -176,8 +161,7 @@ public Integer getLongestHoldTime() * @param longestHoldTime the longest hold time of the a queue entry currently in the queue. * @since 1.0.0 */ - public void setLongestHoldTime(Integer longestHoldTime) - { + public void setLongestHoldTime(Integer longestHoldTime) { this.longestHoldTime = longestHoldTime; } } diff --git a/src/main/java/org/asteriskjava/manager/event/ReceiveFaxEvent.java b/src/main/java/org/asteriskjava/manager/event/ReceiveFaxEvent.java index 5dfb41444..2585040db 100644 --- a/src/main/java/org/asteriskjava/manager/event/ReceiveFaxEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ReceiveFaxEvent.java @@ -3,8 +3,7 @@ /** * A ReceiveFaxEvent is an event of Digium's Fax For Asterisk add-on. */ -public class ReceiveFaxEvent extends ManagerEvent -{ +public class ReceiveFaxEvent extends ManagerEvent { private static final long serialVersionUID = 0L; private String channel; private String callerId; @@ -15,88 +14,71 @@ public class ReceiveFaxEvent extends ManagerEvent private Integer transferRate; private String fileName; - public ReceiveFaxEvent(Object source) - { + public ReceiveFaxEvent(Object source) { super(source); } - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } - public String getCallerId() - { + public String getCallerId() { return callerId; } - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { this.callerId = callerId; } - public String getRemoteStationId() - { + public String getRemoteStationId() { return remoteStationId; } - public void setRemoteStationId(String remoteStationId) - { + public void setRemoteStationId(String remoteStationId) { this.remoteStationId = remoteStationId; } - public String getLocalStationId() - { + public String getLocalStationId() { return localStationId; } - public void setLocalStationId(String localStationId) - { + public void setLocalStationId(String localStationId) { this.localStationId = localStationId; } - public Integer getPagesTransferred() - { + public Integer getPagesTransferred() { return pagesTransferred; } - public void setPagesTransferred(Integer pagesTransferred) - { + public void setPagesTransferred(Integer pagesTransferred) { this.pagesTransferred = pagesTransferred; } - public String getResolution() - { + public String getResolution() { return resolution; } - public void setResolution(String resolution) - { + public void setResolution(String resolution) { this.resolution = resolution; } - public Integer getTransferRate() - { + public Integer getTransferRate() { return transferRate; } - public void setTransferRate(Integer transferRate) - { + public void setTransferRate(Integer transferRate) { this.transferRate = transferRate; } - public String getFileName() - { + public String getFileName() { return fileName; } - public void setFileName(String fileName) - { + public void setFileName(String fileName) { this.fileName = fileName; } } diff --git a/src/main/java/org/asteriskjava/manager/event/RegistrationsCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/RegistrationsCompleteEvent.java index f13f2d951..f79103c89 100644 --- a/src/main/java/org/asteriskjava/manager/event/RegistrationsCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RegistrationsCompleteEvent.java @@ -27,21 +27,19 @@ * @see org.asteriskjava.manager.action.SipShowRegistryAction * @since 1.0.0 */ -public class RegistrationsCompleteEvent extends ResponseEvent -{ +public class RegistrationsCompleteEvent extends ResponseEvent { /** - * - */ - private static final long serialVersionUID = 6269829662009989518L; - private Integer listItems; + * + */ + private static final long serialVersionUID = 6269829662009989518L; + private Integer listItems; private String eventList; /** * Creates a new RegistrationsCompleteEvent. */ - public RegistrationsCompleteEvent(Object source) - { + public RegistrationsCompleteEvent(Object source) { super(source); } @@ -50,8 +48,7 @@ public RegistrationsCompleteEvent(Object source) * * @return the number of SIP registrations that have been reported. */ - public Integer getListItems() - { + public Integer getListItems() { return listItems; } @@ -60,8 +57,7 @@ public Integer getListItems() * * @param listItems the number of SIP registrations that have been reported. */ - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } @@ -70,14 +66,12 @@ public void setListItems(Integer listItems) * * @return always returns "Complete" confirming that all RegistryEntry events have been sent. */ - public String getEventList() - { + public String getEventList() { return eventList; } - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } diff --git a/src/main/java/org/asteriskjava/manager/event/RegistryEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/RegistryEntryEvent.java index 94d956f58..1280e86e7 100644 --- a/src/main/java/org/asteriskjava/manager/event/RegistryEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RegistryEntryEvent.java @@ -25,13 +25,12 @@ * @version $Id$ * @since 1.0.0 */ -public class RegistryEntryEvent extends ResponseEvent -{ +public class RegistryEntryEvent extends ResponseEvent { /** - * - */ - private static final long serialVersionUID = -7158046719541054868L; - private Integer port; + * + */ + private static final long serialVersionUID = -7158046719541054868L; + private Integer port; private String username; private String state; private Integer refresh; @@ -43,8 +42,7 @@ public class RegistryEntryEvent extends ResponseEvent * * @param source */ - public RegistryEntryEvent(Object source) - { + public RegistryEntryEvent(Object source) { super(source); } @@ -53,8 +51,7 @@ public RegistryEntryEvent(Object source) * * @return epoch since the last registration. */ - public Long getRegistrationTime() - { + public Long getRegistrationTime() { return registrationTime; } @@ -64,8 +61,7 @@ public Long getRegistrationTime() * * @param registrationTime the epoch of the last registration. */ - public void setRegistrationTime(String registrationTime) - { + public void setRegistrationTime(String registrationTime) { this.registrationTime = Long.valueOf(registrationTime); } @@ -74,8 +70,7 @@ public void setRegistrationTime(String registrationTime) * * @return the port number. */ - public Integer getPort() - { + public Integer getPort() { return port; } @@ -84,8 +79,7 @@ public Integer getPort() * * @param port the port number. */ - public void setPort(Integer port) - { + public void setPort(Integer port) { this.port = port; } @@ -94,8 +88,7 @@ public void setPort(Integer port) * * @return the username. */ - public String getUsername() - { + public String getUsername() { return username; } @@ -104,8 +97,7 @@ public String getUsername() * * @param username the username. */ - public void setUsername(String username) - { + public void setUsername(String username) { this.username = username; } @@ -114,8 +106,7 @@ public void setUsername(String username) * * @return the IP address or the hostname. */ - public String getHost() - { + public String getHost() { return host; } @@ -124,8 +115,7 @@ public String getHost() * * @param host IP address or hostname. */ - public void setHost(String host) - { + public void setHost(String host) { this.host = host; } @@ -134,8 +124,7 @@ public void setHost(String host) * * @return the value of state */ - public String getState() - { + public String getState() { return state; } @@ -144,8 +133,7 @@ public String getState() * * @param state new value of state */ - public void setState(String state) - { + public void setState(String state) { this.state = state; } @@ -154,8 +142,7 @@ public void setState(String state) * * @return the value of refresh. */ - public Integer getRefresh() - { + public Integer getRefresh() { return refresh; } @@ -164,8 +151,7 @@ public Integer getRefresh() * * @param refresh new value of refresh */ - public void setRefresh(Integer refresh) - { + public void setRefresh(Integer refresh) { this.refresh = refresh; } } diff --git a/src/main/java/org/asteriskjava/manager/event/RegistryEvent.java b/src/main/java/org/asteriskjava/manager/event/RegistryEvent.java index 2f5e86063..28ad6ca80 100644 --- a/src/main/java/org/asteriskjava/manager/event/RegistryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RegistryEvent.java @@ -25,8 +25,7 @@ * @author srt * @version $Id$ */ -public class RegistryEvent extends ManagerEvent -{ +public class RegistryEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -50,8 +49,7 @@ public class RegistryEvent extends ManagerEvent /** * @param source */ - public RegistryEvent(Object source) - { + public RegistryEvent(Object source) { super(source); } @@ -62,8 +60,7 @@ public RegistryEvent(Object source) * @return the type of channel that is registered. * @since 1.0.0 */ - public String getChannelType() - { + public String getChannelType() { return channelType; } @@ -73,8 +70,7 @@ public String getChannelType() * @param channelType the type of channel that is registered. * @since 1.0.0 */ - public void setChannelType(String channelType) - { + public void setChannelType(String channelType) { this.channelType = channelType; } @@ -86,8 +82,8 @@ public void setChannelType(String channelType) * @since 0.3 * @deprecated */ - @Deprecated public String getChannelDriver() - { + @Deprecated + public String getChannelDriver() { return channelType; } @@ -98,8 +94,8 @@ public void setChannelType(String channelType) * @since 0.3 * @deprecated */ - @Deprecated public void setChannelDriver(String channelDriver) - { + @Deprecated + public void setChannelDriver(String channelDriver) { this.channelType = channelDriver; } @@ -110,8 +106,8 @@ public void setChannelType(String channelType) * @see #getChannelType() * @deprecated */ - @Deprecated public String getChannel() - { + @Deprecated + public String getChannel() { return channelType; } @@ -121,8 +117,8 @@ public void setChannelType(String channelType) * @see #setChannelType(String) * @deprecated */ - @Deprecated public void setChannel(String channel) - { + @Deprecated + public void setChannel(String channel) { this.channelType = channel; } @@ -133,8 +129,7 @@ public void setChannelType(String channelType) * * @return the domain or host name of the SIP or IAX2 server. */ - public String getDomain() - { + public String getDomain() { return domain; } @@ -143,8 +138,7 @@ public String getDomain() * * @param domain the domain or host name of the SIP or IAX2 server. */ - public void setDomain(String domain) - { + public void setDomain(String domain) { this.domain = domain; } @@ -155,8 +149,7 @@ public void setDomain(String domain) * * @return the username used for registration. */ - public String getUsername() - { + public String getUsername() { return username; } @@ -165,8 +158,7 @@ public String getUsername() * * @param username the username used for registration. */ - public void setUsername(String username) - { + public void setUsername(String username) { this.username = username; } @@ -175,10 +167,10 @@ public void setUsername(String username) * * @see #setUsername(String) * @deprecated Please do not use this method it is a workaround for Asterisk - * 1.0.x servers. See Asterisk bug 4916. + * 1.0.x servers. See Asterisk bug 4916. */ - @Deprecated public void setUser(String username) - { + @Deprecated + public void setUser(String username) { this.username = username; } @@ -204,8 +196,7 @@ public void setUsername(String username) * * @return the registration state. */ - public String getStatus() - { + public String getStatus() { return status; } @@ -214,8 +205,7 @@ public String getStatus() * * @param status the registration state. */ - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } @@ -225,8 +215,7 @@ public void setStatus(String status) * @return the cause of a rejected registration or null if the cause is unknown. * @since 0.2 */ - public String getCause() - { + public String getCause() { return cause; } @@ -236,8 +225,7 @@ public String getCause() * @param cause the cause of a rejected registration. * @since 0.2 */ - public void setCause(String cause) - { + public void setCause(String cause) { this.cause = cause; } diff --git a/src/main/java/org/asteriskjava/manager/event/ReloadEvent.java b/src/main/java/org/asteriskjava/manager/event/ReloadEvent.java index 83a931c3b..6bc8f6824 100644 --- a/src/main/java/org/asteriskjava/manager/event/ReloadEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ReloadEvent.java @@ -24,8 +24,7 @@ * @author srt * @version $Id$ */ -public class ReloadEvent extends ManagerEvent -{ +public class ReloadEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -44,8 +43,7 @@ public class ReloadEvent extends ManagerEvent private String status; private String message; - public ReloadEvent(Object source) - { + public ReloadEvent(Object source) { super(source); } @@ -56,8 +54,7 @@ public ReloadEvent(Object source) * @return the name of the module that has been reloaded. * @since 1.0.0 */ - public String getModule() - { + public String getModule() { return module; } @@ -67,8 +64,7 @@ public String getModule() * @param module the name of the module that has been reloaded. * @since 1.0.0 */ - public void setModule(String module) - { + public void setModule(String module) { this.module = module; } @@ -77,14 +73,13 @@ public void setModule(String module) * Available since Asterisk 1.6. * * @return "Enabled" if the module is endabled, "Disabled" if it is disabled. - * @since 1.0.0 * @see #STATUS_ENABLED * @see #STATUS_DISABLED * @see #isEnabled() * @see #isDisabled() + * @since 1.0.0 */ - public String getStatus() - { + public String getStatus() { return status; } @@ -94,18 +89,15 @@ public String getStatus() * @param status "Enabled" if the module is endabled, "Disabled" if it is disabled. * @since 1.0.0 */ - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } - public String getMessage() - { + public String getMessage() { return message; } - public void setMessage(String message) - { + public void setMessage(String message) { this.message = message; } @@ -114,12 +106,11 @@ public void setMessage(String message) * Available since Asterisk 1.6. * * @return true the module is now enabled, false if it is disabled. - * For Asterisk versions up to 1.4 that do not support the "Status" property false is returned. + * For Asterisk versions up to 1.4 that do not support the "Status" property false is returned. * @see #getStatus() * @since 1.0.0 */ - public boolean isEnabled() - { + public boolean isEnabled() { return STATUS_ENABLED.equalsIgnoreCase(status); } @@ -128,12 +119,11 @@ public boolean isEnabled() * Available since Asterisk 1.6. * * @return true the module is now disabled, false if it is enabled. - * For Asterisk versions up to 1.4 that do not support the "Status" property false is returned. + * For Asterisk versions up to 1.4 that do not support the "Status" property false is returned. * @see #getStatus() * @since 1.0.0 */ - public boolean isDisabled() - { + public boolean isDisabled() { return STATUS_DISABLED.equalsIgnoreCase(status); } } diff --git a/src/main/java/org/asteriskjava/manager/event/RenameEvent.java b/src/main/java/org/asteriskjava/manager/event/RenameEvent.java index 9ea5c8cec..6bab2bfc9 100644 --- a/src/main/java/org/asteriskjava/manager/event/RenameEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RenameEvent.java @@ -20,12 +20,11 @@ * A RenameEvent is triggered when the name of a channel is changed. *

    * It is implemented in channel.c - * + * * @author srt * @version $Id$ */ -public class RenameEvent extends ManagerEvent -{ +public class RenameEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -51,28 +50,25 @@ public class RenameEvent extends ManagerEvent */ protected String uniqueId; - public RenameEvent(Object source) - { + public RenameEvent(Object source) { super(source); } /** * Returns the new name of the channel. - * + * * @return the new name of the channel. */ - public final String getNewname() - { + public final String getNewname() { return newname; } /** * Sets the new name of the channel. - * + * * @param newname the new name of the channel. */ - public final void setNewname(final String newname) - { + public final void setNewname(final String newname) { this.newname = newname; } @@ -82,8 +78,7 @@ public final void setNewname(final String newname) * @return the old name of the channel. * @since 1.0.0 */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -94,19 +89,18 @@ public String getChannel() * @param channel the old name of the channel. * @since 1.0.0 */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the old name of the channel. - * + * * @return the old name of the channel. * @deprecated use {@link #getChannel} instead. */ - @Deprecated public final String getOldname() - { + @Deprecated + public final String getOldname() { return channel; } @@ -114,31 +108,28 @@ public void setChannel(String channel) * Sets the old name of the channel.

    * The "Oldchannel" property is used by Asterisk up to 1.4 and has been renamed to "Channel" * as of Asterisk 1.6. - * + * * @param oldname the old name of the channel. */ - public final void setOldname(final String oldname) - { + public final void setOldname(final String oldname) { this.channel = oldname; } /** * Returns the unique id of the channel. - * + * * @return the unique id of the channel. */ - public final String getUniqueId() - { + public final String getUniqueId() { return uniqueId; } /** * Sets the unique id of the channel. - * + * * @param uniqueId the unique id of the channel. */ - public final void setUniqueId(final String uniqueId) - { + public final void setUniqueId(final String uniqueId) { this.uniqueId = uniqueId; } @@ -149,12 +140,11 @@ public final void setUniqueId(final String uniqueId) *

    * The purpose of this property is unclear as the unique id is supposed to * never change. - * + * * @return the new unique id of the channel. * @since 0.3 */ - public final String getNewUniqueId() - { + public final String getNewUniqueId() { return newUniqueId; } @@ -165,12 +155,11 @@ public final String getNewUniqueId() *

    * The purpose of this property is unclear as the unique id is supposed to * never change. - * + * * @param newUniqueId the new unique id of the channel. * @since 0.3 */ - public final void setNewUniqueId(final String newUniqueId) - { + public final void setNewUniqueId(final String newUniqueId) { this.newUniqueId = newUniqueId; } } diff --git a/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java b/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java index 8f8b0072c..cd2f96ce5 100644 --- a/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java @@ -6,112 +6,112 @@ public class RequestBadFormatEvent extends ManagerEvent { - /** - * Serializable version identifier. - */ - private final static long serialVersionUID = 12534663L; + /** + * Serializable version identifier. + */ + private final static long serialVersionUID = 12534663L; - private String severity; + private String severity; - private Integer eventversion; + private Integer eventversion; - private String sessiontv; + private String sessiontv; - private String eventtv; + private String eventtv; - private String sessionid; + private String sessionid; - private String localaddress; + private String localaddress; - private String accountid; + private String accountid; - private String requesttype; + private String requesttype; - private String service; + private String service; - private String remoteaddress; + private String remoteaddress; - public RequestBadFormatEvent(Object source) { - super(source); - } + public RequestBadFormatEvent(Object source) { + super(source); + } - public String getSeverity() { - return severity; - } + public String getSeverity() { + return severity; + } - public void setSeverity(String severity) { - this.severity = severity; - } + public void setSeverity(String severity) { + this.severity = severity; + } - public Integer getEventversion() { - return eventversion; - } + public Integer getEventversion() { + return eventversion; + } - public void setEventversion(Integer eventversion) { - this.eventversion = eventversion; - } + public void setEventversion(Integer eventversion) { + this.eventversion = eventversion; + } - public String getSessiontv() { - return sessiontv; - } + public String getSessiontv() { + return sessiontv; + } - public void setSessiontv(String sessiontv) { - this.sessiontv = sessiontv; - } + public void setSessiontv(String sessiontv) { + this.sessiontv = sessiontv; + } - public String getEventtv() { - return eventtv; - } + public String getEventtv() { + return eventtv; + } - public void setEventtv(String eventtv) { - this.eventtv = eventtv; - } + public void setEventtv(String eventtv) { + this.eventtv = eventtv; + } - public String getSessionid() { - return sessionid; - } + public String getSessionid() { + return sessionid; + } - public void setSessionid(String sessionid) { - this.sessionid = sessionid; - } + public void setSessionid(String sessionid) { + this.sessionid = sessionid; + } - public String getLocaladdress() { - return localaddress; - } + public String getLocaladdress() { + return localaddress; + } - public void setLocaladdress(String localaddress) { - this.localaddress = localaddress; - } + public void setLocaladdress(String localaddress) { + this.localaddress = localaddress; + } - public String getAccountid() { - return accountid; - } + public String getAccountid() { + return accountid; + } - public void setAccountid(String accountid) { - this.accountid = accountid; - } + public void setAccountid(String accountid) { + this.accountid = accountid; + } - public String getRequesttype() { - return requesttype; - } + public String getRequesttype() { + return requesttype; + } - public void setRequesttype(String requesttype) { - this.requesttype = requesttype; - } + public void setRequesttype(String requesttype) { + this.requesttype = requesttype; + } - public String getService() { - return service; - } + public String getService() { + return service; + } - public void setService(String service) { - this.service = service; - } + public void setService(String service) { + this.service = service; + } - public String getRemoteaddress() { - return remoteaddress; - } + public String getRemoteaddress() { + return remoteaddress; + } - public void setRemoteaddress(String remoteaddress) { - this.remoteaddress = remoteaddress; - } + public void setRemoteaddress(String remoteaddress) { + this.remoteaddress = remoteaddress; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/ResponseEvent.java b/src/main/java/org/asteriskjava/manager/event/ResponseEvent.java index 13184eaa7..cd7f1312a 100644 --- a/src/main/java/org/asteriskjava/manager/event/ResponseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ResponseEvent.java @@ -26,14 +26,12 @@ * @version $Id$ * @see org.asteriskjava.manager.action.ManagerAction */ -public abstract class ResponseEvent extends ManagerEvent -{ +public abstract class ResponseEvent extends ManagerEvent { private static final long serialVersionUID = 1L; protected String actionId; private String internalActionId; - public ResponseEvent(Object source) - { + public ResponseEvent(Object source) { super(source); } @@ -43,11 +41,10 @@ public ResponseEvent(Object source) * null. * * @return the action id of the ManagerAction that caused this event or - * null if none was set. + * null if none was set. * @see org.asteriskjava.manager.action.ManagerAction#setActionId(String) */ - public final String getActionId() - { + public final String getActionId() { return actionId; } @@ -55,10 +52,9 @@ public final String getActionId() * Sets the action id of the ManagerAction that caused this event. * * @param actionId the action id of the ManagerAction that caused this - * event. + * event. */ - public final void setActionId(String actionId) - { + public final void setActionId(String actionId) { this.actionId = actionId; } @@ -70,11 +66,10 @@ public final void setActionId(String actionId) * used in application code. * * @return the internal action id of the ManagerAction that caused this - * event. + * event. * @since 0.2 */ - public final String getInternalActionId() - { + public final String getInternalActionId() { return internalActionId; } @@ -82,11 +77,10 @@ public final String getInternalActionId() * Sets the internal action id of the ManagerAction that caused this event. * * @param internalActionId the internal action id of the ManagerAction that - * caused this event. + * caused this event. * @since 0.2 */ - public final void setInternalActionId(String internalActionId) - { + public final void setInternalActionId(String internalActionId) { this.internalActionId = internalActionId; } } diff --git a/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java b/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java index c5d9682c0..b0f3dcc37 100644 --- a/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java @@ -27,8 +27,7 @@ * @version $Id$ * @since 1.0.0 */ -public class RtcpReceivedEvent extends AbstractRtcpEvent -{ +public class RtcpReceivedEvent extends AbstractRtcpEvent { private static final long serialVersionUID = 2L; /** @@ -52,9 +51,9 @@ public class RtcpReceivedEvent extends AbstractRtcpEvent private Long sequenceNumberCycles; private Double lastSr; private Double rtt; - + private String channel; - private String language; + private String language; private String report0SequenceNumberCycles; private String ssrc; private String linkedId; @@ -74,10 +73,9 @@ public class RtcpReceivedEvent extends AbstractRtcpEvent private Long sentPackets; private Long sentrtp; private String accountCode; - - public RtcpReceivedEvent(Object source) - { + + public RtcpReceivedEvent(Object source) { super(source); } @@ -86,8 +84,7 @@ public RtcpReceivedEvent(Object source) * * @return the IP address the RTCP message has been received from. */ - public InetAddress getFromAddress() - { + public InetAddress getFromAddress() { return fromAddress; } @@ -96,13 +93,11 @@ public InetAddress getFromAddress() * * @return the port of the RTCP message has been received from. */ - public Integer getFromPort() - { + public Integer getFromPort() { return fromPort; } - public void setFrom(String from) - { + public void setFrom(String from) { // Format is "%s:%d" this.fromAddress = stringToAddress(from); this.fromPort = stringToPort(from); @@ -113,18 +108,16 @@ public void setFrom(String from) * * @return the port the RTCP message has been sent to. */ - public Integer getToPort() - { + public Integer getToPort() { return toPort; } - public void setTo(String to) - { + public void setTo(String to) { // Format is "%s:%d" this.toAddress = stringToAddress(to); this.toPort = stringToPort(to); } - + /** * Indicates the format of the payload, typical values are 200 for sender reports and * 201 for receiver reports. @@ -133,44 +126,34 @@ public void setTo(String to) * @see #PT_SENDER_REPORT * @see #PT_RECEIVER_REPORT */ - public Long getPt() - { + public Long getPt() { return pt; } - public void setPt(String ptString) - { + public void setPt(String ptString) { // Format is "PT: %d(%s)" - if (ptString == null || ptString.length() == 0) - { + if (ptString == null || ptString.length() == 0) { this.pt = null; return; } - try - { - if (ptString.indexOf('(') > 0) - { + try { + if (ptString.indexOf('(') > 0) { this.pt = Long.parseLong(ptString.substring(0, ptString.indexOf('('))); - } - else - { + } else { this.pt = Long.parseLong(ptString); } - } catch (NumberFormatException e) - { + } catch (NumberFormatException e) { throw new NumberFormatException(String.format("Input string [%s] is not a parsable long", ptString)); } } - public Long getReceptionReports() - { + public Long getReceptionReports() { return receptionReports; } - public void setReceptionReports(Long receptionReports) - { + public void setReceptionReports(Long receptionReports) { this.receptionReports = receptionReports; } @@ -179,13 +162,11 @@ public void setReceptionReports(Long receptionReports) * * @return the synchronization source identifier of the sender. */ - public Long getSenderSsrc() - { + public Long getSenderSsrc() { return senderSsrc; } - public void setSenderSsrc(Long senderSsrc) - { + public void setSenderSsrc(Long senderSsrc) { this.senderSsrc = senderSsrc; } @@ -194,43 +175,35 @@ public void setSenderSsrc(Long senderSsrc) * * @return the number of packets lost. */ - public Long getPacketsLost() - { + public Long getPacketsLost() { return packetsLost; } - public void setPacketsLost(Long packetsLost) - { + public void setPacketsLost(Long packetsLost) { this.packetsLost = packetsLost; } - public Long getHighestSequence() - { + public Long getHighestSequence() { return highestSequence; } - public void setHighestSequence(Long highestSequence) - { + public void setHighestSequence(Long highestSequence) { this.highestSequence = highestSequence; } - public Long getSequenceNumberCycles() - { + public Long getSequenceNumberCycles() { return sequenceNumberCycles; } - public void setSequenceNumberCycles(Long sequenceNumberCycles) - { + public void setSequenceNumberCycles(Long sequenceNumberCycles) { this.sequenceNumberCycles = sequenceNumberCycles; } - public Double getLastSr() - { + public Double getLastSr() { return lastSr; } - public void setLastSr(Double lastSr) - { + public void setLastSr(Double lastSr) { this.lastSr = lastSr; } @@ -239,216 +212,173 @@ public void setLastSr(Double lastSr) * * @return the round trip time in seconds, may be null. */ - public Double getRtt() - { + public Double getRtt() { return rtt; } - public void setRtt(String rttString) - { + public void setRtt(String rttString) { this.rtt = secStringToDouble(rttString); } - - public Long getRttAsMillseconds() - { - return (long) (rtt * 1000); + + public Long getRttAsMillseconds() { + return (long) (rtt * 1000); } - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getReport0SequenceNumberCycles() - { + public String getReport0SequenceNumberCycles() { return report0SequenceNumberCycles; } - public void setReport0SequenceNumberCycles(String report0SequenceNumberCycles) - { + public void setReport0SequenceNumberCycles(String report0SequenceNumberCycles) { this.report0SequenceNumberCycles = report0SequenceNumberCycles; } - public String getSsrc() - { + public String getSsrc() { return ssrc; } - public void setSsrc(String ssrc) - { + public void setSsrc(String ssrc) { this.ssrc = ssrc; } - public String getReport0lsr() - { + public String getReport0lsr() { return report0lsr; } - public void setReport0lsr(String report0lsr) - { + public void setReport0lsr(String report0lsr) { this.report0lsr = report0lsr; } - public Long getSentOctets() - { + public Long getSentOctets() { return sentOctets; } - public void setSentOctets(Long sentOctets) - { + public void setSentOctets(Long sentOctets) { this.sentOctets = sentOctets; } - public String getReport0Sourcessrc() - { + public String getReport0Sourcessrc() { return report0Sourcessrc; } - public void setReport0Sourcessrc(String report0Sourcessrc) - { + public void setReport0Sourcessrc(String report0Sourcessrc) { this.report0Sourcessrc = report0Sourcessrc; } - public Double getReport0dlsr() - { + public Double getReport0dlsr() { return report0dlsr; } - public void setReport0dlsr(Double report0dlsr) - { + public void setReport0dlsr(Double report0dlsr) { this.report0dlsr = report0dlsr; } - public String getUniqueid() - { + public String getUniqueid() { return uniqueid; } - public void setUniqueid(String uniqueid) - { + public void setUniqueid(String uniqueid) { this.uniqueid = uniqueid; } - public Integer getReport0CumulativeLost() - { + public Integer getReport0CumulativeLost() { return report0CumulativeLost; } - public void setReport0CumulativeLost(Integer report0CumulativeLost) - { + public void setReport0CumulativeLost(Integer report0CumulativeLost) { this.report0CumulativeLost = report0CumulativeLost; } - public Integer getReport0FractionLost() - { + public Integer getReport0FractionLost() { return report0FractionLost; } - public void setReport0FractionLost(Integer report0FractionLost) - { + public void setReport0FractionLost(Integer report0FractionLost) { this.report0FractionLost = report0FractionLost; } - public Long getReport0iaJitter() - { + public Long getReport0iaJitter() { return report0iaJitter; } - public void setReport0iaJitter(Long report0iaJitter) - { + public void setReport0iaJitter(Long report0iaJitter) { this.report0iaJitter = report0iaJitter; } - public InetAddress getToAddress() - { + public InetAddress getToAddress() { return toAddress; } - public String getSentntp() - { + public String getSentntp() { return sentntp; } - public void setSentntp(String sentntp) - { + public void setSentntp(String sentntp) { this.sentntp = sentntp; } - public Long getSentrtp() - { + public Long getSentrtp() { return sentrtp; } - public void setSentrtp(Long sentrtp) - { + public void setSentrtp(Long sentrtp) { this.sentrtp = sentrtp; } - public Integer getReportCount() - { + public Integer getReportCount() { return reportCount; } - public void setReportCount(Integer reportCount) - { + public void setReportCount(Integer reportCount) { this.reportCount = reportCount; } - public Integer getReport0HighestSequence() - { + public Integer getReport0HighestSequence() { return report0HighestSequence; } - public void setReport0HighestSequence(Integer report0HighestSequence) - { + public void setReport0HighestSequence(Integer report0HighestSequence) { this.report0HighestSequence = report0HighestSequence; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public Long getSentPackets() - { + public Long getSentPackets() { return sentPackets; } - public void setSentPackets(Long sentPackets) - { + public void setSentPackets(Long sentPackets) { this.sentPackets = sentPackets; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - - - + + } diff --git a/src/main/java/org/asteriskjava/manager/event/RtcpSentEvent.java b/src/main/java/org/asteriskjava/manager/event/RtcpSentEvent.java index e556ce733..ba130793d 100644 --- a/src/main/java/org/asteriskjava/manager/event/RtcpSentEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RtcpSentEvent.java @@ -27,8 +27,7 @@ * @version $Id$ * @since 1.0.0 */ -public class RtcpSentEvent extends AbstractRtcpEvent -{ +public class RtcpSentEvent extends AbstractRtcpEvent { private static final long serialVersionUID = 1L; private InetAddress fromAddress; @@ -59,9 +58,8 @@ public class RtcpSentEvent extends AbstractRtcpEvent private Integer report0iaJitter; private Integer report0HighestSequence; private String accountCode; - - public RtcpSentEvent(Object source) - { + + public RtcpSentEvent(Object source) { super(source); } @@ -70,8 +68,7 @@ public RtcpSentEvent(Object source) * * @return the IP address the RTCP message has been received from. */ - public InetAddress getFromAddress() - { + public InetAddress getFromAddress() { return fromAddress; } @@ -80,13 +77,11 @@ public InetAddress getFromAddress() * * @return the port of the RTCP message has been received from. */ - public Integer getFromPort() - { + public Integer getFromPort() { return fromPort; } - public void setFrom(String from) - { + public void setFrom(String from) { // Format is "%s:%d" this.fromAddress = stringToAddress(from); this.fromPort = stringToPort(from); @@ -100,38 +95,31 @@ public void setFrom(String from) * @see #RtcpReceivedEvent.PT_SENDER_REPORT * @see #RtcpReceivedEvent.PT_RECEIVER_REPORT */ - public Long getPt() - { + public Long getPt() { return pt; } - public void setPt(String ptString) - { + public void setPt(String ptString) { // Format is "PT: %d(%s)" - if (ptString == null || ptString.length() == 0) - { + if (ptString == null || ptString.length() == 0) { this.pt = null; return; } - if (ptString.indexOf('(') > 0) - { + if (ptString.indexOf('(') > 0) { this.pt = Long.parseLong(ptString.substring(0, ptString.indexOf('('))); - } - else - { + } else { this.pt = Long.parseLong(ptString); } } - - + + /** * Returns the IP address the RTCP message has been sent to. * * @return the IP address the RTCP message has been sent to. */ - public InetAddress getToAddress() - { + public InetAddress getToAddress() { return toAddress; } @@ -140,13 +128,11 @@ public InetAddress getToAddress() * * @return the port the RTCP message has been sent to. */ - public Integer getToPort() - { + public Integer getToPort() { return toPort; } - public void setTo(String to) - { + public void setTo(String to) { // Format is "%s:%d" this.toAddress = stringToAddress(to); this.toPort = stringToPort(to); @@ -154,35 +140,30 @@ public void setTo(String to) /** * Returns our synchronization source identifier that uniquely identifies the source of a stream. + * * @return our synchronization source identifier. */ - public Long getOurSsrc() - { + public Long getOurSsrc() { return ourSsrc; } - public void setOurSsrc(Long ourSsrc) - { + public void setOurSsrc(Long ourSsrc) { this.ourSsrc = ourSsrc; } - public Double getSentNtp() - { + public Double getSentNtp() { return sentNtp; } - public void setSentNtp(Double sentNtp) - { + public void setSentNtp(Double sentNtp) { this.sentNtp = sentNtp; } - public Long getSentRtp() - { + public Long getSentRtp() { return sentRtp; } - public void setSentRtp(Long sentRtp) - { + public void setSentRtp(Long sentRtp) { this.sentRtp = sentRtp; } @@ -191,13 +172,11 @@ public void setSentRtp(Long sentRtp) * * @return the number of packets sent. */ - public Long getSentPackets() - { + public Long getSentPackets() { return sentPackets; } - public void setSentPackets(Long sentPackets) - { + public void setSentPackets(Long sentPackets) { this.sentPackets = sentPackets; } @@ -206,183 +185,147 @@ public void setSentPackets(Long sentPackets) * * @return the number of octets (bytes) sent. */ - public Long getSentOctets() - { + public Long getSentOctets() { return sentOctets; } - public void setSentOctets(Long sentOctets) - { + public void setSentOctets(Long sentOctets) { this.sentOctets = sentOctets; } - public Long getCumulativeLoss() - { + public Long getCumulativeLoss() { return cumulativeLoss; } - public void setCumulativeLoss(Long cumulativeLoss) - { + public void setCumulativeLoss(Long cumulativeLoss) { this.cumulativeLoss = cumulativeLoss; } - public Long getTheirLastSr() - { + public Long getTheirLastSr() { return theirLastSr; } - public void setTheirLastSr(Long theirLastSr) - { + public void setTheirLastSr(Long theirLastSr) { this.theirLastSr = theirLastSr; } - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getReport0SequenceNumberCycles() - { + public String getReport0SequenceNumberCycles() { return report0SequenceNumberCycles; } - public void setReport0SequenceNumberCycles(String report0SequenceNumberCycles) - { + public void setReport0SequenceNumberCycles(String report0SequenceNumberCycles) { this.report0SequenceNumberCycles = report0SequenceNumberCycles; } - public String getSsrc() - { + public String getSsrc() { return ssrc; } - public void setSsrc(String ssrc) - { + public void setSsrc(String ssrc) { this.ssrc = ssrc; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getReport0lsr() - { + public String getReport0lsr() { return report0lsr; } - public void setReport0lsr(String report0lsr) - { + public void setReport0lsr(String report0lsr) { this.report0lsr = report0lsr; } - public String getReport0Sourcessrc() - { + public String getReport0Sourcessrc() { return report0Sourcessrc; } - public void setReport0Sourcessrc(String report0Sourcessrc) - { + public void setReport0Sourcessrc(String report0Sourcessrc) { this.report0Sourcessrc = report0Sourcessrc; } - public Double getReport0dlsr() - { + public Double getReport0dlsr() { return report0dlsr; } - public void setReport0dlsr(Double report0dlsr) - { + public void setReport0dlsr(Double report0dlsr) { this.report0dlsr = report0dlsr; } - public String getUniqueid() - { + public String getUniqueid() { return uniqueid; } - public void setUniqueid(String uniqueid) - { + public void setUniqueid(String uniqueid) { this.uniqueid = uniqueid; } - public Integer getReportCount() - { + public Integer getReportCount() { return reportCount; } - public void setReportCount(Integer reportCount) - { + public void setReportCount(Integer reportCount) { this.reportCount = reportCount; } - public Integer getReport0CumulativeLost() - { + public Integer getReport0CumulativeLost() { return report0CumulativeLost; } - public void setReport0CumulativeLost(Integer report0CumulativeLost) - { + public void setReport0CumulativeLost(Integer report0CumulativeLost) { this.report0CumulativeLost = report0CumulativeLost; } - public Integer getReport0FractionLost() - { + public Integer getReport0FractionLost() { return report0FractionLost; } - public void setReport0FractionLost(Integer report0FractionLost) - { + public void setReport0FractionLost(Integer report0FractionLost) { this.report0FractionLost = report0FractionLost; } - public Integer getReport0iaJitter() - { + public Integer getReport0iaJitter() { return report0iaJitter; } - public void setReport0iaJitter(Integer report0iaJitter) - { + public void setReport0iaJitter(Integer report0iaJitter) { this.report0iaJitter = report0iaJitter; } - public Integer getReport0HighestSequence() - { + public Integer getReport0HighestSequence() { return report0HighestSequence; } - public void setReport0HighestSequence(Integer report0HighestSequence) - { + public void setReport0HighestSequence(Integer report0HighestSequence) { this.report0HighestSequence = report0HighestSequence; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/RtpReceiverStatEvent.java b/src/main/java/org/asteriskjava/manager/event/RtpReceiverStatEvent.java index 49416cc88..e31aeab88 100644 --- a/src/main/java/org/asteriskjava/manager/event/RtpReceiverStatEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RtpReceiverStatEvent.java @@ -26,8 +26,7 @@ * @version $Id$ * @since 1.0.0 */ -public class RtpReceiverStatEvent extends AbstractRtpStatEvent -{ +public class RtpReceiverStatEvent extends AbstractRtpStatEvent { private static final long serialVersionUID = 1L; private Long receivedPackets; @@ -35,8 +34,7 @@ public class RtpReceiverStatEvent extends AbstractRtpStatEvent private Long rrCount; private String accountCode; - public RtpReceiverStatEvent(Object source) - { + public RtpReceiverStatEvent(Object source) { super(source); } @@ -45,23 +43,19 @@ public RtpReceiverStatEvent(Object source) * * @return the number of packets received. */ - public Long getReceivedPackets() - { + public Long getReceivedPackets() { return receivedPackets; } - public void setReceivedPackets(Long receivedPackets) - { + public void setReceivedPackets(Long receivedPackets) { this.receivedPackets = receivedPackets; } - public Double getTransit() - { + public Double getTransit() { return transit; } - public void setTransit(Double transit) - { + public void setTransit(Double transit) { this.transit = transit; } @@ -70,25 +64,21 @@ public void setTransit(Double transit) * * @return the number of receiver reports. */ - public Long getRrCount() - { + public Long getRrCount() { return rrCount; } - public void setRrCount(Long rrCount) - { + public void setRrCount(Long rrCount) { this.rrCount = rrCount; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - - -} \ No newline at end of file + + +} diff --git a/src/main/java/org/asteriskjava/manager/event/RtpSenderStatEvent.java b/src/main/java/org/asteriskjava/manager/event/RtpSenderStatEvent.java index 793beeb69..7beff21a9 100644 --- a/src/main/java/org/asteriskjava/manager/event/RtpSenderStatEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RtpSenderStatEvent.java @@ -26,16 +26,14 @@ * @version $Id$ * @since 1.0.0 */ -public class RtpSenderStatEvent extends AbstractRtpStatEvent -{ +public class RtpSenderStatEvent extends AbstractRtpStatEvent { private static final long serialVersionUID = 1L; private Long sentPackets; private Long srCount; private Double rtt; - public RtpSenderStatEvent(Object source) - { + public RtpSenderStatEvent(Object source) { super(source); } @@ -44,13 +42,11 @@ public RtpSenderStatEvent(Object source) * * @return the number of packets sent. */ - public Long getSentPackets() - { + public Long getSentPackets() { return sentPackets; } - public void setSentPackets(Long sentPackets) - { + public void setSentPackets(Long sentPackets) { this.sentPackets = sentPackets; } @@ -59,23 +55,19 @@ public void setSentPackets(Long sentPackets) * * @return the number of sender reports. */ - public Long getSrCount() - { + public Long getSrCount() { return srCount; } - public void setSrCount(Long srCount) - { + public void setSrCount(Long srCount) { this.srCount = srCount; } - public Double getRtt() - { + public Double getRtt() { return rtt; } - public void setRtt(Double rtt) - { + public void setRtt(Double rtt) { this.rtt = rtt; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/SendFaxEvent.java b/src/main/java/org/asteriskjava/manager/event/SendFaxEvent.java index 1f6ae5ae0..6398df053 100644 --- a/src/main/java/org/asteriskjava/manager/event/SendFaxEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SendFaxEvent.java @@ -19,8 +19,7 @@ /** * A SendFaxEvent is an event of Digium's Fax For Asterisk add-on. */ -public class SendFaxEvent extends AbstractFaxEvent -{ +public class SendFaxEvent extends AbstractFaxEvent { /** * Serial version identifier. */ @@ -34,8 +33,7 @@ public class SendFaxEvent extends AbstractFaxEvent private String fileName; - public SendFaxEvent(Object source) - { + public SendFaxEvent(Object source) { super(source); } @@ -43,8 +41,7 @@ public SendFaxEvent(Object source) /** * @return the callerId */ - public String getCallerId() - { + public String getCallerId() { return callerId; } @@ -52,8 +49,7 @@ public String getCallerId() /** * @param callerId the callerId to set */ - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { this.callerId = callerId; } @@ -61,8 +57,7 @@ public void setCallerId(String callerId) /** * @return the localStationId */ - public String getLocalStationId() - { + public String getLocalStationId() { return localStationId; } @@ -70,8 +65,7 @@ public String getLocalStationId() /** * @param localStationId the localStationId to set */ - public void setLocalStationId(String localStationId) - { + public void setLocalStationId(String localStationId) { this.localStationId = localStationId; } @@ -79,8 +73,7 @@ public void setLocalStationId(String localStationId) /** * @return the remoteStationId */ - public String getRemoteStationId() - { + public String getRemoteStationId() { return remoteStationId; } @@ -88,8 +81,7 @@ public String getRemoteStationId() /** * @param remoteStationId the remoteStationId to set */ - public void setRemoteStationId(String remoteStationId) - { + public void setRemoteStationId(String remoteStationId) { this.remoteStationId = remoteStationId; } @@ -97,8 +89,7 @@ public void setRemoteStationId(String remoteStationId) /** * @return the pagesTransferred */ - public String getPagesTransferred() - { + public String getPagesTransferred() { return pagesTransferred; } @@ -106,8 +97,7 @@ public String getPagesTransferred() /** * @param pagesTransferred the pagesTransferred to set */ - public void setPagesTransferred(String pagesTransferred) - { + public void setPagesTransferred(String pagesTransferred) { this.pagesTransferred = pagesTransferred; } @@ -115,8 +105,7 @@ public void setPagesTransferred(String pagesTransferred) /** * @return the resolution */ - public String getResolution() - { + public String getResolution() { return resolution; } @@ -124,8 +113,7 @@ public String getResolution() /** * @param resolution the resolution to set */ - public void setResolution(String resolution) - { + public void setResolution(String resolution) { this.resolution = resolution; } @@ -133,8 +121,7 @@ public void setResolution(String resolution) /** * @return the transferRate */ - public String getTransferRate() - { + public String getTransferRate() { return transferRate; } @@ -142,8 +129,7 @@ public String getTransferRate() /** * @param transferRate the transferRate to set */ - public void setTransferRate(String transferRate) - { + public void setTransferRate(String transferRate) { this.transferRate = transferRate; } @@ -151,8 +137,7 @@ public void setTransferRate(String transferRate) /** * @return the fileName */ - public String getFileName() - { + public String getFileName() { return fileName; } @@ -160,8 +145,7 @@ public String getFileName() /** * @param fileName the fileName to set */ - public void setFileName(String fileName) - { + public void setFileName(String fileName) { this.fileName = fileName; } diff --git a/src/main/java/org/asteriskjava/manager/event/SendFaxStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/SendFaxStatusEvent.java index f09be6e8b..6a84f1c7b 100644 --- a/src/main/java/org/asteriskjava/manager/event/SendFaxStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SendFaxStatusEvent.java @@ -19,8 +19,7 @@ /** * A SendFaxStatusEvent is an event of Digium's Fax For Asterisk add-on. */ -public class SendFaxStatusEvent extends AbstractFaxEvent -{ +public class SendFaxStatusEvent extends AbstractFaxEvent { /** * Serial version identifier. */ @@ -31,8 +30,7 @@ public class SendFaxStatusEvent extends AbstractFaxEvent private String fileName; - public SendFaxStatusEvent(Object source) - { + public SendFaxStatusEvent(Object source) { super(source); } @@ -40,8 +38,7 @@ public SendFaxStatusEvent(Object source) /** * @return the status */ - public String getStatus() - { + public String getStatus() { return status; } @@ -49,8 +46,7 @@ public String getStatus() /** * @param status the status to set */ - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } @@ -58,8 +54,7 @@ public void setStatus(String status) /** * @return the callerId */ - public String getCallerId() - { + public String getCallerId() { return callerId; } @@ -67,8 +62,7 @@ public String getCallerId() /** * @param callerId the callerId to set */ - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { this.callerId = callerId; } @@ -76,8 +70,7 @@ public void setCallerId(String callerId) /** * @return the localStationId */ - public String getLocalStationId() - { + public String getLocalStationId() { return localStationId; } @@ -85,8 +78,7 @@ public String getLocalStationId() /** * @param localStationId the localStationId to set */ - public void setLocalStationId(String localStationId) - { + public void setLocalStationId(String localStationId) { this.localStationId = localStationId; } @@ -94,8 +86,7 @@ public void setLocalStationId(String localStationId) /** * @return the fileName */ - public String getFileName() - { + public String getFileName() { return fileName; } @@ -103,8 +94,7 @@ public String getFileName() /** * @param fileName the fileName to set */ - public void setFileName(String fileName) - { + public void setFileName(String fileName) { this.fileName = fileName; } diff --git a/src/main/java/org/asteriskjava/manager/event/ShowDialplanCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/ShowDialplanCompleteEvent.java index 26f8ae015..22a96b50a 100644 --- a/src/main/java/org/asteriskjava/manager/event/ShowDialplanCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ShowDialplanCompleteEvent.java @@ -12,8 +12,7 @@ * @see org.asteriskjava.manager.event.ListDialplanEvent * @since 1.0.0 */ -public class ShowDialplanCompleteEvent extends ResponseEvent -{ +public class ShowDialplanCompleteEvent extends ResponseEvent { private static final long serialVersionUID = 1L; private Integer listItems; @@ -21,8 +20,7 @@ public class ShowDialplanCompleteEvent extends ResponseEvent private Integer listPriorities; private Integer listContexts; - public ShowDialplanCompleteEvent(Object source) - { + public ShowDialplanCompleteEvent(Object source) { super(source); } @@ -31,13 +29,11 @@ public ShowDialplanCompleteEvent(Object source) * * @return the total number of list items reported. */ - public Integer getListItems() - { + public Integer getListItems() { return listItems; } - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } @@ -46,13 +42,11 @@ public void setListItems(Integer listItems) * * @return the number of extensions reported. */ - public Integer getListExtensions() - { + public Integer getListExtensions() { return listExtensions; } - public void setListExtensions(Integer listExtensions) - { + public void setListExtensions(Integer listExtensions) { this.listExtensions = listExtensions; } @@ -61,13 +55,11 @@ public void setListExtensions(Integer listExtensions) * * @return the number of priorites reported. */ - public Integer getListPriorities() - { + public Integer getListPriorities() { return listPriorities; } - public void setListPriorities(Integer listPriorities) - { + public void setListPriorities(Integer listPriorities) { this.listPriorities = listPriorities; } @@ -76,13 +68,11 @@ public void setListPriorities(Integer listPriorities) * * @return the number of contexts reported. */ - public Integer getListContexts() - { + public Integer getListContexts() { return listContexts; } - public void setListContexts(Integer listContexts) - { + public void setListContexts(Integer listContexts) { this.listContexts = listContexts; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/ShutdownEvent.java b/src/main/java/org/asteriskjava/manager/event/ShutdownEvent.java index fb593c2b8..46eee4d9a 100644 --- a/src/main/java/org/asteriskjava/manager/event/ShutdownEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ShutdownEvent.java @@ -23,8 +23,7 @@ * @author srt * @version $Id$ */ -public class ShutdownEvent extends ManagerEvent -{ +public class ShutdownEvent extends ManagerEvent { /** * Serial version identifier */ @@ -36,8 +35,7 @@ public class ShutdownEvent extends ManagerEvent /** * @param source */ - public ShutdownEvent(Object source) - { + public ShutdownEvent(Object source) { super(source); } @@ -45,13 +43,11 @@ public ShutdownEvent(Object source) * Returns the kind of shutdown or restart. Possible values are "Uncleanly" and "Cleanly". A * shutdown is considered unclean if there are any active channels when the system is shut down. */ - public String getShutdown() - { + public String getShutdown() { return shutdown; } - public void setShutdown(String shutdown) - { + public void setShutdown(String shutdown) { this.shutdown = shutdown; } @@ -59,13 +55,11 @@ public void setShutdown(String shutdown) * Returns true if the server has been restarted; false if it has * been halted. */ - public Boolean getRestart() - { + public Boolean getRestart() { return restart; } - public void setRestart(Boolean restart) - { + public void setRestart(Boolean restart) { this.restart = restart; } } diff --git a/src/main/java/org/asteriskjava/manager/event/SkypeAccountStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/SkypeAccountStatusEvent.java index e81b3c1d5..e433b3d19 100644 --- a/src/main/java/org/asteriskjava/manager/event/SkypeAccountStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SkypeAccountStatusEvent.java @@ -1,6 +1,6 @@ /* * Copyright 2004-2006 Stefan Reuter - * + * * amended 2010 Allan Wylie * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,8 +26,7 @@ * * @since 1.0.0 */ -public class SkypeAccountStatusEvent extends ManagerEvent -{ +public class SkypeAccountStatusEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private String username; private String status; @@ -35,8 +34,7 @@ public class SkypeAccountStatusEvent extends ManagerEvent static final String STATUS_LOGGED_IN = "Logged In"; static final String STATUS_LOGGED_OUT = "Logged Out"; - public SkypeAccountStatusEvent(Object source) - { + public SkypeAccountStatusEvent(Object source) { super(source); } @@ -45,8 +43,7 @@ public SkypeAccountStatusEvent(Object source) * * @return the name of the Skype user. */ - public String getUsername() - { + public String getUsername() { return username; } @@ -55,8 +52,7 @@ public String getUsername() * * @param username the name of the Skype user. */ - public void setUsername(String username) - { + public void setUsername(String username) { this.username = username; } @@ -65,8 +61,7 @@ public void setUsername(String username) * * @return the Skype user status. */ - public String getStatus() - { + public String getStatus() { return status; } @@ -75,8 +70,7 @@ public String getStatus() * * @param status user status. */ - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } } diff --git a/src/main/java/org/asteriskjava/manager/event/SkypeBuddyEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/SkypeBuddyEntryEvent.java index 914b2b3c4..e38826277 100644 --- a/src/main/java/org/asteriskjava/manager/event/SkypeBuddyEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SkypeBuddyEntryEvent.java @@ -25,8 +25,7 @@ * @see org.asteriskjava.manager.action.SkypeBuddiesAction * @since 1.0.0 */ -public class SkypeBuddyEntryEvent extends ResponseEvent -{ +public class SkypeBuddyEntryEvent extends ResponseEvent { /** * Serial version identifier. */ @@ -35,8 +34,7 @@ public class SkypeBuddyEntryEvent extends ResponseEvent private String status; private String fullname; - public SkypeBuddyEntryEvent(Object source) - { + public SkypeBuddyEntryEvent(Object source) { super(source); } @@ -45,8 +43,7 @@ public SkypeBuddyEntryEvent(Object source) * * @return the Skype username of the buddy. */ - public String getBuddy() - { + public String getBuddy() { return buddy; } @@ -55,8 +52,7 @@ public String getBuddy() * * @param buddy the Skype username of the buddy. */ - public void setBuddy(String buddy) - { + public void setBuddy(String buddy) { this.buddy = buddy; } @@ -65,8 +61,7 @@ public void setBuddy(String buddy) * * @return the status of the buddy. */ - public String getStatus() - { + public String getStatus() { return status; } @@ -75,8 +70,7 @@ public String getStatus() * * @param status the status of the buddy. */ - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } @@ -85,8 +79,7 @@ public void setStatus(String status) * * @return the full name of the buddy. */ - public String getFullname() - { + public String getFullname() { return fullname; } @@ -95,8 +88,7 @@ public String getFullname() * * @param fullname the full name of the buddy. */ - public void setFullname(String fullname) - { + public void setFullname(String fullname) { this.fullname = fullname; } } diff --git a/src/main/java/org/asteriskjava/manager/event/SkypeBuddyListCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/SkypeBuddyListCompleteEvent.java index d49f363b5..e960a526a 100644 --- a/src/main/java/org/asteriskjava/manager/event/SkypeBuddyListCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SkypeBuddyListCompleteEvent.java @@ -25,16 +25,14 @@ * @see org.asteriskjava.manager.action.SkypeBuddiesAction * @since 1.0.0 */ -public class SkypeBuddyListCompleteEvent extends ResponseEvent -{ +public class SkypeBuddyListCompleteEvent extends ResponseEvent { /** * Serial version identifier. */ private static final long serialVersionUID = 1L; private Integer listItems; - public SkypeBuddyListCompleteEvent(Object source) - { + public SkypeBuddyListCompleteEvent(Object source) { super(source); } @@ -43,8 +41,7 @@ public SkypeBuddyListCompleteEvent(Object source) * * @return the number of buddies that have been reported. */ - public Integer getListItems() - { + public Integer getListItems() { return listItems; } @@ -53,8 +50,7 @@ public Integer getListItems() * * @param listItems the number of buddies that have been reported. */ - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } } diff --git a/src/main/java/org/asteriskjava/manager/event/SkypeBuddyStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/SkypeBuddyStatusEvent.java index 8934d18fa..eda2121f8 100644 --- a/src/main/java/org/asteriskjava/manager/event/SkypeBuddyStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SkypeBuddyStatusEvent.java @@ -1,6 +1,6 @@ /* * Copyright 2004-2006 Stefan Reuter - * + * * amended 2010 - Allan Wylie * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,8 +29,7 @@ * * @since 1.0.0 */ -public class SkypeBuddyStatusEvent extends ManagerEvent -{ +public class SkypeBuddyStatusEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -63,8 +62,7 @@ public class SkypeBuddyStatusEvent extends ManagerEvent private String buddyStatus; - public SkypeBuddyStatusEvent(Object source) - { + public SkypeBuddyStatusEvent(Object source) { super(source); } @@ -78,8 +76,7 @@ public SkypeBuddyStatusEvent(Object source) * @see #getUser() * @see #getBuddySkypename() */ - public String getBuddy() - { + public String getBuddy() { return buddy; } @@ -88,8 +85,7 @@ public String getBuddy() * * @return the Skype username of the Skype for Asterisk user. */ - public String getUser() - { + public String getUser() { return buddyGroup(1); } @@ -98,20 +94,16 @@ public String getUser() * * @return the Skype username of the buddy who changed his status. */ - public String getBuddySkypename() - { + public String getBuddySkypename() { return buddyGroup(2); } - private String buddyGroup(int group) - { - if (buddy == null) - { + private String buddyGroup(int group) { + if (buddy == null) { return null; } final Matcher buddyMatcher = BUDDY_PATTERN.matcher(buddy); - if (buddyMatcher.matches()) - { + if (buddyMatcher.matches()) { return buddyMatcher.group(group); } return null; @@ -122,8 +114,7 @@ private String buddyGroup(int group) * * @param buddy the address of the buddy. */ - public void setBuddy(String buddy) - { + public void setBuddy(String buddy) { this.buddy = buddy; } @@ -132,13 +123,11 @@ public void setBuddy(String buddy) * * @return the status of the buddy. */ - public String getBuddyStatus() - { + public String getBuddyStatus() { return buddyStatus; } - public void setBuddyStatus(String buddyStatus) - { + public void setBuddyStatus(String buddyStatus) { this.buddyStatus = buddyStatus; } } diff --git a/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java b/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java index 67ce040bc..a4c597577 100644 --- a/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java @@ -16,10 +16,10 @@ */ package org.asteriskjava.manager.event; -import java.nio.charset.StandardCharsets; - import org.asteriskjava.util.Base64; +import java.nio.charset.StandardCharsets; + /** * A SkypeChatMessageEvent is triggered when a Skype Chat message is sent or * received. @@ -30,8 +30,7 @@ * * @since 1.0.0 */ -public class SkypeChatMessageEvent extends ManagerEvent -{ +public class SkypeChatMessageEvent extends ManagerEvent { /** * Serializable version identifier. */ @@ -41,8 +40,7 @@ public class SkypeChatMessageEvent extends ManagerEvent private String from; private String message; - public SkypeChatMessageEvent(Object source) - { + public SkypeChatMessageEvent(Object source) { super(source); } @@ -51,8 +49,7 @@ public SkypeChatMessageEvent(Object source) * * @return the Skype username of the recipient of this chat message. */ - public String getTo() - { + public String getTo() { return to; } @@ -61,8 +58,7 @@ public String getTo() * * @param to the Skype username of the recipient of this chat message. */ - public void setTo(String to) - { + public void setTo(String to) { this.to = to; } @@ -71,8 +67,7 @@ public void setTo(String to) * * @return the Skype username of the sender of this chat message. */ - public String getFrom() - { + public String getFrom() { return from; } @@ -81,8 +76,7 @@ public String getFrom() * * @param from the Skype username of the sender of this chat message. */ - public void setFrom(String from) - { + public void setFrom(String from) { this.from = from; } @@ -91,8 +85,7 @@ public void setFrom(String from) * * @return the Base64 encoded message. */ - public String getMessage() - { + public String getMessage() { return message; } @@ -101,8 +94,7 @@ public String getMessage() * * @param message the Base64 encoded message. */ - public void setMessage(String message) - { + public void setMessage(String message) { this.message = message; } @@ -111,10 +103,8 @@ public void setMessage(String message) * * @return the decoded message. */ - public String getDecodedMessage() - { - if (message == null) - { + public String getDecodedMessage() { + if (message == null) { return null; } return new String(Base64.base64ToByteArray(message), StandardCharsets.UTF_8); diff --git a/src/main/java/org/asteriskjava/manager/event/SkypeLicenseEvent.java b/src/main/java/org/asteriskjava/manager/event/SkypeLicenseEvent.java index 96aefa352..2d0d2c09e 100644 --- a/src/main/java/org/asteriskjava/manager/event/SkypeLicenseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SkypeLicenseEvent.java @@ -25,8 +25,7 @@ * @see org.asteriskjava.manager.action.SkypeLicenseListAction * @since 1.0.0 */ -public class SkypeLicenseEvent extends ResponseEvent -{ +public class SkypeLicenseEvent extends ResponseEvent { /** * Serial version identifier. */ @@ -37,8 +36,7 @@ public class SkypeLicenseEvent extends ResponseEvent private Integer channels; private String status; - public SkypeLicenseEvent(Object source) - { + public SkypeLicenseEvent(Object source) { super(source); } @@ -47,8 +45,7 @@ public SkypeLicenseEvent(Object source) * * @return the license key. */ - public String getKey() - { + public String getKey() { return key; } @@ -57,8 +54,7 @@ public String getKey() * * @param key the license key. */ - public void setKey(String key) - { + public void setKey(String key) { this.key = key; } @@ -67,8 +63,7 @@ public void setKey(String key) * * @return the date the license expires in the format "YYYY-MM-DD". */ - public String getExpires() - { + public String getExpires() { return expires; } @@ -77,18 +72,15 @@ public String getExpires() * * @param expires the date the license expires in the format "YYYY-MM-DD". */ - public void setExpires(String expires) - { + public void setExpires(String expires) { this.expires = expires; } - public String getHostId() - { + public String getHostId() { return hostId; } - public void setHostId(String hostId) - { + public void setHostId(String hostId) { this.hostId = hostId; } @@ -97,8 +89,7 @@ public void setHostId(String hostId) * * @return the number of licensed channels. */ - public Integer getChannels() - { + public Integer getChannels() { return channels; } @@ -107,18 +98,15 @@ public Integer getChannels() * * @param channels the number of licensed channels. */ - public void setChannels(Integer channels) - { + public void setChannels(Integer channels) { this.channels = channels; } - public String getStatus() - { + public String getStatus() { return status; } - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } } diff --git a/src/main/java/org/asteriskjava/manager/event/SkypeLicenseListCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/SkypeLicenseListCompleteEvent.java index ed0c586e6..796d6ec4e 100644 --- a/src/main/java/org/asteriskjava/manager/event/SkypeLicenseListCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SkypeLicenseListCompleteEvent.java @@ -25,15 +25,13 @@ * @see org.asteriskjava.manager.action.SkypeLicenseListAction * @since 1.0.0 */ -public class SkypeLicenseListCompleteEvent extends ResponseEvent -{ +public class SkypeLicenseListCompleteEvent extends ResponseEvent { /** * Serial version identifier. */ private static final long serialVersionUID = 1L; - public SkypeLicenseListCompleteEvent(Object source) - { + public SkypeLicenseListCompleteEvent(Object source) { super(source); } } diff --git a/src/main/java/org/asteriskjava/manager/event/SoftHangupRequestEvent.java b/src/main/java/org/asteriskjava/manager/event/SoftHangupRequestEvent.java index 25523b435..6179a3e10 100644 --- a/src/main/java/org/asteriskjava/manager/event/SoftHangupRequestEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SoftHangupRequestEvent.java @@ -21,8 +21,7 @@ *

    * It is implemented in channel.c */ -public class SoftHangupRequestEvent extends AbstractChannelEvent -{ +public class SoftHangupRequestEvent extends AbstractChannelEvent { /** * Serializable version identifier. */ @@ -32,18 +31,15 @@ public class SoftHangupRequestEvent extends AbstractChannelEvent private String language; private String linkedId; - public SoftHangupRequestEvent(Object source) - { + public SoftHangupRequestEvent(Object source) { super(source); } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } @@ -53,8 +49,7 @@ public void setLanguage(String language) * @return the hangup cause. * @see org.asteriskjava.live.HangupCause */ - public Integer getCause() - { + public Integer getCause() { return cause; } @@ -63,19 +58,16 @@ public Integer getCause() * * @param cause the hangup cause. */ - public void setCause(Integer cause) - { + public void setCause(Integer cause) { this.cause = cause; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - + } diff --git a/src/main/java/org/asteriskjava/manager/event/StatusCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/StatusCompleteEvent.java index 208f978af..74e0a124c 100644 --- a/src/main/java/org/asteriskjava/manager/event/StatusCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/StatusCompleteEvent.java @@ -19,14 +19,13 @@ /** * A StatusCompleteEvent is triggered after the state of all channels has been * reported in response to a StatusAction. - * - * @see org.asteriskjava.manager.action.StatusAction - * @see org.asteriskjava.manager.event.StatusEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.StatusAction + * @see org.asteriskjava.manager.event.StatusEvent */ -public class StatusCompleteEvent extends ResponseEvent -{ +public class StatusCompleteEvent extends ResponseEvent { /** * Serial version identifier. */ @@ -36,8 +35,7 @@ public class StatusCompleteEvent extends ResponseEvent private Integer listItems; private String eventList; - public StatusCompleteEvent(Object source) - { + public StatusCompleteEvent(Object source) { super(source); } @@ -49,8 +47,7 @@ public StatusCompleteEvent(Object source) * @return the number of channels reported. * @since 1.0.0 */ - public Integer getItems() - { + public Integer getItems() { return items; } @@ -62,28 +59,23 @@ public Integer getItems() * @param items the number of channels reported. * @since 1.0.0 */ - public void setItems(Integer items) - { + public void setItems(Integer items) { this.items = items; } - public Integer getListItems() - { + public Integer getListItems() { return listItems; } - public String getEventList() - { + public String getEventList() { return eventList; } - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } - public void setListItems(Integer listItems) - { + public void setListItems(Integer listItems) { this.listItems = listItems; } diff --git a/src/main/java/org/asteriskjava/manager/event/StatusEvent.java b/src/main/java/org/asteriskjava/manager/event/StatusEvent.java index be7009575..193a0be3d 100644 --- a/src/main/java/org/asteriskjava/manager/event/StatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/StatusEvent.java @@ -26,8 +26,7 @@ * @version $Id$ * @see org.asteriskjava.manager.action.StatusAction */ -public class StatusEvent extends ResponseEvent -{ +public class StatusEvent extends ResponseEvent { /** * Serial version identifier. */ @@ -57,8 +56,7 @@ public class StatusEvent extends ResponseEvent private String readtrans; private String language; - public StatusEvent(Object source) - { + public StatusEvent(Object source) { super(source); } @@ -67,8 +65,7 @@ public StatusEvent(Object source) * * @return the name of this channel. */ - public String getChannel() - { + public String getChannel() { return channel; } @@ -77,8 +74,7 @@ public String getChannel() * * @param channel the name of this channel. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -89,12 +85,11 @@ public void setChannel(String channel) * {@link #getCallerIdNum()} instead. * * @return the Caller*ID Number of this channel or null if none - * is available. + * is available. * @deprecated */ @Deprecated - public String getCallerId() - { + public String getCallerId() { return callerIdNum; } @@ -105,8 +100,7 @@ public String getCallerId() * * @param callerIdNum the Caller*ID Number to set. */ - public void setCallerId(String callerIdNum) - { + public void setCallerId(String callerIdNum) { this.callerIdNum = callerIdNum; } @@ -116,8 +110,7 @@ public void setCallerId(String callerIdNum) * @return the account code of this channel. * @since 1.0.0 */ - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } @@ -127,8 +120,7 @@ public String getAccountCode() * @param accountCode the account code of this channel. * @since 1.0.0 */ - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } @@ -139,8 +131,7 @@ public void setAccountCode(String accountCode) * @deprecated since 1.0.0, use {@link #getAccountCode()} instead. */ @Deprecated - public String getAccount() - { + public String getAccount() { return accountCode; } @@ -152,8 +143,7 @@ public String getAccount() * * @param account the account code of this channel. */ - public void setAccount(String account) - { + public void setAccount(String account) { this.accountCode = account; } @@ -164,23 +154,19 @@ public void setAccount(String account) * @deprecated use {@link #getChannelStateDesc()} instead. */ @Deprecated - public String getState() - { + public String getState() { return getChannelStateDesc(); } - public void setState(String state) - { + public void setState(String state) { setChannelStateDesc(state); } - public String getExtension() - { + public String getExtension() { return getExten(); } - public void setExtension(String extension) - { + public void setExtension(String extension) { setExten(extension); } @@ -189,8 +175,7 @@ public void setExtension(String extension) * * @return the number of elapsed seconds. */ - public Integer getSeconds() - { + public Integer getSeconds() { return seconds; } @@ -199,8 +184,7 @@ public Integer getSeconds() * * @param seconds the number of elapsed seconds. */ - public void setSeconds(Integer seconds) - { + public void setSeconds(Integer seconds) { this.seconds = seconds; } @@ -210,8 +194,7 @@ public void setSeconds(Integer seconds) * @return the name of the linked channel if this channel is bridged. * @since 1.0.0 */ - public String getBridgedChannel() - { + public String getBridgedChannel() { return bridgedChannel; } @@ -219,11 +202,10 @@ public String getBridgedChannel() * Sets the name of the linked channel. * * @param bridgedChannel the name of the linked channel if this channel is - * bridged. + * bridged. * @since 1.0.0 */ - public void setBridgedChannel(String bridgedChannel) - { + public void setBridgedChannel(String bridgedChannel) { this.bridgedChannel = bridgedChannel; } @@ -234,8 +216,7 @@ public void setBridgedChannel(String bridgedChannel) * @deprecated as of 1.0.0, use {@link #getBridgedChannel()} instead. */ @Deprecated - public String getLink() - { + public String getLink() { return bridgedChannel; } @@ -246,8 +227,7 @@ public String getLink() * * @param link the name of the linked channel if this channel is bridged. */ - public void setLink(String link) - { + public void setLink(String link) { this.bridgedChannel = link; } @@ -259,8 +239,7 @@ public void setLink(String link) * @return the unique id of the linked channel if this channel is bridged. * @since 1.0.0 */ - public String getBridgedUniqueId() - { + public String getBridgedUniqueId() { return bridgedUniqueId; } @@ -270,11 +249,10 @@ public String getBridgedUniqueId() * Available since Asterisk 1.6. * * @param bridgedUniqueId the unique id of the linked channel if this - * channel is bridged. + * channel is bridged. * @since 1.0.0 */ - public void setBridgedUniqueId(String bridgedUniqueId) - { + public void setBridgedUniqueId(String bridgedUniqueId) { this.bridgedUniqueId = bridgedUniqueId; } @@ -283,8 +261,7 @@ public void setBridgedUniqueId(String bridgedUniqueId) * * @return the unique id of this channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } @@ -293,8 +270,7 @@ public String getUniqueId() * * @param uniqueId the unique id of this channel. */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -308,8 +284,7 @@ public void setUniqueId(String uniqueId) * @return the channel variables. * @since 1.0.0 */ - public Map getVariables() - { + public Map getVariables() { return variables; } @@ -321,202 +296,167 @@ public Map getVariables() * @param variables the channel variables. * @since 1.0.0 */ - public void setVariables(Map variables) - { + public void setVariables(Map variables) { this.variables = variables; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getData() - { + public String getData() { return data; } - public void setData(String data) - { + public void setData(String data) { this.data = data; } - public String getReadFormat() - { + public String getReadFormat() { return readFormat; } - public void setReadFormat(String readFormat) - { + public void setReadFormat(String readFormat) { this.readFormat = readFormat; } - public String getWriteFormat() - { + public String getWriteFormat() { return writeFormat; } - public void setWriteFormat(String writeFormat) - { + public void setWriteFormat(String writeFormat) { this.writeFormat = writeFormat; } - public String getType() - { + public String getType() { return type; } - public void setType(String type) - { + public void setType(String type) { this.type = type; } - public String getEffectiveConnectedLineName() - { + public String getEffectiveConnectedLineName() { return effectiveConnectedLineName; } - public void setEffectiveConnectedLineName(String effectiveConnectedLineName) - { + public void setEffectiveConnectedLineName(String effectiveConnectedLineName) { this.effectiveConnectedLineName = effectiveConnectedLineName; } - public String getEffectiveConnectedLineNum() - { + public String getEffectiveConnectedLineNum() { return effectiveConnectedLineNum; } - public void setEffectiveConnectedLineNum(String effectiveConnectedLineNum) - { + public void setEffectiveConnectedLineNum(String effectiveConnectedLineNum) { this.effectiveConnectedLineNum = effectiveConnectedLineNum; } - public String getApplication() - { + public String getApplication() { return application; } - public void setApplication(String application) - { + public void setApplication(String application) { this.application = application; } - public String getCallGroup() - { + public String getCallGroup() { return callGroup; } - public void setCallGroup(String callGroup) - { + public void setCallGroup(String callGroup) { this.callGroup = callGroup; } - public String getNativeFormats() - { + public String getNativeFormats() { return nativeFormats; } - public void setNativeFormats(String nativeFormats) - { + public void setNativeFormats(String nativeFormats) { this.nativeFormats = nativeFormats; } - public String getPickupGroup() - { + public String getPickupGroup() { return pickupGroup; } - public void setPickupGroup(String pickupGroup) - { + public void setPickupGroup(String pickupGroup) { this.pickupGroup = pickupGroup; } - public String getTimeToHangup() - { + public String getTimeToHangup() { return timeToHangup; } - public void setTimeToHangup(String timeToHangup) - { + public void setTimeToHangup(String timeToHangup) { this.timeToHangup = timeToHangup; } /** * @return the dnid */ - public String getDnid() - { + public String getDnid() { return dnid; } /** * @param dnid the dnid to set */ - public void setDnid(String dnid) - { + public void setDnid(String dnid) { this.dnid = dnid; } /** * @return the writetrans */ - public String getWritetrans() - { + public String getWritetrans() { return writetrans; } /** * @param writetrans the writetrans to set */ - public void setWritetrans(String writetrans) - { + public void setWritetrans(String writetrans) { this.writetrans = writetrans; } /** * @return the bridgeid */ - public String getBridgeId() - { + public String getBridgeId() { return bridgeId; } /** * @param bridgeid the bridgeid to set */ - public void setBridgeId(String bridgeid) - { + public void setBridgeId(String bridgeid) { this.bridgeId = bridgeid; } /** * @return the readtrans */ - public String getReadtrans() - { + public String getReadtrans() { return readtrans; } /** * @param readtrans the readtrans to set */ - public void setReadtrans(String readtrans) - { + public void setReadtrans(String readtrans) { this.readtrans = readtrans; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } } diff --git a/src/main/java/org/asteriskjava/manager/event/SuccessfulAuthEvent.java b/src/main/java/org/asteriskjava/manager/event/SuccessfulAuthEvent.java index 9e8b7e4df..e8b533ddf 100644 --- a/src/main/java/org/asteriskjava/manager/event/SuccessfulAuthEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SuccessfulAuthEvent.java @@ -3,125 +3,103 @@ /** * Created by plhk on 1/15/15. */ -public class SuccessfulAuthEvent extends ManagerEvent -{ - /** - * - */ - private static final long serialVersionUID = 1L; - private String severity; - private Integer eventVersion; - private String accountId; - private Integer usingPassword; - private String sessiontv; - private String service; - private String eventtv; - private String remoteAddress; - private String localAddress; - private String sessionId; - - public SuccessfulAuthEvent(Object source) - { - super(source); - } - - public String getSeverity() - { - return severity; - } - - public void setSeverity(String severity) - { - this.severity = severity; - } - - public Integer getEventVersion() - { - return eventVersion; - } - - public void setEventVersion(Integer eventVersion) - { - this.eventVersion = eventVersion; - } - - public String getAccountId() - { - return accountId; - } - - public void setAccountId(String accountId) - { - this.accountId = accountId; - } - - public Integer getUsingPassword() - { - return usingPassword; - } - - public void setUsingPassword(Integer usingPassword) - { - this.usingPassword = usingPassword; - } - - public String getSessiontv() - { - return sessiontv; - } - - public void setSessiontv(String sessiontv) - { - this.sessiontv = sessiontv; - } - - public String getService() - { - return service; - } - - public void setService(String service) - { - this.service = service; - } - - public String getEventtv() - { - return eventtv; - } - - public void setEventtv(String eventtv) - { - this.eventtv = eventtv; - } - - public String getRemoteAddress() - { - return remoteAddress; - } - - public void setRemoteAddress(String remoteAddress) - { - this.remoteAddress = remoteAddress; - } - - public String getLocalAddress() - { - return localAddress; - } - - public void setLocalAddress(String localAddress) - { - this.localAddress = localAddress; - } - - public String getSessionId() - { - return sessionId; - } - - public void setSessionId(String sessionId) - { - this.sessionId = sessionId; - } +public class SuccessfulAuthEvent extends ManagerEvent { + /** + * + */ + private static final long serialVersionUID = 1L; + private String severity; + private Integer eventVersion; + private String accountId; + private Integer usingPassword; + private String sessiontv; + private String service; + private String eventtv; + private String remoteAddress; + private String localAddress; + private String sessionId; + + public SuccessfulAuthEvent(Object source) { + super(source); + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public Integer getEventVersion() { + return eventVersion; + } + + public void setEventVersion(Integer eventVersion) { + this.eventVersion = eventVersion; + } + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public Integer getUsingPassword() { + return usingPassword; + } + + public void setUsingPassword(Integer usingPassword) { + this.usingPassword = usingPassword; + } + + public String getSessiontv() { + return sessiontv; + } + + public void setSessiontv(String sessiontv) { + this.sessiontv = sessiontv; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public String getEventtv() { + return eventtv; + } + + public void setEventtv(String eventtv) { + this.eventtv = eventtv; + } + + public String getRemoteAddress() { + return remoteAddress; + } + + public void setRemoteAddress(String remoteAddress) { + this.remoteAddress = remoteAddress; + } + + public String getLocalAddress() { + return localAddress; + } + + public void setLocalAddress(String localAddress) { + this.localAddress = localAddress; + } + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/T38FaxStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/T38FaxStatusEvent.java index 9a2a6248b..2ac0158ed 100644 --- a/src/main/java/org/asteriskjava/manager/event/T38FaxStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/T38FaxStatusEvent.java @@ -19,8 +19,7 @@ /** * A FaxDocumentStatusEvent is an event of Digium's Fax For Asterisk add-on. */ -public class T38FaxStatusEvent extends AbstractFaxEvent -{ +public class T38FaxStatusEvent extends AbstractFaxEvent { /** * Serial version identifier. */ @@ -40,8 +39,7 @@ public class T38FaxStatusEvent extends AbstractFaxEvent private Integer minimumJitterSpace; private Integer unrecoverablePackets; - public T38FaxStatusEvent(Object source) - { + public T38FaxStatusEvent(Object source) { super(source); } @@ -49,274 +47,237 @@ public T38FaxStatusEvent(Object source) /** * @return the maxLag */ - public String getMaxLag() - { + public String getMaxLag() { return maxLag; } /** * @param maxLag the maxLag to set */ - public void setMaxLag(String maxLag) - { + public void setMaxLag(String maxLag) { this.maxLag = maxLag; } /** * @return the totalLag */ - public String getTotalLag() - { + public String getTotalLag() { return totalLag; } /** * @param totalLag the totalLag to set */ - public void setTotalLag(String totalLag) - { + public void setTotalLag(String totalLag) { this.totalLag = totalLag; } /** * @return the averageLag */ - public String getAverageLag() - { + public String getAverageLag() { return averageLag; } /** * @param averageLag the averageLag to set */ - public void setAverageLag(String averageLag) - { + public void setAverageLag(String averageLag) { this.averageLag = averageLag; } /** * @return the totalEvents */ - public Integer getTotalEvents() - { + public Integer getTotalEvents() { return totalEvents; } /** * @param totalEvents the totalEvents to set */ - public void setTotalEvents(Integer totalEvents) - { + public void setTotalEvents(Integer totalEvents) { this.totalEvents = totalEvents; } /** * @return the t38SessionDuration */ - public String getT38SessionDuration() - { + public String getT38SessionDuration() { return t38SessionDuration; } /** * @param t38SessionDuration the t38SessionDuration to set */ - public void setT38SessionDuration(String t38SessionDuration) - { + public void setT38SessionDuration(String t38SessionDuration) { this.t38SessionDuration = t38SessionDuration; } /** * @return the t38PacketsSent */ - public Integer getT38PacketsSent() - { + public Integer getT38PacketsSent() { return t38PacketsSent; } /** * @param t38PacketsSent the t38PacketsSent to set */ - public void setT38PacketsSent(Integer t38PacketsSent) - { + public void setT38PacketsSent(Integer t38PacketsSent) { this.t38PacketsSent = t38PacketsSent; } /** * @return the t38OctetsSent */ - public Integer getT38OctetsSent() - { + public Integer getT38OctetsSent() { return t38OctetsSent; } /** * @param t38OctetsSent the t38OctetsSent to set */ - public void setT38OctetsSent(Integer t38OctetsSent) - { + public void setT38OctetsSent(Integer t38OctetsSent) { this.t38OctetsSent = t38OctetsSent; } /** * @return the averageTxDataRate */ - public String getAverageTxDataRate() - { + public String getAverageTxDataRate() { return averageTxDataRate; } /** * @param averageTxDataRate the averageTxDataRate to set */ - public void setAverageTxDataRate(String averageTxDataRate) - { + public void setAverageTxDataRate(String averageTxDataRate) { this.averageTxDataRate = averageTxDataRate; } /** * @return the t38PacketsReceived */ - public Integer getT38PacketsReceived() - { + public Integer getT38PacketsReceived() { return t38PacketsReceived; } /** * @param t38PacketsReceived the t38PacketsReceived to set */ - public void setT38PacketsReceived(Integer t38PacketsReceived) - { + public void setT38PacketsReceived(Integer t38PacketsReceived) { this.t38PacketsReceived = t38PacketsReceived; } /** * @return the t38OctetsReceived */ - public Integer getT38OctetsReceived() - { + public Integer getT38OctetsReceived() { return t38OctetsReceived; } /** * @param t38OctetsReceived the t38OctetsReceived to set */ - public void setT38OctetsReceived(Integer t38OctetsReceived) - { + public void setT38OctetsReceived(Integer t38OctetsReceived) { this.t38OctetsReceived = t38OctetsReceived; } /** * @return the averageRxDataRate */ - public String getAverageRxDataRate() - { + public String getAverageRxDataRate() { return averageRxDataRate; } /** * @param averageRxDataRate the averageRxDataRate to set */ - public void setAverageRxDataRate(String averageRxDataRate) - { + public void setAverageRxDataRate(String averageRxDataRate) { this.averageRxDataRate = averageRxDataRate; } /** * @return the jitterBufferOverflows */ - public Integer getJitterBufferOverflows() - { + public Integer getJitterBufferOverflows() { return jitterBufferOverflows; } /** * @param jitterBufferOverflows the jitterBufferOverflows to set */ - public void setJitterBufferOverflows(Integer jitterBufferOverflows) - { + public void setJitterBufferOverflows(Integer jitterBufferOverflows) { this.jitterBufferOverflows = jitterBufferOverflows; } /** * @return the minimumJitterSpace */ - public Integer getMinimumJitterSpace() - { + public Integer getMinimumJitterSpace() { return minimumJitterSpace; } /** * @param minimumJitterSpace the minimumJitterSpace to set */ - public void setMinimumJitterSpace(Integer minimumJitterSpace) - { + public void setMinimumJitterSpace(Integer minimumJitterSpace) { this.minimumJitterSpace = minimumJitterSpace; } /** * @return the unrecoverablePackets */ - public Integer getUnrecoverablePackets() - { + public Integer getUnrecoverablePackets() { return unrecoverablePackets; } /** * @param unrecoverablePackets the unrecoverablePackets to set */ - public void setUnrecoverablePackets(Integer unrecoverablePackets) - { + public void setUnrecoverablePackets(Integer unrecoverablePackets) { this.unrecoverablePackets = unrecoverablePackets; } // convenience methods - public Integer getTotalLagInMilliSeconds() - { + public Integer getTotalLagInMilliSeconds() { final String totalLagStripped = stripUnit(this.totalLag); return totalLagStripped == null ? null : Integer.valueOf(totalLagStripped); } - public Integer getMaxLagInMilliSeconds() - { + public Integer getMaxLagInMilliSeconds() { final String maxLagStripped = stripUnit(this.maxLag); return maxLagStripped == null ? null : Integer.valueOf(maxLagStripped); } - public Double getT38SessionDurationInSeconds() - { + public Double getT38SessionDurationInSeconds() { final String t38SessionDurationStripped = stripUnit(this.t38SessionDuration); return t38SessionDurationStripped == null ? null : Double.valueOf(t38SessionDurationStripped); } - public Double getAverageLagInMilliSeconds() - { + public Double getAverageLagInMilliSeconds() { final String averageLagStripped = stripUnit(this.averageLag); return averageLagStripped == null ? null : Double.valueOf(averageLagStripped); } - public Integer getAverageTxDataRateInBps() - { + public Integer getAverageTxDataRateInBps() { final String averageTxDataRateStripped = stripUnit(this.averageTxDataRate); return averageTxDataRateStripped == null ? null : Integer.valueOf(averageTxDataRateStripped); } - public Integer getAverageRxDataRateInBps() - { + public Integer getAverageRxDataRateInBps() { final String averageRxDataRateStripped = stripUnit(this.averageRxDataRate); return averageRxDataRateStripped == null ? null : Integer.valueOf(averageRxDataRateStripped); } - String stripUnit(String s) - { - if (s == null || s.length() == 0) - { + String stripUnit(String s) { + if (s == null || s.length() == 0) { return null; } int index = s.indexOf(' '); - if (index < 0) - { + if (index < 0) { return s; } return s.substring(0, index); diff --git a/src/main/java/org/asteriskjava/manager/event/TransferEvent.java b/src/main/java/org/asteriskjava/manager/event/TransferEvent.java index 9e33d857a..f6532cf65 100644 --- a/src/main/java/org/asteriskjava/manager/event/TransferEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/TransferEvent.java @@ -25,8 +25,7 @@ * @version $Id$ * @since 1.0.0 */ -public class TransferEvent extends ManagerEvent -{ +public class TransferEvent extends ManagerEvent { private static final long serialVersionUID = 1L; public static final String TRANSFER_METHOD_SIP = "SIP"; @@ -45,8 +44,7 @@ public class TransferEvent extends ManagerEvent private String transferContext; private Boolean transfer2Parking; - public TransferEvent(Object source) - { + public TransferEvent(Object source) { super(source); } @@ -55,13 +53,11 @@ public TransferEvent(Object source) * * @return channel the name of the transfering channel. */ - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -70,13 +66,11 @@ public void setChannel(String channel) * * @return the unique id of the transfering channel. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -85,13 +79,11 @@ public void setUniqueId(String uniqueId) * * @return the transfer method ("SIP"). */ - public String getTransferMethod() - { + public String getTransferMethod() { return transferMethod; } - public void setTransferMethod(String transferMethod) - { + public void setTransferMethod(String transferMethod) { this.transferMethod = transferMethod; } @@ -103,8 +95,7 @@ public void setTransferMethod(String transferMethod) * @see #TRANSFER_TYPE_ATTENDED * @see #TRANSFER_TYPE_BLIND */ - public String getTransferType() - { + public String getTransferType() { return transferType; } @@ -113,8 +104,7 @@ public String getTransferType() * * @return true if this is an attended transfer, false if not. */ - public boolean isAttended() - { + public boolean isAttended() { return TRANSFER_TYPE_ATTENDED.equals(transferType); } @@ -123,13 +113,11 @@ public boolean isAttended() * * @return true if this is an blind transfer, false if not. */ - public boolean isBlind() - { + public boolean isBlind() { return TRANSFER_TYPE_BLIND.equals(transferType); } - public void setTransferType(String transferType) - { + public void setTransferType(String transferType) { this.transferType = transferType; } @@ -138,13 +126,11 @@ public void setTransferType(String transferType) * * @return the SIP call id. */ - public String getSipCallId() - { + public String getSipCallId() { return sipCallId; } - public void setSipCallId(String sipCallId) - { + public void setSipCallId(String sipCallId) { this.sipCallId = sipCallId; } @@ -153,13 +139,11 @@ public void setSipCallId(String sipCallId) * * @return the name of the target channel. */ - public String getTargetChannel() - { + public String getTargetChannel() { return targetChannel; } - public void setTargetChannel(String targetChannel) - { + public void setTargetChannel(String targetChannel) { this.targetChannel = targetChannel; } @@ -168,13 +152,11 @@ public void setTargetChannel(String targetChannel) * * @return the unique id of the target channel. */ - public String getTargetUniqueId() - { + public String getTargetUniqueId() { return targetUniqueId; } - public void setTargetUniqueId(String targetUniqueId) - { + public void setTargetUniqueId(String targetUniqueId) { this.targetUniqueId = targetUniqueId; } @@ -184,15 +166,13 @@ public void setTargetUniqueId(String targetUniqueId) * is returned. * * @return the target extension the call is transfered to or null for attended - * transfers. + * transfers. */ - public String getTransferExten() - { + public String getTransferExten() { return transferExten; } - public void setTransferExten(String transferExten) - { + public void setTransferExten(String transferExten) { this.transferExten = transferExten; } @@ -201,15 +181,13 @@ public void setTransferExten(String transferExten) * blind transfers. If the call is transfered to a parking extension null is returned. * * @return the target context the call is transfered to or null for attended - * transfers and transfers to a parking extension. + * transfers and transfers to a parking extension. */ - public String getTransferContext() - { + public String getTransferContext() { return transferContext; } - public void setTransferContext(String transferContext) - { + public void setTransferContext(String transferContext) { this.transferContext = transferContext; } @@ -218,13 +196,11 @@ public void setTransferContext(String transferContext) * * @return Boolean.TRUE if this is a transfer to a parking extension, null otherwise. */ - public Boolean getTransfer2Parking() - { + public Boolean getTransfer2Parking() { return transfer2Parking; } - public void setTransfer2Parking(Boolean transfer2Parking) - { + public void setTransfer2Parking(Boolean transfer2Parking) { this.transfer2Parking = transfer2Parking; } @@ -233,8 +209,7 @@ public void setTransfer2Parking(Boolean transfer2Parking) * * @return true if this is a transfer to a parking extension, false otherwise. */ - public boolean isParking() - { + public boolean isParking() { return transfer2Parking != null && transfer2Parking; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/TransportDetail.java b/src/main/java/org/asteriskjava/manager/event/TransportDetail.java index 2db7b20d6..d05aaca2a 100644 --- a/src/main/java/org/asteriskjava/manager/event/TransportDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/TransportDetail.java @@ -16,242 +16,242 @@ public class TransportDetail extends ResponseEvent { /** * Serial version identifier. */ - private static final long serialVersionUID = 8558130768089350575L; - private String Event; - private String objectType; - private String pbjectName; - private String protocol; - private String bind; - private int asycOperations; - private String caListFile; - private String caListPath; - private String certFile; - private String privKeyFile; - private String password; - private String externalSignalingAddress; - private int externalSignalingPort; - private String externalMediaAddress; - private String domain; - private String verifyServer; - private String verifyClient; - private Boolean requireClientCert; - private String method; - private String cipher; - private String localNet; - private String tos; - private int cos; - private int websocketWriteTimeout; - private String endpointName; - - - /** + private static final long serialVersionUID = 8558130768089350575L; + private String Event; + private String objectType; + private String pbjectName; + private String protocol; + private String bind; + private int asycOperations; + private String caListFile; + private String caListPath; + private String certFile; + private String privKeyFile; + private String password; + private String externalSignalingAddress; + private int externalSignalingPort; + private String externalMediaAddress; + private String domain; + private String verifyServer; + private String verifyClient; + private Boolean requireClientCert; + private String method; + private String cipher; + private String localNet; + private String tos; + private int cos; + private int websocketWriteTimeout; + private String endpointName; + + + /** * Serial version identifier. */ - public TransportDetail(Object source) { - super(source); - } + public TransportDetail(Object source) { + super(source); + } - public String getEvent() { - return Event; - } + public String getEvent() { + return Event; + } - public void setEvent(String event) { - Event = event; - } + public void setEvent(String event) { + Event = event; + } - public String getObjectType() { - return objectType; - } + public String getObjectType() { + return objectType; + } - public void setObjectType(String objectType) { - this.objectType = objectType; - } + public void setObjectType(String objectType) { + this.objectType = objectType; + } - public String getPbjectName() { - return pbjectName; - } + public String getPbjectName() { + return pbjectName; + } - public void setPbjectName(String pbjectName) { - this.pbjectName = pbjectName; - } + public void setPbjectName(String pbjectName) { + this.pbjectName = pbjectName; + } - public String getProtocol() { - return protocol; - } + public String getProtocol() { + return protocol; + } - public void setProtocol(String protocol) { - this.protocol = protocol; - } + public void setProtocol(String protocol) { + this.protocol = protocol; + } - public String getBind() { - return bind; - } + public String getBind() { + return bind; + } - public void setBind(String bind) { - this.bind = bind; - } + public void setBind(String bind) { + this.bind = bind; + } - public int getAsycOperations() { - return asycOperations; - } + public int getAsycOperations() { + return asycOperations; + } - public void setAsycOperations(int asycOperations) { - this.asycOperations = asycOperations; - } + public void setAsycOperations(int asycOperations) { + this.asycOperations = asycOperations; + } - public String getCaListFile() { - return caListFile; - } + public String getCaListFile() { + return caListFile; + } - public void setCaListFile(String caListFile) { - this.caListFile = caListFile; - } + public void setCaListFile(String caListFile) { + this.caListFile = caListFile; + } - public String getCaListPath() { - return caListPath; - } + public String getCaListPath() { + return caListPath; + } - public void setCaListPath(String caListPath) { - this.caListPath = caListPath; - } + public void setCaListPath(String caListPath) { + this.caListPath = caListPath; + } - public String getCertFile() { - return certFile; - } + public String getCertFile() { + return certFile; + } - public void setCertFile(String certFile) { - this.certFile = certFile; - } + public void setCertFile(String certFile) { + this.certFile = certFile; + } - public String getPrivKeyFile() { - return privKeyFile; - } + public String getPrivKeyFile() { + return privKeyFile; + } - public void setPrivKeyFile(String privKeyFile) { - this.privKeyFile = privKeyFile; - } + public void setPrivKeyFile(String privKeyFile) { + this.privKeyFile = privKeyFile; + } - public String getPassword() { - return password; - } + public String getPassword() { + return password; + } - public void setPassword(String password) { - this.password = password; - } + public void setPassword(String password) { + this.password = password; + } - public String getExternalSignalingAddress() { - return externalSignalingAddress; - } + public String getExternalSignalingAddress() { + return externalSignalingAddress; + } - public void setExternalSignalingAddress(String externalSignalingAddress) { - this.externalSignalingAddress = externalSignalingAddress; - } + public void setExternalSignalingAddress(String externalSignalingAddress) { + this.externalSignalingAddress = externalSignalingAddress; + } - public int getExternalSignalingPort() { - return externalSignalingPort; - } + public int getExternalSignalingPort() { + return externalSignalingPort; + } - public void setExternalSignalingPort(int externalSignalingPort) { - this.externalSignalingPort = externalSignalingPort; - } + public void setExternalSignalingPort(int externalSignalingPort) { + this.externalSignalingPort = externalSignalingPort; + } - public String getExternalMediaAddress() { - return externalMediaAddress; - } + public String getExternalMediaAddress() { + return externalMediaAddress; + } - public void setExternalMediaAddress(String externalMediaAddress) { - this.externalMediaAddress = externalMediaAddress; - } + public void setExternalMediaAddress(String externalMediaAddress) { + this.externalMediaAddress = externalMediaAddress; + } - public String getDomain() { - return domain; - } + public String getDomain() { + return domain; + } - public void setDomain(String domain) { - this.domain = domain; - } + public void setDomain(String domain) { + this.domain = domain; + } - public String getVerifyServer() { - return verifyServer; - } + public String getVerifyServer() { + return verifyServer; + } - public void setVerifyServer(String verifyServer) { - this.verifyServer = verifyServer; - } + public void setVerifyServer(String verifyServer) { + this.verifyServer = verifyServer; + } - public String getVerifyClient() { - return verifyClient; - } + public String getVerifyClient() { + return verifyClient; + } - public void setVerifyClient(String verifyClient) { - this.verifyClient = verifyClient; - } + public void setVerifyClient(String verifyClient) { + this.verifyClient = verifyClient; + } - public Boolean getRequireClientCert() { - return requireClientCert; - } + public Boolean getRequireClientCert() { + return requireClientCert; + } - public void setRequireClientCert(Boolean requireClientCert) { - this.requireClientCert = requireClientCert; - } + public void setRequireClientCert(Boolean requireClientCert) { + this.requireClientCert = requireClientCert; + } - public String getMethod() { - return method; - } + public String getMethod() { + return method; + } - public void setMethod(String method) { - this.method = method; - } + public void setMethod(String method) { + this.method = method; + } - public String getCipher() { - return cipher; - } + public String getCipher() { + return cipher; + } - public void setCipher(String cipher) { - this.cipher = cipher; - } + public void setCipher(String cipher) { + this.cipher = cipher; + } - public String getLocalNet() { - return localNet; - } + public String getLocalNet() { + return localNet; + } - public void setLocalNet(String localNet) { - this.localNet = localNet; - } + public void setLocalNet(String localNet) { + this.localNet = localNet; + } - public String getTos() { - return tos; - } + public String getTos() { + return tos; + } - public void setTos(String tos) { - this.tos = tos; - } + public void setTos(String tos) { + this.tos = tos; + } - public int getCos() { - return cos; - } + public int getCos() { + return cos; + } - public void setCos(int cos) { - this.cos = cos; - } + public void setCos(int cos) { + this.cos = cos; + } - public int getWebsocketWriteTimeout() { - return websocketWriteTimeout; - } + public int getWebsocketWriteTimeout() { + return websocketWriteTimeout; + } - public void setWebsocketWriteTimeout(int websocketWriteTimeout) { - this.websocketWriteTimeout = websocketWriteTimeout; - } + public void setWebsocketWriteTimeout(int websocketWriteTimeout) { + this.websocketWriteTimeout = websocketWriteTimeout; + } - public String getEndpointName() { - return endpointName; - } + public String getEndpointName() { + return endpointName; + } - public void setEndpointName(String endpointName) { - this.endpointName = endpointName; - } + public void setEndpointName(String endpointName) { + this.endpointName = endpointName; + } - public static long getSerialversionuid() { - return serialVersionUID; - } + public static long getSerialversionuid() { + return serialVersionUID; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/UnholdEvent.java b/src/main/java/org/asteriskjava/manager/event/UnholdEvent.java index dbfce1eca..a17771658 100644 --- a/src/main/java/org/asteriskjava/manager/event/UnholdEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/UnholdEvent.java @@ -30,23 +30,21 @@ * @version $Id$ * @see org.asteriskjava.manager.event.HoldEvent * @since 0.2 Enro 2015-03: No longer deprecated since Asterisk 13 uses this - * again. + * again. */ -public class UnholdEvent extends AbstractHoldEvent -{ +public class UnholdEvent extends AbstractHoldEvent { /** * Serializable version identifier. */ static final long serialVersionUID = 1L; - - + + /** * Creates a new UnholdEvent. * * @param source */ - public UnholdEvent(Object source) - { + public UnholdEvent(Object source) { super(source); setStatus(false); } diff --git a/src/main/java/org/asteriskjava/manager/event/UnlinkEvent.java b/src/main/java/org/asteriskjava/manager/event/UnlinkEvent.java index 5a53f0e4c..075d7031b 100644 --- a/src/main/java/org/asteriskjava/manager/event/UnlinkEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/UnlinkEvent.java @@ -20,21 +20,20 @@ * An UnlinkEvent is triggered when a link between two voice channels is discontinued, for example, * just before call completion.

    * It is implemented in channel.c - * + * * @author srt * @version $Id$ * @deprecated as of 1.0.0, use {@link org.asteriskjava.manager.event.BridgeEvent} and - * {@link BridgeEvent#isUnlink()} instead + * {@link BridgeEvent#isUnlink()} instead */ -@Deprecated public class UnlinkEvent extends BridgeEvent -{ +@Deprecated +public class UnlinkEvent extends BridgeEvent { /** * Serial version identifier. */ static final long serialVersionUID = -2943257621137870024L; - public UnlinkEvent(Object source) - { + public UnlinkEvent(Object source) { super(source); setBridgeState(BRIDGE_STATE_UNLINK); } diff --git a/src/main/java/org/asteriskjava/manager/event/UnparkedCallEvent.java b/src/main/java/org/asteriskjava/manager/event/UnparkedCallEvent.java index f8fa999a9..6795b6521 100644 --- a/src/main/java/org/asteriskjava/manager/event/UnparkedCallEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/UnparkedCallEvent.java @@ -23,13 +23,12 @@ * It is implemented in res/res_features.c *

    * Available since Asterisk 1.2 - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class UnparkedCallEvent extends AbstractUnParkedEvent -{ +public class UnparkedCallEvent extends AbstractUnParkedEvent { /** * Serializable version identifier */ @@ -54,128 +53,103 @@ public class UnparkedCallEvent extends AbstractUnParkedEvent /** * @param source */ - public UnparkedCallEvent(Object source) - { + public UnparkedCallEvent(Object source) { super(source); } - public String getRetrieverChannel() - { + public String getRetrieverChannel() { return RetrieverChannel; } - public void setRetrieverChannel(String retrieverChannel) - { + public void setRetrieverChannel(String retrieverChannel) { RetrieverChannel = retrieverChannel; } - public Integer getRetrieverChannelState() - { + public Integer getRetrieverChannelState() { return RetrieverChannelState; } - public void setRetrieverChannelState(Integer retrieverChannelState) - { + public void setRetrieverChannelState(Integer retrieverChannelState) { RetrieverChannelState = retrieverChannelState; } - public String getRetrieverChannelStateDesc() - { + public String getRetrieverChannelStateDesc() { return RetrieverChannelStateDesc; } - public void setRetrieverChannelStateDesc(String retrieverChannelStateDesc) - { + public void setRetrieverChannelStateDesc(String retrieverChannelStateDesc) { RetrieverChannelStateDesc = retrieverChannelStateDesc; } - public String getRetrieverCallerIDNum() - { + public String getRetrieverCallerIDNum() { return RetrieverCallerIDNum; } - public void setRetrieverCallerIDNum(String retrieverCallerIDNum) - { + public void setRetrieverCallerIDNum(String retrieverCallerIDNum) { RetrieverCallerIDNum = retrieverCallerIDNum; } - public String getRetrieverCallerIDName() - { + public String getRetrieverCallerIDName() { return RetrieverCallerIDName; } - public void setRetrieverCallerIDName(String retrieverCallerIDName) - { + public void setRetrieverCallerIDName(String retrieverCallerIDName) { RetrieverCallerIDName = retrieverCallerIDName; } - public String getRetrieverConnectedLineNum() - { + public String getRetrieverConnectedLineNum() { return RetrieverConnectedLineNum; } - public void setRetrieverConnectedLineNum(String retrieverConnectedLineNum) - { + public void setRetrieverConnectedLineNum(String retrieverConnectedLineNum) { RetrieverConnectedLineNum = retrieverConnectedLineNum; } - public String getRetrieverConnectedLineName() - { + public String getRetrieverConnectedLineName() { return RetrieverConnectedLineName; } - public void setRetrieverConnectedLineName(String retrieverConnectedLineName) - { + public void setRetrieverConnectedLineName(String retrieverConnectedLineName) { RetrieverConnectedLineName = retrieverConnectedLineName; } - public String getRetrieverAccountCode() - { + public String getRetrieverAccountCode() { return RetrieverAccountCode; } - public void setRetrieverAccountCode(String retrieverAccountCode) - { + public void setRetrieverAccountCode(String retrieverAccountCode) { RetrieverAccountCode = retrieverAccountCode; } - public String getRetrieverContext() - { + public String getRetrieverContext() { return RetrieverContext; } - public void setRetrieverContext(String retrieverContext) - { + public void setRetrieverContext(String retrieverContext) { RetrieverContext = retrieverContext; } - public String getRetrieverExten() - { + public String getRetrieverExten() { return RetrieverExten; } - public void setRetrieverExten(String retrieverExten) - { + public void setRetrieverExten(String retrieverExten) { RetrieverExten = retrieverExten; } - public String getRetrieverPriority() - { + public String getRetrieverPriority() { return RetrieverPriority; } - public void setRetrieverPriority(String retrieverPriority) - { + public void setRetrieverPriority(String retrieverPriority) { RetrieverPriority = retrieverPriority; } - public String getRetrieverUniqueid() - { + public String getRetrieverUniqueid() { return RetrieverUniqueid; } - public void setRetrieverUniqueid(String retrieverUniqueid) - { + public void setRetrieverUniqueid(String retrieverUniqueid) { RetrieverUniqueid = retrieverUniqueid; } } diff --git a/src/main/java/org/asteriskjava/manager/event/UnpausedEvent.java b/src/main/java/org/asteriskjava/manager/event/UnpausedEvent.java index 76ea9fe00..cd6196e0e 100644 --- a/src/main/java/org/asteriskjava/manager/event/UnpausedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/UnpausedEvent.java @@ -2,33 +2,33 @@ public class UnpausedEvent extends UserEvent { - public UnpausedEvent(Object source) { - super(source); - } - - /** - * - */ - private static final long serialVersionUID = 4175034098824101733L; - - private String header; - - private String extension; - - public String getHeader() { - return header; - } - - public void setHeader(String header) { - this.header = header; - } - - public String getExtension() { - return extension; - } - - public void setExtension(String extension) { - this.extension = extension; - } + public UnpausedEvent(Object source) { + super(source); + } + + /** + * + */ + private static final long serialVersionUID = 4175034098824101733L; + + private String header; + + private String extension; + + public String getHeader() { + return header; + } + + public void setHeader(String header) { + this.header = header; + } + + public String getExtension() { + return extension; + } + + public void setExtension(String extension) { + this.extension = extension; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/UserEvent.java b/src/main/java/org/asteriskjava/manager/event/UserEvent.java index 153a82496..6a8f6a377 100644 --- a/src/main/java/org/asteriskjava/manager/event/UserEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/UserEvent.java @@ -34,29 +34,29 @@ * methods in your new class. *

    * Example: - * + * *

      * public class VIPCallEvent extends UserEvent
      * {
      *     private String firstName;
    - * 
    + *
      *     public VIPCallEvent(Object source)
      *     {
      *         super(source);
      *     }
    - * 
    + *
      *     public String getFirstName()
      *     {
      *         return firstName;
      *     }
    - * 
    + *
      *     public void setFirstName(String firstName)
      *     {
      *         this.firstName = firstName;
      *     }
      * }
      * 
    - * + *

    * To send this event use UserEvent(VIPCall|firstName: Jon) in your * dialplan. Asterisk up to 1.2 (including) does only support one property in * the UserEvent so something like @@ -67,13 +67,12 @@ *

    * Note that you must register your UserEvent with the ManagerConnection you are * using in order to be recognized. - * - * @see org.asteriskjava.manager.ManagerConnection#registerUserEventClass(Class) + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.ManagerConnection#registerUserEventClass(Class) */ -public abstract class UserEvent extends ManagerEvent -{ +public abstract class UserEvent extends ManagerEvent { /** * Serial version identifier */ @@ -89,48 +88,43 @@ public abstract class UserEvent extends ManagerEvent */ private String uniqueId; - public UserEvent(Object source) - { + public UserEvent(Object source) { super(source); } /** * Returns the name of the channel this event occured in. - * + * * @return the name of the channel this event occured in. */ - public String getChannel() - { + public String getChannel() { return channel; } /** * Sets the name of the channel this event occured in. - * + * * @param channel the name of the channel this event occured in. */ - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } /** * Returns the unqiue id of the channel this event occured in. - * + * * @return the unqiue id of the channel this event occured in. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } /** * Sets the unqiue id of the channel this event occured in. - * + * * @param uniqueId the unqiue id of the channel this event occured in. */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } } diff --git a/src/main/java/org/asteriskjava/manager/event/VarSetEvent.java b/src/main/java/org/asteriskjava/manager/event/VarSetEvent.java index 3b5feda69..2bf16e395 100644 --- a/src/main/java/org/asteriskjava/manager/event/VarSetEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/VarSetEvent.java @@ -28,8 +28,7 @@ * @version $Id$ * @since 1.0.0 */ -public class VarSetEvent extends ManagerEvent -{ +public class VarSetEvent extends ManagerEvent { static final long serialVersionUID = 1L; private String channel; @@ -40,18 +39,15 @@ public class VarSetEvent extends ManagerEvent private String linkedId; private String accountCode; - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public VarSetEvent(Object source) - { + public VarSetEvent(Object source) { super(source); } @@ -60,15 +56,13 @@ public VarSetEvent(Object source) * variables. * * @return the name of the channel or null for global - * variables. + * variables. */ - public String getChannel() - { + public String getChannel() { return channel; } - public void setChannel(String channel) - { + public void setChannel(String channel) { this.channel = channel; } @@ -77,15 +71,13 @@ public void setChannel(String channel) * variables. * * @return the unique id of the channel or null for global - * variables. + * variables. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -94,13 +86,11 @@ public void setUniqueId(String uniqueId) * * @return the name of the variable that has been set. */ - public String getVariable() - { + public String getVariable() { return variable; } - public void setVariable(String variable) - { + public void setVariable(String variable) { this.variable = variable; } @@ -109,34 +99,28 @@ public void setVariable(String variable) * * @return the new value of the variable. */ - public String getValue() - { + public String getValue() { return value; } - public void setValue(String value) - { + public void setValue(String value) { this.value = value; } - public String getLinkedId() - { + public String getLinkedId() { return linkedId; } - public void setLinkedId(String linkedId) - { + public void setLinkedId(String linkedId) { this.linkedId = linkedId; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - + } diff --git a/src/main/java/org/asteriskjava/manager/event/VoicemailUserEntryCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/VoicemailUserEntryCompleteEvent.java index 46039db1a..6f1aebdad 100644 --- a/src/main/java/org/asteriskjava/manager/event/VoicemailUserEntryCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/VoicemailUserEntryCompleteEvent.java @@ -23,14 +23,13 @@ *

    * Available since Asterisk 1.6 * - * @see VoicemailUserEntryEvent - * @see org.asteriskjava.manager.action.VoicemailUsersListAction * @author srt * @version $Id$ + * @see VoicemailUserEntryEvent + * @see org.asteriskjava.manager.action.VoicemailUsersListAction * @since 1.0.0 */ -public class VoicemailUserEntryCompleteEvent extends ResponseEvent -{ +public class VoicemailUserEntryCompleteEvent extends ResponseEvent { /** * Serial version identifier. */ @@ -41,8 +40,7 @@ public class VoicemailUserEntryCompleteEvent extends ResponseEvent * * @param source */ - public VoicemailUserEntryCompleteEvent(Object source) - { + public VoicemailUserEntryCompleteEvent(Object source) { super(source); } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/VoicemailUserEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/VoicemailUserEntryEvent.java index ede012636..8fbc8fd14 100644 --- a/src/main/java/org/asteriskjava/manager/event/VoicemailUserEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/VoicemailUserEntryEvent.java @@ -29,8 +29,7 @@ * @see org.asteriskjava.manager.action.VoicemailUsersListAction * @since 1.0.0 */ -public class VoicemailUserEntryEvent extends ResponseEvent -{ +public class VoicemailUserEntryEvent extends ResponseEvent { /** * Serial version identifier. */ @@ -70,8 +69,7 @@ public class VoicemailUserEntryEvent extends ResponseEvent * * @param source */ - public VoicemailUserEntryEvent(Object source) - { + public VoicemailUserEntryEvent(Object source) { super(source); } @@ -80,8 +78,7 @@ public VoicemailUserEntryEvent(Object source) * * @return the voicemail context. */ - public String getVmContext() - { + public String getVmContext() { return vmContext; } @@ -90,8 +87,7 @@ public String getVmContext() * * @param vmContext the voicemail context. */ - public void setVmContext(String vmContext) - { + public void setVmContext(String vmContext) { this.vmContext = vmContext; } @@ -100,8 +96,7 @@ public void setVmContext(String vmContext) * * @return the mailbox id. */ - public String getVoicemailbox() - { + public String getVoicemailbox() { return voicemailbox; } @@ -110,8 +105,7 @@ public String getVoicemailbox() * * @param voicemailbox the mailbox id. */ - public void setVoicemailbox(String voicemailbox) - { + public void setVoicemailbox(String voicemailbox) { this.voicemailbox = voicemailbox; } @@ -120,8 +114,7 @@ public void setVoicemailbox(String voicemailbox) * * @return the full name of the voicemail user. */ - public String getFullname() - { + public String getFullname() { return fullname; } @@ -130,8 +123,7 @@ public String getFullname() * * @param fullname the full name of the voicemail user. */ - public void setFullname(String fullname) - { + public void setFullname(String fullname) { this.fullname = fullname; } @@ -140,8 +132,7 @@ public void setFullname(String fullname) * * @return the email address of the voicemail user. */ - public String getEmail() - { + public String getEmail() { return email; } @@ -150,8 +141,7 @@ public String getEmail() * * @param email the email address of the voicemail user. */ - public void setEmail(String email) - { + public void setEmail(String email) { this.email = email; } @@ -161,8 +151,7 @@ public void setEmail(String email) * * @return the email adress of pager of the voicemail user. */ - public String getPager() - { + public String getPager() { return pager; } @@ -171,8 +160,7 @@ public String getPager() * * @param pager the email adress of pager of the voicemail user. */ - public void setPager(String pager) - { + public void setPager(String pager) { this.pager = pager; } @@ -181,8 +169,7 @@ public void setPager(String pager) * * @return the email address used for the "from" header when sending notification emails. */ - public String getServerEmail() - { + public String getServerEmail() { return serverEmail; } @@ -191,8 +178,7 @@ public String getServerEmail() * * @param serverEmail the email address used for the "from" header when sending notification emails. */ - public void setServerEmail(String serverEmail) - { + public void setServerEmail(String serverEmail) { this.serverEmail = serverEmail; } @@ -201,8 +187,7 @@ public void setServerEmail(String serverEmail) * * @return the custom mail command used to send notifications to the voicemail user. */ - public String getMailCommand() - { + public String getMailCommand() { return mailCommand; } @@ -211,28 +196,23 @@ public String getMailCommand() * * @param mailCommand the custom mail command used to send notifications to the voicemail user. */ - public void setMailCommand(String mailCommand) - { + public void setMailCommand(String mailCommand) { this.mailCommand = mailCommand; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getTimezone() - { + public String getTimezone() { return timezone; } - public void setTimezone(String timezone) - { + public void setTimezone(String timezone) { this.timezone = timezone; } @@ -241,10 +221,9 @@ public void setTimezone(String timezone) * voicemail features menu. * * @return the dialplan context used by the "return phone call" feature in the advanced - * voicemail features menu. + * voicemail features menu. */ - public String getCallback() - { + public String getCallback() { return callback; } @@ -255,8 +234,7 @@ public String getCallback() * @param callback the dialplan context used by the "return phone call" feature in the advanced * voicemail features menu. */ - public void setCallback(String callback) - { + public void setCallback(String callback) { this.callback = callback; } @@ -265,10 +243,9 @@ public void setCallback(String callback) * voicemail features menu. * * @return the dialplan context used by the "place an outgoing call" feature in the advanced - * voicemail features menu. + * voicemail features menu. */ - public String getDialout() - { + public String getDialout() { return dialout; } @@ -279,18 +256,15 @@ public String getDialout() * @param dialout the dialplan context used by the "place an outgoing call" feature in the advanced * voicemail features menu. */ - public void setDialout(String dialout) - { + public void setDialout(String dialout) { this.dialout = dialout; } - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } @@ -299,8 +273,7 @@ public void setUniqueId(String uniqueId) * * @return the dialplan context the user is dropped into after he has pressed * or 0 to exit voicemail. */ - public String getExitContext() - { + public String getExitContext() { return exitContext; } @@ -309,38 +282,31 @@ public String getExitContext() * * @param exitContext the dialplan context the user is dropped into after he has pressed * or 0 to exit voicemail. */ - public void setExitContext(String exitContext) - { + public void setExitContext(String exitContext) { this.exitContext = exitContext; } - public Integer getSayDurationMinimum() - { + public Integer getSayDurationMinimum() { return sayDurationMinimum; } - public void setSayDurationMinimum(Integer sayDurationMinimum) - { + public void setSayDurationMinimum(Integer sayDurationMinimum) { this.sayDurationMinimum = sayDurationMinimum; } - public Boolean getSayEnvelope() - { + public Boolean getSayEnvelope() { return sayEnvelope; } - public void setSayEnvelope(Boolean sayEnvelope) - { + public void setSayEnvelope(Boolean sayEnvelope) { this.sayEnvelope = sayEnvelope; } - public Boolean getSayCid() - { + public Boolean getSayCid() { return sayCid; } - public void setSayCid(Boolean sayCid) - { + public void setSayCid(Boolean sayCid) { this.sayCid = sayCid; } @@ -350,8 +316,7 @@ public void setSayCid(Boolean sayCid) * * @return Booelan.TRUE if message will be attached, Boolean.FALSE if not, null if unset. */ - public Boolean getAttachMessage() - { + public Boolean getAttachMessage() { return attachMessage; } @@ -361,18 +326,15 @@ public Boolean getAttachMessage() * * @param attachMessage Booelan.TRUE if message will be attached, Boolean.FALSE if not, null if unset. */ - public void setAttachMessage(Boolean attachMessage) - { + public void setAttachMessage(Boolean attachMessage) { this.attachMessage = attachMessage; } - public String getAttachmentFormat() - { + public String getAttachmentFormat() { return attachmentFormat; } - public void setAttachmentFormat(String attachmentFormat) - { + public void setAttachmentFormat(String attachmentFormat) { this.attachmentFormat = attachmentFormat; } @@ -380,10 +342,9 @@ public void setAttachmentFormat(String attachmentFormat) * Returns whether messages will be deleted from the voicemailbox (after having been emailed). * * @return Booelan.TRUE if messages will be deleted from the voicemailbox, Boolean.FALSE if not, - * null if unset. + * null if unset. */ - public Boolean getDeleteMessage() - { + public Boolean getDeleteMessage() { return deleteMessage; } @@ -392,8 +353,7 @@ public Boolean getDeleteMessage() * * @param deleteMessage Booelan.TRUE if messages will be deleted from the voicemailbox, Boolean.FALSE if not. */ - public void setDeleteMessage(Boolean deleteMessage) - { + public void setDeleteMessage(Boolean deleteMessage) { this.deleteMessage = deleteMessage; } @@ -402,8 +362,7 @@ public void setDeleteMessage(Boolean deleteMessage) * * @return the volume gain used for voicemails sent via email. */ - public Double getVolumeGain() - { + public Double getVolumeGain() { return volumeGain; } @@ -412,28 +371,23 @@ public Double getVolumeGain() * * @param volumeGain the volume gain used for voicemails sent via email. */ - public void setVolumeGain(Double volumeGain) - { + public void setVolumeGain(Double volumeGain) { this.volumeGain = volumeGain; } - public Boolean getCanReview() - { + public Boolean getCanReview() { return canReview; } - public void setCanReview(Boolean canReview) - { + public void setCanReview(Boolean canReview) { this.canReview = canReview; } - public Boolean getCallOperator() - { + public Boolean getCallOperator() { return callOperator; } - public void setCallOperator(Boolean callOperator) - { + public void setCallOperator(Boolean callOperator) { this.callOperator = callOperator; } @@ -442,8 +396,7 @@ public void setCallOperator(Boolean callOperator) * * @return the maximum number of messages per folder or 0 for unlimited. */ - public Integer getMaxMessageCount() - { + public Integer getMaxMessageCount() { return maxMessageCount; } @@ -452,8 +405,7 @@ public Integer getMaxMessageCount() * * @param maxMessageCount the maximum number of messages per folder. */ - public void setMaxMessageCount(Integer maxMessageCount) - { + public void setMaxMessageCount(Integer maxMessageCount) { this.maxMessageCount = maxMessageCount; } @@ -462,8 +414,7 @@ public void setMaxMessageCount(Integer maxMessageCount) * * @return the maximum duration in seconds. */ - public Integer getMaxMessageLength() - { + public Integer getMaxMessageLength() { return maxMessageLength; } @@ -472,18 +423,15 @@ public Integer getMaxMessageLength() * * @param maxMessageLength the maximum duration in seconds. */ - public void setMaxMessageLength(Integer maxMessageLength) - { + public void setMaxMessageLength(Integer maxMessageLength) { this.maxMessageLength = maxMessageLength; } - public Integer getNewMessageCount() - { + public Integer getNewMessageCount() { return newMessageCount; } - public void setNewMessageCount(Integer newMessageCount) - { + public void setNewMessageCount(Integer newMessageCount) { this.newMessageCount = newMessageCount; } @@ -493,8 +441,7 @@ public void setNewMessageCount(Integer newMessageCount) * * @return the number of old messages for this voicemail user. */ - public Integer getOldMessageCount() - { + public Integer getOldMessageCount() { return oldMessageCount; } @@ -503,8 +450,7 @@ public Integer getOldMessageCount() * * @param oldMessageCount the number of old messages for this voicemail user. */ - public void setOldMessageCount(Integer oldMessageCount) - { + public void setOldMessageCount(Integer oldMessageCount) { this.oldMessageCount = oldMessageCount; } @@ -514,8 +460,7 @@ public void setOldMessageCount(Integer oldMessageCount) * * @return the username of the IMAP account associated with this mailbox. */ - public String getImapUser() - { + public String getImapUser() { return imapUser; } @@ -524,8 +469,7 @@ public String getImapUser() * * @param imapUser the username of the IMAP account associated with this mailbox. */ - public void setImapUser(String imapUser) - { + public void setImapUser(String imapUser) { this.imapUser = imapUser; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/ZapShowChannelsCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/ZapShowChannelsCompleteEvent.java index fef123bf9..55e10313e 100644 --- a/src/main/java/org/asteriskjava/manager/event/ZapShowChannelsCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ZapShowChannelsCompleteEvent.java @@ -19,15 +19,13 @@ /** * A ZapShowChannelsCompleteEvent is triggered after the state of all zap channels has been reported * in response to a ZapShowChannelsAction. - * - * @see org.asteriskjava.manager.action.ZapShowChannelsAction - * @see org.asteriskjava.manager.event.ZapShowChannelsEvent - * + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.ZapShowChannelsAction + * @see org.asteriskjava.manager.event.ZapShowChannelsEvent */ -public class ZapShowChannelsCompleteEvent extends ResponseEvent -{ +public class ZapShowChannelsCompleteEvent extends ResponseEvent { /** * Serial version identifier */ @@ -36,8 +34,7 @@ public class ZapShowChannelsCompleteEvent extends ResponseEvent /** * @param source */ - public ZapShowChannelsCompleteEvent(Object source) - { + public ZapShowChannelsCompleteEvent(Object source) { super(source); } } diff --git a/src/main/java/org/asteriskjava/manager/event/ZapShowChannelsEvent.java b/src/main/java/org/asteriskjava/manager/event/ZapShowChannelsEvent.java index 062e1b391..5460927b2 100644 --- a/src/main/java/org/asteriskjava/manager/event/ZapShowChannelsEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ZapShowChannelsEvent.java @@ -19,13 +19,12 @@ /** * A ZapShowChannelsEvent is triggered in response to a ZapShowChannelsAction * and shows the state of a zap channel. - * - * @see org.asteriskjava.manager.action.ZapShowChannelsAction + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.ZapShowChannelsAction */ -public class ZapShowChannelsEvent extends ResponseEvent -{ +public class ZapShowChannelsEvent extends ResponseEvent { /** * Serial version identifier */ @@ -39,24 +38,21 @@ public class ZapShowChannelsEvent extends ResponseEvent /** * @param source */ - public ZapShowChannelsEvent(Object source) - { + public ZapShowChannelsEvent(Object source) { super(source); } /** * Returns the number of this zap channel. */ - public Integer getChannel() - { + public Integer getChannel() { return channel; } /** * Sets the number of this zap channel. */ - public void setChannel(Integer channel) - { + public void setChannel(Integer channel) { this.channel = channel; } @@ -90,40 +86,36 @@ public void setChannel(Integer channel) *

  • Pseudo Signalling
  • * */ - public String getSignalling() - { + public String getSignalling() { return signalling; } /** * Sets the signalling of this zap channel. */ - public void setSignalling(String signalling) - { + public void setSignalling(String signalling) { this.signalling = signalling; } /** * Returns whether dnd (do not disturb) is enabled for this zap channel. - * + * * @return Boolean.TRUE if dnd is enabled, Boolean.FALSE if it is disabled, - * null if not set. + * null if not set. * @since 0.3 */ - public Boolean getDnd() - { + public Boolean getDnd() { return dnd; } /** * Sets whether dnd (do not disturb) is enabled for this zap channel. - * + * * @param dnd Boolean.TRUE if dnd is enabled, Boolean.FALSE if it is * disabled. * @since 0.3 */ - public void setDnd(Boolean dnd) - { + public void setDnd(Boolean dnd) { this.dnd = dnd; } @@ -141,16 +133,14 @@ public void setDnd(Boolean dnd) *
  • No Alarm
  • * */ - public String getAlarm() - { + public String getAlarm() { return alarm; } /** * Sets the alarm state of this zap channel. */ - public void setAlarm(String alarm) - { + public void setAlarm(String alarm) { this.alarm = alarm; } } diff --git a/src/main/java/org/asteriskjava/manager/event/package.html b/src/main/java/org/asteriskjava/manager/event/package.html index d6d1dcb81..92e1e1d1d 100644 --- a/src/main/java/org/asteriskjava/manager/event/package.html +++ b/src/main/java/org/asteriskjava/manager/event/package.html @@ -1,28 +1,28 @@ - +

    Provides classes that represent the standard events that can be received - from an Asterisk server via the Manager API.

    + from an Asterisk server via the Manager API.

    - \ No newline at end of file + diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index 26f11e8cf..62262be6e 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -1,5 +1,12 @@ package org.asteriskjava.manager.internal; +import org.asteriskjava.manager.event.UserEvent; +import org.asteriskjava.manager.response.ManagerResponse; +import org.asteriskjava.util.AstUtil; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; +import org.asteriskjava.util.ReflectionUtil; + import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.LinkedHashMap; @@ -8,34 +15,23 @@ import java.util.Map.Entry; import java.util.Set; -import org.asteriskjava.manager.event.UserEvent; -import org.asteriskjava.manager.response.ManagerResponse; -import org.asteriskjava.util.AstUtil; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; -import org.asteriskjava.util.ReflectionUtil; - /** * Abstract base class for reflection based builders. */ -abstract class AbstractBuilder -{ +abstract class AbstractBuilder { protected final Log logger = LogFactory.getLog(getClass()); - protected void setAttributes(Object target, Map attributes, Set ignoredAttributes) - { + protected void setAttributes(Object target, Map attributes, Set ignoredAttributes) { Map setters; setters = ReflectionUtil.getSetters(target.getClass()); - for (Map.Entry entry : attributes.entrySet()) - { + for (Map.Entry entry : attributes.entrySet()) { Object value; - final Class< ? > dataType; + final Class dataType; Method setter; String setterName; - if (ignoredAttributes != null && ignoredAttributes.contains(entry.getKey())) - { + if (ignoredAttributes != null && ignoredAttributes.contains(entry.getKey())) { continue; } @@ -46,88 +42,63 @@ protected void setAttributes(Object target, Map attributes, Set< * defined in java.util.EventObject (the base class of * ManagerEvent), so we have to translate it. */ - if ("source".equals(setterName)) - { + if ("source".equals(setterName)) { setterName = "src"; - } - else if ("class".equals(setterName)) - { + } else if ("class".equals(setterName)) { setterName = "clazz"; } setter = setters.get(setterName); if (setter == null && !setterName.endsWith("s")) // no exact match - // => try plural + // => try plural { setter = setters.get(setterName + "s"); // but only for maps - if (setter != null && !(setter.getParameterTypes()[0].isAssignableFrom(Map.class))) - { + if (setter != null && !(setter.getParameterTypes()[0].isAssignableFrom(Map.class))) { setter = null; } } // it seems silly to warn if it's a user event -- maybe it was // intentional - if (setter == null && !(target instanceof UserEvent) && !target.getClass().equals(ManagerResponse.class)) - { + if (setter == null && !(target instanceof UserEvent) && !target.getClass().equals(ManagerResponse.class)) { logger.warn("Unable to set property '" + entry.getKey() + "' to '" + entry.getValue() + "' on " + target.getClass().getName() + ": no setter. Please report at https://github.com/asterisk-java/asterisk-java/issues"); - for (Entry entry2 : attributes.entrySet()) - { + for (Entry entry2 : attributes.entrySet()) { logger.debug("Key: " + entry2.getKey() + " Value: " + entry2.getValue()); } } - if (setter == null) - { + if (setter == null) { continue; } - try - { + try { dataType = setter.getParameterTypes()[0]; - if (dataType == Boolean.class) - { + if (dataType == Boolean.class) { value = AstUtil.isTrue(entry.getValue()); - } - else if (dataType.isAssignableFrom(String.class)) - { + } else if (dataType.isAssignableFrom(String.class)) { value = parseString(entry); - } - else if (dataType.isAssignableFrom(Map.class)) - { + } else if (dataType.isAssignableFrom(Map.class)) { value = parseMap(entry); - } - else if (dataType.isAssignableFrom(double.class) || dataType.isAssignableFrom(Double.class)) - { + } else if (dataType.isAssignableFrom(double.class) || dataType.isAssignableFrom(Double.class)) { value = parseDouble(entry); - } - else if (dataType.isAssignableFrom(long.class) || dataType.isAssignableFrom(Long.class)) - { + } else if (dataType.isAssignableFrom(long.class) || dataType.isAssignableFrom(Long.class)) { value = parseLong(entry); - } - else if (dataType.isAssignableFrom(int.class) || dataType.isAssignableFrom(Integer.class)) - { + } else if (dataType.isAssignableFrom(int.class) || dataType.isAssignableFrom(Integer.class)) { value = parseInteger(entry); - } - else - { - try - { - Constructor< ? > constructor = dataType.getConstructor(String.class); + } else { + try { + Constructor constructor = dataType.getConstructor(String.class); // Asterisk sometimes uses yes/no instead of True/False for boolean. java.lang.Boolean(String) doesn't handle this. if (dataType.isAssignableFrom(Boolean.class)) { - value = constructor.newInstance(AstUtil.convertAsteriskBooleanStringToStandardBooleanString((String)entry.getValue())); - } - else value = constructor.newInstance(entry.getValue()); - } - catch (Exception e) - { + value = constructor.newInstance(AstUtil.convertAsteriskBooleanStringToStandardBooleanString((String) entry.getValue())); + } else value = constructor.newInstance(entry.getValue()); + } catch (Exception e) { logger.error("Unable to convert value: Called the constructor of " + dataType + " with value '" + entry.getValue() + "' for the attribute '" + entry.getKey() + "'\n of event type " + target.getClass().getName() + " with resulting error: " + e.getMessage(), e); @@ -136,67 +107,50 @@ else if (dataType.isAssignableFrom(int.class) || dataType.isAssignableFrom(Integ } setter.invoke(target, value); - } - catch (Exception e) - { + } catch (Exception e) { logger.error("Unable to set property '" + entry.getKey() + "' to '" + entry.getValue() + "' on " + target.getClass().getName() + " " + e.getMessage(), e); } } } - private Integer parseInteger(Entry entry) - { + private Integer parseInteger(Entry entry) { Integer value; String stringValue = (String) entry.getValue(); - if (stringValue != null && stringValue.length() > 0) - { + if (stringValue != null && stringValue.length() > 0) { value = Integer.parseInt(stringValue); - } - else - { + } else { value = null; } return value; } @SuppressWarnings("unchecked") - private Map parseMap(Map.Entry entry) - { + private Map parseMap(Map.Entry entry) { Map value; - if (entry.getValue() instanceof List) - { + if (entry.getValue() instanceof List) { List list = (List) entry.getValue(); value = buildMap(list.toArray(new String[list.size()])); - } - else if (entry.getValue() instanceof String) - { + } else if (entry.getValue() instanceof String) { value = buildMap((String) entry.getValue()); - } - else - { + } else { value = null; } return value; } @SuppressWarnings("unchecked") - private Object parseString(Map.Entry entry) - { + private Object parseString(Map.Entry entry) { Object value; value = entry.getValue(); - if (AstUtil.isNull(value)) - { + if (AstUtil.isNull(value)) { value = null; } - if (value instanceof List) - { + if (value instanceof List) { StringBuilder strBuff = new StringBuilder(); - for (String tmp : (List) value) - { - if (tmp != null && tmp.length() != 0) - { + for (String tmp : (List) value) { + if (tmp != null && tmp.length() != 0) { strBuff.append(tmp).append('\n'); } } @@ -205,55 +159,41 @@ private Object parseString(Map.Entry entry) return value; } - private Double parseDouble(Map.Entry entry) - { + private Double parseDouble(Map.Entry entry) { Double value; String stringValue = (String) entry.getValue(); - if (stringValue != null && stringValue.length() > 0) - { + if (stringValue != null && stringValue.length() > 0) { value = Double.parseDouble(stringValue); - } - else - { + } else { value = null; } return value; } - private Long parseLong(Map.Entry entry) - { + private Long parseLong(Map.Entry entry) { Long value; String stringValue = (String) entry.getValue(); - if (stringValue != null && stringValue.length() > 0) - { + if (stringValue != null && stringValue.length() > 0) { value = Long.parseLong(stringValue); - } - else - { + } else { value = null; } return value; } - private Map buildMap(String... lines) - { - if (lines == null) - { + private Map buildMap(String... lines) { + if (lines == null) { return null; } final Map map = new LinkedHashMap<>(); - for (String line : lines) - { + for (String line : lines) { final int index = line.indexOf('='); - if (index > 0) - { + if (index > 0) { final String key = line.substring(0, index); final String value = line.substring(index + 1, line.length()); map.put(key, value); - } - else - { + } else { logger.warn("Malformed line '" + line + "' for a map property"); } } diff --git a/src/main/java/org/asteriskjava/manager/internal/ActionBuilder.java b/src/main/java/org/asteriskjava/manager/internal/ActionBuilder.java index 09cc3d44f..eb7bd69ba 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ActionBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/ActionBuilder.java @@ -23,15 +23,14 @@ /** * Transforms ManagerActions to Strings suitable to be sent to Asterisk.

    * The attributes are determined using reflection. - * + * * @author srt * @version $Id$ */ -interface ActionBuilder -{ +interface ActionBuilder { /** * Sets the version of the Asterisk server to built the action for. - * + * * @param targetVersion the version of the target Asterisk server. * @since 0.2 */ @@ -42,7 +41,7 @@ interface ActionBuilder * Asterisk actions consist of an unordered set of key value pairs corresponding to the * attributes of the ManagerActions. Key and value are separated by a colon (":"), key value * pairs by a CR/NL ("\r\n"). An action is terminated by an empty line ("\r\n\r\n"). - * + * * @param action the action to transform * @return a String representing the given action in an asterisk compatible format */ @@ -53,8 +52,8 @@ interface ActionBuilder * Asterisk actions consist of an unordered set of key value pairs corresponding to the * attributes of the ManagerActions. Key and value are separated by a colon (":"), key value * pairs by a CR/NL ("\r\n"). An action is terminated by an empty line ("\r\n\r\n"). - * - * @param action the action to transform + * + * @param action the action to transform * @param internalActionId the internal action id to add * @return a String representing the given action in an asterisk compatible format */ diff --git a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java index e4423b4b5..77f05d445 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java @@ -16,14 +16,6 @@ */ package org.asteriskjava.manager.internal; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.AsteriskMapping; import org.asteriskjava.manager.action.ManagerAction; @@ -33,14 +25,17 @@ import org.asteriskjava.util.LogFactory; import org.asteriskjava.util.ReflectionUtil; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.*; + /** * Default implementation of the ActionBuilder interface. * * @author srt * @version $Id$ */ -class ActionBuilderImpl implements ActionBuilder -{ +class ActionBuilderImpl implements ActionBuilder { private static final String LINE_SEPARATOR = "\r\n"; private static final String ATTRIBUTES_PROPERTY_NAME = "attributes"; @@ -55,10 +50,9 @@ class ActionBuilderImpl implements ActionBuilder /** * Creates a new ActionBuilder for Asterisk 1.0. */ - ActionBuilderImpl() - { + ActionBuilderImpl() { this.targetVersion = AsteriskVersion.ASTERISK_1_0; - + /* * When using the Reflection API to get all of the getters for building * actions to send, we ignore some of the getters @@ -69,32 +63,26 @@ class ActionBuilderImpl implements ActionBuilder this.membersToIgnore.add(ATTRIBUTES_PROPERTY_NAME); } - public void setTargetVersion(AsteriskVersion targetVersion) - { + public void setTargetVersion(AsteriskVersion targetVersion) { this.targetVersion = targetVersion; } - public String buildAction(final ManagerAction action) - { + public String buildAction(final ManagerAction action) { return buildAction(action, null); } @SuppressWarnings("unchecked") - public String buildAction(final ManagerAction action, final String internalActionId) - { + public String buildAction(final ManagerAction action, final String internalActionId) { StringBuilder sb = new StringBuilder(); sb.append("action: "); sb.append(action.getAction()); sb.append(LINE_SEPARATOR); - if (internalActionId != null) - { + if (internalActionId != null) { sb.append("actionid: "); sb.append(ManagerUtil.addInternalActionId(action.getActionId(), internalActionId)); sb.append(LINE_SEPARATOR); - } - else if (action.getActionId() != null) - { + } else if (action.getActionId() != null) { sb.append("actionid: "); sb.append(action.getActionId()); sb.append(LINE_SEPARATOR); @@ -104,19 +92,16 @@ else if (action.getActionId() != null) // if this is a user event action, we need to grab the internal event, // otherwise do below as normal - if (action instanceof UserEventAction) - { + if (action instanceof UserEventAction) { UserEvent userEvent = ((UserEventAction) action).getUserEvent(); appendUserEvent(sb, userEvent); - + getters = ReflectionUtil.getGetters(userEvent.getClass()); // eventually we may want to add more Map keys for events to ignore // when appending appendGetters(sb, userEvent, getters); - } - else - { + } else { getters = ReflectionUtil.getGetters(action.getClass()); appendGetters(sb, action, getters); @@ -124,26 +109,20 @@ else if (action.getActionId() != null) // actions that have the special getAttributes method will // have their Map appended without a singular key or separator - if (getters.containsKey(ATTRIBUTES_PROPERTY_NAME)) - { + if (getters.containsKey(ATTRIBUTES_PROPERTY_NAME)) { Method getter = getters.get(ATTRIBUTES_PROPERTY_NAME); Object value = null; - try - { + try { value = getter.invoke(action); - } - catch (Exception ex) - { + } catch (Exception ex) { logger.error("Unable to retrieve property '" + ATTRIBUTES_PROPERTY_NAME + "' of " + action.getClass(), ex); } - if (value instanceof Map) - { + if (value instanceof Map) { Map attributes = (Map) value; - for (Map.Entry entry : attributes.entrySet()) - { + for (Map.Entry entry : attributes.entrySet()) { appendString(sb, entry.getKey() == null ? "null" : entry.getKey().toString(), - entry.getValue() == null ? "null" : entry.getValue().toString()); + entry.getValue() == null ? "null" : entry.getValue().toString()); } } } @@ -152,75 +131,58 @@ else if (action.getActionId() != null) return sb.toString(); } - private void appendMap(StringBuilder sb, String key, Map values) - { + private void appendMap(StringBuilder sb, String key, Map values) { String singularKey; // strip plural s (i.e. use "variable: " instead of "variables: " - if (key.endsWith("s")) - { + if (key.endsWith("s")) { singularKey = key.substring(0, key.length() - 1); - } - else - { + } else { singularKey = key; } - if (targetVersion.isAtLeast(AsteriskVersion.ASTERISK_1_2)) - { + if (targetVersion.isAtLeast(AsteriskVersion.ASTERISK_1_2)) { appendMap12(sb, singularKey, values); - } - else - { + } else { appendMap10(sb, singularKey, values); } } - private void appendMap10(StringBuilder sb, String singularKey, Map values) - { + private void appendMap10(StringBuilder sb, String singularKey, Map values) { Iterator> entryIterator; sb.append(singularKey); sb.append(": "); entryIterator = values.entrySet().iterator(); - while (entryIterator.hasNext()) - { + while (entryIterator.hasNext()) { Map.Entry entry; entry = entryIterator.next(); sb.append(entry.getKey()); sb.append("="); - if (entry.getValue() != null) - { + if (entry.getValue() != null) { sb.append(entry.getValue()); } - if (entryIterator.hasNext()) - { + if (entryIterator.hasNext()) { sb.append("|"); } } sb.append(LINE_SEPARATOR); } - private void appendMap12(StringBuilder sb, String singularKey, Map values) - { - for (Map.Entry entry : values.entrySet()) - { + private void appendMap12(StringBuilder sb, String singularKey, Map values) { + for (Map.Entry entry : values.entrySet()) { sb.append(singularKey); sb.append(": "); sb.append(entry.getKey()); sb.append("="); - if (entry.getValue() != null) - { - if (entry.getKey().equalsIgnoreCase("Content")) - { + if (entry.getValue() != null) { + if (entry.getKey().equalsIgnoreCase("Content")) { String sp[] = entry.getValue().split("\n"); - if (sp.length > 0) - { + if (sp.length > 0) { sb.append(sp[0]); - for (int i = 1; i < sp.length; i++) - { + for (int i = 1; i < sp.length; i++) { sb.append(LINE_SEPARATOR); sb.append(singularKey); sb.append(": "); @@ -230,9 +192,7 @@ private void appendMap12(StringBuilder sb, String singularKey, Map clazz = event.getClass(); String className = clazz.getName(); String eventType = className.substring(className.lastIndexOf('.') + 1).toLowerCase(Locale.ENGLISH); - if (eventType.endsWith("event")) - { + if (eventType.endsWith("event")) { eventType = eventType.substring(0, eventType.length() - "event".length()); } @@ -265,134 +222,98 @@ private void appendUserEvent(StringBuilder sb, UserEvent event) } @SuppressWarnings("unchecked") - private void appendGetters(StringBuilder sb, Object action, Map getters) - { - for (Map.Entry entry : getters.entrySet()) - { + private void appendGetters(StringBuilder sb, Object action, Map getters) { + for (Map.Entry entry : getters.entrySet()) { final String name = entry.getKey(); final Method getter = entry.getValue(); final Object value; - if (membersToIgnore.contains(name)) - { + if (membersToIgnore.contains(name)) { continue; } - try - { + try { value = getter.invoke(action); - } - catch (Exception ex) - { + } catch (Exception ex) { logger.error("Unable to retrieve property '" + name + "' of " + action.getClass(), ex); continue; } - if (value == null || value instanceof Class) - { + if (value == null || value instanceof Class) { continue; } final String mappedName = mapToAsterisk(getter); - if (value instanceof Map) - { + if (value instanceof Map) { appendMap(sb, mappedName, (Map) value); - } - else if (value instanceof String) - { + } else if (value instanceof String) { appendString(sb, mappedName, (String) value); - } - else - { + } else { appendString(sb, mappedName, value.toString()); } } } - private static String mapToAsterisk(Method getter) - { + private static String mapToAsterisk(Method getter) { AsteriskMapping annotation; // check annotation of getter method annotation - = getter.getAnnotation(AsteriskMapping.class - ); - if (annotation != null) - { + = getter.getAnnotation(AsteriskMapping.class + ); + if (annotation != null) { return annotation.value(); } // check annotation of setter method String setterName = determineSetterName(getter.getName()); - try - { + try { Method setter = getter.getDeclaringClass().getDeclaredMethod(setterName, getter.getReturnType()); annotation - = setter.getAnnotation(AsteriskMapping.class - ); - if (annotation != null) - { + = setter.getAnnotation(AsteriskMapping.class + ); + if (annotation != null) { return annotation.value(); } - } - catch (NoSuchMethodException e) - { + } catch (NoSuchMethodException e) { // ok, no setter method } // check annotation of field String fieldName = determineFieldName(getter.getName()); - try - { + try { Field field = getter.getDeclaringClass().getDeclaredField(fieldName); annotation - = field.getAnnotation(AsteriskMapping.class - ); - if (annotation != null) - { + = field.getAnnotation(AsteriskMapping.class + ); + if (annotation != null) { return annotation.value(); } - } - catch (NoSuchFieldException e) - { + } catch (NoSuchFieldException e) { // ok, no field } return fieldName.toLowerCase(Locale.US); } - static String determineSetterName(String getterName) - { - if (getterName.startsWith("get")) - { + static String determineSetterName(String getterName) { + if (getterName.startsWith("get")) { return "set" + getterName.substring(3); - } - else if (getterName.startsWith("is")) - { + } else if (getterName.startsWith("is")) { return "set" + getterName.substring(2); - } - else - { + } else { throw new IllegalArgumentException("Getter '" + getterName + "' doesn't start with either 'get' or 'is'"); } } - static String determineFieldName(String accessorName) - { - if (accessorName.startsWith("get")) - { + static String determineFieldName(String accessorName) { + if (accessorName.startsWith("get")) { return lcFirst(accessorName.substring(3)); - } - else if (accessorName.startsWith("is")) - { + } else if (accessorName.startsWith("is")) { return lcFirst(accessorName.substring(2)); - } - else if (accessorName.startsWith("set")) - { + } else if (accessorName.startsWith("set")) { return lcFirst(accessorName.substring(3)); - } - else - { + } else { throw new IllegalArgumentException("Accessor '" + accessorName + "' doesn't start with either 'get', 'is' or 'set'"); } } @@ -403,10 +324,8 @@ else if (accessorName.startsWith("set")) * @param s the string to convert. * @return the converted string. */ - private static String lcFirst(String s) - { - if (s == null || s.isEmpty()) - { + private static String lcFirst(String s) { + if (s == null || s.isEmpty()) { return s; } diff --git a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java index 7dd841ee9..d17b6ae4c 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java +++ b/src/main/java/org/asteriskjava/manager/internal/AsyncEventPump.java @@ -1,10 +1,6 @@ package org.asteriskjava.manager.internal; -import java.lang.ref.WeakReference; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - +import com.google.common.util.concurrent.RateLimiter; import org.asteriskjava.lock.Locker; import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.response.ManagerResponse; @@ -12,17 +8,19 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -import com.google.common.util.concurrent.RateLimiter; +import java.lang.ref.WeakReference; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; /** * AsyncEventPump delivers events and responses to a Dispatcher without blocking * the thread which is producing the events and responses. AsyncEventPump also * adds logging around timely handling of events - * + * * @author rsutton */ -public class AsyncEventPump implements Dispatcher, Runnable -{ +public class AsyncEventPump implements Dispatcher, Runnable { private final Log logger = LogFactory.getLog(AsyncEventPump.class); private static final long MAX_SAFE_EVENT_AGE = 500; @@ -38,15 +36,14 @@ public class AsyncEventPump implements Dispatcher, Runnable private final String name; /** - * @param owner: A weak reference to the owner is created, should it be - * garbage collected then AsyncEventPump will shutdown. + * @param owner: A weak reference to the owner is created, should it be + * garbage collected then AsyncEventPump will shutdown. * @param dispatcher: The dispatcher that AsyncEventPump should deliver - * events to. + * events to. * @param threadName: The AsyncEventPump's thread will be named with a - * variant of threadName + * variant of threadName */ - AsyncEventPump(Object owner, Dispatcher dispatcher, String threadName) - { + AsyncEventPump(Object owner, Dispatcher dispatcher, String threadName) { this.dispatcher = dispatcher; this.owner = new WeakReference<>(owner); name = threadName + ":AsyncEventPump"; @@ -55,21 +52,15 @@ public class AsyncEventPump implements Dispatcher, Runnable } @Override - public void run() - { - try - { + public void run() { + try { logger.info("starting"); RateLimiter rateLimiter = RateLimiter.create(2); - while (!stop || !queue.isEmpty()) - { - try - { + while (!stop || !queue.isEmpty()) { + try { EventWrapper wrapper = queue.poll(1, TimeUnit.MINUTES); - if (wrapper != null) - { - if (wrapper.timer.timeTaken() > MAX_SAFE_EVENT_AGE && rateLimiter.tryAcquire()) - { + if (wrapper != null) { + if (wrapper.timer.timeTaken() > MAX_SAFE_EVENT_AGE && rateLimiter.tryAcquire()) { logger.warn("The following message will only appear once per second!\n" + "Event dispatched " + wrapper.timer.timeTaken() + " MS after arriving, your ManagerEvent handlers are too slow!\n" @@ -82,38 +73,25 @@ public void run() // MAX_SAFE_EVENT_AGE int requiredHandlingTime = (int) (MAX_SAFE_EVENT_AGE / Math.max(1, queue.size())); - if (wrapper.response != null) - { + if (wrapper.response != null) { dispatcher.dispatchResponse(wrapper.response, requiredHandlingTime); - } - else if (wrapper.event != null) - { + } else if (wrapper.event != null) { dispatcher.dispatchEvent(wrapper.event, requiredHandlingTime); - } - else if (wrapper.poison != null) - { + } else if (wrapper.poison != null) { wrapper.poison.countDown(); } - } - else if (owner.get() == null) - { + } else if (owner.get() == null) { stop = true; logger.error("The owner has been garbage collected!"); } - } - catch (InterruptedException e) - { + } catch (InterruptedException e) { logger.error(e); - } - catch (Exception e) - { + } catch (Exception e) { logger.error(e, e); } } - } - finally - { + } finally { terminated = true; logger.warn("AsyncEventPump has exited"); } @@ -124,14 +102,11 @@ else if (owner.get() == null) * call stop() to cause the AsyncEventPump to stop, it will first empty the * queue. */ - public void stop() - { + public void stop() { logger.info(name + " Requesting AsyncEventPump to stop"); - if (terminated) - { + if (terminated) { logger.warn(name + " AsyncEventPump is already stopped"); - if (!queue.isEmpty()) - { + if (!queue.isEmpty()) { logger.error(name + " There are unprocessed events in the queue"); } @@ -141,16 +116,12 @@ public void stop() queue.add(poisonWrapper); stop = true; LogTime timer = new LogTime(); - try - { + try { int queueSize = queue.size(); - while (!poisonWrapper.poison.await(5, TimeUnit.SECONDS)) - { + while (!poisonWrapper.poison.await(5, TimeUnit.SECONDS)) { // still waiting for the poison to be consumed. - if (queueSize == queue.size()) - { - if (!terminated) - { + if (queueSize == queue.size()) { + if (!terminated) { Locker.dumpThread(thread, name + " AsyncEventPump thread is blocked here..."); } throw new RuntimeException(name + " Failed to shutdown AsyncEventPump cleanly!"); @@ -159,14 +130,11 @@ public void stop() queueSize = queue.size(); logger.info(name + " Waiting for AsyncEventPump to Stop... "); - if (timer.timeTaken() > 60_000) - { + if (timer.timeTaken() > 60_000) { throw new RuntimeException(name + " Failed to shutdown AsyncEventPump cleanly!"); } } - } - catch (InterruptedException e1) - { + } catch (InterruptedException e1) { logger.error(name + e1.getMessage()); } } @@ -175,10 +143,8 @@ public void stop() * add a ManagerResponse to the queue, only if the queue is not full */ @Override - public void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime) - { - if (!queue.offer(new EventWrapper(response))) - { + public void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime) { + if (!queue.offer(new EventWrapper(response))) { logger.error(name + " Event queue is full, not processing ManagerResponse " + response); } } @@ -187,48 +153,38 @@ public void dispatchResponse(ManagerResponse response, Integer requiredHandlingT * add a ManagerEvent to the queue, only if the queue is not full */ @Override - public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) - { - if (!queue.offer(new EventWrapper(event))) - { + public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) { + if (!queue.offer(new EventWrapper(event))) { logger.error(name + " Event queue is full, not processing ManagerEvent " + event); } } - private static class EventWrapper - { + private static class EventWrapper { LogTime timer = new LogTime(); ManagerResponse response; ManagerEvent event; CountDownLatch poison; - EventWrapper() - { + EventWrapper() { // poison poison = new CountDownLatch(1); } - public String getPayloadAsString() - { - if (response != null) - { + public String getPayloadAsString() { + if (response != null) { return response.toString(); - } - else if (event != null) - { + } else if (event != null) { return event.toString(); } return "Poison"; } - EventWrapper(ManagerResponse response) - { + EventWrapper(ManagerResponse response) { this.response = response; } - EventWrapper(ManagerEvent event) - { + EventWrapper(ManagerEvent event) { this.event = event; } diff --git a/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java b/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java index 84c5fcca4..95f36efe0 100644 --- a/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java +++ b/src/main/java/org/asteriskjava/manager/internal/Dispatcher.java @@ -25,20 +25,19 @@ *

    * Do not use this interface in your code, it is intended to be used only by the * DefaultManagerConnection and its ManagerReader. - * + * * @author srt * @version $Id$ */ -interface Dispatcher -{ +interface Dispatcher { /** * This method is called by the reader whenever a {@link ManagerResponse} is * received. The response is dispatched to the associated * {@link org.asteriskjava.manager.SendActionCallback}. - * - * @param response the response received by the reader + * + * @param response the response received by the reader * @param requiredHandlingTime the time that this event must be handled - * within to not cause a back log of events + * within to not cause a back log of events * @see ManagerReader */ void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime); @@ -46,10 +45,10 @@ interface Dispatcher /** * This method is called by the reader whenever a ManagerEvent is received. * The event is dispatched to all registered ManagerEventHandlers. - * - * @param event the event received by the reader + * + * @param event the event received by the reader * @param requiredHandlingTime the time that this event must be handled - * within to not cause a back log of events + * within to not cause a back log of events * @see ManagerReader */ void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime); diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java index 8f1bfdc50..2224dfd2f 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilder.java @@ -16,19 +16,18 @@ */ package org.asteriskjava.manager.internal; -import java.util.Map; - import org.asteriskjava.manager.event.ManagerEvent; +import java.util.Map; + /** * Transforms maps of attributes to instances of ManagerEvent. - * - * @see org.asteriskjava.manager.event.ManagerEvent + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.event.ManagerEvent */ -interface EventBuilder -{ +interface EventBuilder { /** * Registers a new event class. The event this class is registered for is * simply derived from the name of the class by stripping any package name @@ -38,23 +37,23 @@ interface EventBuilder *

    * The event class must be a concrete class with a default constructor (one * that takes no arguments). - * + * * @param clazz the event class to register, must extend - * {@link ManagerEvent}. + * {@link ManagerEvent}. * @throws IllegalArgumentException if clazz is not a valid event class */ - void registerEventClass(Class< ? extends ManagerEvent> clazz) throws IllegalArgumentException; + void registerEventClass(Class clazz) throws IllegalArgumentException; /** * Builds the event based on the given map of attributes and the registered * event classes. - * - * @param source source attribute for the event + * + * @param source source attribute for the event * @param attributes map containing event attributes * @return a concrete instance of ManagerEvent or null if no - * event class was registered for the event type. + * event class was registered for the event type. */ ManagerEvent buildEvent(Object source, Map attributes); - void deregisterEventClass(Class< ? extends ManagerEvent> eventClass); + void deregisterEventClass(Class eventClass); } diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index bfff1b375..b6d39812d 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -16,27 +16,16 @@ */ package org.asteriskjava.manager.internal; -import java.lang.reflect.Constructor; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.PeerEntryEvent; -import org.asteriskjava.manager.event.PeersEvent; -import org.asteriskjava.manager.event.ResponseEvent; -import org.asteriskjava.manager.event.UserEvent; +import org.asteriskjava.manager.event.*; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; import org.reflections.Reflections; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.Map.Entry; + /** * Default implementation of the EventBuilder interface. * @@ -44,19 +33,17 @@ * @version $Id$ * @see org.asteriskjava.manager.event.ManagerEvent */ -class EventBuilderImpl extends AbstractBuilder implements EventBuilder -{ +class EventBuilderImpl extends AbstractBuilder implements EventBuilder { private static final Set ignoredAttributes = new HashSet<>(Arrays.asList("event")); - private Map> registeredEventClasses; + private Map> registeredEventClasses; private final Set eventClassNegativeCache = new HashSet<>(); private static final Log logger = LogFactory.getLog(EventBuilderImpl.class); - private final static Set> knownManagerEventClasses = new Reflections( + private final static Set> knownManagerEventClasses = new Reflections( "org.asteriskjava.manager.event").getSubTypesOf(ManagerEvent.class); - EventBuilderImpl() - { + EventBuilderImpl() { this.registeredEventClasses = new HashMap<>(); registerBuiltinEventClasses(); } @@ -64,32 +51,26 @@ class EventBuilderImpl extends AbstractBuilder implements EventBuilder /** * register the known ManagerEventClasses for this builder */ - private void registerBuiltinEventClasses() - { - for (Class< ? extends ManagerEvent> managerEventClass : knownManagerEventClasses) - { - if (!Modifier.isAbstract(managerEventClass.getModifiers())) - { + private void registerBuiltinEventClasses() { + for (Class managerEventClass : knownManagerEventClasses) { + if (!Modifier.isAbstract(managerEventClass.getModifiers())) { registerEventClass(managerEventClass); } } } - public final void registerEventClass(Class< ? extends ManagerEvent> clazz) throws IllegalArgumentException - { + public final void registerEventClass(Class clazz) throws IllegalArgumentException { String className; String eventType; className = clazz.getName(); eventType = className.substring(className.lastIndexOf('.') + 1).toLowerCase(Locale.ENGLISH); - if (eventType.endsWith("event")) - { + if (eventType.endsWith("event")) { eventType = eventType.substring(0, eventType.length() - "event".length()); } - if (UserEvent.class.isAssignableFrom(clazz) && !eventType.startsWith("userevent")) - { + if (UserEvent.class.isAssignableFrom(clazz) && !eventType.startsWith("userevent")) { eventType = "userevent" + eventType; } @@ -100,36 +81,29 @@ public final void registerEventClass(Class< ? extends ManagerEvent> clazz) throw * Registers a new event class for the event given by eventType. * * @param eventType the name of the event to register the class for. For - * example "Join". - * @param clazz the event class to register, must extend - * {@link ManagerEvent}. + * example "Join". + * @param clazz the event class to register, must extend + * {@link ManagerEvent}. * @throws IllegalArgumentException if clazz is not a valid event class. */ - public final void registerEventClass(String eventType, Class< ? extends ManagerEvent> clazz) - throws IllegalArgumentException - { - Constructor< ? > defaultConstructor; + public final void registerEventClass(String eventType, Class clazz) + throws IllegalArgumentException { + Constructor defaultConstructor; - if (Modifier.isAbstract(clazz.getModifiers())) - { + if (Modifier.isAbstract(clazz.getModifiers())) { throw new IllegalArgumentException(clazz + " is abstract"); } - if (clazz.isInterface()) - { + if (clazz.isInterface()) { throw new IllegalArgumentException(clazz + " is abstract"); } - try - { + try { defaultConstructor = clazz.getConstructor(Object.class); - if (!Modifier.isPublic(defaultConstructor.getModifiers())) - { + if (!Modifier.isPublic(defaultConstructor.getModifiers())) { throw new IllegalArgumentException(clazz + " has no public default constructor"); } - } - catch (NoSuchMethodException ex) - { + } catch (NoSuchMethodException ex) { throw new IllegalArgumentException(clazz + " has no usable constructor"); } @@ -139,54 +113,42 @@ public final void registerEventClass(String eventType, Class< ? extends ManagerE } @SuppressWarnings("unchecked") - public ManagerEvent buildEvent(Object source, Map attributes) - { + public ManagerEvent buildEvent(Object source, Map attributes) { ManagerEvent event; String eventType = null; - Class< ? > eventClass; - Constructor< ? > constructor; + Class eventClass; + Constructor constructor; - if (attributes.get("event") == null) - { + if (attributes.get("event") == null) { logger.error("No event type in properties"); return null; } - if (attributes.get("event") instanceof List) - { - List< ? > eventNames = (List< ? >) attributes.get("event"); - if (!eventNames.isEmpty() && "PeerEntry".equals(eventNames.get(0))) - { + if (attributes.get("event") instanceof List) { + List eventNames = (List) attributes.get("event"); + if (!eventNames.isEmpty() && "PeerEntry".equals(eventNames.get(0))) { // List of PeerEntry events was received (AJ-329) // Convert map of lists to list of maps - one map for each // PeerEntry event int peersAmount = attributes.get("listitems") != null ? Integer.parseInt((String) attributes.get("listitems")) : eventNames.size() - 1; // Last event is - // PeerlistComplete + // PeerlistComplete List> peersAttributes = new ArrayList<>(); - for (Map.Entry attribute : attributes.entrySet()) - { + for (Map.Entry attribute : attributes.entrySet()) { String key = attribute.getKey(); Object value = attribute.getValue(); - for (int i = 0; i < peersAmount; i++) - { + for (int i = 0; i < peersAmount; i++) { Map peerAttrs; - if (peersAttributes.size() > i) - { + if (peersAttributes.size() > i) { peerAttrs = peersAttributes.get(i); - } - else - { + } else { peerAttrs = new HashMap<>(); peersAttributes.add(i, peerAttrs); } - if (value instanceof List) - { - peerAttrs.put(key, ((List< ? >) value).get(i)); - } - else if (value instanceof String && !"listitems".equals(key)) - { + if (value instanceof List) { + peerAttrs.put(key, ((List) value).get(i)); + } else if (value instanceof String && !"listitems".equals(key)) { peerAttrs.put(key, value); } } @@ -194,11 +156,8 @@ else if (value instanceof String && !"listitems".equals(key)) attributes.put("peersAttributes", peersAttributes); eventType = "peers"; } - } - else - { - if (!(attributes.get("event") instanceof String)) - { + } else { + if (!(attributes.get("event") instanceof String)) { logger.error("Event type is not a String or List"); return null; } @@ -208,17 +167,14 @@ else if (value instanceof String && !"listitems".equals(key)) // Change in Asterisk 1.4 where the name of the UserEvent is sent as // property instead // of the event name (AJ-48) - if ("userevent".equals(eventType)) - { + if ("userevent".equals(eventType)) { String userEventType; - if (attributes.get("userevent") == null) - { + if (attributes.get("userevent") == null) { logger.error("No user event type in properties"); return null; } - if (!(attributes.get("userevent") instanceof String)) - { + if (!(attributes.get("userevent") instanceof String)) { logger.error("User event type is not a String"); return null; } @@ -229,73 +185,58 @@ else if (value instanceof String && !"listitems".equals(key)) } eventClass = registeredEventClasses.get(eventType); - if (eventClass == null) - { - if (eventClassNegativeCache.add(eventType)) - { + if (eventClass == null) { + if (eventClassNegativeCache.add(eventType)) { logger.info("No event class registered for event type '" + eventType + "', attributes: " + attributes + ". Please report at https://github.com/asterisk-java/asterisk-java/issues"); } return null; } - try - { + try { constructor = eventClass.getConstructor(Object.class); - } - catch (NoSuchMethodException ex) - { + } catch (NoSuchMethodException ex) { logger.error("Unable to get constructor of " + eventClass.getName(), ex); return null; } - try - { + try { event = (ManagerEvent) constructor.newInstance(source); - } - catch (Exception ex) - { + } catch (Exception ex) { logger.error("Unable to create new instance of " + eventClass.getName(), ex); return null; } - if (attributes.get("peersAttributes") != null && attributes.get("peersAttributes") instanceof List) - { + if (attributes.get("peersAttributes") != null && attributes.get("peersAttributes") instanceof List) { // Fill Peers event with list of PeerEntry events (AJ-329) PeersEvent peersEvent = (PeersEvent) event; // TODO: This cast is very ugly, we should review how attributes are // being passed around. - for (Map peerAttrs : (List>) attributes.get("peersAttributes")) - { + for (Map peerAttrs : (List>) attributes.get("peersAttributes")) { PeerEntryEvent peerEntryEvent = new PeerEntryEvent(source); setAttributes(peerEntryEvent, peerAttrs, ignoredAttributes); List peerEntryEvents = peersEvent.getChildEvents(); - if (peerEntryEvents == null) - { + if (peerEntryEvents == null) { peerEntryEvents = new ArrayList<>(); peersEvent.setChildEvents(peerEntryEvents); } peerEntryEvents.add(peerEntryEvent); } peersEvent.setActionId(peersEvent.getChildEvents().get(0).getActionId()); - } - else - { + } else { setAttributes(event, attributes, ignoredAttributes); } // ResponseEvents are sent in response to a ManagerAction if the // response contains lots of data. They include the actionId of // the corresponding ManagerAction. - if (event instanceof ResponseEvent) - { + if (event instanceof ResponseEvent) { ResponseEvent responseEvent; String actionId; responseEvent = (ResponseEvent) event; actionId = responseEvent.getActionId(); - if (actionId != null) - { + if (actionId != null) { responseEvent.setActionId(ManagerUtil.stripInternalActionId(actionId)); responseEvent.setInternalActionId(ManagerUtil.getInternalActionId(actionId)); } @@ -305,25 +246,18 @@ else if (value instanceof String && !"listitems".equals(key)) } @Override - public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) - { + public void deregisterEventClass(Class eventClass) { Set toRemove = new HashSet<>(); - for (Entry> registered : registeredEventClasses.entrySet()) - { - if (registered.getValue().equals(eventClass)) - { + for (Entry> registered : registeredEventClasses.entrySet()) { + if (registered.getValue().equals(eventClass)) { toRemove.add(registered.getKey()); } } - if (toRemove.isEmpty()) - { + if (toRemove.isEmpty()) { logger.warn("Couldn't remove event type " + eventClass); - } - else - { - for (String key : toRemove) - { + } else { + for (String key : toRemove) { registeredEventClasses.remove(key); logger.warn("Removed event type " + key); } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 053c68888..50cc2cb26 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -16,12 +16,21 @@ */ package org.asteriskjava.manager.internal; -import static org.asteriskjava.manager.ManagerConnectionState.CONNECTED; -import static org.asteriskjava.manager.ManagerConnectionState.CONNECTING; -import static org.asteriskjava.manager.ManagerConnectionState.DISCONNECTED; -import static org.asteriskjava.manager.ManagerConnectionState.DISCONNECTING; -import static org.asteriskjava.manager.ManagerConnectionState.INITIAL; -import static org.asteriskjava.manager.ManagerConnectionState.RECONNECTING; +import org.asteriskjava.AsteriskVersion; +import org.asteriskjava.lock.Lockable; +import org.asteriskjava.lock.LockableList; +import org.asteriskjava.lock.LockableMap; +import org.asteriskjava.lock.Locker.LockCloser; +import org.asteriskjava.manager.*; +import org.asteriskjava.manager.action.*; +import org.asteriskjava.manager.event.*; +import org.asteriskjava.manager.response.*; +import org.asteriskjava.pbx.util.LogTime; +import org.asteriskjava.util.DateUtil; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; +import org.asteriskjava.util.SocketConnectionFacade; +import org.asteriskjava.util.internal.SocketConnectionFacadeImpl; import java.io.IOException; import java.io.Serializable; @@ -38,47 +47,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -import org.asteriskjava.AsteriskVersion; -import org.asteriskjava.lock.Lockable; -import org.asteriskjava.lock.LockableList; -import org.asteriskjava.lock.LockableMap; -import org.asteriskjava.lock.Locker.LockCloser; -import org.asteriskjava.manager.AuthenticationFailedException; -import org.asteriskjava.manager.EventTimeoutException; -import org.asteriskjava.manager.ExpectedResponse; -import org.asteriskjava.manager.ManagerConnection; -import org.asteriskjava.manager.ManagerConnectionState; -import org.asteriskjava.manager.ManagerEventListener; -import org.asteriskjava.manager.ResponseEvents; -import org.asteriskjava.manager.SendActionCallback; -import org.asteriskjava.manager.SendEventGeneratingActionCallback; -import org.asteriskjava.manager.TimeoutException; -import org.asteriskjava.manager.action.ChallengeAction; -import org.asteriskjava.manager.action.CommandAction; -import org.asteriskjava.manager.action.CoreSettingsAction; -import org.asteriskjava.manager.action.EventGeneratingAction; -import org.asteriskjava.manager.action.LoginAction; -import org.asteriskjava.manager.action.LogoffAction; -import org.asteriskjava.manager.action.ManagerAction; -import org.asteriskjava.manager.action.UserEventAction; -import org.asteriskjava.manager.event.ConnectEvent; -import org.asteriskjava.manager.event.DialBeginEvent; -import org.asteriskjava.manager.event.DialEvent; -import org.asteriskjava.manager.event.DisconnectEvent; -import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.ProtocolIdentifierReceivedEvent; -import org.asteriskjava.manager.event.ResponseEvent; -import org.asteriskjava.manager.response.ChallengeResponse; -import org.asteriskjava.manager.response.CommandResponse; -import org.asteriskjava.manager.response.CoreSettingsResponse; -import org.asteriskjava.manager.response.ManagerError; -import org.asteriskjava.manager.response.ManagerResponse; -import org.asteriskjava.pbx.util.LogTime; -import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; -import org.asteriskjava.util.SocketConnectionFacade; -import org.asteriskjava.util.internal.SocketConnectionFacadeImpl; +import static org.asteriskjava.manager.ManagerConnectionState.*; /** * Internal implemention of the ManagerConnection interface. @@ -87,8 +56,7 @@ * @version $Id$ * @see org.asteriskjava.manager.ManagerConnectionFactory */ -public class ManagerConnectionImpl extends Lockable implements ManagerConnection, Dispatcher -{ +public class ManagerConnectionImpl extends Lockable implements ManagerConnection, Dispatcher { private static final int RECONNECTION_INTERVAL_1 = 50; private static final int RECONNECTION_INTERVAL_2 = 5000; private static final String DEFAULT_HOSTNAME = "localhost"; @@ -256,8 +224,7 @@ public class ManagerConnectionImpl extends Lockable implements ManagerConnection /** * Creates a new instance. */ - public ManagerConnectionImpl() - { + public ManagerConnectionImpl() { this.id = idCounter.getAndIncrement(); this.responseListeners = new LockableMap<>(new HashMap<>()); this.responseEventListeners = new LockableMap<>(new HashMap<>()); @@ -267,13 +234,11 @@ public ManagerConnectionImpl() // the following two methods can be overriden when running test cases to // return a mock object - protected ManagerReader createReader(Dispatcher dispatcher, Object source) - { + protected ManagerReader createReader(Dispatcher dispatcher, Object source) { return new ManagerReaderImpl(dispatcher, source); } - protected ManagerWriter createWriter() - { + protected ManagerWriter createWriter() { return new ManagerWriterImpl(); } @@ -284,8 +249,7 @@ protected ManagerWriter createWriter() * * @param hostname the hostname to connect to */ - public void setHostname(String hostname) - { + public void setHostname(String hostname) { this.hostname = hostname; } @@ -297,14 +261,10 @@ public void setHostname(String hostname) * * @param port the port to connect to */ - public void setPort(int port) - { - if (port <= 0) - { + public void setPort(int port) { + if (port <= 0) { this.port = DEFAULT_PORT; - } - else - { + } else { this.port = port; } } @@ -317,8 +277,7 @@ public void setPort(int port) * false for a plain text connection. * @since 0.3 */ - public void setSsl(boolean ssl) - { + public void setSsl(boolean ssl) { this.ssl = ssl; } @@ -328,8 +287,7 @@ public void setSsl(boolean ssl) * * @param username the username to use for login */ - public void setUsername(String username) - { + public void setUsername(String username) { this.username = username; } @@ -339,14 +297,12 @@ public void setUsername(String username) * * @param password the password to use for login */ - public void setPassword(String password) - { + public void setPassword(String password) { this.password = password; } @Override - public void setEncoding(Charset encoding) - { + public void setEncoding(Charset encoding) { this.encoding = encoding; } @@ -359,8 +315,7 @@ public void setEncoding(Charset encoding) * @param defaultResponseTimeout default response timeout in milliseconds * @since 0.2 */ - public void setDefaultResponseTimeout(long defaultResponseTimeout) - { + public void setDefaultResponseTimeout(long defaultResponseTimeout) { this.defaultResponseTimeout = defaultResponseTimeout; } @@ -374,8 +329,7 @@ public void setDefaultResponseTimeout(long defaultResponseTimeout) * @param defaultEventTimeout default event timeout in milliseconds * @since 0.2 */ - public void setDefaultEventTimeout(long defaultEventTimeout) - { + public void setDefaultEventTimeout(long defaultEventTimeout) { this.defaultEventTimeout = defaultEventTimeout; } @@ -385,118 +339,94 @@ public void setDefaultEventTimeout(long defaultEventTimeout) * Default is true. * * @param keepAliveAfterAuthenticationFailure true to try - * reconnecting to ther asterisk serve even if the reconnection - * attempt threw an AuthenticationFailedException, - * false otherwise. + * reconnecting to ther asterisk serve even if the reconnection + * attempt threw an AuthenticationFailedException, + * false otherwise. */ - public void setKeepAliveAfterAuthenticationFailure(boolean keepAliveAfterAuthenticationFailure) - { + public void setKeepAliveAfterAuthenticationFailure(boolean keepAliveAfterAuthenticationFailure) { this.keepAliveAfterAuthenticationFailure = keepAliveAfterAuthenticationFailure; } /* Implementation of ManagerConnection interface */ - public String getUsername() - { + public String getUsername() { return username; } - public String getPassword() - { + public String getPassword() { return password; } @Override - public Charset getEncoding() - { + public Charset getEncoding() { return encoding; } - public AsteriskVersion getVersion() - { + public AsteriskVersion getVersion() { return version; } - public String getHostname() - { + public String getHostname() { return hostname; } - public int getPort() - { + public int getPort() { return port; } - public boolean isSsl() - { + public boolean isSsl() { return ssl; } - public InetAddress getLocalAddress() - { + public InetAddress getLocalAddress() { return socket.getLocalAddress(); } - public int getLocalPort() - { + public int getLocalPort() { return socket.getLocalPort(); } - public InetAddress getRemoteAddress() - { + public InetAddress getRemoteAddress() { return socket.getRemoteAddress(); } - public int getRemotePort() - { + public int getRemotePort() { return socket.getRemotePort(); } - public void registerUserEventClass(Class< ? extends ManagerEvent> userEventClass) - { - if (reader == null) - { + public void registerUserEventClass(Class userEventClass) { + if (reader == null) { reader = createReader(this, this); } reader.registerEventClass(userEventClass); } - public void setSocketTimeout(int socketTimeout) - { + public void setSocketTimeout(int socketTimeout) { this.socketTimeout = socketTimeout; } - public void setSocketReadTimeout(int socketReadTimeout) - { + public void setSocketReadTimeout(int socketReadTimeout) { this.socketReadTimeout = socketReadTimeout; } - public void login() throws IOException, AuthenticationFailedException, TimeoutException - { + public void login() throws IOException, AuthenticationFailedException, TimeoutException { login(null); } - public void login(String eventMask) throws IOException, AuthenticationFailedException, TimeoutException - { - try (LockCloser closer = this.withLock()) - { - if (state != INITIAL && state != DISCONNECTED) - { + public void login(String eventMask) throws IOException, AuthenticationFailedException, TimeoutException { + try (LockCloser closer = this.withLock()) { + if (state != INITIAL && state != DISCONNECTED) { throw new IllegalStateException("Login may only be perfomed when in state " + "INITIAL or DISCONNECTED, but connection is in state " + state); } state = CONNECTING; this.eventMask = eventMask; - try - { + try { doLogin(defaultResponseTimeout, eventMask); - } - finally - { - if (state != CONNECTED) - { + } finally { + if (state != CONNECTED) { state = DISCONNECTED; } } @@ -517,25 +447,23 @@ public void login(String eventMask) throws IOException, AuthenticationFailedExce * the received challenge). * * - * @param timeout the maximum time to wait for the protocol identifier (in - * ms) + * @param timeout the maximum time to wait for the protocol identifier (in + * ms) * @param eventMask the event mask. Set to "on" if all events should be - * send, "off" if not events should be sent or a combination of - * "system", "call" and "log" (separated by ',') to specify what - * kind of events should be sent. - * @throws IOException if there is an i/o problem. + * send, "off" if not events should be sent or a combination of + * "system", "call" and "log" (separated by ',') to specify what + * kind of events should be sent. + * @throws IOException if there is an i/o problem. * @throws AuthenticationFailedException if username or password are - * incorrect and the login action returns an error or if the MD5 - * hash cannot be computed. The connection is closed in this - * case. - * @throws TimeoutException if a timeout occurs while waiting for the - * protocol identifier. The connection is closed in this case. + * incorrect and the login action returns an error or if the MD5 + * hash cannot be computed. The connection is closed in this + * case. + * @throws TimeoutException if a timeout occurs while waiting for the + * protocol identifier. The connection is closed in this case. */ protected void doLogin(long timeout, String eventMask) - throws IOException, AuthenticationFailedException, TimeoutException - { - try (LockCloser closer = this.withLock()) - { + throws IOException, AuthenticationFailedException, TimeoutException { + try (LockCloser closer = this.withLock()) { ChallengeAction challengeAction; ManagerResponse challengeResponse; String challenge; @@ -543,89 +471,68 @@ protected void doLogin(long timeout, String eventMask) LoginAction loginAction; ManagerResponse loginResponse; - if (socket == null) - { + if (socket == null) { connect(); } - if (protocolIdentifier.getValue() == null) - { - try - { + if (protocolIdentifier.getValue() == null) { + try { protocolIdentifier.await(timeout); - } - catch (InterruptedException e) // NOPMD + } catch (InterruptedException e) // NOPMD { Thread.currentThread().interrupt(); } } - if (protocolIdentifier.getValue() == null) - { + if (protocolIdentifier.getValue() == null) { disconnect(); - if (reader != null && reader.getTerminationException() != null) - { + if (reader != null && reader.getTerminationException() != null) { throw reader.getTerminationException(); } throw new TimeoutException("Timeout waiting for protocol identifier"); } challengeAction = new ChallengeAction("MD5"); - try - { + try { challengeResponse = sendAction(challengeAction); - } - catch (Exception e) - { + } catch (Exception e) { disconnect(); throw new AuthenticationFailedException("Unable to send challenge action", e); } - if (challengeResponse instanceof ChallengeResponse) - { + if (challengeResponse instanceof ChallengeResponse) { challenge = ((ChallengeResponse) challengeResponse).getChallenge(); - } - else - { + } else { disconnect(); throw new AuthenticationFailedException("Unable to get challenge from Asterisk. ChallengeAction returned: " + challengeResponse.getMessage()); } - try - { + try { MessageDigest md; md = MessageDigest.getInstance("MD5"); - if (challenge != null) - { + if (challenge != null) { md.update(challenge.getBytes(StandardCharsets.UTF_8)); } - if (password != null) - { + if (password != null) { md.update(password.getBytes(StandardCharsets.UTF_8)); } key = ManagerUtil.toHexString(md.digest()); - } - catch (NoSuchAlgorithmException ex) - { + } catch (NoSuchAlgorithmException ex) { disconnect(); throw new AuthenticationFailedException("Unable to create login key using MD5 Message Digest", ex); } loginAction = new LoginAction(username, "MD5", key, eventMask); - try - { + try { loginResponse = sendAction(loginAction); - } - catch (Exception e) - { + } catch (Exception e) { disconnect(); throw new AuthenticationFailedException("Unable to send login action", e); } - if (loginResponse instanceof ManagerError) - { + if (loginResponse instanceof ManagerError) { disconnect(); throw new AuthenticationFailedException(loginResponse.getMessage()); } @@ -649,40 +556,29 @@ protected void doLogin(long timeout, String eventMask) } } - protected AsteriskVersion determineVersion() throws IOException, TimeoutException - { + protected AsteriskVersion determineVersion() throws IOException, TimeoutException { int attempts = 0; logger.info("Got asterisk protocol identifier version " + protocolIdentifier.getValue()); - while (attempts++ < MAX_VERSION_ATTEMPTS) - { - try - { + while (attempts++ < MAX_VERSION_ATTEMPTS) { + try { AsteriskVersion version = determineVersionByCoreSettings(); if (version != null) return version; - } - catch (Exception e) - { + } catch (Exception e) { } - try - { + try { AsteriskVersion version = determineVersionByCoreShowVersion(); if (version != null) return version; - } - catch (Exception e) - { + } catch (Exception e) { } - try - { + try { Thread.sleep(RECONNECTION_VERSION_INTERVAL); - } - catch (Exception ex) - { + } catch (Exception ex) { // ignore } // NOPMD } @@ -699,12 +595,10 @@ protected AsteriskVersion determineVersion() throws IOException, TimeoutExceptio * @return * @throws Exception */ - protected AsteriskVersion determineVersionByCoreSettings() throws Exception - { + protected AsteriskVersion determineVersionByCoreSettings() throws Exception { ManagerResponse response = sendAction(new CoreSettingsAction()); - if (!(response instanceof CoreSettingsResponse)) - { + if (!(response instanceof CoreSettingsResponse)) { // NOTE: you need system or reporting permissions logger.info("Could not get core settings, do we have the necessary permissions?"); return null; @@ -721,20 +615,17 @@ protected AsteriskVersion determineVersionByCoreSettings() throws Exception * @return * @throws Exception */ - protected AsteriskVersion determineVersionByCoreShowVersion() throws Exception - { + protected AsteriskVersion determineVersionByCoreShowVersion() throws Exception { final ManagerResponse coreShowVersionResponse = sendAction(new CommandAction(CMD_SHOW_VERSION)); - if (coreShowVersionResponse == null || !(coreShowVersionResponse instanceof CommandResponse)) - { + if (coreShowVersionResponse == null || !(coreShowVersionResponse instanceof CommandResponse)) { // this needs 'command' permissions logger.info("Could not get response for 'core show version'"); return null; } final List coreShowVersionResult = ((CommandResponse) coreShowVersionResponse).getResult(); - if (coreShowVersionResult == null || coreShowVersionResult.isEmpty()) - { + if (coreShowVersionResult == null || coreShowVersionResult.isEmpty()) { logger.warn("Got empty response for 'core show version'"); return null; } @@ -743,20 +634,16 @@ protected AsteriskVersion determineVersionByCoreShowVersion() throws Exception return AsteriskVersion.getDetermineVersionFromString(coreLine); } - protected void connect() throws IOException - { - try (LockCloser closer = this.withLock()) - { + protected void connect() throws IOException { + try (LockCloser closer = this.withLock()) { logger.info("Connecting to " + hostname + ":" + port); - if (reader == null) - { + if (reader == null) { logger.debug("Creating reader for " + hostname + ":" + port); reader = createReader(this, this); } - if (writer == null) - { + if (writer == null) { logger.debug("Creating writer"); writer = createWriter(); } @@ -767,8 +654,7 @@ protected void connect() throws IOException logger.debug("Passing socket to reader"); reader.setSocket(socket); - if (readerThread == null || !readerThread.isAlive() || reader.isDead()) - { + if (readerThread == null || !readerThread.isAlive() || reader.isDead()) { logger.debug("Creating and starting reader thread"); readerThread = new Thread(reader); readerThread.setName( @@ -782,31 +668,23 @@ protected void connect() throws IOException } } - protected SocketConnectionFacade createSocket() throws IOException - { + protected SocketConnectionFacade createSocket() throws IOException { return new SocketConnectionFacadeImpl(hostname, port, ssl, socketTimeout, socketReadTimeout, encoding); } - public void logoff() throws IllegalStateException - { - try (LockCloser closer = this.withLock()) - { - if (state != CONNECTED && state != RECONNECTING) - { + public void logoff() throws IllegalStateException { + try (LockCloser closer = this.withLock()) { + if (state != CONNECTED && state != RECONNECTING) { throw new IllegalStateException("Logoff may only be perfomed when in state " + "CONNECTED or RECONNECTING, but connection is in state " + state); } state = DISCONNECTING; - if (socket != null) - { - try - { + if (socket != null) { + try { sendAction(new LogoffAction()); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Unable to send LogOff action", e); } } @@ -818,19 +696,13 @@ public void logoff() throws IllegalStateException /** * Closes the socket connection. */ - protected void disconnect() - { - try (LockCloser closer = this.withLock()) - { - if (socket != null) - { + protected void disconnect() { + try (LockCloser closer = this.withLock()) { + if (socket != null) { logger.info("Closing socket."); - try - { + try { socket.close(); - } - catch (IOException ex) - { + } catch (IOException ex) { logger.warn("Unable to close socket: " + ex.getMessage()); } socket = null; @@ -840,8 +712,7 @@ protected void disconnect() } public ManagerResponse sendAction(ManagerAction action) - throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException - { + throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException { return sendAction(action, defaultResponseTimeout); } @@ -851,76 +722,61 @@ public ManagerResponse sendAction(ManagerAction action) * @param timeout - in milliseconds */ public ManagerResponse sendAction(ManagerAction action, long timeout) - throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException - { + throws IOException, TimeoutException, IllegalArgumentException, IllegalStateException { DefaultSendActionCallback callbackHandler = new DefaultSendActionCallback(); ManagerResponse response = null; - try - { + try { sendAction(action, callbackHandler); // definitely return null for the response of user events - if (action instanceof UserEventAction) - { + if (action instanceof UserEventAction) { return null; } - try - { + try { response = callbackHandler.waitForResponse(timeout); // no response? - if (response == null) - { + if (response == null) { throw new TimeoutException("Timeout waiting for response to " + action.getAction() + (action.getActionId() == null - ? "" - : " (actionId: " + action.getActionId() + "), Timeout=" + timeout + " Action=" - + action.getAction())); + ? "" + : " (actionId: " + action.getActionId() + "), Timeout=" + timeout + " Action=" + + action.getAction())); } - } - catch (InterruptedException ex) - { + } catch (InterruptedException ex) { logger.warn("Interrupted while waiting for result"); Thread.currentThread().interrupt(); } - } - finally - { + } finally { callbackHandler.dispose(); } return response; } public void sendAction(ManagerAction action, SendActionCallback callback) - throws IOException, IllegalArgumentException, IllegalStateException - { + throws IOException, IllegalArgumentException, IllegalStateException { final String internalActionId; - if (action == null) - { + if (action == null) { throw new IllegalArgumentException("Unable to send action: action is null."); } // In general sending actions is only allowed while connected, though // there are a few exceptions, these are handled here: if ((state == CONNECTING || state == RECONNECTING) && (action instanceof ChallengeAction - || action instanceof LoginAction || isShowVersionCommandAction(action))) - { + || action instanceof LoginAction || isShowVersionCommandAction(action))) { // when (re-)connecting challenge and login actions are ok. } // NOPMD - else if (state == DISCONNECTING && action instanceof LogoffAction) - { + else if (state == DISCONNECTING && action instanceof LogoffAction) { // when disconnecting logoff action is ok. } // NOPMD - else if (state != CONNECTED) - { + else if (state != CONNECTED) { throw new IllegalStateException( "Actions may only be sent when in state " + "CONNECTED, but connection is in state " + state); } - if (socket == null) - { + if (socket == null) { throw new IllegalStateException("Unable to send " + action.getAction() + " action: socket not connected."); } @@ -928,30 +784,25 @@ else if (state != CONNECTED) // if the callbackHandler is null the user is obviously not interested // in the response, thats fine. - if (callback != null) - { - try (LockCloser closer = this.responseListeners.withLock()) - { + if (callback != null) { + try (LockCloser closer = this.responseListeners.withLock()) { this.responseListeners.put(internalActionId, callback); } } - Class< ? extends ManagerResponse> responseClass = getExpectedResponseClass(action.getClass()); - if (responseClass != null) - { + Class responseClass = getExpectedResponseClass(action.getClass()); + if (responseClass != null) { reader.expectResponseClass(internalActionId, responseClass); } writer.sendAction(action, internalActionId); } - boolean isShowVersionCommandAction(ManagerAction action) - { + boolean isShowVersionCommandAction(ManagerAction action) { if (action instanceof CoreSettingsAction) return true; - if (action instanceof CommandAction) - { + if (action instanceof CommandAction) { String cmd = ((CommandAction) action).getCommand(); return CMD_SHOW_VERSION.equals(cmd); } @@ -959,11 +810,9 @@ boolean isShowVersionCommandAction(ManagerAction action) return false; } - private Class< ? extends ManagerResponse> getExpectedResponseClass(Class< ? extends ManagerAction> actionClass) - { + private Class getExpectedResponseClass(Class actionClass) { final ExpectedResponse annotation = actionClass.getAnnotation(ExpectedResponse.class); - if (annotation == null) - { + if (annotation == null) { return null; } @@ -971,8 +820,7 @@ boolean isShowVersionCommandAction(ManagerAction action) } public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) - throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException - { + throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException { return sendEventGeneratingAction(action, defaultEventTimeout); } @@ -980,30 +828,23 @@ public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) * Implements synchronous sending of event generating actions. */ public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long timeout) - throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException - { + throws IOException, EventTimeoutException, IllegalArgumentException, IllegalStateException { final ResponseEventsImpl responseEvents; final ResponseEventHandler responseEventHandler; final String internalActionId; - if (action == null) - { + if (action == null) { throw new IllegalArgumentException("Unable to send action: action is null."); - } - else if (action.getActionCompleteEventClass() == null) - { + } else if (action.getActionCompleteEventClass() == null) { throw new IllegalArgumentException( "Unable to send action: actionCompleteEventClass for " + action.getClass().getName() + " is null."); - } - else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClass())) - { + } else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClass())) { throw new IllegalArgumentException( "Unable to send action: actionCompleteEventClass (" + action.getActionCompleteEventClass().getName() + ") for " + action.getClass().getName() + " is not a ResponseEvent."); } - if (state != CONNECTED) - { + if (state != CONNECTED) { throw new IllegalStateException( "Actions may only be sent when in state " + "CONNECTED but connection is in state " + state); } @@ -1013,58 +854,46 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas internalActionId = createInternalActionId(); - try - { + try { // register response handler... - try (LockCloser closer = this.responseListeners.withLock()) - { + try (LockCloser closer = this.responseListeners.withLock()) { this.responseListeners.put(internalActionId, responseEventHandler); } // ...and event handler. - try (LockCloser closer = this.responseEventListeners.withLock()) - { + try (LockCloser closer = this.responseEventListeners.withLock()) { this.responseEventListeners.put(internalActionId, responseEventHandler); } writer.sendAction(action, internalActionId); // only wait if response has not yet arrived. - if (responseEvents.getResponse() == null || !responseEvents.isComplete()) - { - try - { + if (responseEvents.getResponse() == null || !responseEvents.isComplete()) { + try { responseEvents.await(timeout); - } - catch (InterruptedException e) - { + } catch (InterruptedException e) { logger.warn("Interrupted while waiting for response events."); Thread.currentThread().interrupt(); } } // still no response or not all events received and timed out? - if (responseEvents.getResponse() == null || !responseEvents.isComplete()) - { + if (responseEvents.getResponse() == null || !responseEvents.isComplete()) { throw new EventTimeoutException( "Timeout waiting for response or response events to " + action.getAction() + (action.getActionId() == null ? "" : " (actionId: " + action.getActionId() + ")"), responseEvents); } - } - finally - { + } finally { // remove the event handler - try (LockCloser closer = this.responseEventListeners.withLock()) - { + try (LockCloser closer = this.responseEventListeners.withLock()) { this.responseEventListeners.remove(internalActionId); } // Note: The response handler should have already been removed // when the response was received, however we remove it here // just in case it was never received. - try (LockCloser closer = this.responseListeners.withLock()) - { + try (LockCloser closer = this.responseListeners.withLock()) { this.responseListeners.remove(internalActionId); } @@ -1074,46 +903,36 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas } public void sendEventGeneratingAction(EventGeneratingAction action, SendEventGeneratingActionCallback callback) - throws IOException, IllegalArgumentException, IllegalStateException - { - if (action == null) - { + throws IOException, IllegalArgumentException, IllegalStateException { + if (action == null) { throw new IllegalArgumentException("Unable to send action: action is null."); - } - else if (action.getActionCompleteEventClass() == null) - { + } else if (action.getActionCompleteEventClass() == null) { throw new IllegalArgumentException( "Unable to send action: actionCompleteEventClass for " + action.getClass().getName() + " is null."); - } - else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClass())) - { + } else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClass())) { throw new IllegalArgumentException( "Unable to send action: actionCompleteEventClass (" + action.getActionCompleteEventClass().getName() + ") for " + action.getClass().getName() + " is not a ResponseEvent."); } - if (state != CONNECTED) - { + if (state != CONNECTED) { throw new IllegalStateException( "Actions may only be sent when in state " + "CONNECTED but connection is in state " + state); } final String internalActionId = createInternalActionId(); - if (callback != null) - { + if (callback != null) { AsyncEventGeneratingResponseHandler responseEventHandler = new AsyncEventGeneratingResponseHandler( action.getActionCompleteEventClass(), callback); // register response handler... - try (LockCloser closer = this.responseListeners.withLock()) - { + try (LockCloser closer = this.responseListeners.withLock()) { this.responseListeners.put(internalActionId, responseEventHandler); } // ...and event handler. - try (LockCloser closer = this.responseEventListeners.withLock()) - { + try (LockCloser closer = this.responseEventListeners.withLock()) { this.responseEventListeners.put(internalActionId, responseEventHandler); } } @@ -1126,12 +945,11 @@ else if (!ResponseEvent.class.isAssignableFrom(action.getActionCompleteEventClas * connection and a sequence. * * @return a new internal action id - * @see ManagerUtil#addInternalActionId(String,String) + * @see ManagerUtil#addInternalActionId(String, String) * @see ManagerUtil#getInternalActionId(String) * @see ManagerUtil#stripInternalActionId(String) */ - private String createInternalActionId() - { + private String createInternalActionId() { final StringBuilder sb; sb = new StringBuilder(); @@ -1142,36 +960,28 @@ private String createInternalActionId() return sb.toString(); } - public void addEventListener(final ManagerEventListener listener) - { - try (LockCloser closer = this.eventListeners.withLock()) - { + public void addEventListener(final ManagerEventListener listener) { + try (LockCloser closer = this.eventListeners.withLock()) { // only add it if its not already there - if (!this.eventListeners.contains(listener)) - { + if (!this.eventListeners.contains(listener)) { this.eventListeners.add(listener); } } } - public void removeEventListener(final ManagerEventListener listener) - { - try (LockCloser closer = this.eventListeners.withLock()) - { - if (this.eventListeners.contains(listener)) - { + public void removeEventListener(final ManagerEventListener listener) { + try (LockCloser closer = this.eventListeners.withLock()) { + if (this.eventListeners.contains(listener)) { this.eventListeners.remove(listener); } } } - public String getProtocolIdentifier() - { + public String getProtocolIdentifier() { return protocolIdentifier.getValue(); } - public ManagerConnectionState getState() - { + public ManagerConnectionState getState() { return state; } @@ -1185,15 +995,13 @@ public ManagerConnectionState getState() * @param response the response received by the reader * @see ManagerReader */ - public void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime) - { + public void dispatchResponse(ManagerResponse response, Integer requiredHandlingTime) { final String actionId; String internalActionId; SendActionCallback listener; // shouldn't happen - if (response == null) - { + if (response == null) { logger.error("Unable to dispatch null response. This should never happen. Please file a bug."); return; } @@ -1202,55 +1010,39 @@ public void dispatchResponse(ManagerResponse response, Integer requiredHandlingT internalActionId = null; listener = null; - if (actionId != null) - { + if (actionId != null) { internalActionId = ManagerUtil.getInternalActionId(actionId); response.setActionId(ManagerUtil.stripInternalActionId(actionId)); } - if (logger.isDebugEnabled()) - { + if (logger.isDebugEnabled()) { logger.debug("Dispatching response with internalActionId '" + internalActionId + "':\n" + response); } - if (internalActionId != null) - { - try (LockCloser closer = this.responseListeners.withLock()) - { + if (internalActionId != null) { + try (LockCloser closer = this.responseListeners.withLock()) { listener = responseListeners.get(internalActionId); - if (listener != null) - { + if (listener != null) { this.responseListeners.remove(internalActionId); - } - else - { + } else { // when using the async sendAction it's ok not to register a // callback so if we don't find a response handler thats ok logger.debug("No response listener registered for " + "internalActionId '" + internalActionId + "'"); } } - } - else - { + } else { logger.error( "Unable to retrieve internalActionId from response: " + "actionId '" + actionId + "':\n" + response); } - if (listener != null) - { + if (listener != null) { LogTime timer = new LogTime(); - try - { + try { listener.onResponse(response); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Unexpected exception in response listener " + listener.getClass().getName(), e); - } - finally - { - if (requiredHandlingTime != null && timer.timeTaken() > requiredHandlingTime) - { + } finally { + if (requiredHandlingTime != null && timer.timeTaken() > requiredHandlingTime) { logger.warn("Slow processing of event " + listener.getClass().getCanonicalName() + " " + timer.timeTaken() + "MS \n" + response); } @@ -1267,17 +1059,14 @@ public void dispatchResponse(ManagerResponse response, Integer requiredHandlingT * @see #removeEventListener(ManagerEventListener) * @see ManagerReader */ - public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) - { + public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) { // shouldn't happen - if (event == null) - { + if (event == null) { logger.error("Unable to dispatch null event. This should never happen. Please file a bug."); return; } dispatchLegacyEventIfNeeded(event, requiredHandlingTime); - if (logger.isDebugEnabled()) - { + if (logger.isDebugEnabled()) { logger.debug("Dispatching event:\n" + event.toString()); } @@ -1286,45 +1075,33 @@ public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) // These events are handled here at first: // Dispatch ResponseEvents to the appropriate responseEventListener - if (event instanceof ResponseEvent) - { + if (event instanceof ResponseEvent) { ResponseEvent responseEvent; String internalActionId; responseEvent = (ResponseEvent) event; internalActionId = responseEvent.getInternalActionId(); - if (internalActionId != null) - { - try (LockCloser closer = responseEventListeners.withLock()) - { + if (internalActionId != null) { + try (LockCloser closer = responseEventListeners.withLock()) { ManagerEventListener listener; listener = responseEventListeners.get(internalActionId); - if (listener != null) - { + if (listener != null) { LogTime timer = new LogTime(); - try - { + try { listener.onManagerEvent(event); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn("Unexpected exception in response event listener " + listener.getClass().getName(), e); - } - finally - { - if (requiredHandlingTime != null && timer.timeTaken() > requiredHandlingTime) - { + } finally { + if (requiredHandlingTime != null && timer.timeTaken() > requiredHandlingTime) { logger.warn("Slow processing of event " + listener.getClass().getCanonicalName() + " " + timer.timeTaken() + "MS \n" + event); } } } } - } - else - { + } else { // ResponseEvent without internalActionId: // this happens if the same event class is used as response // event @@ -1334,26 +1111,21 @@ public void dispatchEvent(ManagerEvent event, Integer requiredHandlingTime) // + "internalActionId:\n" + responseEvent); } // NOPMD } - if (event instanceof DisconnectEvent) - { + if (event instanceof DisconnectEvent) { cleanupActionListeners((DisconnectEvent) event); // When we receive get disconnected while we are connected start // a new reconnect thread and set the state to RECONNECTING. - try (LockCloser closer = this.withLock()) - { - if (state == CONNECTED) - { + try (LockCloser closer = this.withLock()) { + if (state == CONNECTED) { state = RECONNECTING; // close socket if still open and remove reference to // readerThread // After sending the DisconnectThread that thread will die // anyway. cleanup(); - Thread reconnectThread = new Thread(new Runnable() - { + Thread reconnectThread = new Thread(new Runnable() { - public void run() - { + public void run() { reconnect(); } }); @@ -1366,17 +1138,14 @@ public void run() // (clients) and after that the ManagerReaderThread is gone. // So effectively we replaced the reader thread by a // ReconnectThread. - } - else - { + } else { // when we receive a DisconnectEvent while not connected we // ignore it and do not send it to clients return; } } } - if (event instanceof ProtocolIdentifierReceivedEvent) - { + if (event instanceof ProtocolIdentifierReceivedEvent) { ProtocolIdentifierReceivedEvent protocolIdentifierReceivedEvent; String protocolIdentifier; @@ -1394,10 +1163,8 @@ public void run() * Enro 2015-03 Workaround to continue having Legacy Events from Asterisk * 13. */ - private void dispatchLegacyEventIfNeeded(ManagerEvent event, Integer requiredHandlingTime) - { - if (event instanceof DialBeginEvent) - { + private void dispatchLegacyEventIfNeeded(ManagerEvent event, Integer requiredHandlingTime) { + if (event instanceof DialBeginEvent) { DialEvent legacyEvent = new DialEvent((DialBeginEvent) event); dispatchEvent(legacyEvent, requiredHandlingTime); } @@ -1408,25 +1175,16 @@ private void dispatchLegacyEventIfNeeded(ManagerEvent event, Integer requiredHan * * @param event the event to propagate */ - private void fireEvent(ManagerEvent event, Integer requiredHandlingTime) - { - try (LockCloser closer = eventListeners.withLock()) - { - for (ManagerEventListener listener : eventListeners) - { + private void fireEvent(ManagerEvent event, Integer requiredHandlingTime) { + try (LockCloser closer = eventListeners.withLock()) { + for (ManagerEventListener listener : eventListeners) { LogTime timer = new LogTime(); - try - { + try { listener.onManagerEvent(event); - } - catch (RuntimeException e) - { + } catch (RuntimeException e) { logger.warn("Unexpected exception in eventHandler " + listener.getClass().getName(), e); - } - finally - { - if (requiredHandlingTime != null && timer.timeTaken() > requiredHandlingTime) - { + } finally { + if (requiredHandlingTime != null && timer.timeTaken() > requiredHandlingTime) { logger.warn("Slow processing of event " + listener.getClass().getCanonicalName() + " " + timer.timeTaken() + "MS \n" + event); } @@ -1435,15 +1193,12 @@ private void fireEvent(ManagerEvent event, Integer requiredHandlingTime) } } - private boolean isSupportedProtocolIdentifier(final String identifier) - { + private boolean isSupportedProtocolIdentifier(final String identifier) { // Normal version checks - for (String supportedVersion : SUPPORTED_AMI_VERSIONS) - { + for (String supportedVersion : SUPPORTED_AMI_VERSIONS) { String prefix = "Asterisk Call Manager/" + supportedVersion + "."; - if (identifier.startsWith(prefix)) - { + if (identifier.startsWith(prefix)) { return true; } } @@ -1466,12 +1221,10 @@ private boolean isSupportedProtocolIdentifier(final String identifier) * * @param identifier the protocol version used by the Asterisk server. */ - private void setProtocolIdentifier(final String identifier) - { + private void setProtocolIdentifier(final String identifier) { logger.info("Connected via " + identifier); - if (identifier == null || !isSupportedProtocolIdentifier(identifier)) - { + if (identifier == null || !isSupportedProtocolIdentifier(identifier)) { logger.warn("Unsupported protocol version '" + identifier + "'. Use at your own risk."); } protocolIdentifier.setValue(identifier); @@ -1488,46 +1241,34 @@ private void setProtocolIdentifier(final String identifier) * This method is called when a {@link DisconnectEvent} is received from the * reader. */ - private void reconnect() - { + private void reconnect() { int numTries; // try to reconnect numTries = 0; - while (true) - { - try - { - if (numTries < 10) - { + while (true) { + try { + if (numTries < 10) { // try to reconnect quite fast for the firt 10 times // this succeeds if the server has just been restarted Thread.sleep(RECONNECTION_INTERVAL_1); - } - else - { + } else { // slow down after 10 unsuccessful attempts asuming a // shutdown of the server Thread.sleep(RECONNECTION_INTERVAL_2); } - } - catch (InterruptedException e) - { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } - try - { - try (LockCloser closer = this.withLock()) - { - if (state != RECONNECTING) - { + try { + try (LockCloser closer = this.withLock()) { + if (state != RECONNECTING) { break; } connect(); - try - { + try { doLogin(defaultResponseTimeout, eventMask); logger.info("Successfully reconnected."); // everything is ok again, so we leave @@ -1535,46 +1276,33 @@ private void reconnect() // no // need to adjust it break; - } - catch (AuthenticationFailedException e1) - { - if (keepAliveAfterAuthenticationFailure) - { + } catch (AuthenticationFailedException e1) { + if (keepAliveAfterAuthenticationFailure) { logger.error("Unable to log in after reconnect: " + e1.getMessage()); - } - else - { + } else { logger.error("Unable to log in after reconnect: " + e1.getMessage() + ". Giving up."); state = DISCONNECTED; } - } - catch (TimeoutException e1) - { + } catch (TimeoutException e1) { // shouldn't happen - but happens! logger.error("TimeoutException while trying to log in " + "after reconnect."); } } - } - catch (IOException e) - { + } catch (IOException e) { // server seems to be still down, just continue to attempt // reconnection String message = e.getClass().getSimpleName(); - if (e.getMessage() != null) - { + if (e.getMessage() != null) { message = e.getMessage(); } logger.warn("Exception while trying to reconnect: " + message); - try - { + try { // Where multiple connections are present, spread out // their reconnect attempts and prevent hard loop. long randomSleep = (long) (Math.random() * 100); TimeUnit.MILLISECONDS.sleep(50 + randomSleep); - } - catch (InterruptedException e1) - { + } catch (InterruptedException e1) { logger.error(e1); } } @@ -1589,12 +1317,10 @@ private void reconnect() * * @param event */ - private void cleanupActionListeners(DisconnectEvent event) - { + private void cleanupActionListeners(DisconnectEvent event) { HashMap oldResponseListeners = null; - try (LockCloser closer = responseListeners.withLock()) - { + try (LockCloser closer = responseListeners.withLock()) { // Store remaining response listeners to be notified outside of // synchronized oldResponseListeners = new HashMap(responseListeners); @@ -1602,22 +1328,17 @@ private void cleanupActionListeners(DisconnectEvent event) } // Clear pending responseListeners that will not receive their responses - for (SendActionCallback responseListener : oldResponseListeners.values()) - { + for (SendActionCallback responseListener : oldResponseListeners.values()) { // Allows to unblock waiting sendAction() calls - try - { + try { responseListener.onResponse(null); - } - catch (Exception ex) - { + } catch (Exception ex) { logger.warn("Exception notifying responseListener.onResponse(null)", ex); } } HashMap oldResponseEventListeners = null; - try (LockCloser closer = responseEventListeners.withLock()) - { + try (LockCloser closer = responseEventListeners.withLock()) { // Store remaining responseEventListeners to be notified outside of // synchronized oldResponseEventListeners = new HashMap(responseEventListeners); @@ -1626,37 +1347,30 @@ private void cleanupActionListeners(DisconnectEvent event) // Remove those already cleaned up via oldResponseListeners // TODO or should all be notified? - for (String discardedInternalActionId : oldResponseListeners.keySet()) - { + for (String discardedInternalActionId : oldResponseListeners.keySet()) { oldResponseEventListeners.remove(discardedInternalActionId); } // Notify remaining responseEventListeners. // These could be EventGeneratingAction handlers that have received a // response but have not yet received the end event. - for (ManagerEventListener responseEventListener : oldResponseEventListeners.values()) - { - try - { + for (ManagerEventListener responseEventListener : oldResponseEventListeners.values()) { + try { // Allows to unblock waiting sendAction() calls responseEventListener.onManagerEvent(event); - } - catch (Exception ex) - { + } catch (Exception ex) { logger.warn("Exception notifying responseListener.onManagerEvent(DisconnectEvent)", ex); } } } - private void cleanup() - { + private void cleanup() { disconnect(); this.readerThread = null; } @Override - public String toString() - { + public String toString() { StringBuilder sb; sb = new StringBuilder("ManagerConnection["); @@ -1673,26 +1387,22 @@ public String toString() /** * A simple data object to store a ManagerResult. */ - private static class DefaultSendActionCallback implements SendActionCallback, Serializable - { + private static class DefaultSendActionCallback implements SendActionCallback, Serializable { private static final long serialVersionUID = 7831097958568769220L; private ManagerResponse response; private final CountDownLatch latch = new CountDownLatch(1); private volatile boolean disposed = false; private LogTime timer = new LogTime(); - private ManagerResponse waitForResponse(long timeout) throws InterruptedException - { + private ManagerResponse waitForResponse(long timeout) throws InterruptedException { latch.await(timeout, TimeUnit.MILLISECONDS); return this.response; } @Override - public void onResponse(ManagerResponse response) - { + public void onResponse(ManagerResponse response) { this.response = response; - if (disposed) - { + if (disposed) { logger.error("Response arrived after Disposal and assumably Timeout " + response + " elapsed: " + timer.timeTaken() + "(MS)"); logger.error("" + response.getDateReceived()); @@ -1700,8 +1410,7 @@ public void onResponse(ManagerResponse response) latch.countDown(); } - private void dispose() - { + private void dispose() { disposed = true; } @@ -1711,28 +1420,24 @@ private void dispose() * A combinded event and response handler that adds received events and the * response to a ResponseEvents object. */ - private static class ResponseEventHandler implements ManagerEventListener, SendActionCallback - { + private static class ResponseEventHandler implements ManagerEventListener, SendActionCallback { private final ResponseEventsImpl events; - private final Class< ? > actionCompleteEventClass; + private final Class actionCompleteEventClass; /** * Creates a new instance. * - * @param events the ResponseEventsImpl to store the events in + * @param events the ResponseEventsImpl to store the events in * @param actionCompleteEventClass the type of event that indicates that - * all events have been received + * all events have been received */ - public ResponseEventHandler(ResponseEventsImpl events, Class< ? > actionCompleteEventClass) - { + public ResponseEventHandler(ResponseEventsImpl events, Class actionCompleteEventClass) { this.events = events; this.actionCompleteEventClass = actionCompleteEventClass; } - public void onManagerEvent(ManagerEvent event) - { - if (event instanceof DisconnectEvent) - { + public void onManagerEvent(ManagerEvent event) { + if (event instanceof DisconnectEvent) { // Set flag that must not wait for the response events.setComplete(true); // unblock potentially waiting synchronous call to @@ -1743,8 +1448,7 @@ public void onManagerEvent(ManagerEvent event) } // should always be a ResponseEvent, anyway... - if (event instanceof ResponseEvent) - { + if (event instanceof ResponseEvent) { ResponseEvent responseEvent; responseEvent = (ResponseEvent) event; @@ -1752,23 +1456,19 @@ public void onManagerEvent(ManagerEvent event) } // finished? - if (actionCompleteEventClass.isAssignableFrom(event.getClass())) - { + if (actionCompleteEventClass.isAssignableFrom(event.getClass())) { events.setComplete(true); // notify if action complete event and response have been // received - if (events.getResponse() != null) - { + if (events.getResponse() != null) { events.countDown(); } } } - public void onResponse(ManagerResponse response) - { + public void onResponse(ManagerResponse response) { // If disconnected - if (response == null) - { + if (response == null) { // Set flag that must not wait for the response events.setComplete(true); // unblock potentially waiting synchronous call to @@ -1779,31 +1479,27 @@ public void onResponse(ManagerResponse response) } events.setRepsonse(response); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { events.setComplete(true); } // finished? // notify if action complete event and response have been // received - if (events.isComplete()) - { + if (events.isComplete()) { events.countDown(); } } } - private class AsyncEventGeneratingResponseHandler implements SendActionCallback, ManagerEventListener - { - private final Class< ? extends ResponseEvent> actionCompleteEventClass; + private class AsyncEventGeneratingResponseHandler implements SendActionCallback, ManagerEventListener { + private final Class actionCompleteEventClass; private final SendEventGeneratingActionCallback callback; private final ResponseEventsImpl events; - public AsyncEventGeneratingResponseHandler(Class< ? extends ResponseEvent> actionCompleteEventClass, - SendEventGeneratingActionCallback callback) - { + public AsyncEventGeneratingResponseHandler(Class actionCompleteEventClass, + SendEventGeneratingActionCallback callback) { this.actionCompleteEventClass = actionCompleteEventClass; this.callback = callback; @@ -1811,29 +1507,24 @@ public AsyncEventGeneratingResponseHandler(Class< ? extends ResponseEvent> actio } @Override - public void onManagerEvent(ManagerEvent event) - { - if (event instanceof DisconnectEvent) - { + public void onManagerEvent(ManagerEvent event) { + if (event instanceof DisconnectEvent) { callback.onResponse(events); return; } // should always be a ResponseEvent, anyway... - if (false == (event instanceof ResponseEvent)) - { + if (false == (event instanceof ResponseEvent)) { return; } ResponseEvent responseEvent = (ResponseEvent) event; events.addEvent(responseEvent); - if (actionCompleteEventClass.isAssignableFrom(event.getClass())) - { + if (actionCompleteEventClass.isAssignableFrom(event.getClass())) { events.setComplete(true); String internalActionId = responseEvent.getInternalActionId(); - try (LockCloser closer = responseEventListeners.withLock()) - { + try (LockCloser closer = responseEventListeners.withLock()) { responseEventListeners.remove(internalActionId); } callback.onResponse(events); @@ -1841,24 +1532,20 @@ public void onManagerEvent(ManagerEvent event) } @Override - public void onResponse(ManagerResponse response) - { + public void onResponse(ManagerResponse response) { // If disconnected - if (response == null) - { + if (response == null) { callback.onResponse(events); return; } events.setRepsonse(response); - if (response instanceof ManagerError) - { + if (response instanceof ManagerError) { events.setComplete(true); } // finished? - if (events.isComplete()) - { + if (events.isComplete()) { // invoke callback callback.onResponse(events); } @@ -1866,10 +1553,8 @@ public void onResponse(ManagerResponse response) } @Override - public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) - { - if (reader == null) - { + public void deregisterEventClass(Class eventClass) { + if (reader == null) { reader = createReader(this, this); } @@ -1878,8 +1563,7 @@ public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) } @Override - public void stop() - { + public void stop() { // NO_OP } } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java index 4fe566ccd..2b3e46c19 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReader.java @@ -16,12 +16,12 @@ */ package org.asteriskjava.manager.internal; -import java.io.IOException; - import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.SocketConnectionFacade; +import java.io.IOException; + /** * The ManagerReader reads events and responses from the asterisk server, parses * them using EventBuilderImpl and ResponseBuilder and dispatches them to the @@ -36,8 +36,7 @@ * @see org.asteriskjava.manager.internal.ResponseBuilder * @see org.asteriskjava.manager.DefaultManagerConnection */ -public interface ManagerReader extends Runnable -{ +public interface ManagerReader extends Runnable { String COMMAND_RESULT_RESPONSE_KEY = "__result__"; /** @@ -56,9 +55,9 @@ public interface ManagerReader extends Runnable * @see EventBuilder * @see ManagerEvent */ - void registerEventClass(Class< ? extends ManagerEvent> event); + void registerEventClass(Class event); - void expectResponseClass(String internalActionId, Class< ? extends ManagerResponse> responseClass); + void expectResponseClass(String internalActionId, Class responseClass); /** * Terminates this reader. @@ -69,7 +68,7 @@ public interface ManagerReader extends Runnable * Checks whether this reader is terminating or terminated. * * @return true if this reader is terminating or terminated, - * false otherwise. + * false otherwise. */ boolean isDead(); @@ -77,9 +76,9 @@ public interface ManagerReader extends Runnable * Returns the Exception that caused this reader to terminate if any. * * @return the Exception that caused this reader to terminate if any or - * null if not. + * null if not. */ IOException getTerminationException(); - void deregisterEventClass(Class< ? extends ManagerEvent> eventClass); + void deregisterEventClass(Class eventClass); } diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java index 2a707db39..efbc00535 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java @@ -16,14 +16,7 @@ */ package org.asteriskjava.manager.internal; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - +import com.google.common.util.concurrent.RateLimiter; import org.asteriskjava.manager.event.DisconnectEvent; import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.event.ProtocolIdentifierReceivedEvent; @@ -35,7 +28,9 @@ import org.asteriskjava.util.LogFactory; import org.asteriskjava.util.SocketConnectionFacade; -import com.google.common.util.concurrent.RateLimiter; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * Default implementation of the ManagerReader interface. @@ -43,8 +38,7 @@ * @author srt * @version $Id$ */ -public class ManagerReaderImpl implements ManagerReader -{ +public class ManagerReaderImpl implements ManagerReader { /** * Instance logger. */ @@ -62,7 +56,7 @@ public class ManagerReaderImpl implements ManagerReader */ private final ResponseBuilder responseBuilder; - private final Map> expectedResponseClasses; + private final Map> expectedResponseClasses; /** * The source to use when creating {@link ManagerEvent}s. @@ -101,11 +95,10 @@ public class ManagerReaderImpl implements ManagerReader * Creates a new ManagerReaderImpl. * * @param dispatcher the dispatcher to use for dispatching events and - * responses. - * @param source the source to use when creating {@link ManagerEvent}s + * responses. + * @param source the source to use when creating {@link ManagerEvent}s */ - public ManagerReaderImpl(final Dispatcher dispatcher, Object source) - { + public ManagerReaderImpl(final Dispatcher dispatcher, Object source) { this.rawDispatcher = dispatcher; this.source = source; @@ -119,18 +112,15 @@ public ManagerReaderImpl(final Dispatcher dispatcher, Object source) * * @param socket the socket to use for reading from the asterisk server. */ - public void setSocket(final SocketConnectionFacade socket) - { + public void setSocket(final SocketConnectionFacade socket) { this.socket = socket; } - public void registerEventClass(Class< ? extends ManagerEvent> eventClass) - { + public void registerEventClass(Class eventClass) { eventBuilder.registerEventClass(eventClass); } - public void expectResponseClass(String internalActionId, Class< ? extends ManagerResponse> responseClass) - { + public void expectResponseClass(String internalActionId, Class responseClass) { expectedResponseClasses.put(internalActionId, responseClass); } @@ -144,15 +134,13 @@ public void expectResponseClass(String internalActionId, Class< ? extends Manage * @see org.asteriskjava.manager.internal.Dispatcher#dispatchEvent(ManagerEvent) * @see org.asteriskjava.manager.internal.Dispatcher#dispatchResponse(ManagerResponse) */ - public void run() - { + public void run() { long timeOfLastEvent = 0; long reserve = 0; final Map buffer = new HashMap<>(); String line; - if (socket == null) - { + if (socket == null) { throw new IllegalStateException("Unable to run: socket is null."); } @@ -162,18 +150,15 @@ public void run() AsyncEventPump dispatcher = new AsyncEventPump(this, rawDispatcher, Thread.currentThread().getName()); long slowEventThresholdMs = 10; RateLimiter slowEventLogLimiter = RateLimiter.create(4); - try - { + try { // main loop - while (!this.die && (line = socket.readLine()) != null) - { + while (!this.die && (line = socket.readLine()) != null) { // maybe we will find a better way to identify the protocol // identifier but for now // this works quite well. if (line.startsWith("Asterisk Call Manager/") || line.startsWith("Asterisk Call Manager Proxy/") || line.startsWith("Asterisk Manager Proxy/") || line.startsWith("OpenPBX Call Manager/") - || line.startsWith("CallWeaver Call Manager/")) - { + || line.startsWith("CallWeaver Call Manager/")) { ProtocolIdentifierReceivedEvent protocolIdentifierReceivedEvent; protocolIdentifierReceivedEvent = new ProtocolIdentifierReceivedEvent(source); protocolIdentifierReceivedEvent.setProtocolIdentifier(line); @@ -187,14 +172,12 @@ public void run() * we are using "\r\n" as the delimiter for line this also * handles multiline results as long as they only contain "\n". */ - if ("Follows".equals(buffer.get("response")) && line.endsWith("--END COMMAND--")) - { + if ("Follows".equals(buffer.get("response")) && line.endsWith("--END COMMAND--")) { buffer.put(COMMAND_RESULT_RESPONSE_KEY, line); continue; } - if (line.length() > 0) - { + if (line.length() > 0) { // begin of workaround for Astersik bug 13319 // see AJ-77 // Use this workaround only when line starts from "From " @@ -207,8 +190,7 @@ public void run() int delimiterLength = 1; - if (delimiterIndex > 0 && line.length() > delimiterIndex + delimiterLength) - { + if (delimiterIndex > 0 && line.length() > delimiterIndex + delimiterLength) { String name = line.substring(0, delimiterIndex).toLowerCase(Locale.ENGLISH).trim(); String value = line.substring(delimiterIndex + delimiterLength).trim(); @@ -223,18 +205,15 @@ public void run() // we build // the corresponding value object and dispatch it through the // ManagerConnection. - if (line.length() == 0) - { + if (line.length() == 0) { Object cause = null; LogTime timer = new LogTime(); - if (buffer.containsKey("event")) - { + if (buffer.containsKey("event")) { // TODO tracing // logger.debug("attempting to build event: " + // buffer.get("event")); ManagerEvent event = buildEvent(source, buffer); - if (event != null) - { + if (event != null) { cause = event; dispatcher.dispatchEvent(event, null); @@ -246,31 +225,22 @@ public void run() // BridgeEvent's for them allowing legacy code to // still work with BridgeEvent's ManagerEvent secondaryEvent = compatibility.handleEvent(event); - if (secondaryEvent != null) - { + if (secondaryEvent != null) { dispatcher.dispatchEvent(secondaryEvent, null); } - } - else - { + } else { logger.debug("buildEvent returned null"); } - } - else if (buffer.containsKey("response")) - { + } else if (buffer.containsKey("response")) { ManagerResponse response = buildResponse(buffer); // TODO tracing // logger.debug("attempting to build response"); - if (response != null) - { + if (response != null) { cause = response; dispatcher.dispatchResponse(response, null); } - } - else - { - if (!buffer.isEmpty()) - { + } else { + if (!buffer.isEmpty()) { logger.debug("Buffer contains neither response nor event"); } } @@ -299,14 +269,11 @@ else if (buffer.containsKey("response")) timeOfLastEvent = now; // check if the event was slow to build and dispatch - if (elapsed > slowEventThresholdMs) - { + if (elapsed > slowEventThresholdMs) { // check for to many slow events this second. - if (reserve <= 0) - { + if (reserve <= 0) { // check we haven't already logged this to often - if (slowEventLogLimiter.tryAcquire()) - { + if (slowEventLogLimiter.tryAcquire()) { logger.warn("(This is normal during JVM warmup) Slow processing of event " + elapsed + "\n" + cause); } @@ -316,26 +283,19 @@ else if (buffer.containsKey("response")) } this.dead = true; logger.debug("Reached end of stream, terminating reader."); - } - catch (IOException e) - { + } catch (IOException e) { this.terminationException = e; this.dead = true; logger.info("Terminating reader thread: " + e.getMessage()); - } - catch (Exception e) - { - if (this.terminationException == null) - { + } catch (Exception e) { + if (this.terminationException == null) { // wrap in IOException to avoid changing the external API of // asteriskjava this.terminationException = new IOException(e); } logger.error("Manager reader exiting due to unexpected Exception..."); logger.error(e, e); - } - finally - { + } finally { this.dead = true; // cleans resources and reconnects if needed DisconnectEvent disconnectEvent = new DisconnectEvent(source); @@ -346,80 +306,64 @@ else if (buffer.containsKey("response")) } @SuppressWarnings("unchecked") - private void addToBuffer(Map buffer, String name, String value) - { + private void addToBuffer(Map buffer, String name, String value) { // if we already have a value for that key, convert the value to a list // and add // the new value to that list. - if (buffer.containsKey(name)) - { + if (buffer.containsKey(name)) { Object currentValue = buffer.get(name); - if (currentValue instanceof List) - { + if (currentValue instanceof List) { ((List) currentValue).add(value); return; } List list = new ArrayList<>(); - if (currentValue instanceof String) - { + if (currentValue instanceof String) { list.add((String) currentValue); - } - else - { + } else { list.add(currentValue.toString()); } list.add(value); buffer.put(name, list); - } - else - { + } else { buffer.put(name, value); } } - public void die() - { + public void die() { this.die = true; } - public boolean isDead() - { + public boolean isDead() { return dead; } - public IOException getTerminationException() - { + public IOException getTerminationException() { return terminationException; } - private ManagerResponse buildResponse(Map buffer) - { - Class< ? extends ManagerResponse> responseClass = null; + private ManagerResponse buildResponse(Map buffer) { + Class responseClass = null; final String actionId = (String) buffer.get("actionid"); final String internalActionId = ManagerUtil.getInternalActionId(actionId); - if (internalActionId != null) - { + if (internalActionId != null) { responseClass = expectedResponseClasses.remove(internalActionId); } final ManagerResponse response = responseBuilder.buildResponse(responseClass, buffer); - if (response != null) - { + if (response != null) { response.setDateReceived(DateUtil.getDate()); } return response; } - private ManagerEvent buildEvent(Object source, Map buffer) - { + private ManagerEvent buildEvent(Object source, Map buffer) { ManagerEvent event; event = eventBuilder.buildEvent(source, buffer); - if (event != null) - { + if (event != null) { event.setDateReceived(DateUtil.getDate()); } @@ -427,8 +371,7 @@ private ManagerEvent buildEvent(Object source, Map buffer) } @Override - public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) - { + public void deregisterEventClass(Class eventClass) { eventBuilder.deregisterEventClass(eventClass); diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerUtil.java b/src/main/java/org/asteriskjava/manager/internal/ManagerUtil.java index 2ddf18d9f..545b9f18a 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerUtil.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerUtil.java @@ -25,37 +25,34 @@ * unique action id or no action id at all. *

    * All the methods contained in this class are supposed to be internally only. - * + * * @author srt * @version $Id$ */ -public class ManagerUtil -{ +public class ManagerUtil { public static final char INTERNAL_ACTION_ID_DELIMITER = '#'; /** * The hex digits used to build a hex string representation of a byte array. */ private static final char[] hexChar = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - + private ManagerUtil() { - + } /** * Converts a byte array to a hex string representing it. The hex digits are * lower case. - * + * * @param b the byte array to convert * @return the hex representation of b */ - public static String toHexString(byte[] b) - { + public static String toHexString(byte[] b) { final StringBuilder sb; sb = new StringBuilder(b.length * 2); - for (byte aB : b) - { + for (byte aB : b) { sb.append(hexChar[(aB & 0xf0) >>> 4]); sb.append(hexChar[aB & 0x0f]); } @@ -64,24 +61,21 @@ public static String toHexString(byte[] b) /** * Returns the internal action id contained in the given action id. - * + * * @param actionId the action id prefixed by the internal action id as - * received from Asterisk. + * received from Asterisk. * @return the internal action id that has been added before. * @see #addInternalActionId(String, String) */ - public static String getInternalActionId(String actionId) - { + public static String getInternalActionId(String actionId) { final int delimiterIndex; - if (actionId == null) - { + if (actionId == null) { return null; } delimiterIndex = actionId.indexOf(INTERNAL_ACTION_ID_DELIMITER); - if (delimiterIndex > 0) - { + if (delimiterIndex > 0) { return actionId.substring(0, delimiterIndex); } return null; @@ -89,22 +83,19 @@ public static String getInternalActionId(String actionId) /** * Strips the internal action id from the given action id. - * + * * @param actionId the action id prefixed by the internal action id as - * received from Asterisk. + * received from Asterisk. * @return the original action id, that is the action id as it was before - * the internal action id was added. + * the internal action id was added. * @see #addInternalActionId(String, String) */ - public static String stripInternalActionId(String actionId) - { + public static String stripInternalActionId(String actionId) { int delimiterIndex; delimiterIndex = actionId.indexOf(INTERNAL_ACTION_ID_DELIMITER); - if (delimiterIndex > 0) - { - if (actionId.length() > delimiterIndex + 1) - { + if (delimiterIndex > 0) { + if (actionId.length() > delimiterIndex + 1) { return actionId.substring(delimiterIndex + 1); } return null; @@ -114,16 +105,14 @@ public static String stripInternalActionId(String actionId) /** * Adds the internal action id to the given action id. - * - * @param actionId the action id as set by the user. + * + * @param actionId the action id as set by the user. * @param internalActionId the internal action id to add. * @return the action id prefixed by the internal action id suitable to be - * sent to Asterisk. + * sent to Asterisk. */ - public static String addInternalActionId(String actionId, String internalActionId) - { - if (actionId == null) - { + public static String addInternalActionId(String actionId, String internalActionId) { + if (actionId == null) { return internalActionId + INTERNAL_ACTION_ID_DELIMITER; } return internalActionId + INTERNAL_ACTION_ID_DELIMITER + actionId; diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerWriter.java b/src/main/java/org/asteriskjava/manager/internal/ManagerWriter.java index 8e0a0bc28..94d844870 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerWriter.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerWriter.java @@ -16,28 +16,27 @@ */ package org.asteriskjava.manager.internal; -import java.io.IOException; - import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.action.ManagerAction; import org.asteriskjava.util.SocketConnectionFacade; +import java.io.IOException; + /** * The ManagerWriter transforms actions using an ActionBuilder and sends them to * the asterisk server.

    * This class is intended to be used only by the DefaultManagerConnection. - * - * @see org.asteriskjava.manager.internal.ActionBuilder - * @see org.asteriskjava.manager.DefaultManagerConnection + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.internal.ActionBuilder + * @see org.asteriskjava.manager.DefaultManagerConnection */ -public interface ManagerWriter -{ +public interface ManagerWriter { /** * Sets the version of the target Asterisk server. - * + * * @param targetVersion the version of the target Asterisk server. * @since 0.2 */ @@ -45,15 +44,15 @@ public interface ManagerWriter /** * Sets the socket to use for writing to Asterisk. - * + * * @param socket the socket to use for writing to Asterisk. */ void setSocket(final SocketConnectionFacade socket); /** * Sends the given action to the asterisk server. - * - * @param action the action to send to the asterisk server. + * + * @param action the action to send to the asterisk server. * @param internalActionId the internal action id to add. * @throws IOException if there is a problem sending the action. */ diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java index 6ee8220ff..d1d8f01e1 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerWriterImpl.java @@ -16,22 +16,21 @@ */ package org.asteriskjava.manager.internal; -import java.io.IOException; - import org.asteriskjava.AsteriskVersion; import org.asteriskjava.lock.Lockable; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.action.ManagerAction; import org.asteriskjava.util.SocketConnectionFacade; +import java.io.IOException; + /** * Default implementation of ManagerWriter interface. - * + * * @author srt * @version $Id$ */ -public class ManagerWriterImpl extends Lockable implements ManagerWriter -{ +public class ManagerWriterImpl extends Lockable implements ManagerWriter { /** * Instance logger. */ @@ -48,32 +47,25 @@ public class ManagerWriterImpl extends Lockable implements ManagerWriter /** * Creates a new ManagerWriter. */ - public ManagerWriterImpl() - { + public ManagerWriterImpl() { this.actionBuilder = new ActionBuilderImpl(); } - public void setTargetVersion(AsteriskVersion version) - { + public void setTargetVersion(AsteriskVersion version) { actionBuilder.setTargetVersion(version); } - public void setSocket(final SocketConnectionFacade socket) - { - try (LockCloser closer = this.withLock()) - { + public void setSocket(final SocketConnectionFacade socket) { + try (LockCloser closer = this.withLock()) { this.socket = socket; } } - public void sendAction(final ManagerAction action, final String internalActionId) throws IOException - { - try (LockCloser closer = this.withLock()) - { + public void sendAction(final ManagerAction action, final String internalActionId) throws IOException { + try (LockCloser closer = this.withLock()) { final String actionString; - if (socket == null) - { + if (socket == null) { throw new IllegalStateException("Unable to send action: socket is null"); } diff --git a/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java b/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java index 21fea6fd4..4f9f5b09a 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java +++ b/src/main/java/org/asteriskjava/manager/internal/ProtocolIdentifierWrapper.java @@ -3,29 +3,24 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -class ProtocolIdentifierWrapper -{ +class ProtocolIdentifierWrapper { private volatile CountDownLatch latch = new CountDownLatch(1); private String value; - void reset() - { + void reset() { value = null; latch = new CountDownLatch(1); } - boolean await(long timeout) throws InterruptedException - { + boolean await(long timeout) throws InterruptedException { return latch.await(timeout, TimeUnit.MILLISECONDS); } - String getValue() - { + String getValue() { return value; } - public void setValue(String identifier) - { + public void setValue(String identifier) { value = identifier; latch.countDown(); diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilder.java b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilder.java index 8ede4237c..b3c940409 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilder.java @@ -16,10 +16,10 @@ */ package org.asteriskjava.manager.internal; -import java.util.Map; - import org.asteriskjava.manager.response.ManagerResponse; +import java.util.Map; + /** * Transforms maps of attributes to instances of ManagerResponse. @@ -28,8 +28,7 @@ * @version $Id$ * @see org.asteriskjava.manager.response.ManagerResponse */ -interface ResponseBuilder -{ +interface ResponseBuilder { /** * Constructs an instance of ManagerResponse based on a map of attributes. * diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java index 223210165..8d4f5bccd 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java @@ -16,28 +16,21 @@ */ package org.asteriskjava.manager.internal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.asteriskjava.manager.response.CommandResponse; import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; +import java.util.*; + /** * Default implementation of the ResponseBuilder interface. - * - * @see org.asteriskjava.manager.response.ManagerResponse + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.response.ManagerResponse */ -class ResponseBuilderImpl extends AbstractBuilder implements ResponseBuilder -{ +class ResponseBuilderImpl extends AbstractBuilder implements ResponseBuilder { private static final Set ignoredAttributes = new HashSet<>(Arrays.asList( "attributes", "proxyresponse", ManagerReader.COMMAND_RESULT_RESPONSE_KEY)); @@ -47,27 +40,18 @@ class ResponseBuilderImpl extends AbstractBuilder implements ResponseBuilder private static final String OUTPUT_RESPONSE_KEY = "output"; //Asterisk 14.3.0 @SuppressWarnings("unchecked") - public ManagerResponse buildResponse(Class responseClass, Map attributes) - { + public ManagerResponse buildResponse(Class responseClass, Map attributes) { final ManagerResponse response; final String responseType = (String) attributes.get(RESPONSE_KEY); - if (RESPONSE_TYPE_ERROR.equalsIgnoreCase(responseType)) - { + if (RESPONSE_TYPE_ERROR.equalsIgnoreCase(responseType)) { response = new ManagerError(); - } - else if (responseClass == null) - { + } else if (responseClass == null) { response = new ManagerResponse(); - } - else - { - try - { + } else { + try { response = responseClass.getDeclaredConstructor().newInstance(); - } - catch (Exception ex) - { + } catch (Exception ex) { logger.error("Unable to create new instance of " + responseClass.getName(), ex); return null; } @@ -75,37 +59,33 @@ else if (responseClass == null) setAttributes(response, attributes, ignoredAttributes); - if (response instanceof CommandResponse) - { + if (response instanceof CommandResponse) { final CommandResponse commandResponse = (CommandResponse) response; final List result = new ArrayList<>(); //For Asterisk 14 - if(attributes.get(OUTPUT_RESPONSE_KEY) != null){ - if(attributes.get(OUTPUT_RESPONSE_KEY) instanceof List){ - for(String tmp : (List)attributes.get(OUTPUT_RESPONSE_KEY)){ - if(tmp != null && tmp.length() != 0){ - result.add(tmp.trim()); - } - } - }else{ - result.add((String)attributes.get(OUTPUT_RESPONSE_KEY)); - } - - }else{ - for (String resultLine : ((String) attributes.get(ManagerReader.COMMAND_RESULT_RESPONSE_KEY)).split("\n")) - { - // on error there is a leading space - if (!resultLine.equals("--END COMMAND--") && !resultLine.equals(" --END COMMAND--")) - { - result.add(resultLine); - } - } + if (attributes.get(OUTPUT_RESPONSE_KEY) != null) { + if (attributes.get(OUTPUT_RESPONSE_KEY) instanceof List) { + for (String tmp : (List) attributes.get(OUTPUT_RESPONSE_KEY)) { + if (tmp != null && tmp.length() != 0) { + result.add(tmp.trim()); + } + } + } else { + result.add((String) attributes.get(OUTPUT_RESPONSE_KEY)); + } + + } else { + for (String resultLine : ((String) attributes.get(ManagerReader.COMMAND_RESULT_RESPONSE_KEY)).split("\n")) { + // on error there is a leading space + if (!resultLine.equals("--END COMMAND--") && !resultLine.equals(" --END COMMAND--")) { + result.add(resultLine); + } + } } commandResponse.setResult(result); } - if (response.getResponse() != null && attributes.get(PROXY_RESPONSE_KEY) != null) - { + if (response.getResponse() != null && attributes.get(PROXY_RESPONSE_KEY) != null) { response.setResponse((String) attributes.get(PROXY_RESPONSE_KEY)); } diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java index 7375aa0ff..7507f7598 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseEventsImpl.java @@ -16,26 +16,25 @@ */ package org.asteriskjava.manager.internal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - import org.asteriskjava.lock.LockableList; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.event.ResponseEvent; import org.asteriskjava.manager.response.ManagerResponse; +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + /** * Implementation of the ResponseEvents interface. - * + * * @author srt * @version $Id$ * @since 0.2 */ -public class ResponseEventsImpl implements ResponseEvents -{ +public class ResponseEventsImpl implements ResponseEvents { private ManagerResponse response; private final LockableList events; private boolean complete; @@ -44,26 +43,22 @@ public class ResponseEventsImpl implements ResponseEvents /** * Creates a new instance. */ - public ResponseEventsImpl() - { + public ResponseEventsImpl() { this.events = new LockableList<>(new ArrayList<>()); this.complete = false; } // implementation of the ResponseEvents interface - public ManagerResponse getResponse() - { + public ManagerResponse getResponse() { return response; } - public Collection getEvents() - { + public Collection getEvents() { return events; } - public boolean isComplete() - { + public boolean isComplete() { return complete; } @@ -71,35 +66,31 @@ public boolean isComplete() /** * Sets the ManagerResponse received. - * + * * @param response the ManagerResponse received. */ - public void setRepsonse(ManagerResponse response) - { + public void setRepsonse(ManagerResponse response) { this.response = response; } /** * Adds a ResponseEvent that has been received. - * + * * @param event the ResponseEvent that has been received. */ - public void addEvent(ResponseEvent event) - { - try (LockCloser closer = events.withLock()) - { + public void addEvent(ResponseEvent event) { + try (LockCloser closer = events.withLock()) { events.add(event); } } /** * Indicates if all events have been received. - * + * * @param complete true if all events have been received, - * false otherwise. + * false otherwise. */ - public void setComplete(boolean complete) - { + public void setComplete(boolean complete) { this.complete = complete; } @@ -108,19 +99,16 @@ public void setComplete(boolean complete) * @return * @throws InterruptedException */ - public boolean await(long timeout) throws InterruptedException - { + public boolean await(long timeout) throws InterruptedException { return latch.await(timeout, TimeUnit.MILLISECONDS); } - public void countDown() - { + public void countDown() { latch.countDown(); } @Override - public String toString() - { + public String toString() { return "ResponseEventsImpl [response=" + response + ",\nevents=" + events + ",\ncomplete=" + complete + "]"; } } diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/BackwardsCompatibilityForManagerEvents.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/BackwardsCompatibilityForManagerEvents.java index 32d6c4fcd..51d6b3a15 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/BackwardsCompatibilityForManagerEvents.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/BackwardsCompatibilityForManagerEvents.java @@ -4,17 +4,14 @@ import org.asteriskjava.manager.internal.backwardsCompatibility.bridge.BridgesActive; import org.asteriskjava.manager.internal.backwardsCompatibility.meetme.MeetmeCompatibility; -public class BackwardsCompatibilityForManagerEvents -{ +public class BackwardsCompatibilityForManagerEvents { // Logger logger = LogManager.getLogger(); BridgesActive bridges = new BridgesActive(); MeetmeCompatibility meetme = new MeetmeCompatibility(); - public ManagerEvent handleEvent(ManagerEvent event) - { + public ManagerEvent handleEvent(ManagerEvent event) { ManagerEvent newEvent = bridges.handleEvent(event); - if (newEvent == null) - { + if (newEvent == null) { newEvent = meetme.handleEvent(event); } return newEvent; diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java index 9964e057a..cd4ca0c36 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeEnterEventComparator.java @@ -16,27 +16,24 @@ */ package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; +import org.asteriskjava.manager.event.BridgeEnterEvent; + import java.util.Comparator; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.asteriskjava.manager.event.BridgeEnterEvent; - -public class BridgeEnterEventComparator implements Comparator -{ +public class BridgeEnterEventComparator implements Comparator { private static final Pattern UNIQUE_ID_PATTERN = Pattern.compile("([0-9]+)\\.([0-9]+)$"); @Override - public int compare(BridgeEnterEvent o1, BridgeEnterEvent o2) - { + public int compare(BridgeEnterEvent o1, BridgeEnterEvent o2) { Matcher uniqueId1Matcher = UNIQUE_ID_PATTERN.matcher(o1.getUniqueId()); Matcher uniqueId2Matcher = UNIQUE_ID_PATTERN.matcher(o2.getUniqueId()); boolean find1 = uniqueId1Matcher.find(); boolean find2 = uniqueId2Matcher.find(); - if (find1 && find2) - { + if (find1 && find2) { // 1501234567.890 -> epochtime: 1501234567 | serial: 890 long epochtime1 = Long.valueOf(uniqueId1Matcher.group(1)); long epochtime2 = Long.valueOf(uniqueId2Matcher.group(1)); @@ -44,14 +41,10 @@ public int compare(BridgeEnterEvent o1, BridgeEnterEvent o2) int serial2 = Integer.valueOf(uniqueId2Matcher.group(2)); return epochtime1 == epochtime2 ? Integer.compare(serial1, serial2) : Long.compare(epochtime1, epochtime2); - } - else if (!find1 && !find2) - { + } else if (!find1 && !find2) { // Both of inputs are invalid value: id1 == id2 return 0; - } - else - { + } else { // id1 is valid ==> 1 return find1 ? 1 : -1; } diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java index ec0d6727b..cc6d071c1 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgeState.java @@ -1,11 +1,5 @@ package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; - import org.asteriskjava.lock.LockableMap; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.event.BridgeEnterEvent; @@ -14,14 +8,15 @@ import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.util.DateUtil; +import java.util.*; + /** * Track the current members of a bridge, emmitting BridgeEvents when 2 members * join or breakup * * @author rsutton */ -class BridgeState -{ +class BridgeState { // private final Log logger = LogFactory.getLog(getClass()); private static final BridgeEnterEventComparator BRIDGE_ENTER_EVENT_COMPARATOR = new BridgeEnterEventComparator(); @@ -29,10 +24,8 @@ class BridgeState private final LockableMap members = new LockableMap<>(new HashMap<>()); - ManagerEvent destroy() - { - try (LockCloser closer = members.withLock()) - { + ManagerEvent destroy() { + try (LockCloser closer = members.withLock()) { members.clear(); } return null; @@ -44,26 +37,21 @@ ManagerEvent destroy() * @param event * @return */ - ManagerEvent addMember(BridgeEnterEvent event) - { + ManagerEvent addMember(BridgeEnterEvent event) { List remaining = null; - if (HOLDING_BRIDGE_TECH.equals(event.getBridgeTechnology())) - { + if (HOLDING_BRIDGE_TECH.equals(event.getBridgeTechnology())) { /* channels in a holding bridge aren't bridged to one another */ return null; } - try (LockCloser closer = members.withLock()) - { - if (members.put(event.getChannel(), event) == null && members.size() == 2) - { + try (LockCloser closer = members.withLock()) { + if (members.put(event.getChannel(), event) == null && members.size() == 2) { remaining = new ArrayList<>(members.values()); } } - if (remaining == null) - { + if (remaining == null) { return null; } @@ -84,24 +72,19 @@ ManagerEvent addMember(BridgeEnterEvent event) * @return */ - ManagerEvent removeMember(BridgeLeaveEvent event) - { + ManagerEvent removeMember(BridgeLeaveEvent event) { List remaining = new LinkedList<>(); - if (HOLDING_BRIDGE_TECH.equals(event.getBridgeTechnology())) - { + if (HOLDING_BRIDGE_TECH.equals(event.getBridgeTechnology())) { /* channels in a holding bridge aren't bridged to one another */ return null; } - try (LockCloser closer = members.withLock()) - { + try (LockCloser closer = members.withLock()) { remaining.addAll(members.values()); - if (members.remove(event.getChannel()) != null) - { - if (remaining.size() == 2) - { + if (members.remove(event.getChannel()) != null) { + if (remaining.size() == 2) { return buildBridgeEvent(BridgeEvent.BRIDGE_STATE_UNLINK, remaining); } } @@ -114,8 +97,7 @@ ManagerEvent removeMember(BridgeLeaveEvent event) } - private BridgeEvent buildBridgeEvent(String bridgeState, List members) - { + private BridgeEvent buildBridgeEvent(String bridgeState, List members) { Collections.sort(members, BRIDGE_ENTER_EVENT_COMPARATOR); BridgeEvent bridgeEvent = new BridgeEvent(this); diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java index 55e675c42..d91f9cba5 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/bridge/BridgesActive.java @@ -1,16 +1,12 @@ package org.asteriskjava.manager.internal.backwardsCompatibility.bridge; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.asteriskjava.manager.event.BridgeCreateEvent; -import org.asteriskjava.manager.event.BridgeDestroyEvent; -import org.asteriskjava.manager.event.BridgeEnterEvent; -import org.asteriskjava.manager.event.BridgeLeaveEvent; -import org.asteriskjava.manager.event.ManagerEvent; +import org.asteriskjava.manager.event.*; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + /** * Backwards compatibility for bridge events.
    *
    @@ -19,69 +15,53 @@ *
    * Here we track active bridges and simulate BridgeEvent's for them allowing * legacy code to still work with BridgeEvent's - * + * * @author rsutton */ -public class BridgesActive -{ +public class BridgesActive { private final Log logger = LogFactory.getLog(BridgesActive.class); private final ConcurrentMap activeBridges = new ConcurrentHashMap<>(); - public ManagerEvent handleEvent(ManagerEvent event) - { - if (event instanceof BridgeCreateEvent) - { + public ManagerEvent handleEvent(ManagerEvent event) { + if (event instanceof BridgeCreateEvent) { return createBridge((BridgeCreateEvent) event); - } - else if (event instanceof BridgeDestroyEvent) - { + } else if (event instanceof BridgeDestroyEvent) { return destroyBridge((BridgeDestroyEvent) event); - } - else if (event instanceof BridgeEnterEvent) - { + } else if (event instanceof BridgeEnterEvent) { return enterBridge((BridgeEnterEvent) event); - } - else if (event instanceof BridgeLeaveEvent) - { + } else if (event instanceof BridgeLeaveEvent) { return leaveBridge((BridgeLeaveEvent) event); } return null; } - ManagerEvent createBridge(BridgeCreateEvent event) - { + ManagerEvent createBridge(BridgeCreateEvent event) { activeBridges.putIfAbsent(event.getBridgeUniqueId(), new BridgeState()); return null; } - ManagerEvent destroyBridge(BridgeDestroyEvent event) - { + ManagerEvent destroyBridge(BridgeDestroyEvent event) { BridgeState state = activeBridges.remove(event.getBridgeUniqueId()); - if (state != null) - { + if (state != null) { return state.destroy(); } logger.info("Cant find bridge for id " + event.getBridgeUniqueId()); return null; } - ManagerEvent enterBridge(BridgeEnterEvent event) - { + ManagerEvent enterBridge(BridgeEnterEvent event) { BridgeState state = activeBridges.get(event.getBridgeUniqueId()); - if (state != null) - { + if (state != null) { return state.addMember(event); } logger.error("Cant find bridge for id " + event.getBridgeUniqueId()); return null; } - ManagerEvent leaveBridge(BridgeLeaveEvent event) - { + ManagerEvent leaveBridge(BridgeLeaveEvent event) { BridgeState state = activeBridges.get(event.getBridgeUniqueId()); - if (state != null) - { + if (state != null) { return state.removeMember(event); } logger.info("Cant find bridge for id " + event.getBridgeUniqueId()); diff --git a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/meetme/MeetmeCompatibility.java b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/meetme/MeetmeCompatibility.java index cd0dfd3cf..3aea7b3af 100644 --- a/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/meetme/MeetmeCompatibility.java +++ b/src/main/java/org/asteriskjava/manager/internal/backwardsCompatibility/meetme/MeetmeCompatibility.java @@ -1,13 +1,6 @@ package org.asteriskjava.manager.internal.backwardsCompatibility.meetme; -import org.asteriskjava.manager.event.ConfbridgeEndEvent; -import org.asteriskjava.manager.event.ConfbridgeJoinEvent; -import org.asteriskjava.manager.event.ConfbridgeLeaveEvent; -import org.asteriskjava.manager.event.ConfbridgeStartEvent; -import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.MeetMeEndEvent; -import org.asteriskjava.manager.event.MeetMeJoinEvent; -import org.asteriskjava.manager.event.MeetMeLeaveEvent; +import org.asteriskjava.manager.event.*; /** * Backwards compatibility for bridge events.
    @@ -17,28 +10,19 @@ *
    * Here we track active bridges and simulate BridgeEvent's for them allowing * legacy code to still work with BridgeEvent's - * + * * @author rsutton */ -public class MeetmeCompatibility -{ +public class MeetmeCompatibility { - public ManagerEvent handleEvent(ManagerEvent event) - { - if (event instanceof ConfbridgeStartEvent) - { - } - else if (event instanceof ConfbridgeEndEvent) - { + public ManagerEvent handleEvent(ManagerEvent event) { + if (event instanceof ConfbridgeStartEvent) { + } else if (event instanceof ConfbridgeEndEvent) { MeetMeEndEvent endEvent = new MeetMeEndEvent(this); endEvent.setDateReceived(event.getDateReceived()); endEvent.setMeetMe(((ConfbridgeEndEvent) event).getConference()); return endEvent; - } - else - - if (event instanceof ConfbridgeJoinEvent) - { + } else if (event instanceof ConfbridgeJoinEvent) { MeetMeJoinEvent joinEvent = new MeetMeJoinEvent(this); joinEvent.setCallerIdNum(event.getCallerIdNum()); joinEvent.setCallerIdName(event.getCallerIdName()); @@ -48,9 +32,7 @@ else if (event instanceof ConfbridgeEndEvent) joinEvent.setDateReceived(event.getDateReceived()); return joinEvent; - } - else if (event instanceof ConfbridgeLeaveEvent) - { + } else if (event instanceof ConfbridgeLeaveEvent) { MeetMeLeaveEvent leaveEvent = new MeetMeLeaveEvent(this); leaveEvent.setCallerIdNum(event.getCallerIdNum()); leaveEvent.setCallerIdName(event.getCallerIdName()); diff --git a/src/main/java/org/asteriskjava/manager/internal/package.html b/src/main/java/org/asteriskjava/manager/internal/package.html index 18114dfdd..138b830df 100644 --- a/src/main/java/org/asteriskjava/manager/internal/package.html +++ b/src/main/java/org/asteriskjava/manager/internal/package.html @@ -1,28 +1,28 @@ - +

    Provides private implementations for interfaces defined in the - org.asteriskjava.manager package.

    + org.asteriskjava.manager package.

    - \ No newline at end of file + diff --git a/src/main/java/org/asteriskjava/manager/package.html b/src/main/java/org/asteriskjava/manager/package.html index 706dd9aa2..5f40b682e 100644 --- a/src/main/java/org/asteriskjava/manager/package.html +++ b/src/main/java/org/asteriskjava/manager/package.html @@ -1,27 +1,27 @@ - +

    Provides an implementaion of Asterisk's Manager API.

    - \ No newline at end of file + diff --git a/src/main/java/org/asteriskjava/manager/response/ChallengeResponse.java b/src/main/java/org/asteriskjava/manager/response/ChallengeResponse.java index 0727fb552..662668784 100644 --- a/src/main/java/org/asteriskjava/manager/response/ChallengeResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/ChallengeResponse.java @@ -25,8 +25,7 @@ * @see org.asteriskjava.manager.action.ChallengeAction * @see org.asteriskjava.manager.action.LoginAction */ -public class ChallengeResponse extends ManagerResponse -{ +public class ChallengeResponse extends ManagerResponse { private static final long serialVersionUID = -7253724086340850957L; private String challenge; @@ -37,13 +36,11 @@ public class ChallengeResponse extends ManagerResponse * @return the challenge to use when creating the key for log in. * @see org.asteriskjava.manager.action.LoginAction#setKey(String) */ - public String getChallenge() - { + public String getChallenge() { return challenge; } - public void setChallenge(String challenge) - { + public void setChallenge(String challenge) { this.challenge = challenge; } } diff --git a/src/main/java/org/asteriskjava/manager/response/CommandResponse.java b/src/main/java/org/asteriskjava/manager/response/CommandResponse.java index f0a33baa9..f1e640dde 100644 --- a/src/main/java/org/asteriskjava/manager/response/CommandResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/CommandResponse.java @@ -24,14 +24,12 @@ * Follows" line followed by the raw output of the command including empty lines. At the end of the * command output a line containing "--END COMMAND--" is sent. The reader parses this response into * a CommandResponse object to hide these details. - * - * @see org.asteriskjava.manager.action.CommandAction - * + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.CommandAction */ -public class CommandResponse extends ManagerResponse -{ +public class CommandResponse extends ManagerResponse { private static final long serialVersionUID = 1L; private String privilege; @@ -43,13 +41,11 @@ public class CommandResponse extends ManagerResponse * @return always "Command" * @since 1.0.0 */ - public String getPrivilege() - { + public String getPrivilege() { return privilege; } - public void setPrivilege(String privilege) - { + public void setPrivilege(String privilege) { this.privilege = privilege; } @@ -58,16 +54,14 @@ public void setPrivilege(String privilege) * * @return a List of strings representing the lines returned by the CLI command. */ - public List getResult() - { + public List getResult() { return result; } /** * Sets the result. */ - public void setResult(List result) - { + public void setResult(List result) { this.result = result; } } diff --git a/src/main/java/org/asteriskjava/manager/response/CoreSettingsResponse.java b/src/main/java/org/asteriskjava/manager/response/CoreSettingsResponse.java index cd06a0f82..e7e233922 100644 --- a/src/main/java/org/asteriskjava/manager/response/CoreSettingsResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/CoreSettingsResponse.java @@ -25,8 +25,7 @@ * @see org.asteriskjava.manager.action.CoreSettingsAction * @since 1.0.0 */ -public class CoreSettingsResponse extends ManagerResponse -{ +public class CoreSettingsResponse extends ManagerResponse { private static final long serialVersionUID = 1L; private String amiVersion; @@ -46,13 +45,11 @@ public class CoreSettingsResponse extends ManagerResponse * * @return the version of the Asterisk Manager Interface (AMI). */ - public String getAmiVersion() - { + public String getAmiVersion() { return amiVersion; } - public void setAmiVersion(String amiVersion) - { + public void setAmiVersion(String amiVersion) { this.amiVersion = amiVersion; } @@ -61,73 +58,59 @@ public void setAmiVersion(String amiVersion) * * @return the version of the Asterisk server. */ - public String getAsteriskVersion() - { + public String getAsteriskVersion() { return asteriskVersion; } - public void setAsteriskVersion(String asteriskVersion) - { + public void setAsteriskVersion(String asteriskVersion) { this.asteriskVersion = asteriskVersion; } - public String getSystemName() - { + public String getSystemName() { return systemName; } - public void setSystemName(String systemName) - { + public void setSystemName(String systemName) { this.systemName = systemName; } - public Integer getCoreMaxCalls() - { + public Integer getCoreMaxCalls() { return coreMaxCalls; } - public void setCoreMaxCalls(Integer coreMaxCalls) - { + public void setCoreMaxCalls(Integer coreMaxCalls) { this.coreMaxCalls = coreMaxCalls; } - public Double getCoreMaxLoadAvg() - { + public Double getCoreMaxLoadAvg() { return coreMaxLoadAvg; } - public void setCoreMaxLoadAvg(Double coreMaxLoadAvg) - { + public void setCoreMaxLoadAvg(Double coreMaxLoadAvg) { this.coreMaxLoadAvg = coreMaxLoadAvg; } - public String getCoreRunUser() - { + public String getCoreRunUser() { return coreRunUser; } - public void setCoreRunUser(String coreRunUser) - { + public void setCoreRunUser(String coreRunUser) { this.coreRunUser = coreRunUser; } - public String getCoreRunGroup() - { + public String getCoreRunGroup() { return coreRunGroup; } - public void setCoreRunGroup(String coreRunGroup) - { + public void setCoreRunGroup(String coreRunGroup) { this.coreRunGroup = coreRunGroup; } - public Integer getCoreMaxFilehandles() - { + public Integer getCoreMaxFilehandles() { return coreMaxFilehandles; } - public void setCoreMaxFilehandles(Integer coreMaxFilehandles) - { + public void setCoreMaxFilehandles(Integer coreMaxFilehandles) { this.coreMaxFilehandles = coreMaxFilehandles; } @@ -136,13 +119,11 @@ public void setCoreMaxFilehandles(Integer coreMaxFilehandles) * * @return true if the realtime subsystem is enabled, false otherwise. */ - public boolean isCoreRealtimeEnabled() - { + public boolean isCoreRealtimeEnabled() { return coreRealtimeEnabled != null && coreRealtimeEnabled; } - public void setCoreRealtimeEnabled(Boolean coreRealtimeEnabled) - { + public void setCoreRealtimeEnabled(Boolean coreRealtimeEnabled) { this.coreRealtimeEnabled = coreRealtimeEnabled; } @@ -151,13 +132,11 @@ public void setCoreRealtimeEnabled(Boolean coreRealtimeEnabled) * * @return true if the CDR subsystem is enabled, false otherwise. */ - public boolean isCoreCdrEnabled() - { + public boolean isCoreCdrEnabled() { return coreCdrEnabled != null && coreCdrEnabled; } - public void setCoreCdrEnabled(Boolean coreCdrEnabled) - { + public void setCoreCdrEnabled(Boolean coreCdrEnabled) { this.coreCdrEnabled = coreCdrEnabled; } @@ -166,13 +145,11 @@ public void setCoreCdrEnabled(Boolean coreCdrEnabled) * * @return true if the HTTP subsystem is enabled, false otherwise. */ - public boolean isCoreHttpEnabled() - { + public boolean isCoreHttpEnabled() { return coreHttpEnabled != null && coreHttpEnabled; } - public void setCoreHttpEnabled(Boolean coreHttpEnabled) - { + public void setCoreHttpEnabled(Boolean coreHttpEnabled) { this.coreHttpEnabled = coreHttpEnabled; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/response/CoreStatusResponse.java b/src/main/java/org/asteriskjava/manager/response/CoreStatusResponse.java index 9e78dde1e..cc2f8237a 100644 --- a/src/main/java/org/asteriskjava/manager/response/CoreStatusResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/CoreStatusResponse.java @@ -16,11 +16,11 @@ */ package org.asteriskjava.manager.response; +import org.asteriskjava.util.DateUtil; + import java.util.Date; import java.util.TimeZone; -import org.asteriskjava.util.DateUtil; - /** * Corresponds to a CoreStatusAction and contains the current status summary of the * Asterisk server. @@ -30,8 +30,7 @@ * @see org.asteriskjava.manager.action.CoreStatusAction * @since 1.0.0 */ -public class CoreStatusResponse extends ManagerResponse -{ +public class CoreStatusResponse extends ManagerResponse { private static final long serialVersionUID = 1L; private String coreStartupTime; @@ -46,13 +45,11 @@ public class CoreStatusResponse extends ManagerResponse * * @return the time the server (core module) was last reloaded. */ - public String getCoreReloadTime() - { + public String getCoreReloadTime() { return coreReloadTime; } - public void setCoreReloadTime(String s) - { + public void setCoreReloadTime(String s) { // format is %H:%M:%S this.coreReloadTime = s; } @@ -63,13 +60,11 @@ public void setCoreReloadTime(String s) * * @return the date the server (core module) was last reloaded. */ - public String getCoreReloadDate() - { + public String getCoreReloadDate() { return coreReloadDate; } - public void setCoreReloadDate(String CoreReloadDate) - { + public void setCoreReloadDate(String CoreReloadDate) { this.coreReloadDate = CoreReloadDate; } @@ -83,8 +78,7 @@ public void setCoreReloadDate(String CoreReloadDate) * @see #getCoreReloadTime() * @see #getCoreReloadDateTimeAsDate(java.util.TimeZone) */ - public Date getCoreReloadDateTimeAsDate() - { + public Date getCoreReloadDateTimeAsDate() { return getCoreReloadDateTimeAsDate(null); } @@ -98,10 +92,8 @@ public Date getCoreReloadDateTimeAsDate() * @see #getCoreReloadDate() * @see #getCoreReloadTime() */ - public Date getCoreReloadDateTimeAsDate(TimeZone tz) - { - if (coreReloadDate == null || coreReloadTime == null) - { + public Date getCoreReloadDateTimeAsDate(TimeZone tz) { + if (coreReloadDate == null || coreReloadTime == null) { return null; } @@ -114,13 +106,11 @@ public Date getCoreReloadDateTimeAsDate(TimeZone tz) * * @return the date the server was started. */ - public String getCoreStartupDate() - { + public String getCoreStartupDate() { return coreStartupDate; } - public void setCoreStartupDate(String CoreStartupDate) - { + public void setCoreStartupDate(String CoreStartupDate) { this.coreStartupDate = CoreStartupDate; } @@ -129,13 +119,11 @@ public void setCoreStartupDate(String CoreStartupDate) * * @return the time the server was started. */ - public String getCoreStartupTime() - { + public String getCoreStartupTime() { return coreStartupTime; } - public void setCoreStartupTime(String s) - { + public void setCoreStartupTime(String s) { // format is %H:%M:%S this.coreStartupTime = s; } @@ -150,8 +138,7 @@ public void setCoreStartupTime(String s) * @see #getCoreStartupTime() * @see #getCoreStartupDateTimeAsDate(java.util.TimeZone) */ - public Date getCoreStartupDateTimeAsDate() - { + public Date getCoreStartupDateTimeAsDate() { return getCoreStartupDateTimeAsDate(null); } @@ -165,10 +152,8 @@ public Date getCoreStartupDateTimeAsDate() * @see #getCoreStartupDate() * @see #getCoreStartupTime() */ - public Date getCoreStartupDateTimeAsDate(TimeZone tz) - { - if (coreStartupDate == null || coreStartupTime == null) - { + public Date getCoreStartupDateTimeAsDate(TimeZone tz) { + if (coreStartupDate == null || coreStartupTime == null) { return null; } @@ -180,13 +165,11 @@ public Date getCoreStartupDateTimeAsDate(TimeZone tz) * * @return the number of currently active channels on the server. */ - public Integer getCoreCurrentCalls() - { + public Integer getCoreCurrentCalls() { return coreCurrentCalls; } - public void setCoreCurrentCalls(Integer coreCurrentCalls) - { + public void setCoreCurrentCalls(Integer coreCurrentCalls) { this.coreCurrentCalls = coreCurrentCalls; } } diff --git a/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java b/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java index 086cf9635..e9afcb964 100644 --- a/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/ExtensionStateResponse.java @@ -17,90 +17,77 @@ package org.asteriskjava.manager.response; /** - * Response to an {@link org.asteriskjava.manager.action.ExtensionStateAction}. + * Response to an {@link org.asteriskjava.manager.action.ExtensionStateAction}. * * @author srt * @version $Id$ * @see org.asteriskjava.manager.action.ExtensionStateAction */ -public class ExtensionStateResponse extends ManagerResponse -{ - private static final long serialVersionUID = -2044248427247227390L; - private String exten; - private String context; - private String hint; - private Integer status; - private String statusText; +public class ExtensionStateResponse extends ManagerResponse { + private static final long serialVersionUID = -2044248427247227390L; + private String exten; + private String context; + private String hint; + private Integer status; + private String statusText; - public String getExten() - { - return exten; - } + public String getExten() { + return exten; + } - public void setExten(String exten) - { - this.exten = exten; - } + public void setExten(String exten) { + this.exten = exten; + } - public String getContext() - { - return context; - } + public String getContext() { + return context; + } - public void setContext(String context) - { - this.context = context; - } + public void setContext(String context) { + this.context = context; + } - public String getHint() - { - return hint; - } + public String getHint() { + return hint; + } - public void setHint(String hint) - { - this.hint = hint; - } + public void setHint(String hint) { + this.hint = hint; + } - public Integer getStatus() - { - return status; - } + public Integer getStatus() { + return status; + } - public void setStatus(Integer status) - { - this.status = status; - } + public void setStatus(Integer status) { + this.status = status; + } - public String getStatusText() - { - return statusText; - } + public String getStatusText() { + return statusText; + } - public void setStatusText(String statusText) - { - this.statusText = statusText; - } + public void setStatusText(String statusText) { + this.statusText = statusText; + } - - - @Override - public String toString() - { - StringBuilder sb; - sb = new StringBuilder(getClass().getName() + ": "); - sb.append("actionId='").append(getActionId()).append("'; "); - sb.append("message='").append(getMessage()).append("'; "); - sb.append("response='").append(getResponse()).append("'; "); - sb.append("uniqueId='").append(getUniqueId()).append("'; "); - sb.append("exten='").append(getExten()).append("'; "); - sb.append("context='").append(getContext()).append("'; "); - sb.append("hint='").append(getHint()).append("'; "); - sb.append("status='").append(getStatus()).append("'; "); - sb.append("statustext='").append(getStatusText()).append("'; "); - sb.append("systemHashcode=").append(System.identityHashCode(this)); + @Override + public String toString() { + StringBuilder sb; - return sb.toString(); - } + sb = new StringBuilder(getClass().getName() + ": "); + sb.append("actionId='").append(getActionId()).append("'; "); + sb.append("message='").append(getMessage()).append("'; "); + sb.append("response='").append(getResponse()).append("'; "); + sb.append("uniqueId='").append(getUniqueId()).append("'; "); + sb.append("exten='").append(getExten()).append("'; "); + sb.append("context='").append(getContext()).append("'; "); + sb.append("hint='").append(getHint()).append("'; "); + sb.append("status='").append(getStatus()).append("'; "); + sb.append("statustext='").append(getStatusText()).append("'; "); + sb.append("systemHashcode=").append(System.identityHashCode(this)); + + return sb.toString(); + } } diff --git a/src/main/java/org/asteriskjava/manager/response/GetConfigResponse.java b/src/main/java/org/asteriskjava/manager/response/GetConfigResponse.java index 7ed95d4d5..da4ec4a02 100644 --- a/src/main/java/org/asteriskjava/manager/response/GetConfigResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/GetConfigResponse.java @@ -29,37 +29,32 @@ * the ugly details. If the file requested exists but does not contain at least * a line with a category, the ResponseBuilder won't create an instance of * GetConfigResponse, as it won't know what the empty response is. - * - * @see org.asteriskjava.manager.action.GetConfigAction + * * @author martins + * @see org.asteriskjava.manager.action.GetConfigAction * @since 0.3 */ -public class GetConfigResponse extends ManagerResponse -{ +public class GetConfigResponse extends ManagerResponse { private static final long serialVersionUID = -2044248427247227390L; - + private Map categories; private Map> lines; /** * Returns the map of category numbers to category names. - * + * * @return the map of category numbers to names. * @see org.asteriskjava.manager.response.GetConfigResponse#getLines */ - public Map getCategories() - { - if (categories == null) - { + public Map getCategories() { + if (categories == null) { categories = new TreeMap<>(); } Map responseMap = super.getAttributes(); - for (Entry response : responseMap.entrySet()) - { + for (Entry response : responseMap.entrySet()) { String key = response.getKey(); - if (key.toLowerCase(Locale.US).contains("category")) - { + if (key.toLowerCase(Locale.US).contains("category")) { String[] keyParts = key.split("-"); // if it doesn't have at least category-XXXXXX, skip @@ -68,12 +63,9 @@ public Map getCategories() // try to get the number of this category, skip if we mess up Integer categoryNumber; - try - { + try { categoryNumber = Integer.parseInt(keyParts[1]); - } - catch (Exception exception) - { + } catch (Exception exception) { continue; } @@ -86,65 +78,52 @@ public Map getCategories() /** * Returns the map of line number to line value for a given category. - * + * * @param categoryNumber a valid category number from getCategories. * @return the map of category numbers to names. * @see org.asteriskjava.manager.response.GetConfigResponse#getCategories */ - public Map getLines(int categoryNumber) - { - if (lines == null) - { + public Map getLines(int categoryNumber) { + if (lines == null) { lines = new TreeMap<>(); } Map responseMap = super.getAttributes(); - for (Entry response : responseMap.entrySet()) - { + for (Entry response : responseMap.entrySet()) { String key = response.getKey(); - if (key.toLowerCase(Locale.US).contains("line")) - { + if (key.toLowerCase(Locale.US).contains("line")) { String[] keyParts = key.split("-"); // if it doesn't have at least line-XXXXXX-XXXXXX, skip - if (keyParts.length < 3) - { + if (keyParts.length < 3) { continue; } // try to get the number of this category, skip if we mess up Integer potentialCategoryNumber; - try - { + try { potentialCategoryNumber = Integer.parseInt(keyParts[1]); - } - catch (Exception exception) - { + } catch (Exception exception) { continue; } // try to get the number of this line, skip if we mess up Integer potentialLineNumber; - try - { + try { potentialLineNumber = Integer.parseInt(keyParts[2]); - } - catch (Exception exception) - { + } catch (Exception exception) { continue; } // get the List out for placing stuff in Map linesForCategory = lines.get(potentialCategoryNumber); - if (linesForCategory == null) - { + if (linesForCategory == null) { linesForCategory = new TreeMap<>(); } // put the line we just parsed into the line map for this category linesForCategory.put(potentialLineNumber, (String) response.getValue()); - if (!lines.containsKey(potentialCategoryNumber)) - { + if (!lines.containsKey(potentialCategoryNumber)) { lines.put(potentialCategoryNumber, linesForCategory); } } diff --git a/src/main/java/org/asteriskjava/manager/response/GetVarResponse.java b/src/main/java/org/asteriskjava/manager/response/GetVarResponse.java index ba862d475..8758a6da7 100644 --- a/src/main/java/org/asteriskjava/manager/response/GetVarResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/GetVarResponse.java @@ -24,8 +24,7 @@ * @see org.asteriskjava.manager.action.GetVarAction * @since 1.0.0 */ -public class GetVarResponse extends ManagerResponse -{ +public class GetVarResponse extends ManagerResponse { private static final long serialVersionUID = 1L; private String variable; @@ -36,8 +35,7 @@ public class GetVarResponse extends ManagerResponse * * @return the name of the requested variable. */ - public String getVariable() - { + public String getVariable() { return variable; } @@ -46,8 +44,7 @@ public String getVariable() * * @param variable the name of the requested variable. */ - public void setVariable(String variable) - { + public void setVariable(String variable) { this.variable = variable; } @@ -56,8 +53,7 @@ public void setVariable(String variable) * * @return the value of the requested variable. */ - public String getValue() - { + public String getValue() { return value; } @@ -66,8 +62,7 @@ public String getValue() * * @param value the value of the requested variable. */ - public void setValue(String value) - { + public void setValue(String value) { this.value = value; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/response/MailboxCountResponse.java b/src/main/java/org/asteriskjava/manager/response/MailboxCountResponse.java index 24db2e53e..66bdae04e 100644 --- a/src/main/java/org/asteriskjava/manager/response/MailboxCountResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/MailboxCountResponse.java @@ -19,14 +19,12 @@ /** * A MailboxCountResponse is sent in response to a MailboxCountAction and contains the number of old * and new messages in a mailbox. - * - * @see org.asteriskjava.manager.action.MailboxCountAction - * + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.MailboxCountAction */ -public class MailboxCountResponse extends ManagerResponse -{ +public class MailboxCountResponse extends ManagerResponse { /** * Serial version identifier */ @@ -38,48 +36,42 @@ public class MailboxCountResponse extends ManagerResponse /** * Returns the name of the mailbox. */ - public String getMailbox() - { + public String getMailbox() { return mailbox; } /** * Sets the name of the mailbox. */ - public void setMailbox(String mailbox) - { + public void setMailbox(String mailbox) { this.mailbox = mailbox; } /** * Returns the number of new messages in the mailbox. */ - public Integer getNewMessages() - { + public Integer getNewMessages() { return newMessages; } /** * Sets the number of new messages in the mailbox. */ - public void setNewMessages(Integer newMessages) - { + public void setNewMessages(Integer newMessages) { this.newMessages = newMessages; } /** * Returns the number of old messages in the mailbox. */ - public Integer getOldMessages() - { + public Integer getOldMessages() { return oldMessages; } /** * Sets the number of old messages in the mailbox. */ - public void setOldMessages(Integer oldMessages) - { + public void setOldMessages(Integer oldMessages) { this.oldMessages = oldMessages; } } diff --git a/src/main/java/org/asteriskjava/manager/response/MailboxStatusResponse.java b/src/main/java/org/asteriskjava/manager/response/MailboxStatusResponse.java index f76155fd5..c0e245d0d 100644 --- a/src/main/java/org/asteriskjava/manager/response/MailboxStatusResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/MailboxStatusResponse.java @@ -19,24 +19,22 @@ /** * A MailboxStatusResponse is sent in response to a MailboxStatusAction and indicates if a set * of mailboxes contains waiting messages. - * - * @see org.asteriskjava.manager.action.MailboxStatusAction - * + * * @author srt * @version $Id$ + * @see org.asteriskjava.manager.action.MailboxStatusAction */ -public class MailboxStatusResponse extends ManagerResponse -{ +public class MailboxStatusResponse extends ManagerResponse { /** * Serial version identifier */ private static final long serialVersionUID = -7193581424292429279L; - + /** * The name of the mailbox. */ private String mailbox; - + /** * Indicates if there are new messages waiting in the given set of mailboxes. */ @@ -44,19 +42,19 @@ public class MailboxStatusResponse extends ManagerResponse /** * Returns the names of the mailboxes, separated by ",". + * * @return the names of the mailbox. */ - public String getMailbox() - { + public String getMailbox() { return mailbox; } /** * Sets the names of the mailboxes. + * * @param mailbox the names of the mailboxes. */ - public void setMailbox(String mailbox) - { + public void setMailbox(String mailbox) { this.mailbox = mailbox; } @@ -64,8 +62,7 @@ public void setMailbox(String mailbox) * Returns Boolean.TRUE if at least one of the given mailboxes contains new messages; * Boolean.FALSE otherwise. */ - public Boolean getWaiting() - { + public Boolean getWaiting() { return waiting; } @@ -73,8 +70,7 @@ public Boolean getWaiting() * Set to Boolean.TRUE if at least one of the mailboxes contains new messages; * Boolean.FALSE otherwise. */ - public void setWaiting(Boolean waiting) - { + public void setWaiting(Boolean waiting) { this.waiting = waiting; } } diff --git a/src/main/java/org/asteriskjava/manager/response/ManagerError.java b/src/main/java/org/asteriskjava/manager/response/ManagerError.java index 47947439f..2b208f72b 100644 --- a/src/main/java/org/asteriskjava/manager/response/ManagerError.java +++ b/src/main/java/org/asteriskjava/manager/response/ManagerError.java @@ -19,12 +19,11 @@ /** * Represents an "Response: Error" response received from the asterisk server. * The cause for the error is given in the message attribute. - * + * * @author srt * @version $Id$ */ -public class ManagerError extends ManagerResponse -{ +public class ManagerError extends ManagerResponse { /** * Serial version identifier */ @@ -33,8 +32,7 @@ public class ManagerError extends ManagerResponse /** * Creates a new ManagerError. */ - public ManagerError() - { + public ManagerError() { super(); } } diff --git a/src/main/java/org/asteriskjava/manager/response/ManagerResponse.java b/src/main/java/org/asteriskjava/manager/response/ManagerResponse.java index 75fb7650f..cb8e5c53c 100644 --- a/src/main/java/org/asteriskjava/manager/response/ManagerResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/ManagerResponse.java @@ -33,8 +33,7 @@ * @version $Id$ * @see org.asteriskjava.manager.action.ManagerAction */ -public class ManagerResponse implements Serializable -{ +public class ManagerResponse implements Serializable { private static final long serialVersionUID = 1L; private Date dateReceived; @@ -53,8 +52,7 @@ public class ManagerResponse implements Serializable private Map attributes; private String output; - public ManagerResponse() - { + public ManagerResponse() { this.attributes = null; } @@ -65,8 +63,7 @@ public ManagerResponse() * * @see #getAttribute(String) */ - public Map getAttributes() - { + public Map getAttributes() { return attributes; } @@ -74,10 +71,9 @@ public Map getAttributes() * Sets the Map with all attributes. * * @param attributes Map with containing the attributes with all lower case - * keys. + * keys. */ - public void setAttributes(Map attributes) - { + public void setAttributes(Map attributes) { this.attributes = attributes; } @@ -100,16 +96,15 @@ public void setAttributes(Map attributes) * ManagerResponse response = connection.sendAction(action); * String alertInfo = response.getAttribute("ALERT_INFO"); * - * + *

    * As all attributes are internally stored in lower case the key is * automatically converted to lower case before lookup. * * @param key the key to lookup. * @return the value of the attribute stored under this key or - * null if there is no such attribute. + * null if there is no such attribute. */ - public String getAttribute(String key) - { + public String getAttribute(String key) { return (String) attributes.get(key.toLowerCase(Locale.ENGLISH)); } @@ -117,8 +112,7 @@ public String getAttribute(String key) * Returns the point in time this response was received from the asterisk * server. */ - public Date getDateReceived() - { + public Date getDateReceived() { return dateReceived; } @@ -126,8 +120,7 @@ public Date getDateReceived() * Sets the point in time this response was received from the asterisk * server. */ - public void setDateReceived(Date dateReceived) - { + public void setDateReceived(Date dateReceived) { this.dateReceived = dateReceived; } @@ -137,11 +130,10 @@ public void setDateReceived(Date dateReceived) * null. * * @return the action id of the ManagerAction that caused this response or - * null if none was set. + * null if none was set. * @see org.asteriskjava.manager.action.ManagerAction#setActionId(String) */ - public String getActionId() - { + public String getActionId() { return actionId; } @@ -151,12 +143,11 @@ public String getActionId() * This property is only available when using to AstManProxy. * * @return the name of the Asterisk server from which this response has been - * received or null when directly connected to an - * Asterisk server instead of AstManProxy. + * received or null when directly connected to an + * Asterisk server instead of AstManProxy. * @since 1.0.0 */ - public final String getServer() - { + public final String getServer() { return server; } @@ -165,11 +156,10 @@ public final String getServer() * received. * * @param server the name of the Asterisk server from which this response - * has been received. + * has been received. * @since 1.0.0 */ - public final void setServer(String server) - { + public final void setServer(String server) { this.server = server; } @@ -179,8 +169,7 @@ public final void setServer(String server) * @return "start", "stop" or "complete" * @since 1.0.0 */ - public String getEventList() - { + public String getEventList() { return eventList; } @@ -190,8 +179,7 @@ public String getEventList() * @param eventList the eventList. * @since 1.0.0 */ - public void setEventList(String eventList) - { + public void setEventList(String eventList) { this.eventList = eventList; } @@ -199,10 +187,9 @@ public void setEventList(String eventList) * Sets the action id of the ManagerAction that caused this response. * * @param actionId the action id of the ManagerAction that caused this - * response. + * response. */ - public void setActionId(String actionId) - { + public void setActionId(String actionId) { this.actionId = actionId; } @@ -210,16 +197,14 @@ public void setActionId(String actionId) * Returns the message received with this response. The content depends on * the action that generated this response. */ - public String getMessage() - { + public String getMessage() { return message; } /** * Sets the message. */ - public void setMessage(String message) - { + public void setMessage(String message) { this.message = message; } @@ -228,16 +213,14 @@ public void setMessage(String message) * "Success" or "Error" but depends on the action that generated this * response. */ - public String getResponse() - { + public String getResponse() { return response; } /** * Sets the response. */ - public void setResponse(String response) - { + public void setResponse(String response) { this.response = response; } @@ -246,43 +229,35 @@ public void setResponse(String response) * to keep track of channels created by the action sent, for example an * OriginateAction. */ - public String getUniqueId() - { + public String getUniqueId() { return uniqueId; } /** * Sets the unique id received with this response. */ - public void setUniqueId(String uniqueId) - { + public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } - protected Integer stringToInteger(String s, String suffix) throws NumberFormatException - { - if (s == null || s.length() == 0) - { + protected Integer stringToInteger(String s, String suffix) throws NumberFormatException { + if (s == null || s.length() == 0) { return null; } - if (suffix != null && s.endsWith(suffix)) - { + if (suffix != null && s.endsWith(suffix)) { return Integer.parseInt(s.substring(0, s.length() - suffix.length()).trim()); } return Integer.parseInt(s.trim()); } - protected Long stringToLong(String s, String suffix) throws NumberFormatException - { - if (s == null || s.length() == 0) - { + protected Long stringToLong(String s, String suffix) throws NumberFormatException { + if (s == null || s.length() == 0) { return null; } - if (suffix != null && s.endsWith(suffix)) - { + if (suffix != null && s.endsWith(suffix)) { return Long.parseLong(s.substring(0, s.length() - suffix.length()).trim()); } @@ -290,8 +265,7 @@ protected Long stringToLong(String s, String suffix) throws NumberFormatExceptio } @Override - public String toString() - { + public String toString() { StringBuilder sb; sb = new StringBuilder(100); @@ -305,21 +279,19 @@ public String toString() return sb.toString(); } - public String getEvents() - { + public String getEvents() { return events; } - public void setEvents(String events) - { + public void setEvents(String events) { this.events = events; } - public String getOutput() { - return output; - } + public String getOutput() { + return output; + } - public void setOutput(String output) { - this.output = output; - } + public void setOutput(String output) { + this.output = output; + } } diff --git a/src/main/java/org/asteriskjava/manager/response/MixMonitorResponse.java b/src/main/java/org/asteriskjava/manager/response/MixMonitorResponse.java index 77609965f..ab8d3997f 100644 --- a/src/main/java/org/asteriskjava/manager/response/MixMonitorResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/MixMonitorResponse.java @@ -19,13 +19,12 @@ /** * A MixMonitorResponse is sent in response to a MixMonitorAction and provides * the ID of the MixMonitor that was started on the referenced channel. - * + *

    * Available since Asterisk 11 * * @see org.asteriskjava.manager.action.MixMonitorAction; */ -public class MixMonitorResponse extends ManagerResponse -{ +public class MixMonitorResponse extends ManagerResponse { private static final long serialVersionUID = 1L; private String mixMonitorId; @@ -34,8 +33,7 @@ public class MixMonitorResponse extends ManagerResponse * * @return the MixMonitor ID */ - public String getMixMonitorId() - { + public String getMixMonitorId() { return mixMonitorId; } @@ -44,8 +42,7 @@ public String getMixMonitorId() * * @param mixMonitorId the MixMonitor ID */ - public void setMixMonitorId(String mixMonitorId) - { + public void setMixMonitorId(String mixMonitorId) { this.mixMonitorId = mixMonitorId; } } diff --git a/src/main/java/org/asteriskjava/manager/response/ModuleCheckResponse.java b/src/main/java/org/asteriskjava/manager/response/ModuleCheckResponse.java index ce03aa160..f131a5865 100644 --- a/src/main/java/org/asteriskjava/manager/response/ModuleCheckResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/ModuleCheckResponse.java @@ -24,8 +24,7 @@ * @see org.asteriskjava.manager.action.ModuleCheckAction * @since 1.0.0 */ -public class ModuleCheckResponse extends ManagerResponse -{ +public class ModuleCheckResponse extends ManagerResponse { private static final long serialVersionUID = -7253724086340850957L; private String version; @@ -35,13 +34,11 @@ public class ModuleCheckResponse extends ManagerResponse * * @return the version (svn revision) of the module. */ - public String getVersion() - { + public String getVersion() { return version; } - public void setVersion(String version) - { + public void setVersion(String version) { this.version = version; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/response/PingResponse.java b/src/main/java/org/asteriskjava/manager/response/PingResponse.java index 38a8a3f96..aee7a35b0 100644 --- a/src/main/java/org/asteriskjava/manager/response/PingResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/PingResponse.java @@ -22,40 +22,36 @@ * @author srt * @see org.asteriskjava.manager.action.PingAction */ -public class PingResponse extends ManagerResponse -{ +public class PingResponse extends ManagerResponse { private static final long serialVersionUID = 0L; private String ping; private String timestamp; - + /** * Returns always "Pong". * * @return always "Pong". */ - public String getPing() - { + public String getPing() { return ping; } - public void setPing(String ping) - { + public void setPing(String ping) { this.ping = ping; } /** * Timestamp for the response. + * * @return Timestamp as a String, e.g 1353747825.795863 * @since 1.0.0 */ - public String getTimestamp() - { + public String getTimestamp() { return timestamp; } - public void setTimestamp(String timestamp) - { + public void setTimestamp(String timestamp) { this.timestamp = timestamp; } } diff --git a/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java b/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java index cab680b14..7d24d85d9 100644 --- a/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java @@ -7,11 +7,10 @@ * * @author srt * @version $Id$ - * @since 1.0.0 * @see org.asteriskjava.manager.action.SipShowPeerAction + * @since 1.0.0 */ -public class SipShowPeerResponse extends ManagerResponse -{ +public class SipShowPeerResponse extends ManagerResponse { private static final long serialVersionUID = 1L; private String channelType; @@ -81,678 +80,542 @@ public class SipShowPeerResponse extends ManagerResponse private Map chanVariable; - public String getChannelType() - { + public String getChannelType() { return channelType; } - public void setChannelType(String channelType) - { + public void setChannelType(String channelType) { this.channelType = channelType; } - public String getObjectName() - { + public String getObjectName() { return objectName; } - public void setObjectName(String objectName) - { + public void setObjectName(String objectName) { this.objectName = objectName; } - public String getChanObjectType() - { + public String getChanObjectType() { return chanObjectType; } - public void setChanObjectType(String chanObjectType) - { + public void setChanObjectType(String chanObjectType) { this.chanObjectType = chanObjectType; } - public Boolean getSecretExist() - { + public Boolean getSecretExist() { return secretExist; } - public void setSecretExist(Boolean secretExist) - { + public void setSecretExist(Boolean secretExist) { this.secretExist = secretExist; } - public Boolean getMd5SecretExist() - { + public Boolean getMd5SecretExist() { return md5SecretExist; } - public void setMd5SecretExist(Boolean md5SecretExist) - { + public void setMd5SecretExist(Boolean md5SecretExist) { this.md5SecretExist = md5SecretExist; } - public Boolean getRemoteSecretExist() - { + public Boolean getRemoteSecretExist() { return remoteSecretExist; } - public void setRemoteSecretExist(Boolean remoteSecretExist) - { + public void setRemoteSecretExist(Boolean remoteSecretExist) { this.remoteSecretExist = remoteSecretExist; } - public String getContext() - { + public String getContext() { return context; } - public void setContext(String context) - { + public void setContext(String context) { this.context = context; } - public String getLanguage() - { + public String getLanguage() { return language; } - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } - public String getAccountCode() - { + public String getAccountCode() { return accountCode; } - public void setAccountCode(String accountCode) - { + public void setAccountCode(String accountCode) { this.accountCode = accountCode; } - public String getAmaFlags() - { + public String getAmaFlags() { return amaFlags; } - public void setAmaFlags(String amaFlags) - { + public void setAmaFlags(String amaFlags) { this.amaFlags = amaFlags; } - public String getCidCallingPres() - { + public String getCidCallingPres() { return cidCallingPres; } - public void setCidCallingPres(String cidCallingPres) - { + public void setCidCallingPres(String cidCallingPres) { this.cidCallingPres = cidCallingPres; } - public String getSipFromUser() - { + public String getSipFromUser() { return sipFromUser; } - public void setSipFromUser(String sipFromUser) - { + public void setSipFromUser(String sipFromUser) { this.sipFromUser = sipFromUser; } - public String getSipFromDomain() - { + public String getSipFromDomain() { return sipFromDomain; } - public void setSipFromDomain(String sipFromDomain) - { + public void setSipFromDomain(String sipFromDomain) { this.sipFromDomain = sipFromDomain; } - public String getCallGroup() - { + public String getCallGroup() { return callGroup; } - public void setCallGroup(String callGroup) - { + public void setCallGroup(String callGroup) { this.callGroup = callGroup; } - public String getPickupGroup() - { + public String getPickupGroup() { return pickupGroup; } - public void setPickupGroup(String pickupGroup) - { + public void setPickupGroup(String pickupGroup) { this.pickupGroup = pickupGroup; } - public String getVoiceMailbox() - { + public String getVoiceMailbox() { return voiceMailbox; } - public void setVoiceMailbox(String voiceMailbox) - { + public void setVoiceMailbox(String voiceMailbox) { this.voiceMailbox = voiceMailbox; } - public String getTransferMode() - { + public String getTransferMode() { return transferMode; } - public void setTransferMode(String transferMode) - { + public void setTransferMode(String transferMode) { this.transferMode = transferMode; } - public Integer getLastMsgsSent() - { + public Integer getLastMsgsSent() { return lastMsgsSent; } - public void setLastMsgsSent(Integer lastMsgsSent) - { + public void setLastMsgsSent(Integer lastMsgsSent) { this.lastMsgsSent = lastMsgsSent; } - public Integer getCallLimit() - { + public Integer getCallLimit() { return callLimit; } - public void setCallLimit(Integer callLimit) - { + public void setCallLimit(Integer callLimit) { this.callLimit = callLimit; } - public Integer getBusyLevel() - { + public Integer getBusyLevel() { return busyLevel; } - public void setBusyLevel(Integer busyLevel) - { + public void setBusyLevel(Integer busyLevel) { this.busyLevel = busyLevel; } - public Integer getMaxCallBr() - { + public Integer getMaxCallBr() { return maxCallBr; } - public void setMaxCallBr(String maxCallBr) - { + public void setMaxCallBr(String maxCallBr) { this.maxCallBr = stringToInteger(maxCallBr, "kbps"); } - public Boolean getDynamic() - { + public Boolean getDynamic() { return dynamic; } - public void setDynamic(Boolean dynamic) - { + public void setDynamic(Boolean dynamic) { this.dynamic = dynamic; } - public String getCallerId() - { + public String getCallerId() { return callerId; } - public void setCallerId(String callerId) - { + public void setCallerId(String callerId) { this.callerId = callerId; } - public Long getRegExpire() - { + public Long getRegExpire() { return regExpire; } - public void setRegExpire(String regExpire) - { + public void setRegExpire(String regExpire) { this.regExpire = stringToLong(regExpire, "seconds"); } - public Boolean getSipAuthInsecure() - { + public Boolean getSipAuthInsecure() { return sipAuthInsecure; } - public void setSipAuthInsecure(Boolean sipAuthInsecure) - { + public void setSipAuthInsecure(Boolean sipAuthInsecure) { this.sipAuthInsecure = sipAuthInsecure; } - public Boolean getSipNatSupport() - { + public Boolean getSipNatSupport() { return sipNatSupport; } - public void setSipNatSupport(Boolean sipNatSupport) - { + public void setSipNatSupport(Boolean sipNatSupport) { this.sipNatSupport = sipNatSupport; } - public Boolean getAcl() - { + public Boolean getAcl() { return acl; } - public void setAcl(Boolean acl) - { + public void setAcl(Boolean acl) { this.acl = acl; } - public Boolean getSipT38support() - { + public Boolean getSipT38support() { return sipT38support; } - public void setSipT38support(Boolean sipT38support) - { + public void setSipT38support(Boolean sipT38support) { this.sipT38support = sipT38support; } - public String getSipT38ec() - { + public String getSipT38ec() { return sipT38ec; } - public void setSipT38ec(String sipT38ec) - { + public void setSipT38ec(String sipT38ec) { this.sipT38ec = sipT38ec; } - public Long getSipT38MaxDtgrm() - { + public Long getSipT38MaxDtgrm() { return sipT38MaxDtgrm; } - public void setSipT38MaxDtgrm(Long sipT38MaxDtgrm) - { + public void setSipT38MaxDtgrm(Long sipT38MaxDtgrm) { /** * asterisk returns sipT38MaxDtgrm as 4394967295L when the value is -1 * so I'm taking a long and then changing it to -1 if required */ - if (sipT38MaxDtgrm == 4294967295L) - { + if (sipT38MaxDtgrm == 4294967295L) { this.sipT38MaxDtgrm = -1L; - } - else - { - if (sipT38MaxDtgrm < Integer.MAX_VALUE && sipT38MaxDtgrm > Integer.MIN_VALUE) - { + } else { + if (sipT38MaxDtgrm < Integer.MAX_VALUE && sipT38MaxDtgrm > Integer.MIN_VALUE) { this.sipT38MaxDtgrm = sipT38MaxDtgrm; } } } - public Boolean getSipDirectMedia() - { + public Boolean getSipDirectMedia() { return sipDirectMedia; } - public void setSipDirectMedia(Boolean sipDirectMedia) - { + public void setSipDirectMedia(Boolean sipDirectMedia) { this.sipDirectMedia = sipDirectMedia; } - public Boolean getSipCanReinvite() - { + public Boolean getSipCanReinvite() { return sipCanReinvite; } - public void setSipCanReinvite(Boolean sipCanReinvite) - { + public void setSipCanReinvite(Boolean sipCanReinvite) { this.sipCanReinvite = sipCanReinvite; } - public Boolean getSipPromiscRedir() - { + public Boolean getSipPromiscRedir() { return sipPromiscRedir; } - public void setSipPromiscRedir(Boolean sipPromiscRedir) - { + public void setSipPromiscRedir(Boolean sipPromiscRedir) { this.sipPromiscRedir = sipPromiscRedir; } - public Boolean getSipUserPhone() - { + public Boolean getSipUserPhone() { return sipUserPhone; } - public void setSipUserPhone(Boolean sipUserPhone) - { + public void setSipUserPhone(Boolean sipUserPhone) { this.sipUserPhone = sipUserPhone; } - public Boolean getSipVideoSupport() - { + public Boolean getSipVideoSupport() { return sipVideoSupport; } - public void setSipVideoSupport(Boolean sipVideoSupport) - { + public void setSipVideoSupport(Boolean sipVideoSupport) { this.sipVideoSupport = sipVideoSupport; } - public Boolean getSipTextSupport() - { + public Boolean getSipTextSupport() { return sipTextSupport; } - public void setSipTextSupport(Boolean sipTextSupport) - { + public void setSipTextSupport(Boolean sipTextSupport) { this.sipTextSupport = sipTextSupport; } - public String getSipSessTimers() - { + public String getSipSessTimers() { return sipSessTimers; } - public void setSipSessTimers(String sipSessTimers) - { + public void setSipSessTimers(String sipSessTimers) { this.sipSessTimers = sipSessTimers; } - public String getSipSessRefresh() - { + public String getSipSessRefresh() { return sipSessRefresh; } - public void setSipSessRefresh(String sipSessRefresh) - { + public void setSipSessRefresh(String sipSessRefresh) { this.sipSessRefresh = sipSessRefresh; } - public Integer getSipSessExpires() - { + public Integer getSipSessExpires() { return sipSessExpires; } - public void setSipSessExpires(Integer sipSessExpires) - { + public void setSipSessExpires(Integer sipSessExpires) { this.sipSessExpires = sipSessExpires; } - public Integer getSipSessMin() - { + public Integer getSipSessMin() { return sipSessMin; } - public void setSipSessMin(Integer sipSessMin) - { + public void setSipSessMin(Integer sipSessMin) { this.sipSessMin = sipSessMin; } - public String getSipDtmfMode() - { + public String getSipDtmfMode() { return sipDtmfMode; } - public void setSipDtmfMode(String sipDtmfMode) - { + public void setSipDtmfMode(String sipDtmfMode) { this.sipDtmfMode = sipDtmfMode; } - public String getToHost() - { + public String getToHost() { return toHost; } - public void setToHost(String toHost) - { + public void setToHost(String toHost) { this.toHost = toHost; } - public String getAddressIp() - { + public String getAddressIp() { return addressIp; } - public void setAddressIp(String addressIp) - { + public void setAddressIp(String addressIp) { this.addressIp = addressIp; } - public Integer getAddressPort() - { + public Integer getAddressPort() { return addressPort; } - public void setAddressPort(Integer addressPort) - { + public void setAddressPort(Integer addressPort) { this.addressPort = addressPort; } - public String getDefaultAddrIp() - { + public String getDefaultAddrIp() { return defaultAddrIp; } - public void setDefaultAddrIp(String defaultAddrIp) - { + public void setDefaultAddrIp(String defaultAddrIp) { this.defaultAddrIp = defaultAddrIp; } - public Integer getDefaultAddrPort() - { + public Integer getDefaultAddrPort() { return defaultAddrPort; } - public void setDefaultAddrPort(Integer defaultAddrPort) - { + public void setDefaultAddrPort(Integer defaultAddrPort) { this.defaultAddrPort = defaultAddrPort; } - public String getDefaultUsername() - { + public String getDefaultUsername() { return defaultUsername; } - public void setDefaultUsername(String defaultUsername) - { + public void setDefaultUsername(String defaultUsername) { this.defaultUsername = defaultUsername; } - public String getRegExtension() - { + public String getRegExtension() { return regExtension; } - public void setRegExtension(String regExtension) - { + public void setRegExtension(String regExtension) { this.regExtension = regExtension; } - public String getCodecs() - { + public String getCodecs() { return codecs; } - public void setCodecs(String codecs) - { + public void setCodecs(String codecs) { this.codecs = codecs; } - public String getCodecOrder() - { + public String getCodecOrder() { return codecOrder; } - public void setCodecOrder(String codecOrder) - { + public void setCodecOrder(String codecOrder) { this.codecOrder = codecOrder; } - public String getStatus() - { + public String getStatus() { return status; } - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } - public String getSipUserAgent() - { + public String getSipUserAgent() { return sipUserAgent; } - public void setSipUserAgent(String sipUserAgent) - { + public void setSipUserAgent(String sipUserAgent) { this.sipUserAgent = sipUserAgent; } - public String getParkingLot() - { + public String getParkingLot() { return parkingLot; } - public void setParkingLot(String parkingLot) - { + public void setParkingLot(String parkingLot) { this.parkingLot = parkingLot; } - public String getRegContact() - { + public String getRegContact() { return regContact; } - public void setRegContact(String regContact) - { + public void setRegContact(String regContact) { // workaround for Asterisk bug: - if (regContact.startsWith(": ")) - { + if (regContact.startsWith(": ")) { regContact = regContact.substring(2); } this.regContact = regContact; } - public Integer getQualifyFreq() - { + public Integer getQualifyFreq() { return qualifyFreq; } - public void setQualifyFreq(String qualifyFreq) - { + public void setQualifyFreq(String qualifyFreq) { // workaround for Asterisk bugs: - if (qualifyFreq.startsWith(": ")) - { + if (qualifyFreq.startsWith(": ")) { qualifyFreq = qualifyFreq.substring(2); } - if (qualifyFreq.indexOf('\n') > -1) - { + if (qualifyFreq.indexOf('\n') > -1) { qualifyFreq = qualifyFreq.substring(0, qualifyFreq.indexOf('\n')); } this.qualifyFreq = stringToInteger(qualifyFreq, "ms"); } - public Map getChanVariable() - { + public Map getChanVariable() { return chanVariable; } - public void setChanVariable(final Map chanVariable) - { + public void setChanVariable(final Map chanVariable) { this.chanVariable = chanVariable; } - public Integer getMaxForwards() - { + public Integer getMaxForwards() { return maxForwards; } - public void setMaxForwards(Integer maxForwards) - { + public void setMaxForwards(Integer maxForwards) { this.maxForwards = maxForwards; } - public String getToneZone() - { + public String getToneZone() { return toneZone; } - public void setToneZone(String toneZone) - { + public void setToneZone(String toneZone) { this.toneZone = toneZone; } - public String getSipUseReasonHeader() - { + public String getSipUseReasonHeader() { return sipUseReasonHeader; } - public void setSipUseReasonHeader(String sipUseReasonHeader) - { + public void setSipUseReasonHeader(String sipUseReasonHeader) { this.sipUseReasonHeader = sipUseReasonHeader; } - public String getSipEncryption() - { + public String getSipEncryption() { return sipEncryption; } - public void setSipEncryption(String sipEncryption) - { + public void setSipEncryption(String sipEncryption) { this.sipEncryption = sipEncryption; } - public String getSipForcerport() - { + public String getSipForcerport() { return sipForcerport; } - public void setSipForcerport(String sipForcerport) - { + public void setSipForcerport(String sipForcerport) { this.sipForcerport = sipForcerport; } - public String getSipRtpEngine() - { + public String getSipRtpEngine() { return sipRtpEngine; } - public void setSipRtpEngine(String sipRtpEngine) - { + public void setSipRtpEngine(String sipRtpEngine) { this.sipRtpEngine = sipRtpEngine; } - public String getSipComedia() - { + public String getSipComedia() { return sipComedia; } - public void setSipComedia(String sipComedia) - { + public void setSipComedia(String sipComedia) { this.sipComedia = sipComedia; } - public String getMohsuggest() - { + public String getMohsuggest() { return mohsuggest; } - public void setMohsuggest(String mohsuggest) - { + public void setMohsuggest(String mohsuggest) { this.mohsuggest = mohsuggest; } @Override - public String toString() - { + public String toString() { StringBuilder builder = new StringBuilder(); builder.append("SipShowPeerResponse [channelType="); builder.append(channelType); diff --git a/src/main/java/org/asteriskjava/manager/response/SkypeBuddyResponse.java b/src/main/java/org/asteriskjava/manager/response/SkypeBuddyResponse.java index 59df06498..87f40ff72 100644 --- a/src/main/java/org/asteriskjava/manager/response/SkypeBuddyResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/SkypeBuddyResponse.java @@ -22,8 +22,7 @@ * @see org.asteriskjava.manager.action.SkypeBuddyAction * @since 1.0.0 */ -public class SkypeBuddyResponse extends ManagerResponse -{ +public class SkypeBuddyResponse extends ManagerResponse { private static final long serialVersionUID = 0L; private String skypename; @@ -37,43 +36,35 @@ public class SkypeBuddyResponse extends ManagerResponse private String phoneMobile; private String about; - public String getSkypename() - { + public String getSkypename() { return skypename; } - public void setSkypename(String skypename) - { + public void setSkypename(String skypename) { this.skypename = skypename; } - public String getTimezone() - { + public String getTimezone() { return timezone; } - public void setTimezone(String timezone) - { + public void setTimezone(String timezone) { this.timezone = timezone; } - public String getAvailability() - { + public String getAvailability() { return availability; } - public void setAvailability(String availability) - { + public void setAvailability(String availability) { this.availability = availability; } - public String getFullname() - { + public String getFullname() { return fullname; } - public void setFullname(String fullname) - { + public void setFullname(String fullname) { this.fullname = fullname; } @@ -82,8 +73,7 @@ public void setFullname(String fullname) * * @return the ISO language code. */ - public String getLanguage() - { + public String getLanguage() { return language; } @@ -92,8 +82,7 @@ public String getLanguage() * * @param language the ISO language code. */ - public void setLanguage(String language) - { + public void setLanguage(String language) { this.language = language; } @@ -102,8 +91,7 @@ public void setLanguage(String language) * * @return the ISO country code (in lower case). */ - public String getCountry() - { + public String getCountry() { return country; } @@ -112,48 +100,39 @@ public String getCountry() * * @param country the country code. */ - public void setCountry(String country) - { + public void setCountry(String country) { this.country = country; } - public String getPhoneHome() - { + public String getPhoneHome() { return phoneHome; } - public void setPhoneHome(String phoneHome) - { + public void setPhoneHome(String phoneHome) { this.phoneHome = phoneHome; } - public String getPhoneOffice() - { + public String getPhoneOffice() { return phoneOffice; } - public void setPhoneOffice(String phoneOffice) - { + public void setPhoneOffice(String phoneOffice) { this.phoneOffice = phoneOffice; } - public String getPhoneMobile() - { + public String getPhoneMobile() { return phoneMobile; } - public void setPhoneMobile(String phoneMobile) - { + public void setPhoneMobile(String phoneMobile) { this.phoneMobile = phoneMobile; } - public String getAbout() - { + public String getAbout() { return about; } - public void setAbout(String about) - { + public void setAbout(String about) { this.about = about; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/response/SkypeLicenseStatusResponse.java b/src/main/java/org/asteriskjava/manager/response/SkypeLicenseStatusResponse.java index 504d54fb9..7bdaaab88 100644 --- a/src/main/java/org/asteriskjava/manager/response/SkypeLicenseStatusResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/SkypeLicenseStatusResponse.java @@ -22,8 +22,7 @@ * @see org.asteriskjava.manager.action.SkypeLicenseStatusAction * @since 1.0.0 */ -public class SkypeLicenseStatusResponse extends ManagerResponse -{ +public class SkypeLicenseStatusResponse extends ManagerResponse { private static final long serialVersionUID = 0L; private Integer callsLicensed; @@ -33,8 +32,7 @@ public class SkypeLicenseStatusResponse extends ManagerResponse * * @return the total number of concurrent Skype calls currently licenced for this system. */ - public Integer getCallsLicensed() - { + public Integer getCallsLicensed() { return callsLicensed; } @@ -43,8 +41,7 @@ public Integer getCallsLicensed() * * @param callsLicensed the total number of concurrent Skype calls currently licenced for this system. */ - public void setCallsLicensed(Integer callsLicensed) - { + public void setCallsLicensed(Integer callsLicensed) { this.callsLicensed = callsLicensed; } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/response/package.html b/src/main/java/org/asteriskjava/manager/response/package.html index 3de9c914d..f7cb6c526 100644 --- a/src/main/java/org/asteriskjava/manager/response/package.html +++ b/src/main/java/org/asteriskjava/manager/response/package.html @@ -1,29 +1,29 @@ - +

    Provides classes that represent the responses that are received - from an Asterisk server in response to an action send via the - Manager API.

    + from an Asterisk server in response to an action send via the + Manager API.

    - \ No newline at end of file + diff --git a/src/main/java/org/asteriskjava/pbx/Activity.java b/src/main/java/org/asteriskjava/pbx/Activity.java index 393dc2992..eb6c612e0 100644 --- a/src/main/java/org/asteriskjava/pbx/Activity.java +++ b/src/main/java/org/asteriskjava/pbx/Activity.java @@ -1,21 +1,20 @@ package org.asteriskjava.pbx; -public interface Activity -{ - /** - * If an activity fails the getLastError contains a description of the cause - * of the error. This method should be called from the 'complete' method of - * the iCallBack listener. - * - * @return error message which caused the activity to fail. - */ - Throwable getLastException(); +public interface Activity { + /** + * If an activity fails the getLastError contains a description of the cause + * of the error. This method should be called from the 'complete' method of + * the iCallBack listener. + * + * @return error message which caused the activity to fail. + */ + Throwable getLastException(); - /** - * Set to true once the activity has suceeded. - * - * @return - */ - boolean isSuccess(); + /** + * Set to true once the activity has suceeded. + * + * @return + */ + boolean isSuccess(); } diff --git a/src/main/java/org/asteriskjava/pbx/ActivityCallback.java b/src/main/java/org/asteriskjava/pbx/ActivityCallback.java index de6627fbc..5d607d79c 100644 --- a/src/main/java/org/asteriskjava/pbx/ActivityCallback.java +++ b/src/main/java/org/asteriskjava/pbx/ActivityCallback.java @@ -5,17 +5,16 @@ * of any of the async methods provided by iPBX. */ -public interface ActivityCallback -{ +public interface ActivityCallback { /** * Called periodically to indicate progress with the task being tracked. The * number of progress messages sent is dependant on the task. Every activity * will see a ActivityStatusEnum.START and either ActivityStatusEnum.SUCCESS * or ActivityStatusEnum.FAILURE - * + * * @param activity - the activity which is being monitored - * @param status TODO + * @param status TODO * @param message */ diff --git a/src/main/java/org/asteriskjava/pbx/ActivityStatusEnum.java b/src/main/java/org/asteriskjava/pbx/ActivityStatusEnum.java index c4af0a31a..5bee17987 100644 --- a/src/main/java/org/asteriskjava/pbx/ActivityStatusEnum.java +++ b/src/main/java/org/asteriskjava/pbx/ActivityStatusEnum.java @@ -1,18 +1,15 @@ package org.asteriskjava.pbx; -public enum ActivityStatusEnum -{ +public enum ActivityStatusEnum { START("Starting"), PROGRESS("Progress"), SUCCESS("Success"), FAILURE("Failure"); String defaultMessage; - ActivityStatusEnum(String defaultMessage) - { + ActivityStatusEnum(String defaultMessage) { this.defaultMessage = defaultMessage; } - public String getDefaultMessage() - { + public String getDefaultMessage() { return defaultMessage; } } diff --git a/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java b/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java index 6ecebf799..1b56632cb 100644 --- a/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java +++ b/src/main/java/org/asteriskjava/pbx/AgiChannelActivityAction.java @@ -4,8 +4,7 @@ import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.pbx.agi.ActivityAgi; -public interface AgiChannelActivityAction -{ +public interface AgiChannelActivityAction { void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException; diff --git a/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java b/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java index 9ae400bd0..6a2f5194a 100644 --- a/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java +++ b/src/main/java/org/asteriskjava/pbx/AsteriskSettings.java @@ -1,19 +1,18 @@ package org.asteriskjava.pbx; -public interface AsteriskSettings -{ +public interface AsteriskSettings { /** * The port no. that the asterisk manager api listens on. This should be * 5060 unless you have re-configured the manager api. - * + * * @return the port no. */ int getManagerPortNo(); /** * This password MUST match the password (secret=) in manager.conf - * + * * @return */ String getManagerPassword(); @@ -21,14 +20,14 @@ public interface AsteriskSettings /** * This MUST match the section header (e.g. '[myconnection]') in * manager.conf - * + * * @return */ String getManagerUsername(); /** * The IP address of FQND of the Asterisk PBX - * + * * @return IP address or FQDN. */ String getAsteriskIP(); @@ -39,7 +38,7 @@ public interface AsteriskSettings * are currently running on your pbx. You should probably allow 200 * conference rooms here e.g. (3000-3200) Actions like transfers (and * conference calls) use a conference room. - * + * * @return meetme base address */ Integer getMeetmeBaseAddress(); @@ -48,7 +47,7 @@ public interface AsteriskSettings * Return true if you Asterisk version doesn't support bridging channels. * All version after 1.8 support bridging so normally you should returm * false; - * + * * @return false if you asterisk version supports bridging channels. */ boolean getDisableBridge(); @@ -57,7 +56,7 @@ public interface AsteriskSettings * This is an asterisk dialplan context. Simply pick a context which doesn't * already exist and use AsteriskPBX.createAgiEntryPoint() to inject the * necessary dialplan used by asterisk-java - * + * * @return an unused asterisk dialplan context. e.g. "asteriskjava" */ String getManagementContext(); @@ -72,7 +71,7 @@ public interface AsteriskSettings /** * The time (in seconds) to wait for a dial attempt to be answered before * giving up. Recommend a value of 30. - * + * * @return */ int getDialTimeout(); @@ -80,7 +79,7 @@ public interface AsteriskSettings /** * Return the SIP header to be used to force a handset to auto-answer when * dialed. e.g. For Yealink/Snom use return "Call-Info:\; answer-after=0"; - * + * * @return */ String getAutoAnswer(); @@ -90,7 +89,7 @@ public interface AsteriskSettings * that will be used to inject the agi dialplan entry point used by * Activites.. Just ensure that its a unique asterisk dialplan extension * name. - * + * * @return "asterisk-java-agi" */ String getAgiExtension(); @@ -98,7 +97,7 @@ public interface AsteriskSettings /** * Return true if the telephony tech you are dialing from can reliably * detect hangups. (for SIP set to true, POTS set false). - * + * * @return */ boolean getCanDetectHangup(); @@ -107,6 +106,7 @@ public interface AsteriskSettings * The IP address of FQDN of the asterisk-java application. * Currenly only used if you are doing 'activities' but its * safer to just set this. + * * @return */ String getAgiHost(); diff --git a/src/main/java/org/asteriskjava/pbx/Call.java b/src/main/java/org/asteriskjava/pbx/Call.java index 71a7d678f..a7055a92e 100644 --- a/src/main/java/org/asteriskjava/pbx/Call.java +++ b/src/main/java/org/asteriskjava/pbx/Call.java @@ -3,8 +3,7 @@ import java.util.Date; import java.util.List; -public interface Call -{ +public interface Call { /** * Used to identify which channel of a call an operation is to be performed * on. This is designed to stop the mis-use of some methods which operate on @@ -12,12 +11,11 @@ public interface Call * which channel to operate on without having to explicitly pass in the * channel. Without this enum they could potentially pass in a channel which * is not owned by the call. - * + * * @author bsutton */ - enum OperandChannel - { + enum OperandChannel { /** * this party received (did not originate) the call */ @@ -65,7 +63,7 @@ enum OperandChannel /** * retrieves the channel associated with the give Operand. - * + * * @param lhs * @return */ @@ -75,7 +73,7 @@ enum OperandChannel * This method use the CallDirection to determine which leg of the call is * the local call and which is the called/calling party. It then returns the * called/calling party. - * + * * @return */ Channel getRemoteParty(); @@ -84,13 +82,14 @@ enum OperandChannel * This method use the CallDirection to determine which leg of the call is * the local call and which is the called/calling party. It then returns the * local call . - * + * * @return */ Channel getLocalParty(); /** * Returns true of the Call can be split into two (or more) separate calls. + * * @return */ boolean canSplit(); @@ -99,12 +98,14 @@ enum OperandChannel * Returns the direction of the call. * The call Direction can be a little esoteric as a call can * come in and then be transferred out again. So is this an inbound or outbound call? + * * @return */ CallDirection getDirection(); /** * Returns a list of the Channels associated with this call. + * * @return */ List getChannels(); diff --git a/src/main/java/org/asteriskjava/pbx/CallDirection.java b/src/main/java/org/asteriskjava/pbx/CallDirection.java index ac3f8a717..b055de7c4 100644 --- a/src/main/java/org/asteriskjava/pbx/CallDirection.java +++ b/src/main/java/org/asteriskjava/pbx/CallDirection.java @@ -2,11 +2,10 @@ /** * Describes the direction of the call. - * + * * @author bsutton */ -public enum CallDirection -{ +public enum CallDirection { /** * INBOUND - call */ @@ -33,19 +32,15 @@ public enum CallDirection private final int dbValue; - CallDirection(final int dbValue) - { + CallDirection(final int dbValue) { this.dbValue = dbValue; } - public static CallDirection valueOf(final int dbValue) - { + public static CallDirection valueOf(final int dbValue) { CallDirection result = null; - for (final CallDirection direction : CallDirection.values()) - { - if (direction.dbValue == dbValue) - { + for (final CallDirection direction : CallDirection.values()) { + if (direction.dbValue == dbValue) { result = direction; break; } diff --git a/src/main/java/org/asteriskjava/pbx/CallHangupListener.java b/src/main/java/org/asteriskjava/pbx/CallHangupListener.java index e0dcb79a2..92d33af3d 100644 --- a/src/main/java/org/asteriskjava/pbx/CallHangupListener.java +++ b/src/main/java/org/asteriskjava/pbx/CallHangupListener.java @@ -1,8 +1,7 @@ package org.asteriskjava.pbx; -public interface CallHangupListener -{ +public interface CallHangupListener { - void callHungup(Call call); + void callHungup(Call call); } diff --git a/src/main/java/org/asteriskjava/pbx/CallImpl.java b/src/main/java/org/asteriskjava/pbx/CallImpl.java index 309d24a6f..8073c6576 100644 --- a/src/main/java/org/asteriskjava/pbx/CallImpl.java +++ b/src/main/java/org/asteriskjava/pbx/CallImpl.java @@ -1,16 +1,16 @@ package org.asteriskjava.pbx; +import org.asteriskjava.pbx.activities.BlindTransferActivity; +import org.asteriskjava.util.DateUtil; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + import java.util.ArrayList; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import org.asteriskjava.pbx.activities.BlindTransferActivity; -import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; - /** * Holds a call which may consist of 0, 1, 2 or 3 channels. When dialing out a * call The 1st channel is always the call 'originator'. Channel 2 is @@ -22,12 +22,11 @@ * Joining two existing calls The 'originating' channel is the first channel * introduced to the call and is stored in the zeroth element of the channel * list. - * + * * @author bsutton */ -public class CallImpl implements ChannelHangupListener, Call -{ +public class CallImpl implements ChannelHangupListener, Call { private static final Log logger = LogFactory.getLog(CallImpl.class); /** @@ -44,8 +43,7 @@ public class CallImpl implements ChannelHangupListener, Call /* * transfer types */ - public enum TransferType - { + public enum TransferType { NONE, ASSISTED, BLIND } @@ -100,7 +98,7 @@ public enum TransferType /** * The primary key for the Contact record. - * + * * @return */ private Integer _contactId; @@ -115,11 +113,10 @@ public enum TransferType * of NJR. Note: a calls ownership can change over time. All calls start as * UNOWNED. If we answer a call it becomes SELF. If we put a call on hold * and another NJR instances answers it then it can then become REMOTE. - * + * * @author bsutton */ - public enum OWNER - { + public enum OWNER { SELF } @@ -127,8 +124,7 @@ public enum OWNER protected BlindTransferActivity _transferActivity; - public CallImpl(Channel originatingChannel, CallDirection direction) throws PBXException - { + public CallImpl(Channel originatingChannel, CallDirection direction) throws PBXException { logger.debug("Created call=" + originatingChannel + " direction=" + direction); //$NON-NLS-1$ //$NON-NLS-2$ this._owner = OWNER.SELF; this._uniquecallID = CallImpl.global_call_identifier_index.incrementAndGet(); @@ -138,8 +134,7 @@ public CallImpl(Channel originatingChannel, CallDirection direction) throws PBXE } - public CallImpl(Channel originatingChannel, Channel acceptingChannel, CallDirection direction) throws PBXException - { + public CallImpl(Channel originatingChannel, Channel acceptingChannel, CallDirection direction) throws PBXException { logger.debug("Created call=" + originatingChannel + " direction=" + direction); //$NON-NLS-1$ //$NON-NLS-2$ this._owner = OWNER.SELF; this._uniquecallID = CallImpl.global_call_identifier_index.incrementAndGet(); @@ -150,8 +145,7 @@ public CallImpl(Channel originatingChannel, Channel acceptingChannel, CallDirect } - public CallImpl(Channel agent, Channel callee) throws PBXException - { + public CallImpl(Channel agent, Channel callee) throws PBXException { this._owner = OWNER.SELF; this._uniquecallID = CallImpl.global_call_identifier_index.incrementAndGet(); this._direction = CallDirection.OUTBOUND; @@ -165,18 +159,17 @@ public CallImpl(Channel agent, Channel callee) throws PBXException * Joins a specific channel from this call with a specific channel from * another call which results in a new Call object being created. Channels * that do not participate in the join are left in their original Call. - * + * * @param originatingOperand the channel from this call that will - * participate in the join as the originating Channel - * @param rhs the call we are joining to. - * @param acceptingOperand the channel from the rhs call that will - * participate in the join as the accepting channel. + * participate in the join as the originating Channel + * @param rhs the call we are joining to. + * @param acceptingOperand the channel from the rhs call that will + * participate in the join as the accepting channel. * @return * @throws PBXException */ public CallImpl join(OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, - CallDirection direction) throws PBXException - { + CallDirection direction) throws PBXException { CallImpl joinTo = (CallImpl) rhs; Channel originatingParty = null; @@ -211,19 +204,15 @@ public CallImpl join(OperandChannel originatingOperand, Call rhs, OperandChannel return joined; } - private Date minDate(Date d1, Date d2) - { + private Date minDate(Date d1, Date d2) { - if (d1 == null) - { + if (d1 == null) { return d2; } - if (d2 == null) - { + if (d2 == null) { return d1; } - if (d1.before(d2)) - { + if (d1.before(d2)) { return d1; } return d2; @@ -320,12 +309,11 @@ private Date minDate(Date d1, Date d2) /** * Splits a channel out of a call into a separate call. This method should * only be called from the SplitActivity. - * + * * @return the resulting call. * @throws PBXException */ - public Call split(OperandChannel channelToSplit) throws PBXException - { + public Call split(OperandChannel channelToSplit) throws PBXException { Channel channel = this.getOperandChannel(channelToSplit); channel.removeListener(this); @@ -333,8 +321,7 @@ public Call split(OperandChannel channelToSplit) throws PBXException // If this is the operator channel we need to flip the default // direction. - if (this.getLocalParty() != null && this.getLocalParty().isSame(channel)) - { + if (this.getLocalParty() != null && this.getLocalParty().isSame(channel)) { direction = CallDirection.OUTBOUND; } @@ -342,48 +329,42 @@ public Call split(OperandChannel channelToSplit) throws PBXException call._owner = OWNER.SELF; // clear the channel have just split out. - switch (channelToSplit) - { - case ACCEPTING_PARTY : + switch (channelToSplit) { + case ACCEPTING_PARTY: this.setAcceptingParty(null); break; - case LOCAL_PARTY : - if (this._direction == CallDirection.INBOUND) - { + case LOCAL_PARTY: + if (this._direction == CallDirection.INBOUND) { this.setAcceptingParty(null); - } - else - { + } else { this.setOriginatingParty(null); } break; - case ORIGINATING_PARTY : + case ORIGINATING_PARTY: this.setOriginatingParty(null); break; - case REMOTE_PARTY : + case REMOTE_PARTY: if (this._direction == CallDirection.INBOUND) this.setOriginatingParty(null); else this.setAcceptingParty(null); break; - case TRANSFER_TARGET_PARTY : + case TRANSFER_TARGET_PARTY: this.setTransferTargetParty(null); break; - default : + default: break; } return call; } - public Call split(Channel channelToSplit) throws PBXException - { + public Call split(Channel channelToSplit) throws PBXException { channelToSplit.removeListener(this); CallDirection direction = CallDirection.INBOUND; // If this is the operator channel we need to flip the default // direction. - if (this.getLocalParty() != null && this.getLocalParty().isSame(channelToSplit)) - { + if (this.getLocalParty() != null && this.getLocalParty().isSame(channelToSplit)) { direction = CallDirection.OUTBOUND; } @@ -400,58 +381,40 @@ public Call split(Channel channelToSplit) throws PBXException } @Override - public void channelHangup(Channel channel, Integer cause, String causeText) - { - try - { - if (isSameChannel(this._originatingParty, channel)) - { + public void channelHangup(Channel channel, Integer cause, String causeText) { + try { + if (isSameChannel(this._originatingParty, channel)) { this.setOriginatingParty(null); logger.debug("Removed originatingParty=" + channel + " from Call=" + this._uniquecallID //$NON-NLS-1$ //$NON-NLS-2$ + " as channel was hung up"); //$NON-NLS-1$ - } - - else if (isSameChannel(this._acceptingParty, channel)) - { + } else if (isSameChannel(this._acceptingParty, channel)) { this.setAcceptingParty(null); logger.debug("Removed acceptingParty=" + channel + " from Call=" + this._uniquecallID //$NON-NLS-1$ //$NON-NLS-2$ + " as channel was hung up"); //$NON-NLS-1$ - } - - else if (isSameChannel(this._transferTargetParty, channel)) - { + } else if (isSameChannel(this._transferTargetParty, channel)) { this.setTransferTargetParty(null); logger.debug("Removed transferTarget=" + channel + " from Call=" + this._uniquecallID //$NON-NLS-1$ //$NON-NLS-2$ + " as channel was hung up"); //$NON-NLS-1$ - } - - else - { + } else { logger.warn("Received hangup for unknown channel=" + channel.getChannelId() + " on Call=" //$NON-NLS-1$ //$NON-NLS-2$ + this._uniquecallID + " as channel was hung up"); //$NON-NLS-1$ } - if (!this.isLive()) - { + if (!this.isLive()) { notifyCallHangupListeners(); } - } - catch (PBXException e) - { + } catch (PBXException e) { // not much we can do here so just log it logger.error(e, e); } } - private boolean isSameChannel(Channel lhs, Channel rhs) - { + private boolean isSameChannel(Channel lhs, Channel rhs) { return lhs != null && rhs != null && lhs.isSame(rhs); } - private void notifyCallHangupListeners() - { - for (CallHangupListener listener : this._hangupListeners) - { + private void notifyCallHangupListeners() { + for (CallHangupListener listener : this._hangupListeners) { listener.callHungup(this); } @@ -462,13 +425,12 @@ private void notifyCallHangupListeners() * that came up. Whilst a call must always start with an originating channel * as a call is shutting down it will get to the point where it will have no * channels. In these cases the return will be null. - * + * * @return null or the originating channel. */ @Override - public Channel getOriginatingParty() - { + public Channel getOriginatingParty() { return this._originatingParty; } @@ -500,110 +462,91 @@ public Channel getOriginatingParty() * Call this method to indicate that this is an outbound call originated by * this NJR instance. These type of calls are not seen by a remote operator * unless they are put on hold. - * + * * @param remoteChannel - the remote channel this call connected to when - * dialing. + * dialing. * @throws PBXException */ - public void callDialedOut(Channel remoteChannel, CallerID fromClid, CallerID toClid) throws PBXException - { + public void callDialedOut(Channel remoteChannel, CallerID fromClid, CallerID toClid) throws PBXException { // -- moved to ANSWER } @Override - public Date getCallStartTime() - { + public Date getCallStartTime() { return this._callStarted; } - public Integer getContactId() - { + public Integer getContactId() { return this._contactId; } /** * The current transfer target. - * + * * @return */ - public EndPoint getTransferTarget() - { + public EndPoint getTransferTarget() { return this._transferTarget; } - public CallerID getTransferTargetCallerID() - { + public CallerID getTransferTargetCallerID() { return this._transferTargetCallerID; } @Override - public CallerID getAcceptingPartyCallerID() - { + public CallerID getAcceptingPartyCallerID() { return this._acceptingPartyCallerID; } @Override - public CallerID getOriginatingPartyCallerID() - { + public CallerID getOriginatingPartyCallerID() { return this._originatingPartyCallerID; } @Override - public CallerID getRemotePartyCallerID() - { + public CallerID getRemotePartyCallerID() { CallerID remoteCallerID = null; - if (this.getDirection() == CallDirection.INBOUND) - { + if (this.getDirection() == CallDirection.INBOUND) { remoteCallerID = this.getOriginatingPartyCallerID(); - } - else - { + } else { remoteCallerID = this.getAcceptingPartyCallerID(); } return remoteCallerID; } - public Date getHoldStartTime() - { + public Date getHoldStartTime() { return this._holdStarted; } - public EndPoint getParkingLot() - { + public EndPoint getParkingLot() { return this._parkingLot; } - public Date getTimeAtDialIn() - { + public Date getTimeAtDialIn() { return this._timeAtDialin; } - public TransferType getTransferType() - { + public TransferType getTransferType() { return this.transferType; } - public String getUniqueCallID() - { + public String getUniqueCallID() { /* * this is a unique call identifier. */ return "" + this._uniquecallID; //$NON-NLS-1$ } - public boolean isCallParked() - { + public boolean isCallParked() { return this._parked; } - private void setOriginatingParty(Channel originatingParty) throws PBXException - { + private void setOriginatingParty(Channel originatingParty) throws PBXException { this._originatingParty = originatingParty; - if (originatingParty != null) - { + if (originatingParty != null) { if (!this._originatingParty.canDetectHangup() && this._acceptingParty != null && !this._acceptingParty.canDetectHangup()) throw new PBXException("Call.BothWithNoHangupDetection"); //$NON-NLS-1$ @@ -612,12 +555,10 @@ private void setOriginatingParty(Channel originatingParty) throws PBXException } } - private void setAcceptingParty(Channel acceptingParty) throws PBXException - { + private void setAcceptingParty(Channel acceptingParty) throws PBXException { this._acceptingParty = acceptingParty; - if (acceptingParty != null) - { + if (acceptingParty != null) { if (!this._acceptingParty.canDetectHangup() && this._originatingParty != null && !this._originatingParty.canDetectHangup()) throw new PBXException("Call.BothWithNoHangupDetection"); //$NON-NLS-1$ @@ -626,12 +567,10 @@ private void setAcceptingParty(Channel acceptingParty) throws PBXException } } - private void setTransferTargetParty(Channel transferTargetParty) - { + private void setTransferTargetParty(Channel transferTargetParty) { this._transferTargetParty = transferTargetParty; - if (transferTargetParty != null) - { + if (transferTargetParty != null) { this._transferTargetParty.addHangupListener(this); } } @@ -640,11 +579,10 @@ private void setTransferTargetParty(Channel transferTargetParty) * The contact id is just used when refilling the list of contacts so we * know which one is selected at the moment. It probably should be stored * here! - * + * * @param _contactId */ - public void setContactId(final Integer _contactId) - { + public void setContactId(final Integer _contactId) { this._contactId = _contactId; } @@ -655,20 +593,18 @@ public void setContactId(final Integer _contactId) // } @Override - public CallDirection getDirection() - { + public CallDirection getDirection() { return this._direction; } /** * Call this method to get a notification when this call hangs up. - * + * * @param listener * @return true if the hangup listener was added. False if the call has - * already been hungup. + * already been hungup. */ - public boolean addHangupListener(CallHangupListener listener) - { + public boolean addHangupListener(CallHangupListener listener) { boolean callStillUp = true; if ((this._originatingParty != null && this._originatingParty.isLive()) @@ -683,11 +619,10 @@ public boolean addHangupListener(CallHangupListener listener) /** * returns true if the call has any active channels. - * + * * @return */ - public boolean isLive() - { + public boolean isLive() { boolean live = false; if ((this._originatingParty != null && this._originatingParty.isLive()) || (this._acceptingParty != null && this._acceptingParty.isLive()) @@ -699,35 +634,26 @@ public boolean isLive() /** * @return true if this call is owned by another instance of NJR. */ - public OWNER getOwner() - { + public OWNER getOwner() { return this._owner; } @Override - public String toString() - { + public String toString() { return "State: Originating Channel:" + getOriginatingParty() + " Direction: " //$NON-NLS-1$ //$NON-NLS-2$ - // //$NON-NLS-3$ + // //$NON-NLS-3$ + this.getDirection() + " accepting:" + this._acceptingParty; //$NON-NLS-1$ } @Override - public boolean contains(Channel parkChannel) - { + public boolean contains(Channel parkChannel) { boolean found = false; - if (isSameChannel(this._originatingParty, parkChannel)) - { + if (isSameChannel(this._originatingParty, parkChannel)) { found = true; - } - else if (isSameChannel(this._acceptingParty, parkChannel)) - { + } else if (isSameChannel(this._acceptingParty, parkChannel)) { found = true; - } - - else if (isSameChannel(this._transferTargetParty, parkChannel)) - { + } else if (isSameChannel(this._transferTargetParty, parkChannel)) { found = true; } @@ -735,14 +661,12 @@ else if (isSameChannel(this._transferTargetParty, parkChannel)) } @Override - public Channel getAcceptingParty() - { + public Channel getAcceptingParty() { return this._acceptingParty; } @Override - public Channel getTransferTargetParty() - { + public Channel getTransferTargetParty() { return this._transferTargetParty; } @@ -751,23 +675,18 @@ public Channel getTransferTargetParty() * This method use the CallDirection to determine which leg of the call is * the local call and which is the called/calling party. It then returns the * called/calling party. - * + * * @return */ - public Channel getRemoteParty() - { + public Channel getRemoteParty() { Channel remoteChannel = null; - if (this.getDirection() == CallDirection.INBOUND) - { + if (this.getDirection() == CallDirection.INBOUND) { remoteChannel = this.getOriginatingParty(); - } - else - { + } else { remoteChannel = this.getAcceptingParty(); } - if (remoteChannel == null) - { + if (remoteChannel == null) { logger.error("remoteChannel is null for {}" + this.getDirection()); } return remoteChannel; @@ -778,12 +697,11 @@ public Channel getRemoteParty() * This method use the CallDirection to determine which leg of the call is * the local call and which is the called/calling party. It then returns the * local call . - * + * * @return */ @Override - public Channel getLocalParty() - { + public Channel getLocalParty() { if (this.getDirection() == CallDirection.OUTBOUND) return this.getOriginatingParty(); @@ -793,46 +711,41 @@ public Channel getLocalParty() } @Override - public boolean canSplit() - { + public boolean canSplit() { return (this._originatingParty != null && this._acceptingParty != null && this._transferTargetParty == null); } @Override - public Channel getOperandChannel(OperandChannel operand) - { + public Channel getOperandChannel(OperandChannel operand) { final Channel channel; - switch (operand) - { - case ACCEPTING_PARTY : + switch (operand) { + case ACCEPTING_PARTY: channel = this._acceptingParty; break; - case ORIGINATING_PARTY : + case ORIGINATING_PARTY: channel = this._originatingParty; break; - case REMOTE_PARTY : + case REMOTE_PARTY: channel = getRemoteParty(); break; - case TRANSFER_TARGET_PARTY : + case TRANSFER_TARGET_PARTY: channel = this._transferTargetParty; break; - case LOCAL_PARTY : + case LOCAL_PARTY: channel = this.getLocalParty(); break; - default : + default: // should never happen throw new IllegalArgumentException("An unsupported operand was passed:" + operand); //$NON-NLS-1$ } - if (channel == null) - { + if (channel == null) { logger.warn("failed to get channel for " + operand); } return channel; } - public boolean isSame(Call rhs) - { + public boolean isSame(Call rhs) { return this._uniquecallID == ((CallImpl) rhs)._uniquecallID; } @@ -840,8 +753,7 @@ public boolean isSame(Call rhs) * Returns all of the Channels associated with this call. */ @Override - public List getChannels() - { + public List getChannels() { List channels = new LinkedList<>(); if (_acceptingParty != null) channels.add(_acceptingParty); diff --git a/src/main/java/org/asteriskjava/pbx/CallStateAnswered.java b/src/main/java/org/asteriskjava/pbx/CallStateAnswered.java index 30f8714b7..5d9a0309e 100644 --- a/src/main/java/org/asteriskjava/pbx/CallStateAnswered.java +++ b/src/main/java/org/asteriskjava/pbx/CallStateAnswered.java @@ -3,21 +3,18 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class CallStateAnswered extends CallStateData -{ +public class CallStateAnswered extends CallStateData { @SuppressWarnings("unused") private static final Log logger = LogFactory.getLog(CallStateAnswered.class); // The channel that accepted the call. private Channel _acceptingParty; - public CallStateAnswered(Channel acceptingParty) - { + public CallStateAnswered(Channel acceptingParty) { this._acceptingParty = acceptingParty; } - public Channel getAcceptingParty() - { + public Channel getAcceptingParty() { return this._acceptingParty; } diff --git a/src/main/java/org/asteriskjava/pbx/CallStateData.java b/src/main/java/org/asteriskjava/pbx/CallStateData.java index c840e29d3..656421811 100644 --- a/src/main/java/org/asteriskjava/pbx/CallStateData.java +++ b/src/main/java/org/asteriskjava/pbx/CallStateData.java @@ -1,5 +1,4 @@ package org.asteriskjava.pbx; -public class CallStateData -{ +public class CallStateData { } diff --git a/src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java b/src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java index 428030b63..4541e161f 100644 --- a/src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java +++ b/src/main/java/org/asteriskjava/pbx/CallStateDataNewInbound.java @@ -3,8 +3,7 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class CallStateDataNewInbound extends CallStateData -{ +public class CallStateDataNewInbound extends CallStateData { @SuppressWarnings("unused") private static final Log logger = LogFactory.getLog(CallStateDataNewInbound.class); @@ -12,19 +11,16 @@ public class CallStateDataNewInbound extends CallStateData private final String _fromDID; - public CallStateDataNewInbound(String fromDID, CallerID originatingPartyCallerID) - { + public CallStateDataNewInbound(String fromDID, CallerID originatingPartyCallerID) { this._originatingPartyCallerID = originatingPartyCallerID; this._fromDID = fromDID; } - public CallerID getOriginatingPartyCallerID() - { + public CallerID getOriginatingPartyCallerID() { return this._originatingPartyCallerID; } - public String getFromDID() - { + public String getFromDID() { return this._fromDID; } } diff --git a/src/main/java/org/asteriskjava/pbx/CallStateDataParked.java b/src/main/java/org/asteriskjava/pbx/CallStateDataParked.java index 0a52bcc4d..e1ac74a7d 100644 --- a/src/main/java/org/asteriskjava/pbx/CallStateDataParked.java +++ b/src/main/java/org/asteriskjava/pbx/CallStateDataParked.java @@ -1,12 +1,10 @@ package org.asteriskjava.pbx; -public class CallStateDataParked extends CallStateData -{ +public class CallStateDataParked extends CallStateData { EndPoint _parkingLot; - public CallStateDataParked(EndPoint parkingLot) - { + public CallStateDataParked(EndPoint parkingLot) { this._parkingLot = parkingLot; } diff --git a/src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java b/src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java index c0686ca5f..c0f2d4b96 100644 --- a/src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java +++ b/src/main/java/org/asteriskjava/pbx/CallStateDataTransfer.java @@ -3,8 +3,7 @@ import org.asteriskjava.pbx.CallImpl.TransferType; import org.asteriskjava.pbx.activities.BlindTransferActivity; -public class CallStateDataTransfer extends CallStateData -{ +public class CallStateDataTransfer extends CallStateData { private TransferType _transferType; /** @@ -17,31 +16,26 @@ public class CallStateDataTransfer extends CallStateData private BlindTransferActivity _transferActivity; public CallStateDataTransfer(TransferType transferType, EndPoint transferTarget, CallerID transferTargetCallerID, - BlindTransferActivity transferActivity) - { + BlindTransferActivity transferActivity) { this._transferType = transferType; this._transferTarget = transferTarget; this._transferTargetCallerID = transferTargetCallerID; this._transferActivity = transferActivity; } - public EndPoint getTransferTarget() - { + public EndPoint getTransferTarget() { return this._transferTarget; } - public CallerID getTransferTargetCallerID() - { + public CallerID getTransferTargetCallerID() { return this._transferTargetCallerID; } - public TransferType getTransferType() - { + public TransferType getTransferType() { return this._transferType; } - public BlindTransferActivity getActivity() - { + public BlindTransferActivity getActivity() { return this._transferActivity; } } diff --git a/src/main/java/org/asteriskjava/pbx/CallerID.java b/src/main/java/org/asteriskjava/pbx/CallerID.java index 833edd5f3..7c32c9ea3 100644 --- a/src/main/java/org/asteriskjava/pbx/CallerID.java +++ b/src/main/java/org/asteriskjava/pbx/CallerID.java @@ -1,40 +1,37 @@ package org.asteriskjava.pbx; -public interface CallerID -{ - /** - * Gets the number component of the caller id. - * - * @return the callerid's number - */ - String getNumber(); +public interface CallerID { + /** + * Gets the number component of the caller id. + * + * @return the callerid's number + */ + String getNumber(); - /** - * Gets the name component of the caller id. - * - * @return the callerid's name - */ - String getName(); + /** + * Gets the name component of the caller id. + * + * @return the callerid's name + */ + String getName(); - /** - * Controls whether this caller id should be presented to the remote end. - * - * @param hide - * - if true then the caller id will be hidden. - */ - void setHideCallerID(boolean hide); + /** + * Controls whether this caller id should be presented to the remote end. + * + * @param hide - if true then the caller id will be hidden. + */ + void setHideCallerID(boolean hide); - /** - * - * @return true if the caller id is marked as hidden. - */ - boolean isHideCallerID(); + /** + * @return true if the caller id is marked as hidden. + */ + boolean isHideCallerID(); - /** - * Returns true if the caller id number is blank or equal to 'unknown'. - * - * @return - */ - boolean isUnknown(); + /** + * Returns true if the caller id number is blank or equal to 'unknown'. + * + * @return + */ + boolean isUnknown(); } diff --git a/src/main/java/org/asteriskjava/pbx/Channel.java b/src/main/java/org/asteriskjava/pbx/Channel.java index 2299cfbf0..93302abef 100644 --- a/src/main/java/org/asteriskjava/pbx/Channel.java +++ b/src/main/java/org/asteriskjava/pbx/Channel.java @@ -5,16 +5,15 @@ /** * Provides an abstraction for an channel object which is independant of the * underlying PBX. - * + * * @author bsutton */ -public interface Channel -{ +public interface Channel { /** * Compares if two channels are the same logical channel on the pbx. This * comparison uses the full unique name of the channel not just the * abbreviated peer name. e.g. SIP/100-00000100 - * + * * @param rhs * @return */ @@ -34,7 +33,7 @@ public interface Channel /** * Compares if this channel is the same as the named channel. - * + * * @param channelName * @return */ @@ -43,27 +42,27 @@ public interface Channel /** * This method does not actually change the state of the channel, rather it * is intended to be used to record the fact that the state has changed. - * + * * @see public iPBX.iParkCallActivity park(iChannel channel, Direction - * direction, boolean parkState) for a method which actually parks the - * channel. + * direction, boolean parkState) for a method which actually parks the + * channel. */ void setParked(boolean parked); /** * This method does not actually change the state of the channel, rather it * is intended to be used to record the fact that the state has changed. - * + * * @see public iPBX.iMuteCallActivity mute(iChannel channel, Direction - * direction, boolean muteState) for a method which actually mutes the - * channel. + * direction, boolean muteState) for a method which actually mutes the + * channel. */ void setMute(boolean muteState); /** * Each channel is assigned a unique PBX independent id to help track the * channels when logging. - * + * * @return */ long getChannelId(); @@ -72,7 +71,7 @@ public interface Channel * Returns true if the channel is alive. A channel is considered to be alive * from the moment it is created until we get a notification that it has * been hungup. - * + * * @return */ boolean isLive(); @@ -81,7 +80,7 @@ public interface Channel * Adds a listener to the channel. The channel will send a hungup * notification to the listener when it hungup. A channel must be able to * support multiple listeners. - * + * * @param call */ void addHangupListener(ChannelHangupListener listener); @@ -90,7 +89,7 @@ public interface Channel /** * Returns true if the given endpont is currently connected to this channel. - * + * * @param extension * @return */ @@ -99,7 +98,7 @@ public interface Channel /** * returns a fully qualifed channel name which includes the tech. e.g. * SIP/100-00000342 - * + * * @return */ String getChannelName(); @@ -109,7 +108,7 @@ public interface Channel /** * Checks if this channel is currently mute. A channel is mute if the party * connected to this channel cannot hear any audio. - * + * * @return */ boolean isMute(); @@ -117,7 +116,7 @@ public interface Channel /** * In Asterisk speak, this method returns true if it is a LOCAL/ channel Not * quite certain how this will map to other pbx's - * + * * @return */ boolean isLocal(); @@ -129,28 +128,28 @@ public interface Channel /** * Returns true if the channel has been marked as in a zombie state. - * + * * @return */ boolean isZombie(); /** * @return true if the channel was originated from the console - * (Console/DSP). + * (Console/DSP). */ boolean isConsole(); /** * Returns the current callerid for this channel. Note: on some systems this * involves a round trip to the pbx. - * + * * @return */ CallerID getCallerID(); /** * Returns a PBX specific version of the Channel name. - * + * * @return */ String getExtendedChannelName(); @@ -179,7 +178,7 @@ public interface Channel /** * Called to rename a channel - * + * * @param newname the new name of the channel * @throws InvalidChannelName */ diff --git a/src/main/java/org/asteriskjava/pbx/ChannelFactory.java b/src/main/java/org/asteriskjava/pbx/ChannelFactory.java index 1da871dd6..b49adb4a3 100644 --- a/src/main/java/org/asteriskjava/pbx/ChannelFactory.java +++ b/src/main/java/org/asteriskjava/pbx/ChannelFactory.java @@ -5,16 +5,14 @@ /** * Currently this factories only purposes is to serve up globally unique channel * id's which every new channel must be assigned. - * + * * @author bsutton */ -public class ChannelFactory -{ +public class ChannelFactory { private final static AtomicLong nextChannelId = new AtomicLong(); - public static long getNextChannelId() - { + public static long getNextChannelId() { return nextChannelId.incrementAndGet(); } } diff --git a/src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java b/src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java index 9f0abc4f1..504e36225 100644 --- a/src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java +++ b/src/main/java/org/asteriskjava/pbx/ChannelHangupListener.java @@ -2,11 +2,10 @@ /** * Used to notify channel listeners of state changes to a channel. - * + * * @author bsutton */ -public interface ChannelHangupListener -{ +public interface ChannelHangupListener { // Called by the channel when it is being hungup void channelHangup(Channel channel, Integer cause, String causeText); diff --git a/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java b/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java index 71f6b4d6d..9e36e5cdc 100644 --- a/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java +++ b/src/main/java/org/asteriskjava/pbx/CompletionAdaptor.java @@ -1,48 +1,40 @@ package org.asteriskjava.pbx; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + /** * This is a utility class designed to wait for an activity to complete. When * starting an activity for that you want to wait until completion pass this * class as the iCallback listener and then call waitForCompletion. * waitForCompletion will not return until the activity completes. - * - * @author bsutton + * * @param + * @author bsutton */ -public class CompletionAdaptor implements ActivityCallback -{ +public class CompletionAdaptor implements ActivityCallback { private static final Log logger = LogFactory.getLog(CompletionAdaptor.class); CountDownLatch _latch = new CountDownLatch(1); @Override - public void progress(final T activity, ActivityStatusEnum status, String message) - { - if (status == ActivityStatusEnum.FAILURE || status == ActivityStatusEnum.SUCCESS) - { + public void progress(final T activity, ActivityStatusEnum status, String message) { + if (status == ActivityStatusEnum.FAILURE || status == ActivityStatusEnum.SUCCESS) { _latch.countDown(); } } - public void waitForCompletion(long timeout, TimeUnit unit) - { + public void waitForCompletion(long timeout, TimeUnit unit) { // wait until the activity completes - try - { - if (!_latch.await(timeout, unit)) - { + try { + if (!_latch.await(timeout, unit)) { Exception e = new Exception("Timeout waiting for activity to complete (" + timeout + " " + unit + ")"); logger.error(e, e); } - } - catch (final InterruptedException e) - { + } catch (final InterruptedException e) { // should never happen CompletionAdaptor.logger.error(e, e); } diff --git a/src/main/java/org/asteriskjava/pbx/DTMFTone.java b/src/main/java/org/asteriskjava/pbx/DTMFTone.java index ab6166e02..0eab4c25e 100644 --- a/src/main/java/org/asteriskjava/pbx/DTMFTone.java +++ b/src/main/java/org/asteriskjava/pbx/DTMFTone.java @@ -2,26 +2,22 @@ /** * Used to indicate the set of possible DTMF tones which can be sent. - * + * * @author bsutton - * */ -public enum DTMFTone -{ - ZERO('0'), ONE('1'), TWO('2'), THREE('3'), FOUR('4'), FIVE('5'), SIX('6'), SEVEN('7'), EIGHT('8'), NINE('9'), - HASH('#'), STAR('*'); +public enum DTMFTone { + ZERO('0'), ONE('1'), TWO('2'), THREE('3'), FOUR('4'), FIVE('5'), SIX('6'), SEVEN('7'), EIGHT('8'), NINE('9'), + HASH('#'), STAR('*'); - private final String character; + private final String character; - DTMFTone(final char character) - { - this.character = new String(new char[] { character }); - } + DTMFTone(final char character) { + this.character = new String(new char[]{character}); + } - @Override - public String toString() - { - return this.character; - } + @Override + public String toString() { + return this.character; + } } diff --git a/src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java b/src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java index 50008aaf1..f4f85cbec 100644 --- a/src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java +++ b/src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java @@ -3,104 +3,93 @@ /** * A convenience class that provides a set of defaults that will work * for most people. - * + *

    * You can over-ride any specific methods for settings that you need to change. - * + *

    * Key thing to watch out for is that we user a meetme range of 3000-3200. * If you are already using this range for other meetme rooms then you need * to over-ride the getMeetMeBaseAddress. - * - * If you are using handsets other than yealink or snom you should also over-ride + *

    + * If you are using handsets other than yealink or snom you should also over-ride * the getAutoAnswer settings. - * - * @author bsutton * + * @author bsutton */ -public abstract class DefaultAsteriskSettings implements AsteriskSettings -{ +public abstract class DefaultAsteriskSettings implements AsteriskSettings { - @Override - public int getManagerPortNo() - { - return 5060; - } + @Override + public int getManagerPortNo() { + return 5060; + } - @Override - public Integer getMeetmeBaseAddress() - { - // We use conference rooms. Just make certain that the base address - // doesn't overlap any conference rooms you are currently running on your pbx. - // You should probably allow 200 conference rooms here e.g. (3000-3200) - // Actions like transfers (and conference calls) use a conference room. - return new Integer(3000); - } + @Override + public Integer getMeetmeBaseAddress() { + // We use conference rooms. Just make certain that the base address + // doesn't overlap any conference rooms you are currently running on your pbx. + // You should probably allow 200 conference rooms here e.g. (3000-3200) + // Actions like transfers (and conference calls) use a conference room. + return new Integer(3000); + } - @Override - public boolean getDisableBridge() - { - // Return false if you version of asterisk supports bridging channels. - // All version after 1.8 support bridging. - return false; - } + @Override + public boolean getDisableBridge() { + // Return false if you version of asterisk supports bridging channels. + // All version after 1.8 support bridging. + return false; + } - @Override - public String getManagementContext() - { - // This is an asterisk dialplan context. - // Simply pick a context which doesn't already exist - // and use AsteriskPBX.createAgiEntryPoint() - // to inject the necessary dialplan used by asterisk-java - return "asteriskjava"; - } + @Override + public String getManagementContext() { + // This is an asterisk dialplan context. + // Simply pick a context which doesn't already exist + // and use AsteriskPBX.createAgiEntryPoint() + // to inject the necessary dialplan used by asterisk-java + return "asteriskjava"; + } - @Override - public String getExtensionPark() - { - // Return an asterisk dialplan extension (within the Management Context) - // that will be used to park calls. - // Just ensure that its a unique asterisk dialplan extension name. - return "asterisk-java-park"; - } + @Override + public String getExtensionPark() { + // Return an asterisk dialplan extension (within the Management Context) + // that will be used to park calls. + // Just ensure that its a unique asterisk dialplan extension name. + return "asterisk-java-park"; + } - @Override - public int getDialTimeout() - { - // Return the amount of time to wait (in seconds) when dialing before we give up - // when the call isn't answered - return 30; - } + @Override + public int getDialTimeout() { + // Return the amount of time to wait (in seconds) when dialing before we give up + // when the call isn't answered + return 30; + } - /* - * If you are using handsets other than yealink or snom you should over-ride - * these method to return the correct auto-answer string for you handset type. - * - * If you neve use the auto answer feature in the dial command you can - * ignore this setting. - */ - @Override - public String getAutoAnswer() - { - // Return the auto-answer heading used by your organisations handsets - // to force them to auto-answer when we ring the handset. - // Bad luck if you have incompatible handsets. - return "Call-Info:\\; answer-after=0"; - } + /* + * If you are using handsets other than yealink or snom you should over-ride + * these method to return the correct auto-answer string for you handset type. + * + * If you neve use the auto answer feature in the dial command you can + * ignore this setting. + */ + @Override + public String getAutoAnswer() { + // Return the auto-answer heading used by your organisations handsets + // to force them to auto-answer when we ring the handset. + // Bad luck if you have incompatible handsets. + return "Call-Info:\\; answer-after=0"; + } - @Override - public String getAgiExtension() - { - // Return an asterisk dialplan extension (within the Management Context) - // that will be used to inject the agi dialplan entry point used by Activites.. - // Just ensure that its a unique asterisk dialplan extension name. - return "asterisk-java-agi"; - } + @Override + public String getAgiExtension() { + // Return an asterisk dialplan extension (within the Management Context) + // that will be used to inject the agi dialplan entry point used by Activites.. + // Just ensure that its a unique asterisk dialplan extension name. + return "asterisk-java-agi"; + } - @Override - public boolean getCanDetectHangup() - { - // Return try if the telephony tech you are dialing from can reliabily - // detect hangups. - return true; - } + @Override + public boolean getCanDetectHangup() { + // Return try if the telephony tech you are dialing from can reliabily + // detect hangups. + return true; + } } diff --git a/src/main/java/org/asteriskjava/pbx/DialPlanExtension.java b/src/main/java/org/asteriskjava/pbx/DialPlanExtension.java index cbdf2e7c3..9e0154aee 100644 --- a/src/main/java/org/asteriskjava/pbx/DialPlanExtension.java +++ b/src/main/java/org/asteriskjava/pbx/DialPlanExtension.java @@ -5,51 +5,42 @@ * njr-inbound,1,xxxxx In the above example njr-inbound is the dialplan * extension. This class primarily exists to stop common mistakes that can occur * if we pass this around as a simple string. - * + * * @author bsutton */ -public class DialPlanExtension implements EndPoint -{ +public class DialPlanExtension implements EndPoint { // the dial plan extension. String _extension; final boolean _empty; - public DialPlanExtension(String extension) - { - if (extension == null || extension.trim().length() == 0) - { + public DialPlanExtension(String extension) { + if (extension == null || extension.trim().length() == 0) { this._empty = true; this._extension = ""; - } - else - { + } else { this._extension = extension.trim(); this._empty = false; } } @Override - public int compareTo(EndPoint rhs) - { + public int compareTo(EndPoint rhs) { return this._extension.compareTo(rhs.getSimpleName()); } @Override - public boolean isSame(EndPoint rhs) - { + public boolean isSame(EndPoint rhs) { return this.compareTo(rhs) == 0; } @Override - public boolean isLocal() - { + public boolean isLocal() { return false; } @Override - public boolean isSIP() - { + public boolean isSIP() { return false; } @@ -58,44 +49,37 @@ public boolean isSIP() * identifier rather than a legitimate tech that the pbx understands. */ @Override - public String getFullyQualifiedName() - { + public String getFullyQualifiedName() { return this._extension; } @Override - public String getSimpleName() - { + public String getSimpleName() { return this._extension; } @Override - public String getSIPSimpleName() - { + public String getSIPSimpleName() { throw new UnsupportedOperationException(); } @Override - public boolean isUnknown() - { + public boolean isUnknown() { // TODO Auto-generated method stub return false; } @Override - public TechType getTech() - { + public TechType getTech() { return TechType.DIALPLAN; } - public String toString() - { + public String toString() { return this._extension; } @Override - public boolean isEmpty() - { + public boolean isEmpty() { return false; } } diff --git a/src/main/java/org/asteriskjava/pbx/EndPoint.java b/src/main/java/org/asteriskjava/pbx/EndPoint.java index 731e49a26..0288f3995 100644 --- a/src/main/java/org/asteriskjava/pbx/EndPoint.java +++ b/src/main/java/org/asteriskjava/pbx/EndPoint.java @@ -2,68 +2,65 @@ /** * Provides an abstract interface for entities which can be dialed. - * + *

    * This encompasses entities such as: Phone extensions SIPPeers Asterisk * extensions External phone numbers - * + * * @author bsutton - * */ -public interface EndPoint extends Comparable -{ - boolean isSame(EndPoint rhs); +public interface EndPoint extends Comparable { + boolean isSame(EndPoint rhs); - boolean isLocal(); + boolean isLocal(); - boolean isSIP(); + boolean isSIP(); - /** - * Returns the fully qualified name of the EndPoint including the tech. e.g. - * SIP/100 - * - * @return - */ - String getFullyQualifiedName(); + /** + * Returns the fully qualified name of the EndPoint including the tech. e.g. + * SIP/100 + * + * @return + */ + String getFullyQualifiedName(); - /** - * Returns the simple name of the EndPoint sans the tech. e.g. SIP/100 would - * be returned as 100. - * - * @return - */ - String getSimpleName(); + /** + * Returns the simple name of the EndPoint sans the tech. e.g. SIP/100 would + * be returned as 100. + * + * @return + */ + String getSimpleName(); - /** - * Returns the simple name of a SIP EndPoint sans the tech. e.g. SIP/100 - * would be returned as 100. If the endpoint is not actually a SIP end point - * then this method returns the full end point name. - * - * - * @return - */ - String getSIPSimpleName(); + /** + * Returns the simple name of a SIP EndPoint sans the tech. e.g. SIP/100 + * would be returned as 100. If the endpoint is not actually a SIP end point + * then this method returns the full end point name. + * + * @return + */ + String getSIPSimpleName(); - /** - * Returns true if the tech is not know for this end point. - * - * @return - */ - boolean isUnknown(); + /** + * Returns true if the tech is not know for this end point. + * + * @return + */ + boolean isUnknown(); - /** - * Returns the Tech that is used to reach this endpoint. - * - * @return - */ - TechType getTech(); + /** + * Returns the Tech that is used to reach this endpoint. + * + * @return + */ + TechType getTech(); - boolean isEmpty(); + boolean isEmpty(); - /** - * Sets the tech on the end point to the specified tech. - * - * @param sip - */ - // public void setTech(Tech tech); + /** + * Sets the tech on the end point to the specified tech. + * + * @param sip + */ + // public void setTech(Tech tech); } diff --git a/src/main/java/org/asteriskjava/pbx/InvalidChannelName.java b/src/main/java/org/asteriskjava/pbx/InvalidChannelName.java index b1cb6de54..834ad3287 100644 --- a/src/main/java/org/asteriskjava/pbx/InvalidChannelName.java +++ b/src/main/java/org/asteriskjava/pbx/InvalidChannelName.java @@ -1,12 +1,10 @@ package org.asteriskjava.pbx; -public class InvalidChannelName extends Exception -{ - private static final long serialVersionUID = 1L; +public class InvalidChannelName extends Exception { + private static final long serialVersionUID = 1L; - public InvalidChannelName(final String message) - { - super(message); - } + public InvalidChannelName(final String message) { + super(message); + } } diff --git a/src/main/java/org/asteriskjava/pbx/ListenerPriority.java b/src/main/java/org/asteriskjava/pbx/ListenerPriority.java index 7c622ff43..de211bbb0 100644 --- a/src/main/java/org/asteriskjava/pbx/ListenerPriority.java +++ b/src/main/java/org/asteriskjava/pbx/ListenerPriority.java @@ -1,35 +1,32 @@ package org.asteriskjava.pbx; -public enum ListenerPriority -{ - /** - * Provide access to events in near real time for specialised services that - * need priority access to events. Realtime events are sent before any other - * listeners get a chance to process the events. With the event dispatcher - * running in its own thread. This means that they are passed without delay. - * You must also ensure that you don't delay the processing of these - * messages as there may be real time event listeners. If you are concerned - * that you are going to delay the processing then you need to add in your - * own ManagerEventQueue to insulate other priority listeners from your - * tardiness. NOTE: you cannot rely on the LiveChannelManager as it - * processes events from the standard event queue. This means that Rename - * and Masquerade events MAY (very likely) not have been process when the - * realtime listener recieves an event. - */ +public enum ListenerPriority { + /** + * Provide access to events in near real time for specialised services that + * need priority access to events. Realtime events are sent before any other + * listeners get a chance to process the events. With the event dispatcher + * running in its own thread. This means that they are passed without delay. + * You must also ensure that you don't delay the processing of these + * messages as there may be real time event listeners. If you are concerned + * that you are going to delay the processing then you need to add in your + * own ManagerEventQueue to insulate other priority listeners from your + * tardiness. NOTE: you cannot rely on the LiveChannelManager as it + * processes events from the standard event queue. This means that Rename + * and Masquerade events MAY (very likely) not have been process when the + * realtime listener recieves an event. + */ - REALTIME(100), CRITICAL(10), HIGH(8), NORMAL(6), LOW(4); + REALTIME(100), CRITICAL(10), HIGH(8), NORMAL(6), LOW(4); - // The priority of the listeners. Higher priority listeners receive - // events first. - private int _priority; + // The priority of the listeners. Higher priority listeners receive + // events first. + private int _priority; - ListenerPriority(int priority) - { - this._priority = priority; - } + ListenerPriority(int priority) { + this._priority = priority; + } - public int compare(ListenerPriority rhs) - { - return rhs._priority - this._priority; - } -} \ No newline at end of file + public int compare(ListenerPriority rhs) { + return rhs._priority - this._priority; + } +} diff --git a/src/main/java/org/asteriskjava/pbx/NewChannelListener.java b/src/main/java/org/asteriskjava/pbx/NewChannelListener.java index c4725b1ac..4f1d8241f 100644 --- a/src/main/java/org/asteriskjava/pbx/NewChannelListener.java +++ b/src/main/java/org/asteriskjava/pbx/NewChannelListener.java @@ -1,24 +1,23 @@ package org.asteriskjava.pbx; -public interface NewChannelListener -{ - /** - * Allows a listener to be informed as new channels come up during an - * originate. - * - * The OriginateBase class will call this for each channel that comes up (as - * a result of the originate). - * - * Intermediate channels (local etc) that the underlying pbx may create on - * the way through are ignored with only the final channels being notified. - * - * This listener should be used by anyone that needs to have the channel at - * the earliest possible moment. - * - * Listeners should not run long lived process from this call as it will - * stall the dialer. - * - * @param channel - */ - void channelUpdate(Channel channel); +public interface NewChannelListener { + /** + * Allows a listener to be informed as new channels come up during an + * originate. + *

    + * The OriginateBase class will call this for each channel that comes up (as + * a result of the originate). + *

    + * Intermediate channels (local etc) that the underlying pbx may create on + * the way through are ignored with only the final channels being notified. + *

    + * This listener should be used by anyone that needs to have the channel at + * the earliest possible moment. + *

    + * Listeners should not run long lived process from this call as it will + * stall the dialer. + * + * @param channel + */ + void channelUpdate(Channel channel); } diff --git a/src/main/java/org/asteriskjava/pbx/NewExtensionListener.java b/src/main/java/org/asteriskjava/pbx/NewExtensionListener.java index 5bce30e85..edcf5f524 100644 --- a/src/main/java/org/asteriskjava/pbx/NewExtensionListener.java +++ b/src/main/java/org/asteriskjava/pbx/NewExtensionListener.java @@ -3,13 +3,11 @@ /** * Used to notify interested parties when a new extension has been read from the * pbx configuration. - * + * * @author bsutton - * */ -public interface NewExtensionListener -{ +public interface NewExtensionListener { - void newExtension(); + void newExtension(); } diff --git a/src/main/java/org/asteriskjava/pbx/PBX.java b/src/main/java/org/asteriskjava/pbx/PBX.java index 9b355e702..a42d81a9b 100644 --- a/src/main/java/org/asteriskjava/pbx/PBX.java +++ b/src/main/java/org/asteriskjava/pbx/PBX.java @@ -1,23 +1,16 @@ package org.asteriskjava.pbx; -import java.util.List; - import org.asteriskjava.pbx.Call.OperandChannel; -import org.asteriskjava.pbx.activities.BlindTransferActivity; -import org.asteriskjava.pbx.activities.DialActivity; -import org.asteriskjava.pbx.activities.HoldActivity; -import org.asteriskjava.pbx.activities.JoinActivity; -import org.asteriskjava.pbx.activities.ParkActivity; -import org.asteriskjava.pbx.activities.RedirectToActivity; -import org.asteriskjava.pbx.activities.SplitActivity; +import org.asteriskjava.pbx.activities.*; + +import java.util.List; /** * Provides an abstracted interface for communicating with a PBX. - * + * * @author bsutton */ -public interface PBX -{ +public interface PBX { /** * Call this method when shutting down the PBX interface to allow it to @@ -38,21 +31,21 @@ public interface PBX * It is recommended that you use the blindTransfer method which takes a * callback as there is no way to cancel this action. Until the * transferTarget answers the call or the blind transfer times out. - * + * * @param channelToTransfer the channel which is to be blind transfered - * @param transferTarget the endPoint to which the channel is to be - * tranferred. - * @param toCallerID - the callerID to display to the transferTarget during - * the transfer. - * @param autoAnswer - if true then the transferTarget is to be sent an auto - * answer header - * @param timeout - timeout (in seconds) for the blind transfer attempt. - * When the timeout is reached the Blind Transfer will be - * cancelled. + * @param transferTarget the endPoint to which the channel is to be + * tranferred. + * @param toCallerID - the callerID to display to the transferTarget during + * the transfer. + * @param autoAnswer - if true then the transferTarget is to be sent an auto + * answer header + * @param timeout - timeout (in seconds) for the blind transfer attempt. + * When the timeout is reached the Blind Transfer will be + * cancelled. * @param ActivityCallback */ BlindTransferActivity blindTransfer(final Call call, OperandChannel channelToTransfer, final EndPoint transferTarget, - final CallerID toCallerID, boolean autoAnswer, long timeout, String dialOptions); + final CallerID toCallerID, boolean autoAnswer, long timeout, String dialOptions); /** * The BlindTransferActivity is used by the AsteriksPBX to transfer a live @@ -61,24 +54,24 @@ BlindTransferActivity blindTransfer(final Call call, OperandChannel channelToTra * action will only complete when the call is answered by the tranferTarget. * You can cancel the action at any time by using the activity object * returned from the callback start method. - * + * * @param channelToTransfer the channel which is to be blind transfered - * @param transferTarget the endPoint to which the channel is to be - * transferred. - * @param toCallerID - the callerID to display to the transferTarget during - * the transfer. - * @param autoAnswer - if true then the transferTarget is to be sent an auto - * answer header - * @param timeout - timeout for the blind transfer attempt. When the timeout - * is reached the Blind Transfer will be cancelled. + * @param transferTarget the endPoint to which the channel is to be + * transferred. + * @param toCallerID - the callerID to display to the transferTarget during + * the transfer. + * @param autoAnswer - if true then the transferTarget is to be sent an auto + * answer header + * @param timeout - timeout for the blind transfer attempt. When the timeout + * is reached the Blind Transfer will be cancelled. */ void blindTransfer(Call call, OperandChannel channelToTransfer, final EndPoint transferTarget, final CallerID toCallerID, - boolean autoAnswer, long timeout, ActivityCallback callback, String dialOptions); + boolean autoAnswer, long timeout, ActivityCallback callback, String dialOptions); /** * Sends a DTMF tone to given channel. Not returning until the tone has been * sent. - * + * * @param channel */ void conference(Channel channelOne, Channel channelTwo, Channel channelThree); @@ -87,7 +80,7 @@ void blindTransfer(Call call, OperandChannel channelToTransfer, final EndPoint t * Sends a DTMF tone to the given channel. This method returns immediately * with progress information passed to the given callback. Note: the * callback method will be called from a different thread. - * + * * @param channel * @param callback */ @@ -97,7 +90,7 @@ void blindTransfer(Call call, OperandChannel channelToTransfer, final EndPoint t * Dials the given phone number using the specified trunk. Not returning * until the call has been dialled. The dial will return as soon as the * trunk comes up, it does not wait for remote end to answer. - * + * * @return Call - the call resulting from dialing the number. */ DialActivity dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID, String dialOptions); @@ -106,15 +99,15 @@ void blindTransfer(Call call, OperandChannel channelToTransfer, final EndPoint t * Dials the given phone number using the specified trunk. Not returning * until the call has been dialled. The dial will return as soon as the * trunk comes up, it does not wait for remote end to answer. - * + * * @return Call the call resulting from dialing the number. */ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID, - ActivityCallback callback, String dialOptions); + ActivityCallback callback, String dialOptions); /** * Hangs up the given channel. Not returning until the call is hungup. - * + * * @param channel * @throws PBXException */ @@ -124,7 +117,7 @@ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID * Hangs up the given channel. This method returns immediately with progress * information passed to the given callback. Note: the callback method will * be called from a different thread. - * + * * @param channel * @param callback */ @@ -132,14 +125,14 @@ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID /** * Hangup the given call, not returning until the call is hungup. - * + * * @param call */ void hangup(Call call) throws PBXException; /** * Put the given channel on hold. - * + * * @param channel * @return */ @@ -159,10 +152,10 @@ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID * (obvious?) limitation is that we can't park something like a conference * call as it has more than two channels. The returned iParkActivty can be * used to obtain the extension the call was parked on. - * - * @param the call which is to be parked. - * @param parkChannel - the channel which is going to be redirect to the - * njr-park extension. + * + * @param the call which is to be parked. + * @param parkChannel - the channel which is going to be redirect to the + * njr-park extension. * @param hangupChannel - the channel which is going to be hungup. */ ParkActivity park(Call call, Channel parkChannel); @@ -176,17 +169,17 @@ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID * be hung up. The (obvious?) limitation is that we can't park something * like a conference call as it has more than two channels. The returned * iParkActivty can be used to obtain the extension the call was parked on. - * - * @param the call which is to be parked. + * + * @param the call which is to be parked. * @param parkChannel - the channel which is going to be redirect to the - * njr-park extension. + * njr-park extension. */ void park(Call call, Channel parkChannel, ActivityCallback callback); /** * Sends a DTMF tone to given channel. Not returning until the tone has been * sent. - * + * * @param channel * @throws PBXException */ @@ -196,7 +189,7 @@ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID * Sends a DTMF tone to the given channel. This method returns immediately * with progress information passed to the given callback. Note: the * callback method will be called from a different thread. - * + * * @param channel * @param callback */ @@ -218,18 +211,18 @@ void dial(EndPoint from, CallerID fromCallerID, EndPoint to, CallerID toCallerID * only have one active channel */ JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, - CallDirection direction); + CallDirection direction); void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, - CallDirection direction, ActivityCallback listener); + CallDirection direction, ActivityCallback listener); /** * Returns the channel currently attached to the given end point, if one * exists. If no channel is attached to the given end point then null is * returned. - * + * * @return the channel attached to the end point or null if the endpoint is - * not currently in a call. + * not currently in a call. */ Channel getChannelByEndPoint(EndPoint endPoint); @@ -248,7 +241,7 @@ void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel * Builds an end point from a fully qualified end point name. A fully * qualified name includes the tech. How the tech is encoded is pbx * specific. - * + * * @param fullyQualifiedEndPointName * @return */ @@ -258,7 +251,7 @@ void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel * Builds an iEndPoint from an end point name. If the tech isn't passed in * the endPointName the tech is set to the defaultTech The encoding for an * end point name is pbx specific. - * + * * @param endPointName * @return */ diff --git a/src/main/java/org/asteriskjava/pbx/PBXException.java b/src/main/java/org/asteriskjava/pbx/PBXException.java index 6d12bf3fe..5d7a6136c 100644 --- a/src/main/java/org/asteriskjava/pbx/PBXException.java +++ b/src/main/java/org/asteriskjava/pbx/PBXException.java @@ -1,21 +1,17 @@ package org.asteriskjava.pbx; -public class PBXException extends Exception -{ +public class PBXException extends Exception { private static final long serialVersionUID = 1L; - public PBXException(String message, final Exception e) - { + public PBXException(String message, final Exception e) { super(message, e); } - public PBXException(final String message) - { + public PBXException(final String message) { super(message); } - public PBXException(Throwable e) - { + public PBXException(Throwable e) { super(e); } } diff --git a/src/main/java/org/asteriskjava/pbx/PBXFactory.java b/src/main/java/org/asteriskjava/pbx/PBXFactory.java index 7a64e7e40..3e99f79fa 100644 --- a/src/main/java/org/asteriskjava/pbx/PBXFactory.java +++ b/src/main/java/org/asteriskjava/pbx/PBXFactory.java @@ -1,32 +1,27 @@ package org.asteriskjava.pbx; -import java.util.concurrent.atomic.AtomicReference; - import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class PBXFactory -{ +import java.util.concurrent.atomic.AtomicReference; + +public class PBXFactory { - public static PBX getActivePBX() - { + public static PBX getActivePBX() { return AsteriskPBX.SELF; } final static AtomicReference profile = new AtomicReference<>(); - public static void init(AsteriskSettings newProfile) - { + public static void init(AsteriskSettings newProfile) { profile.set(newProfile); getActivePBX().performPostCreationTasks(); } - public static AsteriskSettings getActiveProfile() - { + public static AsteriskSettings getActiveProfile() { AsteriskSettings activeProfile = profile.get(); - if (activeProfile == null) - { + if (activeProfile == null) { throw new RuntimeException( "you must call setAsteriskSettings() before getActiveProfile() is called the first time"); } diff --git a/src/main/java/org/asteriskjava/pbx/PhoneNumber.java b/src/main/java/org/asteriskjava/pbx/PhoneNumber.java index 31c99e165..501e3cc2c 100644 --- a/src/main/java/org/asteriskjava/pbx/PhoneNumber.java +++ b/src/main/java/org/asteriskjava/pbx/PhoneNumber.java @@ -3,16 +3,14 @@ /** * Provides an abstraction of a phone number. This allows different PBX's to * store the phone numbers in a way that may be specific to the pbx. - * + *

    * In general most PBX's there is no need for a special abstraction, however * using the interface just makes the code clearer that we are passing a phone * number. - * + * * @author bsutton - * */ -public interface PhoneNumber -{ - // TODO +public interface PhoneNumber { + // TODO } diff --git a/src/main/java/org/asteriskjava/pbx/Tech.java b/src/main/java/org/asteriskjava/pbx/Tech.java index 954834e22..2699cb641 100644 --- a/src/main/java/org/asteriskjava/pbx/Tech.java +++ b/src/main/java/org/asteriskjava/pbx/Tech.java @@ -1,6 +1,5 @@ package org.asteriskjava.pbx; -public interface Tech -{ - // TODO: do we need this? +public interface Tech { + // TODO: do we need this? } diff --git a/src/main/java/org/asteriskjava/pbx/TechType.java b/src/main/java/org/asteriskjava/pbx/TechType.java index eb767ddc6..f3307f150 100644 --- a/src/main/java/org/asteriskjava/pbx/TechType.java +++ b/src/main/java/org/asteriskjava/pbx/TechType.java @@ -3,8 +3,7 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public enum TechType implements Tech -{ +public enum TechType implements Tech { // UNKNOWN, SIP, DAHDI, LOCAL, IAX, IAX2 @@ -27,14 +26,12 @@ public enum TechType implements Tech /** * Extracts the technology from a fully qualified endpoint string of the form: * TECH/NNNN - * + * * @param fullyQualifiedEndPoint * @return */ - public static TechType getTech(final String fullyQualifiedEndPoint) - { - if (!TechType.hasValidTech(fullyQualifiedEndPoint)) - { + public static TechType getTech(final String fullyQualifiedEndPoint) { + if (!TechType.hasValidTech(fullyQualifiedEndPoint)) { throw new IllegalArgumentException("The provided end point '" //$NON-NLS-1$ + fullyQualifiedEndPoint + "' must contain a tech prefix. e.g. SIP/100"); //$NON-NLS-1$ } @@ -45,24 +42,19 @@ public static TechType getTech(final String fullyQualifiedEndPoint) /** * returns true if the endPoint name contains a valid tech descriptor. - * + * * @param endPointName * @return */ - public static boolean hasValidTech(final String endPointName) - { + public static boolean hasValidTech(final String endPointName) { TechType tech = UNKNOWN; final int index = endPointName.indexOf("/"); //$NON-NLS-1$ - if (index >= 1) - { + if (index >= 1) { final String techName = endPointName.substring(0, index); - try - { + try { tech = TechType.valueOf(techName.toUpperCase()); - } - catch (final IllegalArgumentException e) - { + } catch (final IllegalArgumentException e) { TechType.logger.error("Invalid tech for endpoint:" + endPointName); //$NON-NLS-1$ } } @@ -74,18 +66,16 @@ public static boolean hasValidTech(final String endPointName) /** * returns true if the endPoint name contains a tech descriptor even if it isn't * a known descriptor. - * + * * @param endPointName * @return */ - public static boolean hasTech(final String endPointName) - { + public static boolean hasTech(final String endPointName) { boolean hasTech = false; final int index = endPointName.indexOf("/"); //$NON-NLS-1$ - if (index != -1) - { + if (index != -1) { hasTech = true; } diff --git a/src/main/java/org/asteriskjava/pbx/Trunk.java b/src/main/java/org/asteriskjava/pbx/Trunk.java index 981591102..005165b1f 100644 --- a/src/main/java/org/asteriskjava/pbx/Trunk.java +++ b/src/main/java/org/asteriskjava/pbx/Trunk.java @@ -3,7 +3,6 @@ /** * Provides an abstraction of a trunk * @author bsutton */ -public interface Trunk -{ +public interface Trunk { String getTrunkAsString(); } diff --git a/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java b/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java index 6e5e56451..802cc3104 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/BlindTransferActivity.java @@ -1,22 +1,15 @@ package org.asteriskjava.pbx.activities; -import org.asteriskjava.pbx.Activity; -import org.asteriskjava.pbx.Call; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.PBXException; +import org.asteriskjava.pbx.*; -public interface BlindTransferActivity extends Activity -{ +public interface BlindTransferActivity extends Activity { /** * A bridged call is a successful transfer all other options are a failed * transfer. - * + * * @author bsutton */ - enum CompletionCause - { + enum CompletionCause { // The call was bridged. BRIDGED("Connected") // The call hungup @@ -31,13 +24,11 @@ enum CompletionCause String message; - CompletionCause(String message) - { + CompletionCause(String message) { this.message = message; } - public String getMessage() - { + public String getMessage() { return message; } } @@ -56,7 +47,7 @@ public String getMessage() /** * The call created as a result of the blind transfer being answered. - * + * * @return * @throws PBXException */ diff --git a/src/main/java/org/asteriskjava/pbx/activities/BridgeActivity.java b/src/main/java/org/asteriskjava/pbx/activities/BridgeActivity.java index 11fbd13dc..62a6aa8d5 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/BridgeActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/BridgeActivity.java @@ -2,7 +2,6 @@ import org.asteriskjava.pbx.Activity; -public interface BridgeActivity extends Activity -{ - // TODO +public interface BridgeActivity extends Activity { + // TODO } diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialActivity.java b/src/main/java/org/asteriskjava/pbx/activities/DialActivity.java index 46a7ceab4..0565676ca 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/DialActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/DialActivity.java @@ -5,49 +5,49 @@ import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; -public interface DialActivity extends Activity -{ - /** - * Returns the end point which originated the dial. - */ - EndPoint getOriginatingEndPoint(); - - /** - * Returns the end point which is being dialed. This is available even - * before the dial commences. - */ - EndPoint getAcceptingEndPoint(); - - /** - * Returns the 'originating' channel which is brought up as part of the dial - * activity. The 'originating' channel may return null if the channel is not - * up. - * - * @return the 'originating' channel if it has been brought up otherwise - * null. - */ - Channel getOriginatingChannel(); - - /** - * Returns the 'accepting' channel which is brought up as part of the dial - * activity. The accepting party is the party that answers the call. The - * 'accepting' channel may return null if the channel is not up. - * - * @return the 'accepting' channel if it has been brought up otherwise null - */ - Channel getAcceptingChannel(); - - /** - * Call markCancelled if you want to stop a dial which is in progress from - * completing. This allows a user to cancel a dial. - */ - void markCancelled(); - - /** - * Returns true if markCancelled was called during the dial attempt. - * @return - */ - boolean cancelledByOperator(); - - Call getNewCall(); +public interface DialActivity extends Activity { + /** + * Returns the end point which originated the dial. + */ + EndPoint getOriginatingEndPoint(); + + /** + * Returns the end point which is being dialed. This is available even + * before the dial commences. + */ + EndPoint getAcceptingEndPoint(); + + /** + * Returns the 'originating' channel which is brought up as part of the dial + * activity. The 'originating' channel may return null if the channel is not + * up. + * + * @return the 'originating' channel if it has been brought up otherwise + * null. + */ + Channel getOriginatingChannel(); + + /** + * Returns the 'accepting' channel which is brought up as part of the dial + * activity. The accepting party is the party that answers the call. The + * 'accepting' channel may return null if the channel is not up. + * + * @return the 'accepting' channel if it has been brought up otherwise null + */ + Channel getAcceptingChannel(); + + /** + * Call markCancelled if you want to stop a dial which is in progress from + * completing. This allows a user to cancel a dial. + */ + void markCancelled(); + + /** + * Returns true if markCancelled was called during the dial attempt. + * + * @return + */ + boolean cancelledByOperator(); + + Call getNewCall(); } diff --git a/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java index bd743ea86..27a17dda6 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/DialToAgiActivity.java @@ -4,8 +4,7 @@ import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; -public interface DialToAgiActivity extends Activity -{ +public interface DialToAgiActivity extends Activity { void markCancelled(); diff --git a/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java b/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java index e932204e6..bc4e62322 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/HoldActivity.java @@ -3,8 +3,7 @@ import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.Channel; -public interface HoldActivity extends Activity -{ - // Returns the Channel that is on hold - Channel getChannel(); +public interface HoldActivity extends Activity { + // Returns the Channel that is on hold + Channel getChannel(); } diff --git a/src/main/java/org/asteriskjava/pbx/activities/JoinActivity.java b/src/main/java/org/asteriskjava/pbx/activities/JoinActivity.java index 30acf65cd..e7430dc7c 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/JoinActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/JoinActivity.java @@ -3,8 +3,7 @@ import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.Call; -public interface JoinActivity extends Activity -{ - Call getJoinedCall(); +public interface JoinActivity extends Activity { + Call getJoinedCall(); } diff --git a/src/main/java/org/asteriskjava/pbx/activities/ParkActivity.java b/src/main/java/org/asteriskjava/pbx/activities/ParkActivity.java index 5d4282115..ab15228ad 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/ParkActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/ParkActivity.java @@ -3,14 +3,13 @@ import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.EndPoint; -public interface ParkActivity extends Activity -{ - - /** - * Returns the endpoint (parking lot) that the call was park on. - * - * @return - */ - EndPoint getParkingLot(); +public interface ParkActivity extends Activity { + + /** + * Returns the endpoint (parking lot) that the call was park on. + * + * @return + */ + EndPoint getParkingLot(); } diff --git a/src/main/java/org/asteriskjava/pbx/activities/RedirectToActivity.java b/src/main/java/org/asteriskjava/pbx/activities/RedirectToActivity.java index ff2342b46..1352d8077 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/RedirectToActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/RedirectToActivity.java @@ -3,16 +3,15 @@ import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.Call; -public interface RedirectToActivity extends Activity -{ +public interface RedirectToActivity extends Activity { /** * After a call has been split we get a new calls. The call created as a * result of the lhsOperandChannel being split can be retrieved by calling * this method. - * + * * @return the call which holds the call associated with the - * lhsOperandChannel + * lhsOperandChannel */ Call getCall(); diff --git a/src/main/java/org/asteriskjava/pbx/activities/SplitActivity.java b/src/main/java/org/asteriskjava/pbx/activities/SplitActivity.java index cfd99fcd9..3af630d70 100644 --- a/src/main/java/org/asteriskjava/pbx/activities/SplitActivity.java +++ b/src/main/java/org/asteriskjava/pbx/activities/SplitActivity.java @@ -3,30 +3,29 @@ import org.asteriskjava.pbx.Activity; import org.asteriskjava.pbx.Call; -public interface SplitActivity extends Activity -{ +public interface SplitActivity extends Activity { - /** - * After a call has been split we get a new calls. The call created as a - * result of the lhsOperandChannel being split can be retrieved by calling - * this method. - * - * @return the call which holds the call associated with the - * lhsOperandChannel - */ - Call getLHSCall(); + /** + * After a call has been split we get a new calls. The call created as a + * result of the lhsOperandChannel being split can be retrieved by calling + * this method. + * + * @return the call which holds the call associated with the + * lhsOperandChannel + */ + Call getLHSCall(); - /** - * After a call has been split we get a new calls. The call created as a - * result of the rhsOperandChannel being split can be retrieved by calling - * this method. - * - * This method will return now if split was called with only a single - * operand channel. - * - * @return the call which holds the call associated with the - * lhsOperandChannel - */ - Call getRHSCall(); + /** + * After a call has been split we get a new calls. The call created as a + * result of the rhsOperandChannel being split can be retrieved by calling + * this method. + *

    + * This method will return now if split was called with only a single + * operand channel. + * + * @return the call which holds the call associated with the + * lhsOperandChannel + */ + Call getRHSCall(); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java index ce31fcc47..f3a08c1b1 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityAgi.java @@ -1,27 +1,21 @@ package org.asteriskjava.pbx.agi; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - +import com.google.common.util.concurrent.RateLimiter; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; -import org.asteriskjava.pbx.AgiChannelActivityAction; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.ChannelHangupListener; -import org.asteriskjava.pbx.InvalidChannelName; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.agi.config.ServiceAgiScriptImpl; import org.asteriskjava.pbx.asterisk.wrap.actions.OriginateAction; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -import com.google.common.util.concurrent.RateLimiter; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; -public abstract class ActivityAgi extends ServiceAgiScriptImpl -{ +public abstract class ActivityAgi extends ServiceAgiScriptImpl { public static final String ARRIVAL_KEY = "ActivityAgiArrivalKey"; @@ -29,13 +23,11 @@ public abstract class ActivityAgi extends ServiceAgiScriptImpl private static final Map arrivalListeners = new ConcurrentHashMap<>(); - public static AutoCloseable addArrivalListener(OriginateAction originate, ActivityArrivalListener listener) - { + public static AutoCloseable addArrivalListener(OriginateAction originate, ActivityArrivalListener listener) { final String key = UUID.randomUUID().toString(); arrivalListeners.put(key, listener); - if (arrivalListeners.size() > 100) - { + if (arrivalListeners.size() > 100) { // pick one at random to remove ActivityArrivalListener leaked = arrivalListeners.remove(arrivalListeners.keySet().iterator().next()); logger.error("Arrival Listeners are leaking" + leaked.getClass().getCanonicalName()); @@ -44,12 +36,10 @@ public static AutoCloseable addArrivalListener(OriginateAction originate, Activi Map vars = new HashMap<>(); vars.put("_" + ARRIVAL_KEY, key); originate.setVariables(vars); - return new AutoCloseable() - { + return new AutoCloseable() { @Override - public void close() throws Exception - { + public void close() throws Exception { arrivalListeners.remove(key); } @@ -57,21 +47,17 @@ public void close() throws Exception } @Override - public void service() throws AgiException - { + public void service() throws AgiException { Channel channelProxy = null; String channelName = channel.getName(); - try - { + try { AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); String proxyId = getVariable("proxyId"); - if (proxyId != null && proxyId.length() > 0) - { + if (proxyId != null && proxyId.length() > 0) { channelProxy = pbx.getProxyById(proxyId); } - if (channelProxy == null) - { + if (channelProxy == null) { logger.info("'proxyId' var not set or proxy doesn't exist anymore, trying to match the channel name... " + channelName); channelProxy = pbx.internalRegisterChannel(channel.getName(), channel.getUniqueId()); @@ -81,15 +67,12 @@ public void service() throws AgiException logger.info("Channel " + channelName + " arrived in agi"); channelProxy.setIsInAgi(true); - channelProxy.addHangupListener(new ChannelHangupListener() - { + channelProxy.addHangupListener(new ChannelHangupListener() { @Override - public void channelHangup(Channel channel, Integer cause, String causeText) - { + public void channelHangup(Channel channel, Integer cause, String causeText) { final AgiChannelActivityAction currentActivityAction = channel.getCurrentActivityAction(); - if (currentActivityAction != null) - { + if (currentActivityAction != null) { currentActivityAction.cancel(); } @@ -97,25 +80,21 @@ public void channelHangup(Channel channel, Integer cause, String causeText) }); AgiChannelActivityAction action = channelProxy.getCurrentActivityAction(); - if (action == null) - { + if (action == null) { action = new AgiChannelActivityHold(); } String arrivalKey = channel.getVariable(ARRIVAL_KEY); - if (arrivalKey != null && arrivalKey.length() > 0) - { + if (arrivalKey != null && arrivalKey.length() > 0) { ActivityArrivalListener listener = arrivalListeners.get(arrivalKey); - if (listener != null) - { + if (listener != null) { listener.channelArrived(channelProxy); } } boolean isAlive = true; RateLimiter slowRateLimiter = RateLimiter.create(2); - while (!action.isDisconnect(this) && isAlive) - { + while (!action.isDisconnect(this) && isAlive) { action.execute(this.channel, channelProxy); action = channelProxy.getCurrentActivityAction(); @@ -124,13 +103,9 @@ public void channelHangup(Channel channel, Integer cause, String causeText) slowRateLimiter.acquire(); } - } - catch (AgiHangupException e) - { + } catch (AgiHangupException e) { logger.warn("Channel hungup " + channelName); - } - catch (InvalidChannelName | InterruptedException e) - { + } catch (InvalidChannelName | InterruptedException e) { logger.error(e, e); } @@ -138,16 +113,11 @@ public void channelHangup(Channel channel, Integer cause, String causeText) } - private boolean checkChannelIsStillUp() - { - try - - { + private boolean checkChannelIsStillUp() { + try { this.answer(); return true; - } - catch (Exception e) - { + } catch (Exception e) { } return false; diff --git a/src/main/java/org/asteriskjava/pbx/agi/ActivityArrivalListener.java b/src/main/java/org/asteriskjava/pbx/agi/ActivityArrivalListener.java index d475f0e41..877de668b 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/ActivityArrivalListener.java +++ b/src/main/java/org/asteriskjava/pbx/agi/ActivityArrivalListener.java @@ -2,8 +2,7 @@ import org.asteriskjava.pbx.Channel; -public interface ActivityArrivalListener -{ +public interface ActivityArrivalListener { void channelArrived(Channel channel); diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java index 888865843..c25e89a4b 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBlindTransfer.java @@ -1,14 +1,13 @@ package org.asteriskjava.pbx.agi; -import java.util.concurrent.CountDownLatch; - import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; -public class AgiChannelActivityBlindTransfer implements AgiChannelActivityAction -{ +import java.util.concurrent.CountDownLatch; + +public class AgiChannelActivityBlindTransfer implements AgiChannelActivityAction { CountDownLatch latch = new CountDownLatch(1); private String target; @@ -19,22 +18,19 @@ public class AgiChannelActivityBlindTransfer implements AgiChannelActivityAction private BlindTransferResultListener listener; public AgiChannelActivityBlindTransfer(String fullyQualifiedName, String sipHeader, String callerId, String dialOptions, - BlindTransferResultListener listener) - { + BlindTransferResultListener listener) { this.target = fullyQualifiedName; this.sipHeader = sipHeader; this.callerId = callerId; this.dialOptions = dialOptions; - if (sipHeader == null) - { + if (sipHeader == null) { this.sipHeader = ""; } this.listener = listener; } @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { channel.setVariable("__SIPADDHEADER", sipHeader); channel.setCallerId(callerId); @@ -42,21 +38,18 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I channel.dial(target, timeout, dialOptions); String status = channel.getVariable("DIALSTATUS"); boolean success = "ANSWER".equalsIgnoreCase(status); - if (listener != null) - { + if (listener != null) { listener.result(status, success); } } @Override - public boolean isDisconnect(ActivityAgi activityAgi) - { + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } @Override - public void cancel() - { + public void cancel() { latch.countDown(); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java index afa8c805e..458c8920a 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityBridge.java @@ -1,7 +1,5 @@ package org.asteriskjava.pbx.agi; -import java.util.concurrent.CountDownLatch; - import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; @@ -10,24 +8,22 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class AgiChannelActivityBridge implements AgiChannelActivityAction -{ +import java.util.concurrent.CountDownLatch; + +public class AgiChannelActivityBridge implements AgiChannelActivityAction { private Channel target; private final Log logger = LogFactory.getLog(this.getClass()); CountDownLatch latch = new CountDownLatch(1); - public AgiChannelActivityBridge(Channel target) - { + public AgiChannelActivityBridge(Channel target) { this.target = target; } @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { - try - { + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { + try { // TODO: this should probably pass the 'F' option to allow the // bridgee // to go back to dialplan. @@ -36,33 +32,26 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I // I can't currently see it causing problems. channel.bridge(target.getChannelName(), ""); channel.hangup(); - } - catch (AgiHangupException e) - { + } catch (AgiHangupException e) { logger.warn(e); - } - finally - { + } finally { latch.countDown(); } } @Override - public boolean isDisconnect(ActivityAgi activityAgi) - { + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } @Override - public void cancel() - { + public void cancel() { latch.countDown(); } // Logger logger = LogManager.getLogger(); - public void sleepWhileBridged() throws InterruptedException - { + public void sleepWhileBridged() throws InterruptedException { latch.await(); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java index e4d2924d6..9b3ae4f07 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityDial.java @@ -1,38 +1,33 @@ package org.asteriskjava.pbx.agi; -import java.util.concurrent.CountDownLatch; - import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; -public class AgiChannelActivityDial implements AgiChannelActivityAction -{ +import java.util.concurrent.CountDownLatch; + +public class AgiChannelActivityDial implements AgiChannelActivityAction { CountDownLatch latch = new CountDownLatch(1); private String target; private String sipHeader; private String dialOptions; - public AgiChannelActivityDial(String target, String dialOptions) - { + public AgiChannelActivityDial(String target, String dialOptions) { this.target = target; this.dialOptions = dialOptions; } - public AgiChannelActivityDial(String fullyQualifiedName, String sipHeader, String dialOptions) - { + public AgiChannelActivityDial(String fullyQualifiedName, String sipHeader, String dialOptions) { target = fullyQualifiedName; this.sipHeader = sipHeader; this.dialOptions = dialOptions; } @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { - if (sipHeader != null) - { + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { + if (sipHeader != null) { channel.setVariable("__SIPADDHEADER", sipHeader); } // setting the activity to hold, means that when the call falls out of @@ -47,14 +42,12 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect(ActivityAgi activityAgi) - { + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } @Override - public void cancel() - { + public void cancel() { latch.countDown(); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java index 300067bab..6963e04cd 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHangup.java @@ -1,7 +1,5 @@ package org.asteriskjava.pbx.agi; -import java.util.concurrent.CountDownLatch; - import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; @@ -10,37 +8,32 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class AgiChannelActivityHangup implements AgiChannelActivityAction -{ +import java.util.concurrent.CountDownLatch; + +public class AgiChannelActivityHangup implements AgiChannelActivityAction { private final Log logger = LogFactory.getLog(this.getClass()); CountDownLatch latch = new CountDownLatch(1); @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { - try - { + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { + try { channel.hangup(); logger.info("Hungup"); - } - catch (AgiHangupException e) - { + } catch (AgiHangupException e) { // don't care } } @Override - public boolean isDisconnect(ActivityAgi activityAgi) - { + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } @Override - public void cancel() - { + public void cancel() { latch.countDown(); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java index a6a02aa56..8a80ba9eb 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHold.java @@ -1,8 +1,5 @@ package org.asteriskjava.pbx.agi; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; @@ -11,8 +8,10 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class AgiChannelActivityHold implements AgiChannelActivityAction -{ +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class AgiChannelActivityHold implements AgiChannelActivityAction { private final Log logger = LogFactory.getLog(this.getClass()); CountDownLatch latch = new CountDownLatch(1); @@ -20,65 +19,48 @@ public class AgiChannelActivityHold implements AgiChannelActivityAction long timer = System.currentTimeMillis(); @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { - try - { + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { + try { callReachedAgi = true; channel.answer(); channel.playMusicOnHold(); long secondsOnHold = Math.abs(System.currentTimeMillis() - timer) / 1000; - if (secondsOnHold > 600) - { + if (secondsOnHold > 600) { logger.info(ichannel + " is still on hold after " + secondsOnHold + " seconds"); } - if (latch.await(10, TimeUnit.SECONDS)) - { - try - { + if (latch.await(10, TimeUnit.SECONDS)) { + try { channel.stopMusicOnHold(); - } - catch (AgiHangupException e) - { + } catch (AgiHangupException e) { logger.info("Channel hungup " + channel.getName()); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn(e); } - } - else - { - if (channel.getName().startsWith("Local") && secondsOnHold > 3600) - { + } else { + if (channel.getName().startsWith("Local") && secondsOnHold > 3600) { // cleanup Local channels older than 1 hour logger.error("Hanging up local channel that has been on hold for 1 hour " + channel.getName()); channel.hangup(); } } - } - catch (AgiHangupException e) - { + } catch (AgiHangupException e) { logger.warn(e); } } @Override - public boolean isDisconnect(ActivityAgi activityAgi) - { + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } @Override - public void cancel() - { + public void cancel() { latch.countDown(); } - public boolean hasCallReachedAgi() - { + public boolean hasCallReachedAgi() { return callReachedAgi; } } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java index 973fd7a7f..5760a21cf 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityHoldForBridge.java @@ -8,46 +8,37 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class AgiChannelActivityHoldForBridge implements AgiChannelActivityAction -{ +public class AgiChannelActivityHoldForBridge implements AgiChannelActivityAction { private final Log logger = LogFactory.getLog(this.getClass()); private AgiChannelActivityBridge bridgeActivity; private volatile boolean hangup = true; - public AgiChannelActivityHoldForBridge(AgiChannelActivityBridge bridgeActivity) - { + public AgiChannelActivityHoldForBridge(AgiChannelActivityBridge bridgeActivity) { this.bridgeActivity = bridgeActivity; } @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { - try - { + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { + try { channel.playMusicOnHold(); bridgeActivity.sleepWhileBridged(); - if (hangup) - { + if (hangup) { channel.hangup(); } - } - catch (AgiHangupException e) - { + } catch (AgiHangupException e) { logger.warn(e.getMessage() + " " + channel.getName()); } } @Override - public boolean isDisconnect(ActivityAgi activityAgi) - { + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } @Override - public void cancel() - { + public void cancel() { // this seems a bit strange, but the logic here is that if you cancel // this action you want to invoke a new action. We can't end the bridge // from here, but not hanging up when it does collapse is @@ -56,8 +47,7 @@ public void cancel() } - public void hangupAfterBridge(boolean b) - { + public void hangupAfterBridge(boolean b) { hangup = b; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java index b9f32b9ef..3c5acad65 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityMeetme.java @@ -1,8 +1,5 @@ package org.asteriskjava.pbx.agi; -import java.io.IOException; -import java.util.concurrent.CountDownLatch; - import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.manager.TimeoutException; @@ -15,8 +12,10 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class AgiChannelActivityMeetme implements AgiChannelActivityAction -{ +import java.io.IOException; +import java.util.concurrent.CountDownLatch; + +public class AgiChannelActivityMeetme implements AgiChannelActivityAction { private final Log logger = LogFactory.getLog(this.getClass()); CountDownLatch latch = new CountDownLatch(1); @@ -29,31 +28,24 @@ public class AgiChannelActivityMeetme implements AgiChannelActivityAction private String userProfile; - public AgiChannelActivityMeetme(String room, String bridgeProfile, String userProfile) - { + public AgiChannelActivityMeetme(String room, String bridgeProfile, String userProfile) { this.room = room; this.bridgeProfile = bridgeProfile; this.userProfile = userProfile; } @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { - if (ichannel == null) - { + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { + if (ichannel == null) { throw new NullPointerException("ichannel cannot be null"); } this.ichannel = ichannel; channel.confbridge(room, bridgeProfile + "," + userProfile); - if (hangup) - { - try - { + if (hangup) { + try { channel.hangup(); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn(e); } } @@ -62,26 +54,21 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect(ActivityAgi activityAgi) - { + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } @Override - public void cancel() - { + public void cancel() { hangup = false; final AsteriskSettings profile = PBXFactory.getActiveProfile(); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); final RedirectAction redirect = new RedirectAction(ichannel, profile.getManagementContext(), pbx.getExtensionAgi(), 1); - try - { + try { pbx.sendAction(redirect, 1000); - } - catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) - { + } catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) { logger.error(e, e); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java index 867e48dd8..f45646b22 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityPlayMessage.java @@ -1,28 +1,24 @@ package org.asteriskjava.pbx.agi; -import java.util.concurrent.TimeUnit; - import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; -public class AgiChannelActivityPlayMessage implements AgiChannelActivityAction -{ +import java.util.concurrent.TimeUnit; + +public class AgiChannelActivityPlayMessage implements AgiChannelActivityAction { private String file; private boolean hangup = false; - public AgiChannelActivityPlayMessage(String file) - { + public AgiChannelActivityPlayMessage(String file) { this.file = file; } @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { - if (ichannel == null) - { + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { + if (ichannel == null) { throw new NullPointerException("ichannel cannot be null"); } String tmp = file; @@ -32,12 +28,9 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I // file, escape, offset, forward, rewind, pause // # to exit, 6 forward, 4 back, 5 pause - try - { + try { channel.controlStreamFile(tmp, "#", 15000, "6", "4", "5"); - } - catch (Exception e) - { + } catch (Exception e) { TimeUnit.MILLISECONDS.sleep(100); throw e; } @@ -50,14 +43,12 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect(ActivityAgi activityAgi) - { + public boolean isDisconnect(ActivityAgi activityAgi) { return hangup; } @Override - public void cancel() - { + public void cancel() { hangup = true; } } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java index ef61c40b0..d6d50d8dd 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityQueue.java @@ -1,8 +1,5 @@ package org.asteriskjava.pbx.agi; -import java.io.IOException; -import java.util.concurrent.CountDownLatch; - import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; @@ -16,8 +13,10 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class AgiChannelActivityQueue implements AgiChannelActivityAction -{ +import java.io.IOException; +import java.util.concurrent.CountDownLatch; + +public class AgiChannelActivityQueue implements AgiChannelActivityAction { private final Log logger = LogFactory.getLog(this.getClass()); @@ -29,29 +28,21 @@ public class AgiChannelActivityQueue implements AgiChannelActivityAction private Channel ichannel; - public AgiChannelActivityQueue(String queue) - { + public AgiChannelActivityQueue(String queue) { this.queue = queue; } @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { this.ichannel = ichannel; channel.queue(queue); - if (hangup) - { - try - { + if (hangup) { + try { channel.hangup(); - } - catch (AgiHangupException e) - { + } catch (AgiHangupException e) { logger.warn("Channel " + channel.getName() + " hungup"); - } - catch (Exception e) - { + } catch (Exception e) { logger.warn(e); } } @@ -60,14 +51,12 @@ public void execute(AgiChannel channel, Channel ichannel) throws AgiException, I } @Override - public boolean isDisconnect(ActivityAgi activityAgi) - { + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } @Override - public void cancel() - { + public void cancel() { hangup = false; final AsteriskSettings profile = PBXFactory.getActiveProfile(); @@ -75,13 +64,10 @@ public void cancel() AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); final RedirectAction redirect = new RedirectAction(ichannel, profile.getManagementContext(), pbx.getExtensionAgi(), 1); - try - { + try { pbx.sendAction(redirect, 1000); - } - catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) - { + } catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) { logger.error(e, e); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java index 74b74b935..77e235a20 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityTransientHoldSilence.java @@ -1,8 +1,5 @@ package org.asteriskjava.pbx.agi; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiException; import org.asteriskjava.fastagi.AgiHangupException; @@ -11,14 +8,16 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + /** * Waits in silence for 10 seconds, then hangs up. This is useful where channels * are waiting for some external action to redirect/bridge them. - * + * * @author rsutton */ -public class AgiChannelActivityTransientHoldSilence implements AgiChannelActivityAction -{ +public class AgiChannelActivityTransientHoldSilence implements AgiChannelActivityAction { private final Log logger = LogFactory.getLog(this.getClass()); CountDownLatch latch = new CountDownLatch(1); @@ -26,51 +25,38 @@ public class AgiChannelActivityTransientHoldSilence implements AgiChannelActivit boolean firstPass = true; @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { - try - { + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { + try { callReachedAgi = true; channel.answer(); - if (!firstPass) - { + if (!firstPass) { logger.error(ichannel + " is still on hold after first pass, Hanging up"); channel.hangup(); - } - else - { - if (!latch.await(10, TimeUnit.SECONDS)) - { + } else { + if (!latch.await(10, TimeUnit.SECONDS)) { logger.warn("Exiting with timeout"); } } - } - catch (AgiHangupException e) - { + } catch (AgiHangupException e) { logger.warn(e); - } - finally - { + } finally { firstPass = false; } } @Override - public boolean isDisconnect(ActivityAgi activityAgi) - { + public boolean isDisconnect(ActivityAgi activityAgi) { return false; } @Override - public void cancel() - { + public void cancel() { latch.countDown(); } - public boolean hasCallReachedAgi() - { + public boolean hasCallReachedAgi() { return callReachedAgi; } } diff --git a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java index 228c47501..c47945720 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java +++ b/src/main/java/org/asteriskjava/pbx/agi/AgiChannelActivityVoicemail.java @@ -5,31 +5,26 @@ import org.asteriskjava.pbx.AgiChannelActivityAction; import org.asteriskjava.pbx.Channel; -public class AgiChannelActivityVoicemail implements AgiChannelActivityAction -{ +public class AgiChannelActivityVoicemail implements AgiChannelActivityAction { - public AgiChannelActivityVoicemail(String mailbox) - { + public AgiChannelActivityVoicemail(String mailbox) { // TODO Auto-generated constructor stub } @Override - public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException - { + public void execute(AgiChannel channel, Channel ichannel) throws AgiException, InterruptedException { // TODO Auto-generated method stub } @Override - public boolean isDisconnect(ActivityAgi activityAgi) - { + public boolean isDisconnect(ActivityAgi activityAgi) { // TODO Auto-generated method stub return false; } @Override - public void cancel() - { + public void cancel() { // TODO Auto-generated method stub } diff --git a/src/main/java/org/asteriskjava/pbx/agi/BlindTransferResultListener.java b/src/main/java/org/asteriskjava/pbx/agi/BlindTransferResultListener.java index b053979c0..1f88d5a3e 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/BlindTransferResultListener.java +++ b/src/main/java/org/asteriskjava/pbx/agi/BlindTransferResultListener.java @@ -1,7 +1,6 @@ package org.asteriskjava.pbx.agi; -public interface BlindTransferResultListener -{ +public interface BlindTransferResultListener { void result(String status, boolean success); diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/AgiConfiguration.java b/src/main/java/org/asteriskjava/pbx/agi/config/AgiConfiguration.java index 14bbd70e1..6c107d824 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/AgiConfiguration.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/AgiConfiguration.java @@ -2,9 +2,8 @@ import java.util.List; -public interface AgiConfiguration -{ +public interface AgiConfiguration { - List> getAgiHandlers(); + List> getAgiHandlers(); } diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java b/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java index 3f1bf3038..ccd8cf424 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/AgiMappingStragegy.java @@ -1,33 +1,28 @@ /* * Copyright 2004-2006 by S. Brett Sutton. Commercial support is provided by * Asterisk I.T. http://www.asteriskit.com.au - * + * * The contents of this file are subject to a modified GPL Version 2 License or * later version at your discretion. - * + * * The sole modification to the GPL is a limitation on use. - * + * * The limitation is that AsterFax (and its source components) may only be used * on a single Channel as defined in AsterFax.xml. The implications of the * limitation is that the free verions of AsterFax may only be used to send or * receive a single fax at a time. - * + * * Any copied or modified versions of the AsterFax source must retain this * limitation. - * + * * If you wish to use multiple channels then you can purchase a commercial * license by emailing sales@asteriskit.com.au - * + * * Contributor(s): all the names of the contributors are added in the source * code where applicable. */ package org.asteriskjava.pbx.agi.config; -import java.lang.reflect.InvocationTargetException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - import org.asteriskjava.fastagi.AgiChannel; import org.asteriskjava.fastagi.AgiRequest; import org.asteriskjava.fastagi.AgiScript; @@ -35,34 +30,34 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class AgiMappingStragegy implements MappingStrategy -{ +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class AgiMappingStragegy implements MappingStrategy { static private final Log logger = LogFactory.getLog(AgiMappingStragegy.class); private Map> handlers = new HashMap<>(); @Override - public AgiScript determineScript(AgiRequest request, AgiChannel channel) - { + public AgiScript determineScript(AgiRequest request, AgiChannel channel) { AgiScript ret = null; String script = request.getScript(); - if (script.indexOf(".") != -1) - { + if (script.indexOf(".") != -1) { script = script.substring(0, script.indexOf(".")); } - if (script.startsWith("/")) - { + if (script.startsWith("/")) { // this is specifically for the "FastAgiSimulator" script = script.substring(1); } Iterator itr = request.getParameterMap().keySet().iterator(); logger.debug("*********************************"); logger.debug("script " + script); - while (itr.hasNext()) - { + while (itr.hasNext()) { String key = itr.next(); String val = request.getParameter(key); if (key.compareToIgnoreCase("cardNumber") == 0) @@ -71,15 +66,11 @@ public AgiScript determineScript(AgiRequest request, AgiChannel channel) } logger.debug("******"); - if (handlers.containsKey(script)) - { - try - { + if (handlers.containsKey(script)) { + try { ret = handlers.get(script).getDeclaredConstructor().newInstance(); - } - catch (IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException - | InstantiationException | IllegalAccessException e) - { + } catch (IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException + | InstantiationException | IllegalAccessException e) { logger.error(e, e); } @@ -91,7 +82,7 @@ public AgiScript determineScript(AgiRequest request, AgiChannel channel) /** * this will be a pluggable extension system for the agi core, it's still a * work in progress and is not useable - * + * * @param handler * @throws DuplicateScriptException * @throws IllegalAccessException @@ -102,23 +93,20 @@ public AgiScript determineScript(AgiRequest request, AgiChannel channel) * @throws IllegalArgumentException */ @SuppressWarnings("unchecked") - public void addServiceAgiScript(Class< ? extends ServiceAgiScript> handler) + public void addServiceAgiScript(Class handler) throws DuplicateScriptException, InstantiationException, IllegalAccessException, IllegalArgumentException, - InvocationTargetException, NoSuchMethodException, SecurityException - { + InvocationTargetException, NoSuchMethodException, SecurityException { logger.info("loading agi handler {}" + handler.getCanonicalName()); ServiceAgiScript tmpHandler = handler.getDeclaredConstructor().newInstance(); - if (handlers.containsKey(tmpHandler.getScriptName())) - { + if (handlers.containsKey(tmpHandler.getScriptName())) { throw new DuplicateScriptException("Script " + tmpHandler.getScriptName() + " already exists"); } String[] parameters = tmpHandler.getParameters(); String sample = "Agi(agi://localhost/" + tmpHandler.getScriptName() + ".agi"; logger.info("********************************************"); logger.info("registered new agi script: " + tmpHandler.getScriptName()); - for (int i = 0; i < parameters.length; i++) - { + for (int i = 0; i < parameters.length; i++) { logger.info("parameter: " + parameters[i]); if (i == 0) sample += "?" + parameters[i] + "=testdata"; diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java b/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java index aeccd167e..aef536075 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/ConfiguableAGIServer.java @@ -1,19 +1,19 @@ /* - * Copyright 2004-2006 by S. Brett Sutton. + * Copyright 2004-2006 by S. Brett Sutton. * Commercial support is provided by Asterisk I.T. http://www.asteriskit.com.au * - * The contents of this file are subject to a modified GPL Version 2 License + * The contents of this file are subject to a modified GPL Version 2 License * or later version at your discretion. - * + * * The sole modification to the GPL is a limitation on use. - * - * The limitation is that AsterFax (and its source components) may only be used on a single Channel + * + * The limitation is that AsterFax (and its source components) may only be used on a single Channel * as defined in AsterFax.xml. * The implications of the limitation is that the free verions of AsterFax may only be used to send * or receive a single fax at a time. * * Any copied or modified versions of the AsterFax source must retain this limitation. - * + * * If you wish to use multiple channels then you can purchase a commercial license * by emailing sales@asteriskit.com.au * @@ -22,20 +22,17 @@ */ package org.asteriskjava.pbx.agi.config; -import java.lang.reflect.InvocationTargetException; -import java.util.List; +import org.asteriskjava.fastagi.DefaultAgiServer; import javax.naming.ConfigurationException; +import java.lang.reflect.InvocationTargetException; +import java.util.List; -import org.asteriskjava.fastagi.DefaultAgiServer; - -public class ConfiguableAGIServer extends DefaultAgiServer implements Runnable -{ +public class ConfiguableAGIServer extends DefaultAgiServer implements Runnable { public ConfiguableAGIServer(AgiConfiguration configuration) throws DuplicateScriptException, InstantiationException, IllegalAccessException, ConfigurationException, - IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException - { + IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { AgiMappingStragegy mappingStrategy = new AgiMappingStragegy(); setMaximumPoolSize(500); loadHandlers(mappingStrategy, configuration); @@ -47,11 +44,9 @@ public ConfiguableAGIServer(AgiConfiguration configuration) private void loadHandlers(AgiMappingStragegy mappingStrategy, AgiConfiguration configuration) throws DuplicateScriptException, InstantiationException, IllegalAccessException, IllegalArgumentException, - InvocationTargetException, NoSuchMethodException, SecurityException - { - List> handlers = configuration.getAgiHandlers(); - for (Class< ? extends ServiceAgiScript> clazz : handlers) - { + InvocationTargetException, NoSuchMethodException, SecurityException { + List> handlers = configuration.getAgiHandlers(); + for (Class clazz : handlers) { mappingStrategy.addServiceAgiScript(clazz); } } diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/DuplicateScriptException.java b/src/main/java/org/asteriskjava/pbx/agi/config/DuplicateScriptException.java index 9221273aa..ed091c99f 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/DuplicateScriptException.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/DuplicateScriptException.java @@ -1,14 +1,12 @@ package org.asteriskjava.pbx.agi.config; -public class DuplicateScriptException extends Exception -{ - public DuplicateScriptException(String string) - { - super(string); +public class DuplicateScriptException extends Exception { + public DuplicateScriptException(String string) { + super(string); } /** - * - */ + * + */ private static final long serialVersionUID = -3931649299622511878L; } diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScript.java b/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScript.java index 23f29de2d..ffb52f82b 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScript.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScript.java @@ -2,8 +2,7 @@ import org.asteriskjava.fastagi.AgiScript; -public interface ServiceAgiScript extends AgiScript -{ +public interface ServiceAgiScript extends AgiScript { String getScriptName(); diff --git a/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScriptImpl.java b/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScriptImpl.java index 286114f7e..16f865b6e 100644 --- a/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScriptImpl.java +++ b/src/main/java/org/asteriskjava/pbx/agi/config/ServiceAgiScriptImpl.java @@ -15,17 +15,15 @@ *
    * Requires an implementing agi to provide it's name and parameter list via * getScriptName() and getParameters. - * + * * @author rsutton */ -abstract public class ServiceAgiScriptImpl extends BaseAgiScript implements ServiceAgiScript -{ +abstract public class ServiceAgiScriptImpl extends BaseAgiScript implements ServiceAgiScript { static transient Log logger = LogFactory.getLog(ServiceAgiScriptImpl.class); protected AgiRequest request; protected AgiChannel channel; - public synchronized void service(AgiRequest request, AgiChannel channel) throws AgiException - { + public synchronized void service(AgiRequest request, AgiChannel channel) throws AgiException { this.request = request; this.channel = channel; service(); @@ -34,21 +32,19 @@ public synchronized void service(AgiRequest request, AgiChannel channel) throws /** * field variables request and channel will be set prior to calling * service() AgiRequest request AgiChannel channel - * + * * @throws AgiException */ public abstract void service() throws AgiException; - protected String required(String name, String parameter) throws AgiException - { + protected String required(String name, String parameter) throws AgiException { if (parameter == null || parameter.length() == 0) throw new AgiException("Required parameter " + name + " missing."); return parameter; } - protected String getParameter(String name) throws AgiException - { + protected String getParameter(String name) throws AgiException { return required(name, request.getParameter(name)); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/AbstractManagerAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/AbstractManagerAction.java index 04c33680a..30f7a8f62 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/AbstractManagerAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/AbstractManagerAction.java @@ -5,18 +5,16 @@ /** * Automatically generates a globally unique action id (based on the systems mac * address - * + * * @author bsutton */ -abstract public class AbstractManagerAction implements ManagerAction -{ +abstract public class AbstractManagerAction implements ManagerAction { private final static AtomicLong _nextActionId = new AtomicLong(); private final String _actionId = "" + _nextActionId.incrementAndGet(); - public String getActionId() - { + public String getActionId() { return this._actionId; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/BridgeAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/BridgeAction.java index 2961cf4bb..b0bd14a69 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/BridgeAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/BridgeAction.java @@ -2,30 +2,26 @@ import org.asteriskjava.pbx.Channel; -public class BridgeAction extends AbstractManagerAction -{ +public class BridgeAction extends AbstractManagerAction { - private final Channel _lhs; - private final Channel _rhs; + private final Channel _lhs; + private final Channel _rhs; - public BridgeAction(final Channel lhs, final Channel rhs) - { - this._lhs = lhs; - this._rhs = rhs; - } + public BridgeAction(final Channel lhs, final Channel rhs) { + this._lhs = lhs; + this._rhs = rhs; + } - @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.BridgeAction action = new org.asteriskjava.manager.action.BridgeAction(); - action.setActionId(this.getActionId()); - action.setChannel1(this._lhs.getChannelName()); - action.setChannel2(this._rhs.getChannelName()); - return action; - } + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() { + final org.asteriskjava.manager.action.BridgeAction action = new org.asteriskjava.manager.action.BridgeAction(); + action.setActionId(this.getActionId()); + action.setChannel1(this._lhs.getChannelName()); + action.setChannel2(this._rhs.getChannelName()); + return action; + } - public String toString() - { - return "BridgeAction: lhs=" + this._lhs + " rhs=" + this._rhs; //$NON-NLS-1$ //$NON-NLS-2$ - } + public String toString() { + return "BridgeAction: lhs=" + this._lhs + " rhs=" + this._rhs; //$NON-NLS-1$ //$NON-NLS-2$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/CommandAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/CommandAction.java index 2c6b37988..128fa5b44 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/CommandAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/CommandAction.java @@ -1,32 +1,27 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; -public class CommandAction extends AbstractManagerAction -{ - - private String _command; - - public CommandAction(final String command) - { - this._command = command; - } - - public CommandAction() - { - } - - @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.CommandAction action = new org.asteriskjava.manager.action.CommandAction(); - action.setCommand(this._command); - action.setActionId(this.getActionId()); - - return action; - } - - public String toString() - { - return "CommandAction: command=" + this._command; //$NON-NLS-1$ - } +public class CommandAction extends AbstractManagerAction { + + private String _command; + + public CommandAction(final String command) { + this._command = command; + } + + public CommandAction() { + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() { + final org.asteriskjava.manager.action.CommandAction action = new org.asteriskjava.manager.action.CommandAction(); + action.setCommand(this._command); + action.setActionId(this.getActionId()); + + return action; + } + + public String toString() { + return "CommandAction: command=" + this._command; //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeKickAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeKickAction.java index ae82454b6..21d813898 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeKickAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeKickAction.java @@ -1,20 +1,17 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; -public class ConfbridgeKickAction extends AbstractManagerAction -{ +public class ConfbridgeKickAction extends AbstractManagerAction { private final String channel; private String room; - public ConfbridgeKickAction(final String room, String channel) - { + public ConfbridgeKickAction(final String room, String channel) { this.channel = channel; this.room = room; } @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { + public org.asteriskjava.manager.action.ManagerAction getAJAction() { final org.asteriskjava.manager.action.ConfbridgeKickAction action = new org.asteriskjava.manager.action.ConfbridgeKickAction(); action.setActionId(this.getActionId()); action.setChannel(channel); @@ -23,13 +20,11 @@ public org.asteriskjava.manager.action.ManagerAction getAJAction() return action; } - public String getChannel() - { + public String getChannel() { return channel; } - public String getRoom() - { + public String getRoom() { return room; } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeListAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeListAction.java index af3535b0e..7be64573b 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeListAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ConfbridgeListAction.java @@ -2,19 +2,16 @@ import org.asteriskjava.manager.action.ManagerAction; -public class ConfbridgeListAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class ConfbridgeListAction extends AbstractManagerAction implements EventGeneratingAction { @Override - public ManagerAction getAJAction() - { + public ManagerAction getAJAction() { return new org.asteriskjava.manager.action.ConfbridgeListAction(); } // Logger logger = LogManager.getLogger(); @Override - public org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction() - { + public org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction() { org.asteriskjava.manager.action.ConfbridgeListAction action = new org.asteriskjava.manager.action.ConfbridgeListAction(); action.setActionId(this.getActionId()); return action; diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/DbGetAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/DbGetAction.java index 75ef3a8b5..549cc25d6 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/DbGetAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/DbGetAction.java @@ -2,32 +2,28 @@ import org.asteriskjava.manager.action.ManagerAction; -public class DbGetAction extends AbstractManagerAction -{ - - private final String _key; - private final String _family; - - public DbGetAction(final String family, final String key) - { - this._family = family; - this._key = key; - } - - @Override - public ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.DbGetAction action = new org.asteriskjava.manager.action.DbGetAction(); - action.setActionId(this.getActionId()); - action.setKey(this._key); - action.setFamily(this._family); - - return action; - } - - public String toString() - { - return "DbGetAction: key=" + this._key + " family=" + this._family; //$NON-NLS-1$ //$NON-NLS-2$ - } +public class DbGetAction extends AbstractManagerAction { + + private final String _key; + private final String _family; + + public DbGetAction(final String family, final String key) { + this._family = family; + this._key = key; + } + + @Override + public ManagerAction getAJAction() { + final org.asteriskjava.manager.action.DbGetAction action = new org.asteriskjava.manager.action.DbGetAction(); + action.setActionId(this.getActionId()); + action.setKey(this._key); + action.setFamily(this._family); + + return action; + } + + public String toString() { + return "DbGetAction: key=" + this._key + " family=" + this._family; //$NON-NLS-1$ //$NON-NLS-2$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/EventGeneratingAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/EventGeneratingAction.java index 2f554fca3..781c11b44 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/EventGeneratingAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/EventGeneratingAction.java @@ -1,8 +1,7 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; -public interface EventGeneratingAction -{ +public interface EventGeneratingAction { - org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction(); + org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction(); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/GetVarAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/GetVarAction.java index a222726be..1680df51f 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/GetVarAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/GetVarAction.java @@ -2,32 +2,28 @@ import org.asteriskjava.pbx.Channel; -public class GetVarAction extends AbstractManagerAction -{ - - private final Channel _channel; - private String _variableName; - - public GetVarAction(final Channel channel, String variableName) - { - this._channel = channel; - this._variableName = variableName; - } - - @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.GetVarAction action = new org.asteriskjava.manager.action.GetVarAction(); - action.setActionId(this.getActionId()); - action.setChannel(this._channel.getChannelName()); - action.setVariable(this._variableName); - - return action; - } - - public String toString() - { - return "GetVarAction: channel=" + this._channel + " variableName=" + this._variableName; //$NON-NLS-1$ //$NON-NLS-2$ - } +public class GetVarAction extends AbstractManagerAction { + + private final Channel _channel; + private String _variableName; + + public GetVarAction(final Channel channel, String variableName) { + this._channel = channel; + this._variableName = variableName; + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() { + final org.asteriskjava.manager.action.GetVarAction action = new org.asteriskjava.manager.action.GetVarAction(); + action.setActionId(this.getActionId()); + action.setChannel(this._channel.getChannelName()); + action.setVariable(this._variableName); + + return action; + } + + public String toString() { + return "GetVarAction: channel=" + this._channel + " variableName=" + this._variableName; //$NON-NLS-1$ //$NON-NLS-2$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/HangupAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/HangupAction.java index 8bcf97441..bbbcfdc73 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/HangupAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/HangupAction.java @@ -2,36 +2,31 @@ import org.asteriskjava.pbx.Channel; -public class HangupAction extends AbstractManagerAction -{ - - private final Channel _channel; - private Integer _cause; - - public HangupAction(final Channel channel) - { - this._channel = channel; - } - - @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.HangupAction action = new org.asteriskjava.manager.action.HangupAction(); - action.setActionId(this.getActionId()); - action.setCause(this._cause); - action.setChannel(this._channel.getChannelName()); - - return action; - } - - public Channel getChannel() - { - return this._channel; - } - - public String toString() - { - return "HangupAction: channel=" + this._channel + " cause=" + this._cause; //$NON-NLS-1$ //$NON-NLS-2$ - } +public class HangupAction extends AbstractManagerAction { + + private final Channel _channel; + private Integer _cause; + + public HangupAction(final Channel channel) { + this._channel = channel; + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() { + final org.asteriskjava.manager.action.HangupAction action = new org.asteriskjava.manager.action.HangupAction(); + action.setActionId(this.getActionId()); + action.setCause(this._cause); + action.setChannel(this._channel.getChannelName()); + + return action; + } + + public Channel getChannel() { + return this._channel; + } + + public String toString() { + return "HangupAction: channel=" + this._channel + " cause=" + this._cause; //$NON-NLS-1$ //$NON-NLS-2$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ListCommandsAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ListCommandsAction.java index cd2c77a1a..df9d7f195 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ListCommandsAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ListCommandsAction.java @@ -1,19 +1,16 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; -public class ListCommandsAction extends AbstractManagerAction -{ +public class ListCommandsAction extends AbstractManagerAction { @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { + public org.asteriskjava.manager.action.ManagerAction getAJAction() { final org.asteriskjava.manager.action.ListCommandsAction action = new org.asteriskjava.manager.action.ListCommandsAction(); action.setActionId(this.getActionId()); return action; } - public String toString() - { + public String toString() { return "ListCommandsAction"; //$NON-NLS-1$ } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ManagerAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ManagerAction.java index a573d7c0d..66dd34fbf 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ManagerAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/ManagerAction.java @@ -1,9 +1,8 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; -public interface ManagerAction -{ +public interface ManagerAction { - // Converts an iManagerAction into an asterisk-java ManagerAction. - org.asteriskjava.manager.action.ManagerAction getAJAction(); + // Converts an iManagerAction into an asterisk-java ManagerAction. + org.asteriskjava.manager.action.ManagerAction getAJAction(); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/MonitorAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/MonitorAction.java index 7d7c1a6cf..521a68804 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/MonitorAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/MonitorAction.java @@ -2,35 +2,31 @@ import org.asteriskjava.pbx.Channel; -public class MonitorAction extends AbstractManagerAction -{ - - private final Channel _channel; - private final String _file; - private final String _format; - private final boolean _mix; - - public MonitorAction(final Channel channel, final String file, final String format, final boolean mix) - { - this._channel = channel; - this._file = file; - this._format = format; - this._mix = mix; - } - - @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.MonitorAction action = new org.asteriskjava.manager.action.MonitorAction( - this._channel.getChannelName(), this._file, this._format, this._mix); - action.setActionId(this.getActionId()); - - return action; - } - - public String toString() - { - return "MonitorAction: channel=" + this._channel + " file=" + this._file; //$NON-NLS-1$ //$NON-NLS-2$ - } +public class MonitorAction extends AbstractManagerAction { + + private final Channel _channel; + private final String _file; + private final String _format; + private final boolean _mix; + + public MonitorAction(final Channel channel, final String file, final String format, final boolean mix) { + this._channel = channel; + this._file = file; + this._format = format; + this._mix = mix; + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() { + final org.asteriskjava.manager.action.MonitorAction action = new org.asteriskjava.manager.action.MonitorAction( + this._channel.getChannelName(), this._file, this._format, this._mix); + action.setActionId(this.getActionId()); + + return action; + } + + public String toString() { + return "MonitorAction: channel=" + this._channel + " file=" + this._file; //$NON-NLS-1$ //$NON-NLS-2$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java index 2c507d8b5..75184235c 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/OriginateAction.java @@ -1,14 +1,13 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; -import java.util.Map; - import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.internal.asterisk.CallerIDImpl; -public class OriginateAction extends AbstractManagerAction -{ +import java.util.Map; + +public class OriginateAction extends AbstractManagerAction { /** * Asterisk uses the term channel but it actually appears to be an endpoint @@ -39,26 +38,22 @@ public class OriginateAction extends AbstractManagerAction private String channelId; private String otherChannelId; - public OriginateAction() - { + public OriginateAction() { } - public String toString() - { + public String toString() { return "OriginateAction: endPoint/Channel=" + (this._endPoint == null ? this._channel : this._endPoint) + " context=" //$NON-NLS-1$ //$NON-NLS-2$ + this._context + " extension=" + this._extension + " callerId=" + this._callerID; //$NON-NLS-1$ //$NON-NLS-2$ } @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { + public org.asteriskjava.manager.action.ManagerAction getAJAction() { final org.asteriskjava.manager.action.OriginateAction action = new org.asteriskjava.manager.action.OriginateAction(); action.setActionId(getActionId()); // Was the channel or an end point passed. String channel = (this._channel != null ? this._channel.getChannelName() : this._endPoint.getFullyQualifiedName()); - if (this._option != null) - { + if (this._option != null) { channel += this._option; } action.setChannel((channel)); @@ -77,87 +72,71 @@ public org.asteriskjava.manager.action.ManagerAction getAJAction() return action; } - public void setEndPoint(final EndPoint endPoint) - { + public void setEndPoint(final EndPoint endPoint) { this._endPoint = endPoint; this._channel = null; } - public void setChannel(Channel channel) - { + public void setChannel(Channel channel) { this._channel = channel; this._endPoint = null; } - public void setOption(final String option) - { + public void setOption(final String option) { this._option = option; } - public void setContext(final String context) - { + public void setContext(final String context) { this._context = context; } - public void setExten(final EndPoint extension) - { + public void setExten(final EndPoint extension) { this._extension = extension; } - public void setPriority(final int priority) - { + public void setPriority(final int priority) { this._priority = priority; } - public void setCallingPres(final int callingPres) - { + public void setCallingPres(final int callingPres) { this._callingPres = callingPres; } - public void setCallerId(final CallerID callerID) - { + public void setCallerId(final CallerID callerID) { this._callerID = callerID; } - public void setVariables(final Map variables) - { - if (_variables == null) - { + public void setVariables(final Map variables) { + if (_variables == null) { this._variables = variables; - } - else - { + } else { this._variables.putAll(variables); } } - public void setAsync(final boolean async) - { + public void setAsync(final boolean async) { this._async = async; } - public void setTimeout(final long timeout) - { + public void setTimeout(final long timeout) { this._timeout = timeout; } - public void setChannelId(String channelId) - { + public void setChannelId(String channelId) { this.channelId = channelId; } - public void setOtherChannelId(String otherChannelId) - { + public void setOtherChannelId(String otherChannelId) { this.otherChannelId = otherChannelId; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PingAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PingAction.java index 320526670..9c2e46b02 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PingAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PingAction.java @@ -1,18 +1,15 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; -public class PingAction extends AbstractManagerAction -{ +public class PingAction extends AbstractManagerAction { @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { + public org.asteriskjava.manager.action.ManagerAction getAJAction() { final org.asteriskjava.manager.action.PingAction action = new org.asteriskjava.manager.action.PingAction(); action.setActionId(this.getActionId()); return action; } - public String toString() - { + public String toString() { return "PingAction"; //$NON-NLS-1$ } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PlayDtmfAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PlayDtmfAction.java index 59218af9e..7c0082fc5 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PlayDtmfAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/PlayDtmfAction.java @@ -4,32 +4,28 @@ import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.DTMFTone; -public class PlayDtmfAction extends AbstractManagerAction -{ - - private final Channel _channel; - private final DTMFTone _tone; - - public PlayDtmfAction(final Channel channel, final DTMFTone tone) - { - this._channel = channel; - this._tone = tone; - } - - @Override - public ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.PlayDtmfAction action = new org.asteriskjava.manager.action.PlayDtmfAction(); - action.setActionId(this.getActionId()); - action.setChannel(this._channel.getChannelName()); - action.setDigit(this._tone.toString()); - - return action; - } - - public String toString() - { - return "PlayDtmfAction: channel=" + this._channel + " tone=" + this._tone; //$NON-NLS-1$ //$NON-NLS-2$ - } +public class PlayDtmfAction extends AbstractManagerAction { + + private final Channel _channel; + private final DTMFTone _tone; + + public PlayDtmfAction(final Channel channel, final DTMFTone tone) { + this._channel = channel; + this._tone = tone; + } + + @Override + public ManagerAction getAJAction() { + final org.asteriskjava.manager.action.PlayDtmfAction action = new org.asteriskjava.manager.action.PlayDtmfAction(); + action.setActionId(this.getActionId()); + action.setChannel(this._channel.getChannelName()); + action.setDigit(this._tone.toString()); + + return action; + } + + public String toString() { + return "PlayDtmfAction: channel=" + this._channel + " tone=" + this._tone; //$NON-NLS-1$ //$NON-NLS-2$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/RedirectAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/RedirectAction.java index 52805adfa..d2dd82d2f 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/RedirectAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/RedirectAction.java @@ -3,8 +3,7 @@ import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.EndPoint; -public class RedirectAction extends AbstractManagerAction -{ +public class RedirectAction extends AbstractManagerAction { private final Channel _channel; private final String _context; @@ -15,18 +14,14 @@ public class RedirectAction extends AbstractManagerAction private EndPoint _extraExten; private Integer _extraPriority; - public RedirectAction(final Channel channel, final String context, final EndPoint extension, final int priority) - { - if (channel == null) - { + public RedirectAction(final Channel channel, final String context, final EndPoint extension, final int priority) { + if (channel == null) { throw new NullPointerException("channel cannot be null"); } - if (context == null) - { + if (context == null) { throw new NullPointerException("context cannot be null"); } - if (extension == null) - { + if (extension == null) { throw new NullPointerException("extension cannot be null"); } @@ -37,8 +32,7 @@ public RedirectAction(final Channel channel, final String context, final EndPoin } @Override - public String toString() - { + public String toString() { return "RedirectAction: chanel=" + this._channel + " context=" + this._context //$NON-NLS-1$ //$NON-NLS-2$ + " exten=" + this._exten + " priority=" + this._priority //$NON-NLS-1$ //$NON-NLS-2$ + " extraContext=" + this._extraContext //$NON-NLS-1$ @@ -47,8 +41,7 @@ public String toString() } @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { + public org.asteriskjava.manager.action.ManagerAction getAJAction() { final org.asteriskjava.manager.action.RedirectAction action = new org.asteriskjava.manager.action.RedirectAction(); action.setActionId(this.getActionId()); action.setChannel(this._channel.getChannelName().toLowerCase()); @@ -65,23 +58,19 @@ public org.asteriskjava.manager.action.ManagerAction getAJAction() return action; } - public void setExtraChannel(final Channel extraChannel) - { + public void setExtraChannel(final Channel extraChannel) { this._extraChannel = extraChannel; } - public void setExtraContext(final String extraContext) - { + public void setExtraContext(final String extraContext) { this._extraContext = extraContext; } - public void setExtraExten(final EndPoint extraExten) - { + public void setExtraExten(final EndPoint extraExten) { this._extraExten = extraExten; } - public void setExtraPriority(final int priority) - { + public void setExtraPriority(final int priority) { this._extraPriority = priority; } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SetVarAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SetVarAction.java index 4f89aa5a4..9657f32aa 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SetVarAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SetVarAction.java @@ -2,41 +2,36 @@ import org.asteriskjava.pbx.Channel; -public class SetVarAction extends AbstractManagerAction -{ - - private final Channel _channel; - private String _variableName; - private final String _value; - - public SetVarAction(final Channel channel, final String variableName, final String value) - { - this._channel = channel; - this._variableName = variableName; - this._value = value; - } - - @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.SetVarAction action = new org.asteriskjava.manager.action.SetVarAction(); - action.setActionId(this.getActionId()); - action.setChannel(this._channel.getChannelName()); - action.setVariable(this._variableName); - action.setValue(this._value); - - return action; - } - - public void setVariable(final String variableName) - { - this._variableName = variableName; - - } - - public String toString() - { - return "SetVarAction: channel=" + this._channel + " variableName=" + this._variableName + " value=" + this._value; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } +public class SetVarAction extends AbstractManagerAction { + + private final Channel _channel; + private String _variableName; + private final String _value; + + public SetVarAction(final Channel channel, final String variableName, final String value) { + this._channel = channel; + this._variableName = variableName; + this._value = value; + } + + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() { + final org.asteriskjava.manager.action.SetVarAction action = new org.asteriskjava.manager.action.SetVarAction(); + action.setActionId(this.getActionId()); + action.setChannel(this._channel.getChannelName()); + action.setVariable(this._variableName); + action.setValue(this._value); + + return action; + } + + public void setVariable(final String variableName) { + this._variableName = variableName; + + } + + public String toString() { + return "SetVarAction: channel=" + this._channel + " variableName=" + this._variableName + " value=" + this._value; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipPeersAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipPeersAction.java index b24ee11be..4ff04c8f0 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipPeersAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipPeersAction.java @@ -1,29 +1,24 @@ package org.asteriskjava.pbx.asterisk.wrap.actions; -public class SipPeersAction extends AbstractManagerAction implements EventGeneratingAction -{ +public class SipPeersAction extends AbstractManagerAction implements EventGeneratingAction { - public SipPeersAction() - { - } + public SipPeersAction() { + } - @Override - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { - return new org.asteriskjava.manager.action.SipPeersAction(); - } + @Override + public org.asteriskjava.manager.action.ManagerAction getAJAction() { + return new org.asteriskjava.manager.action.SipPeersAction(); + } - @Override - public org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction() - { - org.asteriskjava.manager.action.SipPeersAction action = new org.asteriskjava.manager.action.SipPeersAction(); - action.setActionId(this.getActionId()); - return action; - } + @Override + public org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction() { + org.asteriskjava.manager.action.SipPeersAction action = new org.asteriskjava.manager.action.SipPeersAction(); + action.setActionId(this.getActionId()); + return action; + } - public String toString() - { - return "SipPeersAction"; //$NON-NLS-1$ - } + public String toString() { + return "SipPeersAction"; //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipShowPeerAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipShowPeerAction.java index f29bbfd1c..1b524b8e1 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipShowPeerAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/SipShowPeerAction.java @@ -3,28 +3,24 @@ import org.asteriskjava.manager.action.ManagerAction; import org.asteriskjava.pbx.EndPoint; -public class SipShowPeerAction extends AbstractManagerAction -{ +public class SipShowPeerAction extends AbstractManagerAction { - private final EndPoint _peer; + private final EndPoint _peer; - public SipShowPeerAction(final EndPoint peer) - { - this._peer = peer; - } + public SipShowPeerAction(final EndPoint peer) { + this._peer = peer; + } - @Override - public ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.SipShowPeerAction action = new org.asteriskjava.manager.action.SipShowPeerAction(); - action.setActionId(this.getActionId()); - action.setPeer(this._peer.getSimpleName()); - return action; - } + @Override + public ManagerAction getAJAction() { + final org.asteriskjava.manager.action.SipShowPeerAction action = new org.asteriskjava.manager.action.SipShowPeerAction(); + action.setActionId(this.getActionId()); + action.setPeer(this._peer.getSimpleName()); + return action; + } - public String toString() - { - return "SipShowPeerAction: peer=" + this._peer; //$NON-NLS-1$ - } + public String toString() { + return "SipShowPeerAction: peer=" + this._peer; //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/StatusAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/StatusAction.java index 8a10e941c..be7ab9b1f 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/StatusAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/StatusAction.java @@ -5,50 +5,44 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class StatusAction extends AbstractManagerAction implements EventGeneratingAction -{ - // used when the status of a single channel has been requested. - final private Channel _channel; - - public StatusAction() - { - this._channel = null; - } - - public StatusAction(Channel channel) - { - AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - - // channel specific request only available since 1.6 - if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) - this._channel = channel; - else - this._channel = null; - } - - public org.asteriskjava.manager.action.ManagerAction getAJAction() - { - final org.asteriskjava.manager.action.StatusAction action; - if (_channel == null) - action = new org.asteriskjava.manager.action.StatusAction(); - else - action = new org.asteriskjava.manager.action.StatusAction(_channel.getChannelName()); - - return action; - } - - @Override - public org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction() - { - final org.asteriskjava.manager.action.StatusAction action = (org.asteriskjava.manager.action.StatusAction) getAJAction(); - action.setActionId(getActionId()); - - return action; - } - - public String toString() - { - return "StatusAction"; //$NON-NLS-1$ - } +public class StatusAction extends AbstractManagerAction implements EventGeneratingAction { + // used when the status of a single channel has been requested. + final private Channel _channel; + + public StatusAction() { + this._channel = null; + } + + public StatusAction(Channel channel) { + AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); + + // channel specific request only available since 1.6 + if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) + this._channel = channel; + else + this._channel = null; + } + + public org.asteriskjava.manager.action.ManagerAction getAJAction() { + final org.asteriskjava.manager.action.StatusAction action; + if (_channel == null) + action = new org.asteriskjava.manager.action.StatusAction(); + else + action = new org.asteriskjava.manager.action.StatusAction(_channel.getChannelName()); + + return action; + } + + @Override + public org.asteriskjava.manager.action.EventGeneratingAction getAJEventGeneratingAction() { + final org.asteriskjava.manager.action.StatusAction action = (org.asteriskjava.manager.action.StatusAction) getAJAction(); + action.setActionId(getActionId()); + + return action; + } + + public String toString() { + return "StatusAction"; //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/UserEventAction.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/UserEventAction.java index ad8c045bb..9ef4d54fb 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/UserEventAction.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/actions/UserEventAction.java @@ -2,23 +2,19 @@ import org.asteriskjava.pbx.asterisk.wrap.userEvents.UserEvent; -abstract public class UserEventAction extends AbstractManagerAction -{ +abstract public class UserEventAction extends AbstractManagerAction { private String _actionId; - public UserEventAction(UserEvent event) - { + public UserEventAction(UserEvent event) { // NOOP } - public void setActionId(String actionId) - { + public void setActionId(String actionId) { this._actionId = actionId; } - public String getActionId() - { + public String getActionId() { return this._actionId; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractChannelStateEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractChannelStateEvent.java index 8e192da87..477f58890 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractChannelStateEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractChannelStateEvent.java @@ -4,8 +4,7 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public abstract class AbstractChannelStateEvent extends ChannelEventHelper -{ +public abstract class AbstractChannelStateEvent extends ChannelEventHelper { private static final long serialVersionUID = 1L; @@ -15,20 +14,17 @@ public abstract class AbstractChannelStateEvent extends ChannelEventHelper private final ChannelState channelState; private final String channelStateDesc; - AbstractChannelStateEvent(final org.asteriskjava.manager.event.AbstractChannelStateEvent event) throws InvalidChannelName - { + AbstractChannelStateEvent(final org.asteriskjava.manager.event.AbstractChannelStateEvent event) throws InvalidChannelName { super(event); this.channelState = ChannelState.valueOfDesc(event.getChannelStateDesc()); this.channelStateDesc = event.getChannelStateDesc(); } - public ChannelState getChannelState() - { + public ChannelState getChannelState() { return this.channelState; } - public String getChannelStateDesc() - { + public String getChannelStateDesc() { return this.channelStateDesc; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractMeetMeEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractMeetMeEvent.java index 0984a2ab7..723a080ed 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractMeetMeEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractMeetMeEvent.java @@ -4,8 +4,7 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class AbstractMeetMeEvent extends ChannelEventHelper -{ +public class AbstractMeetMeEvent extends ChannelEventHelper { private static final long serialVersionUID = 1L; @SuppressWarnings("unused") @@ -14,20 +13,17 @@ public class AbstractMeetMeEvent extends ChannelEventHelper private final String meetMe; private final Integer userNum; - public AbstractMeetMeEvent(final org.asteriskjava.manager.event.AbstractMeetMeEvent event) throws InvalidChannelName - { + public AbstractMeetMeEvent(final org.asteriskjava.manager.event.AbstractMeetMeEvent event) throws InvalidChannelName { super(event.getChannel(), event.getUniqueId()); this.meetMe = event.getMeetMe(); this.userNum = event.getUser(); } - public String getMeetMe() - { + public String getMeetMe() { return this.meetMe; } - public Integer getUserNum() - { + public Integer getUserNum() { return this.userNum; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractParkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractParkedCallEvent.java index 25902d984..921424b68 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AbstractParkedCallEvent.java @@ -4,8 +4,7 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class AbstractParkedCallEvent extends ChannelEventHelper -{ +public class AbstractParkedCallEvent extends ChannelEventHelper { private static final long serialVersionUID = 1L; @SuppressWarnings("unused") @@ -14,20 +13,17 @@ public class AbstractParkedCallEvent extends ChannelEventHelper private final String exten; private final String parkingLot; - AbstractParkedCallEvent(final org.asteriskjava.manager.event.AbstractParkedCallEvent event) throws InvalidChannelName - { + AbstractParkedCallEvent(final org.asteriskjava.manager.event.AbstractParkedCallEvent event) throws InvalidChannelName { super(event.getParkeeChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); this.exten = event.getExten(); this.parkingLot = event.getParkingLot(); } - public String getExten() - { + public String getExten() { return this.exten; } - public String getParkingLot() - { + public String getParkingLot() { return this.parkingLot; } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentCalledEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentCalledEvent.java index 1b03387a6..e06daa5cd 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentCalledEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentCalledEvent.java @@ -4,8 +4,7 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class AgentCalledEvent extends ChannelEventHelper -{ +public class AgentCalledEvent extends ChannelEventHelper { private static final long serialVersionUID = 1L; @SuppressWarnings("unused") @@ -15,21 +14,18 @@ public class AgentCalledEvent extends ChannelEventHelper private String agentInterface; - public AgentCalledEvent(final org.asteriskjava.manager.event.AgentCalledEvent event) throws InvalidChannelName - { + public AgentCalledEvent(final org.asteriskjava.manager.event.AgentCalledEvent event) throws InvalidChannelName { super(event.getChannelCalling(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); agentInterface = event.getAgentCalled(); queue = event.getQueue(); } - public String getQueueName() - { + public String getQueueName() { return queue; } - public String getAgentInterface() - { + public String getAgentInterface() { return agentInterface; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentConnectEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentConnectEvent.java index 50fcf1f99..73095025c 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentConnectEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/AgentConnectEvent.java @@ -4,8 +4,7 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class AgentConnectEvent extends ChannelEventHelper -{ +public class AgentConnectEvent extends ChannelEventHelper { private static final long serialVersionUID = 1L; @SuppressWarnings("unused") @@ -15,21 +14,18 @@ public class AgentConnectEvent extends ChannelEventHelper private String agentInterface; - public AgentConnectEvent(final org.asteriskjava.manager.event.AgentConnectEvent event) throws InvalidChannelName - { + public AgentConnectEvent(final org.asteriskjava.manager.event.AgentConnectEvent event) throws InvalidChannelName { super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); agentInterface = event.getInterface(); queue = event.getQueue(); } - public String getQueueName() - { + public String getQueueName() { return queue; } - public String getAgentInterface() - { + public String getAgentInterface() { return agentInterface; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BlindTransferEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BlindTransferEvent.java index 2e12b2e24..9f4689383 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BlindTransferEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BlindTransferEvent.java @@ -1,7 +1,5 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import java.util.Date; - import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; @@ -9,8 +7,9 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class BlindTransferEvent extends ManagerEvent -{ +import java.util.Date; + +public class BlindTransferEvent extends ManagerEvent { private static final long serialVersionUID = 1L; @SuppressWarnings("unused") @@ -22,8 +21,7 @@ public class BlindTransferEvent extends ManagerEvent private final Channel transfererChannel; - public BlindTransferEvent(final org.asteriskjava.manager.event.BlindTransferEvent event) throws InvalidChannelName - { + public BlindTransferEvent(final org.asteriskjava.manager.event.BlindTransferEvent event) throws InvalidChannelName { super(event); rawEvent = event; @@ -34,293 +32,235 @@ public BlindTransferEvent(final org.asteriskjava.manager.event.BlindTransferEven } - public String getBridgeUniqueId() - { + public String getBridgeUniqueId() { return rawEvent.getBridgeUniqueId(); } - public String getBridgeType() - { + public String getBridgeType() { return rawEvent.getBridgeType(); } - public Integer getBridgeNumChannels() - { + public Integer getBridgeNumChannels() { return rawEvent.getBridgeNumChannels(); } - public String getBridgeCreator() - { + public String getBridgeCreator() { return rawEvent.getBridgeCreator(); } - public String getBridgeName() - { + public String getBridgeName() { return rawEvent.getBridgeName(); } - public String getBridgeTechnology() - { + public String getBridgeTechnology() { return rawEvent.getBridgeTechnology(); } - public String getCallerIdName() - { + public String getCallerIdName() { return rawEvent.getCallerIdName(); } - public String getAccountCode() - { + public String getAccountCode() { return rawEvent.getAccountCode(); } - public String getBridgevideosourcemode() - { + public String getBridgevideosourcemode() { return rawEvent.getBridgevideosourcemode(); } - public String getConnectedLineNum() - { + public String getConnectedLineNum() { return rawEvent.getConnectedLineNum(); } - public String getConnectedLineName() - { + public String getConnectedLineName() { return rawEvent.getConnectedLineName(); } - public Integer getPriority() - { + public Integer getPriority() { return rawEvent.getPriority(); } - public Integer getChannelState() - { + public Integer getChannelState() { return rawEvent.getChannelState(); } - public String getChannelStateDesc() - { + public String getChannelStateDesc() { return rawEvent.getChannelStateDesc(); } - public String getExten() - { + public String getExten() { return rawEvent.getExten(); } - public String getCallerIdNum() - { + public String getCallerIdNum() { return rawEvent.getCallerIdNum(); } - public String getContext() - { + public String getContext() { return rawEvent.getContext(); } - public Date getDateReceived() - { + public Date getDateReceived() { return rawEvent.getDateReceived(); } - public String getPrivilege() - { + public String getPrivilege() { return rawEvent.getPrivilege(); } - public String getExtension() - { + public String getExtension() { return rawEvent.getExtension(); } - public String getIsexternal() - { + public String getIsexternal() { return rawEvent.getIsexternal(); } - public String getResult() - { + public String getResult() { return rawEvent.getResult(); } - public final String getServer() - { + public final String getServer() { return rawEvent.getServer(); } - public String getFile() - { + public String getFile() { return rawEvent.getFile(); } - public Integer getLine() - { + public Integer getLine() { return rawEvent.getLine(); } - public String getFunc() - { + public String getFunc() { return rawEvent.getFunc(); } - public Integer getSequenceNumber() - { + public Integer getSequenceNumber() { return rawEvent.getSequenceNumber(); } - public Object getSource() - { + public Object getSource() { return rawEvent.getSource(); } - public String getTransfererUniqueId() - { + public String getTransfererUniqueId() { return rawEvent.getTransfererUniqueId(); } - public String getTransfererConnectedLineNum() - { + public String getTransfererConnectedLineNum() { return rawEvent.getTransfererConnectedLineNum(); } - public String getTransfererConnectedLineName() - { + public String getTransfererConnectedLineName() { return rawEvent.getTransfererConnectedLineName(); } - public String getTransfererCallerIdName() - { + public String getTransfererCallerIdName() { return rawEvent.getTransfererCallerIdName(); } - public String getTransfererCallerIdNum() - { + public String getTransfererCallerIdNum() { return rawEvent.getTransfererCallerIdNum(); } - public Channel getTransfererChannel() - { + public Channel getTransfererChannel() { return transfererChannel; } - public String getTransfererChannelState() - { + public String getTransfererChannelState() { return rawEvent.getTransfererChannelState(); } - public String getTransfererChannelStateDesc() - { + public String getTransfererChannelStateDesc() { return rawEvent.getTransfererChannelStateDesc(); } - public Integer getTransfererPriority() - { + public Integer getTransfererPriority() { return rawEvent.getTransfererPriority(); } - public String getTransfererContext() - { + public String getTransfererContext() { return rawEvent.getTransfererContext(); } - public String getTransfereeUniqueId() - { + public String getTransfereeUniqueId() { return rawEvent.getTransfereeUniqueId(); } - public String getTransfereeConnectedLineNum() - { + public String getTransfereeConnectedLineNum() { return rawEvent.getTransfereeConnectedLineNum(); } - public String getTransfereeConnectedLineName() - { + public String getTransfereeConnectedLineName() { return rawEvent.getTransfereeConnectedLineName(); } - public String getTransfereeCallerIdName() - { + public String getTransfereeCallerIdName() { return rawEvent.getTransfereeCallerIdName(); } - public String getTransfereeCallerIdNum() - { + public String getTransfereeCallerIdNum() { return rawEvent.getTransfereeCallerIdNum(); } - public Channel getTransfereeChannel() - { + public Channel getTransfereeChannel() { return transfereeChannel; } - public String getTransfereeChannelState() - { + public String getTransfereeChannelState() { return rawEvent.getTransfereeChannelState(); } - public String getTransfereeChannelStateDesc() - { + public String getTransfereeChannelStateDesc() { return rawEvent.getTransfereeChannelStateDesc(); } - public Integer getTransfereePriority() - { + public Integer getTransfereePriority() { return rawEvent.getTransfereePriority(); } - public final Double getTimestamp() - { + public final Double getTimestamp() { return rawEvent.getTimestamp(); } - public String getTransfereeContext() - { + public String getTransfereeContext() { return rawEvent.getTransfereeContext(); } - public String getTransfereeExten() - { + public String getTransfereeExten() { return rawEvent.getTransfereeExten(); } - public String getTransfereeLinkedId() - { + public String getTransfereeLinkedId() { return rawEvent.getTransfereeLinkedId(); } - public String getTransfererAccountCode() - { + public String getTransfererAccountCode() { return rawEvent.getTransfererAccountCode(); } - public String getTransfererExten() - { + public String getTransfererExten() { return rawEvent.getTransfererExten(); } - public String getTransfererLanguage() - { + public String getTransfererLanguage() { return rawEvent.getTransfererLanguage(); } - public String getSystemName() - { + public String getSystemName() { return rawEvent.getSystemName(); } - public String getTransfererLinkedId() - { + public String getTransfererLinkedId() { return rawEvent.getTransfererLinkedId(); } - public String getTransfereeLanguage() - { + public String getTransfereeLanguage() { return rawEvent.getTransfereeLanguage(); } - public String toString() - { + public String toString() { return rawEvent.toString(); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BridgeEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BridgeEvent.java index 7119db605..fd572411b 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BridgeEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/BridgeEvent.java @@ -7,15 +7,13 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class BridgeEvent extends ManagerEvent -{ +public class BridgeEvent extends ManagerEvent { private static final long serialVersionUID = 1L; @SuppressWarnings("unused") private static final Log logger = LogFactory.getLog(BridgeEvent.class); - enum BridgeState - { + enum BridgeState { Link, Unlink } @@ -23,8 +21,7 @@ enum BridgeState private final Channel channel1; private final Channel channel2; - public BridgeEvent(final org.asteriskjava.manager.event.BridgeEvent event) throws InvalidChannelName - { + public BridgeEvent(final org.asteriskjava.manager.event.BridgeEvent event) throws InvalidChannelName { super(event); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -33,47 +30,41 @@ public BridgeEvent(final org.asteriskjava.manager.event.BridgeEvent event) throw this.channel2 = pbx.internalRegisterChannel(event.getChannel2(), event.getUniqueId2()); } - public BridgeState getBridgeState() - { + public BridgeState getBridgeState() { return this.bridgeState; } - public Channel getChannel1() - { + public Channel getChannel1() { return this.channel1; } - public Channel getChannel2() - { + public Channel getChannel2() { return this.channel2; } /** * Returns whether the two channels have been linked. - * + * * @return true the two channels have been linked, - * false if they have been unlinked. + * false if they have been unlinked. * @since 1.0.0 */ - public boolean isLink() - { + public boolean isLink() { return this.bridgeState == BridgeState.Link; } /** * Returns whether the two channels have been unlinked. - * + * * @return true the two channels have been unlinked, - * false if they have been linked. + * false if they have been linked. * @since 1.0.0 */ - public boolean isUnlink() - { + public boolean isUnlink() { return this.bridgeState == BridgeState.Unlink; } - public String toString() - { + public String toString() { return "BridgeEvent: channel1:" + this.channel1 + " channel2:" + this.channel2 + " bridgeState:" + this.bridgeState; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEvent.java index 489076680..5cec903e3 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEvent.java @@ -2,7 +2,6 @@ import org.asteriskjava.pbx.Channel; -public interface ChannelEvent -{ - Channel getChannel(); +public interface ChannelEvent { + Channel getChannel(); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java index 05810b560..93dbcb111 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelEventHelper.java @@ -5,8 +5,7 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public abstract class ChannelEventHelper extends ManagerEvent implements ChannelEvent -{ +public abstract class ChannelEventHelper extends ManagerEvent implements ChannelEvent { private static final long serialVersionUID = 1L; /** @@ -14,50 +13,39 @@ public abstract class ChannelEventHelper extends ManagerEvent implements Channel */ private final Channel channel; - protected ChannelEventHelper(final org.asteriskjava.manager.event.AbstractChannelEvent event) throws InvalidChannelName - { + protected ChannelEventHelper(final org.asteriskjava.manager.event.AbstractChannelEvent event) throws InvalidChannelName { this(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); } protected ChannelEventHelper(final String channel, final String uniqueId, final String callerIdNum, - final String callerIdName) throws InvalidChannelName - { + final String callerIdName) throws InvalidChannelName { super(""); // we must have a source but since don't have one pass - // anything. - if (channel != null) - { + // anything. + if (channel != null) { this.channel = ChannelEventHelper.registerChannel(channel, uniqueId, callerIdNum, callerIdName); - } - else - { + } else { this.channel = null; } } - public ChannelEventHelper(final String channel, final String uniqueId) throws InvalidChannelName - { + public ChannelEventHelper(final String channel, final String uniqueId) throws InvalidChannelName { super("");// we must have a source but since don't have one pass - // anything. + // anything. final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - if (channel != null) - { + if (channel != null) { this.channel = pbx.internalRegisterChannel(channel, uniqueId); - } - else - { + } else { this.channel = null; } } @Override - public Channel getChannel() - { + public Channel getChannel() { return this.channel; } public static Channel registerChannel(final String channelName, final String uniqueId, final String callerIdNum, - final String callerIdName) throws InvalidChannelName - { + final String callerIdName) throws InvalidChannelName { final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); final Channel channel = pbx.internalRegisterChannel(channelName, uniqueId); diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelState.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelState.java index 57163d544..4e7414ba7 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelState.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ChannelState.java @@ -2,41 +2,34 @@ /** * Holds the state of a channel as used by NewStateEvent and NewChannelEvent. - * - * @author bsutton * + * @author bsutton */ -public enum ChannelState -{ - Down, Rsrvd, OffHook, Dialing, Ring, Ringing, Up, Busy, DialingOffhook("Dialing Offhook"), PreRing("Pre-ring"); //$NON-NLS-1$ //$NON-NLS-2$ +public enum ChannelState { + Down, Rsrvd, OffHook, Dialing, Ring, Ringing, Up, Busy, DialingOffhook("Dialing Offhook"), PreRing("Pre-ring"); //$NON-NLS-1$ //$NON-NLS-2$ - String _text; + String _text; - static ChannelState valueOfDesc(String description) - { - ChannelState theState = null; + static ChannelState valueOfDesc(String description) { + ChannelState theState = null; - for (ChannelState aState : ChannelState.values()) - { - if (aState._text.compareToIgnoreCase(description) == 0) - { - theState = aState; - break; - } - } + for (ChannelState aState : ChannelState.values()) { + if (aState._text.compareToIgnoreCase(description) == 0) { + theState = aState; + break; + } + } - return theState; + return theState; - } + } - ChannelState(String text) - { - this._text = text; - } + ChannelState(String text) { + this._text = text; + } - ChannelState() - { - this._text = this.name(); - } + ChannelState() { + this._text = this.name(); + } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListCompleteEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListCompleteEvent.java index a01b32ca9..e4427d66a 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListCompleteEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListCompleteEvent.java @@ -1,12 +1,10 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -public class ConfbridgeListCompleteEvent extends ManagerEvent -{ +public class ConfbridgeListCompleteEvent extends ManagerEvent { private static final long serialVersionUID = 1L; - public ConfbridgeListCompleteEvent(org.asteriskjava.manager.event.ConfbridgeListCompleteEvent source) - { + public ConfbridgeListCompleteEvent(org.asteriskjava.manager.event.ConfbridgeListCompleteEvent source) { super(source); } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListEvent.java index 5073f111b..a6e738f9f 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConfbridgeListEvent.java @@ -1,26 +1,22 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -public class ConfbridgeListEvent extends ResponseEvent -{ +public class ConfbridgeListEvent extends ResponseEvent { private static final long serialVersionUID = 1L; private String conference; private String channel; - public ConfbridgeListEvent(org.asteriskjava.manager.event.ConfbridgeListEvent source) - { + public ConfbridgeListEvent(org.asteriskjava.manager.event.ConfbridgeListEvent source) { super(source); conference = source.getConference(); channel = source.getChannel(); } - - public String getChannel() - { + + public String getChannel() { return channel; } - public String getConference() - { + public String getConference() { return conference; } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConnectEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConnectEvent.java index a33a30204..08c6f7023 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConnectEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ConnectEvent.java @@ -1,7 +1,6 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -public class ConnectEvent extends ManagerEvent -{ +public class ConnectEvent extends ManagerEvent { private static final long serialVersionUID = 1L; /** @@ -9,14 +8,12 @@ public class ConnectEvent extends ManagerEvent */ private final String protocolIdentifier; - public ConnectEvent(final org.asteriskjava.manager.event.ConnectEvent event) - { + public ConnectEvent(final org.asteriskjava.manager.event.ConnectEvent event) { super(event); this.protocolIdentifier = event.getProtocolIdentifier(); } - public String getProtocolIdentifier() - { + public String getProtocolIdentifier() { return this.protocolIdentifier; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java index 9939a4a40..f76c4bc2d 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DbGetResponseEvent.java @@ -1,33 +1,28 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -public class DbGetResponseEvent extends ManagerEvent -{ +public class DbGetResponseEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private final String family; private final String key; private final String val; - public DbGetResponseEvent(final org.asteriskjava.manager.event.DbGetResponseEvent event) - { + public DbGetResponseEvent(final org.asteriskjava.manager.event.DbGetResponseEvent event) { super(event); this.family = event.getFamily(); this.key = event.getKey(); this.val = event.getVal(); } - public String getVal() - { + public String getVal() { return this.val; } - public String getFamily() - { + public String getFamily() { return this.family; } - public String getKey() - { + public String getKey() { return this.key; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialBeginEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialBeginEvent.java index 0585813d0..c91133940 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialBeginEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialBeginEvent.java @@ -1,14 +1,13 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import java.util.Date; - import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class DialBeginEvent extends ChannelEventHelper -{ +import java.util.Date; + +public class DialBeginEvent extends ChannelEventHelper { private static final long serialVersionUID = 1L; /** @@ -18,8 +17,7 @@ public class DialBeginEvent extends ChannelEventHelper final org.asteriskjava.manager.event.DialBeginEvent rawEvent; - public DialBeginEvent(final org.asteriskjava.manager.event.DialBeginEvent event) throws InvalidChannelName - { + public DialBeginEvent(final org.asteriskjava.manager.event.DialBeginEvent event) throws InvalidChannelName { super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -32,221 +30,178 @@ public DialBeginEvent(final org.asteriskjava.manager.event.DialBeginEvent event) } - public String getDestination() - { + public String getDestination() { return rawEvent.getDestination(); } - public String getLanguage() - { + public String getLanguage() { return rawEvent.getLanguage(); } - public String getDestLanguage() - { + public String getDestLanguage() { return rawEvent.getDestLanguage(); } - public String getDestAccountCode() - { + public String getDestAccountCode() { return rawEvent.getDestAccountCode(); } - public String getDestLinkedId() - { + public String getDestLinkedId() { return rawEvent.getDestLinkedId(); } - public String getLinkedId() - { + public String getLinkedId() { return rawEvent.getLinkedId(); } - public String getCallerIdName() - { + public String getCallerIdName() { return rawEvent.getCallerIdName(); } - public String getConnectedLineNum() - { + public String getConnectedLineNum() { return rawEvent.getConnectedLineNum(); } - public String getConnectedLineName() - { + public String getConnectedLineName() { return rawEvent.getConnectedLineName(); } - public Integer getPriority() - { + public Integer getPriority() { return rawEvent.getPriority(); } - public Integer getChannelState() - { + public Integer getChannelState() { return rawEvent.getChannelState(); } - public String getChannelStateDesc() - { + public String getChannelStateDesc() { return rawEvent.getChannelStateDesc(); } - public String getExten() - { + public String getExten() { return rawEvent.getExten(); } - public String getCallerIdNum() - { + public String getCallerIdNum() { return rawEvent.getCallerIdNum(); } - public String getContext() - { + public String getContext() { return rawEvent.getContext(); } - public String getSubEvent() - { + public String getSubEvent() { return rawEvent.getSubEvent(); } - public Date getDateReceived() - { + public Date getDateReceived() { return rawEvent.getDateReceived(); } @SuppressWarnings("deprecation") - public String getSrc() - { + public String getSrc() { return rawEvent.getSrc(); } - public String getPrivilege() - { + public String getPrivilege() { return rawEvent.getPrivilege(); } - public final Double getTimestamp() - { + public final Double getTimestamp() { return rawEvent.getTimestamp(); } - public Channel getDestChannel() - { + public Channel getDestChannel() { return destChannel; } @SuppressWarnings("deprecation") - public String getCallerId() - { + public String getCallerId() { return rawEvent.getCallerId(); } - public final String getServer() - { + public final String getServer() { return rawEvent.getServer(); } - public String getUniqueId() - { + public String getUniqueId() { return rawEvent.getUniqueId(); } - public String getSystemName() - { + public String getSystemName() { return rawEvent.getSystemName(); } @SuppressWarnings("deprecation") - public String getSrcUniqueId() - { + public String getSrcUniqueId() { return rawEvent.getSrcUniqueId(); } - public String getFile() - { + public String getFile() { return rawEvent.getFile(); } - public String getDestUniqueId() - { + public String getDestUniqueId() { return rawEvent.getDestUniqueId(); } - public Integer getLine() - { + public Integer getLine() { return rawEvent.getLine(); } - public String getDialString() - { + public String getDialString() { return rawEvent.getDialString(); } - public String getDialStatus() - { + public String getDialStatus() { return rawEvent.getDialStatus(); } - public String getFunc() - { + public String getFunc() { return rawEvent.getFunc(); } - public Integer getSequenceNumber() - { + public Integer getSequenceNumber() { return rawEvent.getSequenceNumber(); } - public Integer getDestChannelState() - { + public Integer getDestChannelState() { return rawEvent.getDestChannelState(); } - public String getDestContext() - { + public String getDestContext() { return rawEvent.getDestContext(); } - public Integer getDestPriority() - { + public Integer getDestPriority() { return rawEvent.getDestPriority(); } - public String getDestChannelStateDesc() - { + public String getDestChannelStateDesc() { return rawEvent.getDestChannelStateDesc(); } - public String getDestExten() - { + public String getDestExten() { return rawEvent.getDestExten(); } - public String getDestConnectedLineName() - { + public String getDestConnectedLineName() { return rawEvent.getDestConnectedLineName(); } - public String getDestConnectedLineNum() - { + public String getDestConnectedLineNum() { return rawEvent.getDestConnectedLineNum(); } - public String getDestCallerIdName() - { + public String getDestCallerIdName() { return rawEvent.getDestCallerIdName(); } - public String getDestCallerIdNum() - { + public String getDestCallerIdNum() { return rawEvent.getDestCallerIdNum(); } - public Object getSource() - { + public Object getSource() { return rawEvent.getSource(); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEndEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEndEvent.java index 49d5cc2d0..89632e4a5 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEndEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEndEvent.java @@ -1,14 +1,13 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import java.util.Date; - import org.asteriskjava.pbx.Channel; import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class DialEndEvent extends ChannelEventHelper -{ +import java.util.Date; + +public class DialEndEvent extends ChannelEventHelper { private static final long serialVersionUID = 1L; /** @@ -18,8 +17,7 @@ public class DialEndEvent extends ChannelEventHelper final org.asteriskjava.manager.event.DialEndEvent rawEvent; - public DialEndEvent(final org.asteriskjava.manager.event.DialEndEvent event) throws InvalidChannelName - { + public DialEndEvent(final org.asteriskjava.manager.event.DialEndEvent event) throws InvalidChannelName { super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -32,231 +30,186 @@ public DialEndEvent(final org.asteriskjava.manager.event.DialEndEvent event) thr } - public String getDestination() - { + public String getDestination() { return rawEvent.getDestination(); } - public String getLanguage() - { + public String getLanguage() { return rawEvent.getLanguage(); } - public String getDestLanguage() - { + public String getDestLanguage() { return rawEvent.getDestLanguage(); } - public String getAccountCode() - { + public String getAccountCode() { return rawEvent.getAccountCode(); } - public String getDestAccountCode() - { + public String getDestAccountCode() { return rawEvent.getDestAccountCode(); } - public String getDestLinkedId() - { + public String getDestLinkedId() { return rawEvent.getDestLinkedId(); } - public String getLinkedId() - { + public String getLinkedId() { return rawEvent.getLinkedId(); } - public String getForward() - { + public String getForward() { return rawEvent.getForward(); } - public String getCallerIdName() - { + public String getCallerIdName() { return rawEvent.getCallerIdName(); } - public String getConnectedLineNum() - { + public String getConnectedLineNum() { return rawEvent.getConnectedLineNum(); } - public String getConnectedLineName() - { + public String getConnectedLineName() { return rawEvent.getConnectedLineName(); } - public Integer getPriority() - { + public Integer getPriority() { return rawEvent.getPriority(); } - public Integer getChannelState() - { + public Integer getChannelState() { return rawEvent.getChannelState(); } - public String getChannelStateDesc() - { + public String getChannelStateDesc() { return rawEvent.getChannelStateDesc(); } - public String getExten() - { + public String getExten() { return rawEvent.getExten(); } - public String getCallerIdNum() - { + public String getCallerIdNum() { return rawEvent.getCallerIdNum(); } - public String getContext() - { + public String getContext() { return rawEvent.getContext(); } - public String getSubEvent() - { + public String getSubEvent() { return rawEvent.getSubEvent(); } - public Date getDateReceived() - { + public Date getDateReceived() { return rawEvent.getDateReceived(); } @SuppressWarnings("deprecation") - public String getSrc() - { + public String getSrc() { return rawEvent.getSrc(); } - public String getPrivilege() - { + public String getPrivilege() { return rawEvent.getPrivilege(); } - public final Double getTimestamp() - { + public final Double getTimestamp() { return rawEvent.getTimestamp(); } - public Channel getDestChannel() - { + public Channel getDestChannel() { return destChannel; } @SuppressWarnings("deprecation") - public String getCallerId() - { + public String getCallerId() { return rawEvent.getCallerId(); } - public final String getServer() - { + public final String getServer() { return rawEvent.getServer(); } - public String getUniqueId() - { + public String getUniqueId() { return rawEvent.getUniqueId(); } - public String getSystemName() - { + public String getSystemName() { return rawEvent.getSystemName(); } @SuppressWarnings("deprecation") - public String getSrcUniqueId() - { + public String getSrcUniqueId() { return rawEvent.getSrcUniqueId(); } - public String getFile() - { + public String getFile() { return rawEvent.getFile(); } - public String getDestUniqueId() - { + public String getDestUniqueId() { return rawEvent.getDestUniqueId(); } - public Integer getLine() - { + public Integer getLine() { return rawEvent.getLine(); } - public String getDialString() - { + public String getDialString() { return rawEvent.getDialString(); } - public String getDialStatus() - { + public String getDialStatus() { return rawEvent.getDialStatus(); } - public String getFunc() - { + public String getFunc() { return rawEvent.getFunc(); } - public Integer getSequenceNumber() - { + public Integer getSequenceNumber() { return rawEvent.getSequenceNumber(); } - public Integer getDestChannelState() - { + public Integer getDestChannelState() { return rawEvent.getDestChannelState(); } - public String getDestContext() - { + public String getDestContext() { return rawEvent.getDestContext(); } - public Integer getDestPriority() - { + public Integer getDestPriority() { return rawEvent.getDestPriority(); } - public String getDestChannelStateDesc() - { + public String getDestChannelStateDesc() { return rawEvent.getDestChannelStateDesc(); } - public String getDestExten() - { + public String getDestExten() { return rawEvent.getDestExten(); } - public String getDestConnectedLineName() - { + public String getDestConnectedLineName() { return rawEvent.getDestConnectedLineName(); } - public String getDestConnectedLineNum() - { + public String getDestConnectedLineNum() { return rawEvent.getDestConnectedLineNum(); } - public String getDestCallerIdName() - { + public String getDestCallerIdName() { return rawEvent.getDestCallerIdName(); } - public String getDestCallerIdNum() - { + public String getDestCallerIdNum() { return rawEvent.getDestCallerIdNum(); } - public Object getSource() - { + public Object getSource() { return rawEvent.getSource(); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEvent.java index e8e1ba6e2..3574bc5dd 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DialEvent.java @@ -5,8 +5,7 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class DialEvent extends ChannelEventHelper -{ +public class DialEvent extends ChannelEventHelper { private static final long serialVersionUID = 1L; /** @@ -17,8 +16,7 @@ public class DialEvent extends ChannelEventHelper private final String dialString; private final String dialStatus; - public DialEvent(final org.asteriskjava.manager.event.DialEvent event) throws InvalidChannelName - { + public DialEvent(final org.asteriskjava.manager.event.DialEvent event) throws InvalidChannelName { super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -32,18 +30,15 @@ public DialEvent(final org.asteriskjava.manager.event.DialEvent event) throws In } - public Channel getDestination() - { + public Channel getDestination() { return this.destination; } - public String getDialString() - { + public String getDialString() { return this.dialString; } - public String getDialStatus() - { + public String getDialStatus() { return this.dialStatus; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DisconnectEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DisconnectEvent.java index f69fef8a6..2e457cba0 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DisconnectEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DisconnectEvent.java @@ -1,11 +1,9 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -public class DisconnectEvent extends ManagerEvent -{ +public class DisconnectEvent extends ManagerEvent { private static final long serialVersionUID = 1L; - public DisconnectEvent(final org.asteriskjava.manager.event.DisconnectEvent event) - { + public DisconnectEvent(final org.asteriskjava.manager.event.DisconnectEvent event) { super(event); } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DndStateEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DndStateEvent.java index 4e68e61a4..50ac20832 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DndStateEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/DndStateEvent.java @@ -6,8 +6,7 @@ import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelImpl; -public class DndStateEvent extends ManagerEvent implements ChannelEvent -{ +public class DndStateEvent extends ManagerEvent implements ChannelEvent { private static final long serialVersionUID = 1L; /** @@ -20,8 +19,7 @@ public class DndStateEvent extends ManagerEvent implements ChannelEvent */ private final Boolean state; - public DndStateEvent(final org.asteriskjava.manager.event.DndStateEvent event) throws InvalidChannelName - { + public DndStateEvent(final org.asteriskjava.manager.event.DndStateEvent event) throws InvalidChannelName { super(event); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); this.channel = pbx.internalRegisterChannel(event.getChannel(), ChannelImpl.UNKNOWN_UNIQUE_ID); @@ -29,13 +27,11 @@ public DndStateEvent(final org.asteriskjava.manager.event.DndStateEvent event) t } @Override - public Channel getChannel() - { + public Channel getChannel() { return this.channel; } - public Boolean getState() - { + public Boolean getState() { return this.state; } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ExtensionStatusEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ExtensionStatusEvent.java index 4c58223a8..1951b7886 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ExtensionStatusEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ExtensionStatusEvent.java @@ -1,11 +1,9 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -public class ExtensionStatusEvent extends ManagerEvent -{ +public class ExtensionStatusEvent extends ManagerEvent { private static final long serialVersionUID = 1L; - enum Status - { + enum Status { /** * No device INUSE or BUSY. @@ -34,18 +32,14 @@ enum Status int _status; - Status(int status) - { + Status(int status) { this._status = status; } - static Status valueOf(Integer status) - { + static Status valueOf(Integer status) { Status theStatus = null; - for (Status aStatus : Status.values()) - { - if (aStatus._status == status) - { + for (Status aStatus : Status.values()) { + if (aStatus._status == status) { theStatus = aStatus; break; } @@ -59,8 +53,7 @@ static Status valueOf(Integer status) private final String hint; private final Status status; - public ExtensionStatusEvent(final org.asteriskjava.manager.event.ExtensionStatusEvent event) - { + public ExtensionStatusEvent(final org.asteriskjava.manager.event.ExtensionStatusEvent event) { super(event); this.exten = event.getExten(); this.context = event.getContext(); @@ -68,23 +61,19 @@ public ExtensionStatusEvent(final org.asteriskjava.manager.event.ExtensionStatus this.status = Status.valueOf(event.getStatus()); } - public String getExten() - { + public String getExten() { return this.exten; } - public String getContext() - { + public String getContext() { return this.context; } - public String getHint() - { + public String getHint() { return this.hint; } - public Status getStatus() - { + public Status getStatus() { return this.status; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/HangupEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/HangupEvent.java index e18aef5c2..144766626 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/HangupEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/HangupEvent.java @@ -5,8 +5,7 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class HangupEvent extends ManagerEvent implements ChannelEvent -{ +public class HangupEvent extends ManagerEvent implements ChannelEvent { private static final long serialVersionUID = 1L; /** @@ -18,8 +17,7 @@ public class HangupEvent extends ManagerEvent implements ChannelEvent private final String causeTxt; private final String uniqueId; - public HangupEvent(final org.asteriskjava.manager.event.HangupEvent event) throws InvalidChannelName - { + public HangupEvent(final org.asteriskjava.manager.event.HangupEvent event) throws InvalidChannelName { super(event); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -30,29 +28,24 @@ public HangupEvent(final org.asteriskjava.manager.event.HangupEvent event) throw } - public Integer getCause() - { + public Integer getCause() { return this.cause; } - public String getCauseTxt() - { + public String getCauseTxt() { return this.causeTxt; } @Override - public Channel getChannel() - { + public Channel getChannel() { return this.channel; } - public String getUniqueId() - { + public String getUniqueId() { return this.uniqueId; } - public String toString() - { + public String toString() { return "HangupEvent: channel:" + this.channel + " cause:" + this.causeTxt; //$NON-NLS-1$//$NON-NLS-2$ } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/LinkEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/LinkEvent.java index 5a1b48f7c..13c6dfc1a 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/LinkEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/LinkEvent.java @@ -2,13 +2,11 @@ import org.asteriskjava.pbx.InvalidChannelName; -public class LinkEvent extends BridgeEvent -{ +public class LinkEvent extends BridgeEvent { private static final long serialVersionUID = 1L; @SuppressWarnings("deprecation") - public LinkEvent(final org.asteriskjava.manager.event.LinkEvent event) throws InvalidChannelName - { + public LinkEvent(final org.asteriskjava.manager.event.LinkEvent event) throws InvalidChannelName { super(event); } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ManagerEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ManagerEvent.java index 9427c1514..1f2cff256 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ManagerEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ManagerEvent.java @@ -2,12 +2,10 @@ import java.util.EventObject; -public class ManagerEvent extends EventObject -{ +public class ManagerEvent extends EventObject { private static final long serialVersionUID = 1L; - public ManagerEvent(Object source) - { + public ManagerEvent(Object source) { super(source); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MasqueradeEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MasqueradeEvent.java index 4e8a43365..f6695509f 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MasqueradeEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MasqueradeEvent.java @@ -92,11 +92,10 @@ * channel. At the end of the swap the original (new) channel is left active (as * it has the clones guts) and the clone (pre-existing) is inactive so we can * hangup the clone as it is no longer needed. - * + * * @author bsutton */ -public class MasqueradeEvent extends ManagerEvent -{ +public class MasqueradeEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private final Channel _original; @@ -107,8 +106,7 @@ public class MasqueradeEvent extends ManagerEvent private ChannelState originalState; - public MasqueradeEvent(final org.asteriskjava.manager.event.MasqueradeEvent event) throws InvalidChannelName - { + public MasqueradeEvent(final org.asteriskjava.manager.event.MasqueradeEvent event) throws InvalidChannelName { super(event); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -120,31 +118,26 @@ public MasqueradeEvent(final org.asteriskjava.manager.event.MasqueradeEvent even /** * Returns the original channel - * + * * @return */ - public Channel getOriginal() - { + public Channel getOriginal() { return this._original; } - public Channel getClone() - { + public Channel getClone() { return this._clone; } - public ChannelState getCloneState() - { + public ChannelState getCloneState() { return this.cloneState; } - public ChannelState getOriginalState() - { + public ChannelState getOriginalState() { return this.originalState; } - public String toString() - { + public String toString() { // Even though it talks about the original channel return "MasqueradeEvent: originalChannel(new):" + this._original + " cloned from (pre-existing):" + this._clone; //$NON-NLS-1$//$NON-NLS-2$ } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeJoinEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeJoinEvent.java index d86b8b43e..54e5a1e71 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeJoinEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeJoinEvent.java @@ -5,14 +5,12 @@ import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; -public class MeetMeJoinEvent extends AbstractMeetMeEvent -{ +public class MeetMeJoinEvent extends AbstractMeetMeEvent { private static final long serialVersionUID = 1L; CallerID callerID; - public MeetMeJoinEvent(final org.asteriskjava.manager.event.MeetMeJoinEvent event) throws InvalidChannelName - { + public MeetMeJoinEvent(final org.asteriskjava.manager.event.MeetMeJoinEvent event) throws InvalidChannelName { super(event); final PBX pbx = PBXFactory.getActivePBX(); @@ -20,8 +18,7 @@ public MeetMeJoinEvent(final org.asteriskjava.manager.event.MeetMeJoinEvent even } - public CallerID getCallerID() - { + public CallerID getCallerID() { return this.callerID; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeLeaveEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeLeaveEvent.java index b83049fcb..45cb81e22 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeLeaveEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/MeetMeLeaveEvent.java @@ -5,15 +5,13 @@ import org.asteriskjava.pbx.PBX; import org.asteriskjava.pbx.PBXFactory; -public class MeetMeLeaveEvent extends AbstractMeetMeEvent -{ +public class MeetMeLeaveEvent extends AbstractMeetMeEvent { private static final long serialVersionUID = 1L; private final CallerID callerID; private final Long duration; - public MeetMeLeaveEvent(final org.asteriskjava.manager.event.MeetMeLeaveEvent event) throws InvalidChannelName - { + public MeetMeLeaveEvent(final org.asteriskjava.manager.event.MeetMeLeaveEvent event) throws InvalidChannelName { super(event); final PBX pbx = PBXFactory.getActivePBX(); @@ -22,13 +20,11 @@ public MeetMeLeaveEvent(final org.asteriskjava.manager.event.MeetMeLeaveEvent ev this.duration = event.getDuration(); } - public CallerID getCallerID() - { + public CallerID getCallerID() { return this.callerID; } - public Long getDuration() - { + public Long getDuration() { return this.duration; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java index eaf939e81..74df7d71a 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewChannelEvent.java @@ -4,16 +4,14 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class NewChannelEvent extends AbstractChannelStateEvent -{ +public class NewChannelEvent extends AbstractChannelStateEvent { private static final long serialVersionUID = 1L; private final String accountCode; private final String context; private final String exten; - public NewChannelEvent(final org.asteriskjava.manager.event.NewChannelEvent event) throws InvalidChannelName - { + public NewChannelEvent(final org.asteriskjava.manager.event.NewChannelEvent event) throws InvalidChannelName { super(event); this.accountCode = event.getAccountCode(); this.context = event.getContext(); @@ -25,23 +23,19 @@ public NewChannelEvent(final org.asteriskjava.manager.event.NewChannelEvent even } - public String getAccountCode() - { + public String getAccountCode() { return this.accountCode; } - public String getContext() - { + public String getContext() { return this.context; } - public String getExten() - { + public String getExten() { return this.exten; } - public String toString() - { + public String toString() { return "NewChannelEvent: channel: " + this.getChannel() + " context=" + this.context + " exten=" + this.exten //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + " state=" + this.getChannelStateDesc(); //$NON-NLS-1$ } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewExtenEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewExtenEvent.java index 34a6594ac..608f705c4 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewExtenEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewExtenEvent.java @@ -5,8 +5,7 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class NewExtenEvent extends ManagerEvent implements ChannelEvent -{ +public class NewExtenEvent extends ManagerEvent implements ChannelEvent { private static final long serialVersionUID = 1L; private final String context; @@ -16,8 +15,7 @@ public class NewExtenEvent extends ManagerEvent implements ChannelEvent private final Integer priority; private final Channel channel; - public NewExtenEvent(final org.asteriskjava.manager.event.NewExtenEvent event) throws InvalidChannelName - { + public NewExtenEvent(final org.asteriskjava.manager.event.NewExtenEvent event) throws InvalidChannelName { super(event); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -29,34 +27,28 @@ public NewExtenEvent(final org.asteriskjava.manager.event.NewExtenEvent event) t this.priority = event.getPriority(); } - public String getContext() - { + public String getContext() { return this.context; } - public String getExtension() - { + public String getExtension() { return this.extension; } - public String getApplication() - { + public String getApplication() { return this.application; } - public String getAppData() - { + public String getAppData() { return this.appData; } - public Integer getPriority() - { + public Integer getPriority() { return this.priority; } @Override - public Channel getChannel() - { + public Channel getChannel() { return this.channel; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java index e7138cfbb..e010919b4 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/NewStateEvent.java @@ -4,23 +4,19 @@ import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.internal.core.ChannelProxy; -public class NewStateEvent extends AbstractChannelStateEvent -{ +public class NewStateEvent extends AbstractChannelStateEvent { private static final long serialVersionUID = 1L; private ChannelProxy destChannel; - public NewStateEvent(final org.asteriskjava.manager.event.NewStateEvent event) throws InvalidChannelName - { + public NewStateEvent(final org.asteriskjava.manager.event.NewStateEvent event) throws InvalidChannelName { super(event); } - public Channel getDestination() - { + public Channel getDestination() { return destChannel; } - public String toString() - { + public String toString() { return "NewStateEvent: channel:" + this.getChannel() + " channelState:" + this.getChannelState(); //$NON-NLS-1$//$NON-NLS-2$ } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/OriginateResponseEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/OriginateResponseEvent.java index 5ae4bd8e0..ce056a3ab 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/OriginateResponseEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/OriginateResponseEvent.java @@ -1,15 +1,9 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.InvalidChannelName; -import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.TechType; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.internal.core.ChannelImpl; -public class OriginateResponseEvent extends ResponseEvent implements ChannelEvent -{ +public class OriginateResponseEvent extends ResponseEvent implements ChannelEvent { private static final long serialVersionUID = 1L; @@ -23,8 +17,7 @@ public class OriginateResponseEvent extends ResponseEvent implements ChannelEven private final Integer reason; public OriginateResponseEvent(final org.asteriskjava.manager.event.OriginateResponseEvent event) - throws InvalidChannelName - { + throws InvalidChannelName { super(event); PBX pbx = PBXFactory.getActivePBX(); @@ -32,15 +25,12 @@ public OriginateResponseEvent(final org.asteriskjava.manager.event.OriginateResp // The doco says this should be a channel but under 1.4 it comes up as // an endpoint. this.isChannel = pbx.isChannel(event.getChannel()); - if (this.isChannel) - { + if (this.isChannel) { this.channel = ChannelEventHelper.registerChannel(event.getChannel(), (event.getUniqueId() == null ? ChannelImpl.UNKNOWN_UNIQUE_ID : event.getUniqueId()), event.getCallerIdNum(), event.getCallerIdName()); this.endPoint = null; - } - else - { + } else { this.endPoint = pbx.buildEndPoint(TechType.SIP, event.getChannel()); this.channel = null; } @@ -52,44 +42,36 @@ public OriginateResponseEvent(final org.asteriskjava.manager.event.OriginateResp } - public String getResponse() - { + public String getResponse() { return this.response; } - public String getContext() - { + public String getContext() { return this.context; } - public String getExten() - { + public String getExten() { return this.exten; } - public Integer getReason() - { + public Integer getReason() { return this.reason; } - public boolean isChannel() - { + public boolean isChannel() { return this.isChannel; } @Override - public Channel getChannel() - { + public Channel getChannel() { return this.channel; } - public EndPoint getEndPoint() - { + public EndPoint getEndPoint() { return this.endPoint; } - public boolean isSuccess() - { + public boolean isSuccess() { return "Success".equalsIgnoreCase(this.response); //$NON-NLS-1$ } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ParkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ParkedCallEvent.java index 5426bbd03..5ebd2b5bc 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ParkedCallEvent.java @@ -6,8 +6,7 @@ import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelImpl; -public class ParkedCallEvent extends ManagerEvent -{ +public class ParkedCallEvent extends ManagerEvent { private static final long serialVersionUID = 1L; @@ -15,8 +14,7 @@ public class ParkedCallEvent extends ManagerEvent private final Integer timeout; private String exten; - public ParkedCallEvent(final org.asteriskjava.manager.event.ParkedCallEvent event) throws InvalidChannelName - { + public ParkedCallEvent(final org.asteriskjava.manager.event.ParkedCallEvent event) throws InvalidChannelName { super(event); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -30,21 +28,18 @@ public ParkedCallEvent(final org.asteriskjava.manager.event.ParkedCallEvent even /** * The channel that parked the call. In some circumstances this can be null. - * + * * @return */ - public Channel getFromChannel() - { + public Channel getFromChannel() { return this.fromChannel; } - public Integer getTimeout() - { + public Integer getTimeout() { return this.timeout; } - public String getExten() - { + public String getExten() { return this.exten; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerEntryEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerEntryEvent.java index 524dfbdd2..4bab04390 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerEntryEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerEntryEvent.java @@ -5,22 +5,19 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.TechType; -public class PeerEntryEvent extends ResponseEvent -{ +public class PeerEntryEvent extends ResponseEvent { private static final long serialVersionUID = 1L; private final EndPoint peer; - public PeerEntryEvent(final org.asteriskjava.manager.event.PeerEntryEvent event) - { + public PeerEntryEvent(final org.asteriskjava.manager.event.PeerEntryEvent event) { super(event); PBX pbx = PBXFactory.getActivePBX(); this.peer = pbx.buildEndPoint(TechType.valueOf(event.getChannelType()), event.getObjectName()); } - public EndPoint getPeer() - { + public EndPoint getPeer() { return this.peer; } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerStatusEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerStatusEvent.java index 7fa0dc1e5..fbab23813 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerStatusEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerStatusEvent.java @@ -4,23 +4,20 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class PeerStatusEvent extends ManagerEvent -{ +public class PeerStatusEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private final EndPoint peer; - public PeerStatusEvent(final org.asteriskjava.manager.event.PeerStatusEvent event) - { + public PeerStatusEvent(final org.asteriskjava.manager.event.PeerStatusEvent event) { super(event); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); this.peer = pbx.buildEndPoint(event.getPeer());// registerChannel(event.getPeer(), - // Channel.UNKNOWN_UNIQUE_ID); + // Channel.UNKNOWN_UNIQUE_ID); } - public EndPoint getPeer() - { + public EndPoint getPeer() { return this.peer; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerlistCompleteEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerlistCompleteEvent.java index 3044f9468..e9f7f998c 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerlistCompleteEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/PeerlistCompleteEvent.java @@ -1,11 +1,9 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -public class PeerlistCompleteEvent extends ResponseEvent -{ +public class PeerlistCompleteEvent extends ResponseEvent { private static final long serialVersionUID = 1L; - public PeerlistCompleteEvent(final org.asteriskjava.manager.event.PeerlistCompleteEvent event) - { + public PeerlistCompleteEvent(final org.asteriskjava.manager.event.PeerlistCompleteEvent event) { super(event); } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/QueueCallerLeaveEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/QueueCallerLeaveEvent.java index 8c51bf203..10230480f 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/QueueCallerLeaveEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/QueueCallerLeaveEvent.java @@ -2,21 +2,18 @@ import org.asteriskjava.pbx.InvalidChannelName; -public class QueueCallerLeaveEvent extends ChannelEventHelper -{ +public class QueueCallerLeaveEvent extends ChannelEventHelper { private static final long serialVersionUID = 1L; private String queue; - public QueueCallerLeaveEvent(final org.asteriskjava.manager.event.QueueCallerLeaveEvent event) throws InvalidChannelName - { + public QueueCallerLeaveEvent(final org.asteriskjava.manager.event.QueueCallerLeaveEvent event) throws InvalidChannelName { super(event.getChannel(), event.getUniqueId(), event.getCallerIdNum(), event.getCallerIdName()); queue = event.getQueue(); } - public String getQueueName() - { + public String getQueueName() { return queue; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java index 71424c7a9..702bfb817 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ReloadEvent.java @@ -1,12 +1,10 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -public class ReloadEvent extends ManagerEvent -{ +public class ReloadEvent extends ManagerEvent { private static final long serialVersionUID = 1L; - public ReloadEvent(final org.asteriskjava.manager.event.ReloadEvent event) - { + public ReloadEvent(final org.asteriskjava.manager.event.ReloadEvent event) { super(event); } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java index 9a4d88456..95f9fa13c 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/RenameEvent.java @@ -8,8 +8,7 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class RenameEvent extends ManagerEvent implements ChannelEvent -{ +public class RenameEvent extends ManagerEvent implements ChannelEvent { private static final long serialVersionUID = 1L; private static final Log logger = LogFactory.getLog(RenameEvent.class); @@ -26,8 +25,7 @@ public class RenameEvent extends ManagerEvent implements ChannelEvent private String uniqueId; - public RenameEvent(final org.asteriskjava.manager.event.RenameEvent event) throws InvalidChannelName - { + public RenameEvent(final org.asteriskjava.manager.event.RenameEvent event) throws InvalidChannelName { super(event); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -45,24 +43,20 @@ public RenameEvent(final org.asteriskjava.manager.event.RenameEvent event) throw } @Override - public final Channel getChannel() - { + public final Channel getChannel() { return this._channel; } - public final String getNewName() - { + public final String getNewName() { return this._newName; } - public final String getUniqueId() - { + public final String getUniqueId() { return uniqueId; } @Override - public String toString() - { + public String toString() { org.asteriskjava.manager.event.RenameEvent rawEvent = (org.asteriskjava.manager.event.RenameEvent) getSource(); return "RenameEvent: existing channel: " + this._channel + " newname=" + this._newName //$NON-NLS-1$ //$NON-NLS-2$ + "rawExisting:" + rawEvent.getChannel() + " rawNewname:" + rawEvent.getNewname() //$NON-NLS-1$ //$NON-NLS-2$ diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvent.java index 444598af5..bd29067e4 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvent.java @@ -1,26 +1,22 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -public class ResponseEvent extends ManagerEvent -{ +public class ResponseEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private final String actionId; private final String internalActionId; - public ResponseEvent(final org.asteriskjava.manager.event.ResponseEvent event) - { + public ResponseEvent(final org.asteriskjava.manager.event.ResponseEvent event) { super(event); this.actionId = event.getActionId(); this.internalActionId = event.getInternalActionId(); } - public String getActionId() - { + public String getActionId() { return this.actionId; } - public String getInternalActionId() - { + public String getInternalActionId() { return this.internalActionId; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvents.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvents.java index ba6c3dfcc..8a095bfdd 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvents.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/ResponseEvents.java @@ -3,25 +3,22 @@ import java.util.ArrayList; import java.util.Collection; -public class ResponseEvents -{ +public class ResponseEvents { - ArrayList events = new ArrayList<>(); + ArrayList events = new ArrayList<>(); - /** - * Returns a Collection of ManagerEvents that have been received including - * the last one that indicates completion. - * - * @return a Collection of ManagerEvents received. - */ - public Collection getEvents() - { - return this.events; - } + /** + * Returns a Collection of ManagerEvents that have been received including + * the last one that indicates completion. + * + * @return a Collection of ManagerEvents received. + */ + public Collection getEvents() { + return this.events; + } - public void add(ResponseEvent event) - { - this.events.add(event); + public void add(ResponseEvent event) { + this.events.add(event); - } + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusCompleteEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusCompleteEvent.java index cb0d576e3..a4c6907a1 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusCompleteEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusCompleteEvent.java @@ -1,11 +1,9 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -public class StatusCompleteEvent extends ResponseEvent -{ +public class StatusCompleteEvent extends ResponseEvent { private static final long serialVersionUID = 1L; - public StatusCompleteEvent(final org.asteriskjava.manager.event.StatusCompleteEvent event) - { + public StatusCompleteEvent(final org.asteriskjava.manager.event.StatusCompleteEvent event) { super(event); } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusEvent.java index 597956be9..1446400ba 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/StatusEvent.java @@ -1,16 +1,11 @@ package org.asteriskjava.pbx.asterisk.wrap.events; -import java.util.Map; - -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.DialPlanExtension; -import org.asteriskjava.pbx.InvalidChannelName; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class StatusEvent extends ResponseEvent implements ChannelEvent -{ +import java.util.Map; + +public class StatusEvent extends ResponseEvent implements ChannelEvent { private static final long serialVersionUID = 1L; private final Channel channel; @@ -26,8 +21,7 @@ public class StatusEvent extends ResponseEvent implements ChannelEvent private final Map variables; private final String uniqueId; - public StatusEvent(final org.asteriskjava.manager.event.StatusEvent event) throws InvalidChannelName - { + public StatusEvent(final org.asteriskjava.manager.event.StatusEvent event) throws InvalidChannelName { super(event); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -49,63 +43,51 @@ public StatusEvent(final org.asteriskjava.manager.event.StatusEvent event) throw } @Override - public final Channel getChannel() - { + public final Channel getChannel() { return this.channel; } - public final CallerID getCallerId() - { + public final CallerID getCallerId() { return this.callerId; } - public final String getAccountCode() - { + public final String getAccountCode() { return this.accountCode; } - public final ChannelState getState() - { + public final ChannelState getState() { return this.channelState; } - public final String getChannelStateDesc() - { + public final String getChannelStateDesc() { return this.channelStateDesc; } - public final String getContext() - { + public final String getContext() { return this.context; } - public final DialPlanExtension getExtension() - { + public final DialPlanExtension getExtension() { return this.extension; } - public final Integer getPriority() - { + public final Integer getPriority() { return this.priority; } - public final Integer getSeconds() - { + public final Integer getSeconds() { return this.seconds; } - public final Channel getBridgedChannel() - { + public final Channel getBridgedChannel() { return this.bridgedChannel; } - public final Map getVariables() - { + public final Map getVariables() { return this.variables; } - public String getUniqueId() - { + public String getUniqueId() { return this.uniqueId; } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnlinkEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnlinkEvent.java index d537291e5..3389983bd 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnlinkEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnlinkEvent.java @@ -2,13 +2,11 @@ import org.asteriskjava.pbx.InvalidChannelName; -public class UnlinkEvent extends BridgeEvent -{ +public class UnlinkEvent extends BridgeEvent { private static final long serialVersionUID = 1L; @SuppressWarnings("deprecation") - public UnlinkEvent(final org.asteriskjava.manager.event.UnlinkEvent event) throws InvalidChannelName - { + public UnlinkEvent(final org.asteriskjava.manager.event.UnlinkEvent event) throws InvalidChannelName { super(event); } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnparkedCallEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnparkedCallEvent.java index fdd0bda97..1f71857ca 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnparkedCallEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/UnparkedCallEvent.java @@ -6,22 +6,19 @@ import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.pbx.internal.core.ChannelImpl; -public class UnparkedCallEvent extends AbstractParkedCallEvent -{ +public class UnparkedCallEvent extends AbstractParkedCallEvent { private static final long serialVersionUID = 1L; private final Channel fromChannel; - public UnparkedCallEvent(final org.asteriskjava.manager.event.UnparkedCallEvent event) throws InvalidChannelName - { + public UnparkedCallEvent(final org.asteriskjava.manager.event.UnparkedCallEvent event) throws InvalidChannelName { super(event); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); this.fromChannel = pbx.internalRegisterChannel(event.getParkerDialString(), ChannelImpl.UNKNOWN_UNIQUE_ID); } - public Channel getFromChannel() - { + public Channel getFromChannel() { return this.fromChannel; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/VarSetEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/VarSetEvent.java index d4d586dbd..5df6731d6 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/VarSetEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/events/VarSetEvent.java @@ -5,8 +5,7 @@ import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class VarSetEvent extends ManagerEvent implements ChannelEvent -{ +public class VarSetEvent extends ManagerEvent implements ChannelEvent { private static final long serialVersionUID = 1L; /** @@ -18,8 +17,7 @@ public class VarSetEvent extends ManagerEvent implements ChannelEvent private String _variableValue; - public VarSetEvent(final org.asteriskjava.manager.event.VarSetEvent event) throws InvalidChannelName - { + public VarSetEvent(final org.asteriskjava.manager.event.VarSetEvent event) throws InvalidChannelName { super(event); final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); this._channel = pbx.internalRegisterChannel(event.getChannel(), event.getUniqueId()); @@ -28,18 +26,15 @@ public VarSetEvent(final org.asteriskjava.manager.event.VarSetEvent event) throw } @Override - public Channel getChannel() - { + public Channel getChannel() { return this._channel; } - public String getVariableName() - { + public String getVariableName() { return this._variableName; } - public String getVariableValue() - { + public String getVariableValue() { return this._variableValue; } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java index 13d6706b0..135e76138 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/CommandResponse.java @@ -3,31 +3,27 @@ import java.util.Collections; import java.util.List; -public class CommandResponse extends ManagerResponse -{ +public class CommandResponse extends ManagerResponse { private List result; - private boolean error; + private boolean error; - public CommandResponse(org.asteriskjava.manager.response.ManagerResponse response) - { + public CommandResponse(org.asteriskjava.manager.response.ManagerResponse response) { super(response); if (response instanceof org.asteriskjava.manager.response.CommandResponse) { - result = ((org.asteriskjava.manager.response.CommandResponse) response).getResult(); + result = ((org.asteriskjava.manager.response.CommandResponse) response).getResult(); } else if (response instanceof org.asteriskjava.manager.response.ManagerError) { - error = true; - result = Collections.singletonList(response.getOutput()); + error = true; + result = Collections.singletonList(response.getOutput()); } } - public List getResult() - { + public List getResult() { return this.result; } - public boolean isError() - { - return error; - } + public boolean isError() { + return error; + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java index c82e5fad9..68479b634 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerError.java @@ -1,10 +1,8 @@ package org.asteriskjava.pbx.asterisk.wrap.response; -public class ManagerError extends CommandResponse -{ +public class ManagerError extends CommandResponse { - public ManagerError(org.asteriskjava.manager.response.ManagerResponse error) - { + public ManagerError(org.asteriskjava.manager.response.ManagerResponse error) { super(error); } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java index ff08dd374..bd5715997 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/response/ManagerResponse.java @@ -1,93 +1,81 @@ package org.asteriskjava.pbx.asterisk.wrap.response; +import org.asteriskjava.manager.response.ManagerError; + import java.util.Date; import java.util.Locale; import java.util.Map; -import org.asteriskjava.manager.response.ManagerError; - -public class ManagerResponse -{ - - private Date _dateReceived; - private String _actionId; - - /** - * The server from which this response has been received (only used with - * AstManProxy). - */ - final private String _server; - final private String _response; - final private String _eventList; - final private String message; - final private String _uniqueId; - final private Map _attributes; - - public ManagerResponse(org.asteriskjava.manager.response.ManagerResponse response) - { - this._dateReceived = response.getDateReceived(); - this._actionId = response.getActionId(); - this._server = response.getServer(); - this._response = response.getResponse(); - this._eventList = response.getEventList(); - this._uniqueId = response.getUniqueId(); - this._attributes = response.getAttributes(); - - if (response instanceof ManagerError) { - this.message = response.getOutput(); - } else { - this.message = response.getMessage(); - } - } - - public Date getDateReceived() - { - return this._dateReceived; - } - - public String getActionId() - { - return this._actionId; - } - - public String getServer() - { - return this._server; - } - - public String getResponse() - { - return this._response; - } - - public String getEventList() - { - return this._eventList; - } - - public String getMessage() - { - return this.message; - } - - public String getUniqueId() - { - return this._uniqueId; - } - - public Map getAttributes() - { - return this._attributes; - } - - public String getAttribute(String key) - { - return (String) this._attributes.get(key.toLowerCase(Locale.ENGLISH)); - } - - public boolean isSuccess() - { - return this._response.compareToIgnoreCase("Success") == 0; //$NON-NLS-1$ - } +public class ManagerResponse { + + private Date _dateReceived; + private String _actionId; + + /** + * The server from which this response has been received (only used with + * AstManProxy). + */ + final private String _server; + final private String _response; + final private String _eventList; + final private String message; + final private String _uniqueId; + final private Map _attributes; + + public ManagerResponse(org.asteriskjava.manager.response.ManagerResponse response) { + this._dateReceived = response.getDateReceived(); + this._actionId = response.getActionId(); + this._server = response.getServer(); + this._response = response.getResponse(); + this._eventList = response.getEventList(); + this._uniqueId = response.getUniqueId(); + this._attributes = response.getAttributes(); + + if (response instanceof ManagerError) { + this.message = response.getOutput(); + } else { + this.message = response.getMessage(); + } + } + + public Date getDateReceived() { + return this._dateReceived; + } + + public String getActionId() { + return this._actionId; + } + + public String getServer() { + return this._server; + } + + public String getResponse() { + return this._response; + } + + public String getEventList() { + return this._eventList; + } + + public String getMessage() { + return this.message; + } + + public String getUniqueId() { + return this._uniqueId; + } + + public Map getAttributes() { + return this._attributes; + } + + public String getAttribute(String key) { + return (String) this._attributes.get(key.toLowerCase(Locale.ENGLISH)); + } + + public boolean isSuccess() { + return this._response.compareToIgnoreCase("Success") == 0; //$NON-NLS-1$ + } } diff --git a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/userEvents/UserEvent.java b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/userEvents/UserEvent.java index 24bfc3078..d9dada2b9 100644 --- a/src/main/java/org/asteriskjava/pbx/asterisk/wrap/userEvents/UserEvent.java +++ b/src/main/java/org/asteriskjava/pbx/asterisk/wrap/userEvents/UserEvent.java @@ -6,28 +6,24 @@ import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; -public class UserEvent extends ManagerEvent -{ +public class UserEvent extends ManagerEvent { private static final long serialVersionUID = 1L; private Channel channel; - public UserEvent(org.asteriskjava.manager.event.UserEvent source, Channel channel) - { + public UserEvent(org.asteriskjava.manager.event.UserEvent source, Channel channel) { super(source); this.channel = channel; } - public UserEvent(org.asteriskjava.manager.event.UserEvent event) throws InvalidChannelName - { + public UserEvent(org.asteriskjava.manager.event.UserEvent event) throws InvalidChannelName { super(event); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); this.channel = pbx.internalRegisterChannel(event.getChannel(), event.getUniqueId()); } - public Channel getChannel() - { + public Channel getChannel() { return this.channel; } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java index 1554c0a40..fb490819d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ActivityHelper.java @@ -1,16 +1,7 @@ package org.asteriskjava.pbx.internal.activity; -import java.util.HashSet; -import java.util.Set; - import org.asteriskjava.lock.Lockable; -import org.asteriskjava.pbx.Activity; -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.ActivityStatusEnum; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.asterisk.wrap.actions.SetVarAction; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; @@ -19,8 +10,10 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public abstract class ActivityHelper extends Lockable implements Runnable, Activity -{ +import java.util.HashSet; +import java.util.Set; + +public abstract class ActivityHelper extends Lockable implements Runnable, Activity { private static final Log logger = LogFactory.getLog(ActivityHelper.class); /** @@ -42,46 +35,37 @@ public abstract class ActivityHelper extends Lockable implem Exception callSite = new Exception("Invoked from here"); - public ActivityHelper(final String activityName, final ActivityCallback callback) - { + public ActivityHelper(final String activityName, final ActivityCallback callback) { this.callback = callback; this.activityName = activityName; } - private AutoCloseable getManagerListener() - { - if (!_sendEvents) - { - return new AutoCloseable() - { + private AutoCloseable getManagerListener() { + if (!_sendEvents) { + return new AutoCloseable() { @Override - public void close() throws Exception - { + public void close() throws Exception { // do nothing, we never started anything } }; } - EventListenerBaseClass listener = new EventListenerBaseClass(activityName, PBXFactory.getActivePBX()) - { + EventListenerBaseClass listener = new EventListenerBaseClass(activityName, PBXFactory.getActivePBX()) { @Override - public Set> requiredEvents() - { + public Set> requiredEvents() { return ActivityHelper.this.requiredEvents(); } @Override - public void onManagerEvent(ManagerEvent event) - { + public void onManagerEvent(ManagerEvent event) { ActivityHelper.this.onManagerEvent(event); } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ActivityHelper.this.getPriority(); } }; @@ -91,11 +75,9 @@ public ListenerPriority getPriority() } @SuppressWarnings("unchecked") - public void startActivity(final boolean sendEvents) - { + public void startActivity(final boolean sendEvents) { this._sendEvents = sendEvents; - if (this.callback != null) - { + if (this.callback != null) { this.callback.progress((T) this, ActivityStatusEnum.START, ActivityStatusEnum.START.getDefaultMessage()); } @@ -107,35 +89,23 @@ public void startActivity(final boolean sendEvents) @Override @SuppressWarnings("unchecked") - public void run() - { - try (AutoCloseable closer = getManagerListener()) - { + public void run() { + try (AutoCloseable closer = getManagerListener()) { this._success = this.doActivity(); - } - catch (final PBXException e) - { + } catch (final PBXException e) { this.lastException = e; ActivityHelper.logger.error(e, e); logger.error(callSite, callSite); - } - catch (final Throwable e) - { + } catch (final Throwable e) { this.lastException = new PBXException(e); ActivityHelper.logger.error(callSite, callSite); logger.error(e, e); - } - finally - { - if (this.callback != null) - { - if (this._success) - { + } finally { + if (this.callback != null) { + if (this._success) { this.callback.progress((T) this, ActivityStatusEnum.SUCCESS, ActivityStatusEnum.SUCCESS.getDefaultMessage()); - } - else - { + } else { // This went badly so make certain we hang everything up this.callback.progress((T) this, ActivityStatusEnum.FAILURE, ActivityStatusEnum.FAILURE.getDefaultMessage()); @@ -151,25 +121,20 @@ public void run() * Attempt to set a variable on the channel to see if it's up. * @param channel the channel which is to be tested. */ - public boolean validateChannel(final Channel channel) - { + public boolean validateChannel(final Channel channel) { boolean ret = false; final SetVarAction var = new SetVarAction(channel, "testState", "1"); ManagerResponse response = null; - try - { + try { AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); response = pbx.sendAction(var, 500); - } - catch (final Exception e) - { + } catch (final Exception e) { ActivityHelper.logger.debug(e, e); ActivityHelper.logger.error("getVariable: " + e); } - if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) - { + if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) { ret = true; } @@ -178,29 +143,25 @@ public boolean validateChannel(final Channel channel) } @Override - public boolean isSuccess() - { + public boolean isSuccess() { return this._success; } - protected void setLastException(final PBXException e) - { + protected void setLastException(final PBXException e) { this.lastException = e; } @Override - public Throwable getLastException() - { + public Throwable getLastException() { return this.lastException; } - public void progess(final T activity, final String message) - { + public void progess(final T activity, final String message) { this.callback.progress(activity, ActivityStatusEnum.PROGRESS, message); } - abstract HashSet> requiredEvents(); + abstract HashSet> requiredEvents(); abstract void onManagerEvent(final ManagerEvent event); diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java index 9b087704d..73f63ae9a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BlindTransferActivityImpl.java @@ -1,43 +1,28 @@ package org.asteriskjava.pbx.internal.activity; -import java.util.HashSet; -import java.util.Objects; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - import org.asteriskjava.lock.Locker.LockCloser; -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.Call.OperandChannel; -import org.asteriskjava.pbx.CallDirection; -import org.asteriskjava.pbx.CallImpl; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.activities.BlindTransferActivity; import org.asteriskjava.pbx.agi.AgiChannelActivityBlindTransfer; import org.asteriskjava.pbx.agi.BlindTransferResultListener; -import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.DialEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.*; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.HashSet; +import java.util.Objects; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + /** * The BlindTransferActivity is used by the AsteriksPBX to transfer a live * channel to an endpoint that may need to be dialed. - * + * * @author bsutton */ -public class BlindTransferActivityImpl extends ActivityHelper implements BlindTransferActivity -{ +public class BlindTransferActivityImpl extends ActivityHelper implements BlindTransferActivity { private static final Log logger = LogFactory.getLog(BlindTransferActivityImpl.class); private final Call _call; @@ -72,18 +57,17 @@ public class BlindTransferActivityImpl extends ActivityHelper listener, String dialOptions) - { + final CallerID toCallerID, boolean autoAnswer, long timeout, + final ActivityCallback listener, String dialOptions) { super("BlindTransferActivity", listener); this._call = Objects.requireNonNull(call); @@ -100,8 +84,7 @@ public BlindTransferActivityImpl(Call call, final Call.OperandChannel channelToT } public BlindTransferActivityImpl(Channel agentChannel, EndPoint transferTarget, CallerID toCallerID, boolean autoAnswer, - int timeout, ActivityCallback iCallback, String dialOptions) throws PBXException - { + int timeout, ActivityCallback iCallback, String dialOptions) throws PBXException { super("BlindTransferActivity", iCallback); this._transferTarget = transferTarget; @@ -117,8 +100,7 @@ public BlindTransferActivityImpl(Channel agentChannel, EndPoint transferTarget, } @Override - public boolean doActivity() throws PBXException - { + public boolean doActivity() throws PBXException { boolean success = false; AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -127,8 +109,7 @@ public boolean doActivity() throws PBXException * when a link event occurs this call will be removed from the active * call list. */ - try - { + try { logger.debug("*******************************************************************************"); logger.info("*********** begin blind transfer ****************"); @@ -137,8 +118,7 @@ public boolean doActivity() throws PBXException logger.debug("*********** " + this._toCallerID + " ****************"); logger.debug("*******************************************************************************"); - if (!pbx.moveChannelToAgi(actualChannelToTransfer)) - { + if (!pbx.moveChannelToAgi(actualChannelToTransfer)) { throw new PBXException("Channel: " + this._channelToTransfer + " couldn't be moved to agi"); } @@ -151,21 +131,17 @@ public boolean doActivity() throws PBXException // initial answer sequence. If we don't clear it then then transfer // target will be auto-answered, which is fun but bad. String sipHeader = null; - if (this._autoAnswer) - { + if (this._autoAnswer) { sipHeader = PBXFactory.getActiveProfile().getAutoAnswer(); } this._latch = new CountDownLatch(1); - BlindTransferResultListener listener = new BlindTransferResultListener() - { + BlindTransferResultListener listener = new BlindTransferResultListener() { @Override - public void result(String status, boolean success) - { - if (_completionCause == null) - { + public void result(String status, boolean success) { + if (_completionCause == null) { _completionCause = CompletionCause.FAILED; } _latch.countDown(); @@ -183,33 +159,22 @@ public void result(String status, boolean success) // TODO control the caller id. success = this._latch.await(this._timeout, TimeUnit.SECONDS); - if (!success) - { + if (!success) { this._completionCause = CompletionCause.TIMEOUT; - } - else if (_completionCause == CompletionCause.CANCELLED) - { + } else if (_completionCause == CompletionCause.CANCELLED) { logger.warn("Cancelled, hanging up dialed channel"); pbx.hangup(dialedChannel); - } - - else - { + } else { Call call = ((CallImpl) _call).split(actualChannelToTransfer); Call rhsCall = new CallImpl(_transferTargetChannel, CallDirection.OUTBOUND); - try - { + try { _newCall = ((CallImpl) call).join(OperandChannel.ORIGINATING_PARTY, rhsCall, OperandChannel.ORIGINATING_PARTY, CallDirection.OUTBOUND); - } - catch (Exception e) - { + } catch (Exception e) { logger.error("New call doesn't seem to exist!?"); } } - } - catch (final Exception e) - { + } catch (final Exception e) { logger.error("error occurred in blindtransfer", e); this.setLastException(new PBXException(e)); } @@ -218,9 +183,8 @@ else if (_completionCause == CompletionCause.CANCELLED) } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); required.add(BridgeEvent.class); required.add(LinkEvent.class); @@ -231,51 +195,36 @@ else if (_completionCause == CompletionCause.CANCELLED) } @Override - public void onManagerEvent(final ManagerEvent event) - { - try (LockCloser closer = this.withLock()) - { - if (event instanceof BridgeEvent) - { + public void onManagerEvent(final ManagerEvent event) { + try (LockCloser closer = this.withLock()) { + if (event instanceof BridgeEvent) { BridgeEvent bridge = (BridgeEvent) event; - if (bridge.isLink()) - { - if (bridge.getChannel1().isSame(_call.getOperandChannel(this._channelToTransfer))) - { + if (bridge.isLink()) { + if (bridge.getChannel1().isSame(_call.getOperandChannel(this._channelToTransfer))) { this._completionCause = CompletionCause.BRIDGED; this._transferTargetChannel = bridge.getChannel2(); this._latch.countDown(); - } - else if (bridge.getChannel2().isSame(_call.getOperandChannel(this._channelToTransfer))) - { + } else if (bridge.getChannel2().isSame(_call.getOperandChannel(this._channelToTransfer))) { this._completionCause = CompletionCause.BRIDGED; this._transferTargetChannel = bridge.getChannel1(); this._latch.countDown(); } } - } - else if (event instanceof HangupEvent) - { + } else if (event instanceof HangupEvent) { HangupEvent hangup = (HangupEvent) event; - if (hangup.getChannel().isSame(_call.getOperandChannel(this._channelToTransfer))) - { + if (hangup.getChannel().isSame(_call.getOperandChannel(this._channelToTransfer))) { this._completionCause = CompletionCause.HANGUP; this._latch.countDown(); } - if (hangup.getChannel().isSame(dialedChannel)) - { + if (hangup.getChannel().isSame(dialedChannel)) { this._completionCause = CompletionCause.HANGUP; this._latch.countDown(); } - } - else if (event instanceof DialEvent) - { + } else if (event instanceof DialEvent) { DialEvent dialEvent = (DialEvent) event; - if (dialEvent.getChannel() != null) - { + if (dialEvent.getChannel() != null) { Channel operandChannel = _call.getOperandChannel(_channelToTransfer); - if (dialEvent.getChannel().isSame(operandChannel)) - { + if (dialEvent.getChannel().isSame(operandChannel)) { DialEvent de = (DialEvent) event; dialedChannel = de.getDestination(); } @@ -286,14 +235,12 @@ else if (event instanceof DialEvent) } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } @Override - public CompletionCause getCompletionCause() - { + public CompletionCause getCompletionCause() { return this._completionCause; } @@ -301,39 +248,33 @@ public CompletionCause getCompletionCause() * cancels the BlindTransfer. */ @Override - public void cancel() - { + public void cancel() { this._completionCause = CompletionCause.CANCELLED; this._latch.countDown(); } @Override - public Channel getChannelToTransfer() - { + public Channel getChannelToTransfer() { return _call.getOperandChannel(this._channelToTransfer); } @Override - public CallerID getTransferTargetCallerID() - { + public CallerID getTransferTargetCallerID() { return this._toCallerID; } @Override - public EndPoint getTransferTarget() - { + public EndPoint getTransferTarget() { return this._transferTarget; } @Override - public Channel getTransferTargetChannel() - { + public Channel getTransferTargetChannel() { return this._transferTargetChannel; } @Override - public Call getNewCall() throws PBXException - { + public Call getNewCall() throws PBXException { return _newCall; } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java index cd51e531a..0229b3499 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/BridgeActivityImpl.java @@ -1,30 +1,21 @@ package org.asteriskjava.pbx.internal.activity; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.activities.BridgeActivity; import org.asteriskjava.pbx.agi.AgiChannelActivityBridge; import org.asteriskjava.pbx.agi.AgiChannelActivityHoldForBridge; -import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.*; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class BridgeActivityImpl extends ActivityHelper implements BridgeActivity -{ +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class BridgeActivityImpl extends ActivityHelper implements BridgeActivity { private static final Log logger = LogFactory.getLog(BridgeActivityImpl.class); private final Channel _lhsChannel; private final Channel _rhsChannel; @@ -32,8 +23,7 @@ public class BridgeActivityImpl extends ActivityHelper implement private CountDownLatch _bridgeLatch; public BridgeActivityImpl(final Channel lhsChannel, final Channel rhsChannel, - final ActivityCallback callback) - { + final ActivityCallback callback) { super("Bridge", callback); this._lhsChannel = lhsChannel; @@ -42,8 +32,7 @@ public BridgeActivityImpl(final Channel lhsChannel, final Channel rhsChannel, } @Override - public boolean doActivity() throws PBXException - { + public boolean doActivity() throws PBXException { boolean success = false; BridgeActivityImpl.logger.debug("*******************************************************************************"); @@ -51,17 +40,14 @@ public boolean doActivity() throws PBXException BridgeActivityImpl.logger.info("*********** lhs:" + this._lhsChannel + " ****************"); BridgeActivityImpl.logger.debug("*********** rhs:" + this._rhsChannel + " ****************"); BridgeActivityImpl.logger.debug("*******************************************************************************"); - try - { + try { final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - if (!pbx.moveChannelToAgi(_lhsChannel)) - { + if (!pbx.moveChannelToAgi(_lhsChannel)) { throw new PBXException("Channel: " + _lhsChannel + " couldn't be moved to agi"); } - if (!pbx.moveChannelToAgi(_rhsChannel)) - { + if (!pbx.moveChannelToAgi(_rhsChannel)) { throw new PBXException("Channel: " + _rhsChannel + " couldn't be moved to agi"); } @@ -70,10 +56,8 @@ public boolean doActivity() throws PBXException channels.add(_rhsChannel); if (!pbx.waitForChannelsToQuiescent(channels, 3000)) throw new PBXException("Channel: " + this._lhsChannel + " cannot be held as it is still in transition."); - try - { - if (pbx.isBridgeSupported()) - { + try { + if (pbx.isBridgeSupported()) { this._bridgeLatch = new CountDownLatch(1); final AgiChannelActivityBridge action = new AgiChannelActivityBridge(_lhsChannel); @@ -84,15 +68,11 @@ public boolean doActivity() throws PBXException success = this._bridgeLatch.await(3, TimeUnit.SECONDS); } - } - catch (IllegalArgumentException | IllegalStateException | InterruptedException e) - { + } catch (IllegalArgumentException | IllegalStateException | InterruptedException e) { throw new PBXException(e); } - } - catch (IllegalArgumentException | IllegalStateException e) - { + } catch (IllegalArgumentException | IllegalStateException e) { BridgeActivityImpl.logger.error(e, e); BridgeActivityImpl.logger.error(e, e); throw new PBXException(e); @@ -101,9 +81,8 @@ public boolean doActivity() throws PBXException } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); required.add(StatusCompleteEvent.class); required.add(StatusEvent.class); required.add(BridgeEvent.class); @@ -112,17 +91,14 @@ public boolean doActivity() throws PBXException } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } @Override - public void onManagerEvent(ManagerEvent event) - { + public void onManagerEvent(ManagerEvent event) { - if (event instanceof BridgeEvent) - { + if (event instanceof BridgeEvent) { BridgeEvent bridge = (BridgeEvent) event; if (bridge.isLink() && (bridge.getChannel1().isSame(this._lhsChannel) || bridge.getChannel1().isSame(this._rhsChannel)) diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java index b3e11d2bb..106fc4762 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialActivityImpl.java @@ -1,21 +1,6 @@ package org.asteriskjava.pbx.internal.activity; -import java.util.HashSet; -import java.util.Map; - -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.Call; -import org.asteriskjava.pbx.CallDirection; -import org.asteriskjava.pbx.CallImpl; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.NewChannelListener; -import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.activities.DialActivity; import org.asteriskjava.pbx.asterisk.wrap.actions.SetVarAction; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; @@ -26,8 +11,10 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class DialActivityImpl extends ActivityHelper implements DialActivity, NewChannelListener -{ +import java.util.HashSet; +import java.util.Map; + +public class DialActivityImpl extends ActivityHelper implements DialActivity, NewChannelListener { private static final Log logger = LogFactory.getLog(DialActivityImpl.class); private final boolean hideToCallerId; @@ -57,9 +44,8 @@ public class DialActivityImpl extends ActivityHelper implements Di private String dialOptions; public DialActivityImpl(final EndPoint originating, final EndPoint accepting, final CallerID toCallerID, - final boolean hideToCallerID, final ActivityCallback listener, - Map channelVarsToSet, String dialOptions) - { + final boolean hideToCallerID, final ActivityCallback listener, + Map channelVarsToSet, String dialOptions) { super("Dial", listener); this._originating = originating; this._accepting = accepting; @@ -73,12 +59,10 @@ public DialActivityImpl(final EndPoint originating, final EndPoint accepting, fi } @Override - public boolean doActivity() throws PBXException - { + public boolean doActivity() throws PBXException { boolean success = false; - try (Dial nr = new Dial(this.toCallerID.toString())) - { + try (Dial nr = new Dial(this.toCallerID.toString())) { DialActivityImpl.logger.debug("*******************************************************************************"); DialActivityImpl.logger.info("*********** begin dial out ****************"); DialActivityImpl.logger.info("*********** " + this._accepting + " ****************"); @@ -89,20 +73,16 @@ public boolean doActivity() throws PBXException final OriginateResult[] resultChannels = nr.dial(this, this._originating, this._accepting, profile.getManagementContext(), this.toCallerID, this.hideToCallerId, channelVarsToSet, dialOptions); - if ((resultChannels[0] == null) || (resultChannels[1] == null)) - { + if ((resultChannels[0] == null) || (resultChannels[1] == null)) { // the dial failed // so notify the operator. // Unless the operated cancelled the call - if (!this.cancelledByOperator) - { + if (!this.cancelledByOperator) { this.setLastException(new PBXException(("OperatorEndedCall"))); DialActivityImpl.logger.error("dialout to " + this._accepting.getFullyQualifiedName() + " failed."); } - } - else - { + } else { // Dial succeeded. // - get new channel name from result @@ -113,45 +93,33 @@ public boolean doActivity() throws PBXException DialActivityImpl.logger.debug("dialout succeeded: dest channel is :" + this.acceptingChannel); - if (!this.validateChannel(this.acceptingChannel)) - { + if (!this.validateChannel(this.acceptingChannel)) { this.setLastException(new PBXException(("dialed extension hungup unexpectedly"))); DialActivityImpl.logger.error("dialed extension hungup unexpectedly"); - } - else - { + } else { success = true; } } - } - finally - { - if (!success) - { + } finally { + if (!success) { this.hangup(); } } return success; } - private void hangup() - { - try - { + private void hangup() { + try { final PBX pbx = PBXFactory.getActivePBX(); - if (this.acceptingChannel != null) - { + if (this.acceptingChannel != null) { logger.warn("Hanging up"); pbx.hangup(this.acceptingChannel); } - if (this.originatingChannel != null) - { + if (this.originatingChannel != null) { logger.warn("Hanging up"); pbx.hangup(this.originatingChannel); } - } - catch (final Exception e) - { + } catch (final Exception e) { DialActivityImpl.logger.error(e, e); } } @@ -161,45 +129,37 @@ private void hangup() * hangup the associated channels. */ @Override - public void markCancelled() - { + public void markCancelled() { this.cancelledByOperator = true; } @Override - public Channel getOriginatingChannel() - { + public Channel getOriginatingChannel() { return this.originatingChannel; } @Override - public Channel getAcceptingChannel() - { + public Channel getAcceptingChannel() { return this.acceptingChannel; } @Override - public EndPoint getOriginatingEndPoint() - { + public EndPoint getOriginatingEndPoint() { return this._originating; } @Override - public EndPoint getAcceptingEndPoint() - { + public EndPoint getAcceptingEndPoint() { return this._accepting; } @Override - public void channelUpdate(final Channel channel) - { - if (channel.sameEndPoint(this._accepting)) - { + public void channelUpdate(final Channel channel) { + if (channel.sameEndPoint(this._accepting)) { this.acceptingChannel = channel; } - if (channel.sameEndPoint(this._originating)) - { + if (channel.sameEndPoint(this._originating)) { this.originatingChannel = channel; } @@ -212,25 +172,20 @@ public void channelUpdate(final Channel channel) * @param channel the channel which is to be tested. */ @Override - public boolean validateChannel(final Channel channel) - { + public boolean validateChannel(final Channel channel) { boolean ret = false; final SetVarAction var = new SetVarAction(channel, "testState", "1"); ManagerResponse response = null; - try - { + try { AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); response = pbx.sendAction(var, 500); - } - catch (final Exception e) - { + } catch (final Exception e) { DialActivityImpl.logger.debug(e, e); DialActivityImpl.logger.error("getVariable: " + e); } - if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) - { + if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) { ret = true; } @@ -239,34 +194,29 @@ public boolean validateChannel(final Channel channel) } @Override - public boolean cancelledByOperator() - { + public boolean cancelledByOperator() { return this.cancelledByOperator; } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); // no required. return required; } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } @Override - public void onManagerEvent(ManagerEvent event) - { + public void onManagerEvent(ManagerEvent event) { // NOOP } @Override - public Call getNewCall() - { + public Call getNewCall() { return newCall; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java index 46deff592..7304e5565 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/DialToAgiActivityImpl.java @@ -1,18 +1,6 @@ package org.asteriskjava.pbx.internal.activity; -import java.util.HashSet; -import java.util.Map; - -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.AgiChannelActivityAction; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.NewChannelListener; -import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.activities.DialToAgiActivity; import org.asteriskjava.pbx.asterisk.wrap.actions.SetVarAction; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; @@ -23,8 +11,10 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class DialToAgiActivityImpl extends ActivityHelper implements DialToAgiActivity, NewChannelListener -{ +import java.util.HashSet; +import java.util.Map; + +public class DialToAgiActivityImpl extends ActivityHelper implements DialToAgiActivity, NewChannelListener { private static final Log logger = LogFactory.getLog(DialToAgiActivityImpl.class); private final boolean hideToCallerId; @@ -49,9 +39,8 @@ public class DialToAgiActivityImpl extends ActivityHelper imp private Integer timeout; public DialToAgiActivityImpl(final EndPoint originating, final CallerID toCallerID, Integer timeout, - final boolean hideToCallerID, final ActivityCallback listener, - Map channelVarsToSet, AgiChannelActivityAction action) - { + final boolean hideToCallerID, final ActivityCallback listener, + Map channelVarsToSet, AgiChannelActivityAction action) { super("Dial", listener); this.timeout = timeout; this.action = action; @@ -63,18 +52,15 @@ public DialToAgiActivityImpl(final EndPoint originating, final CallerID toCaller } - public void dial() - { + public void dial() { this.startActivity(false); } @Override - public boolean doActivity() throws PBXException - { + public boolean doActivity() throws PBXException { boolean success = false; - try (DialToAgi nr = new DialToAgi(this.toCallerID.toString())) - { + try (DialToAgi nr = new DialToAgi(this.toCallerID.toString())) { DialToAgiActivityImpl.logger.debug("**************************************************************************"); DialToAgiActivityImpl.logger .info("*********** begin dial out to agi " + _originating + " ***********"); @@ -85,20 +71,16 @@ public boolean doActivity() throws PBXException final OriginateResult[] resultChannels = nr.dial(this, this._originating, this.action, this.toCallerID, this.timeout, this.hideToCallerId, channelVarsToSet); - if (resultChannels[0] == null || !resultChannels[0].isSuccess()) - { + if (resultChannels[0] == null || !resultChannels[0].isSuccess()) { // the dial failed // so notify the operator. // Unless the operated cancelled the call - if (!this.cancelledByOperator) - { + if (!this.cancelledByOperator) { this.setLastException(new PBXException(("OperatorEndedCall"))); logger.warn("dialout to " + _originating + " failed."); } - } - else - { + } else { // Dial succeeded. // - get new channel name from result @@ -109,35 +91,25 @@ public boolean doActivity() throws PBXException success = true; } - } - catch (InterruptedException e) - { + } catch (InterruptedException e) { logger.error(e); - } - finally - { - if (!success) - { + } finally { + if (!success) { this.hangup(); } } return success; } - private void hangup() - { - try - { + private void hangup() { + try { final PBX pbx = PBXFactory.getActivePBX(); - if (this.originatingChannel != null) - { + if (this.originatingChannel != null) { logger.info("Hanging up"); pbx.hangup(this.originatingChannel); } - } - catch (final Exception e) - { + } catch (final Exception e) { DialToAgiActivityImpl.logger.error(e, e); } } @@ -147,29 +119,24 @@ private void hangup() * also hangup the trc channel. */ @Override - public void markCancelled() - { + public void markCancelled() { this.cancelledByOperator = true; } @Override - public Channel getOriginatingChannel() - { + public Channel getOriginatingChannel() { return this.originatingChannel; } @Override - public EndPoint getOriginatingEndPoint() - { + public EndPoint getOriginatingEndPoint() { return this._originating; } @Override - public void channelUpdate(final Channel channel) - { + public void channelUpdate(final Channel channel) { - if (channel.sameEndPoint(this._originating)) - { + if (channel.sameEndPoint(this._originating)) { this.originatingChannel = channel; } @@ -182,25 +149,20 @@ public void channelUpdate(final Channel channel) * @param channel the channel which is to be tested. */ @Override - public boolean validateChannel(final Channel channel) - { + public boolean validateChannel(final Channel channel) { boolean ret = false; final SetVarAction var = new SetVarAction(channel, "testState", "1"); ManagerResponse response = null; - try - { + try { AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); response = pbx.sendAction(var, 500); - } - catch (final Exception e) - { + } catch (final Exception e) { DialToAgiActivityImpl.logger.debug(e, e); DialToAgiActivityImpl.logger.error("getVariable: " + e); } - if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) - { + if ((response != null) && (response.getAttribute("Response").compareToIgnoreCase("success") == 0)) { ret = true; } @@ -209,39 +171,31 @@ public boolean validateChannel(final Channel channel) } @Override - public boolean cancelledByOperator() - { + public boolean cancelledByOperator() { return this.cancelledByOperator; } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); // no required. return required; } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } @Override - public void onManagerEvent(ManagerEvent event) - { + public void onManagerEvent(ManagerEvent event) { // NOOP } - public void abort() - { - if (originator != null) - { + public void abort() { + if (originator != null) { originator.abort(); - } - else - { + } else { logger.error("Call to abort, but it doesn't look like the Dial had started yet"); } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java index f8fd68287..835cda768 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/HoldActivityImpl.java @@ -1,12 +1,6 @@ package org.asteriskjava.pbx.internal.activity; -import java.util.HashSet; - -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.activities.HoldActivity; import org.asteriskjava.pbx.agi.AgiChannelActivityHold; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; @@ -14,13 +8,13 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class HoldActivityImpl extends ActivityHelper implements HoldActivity -{ +import java.util.HashSet; + +public class HoldActivityImpl extends ActivityHelper implements HoldActivity { private static final Log logger = LogFactory.getLog(HoldActivityImpl.class); private final Channel _channel; - public HoldActivityImpl(final Channel channel, final ActivityCallback callback) - { + public HoldActivityImpl(final Channel channel, final ActivityCallback callback) { super("HoldCall", callback); this._channel = channel; @@ -28,29 +22,24 @@ public HoldActivityImpl(final Channel channel, final ActivityCallback> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); // no events requried. return required; } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } @Override - public void onManagerEvent(ManagerEvent event) - { + public void onManagerEvent(ManagerEvent event) { // NOOP } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java index 7538d1d97..fc0caacd8 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/JoinActivityImpl.java @@ -1,35 +1,27 @@ package org.asteriskjava.pbx.internal.activity; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; - -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.Call.OperandChannel; -import org.asteriskjava.pbx.CallDirection; -import org.asteriskjava.pbx.CallImpl; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.activities.JoinActivity; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + /** * The JoinActivity is used by the AsteriksPBX implementation to Join two * channels into a single call. The join activity expects two channels which are * each a leg of a different call it will then join those two channels into a * single call.iChannel hangupChannel, The channels that remain in the * originating calls will be hungup implicitly. - * + * * @author bsutton */ -public class JoinActivityImpl extends ActivityHelper implements JoinActivity -{ +public class JoinActivityImpl extends ActivityHelper implements JoinActivity { private static final Log logger = LogFactory.getLog(JoinActivityImpl.class); @@ -48,19 +40,18 @@ public class JoinActivityImpl extends ActivityHelper implements Jo * Joins a specific channel from this call with a specific channel from * another call which results in a new Call object being created. Channels * that do not participate in the join are left in their original Call. - * - * @param lhsCall one of the calls we are joining + * + * @param lhsCall one of the calls we are joining * @param originatingOperand the channel from lhsCall call that will - * participate in the join as the originating Channel - * @param rhsCall the other call we are joining. - * @param acceptingOperand the channel from the rhsCall that will - * participate in the join as the accepting channel. + * participate in the join as the originating Channel + * @param rhsCall the other call we are joining. + * @param acceptingOperand the channel from the rhsCall that will + * participate in the join as the accepting channel. * @return * @throws PBXException */ public JoinActivityImpl(final Call lhsCall, OperandChannel originatingOperand, final Call rhsCall, - OperandChannel acceptingOperand, CallDirection direction, final ActivityCallback listener) - { + OperandChannel acceptingOperand, CallDirection direction, final ActivityCallback listener) { super("JoinActivity", listener); callSite = new Exception("Call site"); @@ -71,23 +62,19 @@ public JoinActivityImpl(final Call lhsCall, OperandChannel originatingOperand, f this._acceptingOperand = acceptingOperand; this._direction = direction; - if (this._lhsCall == null) - { + if (this._lhsCall == null) { throw new IllegalArgumentException("lhsCall may not be null"); } - if (this._originatingOperand == null) - { + if (this._originatingOperand == null) { throw new IllegalArgumentException("lhsOperand may not be null"); } - if (this._rhsCall == null) - { + if (this._rhsCall == null) { throw new IllegalArgumentException("rhsCall may not be null"); } - if (this._acceptingOperand == null) - { + if (this._acceptingOperand == null) { throw new IllegalArgumentException("rhsOperand may not be null"); } @@ -95,8 +82,7 @@ public JoinActivityImpl(final Call lhsCall, OperandChannel originatingOperand, f } @Override - public boolean doActivity() throws PBXException - { + public boolean doActivity() throws PBXException { boolean success = false; final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -106,25 +92,21 @@ public boolean doActivity() throws PBXException JoinActivityImpl.logger.debug("*********** " + this._rhsCall + " ****************"); JoinActivityImpl.logger.debug("*******************************************************************************"); - try - { + try { final Channel rhsChannel = this._rhsCall.getOperandChannel(this._acceptingOperand); final Channel lhsChannel = this._lhsCall.getOperandChannel(this._originatingOperand); - if (!pbx.moveChannelToAgi(rhsChannel)) - { + if (!pbx.moveChannelToAgi(rhsChannel)) { throw new PBXException("Channel: " + rhsChannel + " couldn't be moved to agi"); } - if (!pbx.moveChannelToAgi(lhsChannel)) - { + if (!pbx.moveChannelToAgi(lhsChannel)) { throw new PBXException("Channel: " + lhsChannel + " couldn't be moved to agi"); } List channels = new LinkedList<>(); channels.add(lhsChannel); channels.add(rhsChannel); - if (!pbx.waitForChannelsToQuiescent(channels, 3000)) - { + if (!pbx.waitForChannelsToQuiescent(channels, 3000)) { logger.error(callSite, callSite); throw new PBXException("Channel: " + rhsChannel + " cannot be joined as it is still in transition."); } @@ -134,9 +116,7 @@ public boolean doActivity() throws PBXException this._direction); success = true; - } - catch (RuntimeException e) - { + } catch (RuntimeException e) { logger.error(e, e); logger.error(callSite, callSite); throw new PBXException(e); @@ -146,28 +126,24 @@ public boolean doActivity() throws PBXException } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); return required; } @Override - synchronized public void onManagerEvent(final ManagerEvent event) - { + synchronized public void onManagerEvent(final ManagerEvent event) { // NOOP } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } @Override - public Call getJoinedCall() - { + public Call getJoinedCall() { return this._joined; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java index 928fe6080..53000e297 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/ParkActivityImpl.java @@ -1,22 +1,8 @@ package org.asteriskjava.pbx.internal.activity; -import java.io.IOException; -import java.util.HashSet; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.TimeoutException; -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.Call; -import org.asteriskjava.pbx.CallDirection; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.TechType; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.activities.ParkActivity; import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; @@ -26,6 +12,11 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.io.IOException; +import java.util.HashSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + /** * The ParkActivity is used by the AsteriksPBX implementation to park a channel. * The park activity expects two channels which are two legs legs of the same @@ -33,11 +24,10 @@ * hangupChannel (the second leg of the call) will be hung up. The (obvious?) * limitation is that we can't park something like a conference call as it has * more than two channels. - * + * * @author bsutton */ -public class ParkActivityImpl extends ActivityHelper implements ParkActivity -{ +public class ParkActivityImpl extends ActivityHelper implements ParkActivity { private static final Log logger = LogFactory.getLog(ParkActivityImpl.class); /** @@ -60,16 +50,13 @@ public class ParkActivityImpl extends ActivityHelper implements Pa * @param parkChannel the channel from the call which is the one which will * be parked. All other channels in the call will be hungup. */ - public ParkActivityImpl(final Call call, final Channel parkChannel, final ActivityCallback listener) - { + public ParkActivityImpl(final Call call, final Channel parkChannel, final ActivityCallback listener) { super("ParkActivity", listener); - if (call == null) - { + if (call == null) { throw new IllegalArgumentException("call may not be null"); } - if (parkChannel == null) - { + if (parkChannel == null) { throw new IllegalArgumentException("parkChannel may not be null"); } this._parkChannel = parkChannel; @@ -82,8 +69,7 @@ public ParkActivityImpl(final Call call, final Channel parkChannel, final Activi } @Override - public boolean doActivity() throws PBXException - { + public boolean doActivity() throws PBXException { boolean success = false; final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); @@ -92,8 +78,7 @@ public boolean doActivity() throws PBXException ParkActivityImpl.logger.info("*********** " + this._parkChannel + " ****************"); ParkActivityImpl.logger.debug("*******************************************************************************"); - try - { + try { final AsteriskSettings profile = PBXFactory.getActiveProfile(); if (!pbx.waitForChannelToQuiescent(this._parkChannel, 3000)) @@ -105,53 +90,39 @@ public boolean doActivity() throws PBXException pbx.getExtensionPark(), 1); final ManagerResponse response = pbx.sendAction(redirect, 1000); - if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0)) - { + if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0)) { // Hangup the call as we have parked the other side of // the call. - if (this._call.getDirection() == CallDirection.INBOUND) - { + if (this._call.getDirection() == CallDirection.INBOUND) { logger.warn("Hanging up"); pbx.hangup(this._call.getAcceptingParty()); - } - else - { + } else { logger.warn("Hanging up"); pbx.hangup(this._call.getOriginatingParty()); } success = true; } - } - catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) - { + } catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) { ParkActivityImpl.logger.error(e, e); throw new PBXException(e); - } - finally - { + } finally { // we wait at most 2 seconds for the parking extension to // arrive. - try - { - if (success) - { - if (!this._latch.await(2, TimeUnit.SECONDS)) - { + try { + if (success) { + if (!this._latch.await(2, TimeUnit.SECONDS)) { logger.warn("Timeout, continuing"); } } - if (this._parkingLot == null) - { + if (this._parkingLot == null) { success = false; ParkActivityImpl.logger.warn("ParkCallEvent not recieved within 2 seconds of parking call."); this.setLastException(new PBXException("ParkCallEvent not recieved within 2 seconds of parking call.")); } - } - catch (final InterruptedException e) - { + } catch (final InterruptedException e) { ParkActivityImpl.logger.error(e, e); } @@ -161,15 +132,13 @@ public boolean doActivity() throws PBXException } @Override - public EndPoint getParkingLot() - { + public EndPoint getParkingLot() { return this._parkingLot; } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); required.add(ParkedCallEvent.class); @@ -177,10 +146,8 @@ public EndPoint getParkingLot() } @Override - public void onManagerEvent(final ManagerEvent event) - { - try (LockCloser closer = this.withLock()) - { + public void onManagerEvent(final ManagerEvent event) { + try (LockCloser closer = this.withLock()) { assert event instanceof ParkedCallEvent : "Unexpected event"; final ParkedCallEvent parkedEvent = (ParkedCallEvent) event; @@ -192,8 +159,7 @@ public void onManagerEvent(final ManagerEvent event) } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java index 1ab3fa7aa..5c30dfa3a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/RedirectToActivityImpl.java @@ -1,19 +1,6 @@ package org.asteriskjava.pbx.internal.activity; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; - -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.Call; -import org.asteriskjava.pbx.CallDirection; -import org.asteriskjava.pbx.CallImpl; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.activities.RedirectToActivity; import org.asteriskjava.pbx.agi.AgiChannelActivityHold; import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; @@ -23,16 +10,19 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + /** * The SplitActivity is used by the AsteriksPBX to split a call and place the * component channels into the specialist Activity fastagi. The SplitActivity * can only split a call with two channels. The (obvious?) limitation is that we * can't split something in a conference call as it has more than two channels. - * + * * @author bsutton */ -public class RedirectToActivityImpl extends ActivityHelper implements RedirectToActivity -{ +public class RedirectToActivityImpl extends ActivityHelper implements RedirectToActivity { private static final Log logger = LogFactory.getLog(RedirectToActivityImpl.class); private Channel channel1; @@ -43,12 +33,11 @@ public class RedirectToActivityImpl extends ActivityHelper i * Splits a call by moving each of its two channels into the Activity agi. * The channels will sit in the agi (with no audio) until something is done * with them. As such you should leave them split for too long. - * + * * @param callToSplit The call to split * @param listener */ - public RedirectToActivityImpl(final Channel channel1, final ActivityCallback listener) - { + public RedirectToActivityImpl(final Channel channel1, final ActivityCallback listener) { super("SplitActivity", listener); this.channel1 = channel1; @@ -57,8 +46,7 @@ public RedirectToActivityImpl(final Channel channel1, final ActivityCallback> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); // No events required. return required; } @Override - synchronized public void onManagerEvent(final ManagerEvent event) - { + synchronized public void onManagerEvent(final ManagerEvent event) { // NOOP } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } /** * After a call has been split we get two new calls. One will hold the * original remote party and the other will hold the original local party. - * + * * @return the call which holds the original remote party. */ @Override - public Call getCall() - { + public Call getCall() { return this._lhsCall; } /** * After a call has been split we get two new calls. One will hold the * original remote party and the other will hold the original local party. - * + * * @return the call which holds the original local party. */ /** * Splits two channels moving them to defined endpoints. - * + * * @param lhs * @param lhsTarget * @param lhsTargetContext @@ -135,15 +117,13 @@ public Call getCall() * @return * @throws PBXException */ - private boolean splitTwo() throws PBXException - { + private boolean splitTwo() throws PBXException { final AsteriskSettings profile = PBXFactory.getActiveProfile(); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); List channels = new LinkedList<>(); channels.add(channel1); - if (!pbx.waitForChannelsToQuiescent(channels, 3000)) - { + if (!pbx.waitForChannelsToQuiescent(channels, 3000)) { logger.error(callSite, callSite); throw new PBXException("Channel: " + channel1 + " cannot be split as they are still in transition."); } @@ -169,27 +149,22 @@ private boolean splitTwo() throws PBXException boolean ret = false; { - try - { + try { // final ManagerResponse response = pbx.sendAction(redirect, 1000); double ctr = 0; - while (!agi1.hasCallReachedAgi() && ctr < 10) - { + while (!agi1.hasCallReachedAgi() && ctr < 10) { Thread.sleep(100); ctr += 100.0 / 1000.0; - if (!agi1.hasCallReachedAgi()) - { + if (!agi1.hasCallReachedAgi()) { logger.warn("Waiting on (agi1) " + channel1); } } ret = agi1.hasCallReachedAgi(); - } - catch (final Exception e) - { + } catch (final Exception e) { logger.error(e, e); } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java index 448fc610b..9fa432ca1 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/activity/SplitActivityImpl.java @@ -1,22 +1,7 @@ package org.asteriskjava.pbx.internal.activity; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - import org.asteriskjava.lock.Locker.LockCloser; -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.Call; -import org.asteriskjava.pbx.CallImpl; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.activities.SplitActivity; import org.asteriskjava.pbx.agi.AgiChannelActivityBridge; import org.asteriskjava.pbx.agi.AgiChannelActivityHold; @@ -28,16 +13,22 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + /** * The SplitActivity is used by the AsteriksPBX to split a call and place the * component channels into the specialist Activity fastagi. The SplitActivity * can only split a call with two channels. The (obvious?) limitation is that we * can't split something in a conference call as it has more than two channels. - * + * * @author bsutton */ -public class SplitActivityImpl extends ActivityHelper implements SplitActivity -{ +public class SplitActivityImpl extends ActivityHelper implements SplitActivity { private static final Log logger = LogFactory.getLog(SplitActivityImpl.class); private Call _callToSplit; @@ -54,20 +45,18 @@ public class SplitActivityImpl extends ActivityHelper implements * Splits a call by moving each of its two channels into the Activity agi. * The channels will sit in the agi (with no audio) until something is done * with them. As such you should leave them split for too long. - * + * * @param callToSplit The call to split * @param listener */ - public SplitActivityImpl(final Call callToSplit, final ActivityCallback listener) - { + public SplitActivityImpl(final Call callToSplit, final ActivityCallback listener) { super("SplitActivity", listener); renameEventReceived.set(new CountDownLatch(1)); this._callToSplit = callToSplit; List tmp = callToSplit.getChannels(); - if (tmp.size() > 1) - { + if (tmp.size() > 1) { channel1 = tmp.get(0); channel2 = tmp.get(1); } @@ -76,8 +65,7 @@ public SplitActivityImpl(final Call callToSplit, final ActivityCallback> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); required.add(RenameEvent.class); return required; @@ -116,15 +101,11 @@ public boolean doActivity() throws PBXException final AtomicReference renameEventReceived = new AtomicReference<>(); @Override - public void onManagerEvent(final ManagerEvent event) - { - try (LockCloser closer = this.withLock()) - { - if (event instanceof RenameEvent) - { + public void onManagerEvent(final ManagerEvent event) { + try (LockCloser closer = this.withLock()) { + if (event instanceof RenameEvent) { RenameEvent rename = (RenameEvent) event; - if (rename.getChannel().isSame(channel1) || rename.getChannel().isSame(channel2)) - { + if (rename.getChannel().isSame(channel1) || rename.getChannel().isSame(channel2)) { renameEventReceived.get().countDown(); } } @@ -132,38 +113,35 @@ public void onManagerEvent(final ManagerEvent event) } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } /** * After a call has been split we get two new calls. One will hold the * original remote party and the other will hold the original local party. - * + * * @return the call which holds the original remote party. */ @Override - public Call getLHSCall() - { + public Call getLHSCall() { return this._lhsCall; } /** * After a call has been split we get two new calls. One will hold the * original remote party and the other will hold the original local party. - * + * * @return the call which holds the original local party. */ @Override - public Call getRHSCall() - { + public Call getRHSCall() { return this._rhsCall; } /** * Splits two channels moving them to defined endpoints. - * + * * @param lhs * @param lhsTarget * @param lhsTargetContext @@ -173,21 +151,18 @@ public Call getRHSCall() * @return * @throws PBXException */ - private boolean splitTwo() throws PBXException - { + private boolean splitTwo() throws PBXException { final AsteriskSettings profile = PBXFactory.getActiveProfile(); AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - if (channel1 == channel2) - { + if (channel1 == channel2) { throw new PBXException("channel1 is the same as channel2. if I let this happen, asterisk will core dump :)"); } List channels = new LinkedList<>(); channels.add(channel1); channels.add(channel2); - if (!pbx.waitForChannelsToQuiescent(channels, 3000)) - { + if (!pbx.waitForChannelsToQuiescent(channels, 3000)) { logger.error(callSite, callSite); throw new PBXException( "Channel: " + channel1 + " or " + channel2 + " cannot be split as they are still in transition."); @@ -210,13 +185,10 @@ private boolean splitTwo() throws PBXException // taking an undesired action // when the AgiChannelActivityBridge channel has it's acitvity // cancelled. - if (channel2.getCurrentActivityAction() instanceof AgiChannelActivityBridge) - { + if (channel2.getCurrentActivityAction() instanceof AgiChannelActivityBridge) { channel1.setCurrentActivityAction(agi1); channel2.setCurrentActivityAction(agi2); - } - else - { + } else { channel2.setCurrentActivityAction(agi2); channel1.setCurrentActivityAction(agi1); } @@ -236,22 +208,17 @@ private boolean splitTwo() throws PBXException boolean ret = false; { - try - { + try { renameEventReceived.set(new CountDownLatch(1)); // final ManagerResponse response = pbx.sendAction(redirect, 1000); - if (pbx.expectRenameEvents()) - { + if (pbx.expectRenameEvents()) { // wait for channels to unbridge - if (!renameEventReceived.get().await(2000, TimeUnit.MILLISECONDS)) - { + if (!renameEventReceived.get().await(2000, TimeUnit.MILLISECONDS)) { logger.error("There was no rename event"); - } - else - { + } else { logger.warn("Channels are renaming, now waiting for Quiescent"); } } @@ -260,32 +227,26 @@ private boolean splitTwo() throws PBXException channels.add(channel1); channels.add(channel2); - if (!pbx.waitForChannelsToQuiescent(channels, 3000)) - { + if (!pbx.waitForChannelsToQuiescent(channels, 3000)) { logger.error(callSite, callSite); throw new PBXException("Channel: " + channel1 + " or " + channel2 + " cannot be split as they are still in transition."); } double ctr = 0; - while ((!agi1.hasCallReachedAgi() || !agi2.hasCallReachedAgi()) && ctr < 10) - { + while ((!agi1.hasCallReachedAgi() || !agi2.hasCallReachedAgi()) && ctr < 10) { Thread.sleep(100); ctr += 100.0 / 1000.0; - if (!agi1.hasCallReachedAgi()) - { + if (!agi1.hasCallReachedAgi()) { logger.info("Waiting on (agi1) " + channel1); } - if (!agi2.hasCallReachedAgi()) - { + if (!agi2.hasCallReachedAgi()) { logger.info("Waiting on (agi2) " + channel2); } } ret = agi1.hasCallReachedAgi() && agi2.hasCallReachedAgi(); - } - catch (final Exception e) - { + } catch (final Exception e) { logger.error(e, e); } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java index eac9d1df2..db7b773d2 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/CallerIDImpl.java @@ -3,33 +3,29 @@ import org.asteriskjava.pbx.CallerID; import org.asteriskjava.pbx.PBXFactory; -public class CallerIDImpl implements CallerID -{ +public class CallerIDImpl implements CallerID { private final String number; private final String name; private boolean hideCallerID = false; /** * Creates a caller ID. - * + * * @param number - if null then we store an empty string. - * @param name - if null then we store an empty string. + * @param name - if null then we store an empty string. */ - public CallerIDImpl(final String number, final String name) - { + public CallerIDImpl(final String number, final String name) { this.number = (number == null ? "" : number.trim()); //$NON-NLS-1$ this.name = (name == null ? "" : name.trim()); //$NON-NLS-1$ } @Override - public String getNumber() - { + public String getNumber() { return this.number; } @Override - public String getName() - { + public String getName() { return this.name; } @@ -37,24 +33,20 @@ public String getName() * This is a little helper class which will buid the name component of a * clid from the first and lastnames. If both firstname and lastname are * null then the name component will be an empty string. - * + * * @param firstname the person's firstname, may be null. - * @param lastname the person's lastname, may be null - * @param number the phone number. + * @param lastname the person's lastname, may be null + * @param number the phone number. * @return */ - public static CallerID buildFromComponents(final String firstname, final String lastname, final String number) - { + public static CallerID buildFromComponents(final String firstname, final String lastname, final String number) { String name = ""; //$NON-NLS-1$ - if (firstname != null) - { + if (firstname != null) { name += firstname.trim(); } - if (lastname != null) - { - if (name.length() > 0) - { + if (lastname != null) { + if (name.length() > 0) { name += " "; //$NON-NLS-1$ } name += lastname.trim(); @@ -67,20 +59,16 @@ public static CallerID buildFromComponents(final String firstname, final String * Formats and returns the caller ID in an asterisk specific format suitable * for passing to the likes of the originate action. The format is: name * - * + * * @return a formatted clid. */ - public String formatted() - { + public String formatted() { String callerID = ""; //$NON-NLS-1$ - if (this.name != null) - { + if (this.name != null) { callerID += this.name; } - if (this.number != null) - { - if (callerID.length() > 1) - { + if (this.number != null) { + if (callerID.length() > 1) { callerID += " "; //$NON-NLS-1$ } callerID += "<" + this.number + ">"; //$NON-NLS-1$ //$NON-NLS-2$ @@ -89,27 +77,23 @@ public String formatted() } @Override - public void setHideCallerID(final boolean hide) - { + public void setHideCallerID(final boolean hide) { this.hideCallerID = hide; } @Override - public boolean isHideCallerID() - { + public boolean isHideCallerID() { return this.hideCallerID; } @Override - public String toString() - { + public String toString() { return this.formatted(); } @Override - public boolean isUnknown() - { + public boolean isUnknown() { return (this.number.length() == 0) || (this.number.compareToIgnoreCase("unknown") == 0); //$NON-NLS-1$ } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/DurationRoomOwner.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/DurationRoomOwner.java index 0cd4e830b..64cb11102 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/DurationRoomOwner.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/DurationRoomOwner.java @@ -2,25 +2,21 @@ import java.util.concurrent.TimeUnit; -public class DurationRoomOwner implements RoomOwner -{ +public class DurationRoomOwner implements RoomOwner { long end = System.currentTimeMillis(); - public DurationRoomOwner(long duration, TimeUnit units) - { + public DurationRoomOwner(long duration, TimeUnit units) { end = System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(duration, units); } @Override - public boolean isRoomStillRequired() - { + public boolean isRoomStillRequired() { return System.currentTimeMillis() < end; } @Override - public void setRoom(MeetmeRoom meetmeRoom) - { + public void setRoom(MeetmeRoom meetmeRoom) { } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java index 329c4a328..f01856574 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoom.java @@ -1,20 +1,19 @@ package org.asteriskjava.pbx.internal.asterisk; -import java.util.LinkedList; - import org.asteriskjava.lock.Lockable; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.pbx.Channel; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.LinkedList; + /* * This class tracks the status, channel names and number of participants in * a meetme room. The hangup function will hangup all known participants in * this meetme room. */ -public class MeetmeRoom extends Lockable -{ +public class MeetmeRoom extends Lockable { /** * The asterisk room number. This will be value offset from the Meetme Base. * e.g. if the base is 3750 and this is the third allocated room, then the @@ -36,8 +35,7 @@ public class MeetmeRoom extends Lockable private RoomOwner owner = null; - public MeetmeRoom(final int number) - { + public MeetmeRoom(final int number) { this.roomNumber = number; } @@ -45,86 +43,69 @@ public MeetmeRoom(final int number) * returns true if the channel was added to the list of channels in this * meetme. if the channel is already in the meetme, returns false */ - public boolean addChannel(final Channel channel) - { - try (LockCloser closer = this.withLock()) - { + public boolean addChannel(final Channel channel) { + try (LockCloser closer = this.withLock()) { boolean newChannel = false; - if (!this.channels.contains(channel)) - { + if (!this.channels.contains(channel)) { this.channels.add(channel); this.channelCount++; newChannel = true; - } - else + } else MeetmeRoom.logger.error("rejecting " + channel + " already in meetme."); //$NON-NLS-1$ //$NON-NLS-2$ return newChannel; } } - public int getChannelCount() - { - try (LockCloser closer = this.withLock()) - { + public int getChannelCount() { + try (LockCloser closer = this.withLock()) { return this.channelCount; } } - public Channel[] getChannels() - { - try (LockCloser closer = this.withLock()) - { + public Channel[] getChannels() { + try (LockCloser closer = this.withLock()) { final Channel list[] = new Channel[this.channels.size()]; int cnt = 0; - for (final Channel channel : this.channels) - { + for (final Channel channel : this.channels) { list[cnt++] = channel; } return list; } } - public boolean getForceClose() - { + public boolean getForceClose() { return this.forceClose; } - public Long getLastUpdated() - { + public Long getLastUpdated() { return this.lastUpdated; } - public String getRoomNumber() - { + public String getRoomNumber() { return ("" + this.roomNumber); //$NON-NLS-1$ } /** * returns true if the meetme room is active, false if it is available - * + * * @return */ - public boolean isActive() - { + public boolean isActive() { return this.active; } - public void removeChannel(final Channel channel) - { - try (LockCloser closer = this.withLock()) - { + public void removeChannel(final Channel channel) { + try (LockCloser closer = this.withLock()) { final boolean channelCountInSync = this.channelCount == this.channels.size(); final boolean removed = this.channels.remove(channel); - if (!removed) - { + if (!removed) { MeetmeRoom.logger.warn("An attempt to remove an non-existing channel " + channel + " from Meetme Room " //$NON-NLS-1$ //$NON-NLS-2$ + this.getRoomNumber()); } - if (channelCountInSync && removed) - { + if (channelCountInSync && removed) { this.channelCount--; } @@ -142,15 +123,12 @@ public void removeChannel(final Channel channel) // so // decrementing it keeps us in sync with asterisk // and eventually we will get back in sync (hopefully). - if (!channelCountInSync && removed) - { + if (!channelCountInSync && removed) { this.channelCount--; } - if ((this.channels.size() < 2) && (this.channels.size() > 0)) - { - if (!this.channels.get(0).isLocal()) - { + if ((this.channels.size() < 2) && (this.channels.size() > 0)) { + if (!this.channels.get(0).isLocal()) { logger.warn("One channel left in the meet me room " + this.channels.get(0) + " room " + this.roomNumber); //$NON-NLS-1$ } } @@ -158,18 +136,15 @@ public void removeChannel(final Channel channel) } - public void setActive() - { + public void setActive() { this.active = true; } - public void setForceClose(final boolean canClose) - { + public void setForceClose(final boolean canClose) { this.forceClose = canClose; } - public void setInactive() - { + public void setInactive() { this.active = false; this.channels.clear(); this.forceClose = false; @@ -178,8 +153,7 @@ public void setInactive() } - public void setLastUpdated() - { + public void setLastUpdated() { this.lastUpdated = System.currentTimeMillis(); } @@ -187,35 +161,28 @@ public void setLastUpdated() * This method should only be called if asterisk is reporting a channel * count for this meetme room which does not match our local channel count. * This could happen if it was restarted whilst a call was active. - * + * * @param channelCount */ - public void resetChannelCount(final int resetChannelCount) - { + public void resetChannelCount(final int resetChannelCount) { this.channelCount = resetChannelCount; } - public RoomOwner getOwner() - { + public RoomOwner getOwner() { return owner; } - public void setOwner(RoomOwner newOwner) - { + public void setOwner(RoomOwner newOwner) { owner = newOwner; owner.setRoom(this); setActive(); } - public void removeOwner(RoomOwner toRemove) - { - if (owner == toRemove || owner == null) - { + public void removeOwner(RoomOwner toRemove) { + if (owner == toRemove || owner == null) { owner = null; - } - else - { + } else { logger.error( "Tring to remove the owner, but it's not the current owner. Owner=" + owner + " caller=" + toRemove); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java index 927fe020e..a6d7970a4 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/MeetmeRoomControl.java @@ -1,28 +1,12 @@ package org.asteriskjava.pbx.internal.asterisk; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.atomic.AtomicReference; - import org.asteriskjava.AsteriskVersion; import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.lock.Locker.LockCloser; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.asterisk.wrap.actions.CommandAction; import org.asteriskjava.pbx.asterisk.wrap.actions.ConfbridgeListAction; -import org.asteriskjava.pbx.asterisk.wrap.events.ConfbridgeListEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.MeetMeJoinEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.MeetMeLeaveEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvents; +import org.asteriskjava.pbx.asterisk.wrap.events.*; import org.asteriskjava.pbx.asterisk.wrap.response.CommandResponse; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; @@ -31,8 +15,13 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class MeetmeRoomControl extends EventListenerBaseClass implements CoherentManagerEventListener -{ +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicReference; + +public class MeetmeRoomControl extends EventListenerBaseClass implements CoherentManagerEventListener { /* * listens for a channel entering or leaving meetme rooms. when there is * only 1 channel left in a room it sets it as inactive .It will not set to @@ -52,22 +41,16 @@ public class MeetmeRoomControl extends EventListenerBaseClass implements Coheren private final static AtomicReference self = new AtomicReference<>(); - synchronized public static void init(PBX pbx, final int roomCount) throws NoMeetmeException - { - if (MeetmeRoomControl.self.get() != null) - { + synchronized public static void init(PBX pbx, final int roomCount) throws NoMeetmeException { + if (MeetmeRoomControl.self.get() != null) { logger.warn("The MeetmeRoomControl has already been initialised."); //$NON-NLS-1$ - } - else - { + } else { MeetmeRoomControl.self.set(new MeetmeRoomControl(pbx, roomCount)); } } - public static MeetmeRoomControl getInstance() - { - if (MeetmeRoomControl.self.get() == null) - { + public static MeetmeRoomControl getInstance() { + if (MeetmeRoomControl.self.get() == null) { throw new IllegalStateException( "The MeetmeRoomControl has not been initialised. Please call MeetmeRoomControl.init()."); //$NON-NLS-1$ } @@ -76,8 +59,7 @@ public static MeetmeRoomControl getInstance() } - private MeetmeRoomControl(PBX pbx, final int roomCount) throws NoMeetmeException - { + private MeetmeRoomControl(PBX pbx, final int roomCount) throws NoMeetmeException { super("MeetmeRoomControl", pbx); //$NON-NLS-1$ this.roomCount = roomCount; final AsteriskSettings settings = PBXFactory.getActiveProfile(); @@ -89,9 +71,8 @@ private MeetmeRoomControl(PBX pbx, final int roomCount) throws NoMeetmeException } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); required.add(MeetMeJoinEvent.class); required.add(MeetMeLeaveEvent.class); @@ -103,58 +84,45 @@ private MeetmeRoomControl(PBX pbx, final int roomCount) throws NoMeetmeException * returns the next available meetme room, or null if no rooms are * available. */ - public MeetmeRoom findAvailableRoom(RoomOwner newOwner) - { - try (LockCloser closer = this.withLock()) - { + public MeetmeRoom findAvailableRoom(RoomOwner newOwner) { + try (LockCloser closer = this.withLock()) { int count = 0; - for (final MeetmeRoom room : this.rooms) - { - if (MeetmeRoomControl.logger.isDebugEnabled()) - { + for (final MeetmeRoom room : this.rooms) { + if (MeetmeRoomControl.logger.isDebugEnabled()) { MeetmeRoomControl.logger.debug("room " + room.getRoomNumber() + " count " + count); } - if (room.getOwner() == null || !room.getOwner().isRoomStillRequired()) - { + if (room.getOwner() == null || !room.getOwner().isRoomStillRequired()) { /* * new code to attempt to recover uncleared meetme rooms * safely */ - try - { + try { final Long lastUpdated = room.getLastUpdated(); final long now = System.currentTimeMillis(); - if (lastUpdated != null) - { + if (lastUpdated != null) { final long elapsedTime = now - lastUpdated; MeetmeRoomControl.logger.error( "room: " + room.getRoomNumber() + " count: " + count + " elapsed: " + elapsedTime); - if ((elapsedTime > 1800000) && (room.getChannelCount() < 2)) - { + if ((elapsedTime > 1800000) && (room.getChannelCount() < 2)) { MeetmeRoomControl.logger.error("clearing room"); //$NON-NLS-1$ room.setInactive(); } } - } - catch (final Exception e) - { + } catch (final Exception e) { /* * attempt to make this new change safe */ MeetmeRoomControl.logger.error(e, e); } - if (room.getChannelCount() == 0) - { + if (room.getChannelCount() == 0) { room.setInactive(); room.setOwner(newOwner); MeetmeRoomControl.logger.info("Returning available room " + room.getRoomNumber()); return room; } - } - else - { + } else { logger.warn("Meetme " + room.getRoomNumber() + " is still in use by " + room.getOwner()); } count++; @@ -167,19 +135,15 @@ public MeetmeRoom findAvailableRoom(RoomOwner newOwner) /** * Returns the MeetmeRoom for the given room number. The room number will be * an integer value offset from the meetme base address. - * + * * @param roomNumber the meetme room number * @return */ - private MeetmeRoom findMeetmeRoom(final String roomNumber) - { - try (LockCloser closer = this.withLock()) - { + private MeetmeRoom findMeetmeRoom(final String roomNumber) { + try (LockCloser closer = this.withLock()) { MeetmeRoom foundRoom = null; - for (final MeetmeRoom room : this.rooms) - { - if (room.getRoomNumber().compareToIgnoreCase(roomNumber) == 0) - { + for (final MeetmeRoom room : this.rooms) { + if (room.getRoomNumber().compareToIgnoreCase(roomNumber) == 0) { foundRoom = room; break; } @@ -189,83 +153,66 @@ private MeetmeRoom findMeetmeRoom(final String roomNumber) } - MeetmeRoom getRoom(final int room) - { - try (LockCloser closer = this.withLock()) - { + MeetmeRoom getRoom(final int room) { + try (LockCloser closer = this.withLock()) { return this.rooms[room]; } } @Override - public void onManagerEvent(final ManagerEvent event) - { + public void onManagerEvent(final ManagerEvent event) { MeetmeRoom room; - if (event instanceof MeetMeJoinEvent) - { + if (event instanceof MeetMeJoinEvent) { final MeetMeJoinEvent evt = (MeetMeJoinEvent) event; room = this.findMeetmeRoom(evt.getMeetMe()); final Channel channel = evt.getChannel(); - if (room != null) - { - if (room.addChannel(channel)) - { + if (room != null) { + if (room.addChannel(channel)) { MeetmeRoomControl.logger.debug(channel + " has joined the conference " //$NON-NLS-1$ + room.getRoomNumber() + " channelCount " + (room.getChannelCount())); //$NON-NLS-1$ room.setLastUpdated(); } } } - if (event instanceof MeetMeLeaveEvent) - { + if (event instanceof MeetMeLeaveEvent) { final MeetMeLeaveEvent evt = (MeetMeLeaveEvent) event; room = this.findMeetmeRoom(evt.getMeetMe()); final Channel channel = evt.getChannel(); - if (room != null) - { + if (room != null) { // ignore local dummy channels// && // !channel.toUpperCase().startsWith("LOCAL/")) { - if (MeetmeRoomControl.logger.isDebugEnabled()) - { + if (MeetmeRoomControl.logger.isDebugEnabled()) { MeetmeRoomControl.logger.debug(channel + " has left the conference " //$NON-NLS-1$ + room.getRoomNumber() + " channel count " + (room.getChannelCount())); //$NON-NLS-1$ } room.removeChannel(channel); room.setLastUpdated(); - if (room.getChannelCount() < 2 && room.getForceClose()) - { + if (room.getChannelCount() < 2 && room.getForceClose()) { this.hangupChannels(room); room.setInactive(); } - if (room.getChannelCount() < 1) - { + if (room.getChannelCount() < 1) { room.setInactive(); } } } } - public void hangupChannels(final MeetmeRoom room) - { + public void hangupChannels(final MeetmeRoom room) { final Channel Channels[] = room.getChannels(); - if (room.isActive()) - { + if (room.isActive()) { PBX pbx = PBXFactory.getActivePBX(); - for (final Channel channel : Channels) - { + for (final Channel channel : Channels) { room.removeChannel(channel); - try - { + try { logger.warn("Hanging up"); pbx.hangup(channel); - } - catch (IllegalArgumentException | IllegalStateException | PBXException e) - { + } catch (IllegalArgumentException | IllegalStateException | PBXException e) { logger.error(e, e); } @@ -273,89 +220,66 @@ public void hangupChannels(final MeetmeRoom room) } } - private void configure(AsteriskPBX pbx) throws NoMeetmeException - { + private void configure(AsteriskPBX pbx) throws NoMeetmeException { final int base = this.meetmeBaseAddress; - for (int r = 0; r < this.roomCount; r++) - { + for (int r = 0; r < this.roomCount; r++) { this.rooms[r] = new MeetmeRoom(r + base); } - try - { + try { String command; - if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) - { + if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) { command = "ConfBridge list"; //$NON-NLS-1$ ConfbridgeListAction action = new ConfbridgeListAction(); final ResponseEvents response = pbx.sendEventGeneratingAction(action, 3000); Map roomChannelCount = new HashMap<>(); - for (ResponseEvent event : response.getEvents()) - { + for (ResponseEvent event : response.getEvents()) { ConfbridgeListEvent e = (ConfbridgeListEvent) event; Integer current = roomChannelCount.get(e.getConference()); - if (current == null) - { + if (current == null) { roomChannelCount.put(e.getConference(), 1); - } - else - { + } else { roomChannelCount.put(e.getConference(), current + 1); } } - for (Entry entry : roomChannelCount.entrySet()) - { + for (Entry entry : roomChannelCount.entrySet()) { setRoomCount(entry.getKey(), entry.getValue(), Integer.parseInt(entry.getKey())); } this.meetmeInstalled = true; - } - else - { - if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) - { + } else { + if (pbx.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) { command = "meetme list"; //$NON-NLS-1$ - } - else - { + } else { command = "meetme"; //$NON-NLS-1$ } final CommandAction commandAction = new CommandAction(command); final ManagerResponse response = pbx.sendAction(commandAction, 3000); - if (!(response instanceof CommandResponse)) - { + if (!(response instanceof CommandResponse)) { throw new ManagerCommunicationException(response.getMessage(), null); } final CommandResponse commandResponse = (CommandResponse) response; MeetmeRoomControl.logger.debug("parsing active meetme rooms"); //$NON-NLS-1$ - for (final String line : commandResponse.getResult()) - { + for (final String line : commandResponse.getResult()) { this.parseMeetme(line); this.meetmeInstalled = true; MeetmeRoomControl.logger.debug(line); } } - } - catch (final NoMeetmeException e) - { + } catch (final NoMeetmeException e) { throw e; - } - catch (final Exception e) - { + } catch (final Exception e) { MeetmeRoomControl.logger.error(e, e); throw new NoMeetmeException(e.getLocalizedMessage()); } } - private void parseMeetme(final String line) throws NoMeetmeException - { - try (LockCloser closer = this.withLock()) - { - if (line != null) - { + private void parseMeetme(final String line) throws NoMeetmeException { + try (LockCloser closer = this.withLock()) { + if (line != null) { if (line.toLowerCase().startsWith("no such command 'meetme'")) //$NON-NLS-1$ { throw new NoMeetmeException("Asterisk is not configured correctly! Please enable the MeetMe app"); //$NON-NLS-1$ @@ -366,8 +290,7 @@ private void parseMeetme(final String line) throws NoMeetmeException && (!line.toLowerCase().startsWith("* total number")) //$NON-NLS-1$ && (!line.toLowerCase().startsWith("no such conference")) //$NON-NLS-1$ && (!line.toLowerCase().startsWith("no such command 'meetme")) //$NON-NLS-1$ - ) - { + ) { // Update the stats on each meetme final String roomNumber = line.substring(0, 10).trim(); final String tmp = line.substring(11, 25).trim(); @@ -380,17 +303,13 @@ private void parseMeetme(final String line) throws NoMeetmeException } } - private void setRoomCount(final String roomNumber, final int channelCount, final int roomNo) - { + private void setRoomCount(final String roomNumber, final int channelCount, final int roomNo) { Integer base = this.meetmeBaseAddress; // First check if its one of our rooms. - if ((roomNo >= base) && (roomNo < (base + this.roomCount))) - { + if ((roomNo >= base) && (roomNo < (base + this.roomCount))) { final MeetmeRoom room = this.findMeetmeRoom(roomNumber); - if (room != null) - { - if (room.getChannelCount() != channelCount) - { + if (room != null) { + if (room.getChannelCount() != channelCount) { /* * After a restart there may have been meetme rooms left up * and running with live calls. We need to identify any @@ -412,20 +331,17 @@ private void setRoomCount(final String roomNumber, final int channelCount, final } } - public void stop() - { + public void stop() { this.close(); } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } - public boolean isMeetmeInstalled() - { + public boolean isMeetmeInstalled() { return this.meetmeInstalled; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/NoMeetmeException.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/NoMeetmeException.java index eb666a2d5..7b83e8b20 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/NoMeetmeException.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/NoMeetmeException.java @@ -1,12 +1,10 @@ package org.asteriskjava.pbx.internal.asterisk; -public class NoMeetmeException extends Exception -{ - private static final long serialVersionUID = 1L; +public class NoMeetmeException extends Exception { + private static final long serialVersionUID = 1L; - public NoMeetmeException(final String message) - { - super(message); - } + public NoMeetmeException(final String message) { + super(message); + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/asterisk/RoomOwner.java b/src/main/java/org/asteriskjava/pbx/internal/asterisk/RoomOwner.java index 3bb04c3de..f1f614edb 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/asterisk/RoomOwner.java +++ b/src/main/java/org/asteriskjava/pbx/internal/asterisk/RoomOwner.java @@ -1,12 +1,11 @@ package org.asteriskjava.pbx.internal.asterisk; -public interface RoomOwner -{ +public interface RoomOwner { /** * implementations of this method should NOT take locks and should return * quickly. This is used as an indication that the room (even though empty) * is still required by the owner - * + * * @return true if the meetme room is still required */ boolean isRoomStillRequired(); @@ -14,7 +13,7 @@ public interface RoomOwner /** * this can be usefull to null the reference to the Owner when the room is * nolong owned - * + * * @param meetmeRoom */ void setRoom(MeetmeRoom meetmeRoom); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ActiveCallListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/ActiveCallListener.java index 1a4c44d22..639aa12bd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ActiveCallListener.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ActiveCallListener.java @@ -5,13 +5,11 @@ /** * Used to notify a listener that the status of a call has changed. For instance * the call may have just been parked. - * + * * @author bsutton - * */ -public interface ActiveCallListener -{ +public interface ActiveCallListener { - void callStatusChanged(Call call, boolean isHidden); + void callStatusChanged(Call call, boolean isHidden); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java index 13dff5023..9147f06e7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/AsteriskPBX.java @@ -1,11 +1,5 @@ package org.asteriskjava.pbx.internal.core; -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - import org.asteriskjava.AsteriskVersion; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.AuthenticationFailedException; @@ -13,57 +7,17 @@ import org.asteriskjava.manager.ManagerConnectionState; import org.asteriskjava.manager.TimeoutException; import org.asteriskjava.manager.event.AbstractChannelEvent; -import org.asteriskjava.pbx.Activity; -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.ActivityStatusEnum; -import org.asteriskjava.pbx.AgiChannelActivityAction; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.Call; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.Call.OperandChannel; -import org.asteriskjava.pbx.CallDirection; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.ChannelHangupListener; -import org.asteriskjava.pbx.CompletionAdaptor; -import org.asteriskjava.pbx.DTMFTone; -import org.asteriskjava.pbx.DialPlanExtension; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.InvalidChannelName; -import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.TechType; -import org.asteriskjava.pbx.Trunk; -import org.asteriskjava.pbx.activities.BlindTransferActivity; -import org.asteriskjava.pbx.activities.BridgeActivity; -import org.asteriskjava.pbx.activities.DialActivity; -import org.asteriskjava.pbx.activities.DialToAgiActivity; -import org.asteriskjava.pbx.activities.HoldActivity; -import org.asteriskjava.pbx.activities.JoinActivity; -import org.asteriskjava.pbx.activities.ParkActivity; -import org.asteriskjava.pbx.activities.RedirectToActivity; -import org.asteriskjava.pbx.activities.SplitActivity; +import org.asteriskjava.pbx.activities.*; import org.asteriskjava.pbx.agi.AgiChannelActivityHangup; import org.asteriskjava.pbx.agi.AgiChannelActivityHold; -import org.asteriskjava.pbx.asterisk.wrap.actions.CommandAction; -import org.asteriskjava.pbx.asterisk.wrap.actions.EventGeneratingAction; -import org.asteriskjava.pbx.asterisk.wrap.actions.HangupAction; -import org.asteriskjava.pbx.asterisk.wrap.actions.ManagerAction; -import org.asteriskjava.pbx.asterisk.wrap.actions.PlayDtmfAction; -import org.asteriskjava.pbx.asterisk.wrap.actions.RedirectAction; +import org.asteriskjava.pbx.asterisk.wrap.actions.*; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvents; import org.asteriskjava.pbx.asterisk.wrap.response.CommandResponse; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; -import org.asteriskjava.pbx.internal.activity.BlindTransferActivityImpl; -import org.asteriskjava.pbx.internal.activity.BridgeActivityImpl; -import org.asteriskjava.pbx.internal.activity.DialActivityImpl; -import org.asteriskjava.pbx.internal.activity.DialToAgiActivityImpl; -import org.asteriskjava.pbx.internal.activity.HoldActivityImpl; -import org.asteriskjava.pbx.internal.activity.JoinActivityImpl; -import org.asteriskjava.pbx.internal.activity.ParkActivityImpl; -import org.asteriskjava.pbx.internal.activity.RedirectToActivityImpl; -import org.asteriskjava.pbx.internal.activity.SplitActivityImpl; +import org.asteriskjava.pbx.internal.activity.*; import org.asteriskjava.pbx.internal.asterisk.CallerIDImpl; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoom; import org.asteriskjava.pbx.internal.asterisk.MeetmeRoomControl; @@ -72,8 +26,13 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public enum AsteriskPBX implements PBX, ChannelHangupListener -{ +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public enum AsteriskPBX implements PBX, ChannelHangupListener { SELF; @@ -87,10 +46,8 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener private LiveChannelManager liveChannels; - AsteriskPBX() - { - try - { + AsteriskPBX() { + try { CoherentManagerConnection.init(); this.muteSupported = CoherentManagerConnection.getInstance().isMuteAudioSupported(); @@ -99,16 +56,13 @@ public enum AsteriskPBX implements PBX, ChannelHangupListener liveChannels = new LiveChannelManager(); MeetmeRoomControl.init(this, AsteriskPBX.MAX_MEETME_ROOMS); - } - catch (Exception e) - { + } catch (Exception e) { throw new RuntimeException(e); } } @Override - public void performPostCreationTasks() - { + public void performPostCreationTasks() { liveChannels.performPostCreationTasks(); } @@ -117,22 +71,19 @@ public void performPostCreationTasks() * cleanup. */ @Override - public void shutdown() - { + public void shutdown() { MeetmeRoomControl.getInstance().stop(); CoherentManagerConnection.getInstance().shutDown(); } @Override - public boolean isBridgeSupported() - { + public boolean isBridgeSupported() { return this.bridgeSupport; } @Override public BlindTransferActivity blindTransfer(Call call, Call.OperandChannel channelToTransfer, EndPoint transferTarget, - CallerID toCallerID, boolean autoAnswer, long timeout, String dialOptions) - { + CallerID toCallerID, boolean autoAnswer, long timeout, String dialOptions) { final CompletionAdaptor completion = new CompletionAdaptor<>(); final BlindTransferActivityImpl transfer = new BlindTransferActivityImpl(call, channelToTransfer, transferTarget, @@ -146,17 +97,15 @@ public BlindTransferActivity blindTransfer(Call call, Call.OperandChannel channe @Override public void blindTransfer(Call call, Call.OperandChannel channelToTransfer, EndPoint transferTarget, CallerID toCallerID, - boolean autoAnswer, long timeout, ActivityCallback listener, String dialOptions) - { + boolean autoAnswer, long timeout, ActivityCallback listener, String dialOptions) { new BlindTransferActivityImpl(call, channelToTransfer, transferTarget, toCallerID, autoAnswer, timeout, listener, dialOptions); } public BlindTransferActivity blindTransfer(Channel agentChannel, EndPoint transferTarget, CallerID toCallerID, - boolean autoAnswer, int timeout, ActivityCallback iCallback, String dialOptions) - throws PBXException - { + boolean autoAnswer, int timeout, ActivityCallback iCallback, String dialOptions) + throws PBXException { return new BlindTransferActivityImpl(agentChannel, transferTarget, toCallerID, autoAnswer, timeout, iCallback, dialOptions); @@ -170,8 +119,7 @@ public BlindTransferActivity blindTransfer(Channel agentChannel, EndPoint transf * @param direction * @throws PBXException */ - public BridgeActivity bridge(final Channel lhsChannel, final Channel rhsChannel) throws PBXException - { + public BridgeActivity bridge(final Channel lhsChannel, final Channel rhsChannel) throws PBXException { final CompletionAdaptor completion = new CompletionAdaptor<>(); final BridgeActivityImpl bridge = new BridgeActivityImpl(lhsChannel, rhsChannel, completion); @@ -183,8 +131,7 @@ public BridgeActivity bridge(final Channel lhsChannel, final Channel rhsChannel) } @Override - public void split(final Call callToSplit) throws PBXException - { + public void split(final Call callToSplit) throws PBXException { final CompletionAdaptor completion = new CompletionAdaptor<>(); new SplitActivityImpl(callToSplit, completion); @@ -194,15 +141,13 @@ public void split(final Call callToSplit) throws PBXException } @Override - public SplitActivity split(final Call callToSplit, final ActivityCallback listener) - { + public SplitActivity split(final Call callToSplit, final ActivityCallback listener) { return new SplitActivityImpl(callToSplit, listener); } @Override - public RedirectToActivity redirectToActivity(final Channel channel, final ActivityCallback listener) - { + public RedirectToActivity redirectToActivity(final Channel channel, final ActivityCallback listener) { return new RedirectToActivityImpl(channel, listener); } @@ -214,8 +159,7 @@ public RedirectToActivity redirectToActivity(final Channel channel, final Activi */ @Override public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, - CallDirection direction) - { + CallDirection direction) { final CompletionAdaptor completion = new CompletionAdaptor<>(); final JoinActivityImpl join = new JoinActivityImpl(lhs, originatingOperand, rhs, acceptingOperand, direction, @@ -234,31 +178,27 @@ public JoinActivity join(Call lhs, OperandChannel originatingOperand, Call rhs, */ @Override public void join(Call lhs, OperandChannel originatingOperand, Call rhs, OperandChannel acceptingOperand, - CallDirection direction, ActivityCallback listener) - { + CallDirection direction, ActivityCallback listener) { new JoinActivityImpl(lhs, originatingOperand, rhs, acceptingOperand, direction, listener); } @Override - public void conference(final Channel channelOne, final Channel channelTwo, final Channel channelThree) - { + public void conference(final Channel channelOne, final Channel channelTwo, final Channel channelThree) { // TODO Auto-generated method stub } @Override public void conference(final Channel channelOne, final Channel channelTwo, final Channel channelThree, - final ActivityCallback callback) - { + final ActivityCallback callback) { // TODO Auto-generated method stub } @Override public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID, - String dialOptions) - { + String dialOptions) { final CompletionAdaptor completion = new CompletionAdaptor<>(); final DialActivityImpl dialer = new DialActivityImpl(from, to, toCallerID, false, completion, null, dialOptions); @@ -269,14 +209,12 @@ public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final } public DialLocalToAgiActivity dialLocalToAgi(final EndPoint from, final CallerID fromCallerID, - ActivityCallback callback, Map channelVarsToSet) - { + ActivityCallback callback, Map channelVarsToSet) { return new DialLocalToAgiActivity(from, fromCallerID, callback, channelVarsToSet); } public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID, - final ActivityCallback callback, Map channelVarsToSet, String dialOptions) - { + final ActivityCallback callback, Map channelVarsToSet, String dialOptions) { final DialActivityImpl dialer = new DialActivityImpl(from, to, toCallerID, false, callback, channelVarsToSet, dialOptions); return dialer; @@ -284,8 +222,7 @@ public DialActivity dial(final EndPoint from, final CallerID fromCallerID, final @Override public void dial(final EndPoint from, final CallerID fromCallerID, final EndPoint to, final CallerID toCallerID, - final ActivityCallback callback, String dialOptions) - { + final ActivityCallback callback, String dialOptions) { new DialActivityImpl(from, to, toCallerID, false, callback, null, dialOptions); } @@ -294,16 +231,13 @@ public void dial(final EndPoint from, final CallerID fromCallerID, final EndPoin * Convenience method to hangup the call without having to extract the * channel yourself. */ - public void hangup(Call call) throws PBXException - { + public void hangup(Call call) throws PBXException { this.hangup(call.getOriginatingParty()); } @Override - public void hangup(final Channel channel) throws PBXException - { - if (channel.isLive()) - { + public void hangup(final Channel channel) throws PBXException { + if (channel.isLive()) { logger.info("Sending hangup action for channel: " + channel); //$NON-NLS-1$ PBX pbx = PBXFactory.getActivePBX(); @@ -311,42 +245,33 @@ public void hangup(final Channel channel) throws PBXException throw new PBXException("Channel: " + channel + " cannot be retrieved as it is still in transition."); final HangupAction hangup = new HangupAction(channel); - try - { + try { channel.setCurrentActivityAction(new AgiChannelActivityHangup()); CoherentManagerConnection.sendAction(hangup, 1000); - } - catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) - { + } catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) { logger.error(e, e); throw new PBXException(e); } - } - else + } else logger.debug("Suppressed hangup for " + channel + " as it was already hungup"); //$NON-NLS-1$ //$NON-NLS-2$ } @Override - public void hangup(final Channel channel, final ActivityCallback callback) - { + public void hangup(final Channel channel, final ActivityCallback callback) { throw new UnsupportedOperationException("Not yet implemented."); //$NON-NLS-1$ } @Override - public HoldActivity hold(final Channel channel) - { + public HoldActivity hold(final Channel channel) { final CompletionAdaptor completion = new CompletionAdaptor<>(); HoldActivity activity = null; - try - { + try { activity = new HoldActivityImpl(channel, completion); completion.waitForCompletion(10, TimeUnit.SECONDS); - } - catch (final Exception e) - { + } catch (final Exception e) { logger.error(e, e); } @@ -354,14 +279,12 @@ public HoldActivity hold(final Channel channel) } @Override - public boolean isMuteSupported() - { + public boolean isMuteSupported() { return this.muteSupported; } @Override - public ParkActivity park(final Call call, final Channel parkChannel) - { + public ParkActivity park(final Call call, final Channel parkChannel) { final CompletionAdaptor completion = new CompletionAdaptor<>(); final ParkActivity activity = new ParkActivityImpl(call, parkChannel, completion); @@ -372,70 +295,58 @@ public ParkActivity park(final Call call, final Channel parkChannel) } @Override - public void park(final Call call, final Channel parkChannel, final ActivityCallback callback) - { + public void park(final Call call, final Channel parkChannel, final ActivityCallback callback) { new ParkActivityImpl(call, parkChannel, callback); } @Override - public void sendDTMF(final Channel channel, final DTMFTone tone) throws PBXException - { - try - { + public void sendDTMF(final Channel channel, final DTMFTone tone) throws PBXException { + try { if (!waitForChannelToQuiescent(channel, 3000)) throw new PBXException("Channel: " + channel + " cannot play dtmf as it is still in transition."); CoherentManagerConnection.sendAction(new PlayDtmfAction(channel, tone), 1000); - } - catch (final Exception e) - { + } catch (final Exception e) { logger.error(e, e); throw new PBXException(e); } } @Override - public void sendDTMF(final Channel channel, final DTMFTone tone, final ActivityCallback callback) - { + public void sendDTMF(final Channel channel, final DTMFTone tone, final ActivityCallback callback) { // TODO Auto-generated method stub } @Override - public void transferToMusicOnHold(final Channel channel) throws PBXException - { + public void transferToMusicOnHold(final Channel channel) throws PBXException { final RedirectCall transfer = new RedirectCall(); transfer.redirect(channel, new AgiChannelActivityHold()); } - public String getManagementContext() - { + public String getManagementContext() { final AsteriskSettings settings = PBXFactory.getActiveProfile(); return settings.getManagementContext(); } @Override - public Channel getChannelByEndPoint(final EndPoint endPoint) - { + public Channel getChannelByEndPoint(final EndPoint endPoint) { return this.liveChannels.getChannelByEndPoint(endPoint); } @Override - public void channelHangup(Channel channel, Integer cause, String causeText) - { + public void channelHangup(Channel channel, Integer cause, String causeText) { this.liveChannels.remove((ChannelProxy) channel); } - public DialPlanExtension getExtensionPark() - { + public DialPlanExtension getExtensionPark() { final AsteriskSettings settings = PBXFactory.getActiveProfile(); return this.buildDialPlanExtension(settings.getExtensionPark()); } @Override - public EndPoint getExtensionAgi() - { + public EndPoint getExtensionAgi() { final AsteriskSettings settings = PBXFactory.getActiveProfile(); return this.buildDialPlanExtension(settings.getAgiExtension()); } @@ -447,15 +358,11 @@ public EndPoint getExtensionAgi() */ @Override - public EndPoint buildEndPoint(final String fullyQualifiedEndPoint) - { + public EndPoint buildEndPoint(final String fullyQualifiedEndPoint) { EndPoint endPoint = null; - try - { + try { endPoint = new EndPointImpl(fullyQualifiedEndPoint); - } - catch (final IllegalArgumentException e) - { + } catch (final IllegalArgumentException e) { logger.warn(e, e); } return endPoint; @@ -466,18 +373,14 @@ public EndPoint buildEndPoint(final String fullyQualifiedEndPoint) * have a tech specified then the defaultTech is used. */ @Override - public EndPoint buildEndPoint(final TechType defaultTech, final String endPointName) - { + public EndPoint buildEndPoint(final TechType defaultTech, final String endPointName) { EndPoint endPoint = null; - try - { + try { if (endPointName == null || endPointName.trim().length() == 0) endPoint = new EndPointImpl(); else endPoint = new EndPointImpl(defaultTech, endPointName); - } - catch (final IllegalArgumentException e) - { + } catch (final IllegalArgumentException e) { logger.error(e, e); } return endPoint; @@ -485,8 +388,7 @@ public EndPoint buildEndPoint(final TechType defaultTech, final String endPointN } @Override - public EndPoint buildEndPoint(final TechType defaultTech, final Trunk trunk, final String endPointName) - { + public EndPoint buildEndPoint(final TechType defaultTech, final Trunk trunk, final String endPointName) { return new EndPointImpl(defaultTech, trunk, endPointName); } @@ -495,15 +397,11 @@ public EndPoint buildEndPoint(final TechType defaultTech, final Trunk trunk, fin * Builds an end point from an end point name. If the endpoint name doesn't * have a tech specified then the defaultTech is used. */ - public DialPlanExtension buildDialPlanExtension(final String extension) - { + public DialPlanExtension buildDialPlanExtension(final String extension) { DialPlanExtension dialPlan = null; - try - { + try { dialPlan = new DialPlanExtension(extension); - } - catch (final IllegalArgumentException e) - { + } catch (final IllegalArgumentException e) { logger.error(e, e); } return dialPlan; @@ -511,8 +409,7 @@ public DialPlanExtension buildDialPlanExtension(final String extension) } @Override - public CallerID buildCallerID(final String number, final String name) - { + public CallerID buildCallerID(final String number, final String name) { return new CallerIDImpl(number, name); } @@ -521,36 +418,28 @@ public CallerID buildCallerID(final String number, final String name) * * @param event */ - public CallerID buildCallerID(final AbstractChannelEvent event) - { + public CallerID buildCallerID(final AbstractChannelEvent event) { final String number = event.getCallerIdNum(); final String name = event.getCallerIdName(); return this.buildCallerID(number, name); } - public Channel registerChannel(final String channelName, final String uniqueIdParam) throws InvalidChannelName - { + public Channel registerChannel(final String channelName, final String uniqueIdParam) throws InvalidChannelName { String uniqueID = uniqueIdParam; - if (uniqueIdParam == null || uniqueIdParam.length() == 0) - { + if (uniqueIdParam == null || uniqueIdParam.length() == 0) { uniqueID = ChannelImpl.UNKNOWN_UNIQUE_ID; } - if (channelName == null || channelName.trim().length() == 0) - { + if (channelName == null || channelName.trim().length() == 0) { throw new IllegalArgumentException("Channel name must not be empty"); } Channel proxy = findChannel(cleanChannelName(channelName), null); - if (proxy == null) - { + if (proxy == null) { logger.info("Couldn't find the channel " + channelName + ", creating it"); proxy = internalRegisterChannel(channelName, uniqueID); - } - else - { - if (uniqueID != null && !uniqueID.equals(proxy.getUniqueId())) - { + } else { + if (uniqueID != null && !uniqueID.equals(proxy.getUniqueId())) { logger.info( "Found the channel(" + proxy.getUniqueId() + "), but with a different uniqueId (" + uniqueID + ")"); @@ -572,16 +461,13 @@ public Channel registerChannel(final String channelName, final String uniqueIdPa * @return * @throws InvalidChannelName */ - public Channel internalRegisterChannel(final String channelName, final String uniqueID) throws InvalidChannelName - { + public Channel internalRegisterChannel(final String channelName, final String uniqueID) throws InvalidChannelName { ChannelProxy proxy = null; - try (LockCloser closer = this.liveChannels.withLock()) - { + try (LockCloser closer = this.liveChannels.withLock()) { String localUniqueID = (uniqueID == null ? ChannelImpl.UNKNOWN_UNIQUE_ID : uniqueID); proxy = this.findChannel(cleanChannelName(channelName), localUniqueID); - if (proxy == null) - { + if (proxy == null) { proxy = new ChannelProxy(new ChannelImpl(channelName, localUniqueID)); logger.debug("Creating new Channel Proxy " + proxy); this.liveChannels.add(proxy); @@ -597,21 +483,17 @@ public Channel internalRegisterChannel(final String channelName, final String un * @param name * @return */ - private String cleanChannelName(final String name) - { + private String cleanChannelName(final String name) { String cleanedName = name.trim().toUpperCase(); return cleanedName; } - public Channel registerHangupChannel(String channel, String uniqueId) throws InvalidChannelName - { + public Channel registerHangupChannel(String channel, String uniqueId) throws InvalidChannelName { Channel newChannel = null; - try (LockCloser closer = this.liveChannels.withLock()) - { + try (LockCloser closer = this.liveChannels.withLock()) { newChannel = this.findChannel(channel, uniqueId); - if (newChannel == null) - { + if (newChannel == null) { // WE don't add this channel to the liveChannels as it is in the // process // of being hungup so we don't need to track it. @@ -626,24 +508,20 @@ public Channel registerHangupChannel(String channel, String uniqueId) throws Inv return newChannel; } - public ChannelProxy findChannel(final String channelName, final String uniqueID) - { + public ChannelProxy findChannel(final String channelName, final String uniqueID) { return this.liveChannels.findChannel(channelName, uniqueID); } - public MeetmeRoom acquireMeetmeRoom(RoomOwner owner) - { + public MeetmeRoom acquireMeetmeRoom(RoomOwner owner) { return MeetmeRoomControl.getInstance().findAvailableRoom(owner); } - public void addListener(FilteredManagerListener listener) - { + public void addListener(FilteredManagerListener listener) { CoherentManagerConnection connection = CoherentManagerConnection.getInstance(); connection.addListener(listener); } - public void removeListener(FilteredManagerListener listener) - { + public void removeListener(FilteredManagerListener listener) { CoherentManagerConnection connection = CoherentManagerConnection.getInstance(); connection.removeListener(listener); } @@ -659,86 +537,70 @@ public void removeListener(FilteredManagerListener listener) * @throws TimeoutException */ public ManagerResponse sendAction(ManagerAction theAction) - throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException - { + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException { return CoherentManagerConnection.sendAction(theAction, 30000); } public ManagerResponse sendAction(ManagerAction theAction, int timeout) - throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException - { + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException { return CoherentManagerConnection.sendAction(theAction, timeout); } public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) - throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException - { + throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException { ResponseEvents events = CoherentManagerConnection.sendEventGeneratingAction(action); return events; } public ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, int timeout) - throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException - { + throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException { return CoherentManagerConnection.sendEventGeneratingAction(action, timeout); } - public void setVariable(Channel channel, String name, String value) throws PBXException - { + public void setVariable(Channel channel, String name, String value) throws PBXException { CoherentManagerConnection.getInstance().setVariable(channel, name, value); } - public void sendActionNoWait(final ManagerAction action) - { + public void sendActionNoWait(final ManagerAction action) { CoherentManagerConnection.sendActionNoWait(action); } - public String getVariable(Channel channel, String name) - { + public String getVariable(Channel channel, String name) { return CoherentManagerConnection.getInstance().getVariable(channel, name); } - public AsteriskVersion getVersion() - { + public AsteriskVersion getVersion() { return CoherentManagerConnection.getInstance().getVersion(); } - public boolean isConnected() - { + public boolean isConnected() { return ((CoherentManagerConnection.managerConnection != null) && (CoherentManagerConnection.managerConnection.getState() == ManagerConnectionState.CONNECTED)); } - public boolean isMeetmeInstalled() - { + public boolean isMeetmeInstalled() { return MeetmeRoomControl.getInstance().isMeetmeInstalled(); } @Override - public boolean isChannel(String channelName) - { + public boolean isChannel(String channelName) { boolean isChannel = false; - try - { + try { internalRegisterChannel(channelName, ChannelImpl.UNKNOWN_UNIQUE_ID); isChannel = true; - } - catch (InvalidChannelName e) - { + } catch (InvalidChannelName e) { // if we get here then its not avalid channel name. } return isChannel; } - static public String getSIPADDHeader(final boolean inherit, final boolean targetIsSIP) - { + static public String getSIPADDHeader(final boolean inherit, final boolean targetIsSIP) { String sipHeader = "SIPADDHEADER"; //$NON-NLS-1$ - if (!targetIsSIP || inherit) - { + if (!targetIsSIP || inherit) { sipHeader = "__" + sipHeader; //$NON-NLS-1$ } return sipHeader; @@ -750,35 +612,27 @@ static public String getSIPADDHeader(final boolean inherit, final boolean target * * @param channel * @param timeout the time to wait (in milliseconds) for the channel to - * become quiescent. + * become quiescent. */ @Override - public boolean waitForChannelsToQuiescent(List channels, long timeout) - { + public boolean waitForChannelsToQuiescent(List channels, long timeout) { long elapsed = 0; - while (elapsed < timeout && !channelsAreQuiesent(channels)) - { - try - { + while (elapsed < timeout && !channelsAreQuiesent(channels)) { + try { Thread.sleep(200); - } - catch (InterruptedException e) - { + } catch (InterruptedException e) { logger.error(e, e); } logger.info("Waiting for channesl to Quiescent"); elapsed += 200; } - if (elapsed > timeout / 2) - { + if (elapsed > timeout / 2) { logger.warn("Took " + elapsed + "ms for channels to Quiescent"); } - if (elapsed >= timeout) - { + if (elapsed >= timeout) { logger.error("Channels didn't Quiescent"); - for (Channel channel : channels) - { + for (Channel channel : channels) { logger.error(channel); } @@ -786,24 +640,20 @@ public boolean waitForChannelsToQuiescent(List channels, long timeout) return timeout > elapsed; } - private boolean channelsAreQuiesent(List channels) - { + private boolean channelsAreQuiesent(List channels) { boolean ret = true; - for (Channel channel : channels) - { + for (Channel channel : channels) { ret &= channel.isQuiescent(); } return ret; } - public boolean moveChannelToAgi(Channel channel) throws PBXException - { + public boolean moveChannelToAgi(Channel channel) throws PBXException { if (!waitForChannelToQuiescent(channel, 3000)) throw new PBXException("Channel: " + channel + " cannot be transfered as it is still in transition."); boolean isInAgi = channel.isInAgi(); - if (!isInAgi) - { + if (!isInAgi) { final AsteriskSettings profile = PBXFactory.getActiveProfile(); channel.setCurrentActivityAction(new AgiChannelActivityHold()); @@ -812,26 +662,21 @@ public boolean moveChannelToAgi(Channel channel) throws PBXException logger.error("Issuing redirect on channel " + channel + " to move it to the agi"); - try - { + try { final ManagerResponse response = sendAction(redirect, 1000); if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0))//$NON-NLS-1$ { int limit = 50; - while (!channel.isInAgi() && limit-- > 0) - { + while (!channel.isInAgi() && limit-- > 0) { Thread.sleep(100); } isInAgi = channel.isInAgi(); - if (!isInAgi) - { + if (!isInAgi) { logger.error("Failed to move channel"); } } - } - catch (final Exception e) - { + } catch (final Exception e) { logger.error(e, e); } @@ -840,42 +685,35 @@ public boolean moveChannelToAgi(Channel channel) throws PBXException } - public void moveChannelTo(Channel channel, String context, String exten, int prio) - { + public void moveChannelTo(Channel channel, String context, String exten, int prio) { DialPlanExtension ext = this.buildDialPlanExtension(exten); channel.setCurrentActivityAction(new AgiChannelActivityHold()); final RedirectAction redirect = new RedirectAction(channel, context, ext, prio); - try - { + try { sendAction(redirect, 1000); - } - catch (final Exception e) - { + } catch (final Exception e) { logger.error(e, e); } } @Override - public boolean waitForChannelToQuiescent(Channel channel, int timeout) - { + public boolean waitForChannelToQuiescent(Channel channel, int timeout) { List channels = new LinkedList<>(); channels.add(channel); return waitForChannelsToQuiescent(channels, timeout); } - public ChannelProxy getProxyById(String id) - { + public ChannelProxy getProxyById(String id) { return liveChannels.findProxyById(id); } public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, AgiChannelActivityAction action, - ActivityCallback iCallback, Map channelVarsToSet) - { + ActivityCallback iCallback, Map channelVarsToSet) { final CompletionAdaptor completion = new CompletionAdaptor<>(); @@ -888,12 +726,9 @@ public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, Agi final ActivityStatusEnum status; - if (dialer.isSuccess()) - { + if (dialer.isSuccess()) { status = ActivityStatusEnum.SUCCESS; - } - else - { + } else { status = ActivityStatusEnum.FAILURE; } @@ -903,8 +738,7 @@ public DialToAgiActivityImpl dialToAgi(EndPoint endPoint, CallerID callerID, Agi } public DialToAgiActivityImpl dialToAgiWithAbort(EndPoint endPoint, CallerID callerID, int timeout, - AgiChannelActivityAction action, ActivityCallback iCallback) - { + AgiChannelActivityAction action, ActivityCallback iCallback) { return new DialToAgiActivityImpl(endPoint, callerID, timeout, false, iCallback, null, action); @@ -922,17 +756,13 @@ public DialToAgiActivityImpl dialToAgiWithAbort(EndPoint endPoint, CallerID call * @throws AuthenticationFailedException * @throws TimeoutException */ - public boolean createAgiEntryPoint() throws IOException, AuthenticationFailedException, TimeoutException - { + public boolean createAgiEntryPoint() throws IOException, AuthenticationFailedException, TimeoutException { - try - { + try { AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); AsteriskSettings profile = PBXFactory.getActiveProfile(); - if (!checkDialplanExists(profile)) - - { + if (!checkDialplanExists(profile)) { String host = profile.getAgiHost(); String agi = profile.getAgiExtension(); @@ -944,9 +774,7 @@ public boolean createAgiEntryPoint() throws IOException, AuthenticationFailedExc return checkDialplanExists(profile); } return true; - } - catch (Exception e) - { + } catch (Exception e) { logger.error(e); return false; @@ -954,17 +782,13 @@ public boolean createAgiEntryPoint() throws IOException, AuthenticationFailedExc } - public boolean checkDialplanExists(String dialPlan, String context) throws IOException, TimeoutException - { + public boolean checkDialplanExists(String dialPlan, String context) throws IOException, TimeoutException { String command; - if (getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) - { + if (getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) { // TODO: Use ShowDialplanAction instead of CommandAction? command = "dialplan show " + context; - } - else - { + } else { command = "show dialplan " + context; } @@ -975,15 +799,12 @@ public boolean checkDialplanExists(String dialPlan, String context) throws IOExc } public boolean checkDialplanExists(AsteriskSettings profile) - throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException - { + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException { return checkDialplanExists(ACTIVITY_AGI, profile.getManagementContext()); } - public String addAsteriskExtension(String extNumber, int priority, String command) throws Exception - - { + public String addAsteriskExtension(String extNumber, int priority, String command) throws Exception { String ext = "dialplan add extension " + extNumber + "," + priority + "," + command; CommandAction action = new CommandAction(ext); @@ -992,8 +813,7 @@ public String addAsteriskExtension(String extNumber, int priority, String comman List line = response.getResult(); String tmp = "Extension '" + extNumber + "," + priority + ","; - if (line.stream().anyMatch(answer -> answer.substring(0, tmp.length()).compareToIgnoreCase(tmp) == 0)) - { + if (line.stream().anyMatch(answer -> answer.substring(0, tmp.length()).compareToIgnoreCase(tmp) == 0)) { return "OK"; } @@ -1001,26 +821,21 @@ public String addAsteriskExtension(String extNumber, int priority, String comman } @Override - public Trunk buildTrunk(final String trunk) - { - return new Trunk() - { + public Trunk buildTrunk(final String trunk) { + return new Trunk() { @Override - public String getTrunkAsString() - { + public String getTrunkAsString() { return trunk; } }; } - public List getChannelList() - { + public List getChannelList() { return liveChannels.getChannelList(); } - public boolean expectRenameEvents() - { + public boolean expectRenameEvents() { return expectRenameEvents; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java index fe42b1ce6..7dfb9271a 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CallEndedListener.java @@ -2,13 +2,11 @@ /** * Used to notify a listener that a Call (CallTracker) has ended. - * + *

    * This generally means the last channel has hungup. - * - * @author bsutton * + * @author bsutton */ -public interface CallEndedListener -{ - void callEnded(CallTracker listener); +public interface CallEndedListener { + void callEnded(CallTracker listener); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java index a020e9d2c..458b612c7 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CallTracker.java @@ -1,9 +1,5 @@ package org.asteriskjava.pbx.internal.core; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - import org.asteriskjava.lock.LockableList; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.pbx.Channel; @@ -12,6 +8,10 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + /** * This is a fairly simple class which is used by a Peer to track what calls are * live for the given Peer. It should be noted that the Peer must keep track of @@ -20,11 +20,10 @@ * that it can show if a handset is on a call. In this way the operator can tell * if a person is busy even before they call them. Essentially all this calls * does is track the set of channels associated with a call. - * + * * @author bsutton */ -public class CallTracker implements ChannelHangupListener -{ +public class CallTracker implements ChannelHangupListener { private static final Log logger = LogFactory.getLog(CallTracker.class); /** @@ -39,8 +38,7 @@ public class CallTracker implements ChannelHangupListener private CallEndedListener listener; - CallTracker(Peer peer, Channel initialChannel) - { + CallTracker(Peer peer, Channel initialChannel) { this._associatedChannels.add(initialChannel); initialChannel.addHangupListener(this); this.listener = peer; @@ -53,43 +51,35 @@ public class CallTracker implements ChannelHangupListener * CallTracker for it. When the masquerade event finally turns up we will * realise it belongs to an existing CallTracker and as such we need to * merge the two CallTrackers. - * + * * @param rhs */ - void mergeCalls(CallTracker rhs) - { - try (LockCloser closer = this._associatedChannels.withLock()) - { + void mergeCalls(CallTracker rhs) { + try (LockCloser closer = this._associatedChannels.withLock()) { this._associatedChannels.addAll(rhs._associatedChannels); // not certain this is necessary but lets just tidy up a bit. rhs._associatedChannels.clear(); } } - public PeerState getState() - { + public PeerState getState() { return this._state; } /** * @param s */ - public void setState(final ChannelState channelState) - { + public void setState(final ChannelState channelState) { this._state = PeerState.valueByChannelState(channelState); } - public int findChannel(Channel newChannel) - { + public int findChannel(Channel newChannel) { int index = -1; - try (LockCloser closer = this._associatedChannels.withLock()) - { + try (LockCloser closer = this._associatedChannels.withLock()) { - for (int i = 0; i < this._associatedChannels.size(); i++) - { + for (int i = 0; i < this._associatedChannels.size(); i++) { Channel channel = this._associatedChannels.get(i); - if (channel.isSame(newChannel)) - { + if (channel.isSame(newChannel)) { index = i; break; } @@ -101,16 +91,13 @@ public int findChannel(Channel newChannel) /** * Remove a channel from the call. - * + * * @param channel */ - public void remove(Channel channel) - { - try (LockCloser closer = this._associatedChannels.withLock()) - { + public void remove(Channel channel) { + try (LockCloser closer = this._associatedChannels.withLock()) { int index = findChannel(channel); - if (index != -1) - { + if (index != -1) { if (logger.isDebugEnabled()) logger.debug( "CallTracker removing channel: " + this.toString() + " " + channel.getExtendedChannelName()); //$NON-NLS-1$ //$NON-NLS-2$ @@ -121,26 +108,19 @@ public void remove(Channel channel) } - public void startSweep() - { - try (LockCloser closer = this._associatedChannels.withLock()) - { - for (final Channel channel : this._associatedChannels) - { + public void startSweep() { + try (LockCloser closer = this._associatedChannels.withLock()) { + for (final Channel channel : this._associatedChannels) { ((ChannelProxy) channel).getRealChannel().startSweep(); } } } - public void endSweep() - { + public void endSweep() { final List toremove = new LinkedList<>(); - try (LockCloser closer = this._associatedChannels.withLock()) - { - for (final Channel channel : this._associatedChannels) - { - if (!((ChannelProxy) channel).getRealChannel().wasMarkedDuringSweep()) - { + try (LockCloser closer = this._associatedChannels.withLock()) { + for (final Channel channel : this._associatedChannels) { + if (!((ChannelProxy) channel).getRealChannel().wasMarkedDuringSweep()) { toremove.add(channel); logger.warn("removing channel " + this.hashCode() + " " + channel.getChannelName());//$NON-NLS-1$ //$NON-NLS-2$ } @@ -150,58 +130,46 @@ public void endSweep() } // Now tell each of the channels it has been hungup - for (final Channel channel : toremove) - { + for (final Channel channel : toremove) { ((ChannelProxy) channel).getRealChannel().notifyHangupListeners(-1, "Lingering channel probably due to missed hangup event"); } } - void dumpChannelList() - { - if (logger.isDebugEnabled()) - { + void dumpChannelList() { + if (logger.isDebugEnabled()) { logger.debug("CallTracker: dump channellist:" + this); //$NON-NLS-1$ - try (LockCloser closer = this._associatedChannels.withLock()) - { - for (final Channel channel : this._associatedChannels) - { + try (LockCloser closer = this._associatedChannels.withLock()) { + for (final Channel channel : this._associatedChannels) { logger.debug("--> " + channel.toString()); //$NON-NLS-1$ } } } } - public boolean hasEnded() - { - try (LockCloser closer = this._associatedChannels.withLock()) - { + public boolean hasEnded() { + try (LockCloser closer = this._associatedChannels.withLock()) { return this._associatedChannels.size() == 0; } } @Override - public void channelHangup(Channel channel, Integer cause, String causeText) - { + public void channelHangup(Channel channel, Integer cause, String causeText) { remove(channel); - try (LockCloser closer = this._associatedChannels.withLock()) - { - if (this._associatedChannels.size() == 0) - { + try (LockCloser closer = this._associatedChannels.withLock()) { + if (this._associatedChannels.size() == 0) { this._state = PeerState.NOTSET; notifyCallEndedListener(); } } } - private void notifyCallEndedListener() - { + private void notifyCallEndedListener() { this.listener.callEnded(this); } - public String toString() - { + public String toString() { return this.listener + " : " + this._state; //$NON-NLS-1$ } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java index c3227115e..97a64a66b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelImpl.java @@ -1,21 +1,11 @@ package org.asteriskjava.pbx.internal.core; -import java.util.concurrent.TimeUnit; - -import org.asteriskjava.pbx.AgiChannelActivityAction; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.ChannelFactory; -import org.asteriskjava.pbx.ChannelHangupListener; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.InvalidChannelName; -import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.TechType; +import org.asteriskjava.pbx.*; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.concurrent.TimeUnit; + /** * TODO set the channel unique id when registering against an existing channel * which doesn't have its unique id set.
    @@ -33,872 +23,764 @@ * that pass around an iChannel rather than a raw channel name. By doing this * the rename affectively becomes global updating every instance of the channel * (because they actually only have an instance handle). - * + * * @author bsutton */ -public class ChannelImpl implements Channel -{ - public static final String ZOMBIE = ""; //$NON-NLS-1$ - public static final String MASQ = ""; //$NON-NLS-1$ - - public static final String UNKNOWN_UNIQUE_ID = "-1"; //$NON-NLS-1$ - - private static final Log logger = LogFactory.getLog(ChannelImpl.class); - private static int logCounter = 100; - - /** - * The channel name including the tech and the channel sequence number but - * not the masquerade prefix and not the zombie suffix. Forced to upper case - * for comparisons. - */ - private String _channelName; - - /** - * A unique id created by Asterisk to uniquely identify this channel. Often - * a channel can be 're-created' on the fly. In this case the channels name - * will be the same but the unique id will change. - */ - private String _uniqueID; - /** - * This is an abbreviated form of the channel name obtained by removing - * everything after the '-' in the channel name. - */ - private EndPoint _endPoint; - - /** - * The caller id for this channel. If this is an inbound channel then it the - * callerid received from the remote end. If this is an outbound channel - * then this is the caller id we are to present to the remote end. - */ - private CallerID _callerID; - - /** - * A globally unique id assigned to each channel as it is created - */ - private long _channelId; - - private boolean _muted = false; - - private boolean _parked = false; - - private volatile boolean _isZombie = false; - - /** - * A channel is live if it has not been hungup. - */ - private boolean _isLive = true; - - /** - * Indicates that the channel is being masquerading by another channel. - * Masqueraded channels have an extra suffix after the sequence - * number e.g. SIP/100-000009823 - */ - private volatile boolean _isMasqueraded = false; - - /** - * Indicates that the channel is undergoing an action such as being parked. - * Action channels have an extra prefix before the tech e.g. - * Parked/SIP/100-000009823 - */ - private volatile boolean _isInAction = false; - - /** - * Indicates that the channel has been originated directly from the Asterisk - * console. We can generally ignore these cases. - */ - private boolean _isConsole = false; - - /** - * The prefix added to a channel during some type of action: e.g. - * Parked/SIP/100-0000032323 In this case the prefix is Parked. - */ - private String _actionPrefix = null; - - public static final String[] _actions = new String[] { "PARKED/", "ASYNCGOTO/", "BRIDGE/" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - - /** - * There should be only one hangup listener which is the ChannelProxy that - * wraps this channel. - */ - private ChannelHangupListener hangupListener; - - /** - * When validating channels the start time is set in the _sweepStartTime. as - * a channel is validated the _mark field is set to true. if new channels - * are created as the sweep is in progress the _sweepStartTime will not be - * set so they won't be cleaned up. - */ - private Long _sweepStartTime = null; - private boolean _marked = false; - - /** - * Creates a channel from a channelName
    - *
    - * This constructor is package private for a reason, and is called from - * AsteriskPBX... If you need to add a channel to the PBX do it like - * this
    - *
    - * AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX();
    - * final Channel channel = pbx.registerChannel(channelName, uniqueId);
    - *
    - * Channel names are one of the following formats: - * [Action/]Tech/EndPointName-[][ ] - * DAHDI/i/[:]-
    - *
    - * Where: [Action/] is an action that is being performed on a channel. e.g. - * Parked Tech is the Tech used to reach the end point.
    - *
    - * The set of supported techs are defined by the enum Tech.
    - *
    - * EndPointName the name of the endpoint.
    - *
    - * '' the optional terminating '' which indicates the channel is - * now being masqueraded. A masqueraded channel is one that has been cloned. - * The original channel is marked as being masqueraded and will hangup - * shortly. It plays no further part in the Call.
    - *
    - * '' the optional terminating '' which indicates the - * channel is now a zombie. A zombie channel is one that has been hungup and - * is awaiting final cleanup. I believe the zombie channel is used by the - * hangup extension 'h' in the dialplan.
    - *
    - * The channel name is stripped of the Action, MASQ and ZOMBIE elements. - * - * @param asteriskStateName - * @throws InvalidChannelName - */ - ChannelImpl(final String channelName, final String uniqueID) throws InvalidChannelName - { - if (uniqueID == null) - throw new IllegalArgumentException("The UniqueID may not be null."); //$NON-NLS-1$ - - if (channelName == null) - throw new IllegalArgumentException("The channelName may not be null."); //$NON-NLS-1$ - - if (uniqueID.compareToIgnoreCase("-1") == 0) - { - logger.debug("uniqueID is -1"); - } - - this._uniqueID = uniqueID; - - this.setChannelName(channelName); - - } - - /** - * designed for use by the ChannelProxy when a channel is being cloned as a - * result of Asterisk undertaking an Masquerade. This is not intended to be - * a complete clone just the key elements that we generally track on our - * side rather than getting directly from asterisk. - */ - public void masquerade(Channel channel) - { - // If the channel doesn't have a caller id - // preserve the existing one (as given this is a clone they should be - // identical). - // Asterisk doesn't always pass the caller ID on the channel hence this - // protects us from Asterisk accidentally clearing the caller id. - if (channel.hasCallerID()) - { - this._callerID = channel.getCallerID(); - } - else if (this._callerID != null && ((ChannelImpl) channel)._callerID != null) - { - // Force the caller id back into the channel so it has one as well. - PBX pbx = PBXFactory.getActivePBX(); - if (this._callerID != null) - { - ((ChannelImpl) channel)._callerID = pbx.buildCallerID(this._callerID.getNumber(), - this._callerID.getName()); - } - } - - this._muted = channel.isMute(); - - this._parked = channel.isParked(); - - // just in case the original channel is part way through a sweep by the - // PeerMonitor - // marking the sweep as true will stop the new clone being hungup as it - // may not have been around when the sweep started. - this._marked = true; - this._sweepStartTime = null; - } - - private void setChannelName(final String channelName) throws InvalidChannelName - { - logger.debug("Renamed channel from " + this._channelName + " to " + channelName); - this._channelName = this.cleanChannelName(channelName); - this.validateChannelName(this._channelName); - - this._channelId = ChannelFactory.getNextChannelId(); - this._endPoint = new EndPointImpl(this.extractPeerName(this._channelName)); - - // After stripping everything from the channel name after the hypen - // we should have the endpoint name which shouldn't match the - // channel name - // unless its a channel caused by a console dial (Console/dsp) which - // we don't really care about. - // If the peer name still matches then we have a malformed channel - // name. - if ((this._channelName.compareTo(this.getEndPoint().getFullyQualifiedName()) == 0) && !this._isConsole) - { - if (ChannelImpl.logCounter > 0) - { - ChannelImpl.logger.warn("Invalid channel name " + this._channelName); //$NON-NLS-1$ - ChannelImpl.logCounter--; - } - else if (ChannelImpl.logCounter == 0) - { - ChannelImpl.logger.warn("Further Invalid channel name warnings suppressed"); //$NON-NLS-1$ - ChannelImpl.logCounter--; - } - } - } - - /** - * validates the channel name. Validate is to be called after the channel - * has been cleaned. - * - * @param channelName - * @throws InvalidChannelName - */ - private void validateChannelName(final String channelName) throws InvalidChannelName - { - if (!this._isConsole) - { - if (!TechType.hasValidTech(channelName)) - { - throw new InvalidChannelName("Invalid channelName: " + channelName + ". Unknown tech."); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Check we have the expected hypen - final int hypen = channelName.indexOf("-"); //$NON-NLS-1$ - if (hypen == -1) - { - throw new InvalidChannelName("Invalid channelName: " + channelName + ". Missing hypen."); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Check we have the expected slash - final int slash = channelName.indexOf("/"); //$NON-NLS-1$ - if (slash == -1) - { - throw new InvalidChannelName("Invalid channelName: " + channelName + ". Missing slash."); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Check that the hypen is after the slash. - if (hypen < slash) - { - throw new InvalidChannelName( - "Invalid channelName: " + channelName + ". Hypen must be after the slash."); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Check that there is at least one characters between the hypen and - // the - // slash - if ((hypen - slash) < 2) - { - throw new InvalidChannelName("Invalid channelName: " + channelName //$NON-NLS-1$ - + ". Must be one character between the hypen and the slash."); //$NON-NLS-1$ - } - - // Check that the channel sequence number is at least 1 character - // long. - if ((channelName.length() - hypen) < 2) - { - throw new InvalidChannelName("Invalid channelName: " + channelName //$NON-NLS-1$ - + ". The channel sequence number must be at least 1 character."); //$NON-NLS-1$ - } - } - - } - - /** - * Cleans up the channel name by applying the following: 1) trim any - * whitespace 2) convert to upper case for easy string comparisions 3) strip - * of the masquerade prefix if it exists and mark the channel as - * masquerading 4) strip the zombie suffix and mark it as being a zombie. - * - * @param name - * @return - */ - private String cleanChannelName(final String name) - { - String cleanedName = name.trim().toUpperCase(); - - // If if the channel is the console - this._isConsole = false; - if (name.compareToIgnoreCase("Console/dsp") == 0) //$NON-NLS-1$ - { - this._isConsole = true; - } - - // Check if the channel is in an action - boolean wasInAction = this._isInAction; - this._isInAction = false; - for (final String prefix : ChannelImpl._actions) - { - if (cleanedName.startsWith(prefix)) - { - this._isInAction = true; - this._actionPrefix = cleanedName.substring(0, prefix.length() - 1); - cleanedName = cleanedName.substring(prefix.length()); - break; - } - } - if (wasInAction != this._isInAction) - { - logger.debug( - "Channel " + this + " : inaction status changed from " + wasInAction + " to " + this._isInAction); - } - - // Channels can be marked as in a zombie state - // so we need to strip of the zombie suffix and just mark the channel - // as a - // zombie. - this._isZombie = false; - if (cleanedName.contains(ChannelImpl.ZOMBIE)) - { - this._isZombie = true; - cleanedName = cleanedName.substring(0, cleanedName.indexOf(ChannelImpl.ZOMBIE)); - } - - // Channels can be marked as in a MASQ state - // This happens during transfers (and other times) when the channel is - // replaced - // by a new channel in the call. The old channel is renamed with the - // word - // added as a suffix. - this._isMasqueraded = false; - if (cleanedName.contains(ChannelImpl.MASQ)) - { - this._isMasqueraded = true; - cleanedName = cleanedName.substring(0, cleanedName.indexOf(ChannelImpl.MASQ)); - } - - return cleanedName; - } - - @Override - public void rename(final String newName, String uniqueId) throws InvalidChannelName - { - - String oldChannelName = getChannelName(); - logger.info("Changing " + oldChannelName + " to " + newName + " on " + oldChannelName + " " + _uniqueID); - this.setChannelName(newName); - - if (_uniqueID.equalsIgnoreCase("-1")) - { - logger.info("Changing " + _uniqueID + " to " + uniqueId + " on " + oldChannelName + " " + _uniqueID); - _uniqueID = uniqueId; - } - - // the new replacement channel will go through a rename (without - // MASQ) and is ready to use. - - // the old channel will go through a rename (MASQ), then anther - // rename (ZOMBIE) and finally a hangup - - _isInAction = false; - - } - - @Override - public String getChannelName() - { - return this._channelName; - } - - @Override - public EndPoint getEndPoint() - { - return this._endPoint; - } - - /* - * Extracts the peer name from a full channel name. The channel name is - * created by asterisk and consists of the peer name a hypen and a unique - * sequence number. e.g. SIP/100-000000123 * For SIP channels the Peer name - * is of the form: SIP/100 For dahdi channels the channel name is of the - * form: DAHDI/i/[:]-0000000123 With the peer name - * of the form: DAHDI/i/[:] - */ - private final String extractPeerName(final String channelName) - { - // Find the start of the sequence number - int channelNameEndPoint = channelName.lastIndexOf("-"); //$NON-NLS-1$ - if (channelNameEndPoint == -1) - { - channelNameEndPoint = channelName.length(); - } - // return the peer name which is everything before the sequence number - // (and its hypen). - return channelName.substring(0, channelNameEndPoint); - } - - boolean wasMarkedDuringSweep() - { - boolean ret = false; - if (this._sweepStartTime == null || this._marked) - { - this._sweepStartTime = null; - ret = true; - } - return ret; - } - - @Override - public void setCallerId(final CallerID callerId) - { - this._callerID = callerId; - } - - /** - * Used to start the Mark and Sweep process by setting the marked status to - * false. At the end of the sweep the marked flag should have been set to - * true. If not then this channel has been hungup. - */ - void startSweep() - { - this._sweepStartTime = System.currentTimeMillis(); - this._marked = false; - } - - /** - * The channel was found to be active on asterisk so it is still alive. - */ - void markChannel() - { - this._marked = true; - - } - - /** - * ************************************************************************* - * ************************** The remaining methods are bridging methods to - * the new abstract PBX classes. - * ************************************************************************* - * ************************** - */ - @Override - public boolean isSame(final Channel _rhs) - { - boolean equals = false; - - if (_rhs == null) - { - logger.warn("isSame called with null"); - return false; - } - ChannelImpl rhs; - if (_rhs instanceof ChannelImpl) - { - rhs = (ChannelImpl) _rhs; - } - else - { - rhs = ((ChannelProxy) _rhs).getRealChannel(); - } - // If we have unique id's for both channels then we can compare the id's - // directly. - if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) - && (rhs._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) - { - if (this._uniqueID.compareToIgnoreCase(rhs._uniqueID) == 0) - { - equals = true; - } - } - else - { - boolean ok = (this._channelName != null) && (rhs._channelName != null); - final boolean namesMatch = (ok && (this._channelName.compareToIgnoreCase(rhs._channelName) == 0)); - - if (namesMatch) - { - // check if the actions match - if (this._isInAction != rhs._isInAction) - { - ok = false; - } - else if (this._isInAction) - { - ok = this._actionPrefix.compareTo(rhs._actionPrefix) == 0; - } - } - - if (ok && namesMatch) - { - // check if the zombie match - if (this._isZombie != rhs._isZombie) - { - ok = false; - } - } - - if (ok && namesMatch) - { - // check if the masquerade match - if (this._isMasqueraded != rhs._isMasqueraded) - { - ok = false; - } - } - - equals = ok & namesMatch; - } - return equals; - } - - @Override - public boolean isSame(final String extendedChannelName, final String uniqueID) - { - boolean equals = false; - if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) - && (uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) - { - if (this._uniqueID.compareTo(uniqueID) == 0) - { - equals = true; - } - } - else - { - equals = this.sameExtenededChannelName(extendedChannelName); - } - - return equals; - } - - @Override - public boolean sameExtenededChannelName(final String extendedChannelName) - { - boolean ok = (this.getExtendedChannelName() != null) && (extendedChannelName != null); - - return ok && (this.getExtendedChannelName().compareToIgnoreCase(extendedChannelName) == 0); - } - - /** - * Try to match a channel based solely on its unique ID - * - * @param uniqueID - * @return - */ - public boolean sameUniqueID(String uniqueID) - { - boolean equals = false; - if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) - && (uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) - { - if (this._uniqueID.compareTo(uniqueID) == 0) - { - equals = true; - } - } - - return equals; - } - - @Override - public boolean sameEndPoint(final Channel rhs) - { - return this.sameEndPoint(rhs.getEndPoint()); - } - - @Override - public boolean sameEndPoint(final EndPoint rhs) - { - boolean ok = (this._endPoint != null) && (rhs != null); - return ok && this._endPoint.isSame(rhs); - } - - @Override - public long getChannelId() - { - return this._channelId; - } - - @Override - public boolean isLive() - { - return this._isLive; - } - - @Override - public void addHangupListener(final ChannelHangupListener listener) - { - if (this.hangupListener != null) - throw new IllegalStateException("This channel may only have ONE listener which should be its ChannelProxy"); //$NON-NLS-1$ - - this.hangupListener = listener; - } - - @Override - public void removeListener(final ChannelHangupListener listener) - { - - if (this.hangupListener != listener) - throw new IllegalStateException("An invalid attempt was made to remove a non-existant listener."); //$NON-NLS-1$ - - this.hangupListener = null; - - } - - /** - * Called by Peer when we have been hungup. This can happen when Peer - * receives a HangupEvent or during a periodic sweep done by PeerMonitor to - * find the status of all channels. Notify any listeners that this channel - * has been hung up. - */ - @Override - public void notifyHangupListeners(Integer cause, String causeText) - { - this._isLive = false; - if (this.hangupListener != null) - { - this.hangupListener.channelHangup(this, cause, causeText); - } - else - { - logger.warn("Hangup listener is null"); - } - } - - @Override - public boolean isConnectedTo(final EndPoint endPoint) - { - return this._endPoint.isSame(endPoint); - } - - @Override - public boolean isMute() - { - return this._muted; - } - - @Override - public void setMute(final boolean mutedState) - { - this._muted = mutedState; - } - - @Override - public void setParked(final boolean parked) - { - this._parked = parked; - - } - - @Override - public boolean isParked() - { - return this._parked; - } - - @Override - public String toString() - { - return this.getExtendedChannelName() + ":" + this._uniqueID; //$NON-NLS-1$ - } - - /** - * Returns the full channel name including the masquerade prefix and the - * zombie suffix. - * - * @return - */ - - @Override - public String getExtendedChannelName() - { - int state = getState(); - if (state != lastState || !_channelName.equals(lastChannelName)) - { - final StringBuilder name = new StringBuilder(); - - if (this._isInAction) - { - name.append(this._actionPrefix); - name.append("/"); //$NON-NLS-1$ - } - name.append(this._channelName); - - if (this._isMasqueraded) - { - name.append(ChannelImpl.MASQ); - } - - if (this._isZombie) - { - name.append(ChannelImpl.ZOMBIE); - } - lastState = state; - lastChannelName = _channelName; - cachedExtenedChannelName = name.toString(); - - } - return cachedExtenedChannelName; - - } - - String cachedExtenedChannelName = null; - int lastState = -1; - String lastChannelName = null; - - int getState() - { - int state = 0; - if (_isInAction) - { - state += 2; - } - if (_isZombie) - { - state += 4; - } - if (_isMasqueraded) - { - state += 8; - } - return state; - } - - @Override - public boolean isLocal() - { - return this._endPoint.isLocal(); - } - - @Override - public boolean isZombie() - { - return this._isZombie; - } - - @Override - public boolean isConsole() - { - return this._isConsole; - } - - TechType getTech() - { - return this._endPoint.getTech(); - } - - /** - * Returns the actionPrefix for the channel or an empty string if the - * channel is not doing an action. - * - * @return - */ - String getActionPrefix() - { - return this._isInAction ? this._actionPrefix : ""; //$NON-NLS-1$ - } - - boolean isInAction() - { - return this._isInAction; - } - - boolean isMasqueraded() - { - return this._isMasqueraded; - } - - @Override - public boolean hasCallerID() - { - return this._callerID != null && !this._callerID.isUnknown(); - } - - @Override - public CallerID getCallerID() - { - if (this._callerID == null) - { - final CoherentManagerConnection smc = CoherentManagerConnection.getInstance(); - final String number = smc.getVariable(this, "CALLERID(number)"); //$NON-NLS-1$ - final String name = smc.getVariable(this, "CALLERID(name)"); //$NON-NLS-1$ - final PBX pbx = PBXFactory.getActivePBX(); - this._callerID = pbx.buildCallerID(number, name); - } - - return this._callerID; - - } - - @Override - public String getUniqueId() - { - return this._uniqueID; - } - - /* - * Returns true if this channel can detect hangups A SIP channel can always - * detect a hangup if its not channel then we need to check the profile to - * see if hangup detection is available. Hangup detection is important as we - * don't want to connect two channels both of which can't do hangup - * detection. If this happened then we would end up with a call which would - * never hangup. - */ - @Override - public boolean canDetectHangup() - { - boolean canDetectHangup = true; - - AsteriskSettings profile = PBXFactory.getActiveProfile(); - final boolean detect = profile.getCanDetectHangup(); - if (!this.getEndPoint().isSIP() && !detect) - { - canDetectHangup = false; - } - return canDetectHangup; - } - - /** - * Returns true if the channel is quiescent. A quescent channel is one that - * is current not going through a transition (name change) such as MASQ, - * ZOMBIE, ASYNC, PARK - * - * @return - */ - @Override - public boolean isQuiescent() - { - return !(_isInAction || _isMasqueraded || _isZombie); - } - - @Override - public AgiChannelActivityAction getCurrentActivityAction() - { - throw new RuntimeException("This method is only implemented in ChannelProxy"); - } - - @Override - public void setCurrentActivityAction(AgiChannelActivityAction action) - { - throw new RuntimeException("This method is only implemented in ChannelProxy"); - } - - @Override - public void setIsInAgi(boolean b) - { - throw new RuntimeException("This method is only implemented in ChannelProxy"); - } - - @Override - public boolean isInAgi() - { - throw new RuntimeException("This method is only implemented in ChannelProxy"); - } - - @Override - public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException - { - throw new RuntimeException("This method is only implemented in ChannelProxy"); - } +public class ChannelImpl implements Channel { + public static final String ZOMBIE = ""; //$NON-NLS-1$ + public static final String MASQ = ""; //$NON-NLS-1$ + + public static final String UNKNOWN_UNIQUE_ID = "-1"; //$NON-NLS-1$ + + private static final Log logger = LogFactory.getLog(ChannelImpl.class); + private static int logCounter = 100; + + /** + * The channel name including the tech and the channel sequence number but + * not the masquerade prefix and not the zombie suffix. Forced to upper case + * for comparisons. + */ + private String _channelName; + + /** + * A unique id created by Asterisk to uniquely identify this channel. Often + * a channel can be 're-created' on the fly. In this case the channels name + * will be the same but the unique id will change. + */ + private String _uniqueID; + /** + * This is an abbreviated form of the channel name obtained by removing + * everything after the '-' in the channel name. + */ + private EndPoint _endPoint; + + /** + * The caller id for this channel. If this is an inbound channel then it the + * callerid received from the remote end. If this is an outbound channel + * then this is the caller id we are to present to the remote end. + */ + private CallerID _callerID; + + /** + * A globally unique id assigned to each channel as it is created + */ + private long _channelId; + + private boolean _muted = false; + + private boolean _parked = false; + + private volatile boolean _isZombie = false; + + /** + * A channel is live if it has not been hungup. + */ + private boolean _isLive = true; + + /** + * Indicates that the channel is being masquerading by another channel. + * Masqueraded channels have an extra suffix after the sequence + * number e.g. SIP/100-000009823 + */ + private volatile boolean _isMasqueraded = false; + + /** + * Indicates that the channel is undergoing an action such as being parked. + * Action channels have an extra prefix before the tech e.g. + * Parked/SIP/100-000009823 + */ + private volatile boolean _isInAction = false; + + /** + * Indicates that the channel has been originated directly from the Asterisk + * console. We can generally ignore these cases. + */ + private boolean _isConsole = false; + + /** + * The prefix added to a channel during some type of action: e.g. + * Parked/SIP/100-0000032323 In this case the prefix is Parked. + */ + private String _actionPrefix = null; + + public static final String[] _actions = new String[]{"PARKED/", "ASYNCGOTO/", "BRIDGE/"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + /** + * There should be only one hangup listener which is the ChannelProxy that + * wraps this channel. + */ + private ChannelHangupListener hangupListener; + + /** + * When validating channels the start time is set in the _sweepStartTime. as + * a channel is validated the _mark field is set to true. if new channels + * are created as the sweep is in progress the _sweepStartTime will not be + * set so they won't be cleaned up. + */ + private Long _sweepStartTime = null; + private boolean _marked = false; + + /** + * Creates a channel from a channelName
    + *
    + * This constructor is package private for a reason, and is called from + * AsteriskPBX... If you need to add a channel to the PBX do it like + * this
    + *
    + * AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX();
    + * final Channel channel = pbx.registerChannel(channelName, uniqueId);
    + *
    + * Channel names are one of the following formats: + * [Action/]Tech/EndPointName-[][ ] + * DAHDI/i/[:]-
    + *
    + * Where: [Action/] is an action that is being performed on a channel. e.g. + * Parked Tech is the Tech used to reach the end point.
    + *
    + * The set of supported techs are defined by the enum Tech.
    + *
    + * EndPointName the name of the endpoint.
    + *
    + * '' the optional terminating '' which indicates the channel is + * now being masqueraded. A masqueraded channel is one that has been cloned. + * The original channel is marked as being masqueraded and will hangup + * shortly. It plays no further part in the Call.
    + *
    + * '' the optional terminating '' which indicates the + * channel is now a zombie. A zombie channel is one that has been hungup and + * is awaiting final cleanup. I believe the zombie channel is used by the + * hangup extension 'h' in the dialplan.
    + *
    + * The channel name is stripped of the Action, MASQ and ZOMBIE elements. + * + * @param asteriskStateName + * @throws InvalidChannelName + */ + ChannelImpl(final String channelName, final String uniqueID) throws InvalidChannelName { + if (uniqueID == null) + throw new IllegalArgumentException("The UniqueID may not be null."); //$NON-NLS-1$ + + if (channelName == null) + throw new IllegalArgumentException("The channelName may not be null."); //$NON-NLS-1$ + + if (uniqueID.compareToIgnoreCase("-1") == 0) { + logger.debug("uniqueID is -1"); + } + + this._uniqueID = uniqueID; + + this.setChannelName(channelName); + + } + + /** + * designed for use by the ChannelProxy when a channel is being cloned as a + * result of Asterisk undertaking an Masquerade. This is not intended to be + * a complete clone just the key elements that we generally track on our + * side rather than getting directly from asterisk. + */ + public void masquerade(Channel channel) { + // If the channel doesn't have a caller id + // preserve the existing one (as given this is a clone they should be + // identical). + // Asterisk doesn't always pass the caller ID on the channel hence this + // protects us from Asterisk accidentally clearing the caller id. + if (channel.hasCallerID()) { + this._callerID = channel.getCallerID(); + } else if (this._callerID != null && ((ChannelImpl) channel)._callerID != null) { + // Force the caller id back into the channel so it has one as well. + PBX pbx = PBXFactory.getActivePBX(); + if (this._callerID != null) { + ((ChannelImpl) channel)._callerID = pbx.buildCallerID(this._callerID.getNumber(), + this._callerID.getName()); + } + } + + this._muted = channel.isMute(); + + this._parked = channel.isParked(); + + // just in case the original channel is part way through a sweep by the + // PeerMonitor + // marking the sweep as true will stop the new clone being hungup as it + // may not have been around when the sweep started. + this._marked = true; + this._sweepStartTime = null; + } + + private void setChannelName(final String channelName) throws InvalidChannelName { + logger.debug("Renamed channel from " + this._channelName + " to " + channelName); + this._channelName = this.cleanChannelName(channelName); + this.validateChannelName(this._channelName); + + this._channelId = ChannelFactory.getNextChannelId(); + this._endPoint = new EndPointImpl(this.extractPeerName(this._channelName)); + + // After stripping everything from the channel name after the hypen + // we should have the endpoint name which shouldn't match the + // channel name + // unless its a channel caused by a console dial (Console/dsp) which + // we don't really care about. + // If the peer name still matches then we have a malformed channel + // name. + if ((this._channelName.compareTo(this.getEndPoint().getFullyQualifiedName()) == 0) && !this._isConsole) { + if (ChannelImpl.logCounter > 0) { + ChannelImpl.logger.warn("Invalid channel name " + this._channelName); //$NON-NLS-1$ + ChannelImpl.logCounter--; + } else if (ChannelImpl.logCounter == 0) { + ChannelImpl.logger.warn("Further Invalid channel name warnings suppressed"); //$NON-NLS-1$ + ChannelImpl.logCounter--; + } + } + } + + /** + * validates the channel name. Validate is to be called after the channel + * has been cleaned. + * + * @param channelName + * @throws InvalidChannelName + */ + private void validateChannelName(final String channelName) throws InvalidChannelName { + if (!this._isConsole) { + if (!TechType.hasValidTech(channelName)) { + throw new InvalidChannelName("Invalid channelName: " + channelName + ". Unknown tech."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check we have the expected hypen + final int hypen = channelName.indexOf("-"); //$NON-NLS-1$ + if (hypen == -1) { + throw new InvalidChannelName("Invalid channelName: " + channelName + ". Missing hypen."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check we have the expected slash + final int slash = channelName.indexOf("/"); //$NON-NLS-1$ + if (slash == -1) { + throw new InvalidChannelName("Invalid channelName: " + channelName + ". Missing slash."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check that the hypen is after the slash. + if (hypen < slash) { + throw new InvalidChannelName( + "Invalid channelName: " + channelName + ". Hypen must be after the slash."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Check that there is at least one characters between the hypen and + // the + // slash + if ((hypen - slash) < 2) { + throw new InvalidChannelName("Invalid channelName: " + channelName //$NON-NLS-1$ + + ". Must be one character between the hypen and the slash."); //$NON-NLS-1$ + } + + // Check that the channel sequence number is at least 1 character + // long. + if ((channelName.length() - hypen) < 2) { + throw new InvalidChannelName("Invalid channelName: " + channelName //$NON-NLS-1$ + + ". The channel sequence number must be at least 1 character."); //$NON-NLS-1$ + } + } + + } + + /** + * Cleans up the channel name by applying the following: 1) trim any + * whitespace 2) convert to upper case for easy string comparisions 3) strip + * of the masquerade prefix if it exists and mark the channel as + * masquerading 4) strip the zombie suffix and mark it as being a zombie. + * + * @param name + * @return + */ + private String cleanChannelName(final String name) { + String cleanedName = name.trim().toUpperCase(); + + // If if the channel is the console + this._isConsole = false; + if (name.compareToIgnoreCase("Console/dsp") == 0) //$NON-NLS-1$ + { + this._isConsole = true; + } + + // Check if the channel is in an action + boolean wasInAction = this._isInAction; + this._isInAction = false; + for (final String prefix : ChannelImpl._actions) { + if (cleanedName.startsWith(prefix)) { + this._isInAction = true; + this._actionPrefix = cleanedName.substring(0, prefix.length() - 1); + cleanedName = cleanedName.substring(prefix.length()); + break; + } + } + if (wasInAction != this._isInAction) { + logger.debug( + "Channel " + this + " : inaction status changed from " + wasInAction + " to " + this._isInAction); + } + + // Channels can be marked as in a zombie state + // so we need to strip of the zombie suffix and just mark the channel + // as a + // zombie. + this._isZombie = false; + if (cleanedName.contains(ChannelImpl.ZOMBIE)) { + this._isZombie = true; + cleanedName = cleanedName.substring(0, cleanedName.indexOf(ChannelImpl.ZOMBIE)); + } + + // Channels can be marked as in a MASQ state + // This happens during transfers (and other times) when the channel is + // replaced + // by a new channel in the call. The old channel is renamed with the + // word + // added as a suffix. + this._isMasqueraded = false; + if (cleanedName.contains(ChannelImpl.MASQ)) { + this._isMasqueraded = true; + cleanedName = cleanedName.substring(0, cleanedName.indexOf(ChannelImpl.MASQ)); + } + + return cleanedName; + } + + @Override + public void rename(final String newName, String uniqueId) throws InvalidChannelName { + + String oldChannelName = getChannelName(); + logger.info("Changing " + oldChannelName + " to " + newName + " on " + oldChannelName + " " + _uniqueID); + this.setChannelName(newName); + + if (_uniqueID.equalsIgnoreCase("-1")) { + logger.info("Changing " + _uniqueID + " to " + uniqueId + " on " + oldChannelName + " " + _uniqueID); + _uniqueID = uniqueId; + } + + // the new replacement channel will go through a rename (without + // MASQ) and is ready to use. + + // the old channel will go through a rename (MASQ), then anther + // rename (ZOMBIE) and finally a hangup + + _isInAction = false; + + } + + @Override + public String getChannelName() { + return this._channelName; + } + + @Override + public EndPoint getEndPoint() { + return this._endPoint; + } + + /* + * Extracts the peer name from a full channel name. The channel name is + * created by asterisk and consists of the peer name a hypen and a unique + * sequence number. e.g. SIP/100-000000123 * For SIP channels the Peer name + * is of the form: SIP/100 For dahdi channels the channel name is of the + * form: DAHDI/i/[:]-0000000123 With the peer name + * of the form: DAHDI/i/[:] + */ + private final String extractPeerName(final String channelName) { + // Find the start of the sequence number + int channelNameEndPoint = channelName.lastIndexOf("-"); //$NON-NLS-1$ + if (channelNameEndPoint == -1) { + channelNameEndPoint = channelName.length(); + } + // return the peer name which is everything before the sequence number + // (and its hypen). + return channelName.substring(0, channelNameEndPoint); + } + + boolean wasMarkedDuringSweep() { + boolean ret = false; + if (this._sweepStartTime == null || this._marked) { + this._sweepStartTime = null; + ret = true; + } + return ret; + } + + @Override + public void setCallerId(final CallerID callerId) { + this._callerID = callerId; + } + + /** + * Used to start the Mark and Sweep process by setting the marked status to + * false. At the end of the sweep the marked flag should have been set to + * true. If not then this channel has been hungup. + */ + void startSweep() { + this._sweepStartTime = System.currentTimeMillis(); + this._marked = false; + } + + /** + * The channel was found to be active on asterisk so it is still alive. + */ + void markChannel() { + this._marked = true; + + } + + /** + * ************************************************************************* + * ************************** The remaining methods are bridging methods to + * the new abstract PBX classes. + * ************************************************************************* + * ************************** + */ + @Override + public boolean isSame(final Channel _rhs) { + boolean equals = false; + + if (_rhs == null) { + logger.warn("isSame called with null"); + return false; + } + ChannelImpl rhs; + if (_rhs instanceof ChannelImpl) { + rhs = (ChannelImpl) _rhs; + } else { + rhs = ((ChannelProxy) _rhs).getRealChannel(); + } + // If we have unique id's for both channels then we can compare the id's + // directly. + if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) + && (rhs._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) { + if (this._uniqueID.compareToIgnoreCase(rhs._uniqueID) == 0) { + equals = true; + } + } else { + boolean ok = (this._channelName != null) && (rhs._channelName != null); + final boolean namesMatch = (ok && (this._channelName.compareToIgnoreCase(rhs._channelName) == 0)); + + if (namesMatch) { + // check if the actions match + if (this._isInAction != rhs._isInAction) { + ok = false; + } else if (this._isInAction) { + ok = this._actionPrefix.compareTo(rhs._actionPrefix) == 0; + } + } + + if (ok && namesMatch) { + // check if the zombie match + if (this._isZombie != rhs._isZombie) { + ok = false; + } + } + + if (ok && namesMatch) { + // check if the masquerade match + if (this._isMasqueraded != rhs._isMasqueraded) { + ok = false; + } + } + + equals = ok & namesMatch; + } + return equals; + } + + @Override + public boolean isSame(final String extendedChannelName, final String uniqueID) { + boolean equals = false; + if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) + && (uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) { + if (this._uniqueID.compareTo(uniqueID) == 0) { + equals = true; + } + } else { + equals = this.sameExtenededChannelName(extendedChannelName); + } + + return equals; + } + + @Override + public boolean sameExtenededChannelName(final String extendedChannelName) { + boolean ok = (this.getExtendedChannelName() != null) && (extendedChannelName != null); + + return ok && (this.getExtendedChannelName().compareToIgnoreCase(extendedChannelName) == 0); + } + + /** + * Try to match a channel based solely on its unique ID + * + * @param uniqueID + * @return + */ + public boolean sameUniqueID(String uniqueID) { + boolean equals = false; + if ((this._uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) + && (uniqueID.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0)) { + if (this._uniqueID.compareTo(uniqueID) == 0) { + equals = true; + } + } + + return equals; + } + + @Override + public boolean sameEndPoint(final Channel rhs) { + return this.sameEndPoint(rhs.getEndPoint()); + } + + @Override + public boolean sameEndPoint(final EndPoint rhs) { + boolean ok = (this._endPoint != null) && (rhs != null); + return ok && this._endPoint.isSame(rhs); + } + + @Override + public long getChannelId() { + return this._channelId; + } + + @Override + public boolean isLive() { + return this._isLive; + } + + @Override + public void addHangupListener(final ChannelHangupListener listener) { + if (this.hangupListener != null) + throw new IllegalStateException("This channel may only have ONE listener which should be its ChannelProxy"); //$NON-NLS-1$ + + this.hangupListener = listener; + } + + @Override + public void removeListener(final ChannelHangupListener listener) { + + if (this.hangupListener != listener) + throw new IllegalStateException("An invalid attempt was made to remove a non-existant listener."); //$NON-NLS-1$ + + this.hangupListener = null; + + } + + /** + * Called by Peer when we have been hungup. This can happen when Peer + * receives a HangupEvent or during a periodic sweep done by PeerMonitor to + * find the status of all channels. Notify any listeners that this channel + * has been hung up. + */ + @Override + public void notifyHangupListeners(Integer cause, String causeText) { + this._isLive = false; + if (this.hangupListener != null) { + this.hangupListener.channelHangup(this, cause, causeText); + } else { + logger.warn("Hangup listener is null"); + } + } + + @Override + public boolean isConnectedTo(final EndPoint endPoint) { + return this._endPoint.isSame(endPoint); + } + + @Override + public boolean isMute() { + return this._muted; + } + + @Override + public void setMute(final boolean mutedState) { + this._muted = mutedState; + } + + @Override + public void setParked(final boolean parked) { + this._parked = parked; + + } + + @Override + public boolean isParked() { + return this._parked; + } + + @Override + public String toString() { + return this.getExtendedChannelName() + ":" + this._uniqueID; //$NON-NLS-1$ + } + + /** + * Returns the full channel name including the masquerade prefix and the + * zombie suffix. + * + * @return + */ + + @Override + public String getExtendedChannelName() { + int state = getState(); + if (state != lastState || !_channelName.equals(lastChannelName)) { + final StringBuilder name = new StringBuilder(); + + if (this._isInAction) { + name.append(this._actionPrefix); + name.append("/"); //$NON-NLS-1$ + } + name.append(this._channelName); + + if (this._isMasqueraded) { + name.append(ChannelImpl.MASQ); + } + + if (this._isZombie) { + name.append(ChannelImpl.ZOMBIE); + } + lastState = state; + lastChannelName = _channelName; + cachedExtenedChannelName = name.toString(); + + } + return cachedExtenedChannelName; + + } + + String cachedExtenedChannelName = null; + int lastState = -1; + String lastChannelName = null; + + int getState() { + int state = 0; + if (_isInAction) { + state += 2; + } + if (_isZombie) { + state += 4; + } + if (_isMasqueraded) { + state += 8; + } + return state; + } + + @Override + public boolean isLocal() { + return this._endPoint.isLocal(); + } + + @Override + public boolean isZombie() { + return this._isZombie; + } + + @Override + public boolean isConsole() { + return this._isConsole; + } + + TechType getTech() { + return this._endPoint.getTech(); + } + + /** + * Returns the actionPrefix for the channel or an empty string if the + * channel is not doing an action. + * + * @return + */ + String getActionPrefix() { + return this._isInAction ? this._actionPrefix : ""; //$NON-NLS-1$ + } + + boolean isInAction() { + return this._isInAction; + } + + boolean isMasqueraded() { + return this._isMasqueraded; + } + + @Override + public boolean hasCallerID() { + return this._callerID != null && !this._callerID.isUnknown(); + } + + @Override + public CallerID getCallerID() { + if (this._callerID == null) { + final CoherentManagerConnection smc = CoherentManagerConnection.getInstance(); + final String number = smc.getVariable(this, "CALLERID(number)"); //$NON-NLS-1$ + final String name = smc.getVariable(this, "CALLERID(name)"); //$NON-NLS-1$ + final PBX pbx = PBXFactory.getActivePBX(); + this._callerID = pbx.buildCallerID(number, name); + } + + return this._callerID; + + } + + @Override + public String getUniqueId() { + return this._uniqueID; + } + + /* + * Returns true if this channel can detect hangups A SIP channel can always + * detect a hangup if its not channel then we need to check the profile to + * see if hangup detection is available. Hangup detection is important as we + * don't want to connect two channels both of which can't do hangup + * detection. If this happened then we would end up with a call which would + * never hangup. + */ + @Override + public boolean canDetectHangup() { + boolean canDetectHangup = true; + + AsteriskSettings profile = PBXFactory.getActiveProfile(); + final boolean detect = profile.getCanDetectHangup(); + if (!this.getEndPoint().isSIP() && !detect) { + canDetectHangup = false; + } + return canDetectHangup; + } + + /** + * Returns true if the channel is quiescent. A quescent channel is one that + * is current not going through a transition (name change) such as MASQ, + * ZOMBIE, ASYNC, PARK + * + * @return + */ + @Override + public boolean isQuiescent() { + return !(_isInAction || _isMasqueraded || _isZombie); + } + + @Override + public AgiChannelActivityAction getCurrentActivityAction() { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public void setCurrentActivityAction(AgiChannelActivityAction action) { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public void setIsInAgi(boolean b) { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public boolean isInAgi() { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } + + @Override + public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException { + throw new RuntimeException("This method is only implemented in ChannelProxy"); + } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java index f502d3f78..40dd823b2 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ChannelProxy.java @@ -1,5 +1,10 @@ package org.asteriskjava.pbx.internal.core; +import org.asteriskjava.pbx.*; +import org.asteriskjava.pbx.agi.AgiChannelActivityHold; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; @@ -7,16 +12,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import org.asteriskjava.pbx.AgiChannelActivityAction; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.ChannelHangupListener; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.InvalidChannelName; -import org.asteriskjava.pbx.agi.AgiChannelActivityHold; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; - /** * The ChannelProxy exists to deal with the fact that Asterisk will often * replace a channel during a call. This is referred to as Masquerading. When a @@ -24,11 +19,10 @@ * class acts as a level of indirection for an iChannel. Rather than holding an * iChannel directly you can instead hold a ChannelProxy. If the underlying * iChannel is replaced the ChannelProxy will be updated with the new iChannel. - * + * * @author bsutton */ -public class ChannelProxy implements Channel, ChannelHangupListener -{ +public class ChannelProxy implements Channel, ChannelHangupListener { private static final Log logger = LogFactory.getLog(ChannelProxy.class); @@ -43,8 +37,7 @@ public class ChannelProxy implements Channel, ChannelHangupListener private final List listeners = new CopyOnWriteArrayList<>(); - public ChannelProxy(ChannelImpl channel) - { + public ChannelProxy(ChannelImpl channel) { this._channel = channel; currentActivityAction.set(new AgiChannelActivityHold()); @@ -54,161 +47,136 @@ public ChannelProxy(ChannelImpl channel) /** * returns the current channel - * + * * @return */ - public Channel getChannel() - { + public Channel getChannel() { return this._channel; } @Override - public boolean isSame(Channel rhs) - { + public boolean isSame(Channel rhs) { return this._channel.isSame(rhs); } @Override - public boolean isSame(String extendedChannelName, String uniqueID) - { + public boolean isSame(String extendedChannelName, String uniqueID) { return this._channel.isSame(extendedChannelName, uniqueID); } - public boolean sameUniqueID(String uniqueID) - { + public boolean sameUniqueID(String uniqueID) { return this._channel.sameUniqueID(uniqueID); } @Override - public boolean sameEndPoint(Channel rhs) - { + public boolean sameEndPoint(Channel rhs) { return this._channel.sameEndPoint(rhs); } @Override - public boolean sameEndPoint(EndPoint extensionRoaming) - { + public boolean sameEndPoint(EndPoint extensionRoaming) { return this._channel.sameEndPoint(extensionRoaming); } @Override - public boolean sameExtenededChannelName(String channelName) - { + public boolean sameExtenededChannelName(String channelName) { return this._channel.sameExtenededChannelName(channelName); } @Override - public void setParked(boolean parked) - { + public void setParked(boolean parked) { this._channel.setParked(parked); } @Override - public void setMute(boolean muteState) - { + public void setMute(boolean muteState) { this._channel.setMute(muteState); } @Override - public long getChannelId() - { + public long getChannelId() { return this._channel.getChannelId(); } @Override - public boolean isLive() - { + public boolean isLive() { return this._channel.isLive(); } @Override - public void addHangupListener(ChannelHangupListener listener) - { - if (!listeners.contains(listener)) - { + public void addHangupListener(ChannelHangupListener listener) { + if (!listeners.contains(listener)) { this.listeners.add(listener); } } @Override - public void removeListener(ChannelHangupListener listener) - { + public void removeListener(ChannelHangupListener listener) { this.listeners.remove(listener); } @Override - public boolean isConnectedTo(EndPoint endPoint) - { + public boolean isConnectedTo(EndPoint endPoint) { return this._channel.isConnectedTo(endPoint); } @Override - public String getChannelName() - { + public String getChannelName() { return this._channel.getChannelName(); } @Override - public EndPoint getEndPoint() - { + public EndPoint getEndPoint() { return this._channel.getEndPoint(); } @Override - public boolean isMute() - { + public boolean isMute() { return this._channel.isMute(); } @Override - public boolean isLocal() - { + public boolean isLocal() { return this._channel.isLocal(); } @Override - public boolean isZombie() - { + public boolean isZombie() { return this._channel.isZombie(); } @Override - public boolean isConsole() - { + public boolean isConsole() { return this._channel.isConsole(); } @Override - public CallerID getCallerID() - { + public CallerID getCallerID() { return this._channel.getCallerID(); } @Override - public void rename(String newName, String uniqueId) throws InvalidChannelName - { + public void rename(String newName, String uniqueId) throws InvalidChannelName { this._channel.rename(newName, uniqueId); } @Override - public boolean isParked() - { + public boolean isParked() { return this._channel.isParked(); } /** * Used to handle a MasqueradeEvent. We essentially swap the two underlying * channels between the two proxies. - * + * * @param cloneProxy * @throws InvalidChannelName */ - public void masquerade(ChannelProxy cloneProxy) throws InvalidChannelName - { + public void masquerade(ChannelProxy cloneProxy) throws InvalidChannelName { ChannelImpl originalChannel = this._channel; ChannelImpl cloneChannel = cloneProxy._channel; @@ -229,29 +197,24 @@ public void masquerade(ChannelProxy cloneProxy) throws InvalidChannelName logger.debug(originalChannel + " Channel proxy now points to " + this._channel); } - public ChannelImpl getRealChannel() - { + public ChannelImpl getRealChannel() { return this._channel; } @Override - public String getExtendedChannelName() - { + public String getExtendedChannelName() { return this._channel.getExtendedChannelName(); } private volatile boolean hangupCalled = false; @Override - public void notifyHangupListeners(Integer cause, String causeText) - { - for (ChannelHangupListener listener : this.listeners) - { + public void notifyHangupListeners(Integer cause, String causeText) { + for (ChannelHangupListener listener : this.listeners) { listener.channelHangup(this, cause, causeText); } - if (hangupCalled) - { + if (hangupCalled) { logger.error("Hangup was already called and the listeners removed - OH NO"); } // we will blow up if notify listeners is called again @@ -261,14 +224,12 @@ public void notifyHangupListeners(Integer cause, String causeText) } @Override - public String toString() - { + public String toString() { return "(proxy=" + this._identity + ") " + this._channel.toString(); //$NON-NLS-1$ //$NON-NLS-2$ } @Override - public void channelHangup(Channel channel, Integer cause, String causeText) - { + public void channelHangup(Channel channel, Integer cause, String causeText) { // When the underlying channel hangs up we need to notify all of the // proxy listeners. if (channel == this._channel) @@ -277,20 +238,17 @@ public void channelHangup(Channel channel, Integer cause, String causeText) } @Override - public boolean canDetectHangup() - { + public boolean canDetectHangup() { return this._channel.canDetectHangup(); } @Override - public boolean isQuiescent() - { + public boolean isQuiescent() { return this._channel.isQuiescent(); } @Override - public boolean hasCallerID() - { + public boolean hasCallerID() { return this._channel.hasCallerID(); } @@ -299,8 +257,7 @@ public boolean hasCallerID() * @see java.lang.Object#hashCode() */ @Override - public int hashCode() - { + public int hashCode() { final int prime = 31; int result = 1; result = prime * result + _identity; @@ -312,23 +269,18 @@ public int hashCode() * @see java.lang.Object#equals(java.lang.Object) */ @Override - public boolean equals(Object obj) - { - if (this == obj) - { + public boolean equals(Object obj) { + if (this == obj) { return true; } - if (obj == null) - { + if (obj == null) { return false; } - if (!(obj instanceof ChannelProxy)) - { + if (!(obj instanceof ChannelProxy)) { return false; } ChannelProxy other = (ChannelProxy) obj; - if (_identity != other._identity) - { + if (_identity != other._identity) { return false; } return true; @@ -338,14 +290,12 @@ public boolean equals(Object obj) volatile private boolean isInAgi; @Override - public AgiChannelActivityAction getCurrentActivityAction() - { + public AgiChannelActivityAction getCurrentActivityAction() { return currentActivityAction.get(); } @Override - public void setCurrentActivityAction(AgiChannelActivityAction action) - { + public void setCurrentActivityAction(AgiChannelActivityAction action) { AgiChannelActivityAction previousAction = currentActivityAction.get(); logger.debug("Setting action to " + action.getClass().getSimpleName() + " for " + this); @@ -355,18 +305,15 @@ public void setCurrentActivityAction(AgiChannelActivityAction action) // logger.warn(e, e); currentActivityAction.set(action); - if (previousAction != null) - { + if (previousAction != null) { // when we cancel the previous action, the new one will be invoked previousAction.cancel(); } } @Override - public void setIsInAgi(boolean b) - { - if (b) - { + public void setIsInAgi(boolean b) { + if (b) { hasReachedAgi.countDown(); } isInAgi = b; @@ -375,16 +322,14 @@ public void setIsInAgi(boolean b) } @Override - public boolean isInAgi() - { + public boolean isInAgi() { return isInAgi; } final CountDownLatch hasReachedAgi = new CountDownLatch(1); @Override - public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException - { + public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws InterruptedException { logger.info("Waiting for channel to reach agi " + this); boolean tmp = hasReachedAgi.await(timeout, timeunit); logger.info("Result of waiting for channel to reach agi " + this + " " + tmp); @@ -392,19 +337,16 @@ public boolean waitForChannelToReachAgi(long timeout, TimeUnit timeunit) throws } @Override - public String getUniqueId() - { + public String getUniqueId() { return _channel.getUniqueId(); } - public int getIdentity() - { + public int getIdentity() { return _identity; } @Override - public void setCallerId(CallerID callerId) - { + public void setCallerId(CallerID callerId) { _channel.setCallerId(callerId); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java index c90c6c39f..22941bf19 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java @@ -1,11 +1,5 @@ package org.asteriskjava.pbx.internal.core; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Modifier; -import java.util.Hashtable; -import java.util.Set; - import org.asteriskjava.pbx.asterisk.wrap.actions.ManagerAction; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvent; @@ -16,6 +10,12 @@ import org.asteriskjava.util.LogFactory; import org.asteriskjava.util.ReflectionUtil; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.util.Hashtable; +import java.util.Set; + /** * This class maps asterisk-java events to our internal events that use iChannel * rather than raw channel names. @@ -23,72 +23,53 @@ * @author bsutton */ @SuppressWarnings({"unchecked"}) -public class CoherentEventFactory -{ +public class CoherentEventFactory { private static final Log logger = LogFactory.getLog(CoherentEventFactory.class); // Events static Hashtable, Class> mapEvents = new Hashtable<>(); // Response - static Hashtable, Class< ? extends ResponseEvent>> mapResponses = new Hashtable<>(); + static Hashtable, Class> mapResponses = new Hashtable<>(); // static initialiser - static - { + static { Set> knownClasses = ReflectionUtil.loadClasses("org.asteriskjava.pbx.asterisk.wrap.events", ManagerEvent.class); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - for (Class< ? > known : knownClasses) - { - Class< ? > clazz = null; - try - { + for (Class known : knownClasses) { + Class clazz = null; + try { clazz = classLoader.loadClass("org.asteriskjava.manager.event" + "." + known.getSimpleName()); - if (!Modifier.isAbstract(clazz.getModifiers())) - { - if (known.getConstructor(clazz) != null) - { - if (ResponseEvent.class.isAssignableFrom(known)) - { + if (!Modifier.isAbstract(clazz.getModifiers())) { + if (known.getConstructor(clazz) != null) { + if (ResponseEvent.class.isAssignableFrom(known)) { CoherentEventFactory.mapResponses.put( (Class) clazz, (Class) known); logger.info("Response Event Added " + clazz + " --> " + known); - } - else - { + } else { CoherentEventFactory.mapEvents.put((Class) clazz, (Class) known); logger.info("Manager Event Added " + clazz + " --> " + known); } - } - else - { + } else { logger.warn("Skipping class " + clazz + " it doesn't have a public constructor with one arg of type " + known); } - } - else - { + } else { logger.info("Skipping abstract class " + clazz); } - } - catch (ClassNotFoundException e) - { + } catch (ClassNotFoundException e) { logger.error(e, e); throw new RuntimeException(e); - } - catch (NoSuchMethodException e) - { + } catch (NoSuchMethodException e) { logger.error(clazz.getCanonicalName() + " doesn't have an appropriate event constructor"); - } - catch (SecurityException e) - { + } catch (SecurityException e) { logger.error(e, e); } } @@ -97,12 +78,10 @@ public class CoherentEventFactory } - public static Class< ? extends ManagerEvent> getShadowEvent(org.asteriskjava.manager.event.ManagerEvent event) - { - Class< ? extends ManagerEvent> result = CoherentEventFactory.mapEvents.get(event.getClass()); - if (result == null) - { - Class< ? extends ResponseEvent> response = CoherentEventFactory.mapResponses.get(event.getClass()); + public static Class getShadowEvent(org.asteriskjava.manager.event.ManagerEvent event) { + Class result = CoherentEventFactory.mapEvents.get(event.getClass()); + if (result == null) { + Class response = CoherentEventFactory.mapResponses.get(event.getClass()); result = response; } @@ -110,31 +89,24 @@ public class CoherentEventFactory } - public static ManagerEvent build(final org.asteriskjava.manager.event.ManagerEvent event) - { + public static ManagerEvent build(final org.asteriskjava.manager.event.ManagerEvent event) { ManagerEvent iEvent = null; - Class< ? extends ManagerEvent> target = null; + Class target = null; if (event instanceof org.asteriskjava.manager.event.ResponseEvent) target = CoherentEventFactory.mapResponses.get(event.getClass()); else target = CoherentEventFactory.mapEvents.get(event.getClass()); - if (target == null) - { + if (target == null) { logger.warn("The given event " + event.getClass().getName() + " is not supported "); //$NON-NLS-1$ //$NON-NLS-2$ - } - else - { + } else { - try - { + try { iEvent = target.getDeclaredConstructor(event.getClass()).newInstance(event); - } - catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException - | IllegalArgumentException | InvocationTargetException e) - { + } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { CoherentEventFactory.logger.error(e, e); } @@ -142,28 +114,21 @@ public static ManagerEvent build(final org.asteriskjava.manager.event.ManagerEve return iEvent; } - public static ResponseEvent build(org.asteriskjava.manager.event.ResponseEvent event) - { + public static ResponseEvent build(org.asteriskjava.manager.event.ResponseEvent event) { ResponseEvent response = null; - final Class< ? extends ResponseEvent> target = CoherentEventFactory.mapResponses.get(event.getClass()); + final Class target = CoherentEventFactory.mapResponses.get(event.getClass()); - if (target == null) - { + if (target == null) { logger.warn("The given event " + event.getClass().getName() + " is not supported "); //$NON-NLS-1$ //$NON-NLS-2$ - } - else - { + } else { - try - { - final Constructor< ? extends ResponseEvent> declaredConstructor = target + try { + final Constructor declaredConstructor = target .getDeclaredConstructor(event.getClass()); response = declaredConstructor.newInstance(event); - } - catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException - | IllegalArgumentException | InvocationTargetException e) - { + } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { CoherentEventFactory.logger.error(e, e); } @@ -171,27 +136,20 @@ public static ResponseEvent build(org.asteriskjava.manager.event.ResponseEvent e return response; } - public static ManagerResponse build(org.asteriskjava.manager.response.ManagerResponse response) - { + public static ManagerResponse build(org.asteriskjava.manager.response.ManagerResponse response) { ManagerResponse result; - if (response instanceof org.asteriskjava.manager.response.CommandResponse) - { + if (response instanceof org.asteriskjava.manager.response.CommandResponse) { result = new CommandResponse(response); - } - else if (response instanceof org.asteriskjava.manager.response.ManagerError) - { + } else if (response instanceof org.asteriskjava.manager.response.ManagerError) { result = new ManagerError(response); - } - else - { + } else { result = new ManagerResponse(response); } return result; } - public static org.asteriskjava.manager.action.ManagerAction build(ManagerAction action) - { + public static org.asteriskjava.manager.action.ManagerAction build(ManagerAction action) { org.asteriskjava.manager.action.ManagerAction result = null; // final Class diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java index aeff22db8..fd73f2fd8 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerConnection.java @@ -1,31 +1,9 @@ package org.asteriskjava.pbx.internal.core; -import java.io.IOException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import javax.naming.OperationNotSupportedException; - import org.asteriskjava.AsteriskVersion; -import org.asteriskjava.manager.AuthenticationFailedException; -import org.asteriskjava.manager.EventTimeoutException; -import org.asteriskjava.manager.ManagerConnection; -import org.asteriskjava.manager.ManagerConnectionState; -import org.asteriskjava.manager.TimeoutException; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; -import org.asteriskjava.pbx.asterisk.wrap.actions.EventGeneratingAction; -import org.asteriskjava.pbx.asterisk.wrap.actions.GetVarAction; -import org.asteriskjava.pbx.asterisk.wrap.actions.ListCommandsAction; -import org.asteriskjava.pbx.asterisk.wrap.actions.ManagerAction; -import org.asteriskjava.pbx.asterisk.wrap.actions.SetVarAction; +import org.asteriskjava.manager.*; +import org.asteriskjava.pbx.*; +import org.asteriskjava.pbx.asterisk.wrap.actions.*; import org.asteriskjava.pbx.asterisk.wrap.events.ConnectEvent; import org.asteriskjava.pbx.asterisk.wrap.events.DisconnectEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; @@ -35,6 +13,14 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import javax.naming.OperationNotSupportedException; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + /** * This is a wrapper class for the asterisk manager.
    *
    @@ -64,12 +50,11 @@ * coherent (i.e events are processed in the correct order).
    *
    * For connections that generate large number of events you should use - * + * * @see org.asteriskjava.pbx.internal.core.CoherentManagerEventQueue Note: - * events for any action are distributed to all listeners! + * events for any action are distributed to all listeners! */ -class CoherentManagerConnection implements FilteredManagerListener -{ +class CoherentManagerConnection implements FilteredManagerListener { static private Log logger = LogFactory.getLog(CoherentManagerConnection.class); @@ -116,32 +101,23 @@ class CoherentManagerConnection implements FilteredManagerListener private boolean expectRenameEvents = true; public static synchronized void init() - throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException, InterruptedException - { + throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException, InterruptedException { if (self != null) logger.warn("The CoherentManagerConnection has already been initialised"); - else - { + else { self = new CoherentManagerConnection(); boolean done = false; - while (!done) - { - try - { + while (!done) { + try { self.checkConnection(); self.checkFeatures(); done = true; - } - catch (Exception e) - { + } catch (Exception e) { logger.error(e, e); - try - { + try { TimeUnit.MILLISECONDS.sleep(500); - } - catch (InterruptedException e1) - { + } catch (InterruptedException e1) { throw e1; } } @@ -151,13 +127,11 @@ public static synchronized void init() self.checkConnection(); } - public static void reset() - { + public static void reset() { self = null; } - public static synchronized CoherentManagerConnection getInstance() - { + public static synchronized CoherentManagerConnection getInstance() { if (self == null) throw new IllegalStateException("The CoherentManagerConnection has not been initialised"); @@ -167,22 +141,18 @@ public static synchronized CoherentManagerConnection getInstance() } private CoherentManagerConnection() - throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException - { + throws IllegalStateException, IOException, AuthenticationFailedException, TimeoutException { super(); connector = new Connector(); this.configureConnection(); } - public AsteriskVersion getVersion() throws IllegalStateException - { + public AsteriskVersion getVersion() throws IllegalStateException { return CoherentManagerConnection.managerConnection.getVersion(); } - public void setVariable(final Channel channel, final String variableName, final String value) throws PBXException - { - try - { + public void setVariable(final Channel channel, final String variableName, final String value) throws PBXException { + try { /* * Sets the specified variable on the specified channel to the * specified value. @@ -195,21 +165,16 @@ public void setVariable(final Channel channel, final String variableName, final throw new PBXException("Channel: " + channel + " cannot be retrieved as it is still in transition."); response = sendAction(setVariable, 500); - if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0)) - { + if ((response != null) && (response.getResponse().compareToIgnoreCase("success") == 0)) { // $NON-NLS-1$ CoherentManagerConnection.logger.debug("set variable " + variableName + " to " + value //$NON-NLS-2$ + " on " + channel); - } - else - { + } else { throw new PBXException("failed to set variable '" + variableName + "' on channel " + channel + " to '" //$NON-NLS-2$ //$NON-NLS-3$ + value + "'" + (response != null ? " Error:" + response.getMessage() : "")); //$NON-NLS-2$ //$NON-NLS-3$ } - } - catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) - { + } catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) { logger.error(e, e); throw new PBXException(e); @@ -220,33 +185,28 @@ public void setVariable(final Channel channel, final String variableName, final /** * Retrieves and returns the value of a variable associated with a channel. * If the variable is empty or null then an empty string is returned. - * + * * @param channel * @param variableName * @return */ - public String getVariable(final Channel channel, final String variableName) - { + public String getVariable(final Channel channel, final String variableName) { String value = ""; final GetVarAction var = new GetVarAction(channel, variableName); - try - { + try { PBX pbx = PBXFactory.getActivePBX(); if (!pbx.waitForChannelToQuiescent(channel, 3000)) throw new PBXException("Channel: " + channel + " cannot be retrieved as it is still in transition."); ManagerResponse convertedResponse = sendAction(var, 500); - if (convertedResponse != null) - { + if (convertedResponse != null) { value = convertedResponse.getAttribute("value"); if (value == null) value = ""; CoherentManagerConnection.logger.debug("getVarAction returned name:" + variableName + " value:" + value); //$NON-NLS-2$ } - } - catch (final Exception e) - { + } catch (final Exception e) { CoherentManagerConnection.logger.debug(e, e); CoherentManagerConnection.logger.error("getVariable: " + e); } @@ -257,22 +217,16 @@ public String getVariable(final Channel channel, final String variableName) * Allows the caller to send an action to asterisk without waiting for the * response. You should only use this if you don't care whether the action * actually succeeds. - * + * * @param sa */ - public static void sendActionNoWait(final ManagerAction action) - { - final Thread background = new Thread() - { + public static void sendActionNoWait(final ManagerAction action) { + final Thread background = new Thread() { @Override - public void run() - { - try - { + public void run() { + try { CoherentManagerConnection.sendAction(action, 5000); - } - catch (final Exception e) - { + } catch (final Exception e) { CoherentManagerConnection.logger.error(e, e); } } @@ -283,14 +237,12 @@ public void run() } public static ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) - throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException - { + throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException { org.asteriskjava.manager.ResponseEvents events = CoherentManagerConnection.managerConnection .sendEventGeneratingAction(action.getAJEventGeneratingAction()); ResponseEvents convertedEvents = new ResponseEvents(); - for (org.asteriskjava.manager.event.ResponseEvent event : events.getEvents()) - { + for (org.asteriskjava.manager.event.ResponseEvent event : events.getEvents()) { convertedEvents.add(CoherentEventFactory.build(event)); } return convertedEvents; @@ -298,14 +250,12 @@ public static ResponseEvents sendEventGeneratingAction(EventGeneratingAction act } public static ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, int timeout) - throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException - { + throws EventTimeoutException, IllegalArgumentException, IllegalStateException, IOException { org.asteriskjava.manager.ResponseEvents events = CoherentManagerConnection.managerConnection .sendEventGeneratingAction(action.getAJEventGeneratingAction(), timeout); ResponseEvents convertedEvents = new ResponseEvents(); - for (org.asteriskjava.manager.event.ResponseEvent event : events.getEvents()) - { + for (org.asteriskjava.manager.event.ResponseEvent event : events.getEvents()) { convertedEvents.add(CoherentEventFactory.build(event)); } return convertedEvents; @@ -314,7 +264,7 @@ public static ResponseEvents sendEventGeneratingAction(EventGeneratingAction act /** * Sends an Asterisk action and waits for a ManagerRespose. - * + * * @param action * @param timeout timeout in milliseconds * @return @@ -325,15 +275,13 @@ public static ResponseEvents sendEventGeneratingAction(EventGeneratingAction act * @throws OperationNotSupportedException */ public static ManagerResponse sendAction(final ManagerAction action, final int timeout) - throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException - { + throws IllegalArgumentException, IllegalStateException, IOException, TimeoutException { if (logger.isDebugEnabled()) CoherentManagerConnection.logger.debug("Sending Action: " + action.toString()); CoherentManagerConnection.getInstance(); if ((CoherentManagerConnection.managerConnection != null) - && (CoherentManagerConnection.managerConnection.getState() == ManagerConnectionState.CONNECTED)) - { + && (CoherentManagerConnection.managerConnection.getState() == ManagerConnectionState.CONNECTED)) { final org.asteriskjava.manager.action.ManagerAction ajAction = action.getAJAction(); org.asteriskjava.manager.response.ManagerResponse response = CoherentManagerConnection.managerConnection @@ -344,8 +292,7 @@ public static ManagerResponse sendAction(final ManagerAction action, final int t if (response != null) convertedResponse = CoherentEventFactory.build(response); - if ((convertedResponse != null) && (convertedResponse.getResponse().compareToIgnoreCase("Error") == 0)) - { + if ((convertedResponse != null) && (convertedResponse.getResponse().compareToIgnoreCase("Error") == 0)) { CoherentManagerConnection.logger.warn("Action '" + ajAction + "' failed, Response: " + convertedResponse.getResponse() + " Message: " + convertedResponse.getMessage()); } @@ -355,39 +302,31 @@ public static ManagerResponse sendAction(final ManagerAction action, final int t throw new IllegalStateException("not connected."); } - private void checkConnection() - { + private void checkConnection() { int trys = 3; this._reconnectLatch = new CountDownLatch(1); while ((trys > 0) && ((CoherentManagerConnection.managerConnection == null) - || (CoherentManagerConnection.managerConnection.getState() != ManagerConnectionState.CONNECTED))) - { - if (trys == 3) - { + || (CoherentManagerConnection.managerConnection.getState() != ManagerConnectionState.CONNECTED))) { + if (trys == 3) { CoherentManagerConnection.logger.warn("Awaiting Manager connection"); } - try - { + try { this._reconnectLatch.await(300, TimeUnit.MILLISECONDS); - } - catch (final InterruptedException e) - { + } catch (final InterruptedException e) { CoherentManagerConnection.logger.error(e, e); } trys--; } } - public ManagerConnectionState getState() - { + public ManagerConnectionState getState() { return CoherentManagerConnection.managerConnection.getState(); } private void configureConnection() - throws IOException, AuthenticationFailedException, TimeoutException, IllegalStateException - { + throws IOException, AuthenticationFailedException, TimeoutException, IllegalStateException { final AsteriskSettings profile = PBXFactory.getActiveProfile(); CoherentManagerConnection.managerConnection = CoherentManagerConnection.connector.connect(profile); @@ -400,8 +339,7 @@ private void configureConnection() // garbage collected. CoherentManagerEventQueue newRealtime = new CoherentManagerEventQueue("Realtime", CoherentManagerConnection.managerConnection); - if (this.realtimeEventQueue != null) - { + if (this.realtimeEventQueue != null) { this.realtimeEventQueue.stop(); newRealtime.transferListeners(this.realtimeEventQueue); } @@ -409,16 +347,14 @@ private void configureConnection() CoherentManagerEventQueue newStandard = new CoherentManagerEventQueue("Standard", CoherentManagerConnection.managerConnection); - if (this.eventQueue != null) - { + if (this.eventQueue != null) { this.eventQueue.stop(); newStandard.transferListeners(this.eventQueue); } this.eventQueue = newStandard; } - private void checkFeatures() throws IOException, TimeoutException - { + private void checkFeatures() throws IOException, TimeoutException { final AsteriskSettings profile = PBXFactory.getActiveProfile(); // Determine if the Bridge and Mute events are available. @@ -426,60 +362,46 @@ private void checkFeatures() throws IOException, TimeoutException ManagerResponse convertedResponse = sendAction(lca, 500); boolean bridgeFound = false; boolean muteAudioFound = false; - for (final String command : convertedResponse.getAttributes().keySet()) - { - if (command.toLowerCase().contains("bridge")) - { + for (final String command : convertedResponse.getAttributes().keySet()) { + if (command.toLowerCase().contains("bridge")) { bridgeFound = true; } - if (command.toLowerCase().contains("muteaudio")) - { + if (command.toLowerCase().contains("muteaudio")) { muteAudioFound = true; } } - if (CoherentManagerConnection.managerConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) - { + if (CoherentManagerConnection.managerConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) { // we are really checking for the use of PJ SIP expectRenameEvents = false; } this.canMuteAudio = muteAudioFound; - if (profile.getDisableBridge()) - { + if (profile.getDisableBridge()) { this.canBridge = false; - } - else - { + } else { this.canBridge = bridgeFound; } } - public void shutDown() - { + public void shutDown() { CoherentManagerConnection.managerConnection.removeEventListener(this.eventQueue); this.eventQueue.stop(); - try - { + try { CoherentManagerConnection.managerConnection.logoff(); - } - catch (final Exception e) - { + } catch (final Exception e) { CoherentManagerConnection.logger.debug("Manager logging off"); CoherentManagerConnection.logger.debug(e, e); } } - public boolean isBridgeSupported() - { + public boolean isBridgeSupported() { return this.canBridge; } - public boolean isMuteAudioSupported() - { + public boolean isMuteAudioSupported() { return this.canMuteAudio; } - public void removeListener(FilteredManagerListener listener) - { + public void removeListener(FilteredManagerListener listener) { if (listener.getPriority() == ListenerPriority.REALTIME) this.realtimeEventQueue.removeListener(listener); else @@ -487,8 +409,7 @@ public void removeListener(FilteredManagerListener listener) } - public void addListener(FilteredManagerListener listener) - { + public void addListener(FilteredManagerListener listener) { if (listener.getPriority() == ListenerPriority.REALTIME) this.realtimeEventQueue.addListener(listener); else @@ -497,41 +418,34 @@ public void addListener(FilteredManagerListener listener) } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); required.add(ConnectEvent.class); required.add(DisconnectEvent.class); return required; } @Override - public String getName() - { + public String getName() { return "CoherentManagerConnection"; } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.REALTIME; } @Override - public void onManagerEvent(ManagerEvent event) - { + public void onManagerEvent(ManagerEvent event) { // Special handler for the connect event in case we are // wait()ing for // the connection to complete. This wakes the code up in the shortest // time possible // by notifying it of the connection. - if (event instanceof ConnectEvent) - { + if (event instanceof ConnectEvent) { logger.warn("****************** Asterisk manager connection acquired **************************"); this._reconnectLatch.countDown(); - } - else if (event instanceof DisconnectEvent) - { + } else if (event instanceof DisconnectEvent) { logger.warn("****************** Asterisk manager connection lost **************************"); // new Thread(new Runnable() // { @@ -544,8 +458,7 @@ else if (event instanceof DisconnectEvent) } - public boolean expectRenameEvents() - { + public boolean expectRenameEvents() { return expectRenameEvents; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java index c5aa4799d..62776b976 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventListener.java @@ -1,16 +1,14 @@ package org.asteriskjava.pbx.internal.core; -import java.util.EventListener; - import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -public interface CoherentManagerEventListener extends EventListener -{ - /** - * This method is called when an event is received. - * - * @param event - * the event that has been received - */ - void onManagerEvent(ManagerEvent event); +import java.util.EventListener; + +public interface CoherentManagerEventListener extends EventListener { + /** + * This method is called when an event is received. + * + * @param event the event that has been received + */ + void onManagerEvent(ManagerEvent event); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java index cdf06e05d..213520fe6 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentManagerEventQueue.java @@ -1,16 +1,5 @@ package org.asteriskjava.pbx.internal.core; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - import org.asteriskjava.lock.LockableSet; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.manager.ManagerConnection; @@ -24,6 +13,12 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.*; + /** * This class provides a method of accepting, queueing and delivering manager * events. Asterisk is very sensitive to delays in receiving events. This class @@ -32,11 +27,10 @@ * follows: manager.addEventListener(new * CoherentManagerEventQueue(originalListener)); This affectively daisy changes * the originalListener via our queue. - * + * * @author bsutton */ -class CoherentManagerEventQueue implements ManagerEventListener, Runnable -{ +class CoherentManagerEventQueue implements ManagerEventListener, Runnable { private static final Log logger = LogFactory.getLog(CoherentManagerEventQueue.class); private final ListenerManager listeners = new ListenerManager(); @@ -49,10 +43,9 @@ class CoherentManagerEventQueue implements ManagerEventListener, Runnable long suppressQueueSizeErrorUntil = 0; - private LockableSet> globalEvents = new LockableSet<>(new HashSet<>()); + private LockableSet> globalEvents = new LockableSet<>(new HashSet<>()); - public CoherentManagerEventQueue(String name, ManagerConnection connection) - { + public CoherentManagerEventQueue(String name, ManagerConnection connection) { connection.addEventListener(this); @@ -68,8 +61,7 @@ public CoherentManagerEventQueue(String name, ManagerConnection connection) * subsequently passed on to the original listener. */ @Override - public void onManagerEvent(final org.asteriskjava.manager.event.ManagerEvent event) - { + public void onManagerEvent(final org.asteriskjava.manager.event.ManagerEvent event) { // logger.error(event); boolean wanted = false; @@ -78,22 +70,18 @@ public void onManagerEvent(final org.asteriskjava.manager.event.ManagerEvent eve * processing overhead of these events. */ // Only enqueue the events that are of interest to one of our listeners. - try (LockCloser closer = this.globalEvents.withLock()) - { - Class< ? extends ManagerEvent> shadowEvent = CoherentEventFactory.getShadowEvent(event); - if (this.globalEvents.contains(shadowEvent)) - { + try (LockCloser closer = this.globalEvents.withLock()) { + Class shadowEvent = CoherentEventFactory.getShadowEvent(event); + if (this.globalEvents.contains(shadowEvent)) { wanted = true; } } - if (wanted) - { + if (wanted) { // We don't support all events. this._eventQueue.add(new EventLifeMonitor<>(event)); if (_eventQueue.remainingCapacity() < QUEUE_SIZE / 10 - && suppressQueueSizeErrorUntil < System.currentTimeMillis()) - { + && suppressQueueSizeErrorUntil < System.currentTimeMillis()) { suppressQueueSizeErrorUntil = System.currentTimeMillis() + 1000; logger.error("EventQueue more than 90% full"); } @@ -102,76 +90,58 @@ public void onManagerEvent(final org.asteriskjava.manager.event.ManagerEvent eve } @Override - public void run() - { - try - { - while (!this._stop) - { - try - { + public void run() { + try { + while (!this._stop) { + try { final EventLifeMonitor elm = this._eventQueue.poll(2, TimeUnit.SECONDS); - if (elm != null) - { + if (elm != null) { // A poison queue event means its time to shutdown. - if (elm.getEvent().getClass() == PoisonQueueEvent.class) - { + if (elm.getEvent().getClass() == PoisonQueueEvent.class) { logger.warn("Got Poison event"); break; } final ManagerEvent iEvent = CoherentEventFactory.build(elm.getEvent()); - if (iEvent != null) - { + if (iEvent != null) { dispatchEvent(iEvent); elm.assessAge(); } } - } - catch (final Exception e) - { + } catch (final Exception e) { /** * If an exception is thrown whilst we are shutting down * then we don't care. If it is thrown when we aren't * shutting down then we have a problem and we need to log * it. */ - if (!this._stop) - { + if (!this._stop) { CoherentManagerEventQueue.logger.error(e, e); } } } - } - finally - { + } finally { logger.warn("Shutting down!"); } } - class PoisonQueueEvent extends org.asteriskjava.manager.event.ManagerEvent - { + class PoisonQueueEvent extends org.asteriskjava.manager.event.ManagerEvent { private static final long serialVersionUID = 1L; - public PoisonQueueEvent() - { + public PoisonQueueEvent() { super("PoisonQueueEvent"); //$NON-NLS-1$ } } - public void stop() - { + public void stop() { this._stop = true; - try - { + try { this._eventQueue.put(new EventLifeMonitor(new PoisonQueueEvent())); - } - catch (InterruptedException e) - { + } catch (InterruptedException e) { logger.error(e, e); } @@ -186,10 +156,8 @@ public void stop() * from a dedicated thread attached to the event queue which it uses for * dispatching events. */ - public void dispatchEvent(final ManagerEvent event) - { - if (logger.isDebugEnabled()) - { + public void dispatchEvent(final ManagerEvent event) { + if (logger.isDebugEnabled()) { logger.debug("dispatch=" + event.toString()); //$NON-NLS-1$ } @@ -197,72 +165,53 @@ public void dispatchEvent(final ManagerEvent event) // iterate over them // The iteration may call some long running processes. final List listenerCopy; - try (LockCloser closer = this.listeners.withLock()) - { + try (LockCloser closer = this.listeners.withLock()) { listenerCopy = this.listeners.getCopyAsList(); } - try - { + try { final LogTime totalTime = new LogTime(); CountDownLatch latch = new CountDownLatch(listenerCopy.size()); - for (final FilteredManagerListenerWrapper filter : listenerCopy) - { - if (filter.requiredEvents.contains(event.getClass())) - { + for (final FilteredManagerListenerWrapper filter : listenerCopy) { + if (filter.requiredEvents.contains(event.getClass())) { dispatchEventOnThread(event, filter, latch); - } - else - { + } else { // this listener didn't want the event, so just decrease the // countdown latch.countDown(); } } - if (!latch.await(2, TimeUnit.SECONDS)) - { + if (!latch.await(2, TimeUnit.SECONDS)) { logger.error("Timeout waiting for event to be processed " + event); } - if (totalTime.timeTaken() > 100) - { + if (totalTime.timeTaken() > 100) { logger.warn("Too long to process event " + event + " time taken: " + totalTime.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$ } - } - catch (InterruptedException e) - { + } catch (InterruptedException e) { Thread.interrupted(); } } private void dispatchEventOnThread(final ManagerEvent event, final FilteredManagerListenerWrapper filter, - final CountDownLatch latch) - { - Runnable runner = new Runnable() - { + final CountDownLatch latch) { + Runnable runner = new Runnable() { @Override - public void run() - { - try - { + public void run() { + try { final LogTime time = new LogTime(); filter._listener.onManagerEvent(event); - if (time.timeTaken() > 500) - { + if (time.timeTaken() > 500) { logger.warn("ManagerListener :" + filter._listener.getName() //$NON-NLS-1$ + " is taken too long to process event " + event + " time taken: " + time.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$ } - } - catch (Exception e) - { + } catch (Exception e) { logger.error(e, e); - } - finally - { + } finally { latch.countDown(); } } @@ -278,17 +227,14 @@ public void run() * which is read via a thread which is shared by all listeners. Whilst poor * performance of you listener can affect other listeners you can't affect * the read thread which takes events from asterisk and enqueues them. - * + * * @param listener */ - public void addListener(final FilteredManagerListener listener) - { - try (LockCloser closer = this.listeners.withLock()) - { + public void addListener(final FilteredManagerListener listener) { + try (LockCloser closer = this.listeners.withLock()) { this.listeners.addListener(listener); - try (LockCloser closer2 = this.globalEvents.withLock()) - { - Collection> expandEvents = expandEvents(listener.requiredEvents()); + try (LockCloser closer2 = this.globalEvents.withLock()) { + Collection> expandEvents = expandEvents(listener.requiredEvents()); this.globalEvents.addAll(expandEvents); } } @@ -299,18 +245,15 @@ public void addListener(final FilteredManagerListener listener) * in order to get Bridge Events, we must subscribe to Link and Unlink * events for asterisk 1.4, so we automatically add them if the Bridge Event * is required - * + * * @param events * @return */ - Collection> expandEvents(Collection> events) - { - Collection> requiredEvents = new HashSet<>(); - for (Class< ? extends ManagerEvent> event : events) - { + Collection> expandEvents(Collection> events) { + Collection> requiredEvents = new HashSet<>(); + for (Class event : events) { requiredEvents.add(event); - if (event.equals(BridgeEvent.class)) - { + if (event.equals(BridgeEvent.class)) { requiredEvents.add(UnlinkEvent.class); requiredEvents.add(LinkEvent.class); } @@ -319,23 +262,18 @@ public void addListener(final FilteredManagerListener listener) return requiredEvents; } - public void removeListener(final FilteredManagerListener melf) - { - if (melf != null) - { - try (LockCloser closer = this.listeners.withLock()) - { + public void removeListener(final FilteredManagerListener melf) { + if (melf != null) { + try (LockCloser closer = this.listeners.withLock()) { this.listeners.removeListener(melf); // When we remove a listener we must unfortunately // completely // recalculate the set of required events. - try (LockCloser closer2 = this.globalEvents.withLock()) - { + try (LockCloser closer2 = this.globalEvents.withLock()) { this.globalEvents.clear(); Iterator itr = this.listeners.iterator(); - while (itr.hasNext()) - { + while (itr.hasNext()) { FilteredManagerListenerWrapper readdContainer = itr.next(); this.globalEvents.addAll(expandEvents(readdContainer._listener.requiredEvents())); } @@ -349,18 +287,14 @@ public void removeListener(final FilteredManagerListener melf) /** * transfers the listeners from one queue to another. - * + * * @param eventQueue */ - public void transferListeners(CoherentManagerEventQueue eventQueue) - { - try (LockCloser closer = this.listeners.withLock()) - { - try (LockCloser closer2 = eventQueue.listeners.withLock()) - { + public void transferListeners(CoherentManagerEventQueue eventQueue) { + try (LockCloser closer = this.listeners.withLock()) { + try (LockCloser closer2 = eventQueue.listeners.withLock()) { Iterator itr = eventQueue.listeners.iterator(); - while (itr.hasNext()) - { + while (itr.hasNext()) { FilteredManagerListenerWrapper listener = itr.next(); this.addListener(listener._listener); diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java index bec7f02bd..b399d795b 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/DialLocalToAgiActivity.java @@ -1,22 +1,6 @@ package org.asteriskjava.pbx.internal.core; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.asteriskjava.pbx.Activity; -import org.asteriskjava.pbx.ActivityCallback; -import org.asteriskjava.pbx.ActivityStatusEnum; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.agi.ActivityAgi; import org.asteriskjava.pbx.agi.ActivityArrivalListener; import org.asteriskjava.pbx.asterisk.wrap.actions.OriginateAction; @@ -24,8 +8,14 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class DialLocalToAgiActivity implements Runnable, Activity -{ +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class DialLocalToAgiActivity implements Runnable, Activity { private EndPoint from; private CallerID fromCallerID; @@ -38,8 +28,7 @@ public class DialLocalToAgiActivity implements Runnable, Activity private Map channelVarsToSet; public DialLocalToAgiActivity(EndPoint from, CallerID fromCallerID, ActivityCallback callback, - Map channelVarsToSet) - { + Map channelVarsToSet) { this.from = from; this.fromCallerID = fromCallerID; this.callback = callback; @@ -51,8 +40,7 @@ public DialLocalToAgiActivity(EndPoint from, CallerID fromCallerID, ActivityCall // Logger logger = LogManager.getLogger(); @Override - public void run() - { + public void run() { logger.debug("*******************************************************************************"); logger.info("*********** begin dial local to AGI ****************"); logger.debug("*********** ****************"); @@ -71,48 +59,35 @@ public void run() Map myVars = new HashMap<>(); - if (channelVarsToSet != null) - { + if (channelVarsToSet != null) { myVars.putAll(channelVarsToSet); } originate.setVariables(myVars); - ActivityArrivalListener listener = new ActivityArrivalListener() - { + ActivityArrivalListener listener = new ActivityArrivalListener() { @Override - public void channelArrived(Channel channel) - { + public void channelArrived(Channel channel) { channels.add(channel); - if (isSuccess()) - { + if (isSuccess()) { latch.countDown(); } } }; - try (AutoCloseable closeable = ActivityAgi.addArrivalListener(originate, listener);) - { + try (AutoCloseable closeable = ActivityAgi.addArrivalListener(originate, listener);) { ManagerResponse response = pbx.sendAction(originate, 5000); - if (response.getResponse().compareToIgnoreCase("Success") != 0) - { + if (response.getResponse().compareToIgnoreCase("Success") != 0) { callback.progress(this, ActivityStatusEnum.FAILURE, ActivityStatusEnum.FAILURE.getDefaultMessage()); - } - else - { - if (latch.await(5, TimeUnit.SECONDS)) - { + } else { + if (latch.await(5, TimeUnit.SECONDS)) { callback.progress(this, ActivityStatusEnum.SUCCESS, ActivityStatusEnum.SUCCESS.getDefaultMessage()); - } - else - { + } else { callback.progress(this, ActivityStatusEnum.FAILURE, ActivityStatusEnum.FAILURE.getDefaultMessage()); } } - } - catch (Exception e) - { + } catch (Exception e) { logger.error(e, e); callback.progress(this, ActivityStatusEnum.FAILURE, ActivityStatusEnum.FAILURE.getDefaultMessage()); @@ -120,19 +95,14 @@ public void channelArrived(Channel channel) } - public void abort(final String reason) - { + public void abort(final String reason) { logger.warn("Aborting originate "); - for (Channel channel : channels) - { + for (Channel channel : channels) { PBX pbx = PBXFactory.getActivePBX(); - try - { + try { pbx.hangup(channel); - } - catch (IllegalArgumentException | IllegalStateException | PBXException e) - { + } catch (IllegalArgumentException | IllegalStateException | PBXException e) { logger.error(e, e); } @@ -142,25 +112,21 @@ public void abort(final String reason) } @Override - public Throwable getLastException() - { + public Throwable getLastException() { return null; } @Override - public boolean isSuccess() - { + public boolean isSuccess() { return channels.size() == 2; } - public Channel getChannel1() - { + public Channel getChannel1() { return channels.get(0); } - public Channel getChannel2() - { + public Channel getChannel2() { return channels.get(1); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java index b8914123d..c8f09dece 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/EndPointImpl.java @@ -4,8 +4,7 @@ import org.asteriskjava.pbx.TechType; import org.asteriskjava.pbx.Trunk; -public class EndPointImpl implements EndPoint -{ +public class EndPointImpl implements EndPoint { private static final String DELIMITER = "/"; //$NON-NLS-1$ final private TechType _tech; @@ -23,13 +22,11 @@ public class EndPointImpl implements EndPoint * Creates a EndPoint from a fully qualified peer name of the form: SIP/NNN * LOCAL/NNN TODO: the tech encoding should probably be specific to a * particular pbx Implementation. - * + * * @param fullyQualifiedPeerName */ - public EndPointImpl(final String fullyQualifiedEndPoint) - { - if (fullyQualifiedEndPoint == null) - { + public EndPointImpl(final String fullyQualifiedEndPoint) { + if (fullyQualifiedEndPoint == null) { throw new IllegalArgumentException("The fullyQualifiedEndPoint may not be null"); //$NON-NLS-1$ } @@ -37,12 +34,9 @@ public EndPointImpl(final String fullyQualifiedEndPoint) this._tech = TechType.getTech(cleaned); this._endPointName = cleaned.substring(this._tech.name().length() + 1); - if (this._tech == TechType.DIALPLAN) - { + if (this._tech == TechType.DIALPLAN) { this._fullyQualifiedName = this._endPointName; - } - else - { + } else { this._fullyQualifiedName = this._tech.name() + EndPointImpl.DELIMITER + this._endPointName; } this._empty = false; @@ -51,8 +45,7 @@ public EndPointImpl(final String fullyQualifiedEndPoint) /** * Creates a empty end point. */ - public EndPointImpl() - { + public EndPointImpl() { this._empty = true; this._tech = TechType.UNKNOWN; this._endPointName = ""; @@ -61,7 +54,7 @@ public EndPointImpl() /** * Creates an EndPoint from from a simple endpoint name and a tech. - * + * * @param _tech * @param peerName */ @@ -80,64 +73,50 @@ public EndPointImpl() // this.tech = Tech.valueOf(tech.toUpperCase()); // this.endPointName = cleaned; // } - - public EndPointImpl(final TechType defaultTech, final String endPointName) - { - if (endPointName == null) - { + public EndPointImpl(final TechType defaultTech, final String endPointName) { + if (endPointName == null) { throw new IllegalArgumentException("The endPointName may not be null"); //$NON-NLS-1$ } final String cleaned = this.clean(endPointName); - if (cleaned.length() == 0) - { + if (cleaned.length() == 0) { throw new IllegalArgumentException("The endPointName may not be empty"); //$NON-NLS-1$ } // If tech is unknown then attempt to extract the tech from the // endPointName. - if (TechType.hasTech(cleaned)) - { + if (TechType.hasTech(cleaned)) { this._tech = TechType.getTech(cleaned); this._endPointName = cleaned.substring(this._tech.name().length() + 1); - } - else - { + } else { this._tech = defaultTech; this._endPointName = cleaned; } - if (this._tech == TechType.DIALPLAN) - { + if (this._tech == TechType.DIALPLAN) { this._fullyQualifiedName = this._endPointName; - } - else - { + } else { this._fullyQualifiedName = this._tech.name() + EndPointImpl.DELIMITER + this._endPointName; } this._empty = false; } - public EndPointImpl(TechType defaultTech, Trunk trunk, String endPointName) - { - if (endPointName == null) - { + public EndPointImpl(TechType defaultTech, Trunk trunk, String endPointName) { + if (endPointName == null) { throw new IllegalArgumentException("The endPointName may not be null"); //$NON-NLS-1$ } final String cleaned = this.clean(endPointName); - if (cleaned.length() == 0) - { + if (cleaned.length() == 0) { throw new IllegalArgumentException("The endPointName may not be empty"); //$NON-NLS-1$ } // If tech is unknown then attempt to extract the tech from the // endPointName. - if (TechType.hasTech(cleaned)) - { + if (TechType.hasTech(cleaned)) { throw new IllegalArgumentException("endPointName may not contain a Tech"); } @@ -146,8 +125,7 @@ public EndPointImpl(TechType defaultTech, Trunk trunk, String endPointName) this._endPointName = cleaned; this._trunk = trunk; - if (this._tech == TechType.DIALPLAN || this._tech == TechType.CONSOLE || this._tech == TechType.LOCAL) - { + if (this._tech == TechType.DIALPLAN || this._tech == TechType.CONSOLE || this._tech == TechType.LOCAL) { throw new IllegalArgumentException("defaultTech may not be DIALPLAN, LOCAL or CONSOLE"); } @@ -162,31 +140,26 @@ public EndPointImpl(TechType defaultTech, Trunk trunk, String endPointName) * Returns the fully qualified endPoint. */ @Override - public String getFullyQualifiedName() - { + public String getFullyQualifiedName() { return this._fullyQualifiedName; } - public Trunk getTrunk() - { + public Trunk getTrunk() { return _trunk; } @Override - public boolean isSame(final EndPoint rhs) - { + public boolean isSame(final EndPoint rhs) { return this.compareTo(rhs) == 0; } @Override - public int compareTo(EndPoint rhs) - { + public int compareTo(EndPoint rhs) { return this.getFullyQualifiedName().compareTo(rhs.getFullyQualifiedName()); } @Override - public boolean isLocal() - { + public boolean isLocal() { return this._tech == TechType.LOCAL; } @@ -194,44 +167,38 @@ public boolean isLocal() * For the purposes of asterisk IAX and SIP are both considered SIP. */ @Override - public boolean isSIP() - { + public boolean isSIP() { return this._tech == TechType.SIP || this._tech == TechType.IAX || this._tech == TechType.IAX2; } - public boolean isDAHDI() - { + public boolean isDAHDI() { return this._tech == TechType.DAHDI; } @Override - public String getSimpleName() - { + public String getSimpleName() { return this._endPointName; } @Override - public boolean isUnknown() - { + public boolean isUnknown() { return this._tech == TechType.UNKNOWN; } /** * Cleans up an endpoint name by removing all whitespace (including internal * whitespace) as well as making the string lower case. - * + * * @param _endPointName * @return */ - private String clean(final String _endPointName) - { + private String clean(final String _endPointName) { String localTo = _endPointName.trim(); // strip all white space from within the name as some source // pass in a formatted phone number (e.g. 03 8320 8100) int tmp = localTo.indexOf(" "); //$NON-NLS-1$ - while (tmp != -1) - { + while (tmp != -1) { localTo = localTo.substring(0, tmp) + localTo.substring(tmp + 1, localTo.length()); tmp = localTo.indexOf(" "); //$NON-NLS-1$ } @@ -239,20 +206,17 @@ private String clean(final String _endPointName) } @Override - public TechType getTech() - { + public TechType getTech() { return this._tech; } @Override - public String toString() - { + public String toString() { return this.getFullyQualifiedName(); } @Override - public String getSIPSimpleName() - { + public String getSIPSimpleName() { String name; if (isSIP()) @@ -262,8 +226,7 @@ public String getSIPSimpleName() return name; } - public boolean isEmpty() - { + public boolean isEmpty() { return this._empty; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java index ebf7afbbb..103ca0e61 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListener.java @@ -1,46 +1,44 @@ package org.asteriskjava.pbx.internal.core; -import java.util.Set; - import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; +import java.util.Set; + /** * Allows a object to receive Manager event notification which are pre-filtered. - * + * * @author bsutton - * */ -public interface FilteredManagerListener -{ - /** - * Provides a unique name for the listener. - * - * @return a unique name for the listener. - */ - String getName(); +public interface FilteredManagerListener { + /** + * Provides a unique name for the listener. + * + * @return a unique name for the listener. + */ + String getName(); - /** - * Called whenever the listener is first added and any time any listener is - * removed to refresh the list of required events. - * - * @return list of required events. - */ - Set> requiredEvents(); + /** + * Called whenever the listener is first added and any time any listener is + * removed to refresh the list of required events. + * + * @return list of required events. + */ + Set> requiredEvents(); - /** - * Called for each manager event that the connection receives for which the - * filterEvent returned true. - * - * @param event - */ - void onManagerEvent(T event); + /** + * Called for each manager event that the connection receives for which the + * filterEvent returned true. + * + * @param event + */ + void onManagerEvent(T event); - /** - * Set the listeners priority. Higher priority listeners have events - * dispatched to them before lower priority listeners. - * - * @return - */ - ListenerPriority getPriority(); + /** + * Set the listeners priority. Higher priority listeners have events + * dispatched to them before lower priority listeners. + * + * @return + */ + ListenerPriority getPriority(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListenerWrapper.java b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListenerWrapper.java index ae73a9f22..eba0c8178 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListenerWrapper.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/FilteredManagerListenerWrapper.java @@ -1,39 +1,34 @@ package org.asteriskjava.pbx.internal.core; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; -public class FilteredManagerListenerWrapper -{ +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +public class FilteredManagerListenerWrapper { FilteredManagerListener _listener; - Set> requiredEvents; + Set> requiredEvents; private final static AtomicInteger seed = new AtomicInteger(); Integer equalityBuster = seed.incrementAndGet(); - public FilteredManagerListenerWrapper(FilteredManagerListener listener) - { + public FilteredManagerListenerWrapper(FilteredManagerListener listener) { this._listener = listener; this.requiredEvents = listener.requiredEvents(); - if (requiredEvents.contains(BridgeEvent.class)) - { + if (requiredEvents.contains(BridgeEvent.class)) { // add LinkEvent and UnlinkEvent, as BridgeEvent only will // miss some events requiredEvents.add(LinkEvent.class); requiredEvents.add(UnlinkEvent.class); } - for (Class< ? extends ManagerEvent> event : requiredEvents) - { + for (Class event : requiredEvents) { if (!CoherentEventFactory.mapEvents.values().contains(event) - && !CoherentEventFactory.mapResponses.values().contains(event)) - { + && !CoherentEventFactory.mapResponses.values().contains(event)) { throw new RuntimeException( "The requested event type of " + event + "+isn't known by " + CoherentEventFactory.class); } @@ -41,8 +36,7 @@ public FilteredManagerListenerWrapper(FilteredManagerListener list } @Override - public String toString() - { + public String toString() { return this._listener.getName(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java index 514598c03..fb922097f 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/ListenerManager.java @@ -1,27 +1,20 @@ package org.asteriskjava.pbx.internal.core; -import java.util.Comparator; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.TreeSet; - import org.asteriskjava.lock.Lockable; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class ListenerManager extends Lockable -{ +import java.util.*; + +public class ListenerManager extends Lockable { private final TreeSet listeners = new TreeSet<>(new ListenerPriorityComparator()); Log logger = LogFactory.getLog(ListenerManager.class); - final class ListenerPriorityComparator implements Comparator - { + final class ListenerPriorityComparator implements Comparator { @Override - public int compare(FilteredManagerListenerWrapper lhs, FilteredManagerListenerWrapper rhs) - { + public int compare(FilteredManagerListenerWrapper lhs, FilteredManagerListenerWrapper rhs) { int result = lhs._listener.getPriority().compare(rhs._listener.getPriority()); @@ -32,47 +25,38 @@ public int compare(FilteredManagerListenerWrapper lhs, FilteredManagerListenerWr } } - public void clear() - { + public void clear() { listeners.clear(); } - public int size() - { + public int size() { return listeners.size(); } - public Iterator iterator() - { + public Iterator iterator() { return listeners.iterator(); } - public void addListener(FilteredManagerListener listener) - { + public void addListener(FilteredManagerListener listener) { listeners.add(new FilteredManagerListenerWrapper(listener)); } - List getCopyAsList() - { + List getCopyAsList() { List list = new LinkedList<>(); - for (FilteredManagerListenerWrapper listener : listeners) - { + for (FilteredManagerListenerWrapper listener : listeners) { list.add(listener); } return list; } - boolean removeListener(FilteredManagerListener toRemove) - { + boolean removeListener(FilteredManagerListener toRemove) { boolean removed = false; Iterator itr = listeners.iterator(); - while (itr.hasNext()) - { + while (itr.hasNext()) { FilteredManagerListenerWrapper container = itr.next(); // logger.error("Checking " + container._listener + " " + toRemove); - if (container._listener == toRemove) - { + if (container._listener == toRemove) { logger.debug("Removing listener " + toRemove); itr.remove(); removed = true; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java index 4b115a806..46a1778bd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/LiveChannelManager.java @@ -1,12 +1,5 @@ package org.asteriskjava.pbx.internal.core; -import java.io.IOException; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; - import org.asteriskjava.lock.Lockable; import org.asteriskjava.lock.LockableList; import org.asteriskjava.lock.Locker.LockCloser; @@ -16,17 +9,17 @@ import org.asteriskjava.pbx.InvalidChannelName; import org.asteriskjava.pbx.ListenerPriority; import org.asteriskjava.pbx.asterisk.wrap.actions.StatusAction; -import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.MasqueradeEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.RenameEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ResponseEvents; -import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.*; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.io.IOException; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; + /** * The LiveChannelManager keeps a list of all of the live channels present on an * asterisk system. For this to work it needs to control the stream of asterisk @@ -57,11 +50,10 @@ * a live channel during a masqurade event. A consumer holding an iChannel * handle will not even be aware (and does not need to be) that the underlying * channel has been replaced. - * + * * @author bsutton */ -public class LiveChannelManager extends Lockable implements FilteredManagerListener -{ +public class LiveChannelManager extends Lockable implements FilteredManagerListener { private static final Log logger = LogFactory.getLog(LiveChannelManager.class); /** @@ -71,8 +63,7 @@ public class LiveChannelManager extends Lockable implements FilteredManagerListe */ private final LockableList _liveChannels = new LockableList<>(new CopyOnWriteArrayList<>()); - public LiveChannelManager() - { + public LiveChannelManager() { CoherentManagerConnection.getInstance().addListener(this); } @@ -83,36 +74,27 @@ public LiveChannelManager() * AsteriskPBX which isn't finished constructing until after the Constructor * returns. */ - void performPostCreationTasks() - { + void performPostCreationTasks() { StatusAction statusAction = new StatusAction(); - try - { + try { ResponseEvents events = CoherentManagerConnection.sendEventGeneratingAction(statusAction, 1000); - for (ResponseEvent event : events.getEvents()) - { - if (event instanceof StatusEvent) - { + for (ResponseEvent event : events.getEvents()) { + if (event instanceof StatusEvent) { // do nothing. Creating the events will register the // channels, which is after all what we are trying to do. } } - } - catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) - { + } catch (IllegalArgumentException | IllegalStateException | IOException | TimeoutException e) { logger.error(e, e); } } - public ChannelProxy getChannelByEndPoint(EndPoint endPoint) - { + public ChannelProxy getChannelByEndPoint(EndPoint endPoint) { ChannelProxy connectedChannel = null; - for (final ChannelProxy channel : _liveChannels) - { - if (channel.isConnectedTo(endPoint)) - { + for (final ChannelProxy channel : _liveChannels) { + if (channel.isConnectedTo(endPoint)) { connectedChannel = channel; break; } @@ -121,10 +103,8 @@ public ChannelProxy getChannelByEndPoint(EndPoint endPoint) return connectedChannel; } - public void add(ChannelProxy proxy) - { - try (LockCloser closer = _liveChannels.withLock()) - { + public void add(ChannelProxy proxy) { + try (LockCloser closer = _liveChannels.withLock()) { ChannelProxy index = findProxy(proxy); if (index == null) this._liveChannels.add(proxy); @@ -136,24 +116,19 @@ public void add(ChannelProxy proxy) } - private void dumpProxies(ChannelProxy proxy, String cause) - { - if (logger.isDebugEnabled()) - { + private void dumpProxies(ChannelProxy proxy, String cause) { + if (logger.isDebugEnabled()) { logger.debug("Dump of LiveChannels, cause:" + cause + ": " + proxy); //$NON-NLS-2$ - for (ChannelProxy aProxy : _liveChannels) - { + for (ChannelProxy aProxy : _liveChannels) { logger.debug("ChannelProxy: " + aProxy); } } } - public void remove(ChannelProxy proxy) - { + public void remove(ChannelProxy proxy) { ChannelProxy index = findProxy(proxy); - if (index != null) - { + if (index != null) { logger.info("Removing liveChannel " + proxy); this._liveChannels.remove(index); } @@ -161,8 +136,7 @@ public void remove(ChannelProxy proxy) } - public ChannelProxy findChannel(String extendedChannelName, String uniqueID) - { + public ChannelProxy findChannel(String extendedChannelName, String uniqueID) { ChannelProxy proxy = null; logger.debug("Trying to find channel " + extendedChannelName + " " + uniqueID); @@ -174,13 +148,10 @@ public ChannelProxy findChannel(String extendedChannelName, String uniqueID) // Sometimes we can have two channels with the same name but // different - if (localUniqueId.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) - { + if (localUniqueId.compareTo(ChannelImpl.UNKNOWN_UNIQUE_ID) != 0) { - for (ChannelProxy aChannel : _liveChannels) - { - if (aChannel.sameUniqueID(localUniqueId)) - { + for (ChannelProxy aChannel : _liveChannels) { + if (aChannel.sameUniqueID(localUniqueId)) { proxy = aChannel; break; } @@ -190,24 +161,19 @@ public ChannelProxy findChannel(String extendedChannelName, String uniqueID) // If we don't have a match from the first pass and the new uniqueID // is unknown // then do a search matching by name. - if (proxy == null) - { - for (ChannelProxy aChannel : _liveChannels) - { + if (proxy == null) { + for (ChannelProxy aChannel : _liveChannels) { - if (aChannel.isSame(extendedChannelName, localUniqueId)) - { + if (aChannel.isSame(extendedChannelName, localUniqueId)) { proxy = aChannel; break; } } } - if (proxy == null) - { + if (proxy == null) { logger.debug("Failed to match channel to any of..."); - for (ChannelProxy aChannel : _liveChannels) - { + for (ChannelProxy aChannel : _liveChannels) { logger.debug(aChannel); } @@ -216,12 +182,9 @@ public ChannelProxy findChannel(String extendedChannelName, String uniqueID) return proxy; } - private ChannelProxy findProxy(Channel original) - { - for (ChannelProxy aChannel : _liveChannels) - { - if (aChannel.isSame(original)) - { + private ChannelProxy findProxy(Channel original) { + for (ChannelProxy aChannel : _liveChannels) { + if (aChannel.isSame(original)) { return aChannel; } } @@ -229,9 +192,8 @@ private ChannelProxy findProxy(Channel original) } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); required.add(MasqueradeEvent.class); required.add(RenameEvent.class); @@ -244,12 +206,9 @@ private ChannelProxy findProxy(Channel original) return required; } - ChannelProxy findProxyById(String id) - { - for (ChannelProxy aChannel : _liveChannels) - { - if (("" + aChannel.getIdentity()).equals(id)) - { + ChannelProxy findProxyById(String id) { + for (ChannelProxy aChannel : _liveChannels) { + if (("" + aChannel.getIdentity()).equals(id)) { return aChannel; } } @@ -257,19 +216,15 @@ ChannelProxy findProxyById(String id) } @Override - public void onManagerEvent(ManagerEvent event) - { - if (event instanceof MasqueradeEvent) - { + public void onManagerEvent(ManagerEvent event) { + if (event instanceof MasqueradeEvent) { MasqueradeEvent masq = (MasqueradeEvent) event; ChannelProxy originalIndex = findProxy(masq.getOriginal()); ChannelProxy cloneIndex = findProxy(masq.getClone()); - if (originalIndex != null && cloneIndex != null) - { + if (originalIndex != null && cloneIndex != null) { ChannelProxy originalProxy = (ChannelProxy) masq.getOriginal(); ChannelProxy cloneProxy = (ChannelProxy) masq.getClone(); - try - { + try { // After the masquerade the two underlying channels will // have been switched // between the two proxies. @@ -297,47 +252,35 @@ public void onManagerEvent(ManagerEvent event) originalProxy.masquerade(cloneProxy); dumpProxies(cloneProxy, "Masquerade"); sanityCheck(); - } - catch (InvalidChannelName e) - { + } catch (InvalidChannelName e) { logger.error(e, e); } - } - else + } else logger.error("Either the clone or original channelProxy was missing during a masquerade: cloneIndex=" + cloneIndex + " originalIndex=" + originalIndex); } - if (event instanceof RenameEvent) - { + if (event instanceof RenameEvent) { RenameEvent rename = (RenameEvent) event; ChannelProxy oldChannel = findProxy(rename.getChannel()); - if (oldChannel != null) - { - try - { + if (oldChannel != null) { + try { oldChannel.rename(rename.getNewName(), rename.getUniqueId()); dumpProxies(oldChannel, "RenameEvent"); sanityCheck(); - } - catch (InvalidChannelName e) - { + } catch (InvalidChannelName e) { logger.error(e, e); } - } - else - { + } else { String message = "Unable to rename channel -> Failed to find channel " + rename.getChannel(); logger.warn(message); dumpProxies(null, message); } - } - else if (event instanceof HangupEvent) - { + } else if (event instanceof HangupEvent) { // We need to process every hangup event that goes through the // system // as the LiveChannelManager has a Channel added for every channel @@ -349,12 +292,10 @@ else if (event instanceof HangupEvent) // Yes I've seen a hangup where the channel was null, who knows // why? - if (hangup.getChannel() != null) - { + if (hangup.getChannel() != null) { ChannelProxy proxy = findProxy(hangup.getChannel()); - if (proxy != null) - { + if (proxy != null) { logger.debug("Removing proxy " + proxy); this._liveChannels.remove(proxy); @@ -363,44 +304,34 @@ else if (event instanceof HangupEvent) dumpProxies(proxy, "HangupEvent"); } - } - else - { + } else { logger.error("Didn't remove hungup channel"); } } } @Override - public String getName() - { + public String getName() { return "LiveChannelManager"; } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.CRITICAL; } - public void sanityCheck() - { + public void sanityCheck() { - if (logger.isDebugEnabled()) - { + if (logger.isDebugEnabled()) { logger.error("Performing Sanity Check"); Set channels = new HashSet<>(); - for (ChannelProxy channel : _liveChannels) - { - if (!channels.add(channel.getChannel().getExtendedChannelName())) - { + for (ChannelProxy channel : _liveChannels) { + if (!channels.add(channel.getChannel().getExtendedChannelName())) { logger.error( "Multiple channels by the name " + channel.getChannel().getExtendedChannelName() + " exist"); - for (ChannelProxy channel2 : _liveChannels) - { + for (ChannelProxy channel2 : _liveChannels) { if (channel2.getChannel().getExtendedChannelName() - .equals(channel.getChannel().getExtendedChannelName())) - { + .equals(channel.getChannel().getExtendedChannelName())) { logger.error(channel2); } } @@ -412,8 +343,7 @@ public void sanityCheck() } } - public List getChannelList() - { + public List getChannelList() { List channels = new LinkedList<>(); channels.addAll(_liveChannels); return channels; diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java index 5fff24573..f06e87020 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/Peer.java @@ -1,7 +1,5 @@ package org.asteriskjava.pbx.internal.core; -import java.util.LinkedList; - import org.asteriskjava.lock.LockableList; import org.asteriskjava.lock.Locker.LockCloser; import org.asteriskjava.pbx.Channel; @@ -13,16 +11,17 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.LinkedList; + /* * this class tracks the status of a Peer on asterisk. T - * - * Peers are created by the PeerMonitor which also sends asterisk events to + * + * Peers are created by the PeerMonitor which also sends asterisk events to * the peer. - * + * */ -public class Peer implements CallEndedListener -{ +public class Peer implements CallEndedListener { private static final Log logger = LogFactory.getLog(Peer.class); private final EndPoint peerEndPoint; @@ -37,33 +36,26 @@ public class Peer implements CallEndedListener private PeerState _state = PeerState.NOTSET; private boolean dnd = false; - public Peer(final EndPoint endPoint) - { + public Peer(final EndPoint endPoint) { this.peerEndPoint = endPoint; } - public boolean isSame(final Peer rhs) - { + public boolean isSame(final Peer rhs) { return this.peerEndPoint.isSame(rhs.getEndPoint()); } - private CallTracker registerChannel(final Channel newChannel) - { + private CallTracker registerChannel(final Channel newChannel) { CallTracker associatedCall = null; boolean found = false; - try (LockCloser closer = this.callList.withLock()) - { - for (final CallTracker call : this.callList) - { - if (call.findChannel(newChannel) != -1) - { + try (LockCloser closer = this.callList.withLock()) { + for (final CallTracker call : this.callList) { + if (call.findChannel(newChannel) != -1) { found = true; associatedCall = call; break; } } - if (!found) - { + if (!found) { if (logger.isDebugEnabled()) logger.debug("Peer adding Call: " + this.toString() + " " + newChannel.getExtendedChannelName()); //$NON-NLS-1$ //$NON-NLS-2$ associatedCall = createCallTracker(newChannel); @@ -73,19 +65,16 @@ private CallTracker registerChannel(final Channel newChannel) return associatedCall; } - private CallTracker createCallTracker(final Channel newChannel) - { + private CallTracker createCallTracker(final Channel newChannel) { CallTracker newCall; - try (LockCloser closer = this.callList.withLock()) - { + try (LockCloser closer = this.callList.withLock()) { newCall = new CallTracker(this, newChannel); this.callList.add(newCall); } return newCall; } - public boolean getDND() - { + public boolean getDND() { return this.dnd; } @@ -103,19 +92,17 @@ public boolean getDND() // return channelName; // } - public PeerState getState() - { + public PeerState getState() { return this._state; } /** * Determines if the given channel is connected to this peer. - * + * * @param channel * @return */ - private boolean isConnectedToSelf(final Channel channel) - { + private boolean isConnectedToSelf(final Channel channel) { return this.getEndPoint().isSame(channel.getEndPoint()); } @@ -124,25 +111,21 @@ private boolean isConnectedToSelf(final Channel channel) * During a masquerade we will have two channels for the one peer, the * original and the clone. As the clone is taking over from the original * peer we now need to use that as true indicator of state. - * + * * @param b * @throws Exception */ - public void handleEvent(final MasqueradeEvent b) - { - if (this.isConnectedToSelf(b.getClone())) - { + public void handleEvent(final MasqueradeEvent b) { + if (this.isConnectedToSelf(b.getClone())) { // At this point we will actually have two CallTrackers // which we now need to merge into a single CallTracker. CallTracker original = findCall(b.getOriginal()); CallTracker clone = findCall(b.getClone()); - if (original != null && clone != null) - { + if (original != null && clone != null) { clone.mergeCalls(original); clone.setState(b.getCloneState()); this.evaluateState(); - } - else + } else logger.warn("When processing masquradeEvent we could not find the expected calls. event=" //$NON-NLS-1$ + b.toString() + " original=" + original + " clone=" + clone); //$NON-NLS-1$ //$NON-NLS-2$ } @@ -151,71 +134,57 @@ public void handleEvent(final MasqueradeEvent b) /** * When a new channel comes up associated it with the peer. Be warned a peer * can have multiple calls associated with it. - * + * * @param b * @throws Exception */ - public void handleEvent(final NewChannelEvent b) - { + public void handleEvent(final NewChannelEvent b) { // Very occasionally we get a null channel which we can't do anything // with so just throw the event away. // If we get a Console/dsp channel name it means that someone has // dialled from the asterisk // console. We just ignore these. - if ((b.getChannel() == null) || (b.getChannel().isConsole())) - { + if ((b.getChannel() == null) || (b.getChannel().isConsole())) { return; } - if (this.isConnectedToSelf(b.getChannel())) - { + if (this.isConnectedToSelf(b.getChannel())) { CallTracker call = this.registerChannel(b.getChannel()); - if (call != null) - { + if (call != null) { call.setState(b.getChannelState()); this.evaluateState(); } } } - public void handleEvent(final NewStateEvent b) - { - if (this.isConnectedToSelf(b.getChannel())) - { + public void handleEvent(final NewStateEvent b) { + if (this.isConnectedToSelf(b.getChannel())) { CallTracker call = this.registerChannel(b.getChannel()); - if (call != null) - { + if (call != null) { call.setState(b.getChannelState()); this.evaluateState(); } } } - public void handleEvent(final StatusEvent b) - { + public void handleEvent(final StatusEvent b) { final Channel channel = b.getChannel(); - if (this.isConnectedToSelf(channel)) - { + if (this.isConnectedToSelf(channel)) { ((ChannelProxy) channel).getRealChannel().markChannel(); CallTracker call = findCall(channel); - if (call != null) - { + if (call != null) { call.setState(b.getState()); this.evaluateState(); } } } - private CallTracker findCall(Channel channel) - { + private CallTracker findCall(Channel channel) { CallTracker result = null; - try (LockCloser closer = this.callList.withLock()) - { - for (CallTracker call : this.callList) - { - if (call.findChannel(channel) != -1) - { + try (LockCloser closer = this.callList.withLock()) { + for (CallTracker call : this.callList) { + if (call.findChannel(channel) != -1) { result = call; break; } @@ -225,30 +194,23 @@ private CallTracker findCall(Channel channel) return result; } - public void setDND(final boolean on) - { + public void setDND(final boolean on) { this.dnd = on; } - public void startSweep() - { + public void startSweep() { Peer.logger.debug("Starting sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ - try (LockCloser closer = this.callList.withLock()) - { - for (final CallTracker call : this.callList) - { + try (LockCloser closer = this.callList.withLock()) { + for (final CallTracker call : this.callList) { call.startSweep(); } } } - public void endSweep() - { + public void endSweep() { Peer.logger.debug("Ending sweep for " + this.peerEndPoint.getFullyQualifiedName());//$NON-NLS-1$ - try (LockCloser closer = this.callList.withLock()) - { - for (final CallTracker call : this.callList) - { + try (LockCloser closer = this.callList.withLock()) { + for (final CallTracker call : this.callList) { call.endSweep(); } } @@ -259,14 +221,11 @@ public void endSweep() * Called each time the state of a call changes to determine the Peers * overall state. */ - private void evaluateState() - { - try (LockCloser closer = this.callList.withLock()) - { + private void evaluateState() { + try (LockCloser closer = this.callList.withLock()) { // Get the highest prioirty state from the set of calls. PeerState newState = PeerState.NOTSET; - for (CallTracker call : this.callList) - { + for (CallTracker call : this.callList) { if (call.getState().getPriority() > newState.getPriority()) newState = call.getState(); } @@ -275,39 +234,30 @@ private void evaluateState() } } - public EndPoint getEndPoint() - { + public EndPoint getEndPoint() { return this.peerEndPoint; } @Override - public String toString() - { + public String toString() { return this.getEndPoint().toString(); } - private void dumpCallList() - { - if (logger.isDebugEnabled()) - { + private void dumpCallList() { + if (logger.isDebugEnabled()) { Peer.logger.debug("Peer: dump CallList:" + this); //$NON-NLS-1$ - for (final CallTracker call : this.callList) - { + for (final CallTracker call : this.callList) { call.dumpChannelList(); } } } @Override - public void callEnded(CallTracker call) - { + public void callEnded(CallTracker call) { boolean found = false; - try (LockCloser closer = this.callList.withLock()) - { - for (final CallTracker aCall : this.callList) - { - if (call == aCall) - { + try (LockCloser closer = this.callList.withLock()) { + for (final CallTracker aCall : this.callList) { + if (call == aCall) { found = true; if (logger.isDebugEnabled()) logger.debug("peer Removing call " + call); //$NON-NLS-1$ @@ -317,8 +267,7 @@ public void callEnded(CallTracker call) break; } } - if (!found) - { + if (!found) { logger.error("Error call not found removing call from peer: call=" + call + " peer=" + this); //$NON-NLS-1$ //$NON-NLS-2$ this.dumpCallList(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java index 1377eedf1..05d9c1a25 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerMonitor.java @@ -1,38 +1,24 @@ package org.asteriskjava.pbx.internal.core; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - import org.asteriskjava.lock.LockableList; import org.asteriskjava.lock.Locker.LockCloser; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.NewExtensionListener; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.asterisk.wrap.actions.SipPeersAction; import org.asteriskjava.pbx.asterisk.wrap.actions.StatusAction; -import org.asteriskjava.pbx.asterisk.wrap.events.DndStateEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.MasqueradeEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.NewStateEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.PeerEntryEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.PeerStatusEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.PeerlistCompleteEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.StatusCompleteEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.StatusEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.*; import org.asteriskjava.pbx.internal.managerAPI.EventListenerBaseClass; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + /* * this class tracks the status of all peers on asterisk. */ -public class PeerMonitor extends EventListenerBaseClass implements Runnable -{ +public class PeerMonitor extends EventListenerBaseClass implements Runnable { private static final Log logger = LogFactory.getLog(PeerMonitor.class); @@ -48,51 +34,38 @@ public class PeerMonitor extends EventListenerBaseClass implements Runnable /** * needs to notify PhoneBookDisplayController.getInstance().addExtensions(); - * + * * @param _listener */ - public synchronized static void init(final NewExtensionListener _listener) - { + public synchronized static void init(final NewExtensionListener _listener) { PeerMonitor.listener = _listener; - if (PeerMonitor.self == null) - { + if (PeerMonitor.self == null) { PeerMonitor.self = new PeerMonitor(); - } - else if (_listener != null) - { + } else if (_listener != null) { logger.error("Call to PeerMonitor.init, but it's already initialized. Listener will not be set"); } } - public static synchronized PeerMonitor getInstance() - { - if (PeerMonitor.self == null) - { + public static synchronized PeerMonitor getInstance() { + if (PeerMonitor.self == null) { throw new IllegalStateException("You must call PeerMonitor.init()"); //$NON-NLS-1$ } return PeerMonitor.self; } - private PeerMonitor() - { + private PeerMonitor() { super("PeerMonitor", PBXFactory.getActivePBX()); //$NON-NLS-1$ this.peerList = new LockableList<>(new LinkedList<>()); this.startListener(); this.addSipsToMonitor(); - try - { - if (PeerMonitor.listener != null) - { + try { + if (PeerMonitor.listener != null) { PeerMonitor.listener.newExtension(); - } - else - { + } else { logger.warn("Peer monitor listener is null"); } - } - catch (final Exception e) - { + } catch (final Exception e) { PeerMonitor.logger.error(e, e); } @@ -103,8 +76,7 @@ private PeerMonitor() } - public void addSipsToMonitor() - { + public void addSipsToMonitor() { /* * request asterisk to send a list of sip peers. The monitor will * dynamically add the peers to its list @@ -113,37 +85,29 @@ public void addSipsToMonitor() final StatusAction sa = new StatusAction(); final SipPeersAction t = new SipPeersAction(); - try - { + try { AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); pbx.sendAction(t, 5000); pbx.sendAction(sa, 5000); - } - catch (final Exception e) - { + } catch (final Exception e) { PeerMonitor.logger.error(e, e); } } - public Peer registerPeer(final Channel newChannel) - { + public Peer registerPeer(final Channel newChannel) { final Peer peer = this.registerPeer(newChannel.getEndPoint()); return peer; } - public Peer registerPeer(final EndPoint endPoint) - { - if (endPoint.isLocal()) - { + public Peer registerPeer(final EndPoint endPoint) { + if (endPoint.isLocal()) { return null; } - try (LockCloser closer = peerList.withLock()) - { + try (LockCloser closer = peerList.withLock()) { Peer peer = this.findPeer(endPoint); - if (peer == null) - { + if (peer == null) { peer = new Peer(endPoint); this.peerList.add(peer); } @@ -152,16 +116,12 @@ public Peer registerPeer(final EndPoint endPoint) } - public Peer findPeer(final EndPoint peerEndPoint) - { + public Peer findPeer(final EndPoint peerEndPoint) { Peer found = null; - try (LockCloser closer = peerList.withLock()) - { - for (final Peer peer : this.peerList) - { - if (peer.getEndPoint().isSame(peerEndPoint)) - { + try (LockCloser closer = peerList.withLock()) { + for (final Peer peer : this.peerList) { + if (peer.getEndPoint().isSame(peerEndPoint)) { found = peer; break; } @@ -170,10 +130,8 @@ public Peer findPeer(final EndPoint peerEndPoint) return found; } - public Iterator getIterator() - { - try (LockCloser closer = peerList.withLock()) - { + public Iterator getIterator() { + try (LockCloser closer = peerList.withLock()) { final List clone = new LinkedList(this.peerList); return clone.iterator(); } @@ -181,9 +139,8 @@ public Iterator getIterator() } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); required.add(NewChannelEvent.class); required.add(PeerStatusEvent.class); @@ -198,107 +155,76 @@ public Iterator getIterator() } @Override - public void onManagerEvent(final ManagerEvent event) - { + public void onManagerEvent(final ManagerEvent event) { /* * This function is called from the base class. Here we process events * we are interested in. */ - if (event instanceof PeerStatusEvent) - { + if (event instanceof PeerStatusEvent) { this.handleEvent((PeerStatusEvent) event); - } - else if (event instanceof PeerlistCompleteEvent) - { + } else if (event instanceof PeerlistCompleteEvent) { this.handleEvent((PeerlistCompleteEvent) event); - } - else if (event instanceof PeerEntryEvent) - { + } else if (event instanceof PeerEntryEvent) { this.handleEvent((PeerEntryEvent) event); - } - else if (event instanceof NewChannelEvent) - { + } else if (event instanceof NewChannelEvent) { this.handleEvent((NewChannelEvent) event); - } - else if (event instanceof MasqueradeEvent) - { + } else if (event instanceof MasqueradeEvent) { this.handleEvent((MasqueradeEvent) event); - } - else if (event instanceof StatusEvent) - { + } else if (event instanceof StatusEvent) { this.handleEvent((StatusEvent) event); - } - else if (event instanceof StatusCompleteEvent) - { + } else if (event instanceof StatusCompleteEvent) { this.handleEvent((StatusCompleteEvent) event); - } - else if (event instanceof NewStateEvent) - { + } else if (event instanceof NewStateEvent) { this.handleEvent((NewStateEvent) event); } } - private void handleEvent(NewStateEvent event) - { - try (LockCloser closer = peerList.withLock()) - { - for (Peer peer : this.peerList) - { + private void handleEvent(NewStateEvent event) { + try (LockCloser closer = peerList.withLock()) { + for (Peer peer : this.peerList) { peer.handleEvent(event); } } } - private void handleEvent(final NewChannelEvent event) - { - try (LockCloser closer = peerList.withLock()) - { - for (Peer peer : this.peerList) - { + private void handleEvent(final NewChannelEvent event) { + try (LockCloser closer = peerList.withLock()) { + for (Peer peer : this.peerList) { peer.handleEvent(event); } } } - private void handleEvent(final MasqueradeEvent event) - { - try (LockCloser closer = peerList.withLock()) - { - for (Peer peer : this.peerList) - { + private void handleEvent(final MasqueradeEvent event) { + try (LockCloser closer = peerList.withLock()) { + for (Peer peer : this.peerList) { peer.handleEvent(event); } } } - private void handleEvent(final StatusEvent event) - { - try (LockCloser closer = peerList.withLock()) - { - for (Peer peer : this.peerList) - { + private void handleEvent(final StatusEvent event) { + try (LockCloser closer = peerList.withLock()) { + for (Peer peer : this.peerList) { peer.handleEvent(event); } } } - private void handleEvent(final PeerEntryEvent event) - { + private void handleEvent(final PeerEntryEvent event) { final EndPoint endPoint = event.getPeer(); this.registerPeer(endPoint); } - private void handleEvent(final PeerlistCompleteEvent b) - { + private void handleEvent(final PeerlistCompleteEvent b) { this.initSip = true; } /** * @param event */ - private void handleEvent(final PeerStatusEvent event) - { + private void handleEvent(final PeerStatusEvent event) { this.registerPeer(event.getPeer()); } @@ -306,28 +232,23 @@ private void handleEvent(final PeerStatusEvent event) * We receive the StatusComplete event once the Mark and Sweep channel * operation has completed. We now call endSweep which will remove any * channels that were not marked during the operation. - * + * * @param event */ - private void handleEvent(final StatusCompleteEvent event) - { - try (LockCloser closer = peerList.withLock()) - { - for (final Peer peer : this.peerList) - { + private void handleEvent(final StatusCompleteEvent event) { + try (LockCloser closer = peerList.withLock()) { + for (final Peer peer : this.peerList) { peer.endSweep(); } } PeerMonitor.logger.debug("Channel Mark and Sweep complete"); //$NON-NLS-1$ } - boolean isInitialized() - { + boolean isInitialized() { return this.initSip; } - public void stop() - { + public void stop() { this.close(); } @@ -342,17 +263,12 @@ public void stop() * missed the hangup event. */ @Override - public void run() - { - while (true) - { - try - { + public void run() { + while (true) { + try { Thread.sleep(120000); PeerMonitor.getInstance().startSweep(); - } - catch (final InterruptedException e) - { + } catch (final InterruptedException e) { PeerMonitor.logger.error(e, e); } @@ -368,15 +284,12 @@ public void run() * the end of the process any channels which haven't been marked are then * discarded. */ - public void startSweep() - { + public void startSweep() { PeerMonitor.logger.debug("Starting channel mark and sweep"); //$NON-NLS-1$ // Mark every channel as 'clearing' - try (LockCloser closer = peerList.withLock()) - { - for (final Peer peer : this.peerList) - { + try (LockCloser closer = peerList.withLock()) { + for (final Peer peer : this.peerList) { peer.startSweep(); } } @@ -385,21 +298,17 @@ public void startSweep() * Request Asterisk to send us a status update for every channel. */ final StatusAction sa = new StatusAction(); - try - { + try { AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); pbx.sendAction(sa, 5000); - } - catch (final Exception e) - { + } catch (final Exception e) { PeerMonitor.logger.error(e, e); } } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.HIGH; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java b/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java index 06a3ab2e9..b7405a0df 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/PeerState.java @@ -4,8 +4,7 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public enum PeerState -{ +public enum PeerState { DOWN(1, "Down", "OnHook", false), //$NON-NLS-1$ //$NON-NLS-2$ UP(2, "Up", "OnPhone", true), //$NON-NLS-1$ //$NON-NLS-2$ UNKNOWN(0, "Unknown", "Unknown", false), //$NON-NLS-1$ //$NON-NLS-2$ @@ -40,15 +39,12 @@ public enum PeerState */ private int _priority; - public static PeerState valueByName(final String value) - { + public static PeerState valueByName(final String value) { PeerState status = NOTSET; - for (PeerState aState : PeerState.values()) - { + for (PeerState aState : PeerState.values()) { - if (aState.getAsteriskStateName().compareToIgnoreCase(value) == 0) - { + if (aState.getAsteriskStateName().compareToIgnoreCase(value) == 0) { status = aState; break; } @@ -56,20 +52,16 @@ public static PeerState valueByName(final String value) return status; } - private String getAsteriskStateName() - { + private String getAsteriskStateName() { return this._asteriskStateName; } - public static PeerState valueByChannelState(final ChannelState state) - { + public static PeerState valueByChannelState(final ChannelState state) { PeerState status = NOTSET; - for (PeerState aState : PeerState.values()) - { + for (PeerState aState : PeerState.values()) { - if (aState.getAsteriskStateName().compareToIgnoreCase(state.name()) == 0) - { + if (aState.getAsteriskStateName().compareToIgnoreCase(state.name()) == 0) { status = aState; break; } @@ -80,32 +72,27 @@ public static PeerState valueByChannelState(final ChannelState state) return status; } - PeerState(int priority, final String asteriskStateName, final String label, boolean visible) - { + PeerState(int priority, final String asteriskStateName, final String label, boolean visible) { this._asteriskStateName = asteriskStateName; this.label = label; this._visible = visible; this._priority = priority; } - public String getLabel() - { + public String getLabel() { return this.label; } @Override - public String toString() - { + public String toString() { return this.label; } - public boolean isVisible() - { + public boolean isVisible() { return this._visible; } - public int getPriority() - { + public int getPriority() { return this._priority; } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java b/src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java index 1d7e5ba5f..b2d62d59c 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java +++ b/src/main/java/org/asteriskjava/pbx/internal/eventQueue/EventLifeMonitor.java @@ -4,8 +4,7 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class EventLifeMonitor -{ +public class EventLifeMonitor { private static final Log logger = LogFactory.getLog(EventLifeMonitor.class); /* @@ -17,23 +16,19 @@ public class EventLifeMonitor private final LogTime age; - public EventLifeMonitor(final T event) - { + public EventLifeMonitor(final T event) { this.theEvent = event; this.age = new LogTime(); } - public void assessAge() - { - if (this.age.timeTaken() > 2000) - { + public void assessAge() { + if (this.age.timeTaken() > 2000) { EventLifeMonitor.logger.warn("event age : " + this.age.timeTaken()); //$NON-NLS-1$ } } - public T getEvent() - { + public T getEvent() { return this.theEvent; } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java index a8c47406e..80435bccd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Connector.java @@ -1,10 +1,5 @@ package org.asteriskjava.pbx.internal.managerAPI; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.UnknownHostException; - import org.asteriskjava.manager.AuthenticationFailedException; import org.asteriskjava.manager.ManagerConnection; import org.asteriskjava.manager.ManagerConnectionFactory; @@ -13,18 +8,22 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; + /* * this class is a very thin wrapper around the manager connection class */ -public class Connector -{ +public class Connector { private ManagerConnection managerConnection; private static final Log logger = LogFactory.getLog(Connector.class); /** * Establishes a Asterisk ManagerConnection as well as performing the * 'login' required by Asterisk. - * + * * @param asteriskSettings * @return * @throws IOException @@ -33,8 +32,7 @@ public class Connector * @throws IllegalStateException */ public ManagerConnection connect(final AsteriskSettings asteriskSettings) - throws IOException, AuthenticationFailedException, TimeoutException, IllegalStateException - { + throws IOException, AuthenticationFailedException, TimeoutException, IllegalStateException { checkIfAsteriskRunning(asteriskSettings); this.makeConnection(asteriskSettings); return this.managerConnection; @@ -48,15 +46,13 @@ public ManagerConnection connect(final AsteriskSettings asteriskSettings) * they can go to the asterisk panel. Fix the problem and then we can retry * with the new connection settings within a couple of seconds rather than * waiting a minute for a timeout. - * + * * @param asteriskSettings * @throws UnknownHostException * @throws IOException */ - private void checkIfAsteriskRunning(AsteriskSettings asteriskSettings) throws UnknownHostException, IOException - { - try (Socket socket = new Socket()) - { + private void checkIfAsteriskRunning(AsteriskSettings asteriskSettings) throws UnknownHostException, IOException { + try (Socket socket = new Socket()) { socket.setSoTimeout(2000); InetSocketAddress asteriskHost = new InetSocketAddress(asteriskSettings.getAsteriskIP(), @@ -75,17 +71,13 @@ private void checkIfAsteriskRunning(AsteriskSettings asteriskSettings) throws Un * @throws IllegalStateException */ private void makeConnection(final AsteriskSettings asteriskSettings) - throws IOException, AuthenticationFailedException, TimeoutException, IllegalStateException - { + throws IOException, AuthenticationFailedException, TimeoutException, IllegalStateException { ManagerConnectionFactory factory = null; - if (asteriskSettings.getManagerPortNo() == -1) - { + if (asteriskSettings.getManagerPortNo() == -1) { Connector.logger.debug("Using default port 5038."); //$NON-NLS-1$ factory = new ManagerConnectionFactory(asteriskSettings.getAsteriskIP(), asteriskSettings.getManagerUsername(), asteriskSettings.getManagerPassword()); - } - else - { + } else { factory = new ManagerConnectionFactory(asteriskSettings.getAsteriskIP(), asteriskSettings.getManagerPortNo(), asteriskSettings.getManagerUsername(), asteriskSettings.getManagerPassword()); diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java index fb1e903ac..bf0f98162 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/Dial.java @@ -1,38 +1,25 @@ package org.asteriskjava.pbx.internal.managerAPI; -import java.util.HashSet; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.NewChannelListener; -import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.agi.AgiChannelActivityDial; -import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.*; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class Dial extends EventListenerBaseClass -{ +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class Dial extends EventListenerBaseClass { private static final Log logger = LogFactory.getLog(Dial.class); private final OriginateResult result[] = new OriginateResult[2]; private CountDownLatch _latch; - public Dial(final String descriptiveName) - { + public Dial(final String descriptiveName) { super(descriptiveName, PBXFactory.getActivePBX()); } @@ -41,26 +28,24 @@ public Dial(final String descriptiveName) * dial is done in two parts as we need to set the auto answer header * differently for each phone. For the localHandset we set auto answer on, * whilst for the remote targetEndPoint we MUST not auto answer the phone. - * - * @param localHandset the users handset we are going to dial from (e.g. - * receptionist phone). - * @param targetEndPoint - the remote handset we are going to connect the - * localHandset to. - * @param dialContext - context we are going to dial from. + * + * @param localHandset the users handset we are going to dial from (e.g. + * receptionist phone). + * @param targetEndPoint - the remote handset we are going to connect the + * localHandset to. + * @param dialContext - context we are going to dial from. * @param hideCallerId * @param channelVarsToSet - * @param callerId - the callerID to display on the targetEndPoint. + * @param callerId - the callerID to display on the targetEndPoint. * @return * @throws PBXException */ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint localHandset, - final EndPoint targetEndPoint, final String dialContext, final CallerID callerID, final boolean hideCallerId, - Map channelVarsToSet, String dialOptions) throws PBXException - { + final EndPoint targetEndPoint, final String dialContext, final CallerID callerID, final boolean hideCallerId, + Map channelVarsToSet, String dialOptions) throws PBXException { final PBX pbx = PBXFactory.getActivePBX(); - try (final OriginateToExtension originate = new OriginateToExtension(listener)) - { + try (final OriginateToExtension originate = new OriginateToExtension(listener)) { this.startListener(); @@ -71,26 +56,18 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint ((AsteriskPBX) pbx).getManagementContext(), callerID, null, hideCallerId, channelVarsToSet); this.result[0] = trcResult; - if (trcResult.isSuccess()) - { - - try - { - if (targetEndPoint instanceof HoldAtAgi) - { - if (trcResult.getChannel().waitForChannelToReachAgi(30, TimeUnit.SECONDS)) - { + if (trcResult.isSuccess()) { + + try { + if (targetEndPoint instanceof HoldAtAgi) { + if (trcResult.getChannel().waitForChannelToReachAgi(30, TimeUnit.SECONDS)) { // call is now in agi System.out.println("Call is in agi"); - } - else - { + } else { // call never reached agi System.out.println("Call never reached agi"); } - } - else - { + } else { // The call is now up, so connect it to // the @@ -100,31 +77,25 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint trcResult.getChannel().setCurrentActivityAction( new AgiChannelActivityDial(targetEndPoint.getFullyQualifiedName(), dialOptions)); - if (!this._latch.await(30, TimeUnit.SECONDS)) - { + if (!this._latch.await(30, TimeUnit.SECONDS)) { logger.warn("Timeout waiting for channel. " + trcResult.getChannel()); } } - } - catch (final InterruptedException e) - { + } catch (final InterruptedException e) { // noop } } return this.result; - } - finally - { + } finally { this.close(); } } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); required.add(BridgeEvent.class); // bridge event is a subclass of linkevent, so we need link & unlink in @@ -137,15 +108,12 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint } @Override - public void onManagerEvent(final ManagerEvent event) - { - if (event instanceof BridgeEvent) - { + public void onManagerEvent(final ManagerEvent event) { + if (event instanceof BridgeEvent) { final BridgeEvent link = (BridgeEvent) event; if ((link.getChannel1() != null) && (this.result[0] != null) - && link.getChannel1().isSame(this.result[0].getChannel())) - { + && link.getChannel1().isSame(this.result[0].getChannel())) { Dial.logger.debug("Dial out bridged on " + link.getChannel1() + " to " + link.getChannel2()); //$NON-NLS-1$ //$NON-NLS-2$ this.result[1] = new OriginateResult(); @@ -153,22 +121,17 @@ public void onManagerEvent(final ManagerEvent event) this.result[1].setChannelData(link.getChannel2()); this._latch.countDown(); } - } - else if (event instanceof HangupEvent) - { + } else if (event instanceof HangupEvent) { final HangupEvent hangup = (HangupEvent) event; final Channel hangupChannel = hangup.getChannel(); - if (Dial.logger.isDebugEnabled()) - { + if (Dial.logger.isDebugEnabled()) { Dial.logger.debug("hangup :" + hangupChannel); //$NON-NLS-1$ Dial.logger.debug("channel 0:" + this.result[0]); //$NON-NLS-1$ Dial.logger.debug("channel 1:" + this.result[1]); //$NON-NLS-1$ } - if ((this.result[0] != null) && this.result[0].isSuccess() && hangupChannel.isSame(this.result[0].getChannel())) - { - if (this._latch != null) - { + if ((this.result[0] != null) && this.result[0].isSuccess() && hangupChannel.isSame(this.result[0].getChannel())) { + if (this._latch != null) { this._latch.countDown(); } } @@ -176,8 +139,7 @@ else if (event instanceof HangupEvent) } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java index b83e73177..51bf9a03e 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/DialToAgi.java @@ -1,26 +1,17 @@ package org.asteriskjava.pbx.internal.managerAPI; -import java.util.HashSet; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import org.asteriskjava.pbx.AgiChannelActivityAction; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.NewChannelListener; -import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class DialToAgi extends EventListenerBaseClass -{ +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class DialToAgi extends EventListenerBaseClass { private static final Log logger = LogFactory.getLog(DialToAgi.class); private final OriginateResult result[] = new OriginateResult[2]; @@ -29,8 +20,7 @@ public class DialToAgi extends EventListenerBaseClass private OriginateToExtension originator; - public DialToAgi(final String descriptiveName) - { + public DialToAgi(final String descriptiveName) { super(descriptiveName, PBXFactory.getActivePBX()); } @@ -39,26 +29,24 @@ public DialToAgi(final String descriptiveName) * dial is done in two parts as we need to set the auto answer header * differently for each phone. For the localHandset we set auto answer on, * whilst for the remote targetEndPoint we MUST not auto answer the phone. - * - * @param localHandset the users handset we are going to dial from (e.g. - * receptionist phone). - * @param targetEndPoint - the remote handset we are going to connect the - * localHandset to. - * @param dialContext - context we are going to dial from. + * + * @param localHandset the users handset we are going to dial from (e.g. + * receptionist phone). + * @param targetEndPoint - the remote handset we are going to connect the + * localHandset to. + * @param dialContext - context we are going to dial from. * @param hideCallerId * @param channelVarsToSet - * @param callerId - the callerID to display on the targetEndPoint. + * @param callerId - the callerID to display on the targetEndPoint. * @return * @throws PBXException */ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint localHandset, - final AgiChannelActivityAction action, final CallerID callerID, Integer timeout, final boolean hideCallerId, - Map channelVarsToSet) throws PBXException, InterruptedException - { + final AgiChannelActivityAction action, final CallerID callerID, Integer timeout, final boolean hideCallerId, + Map channelVarsToSet) throws PBXException, InterruptedException { final PBX pbx = PBXFactory.getActivePBX(); - try (final OriginateToExtension originate = new OriginateToExtension(listener)) - { + try (final OriginateToExtension originate = new OriginateToExtension(listener)) { this.startListener(); originator = originate; @@ -69,83 +57,62 @@ public OriginateResult[] dial(final NewChannelListener listener, final EndPoint ((AsteriskPBX) pbx).getManagementContext(), callerID, timeout, hideCallerId, channelVarsToSet); this.result[0] = trcResult; - if (trcResult.isSuccess()) - { - if (trcResult.getChannel() != null) - { + if (trcResult.isSuccess()) { + if (trcResult.getChannel() != null) { trcResult.getChannel().setCurrentActivityAction(action); - if (trcResult.getChannel().waitForChannelToReachAgi(30, TimeUnit.SECONDS)) - { + if (trcResult.getChannel().waitForChannelToReachAgi(30, TimeUnit.SECONDS)) { logger.info("Call reached AGI"); - } - else - { + } else { logger.error("Call never reached agi"); } - } - else - { + } else { logger.error("Call never reached agi"); } - } - else - { + } else { logger.warn("Originate failed: " + trcResult.getAbortReason()); } logger.info("Hangup status is " + hangupDetected); return this.result; - } - finally - { + } finally { this.close(); } } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); required.add(HangupEvent.class); return required; } @Override - public void onManagerEvent(final ManagerEvent event) - { - if (event instanceof HangupEvent) - { + public void onManagerEvent(final ManagerEvent event) { + if (event instanceof HangupEvent) { final HangupEvent hangup = (HangupEvent) event; final Channel hangupChannel = hangup.getChannel(); - if (DialToAgi.logger.isDebugEnabled()) - { + if (DialToAgi.logger.isDebugEnabled()) { DialToAgi.logger.debug("hangup :" + hangupChannel); //$NON-NLS-1$ DialToAgi.logger.debug("channel 0:" + this.result[0]); //$NON-NLS-1$ DialToAgi.logger.debug("channel 1:" + this.result[1]); //$NON-NLS-1$ } - if ((this.result[0] != null) && this.result[0].isSuccess() && hangupChannel.isSame(this.result[0].getChannel())) - { + if ((this.result[0] != null) && this.result[0].isSuccess() && hangupChannel.isSame(this.result[0].getChannel())) { hangupDetected = true; } } } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } - public void abort() - { - if (originator != null) - { + public void abort() { + if (originator != null) { originator.abort("user abort"); - } - else - { + } else { logger.error("Call to abort, but it doesn't look like the Dial had started yet"); } } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java index 980a3497c..2e2e0e8e4 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/EventListenerBaseClass.java @@ -10,21 +10,18 @@ * This is the basic abstract event listener class. It implements a thread * and queue. */ -public abstract class EventListenerBaseClass extends Lockable implements FilteredManagerListener, AutoCloseable -{ +public abstract class EventListenerBaseClass extends Lockable implements FilteredManagerListener, AutoCloseable { private final String name; private final PBX pbx; - protected EventListenerBaseClass(final String descriptiveName, PBX iPBX) - { + protected EventListenerBaseClass(final String descriptiveName, PBX iPBX) { this.name = descriptiveName; this.pbx = iPBX; } @Override - public String getName() - { + public String getName() { return this.name; } @@ -34,8 +31,7 @@ public String getName() * the pbx at that point event though it is initialised. */ - public void startListener() - { + public void startListener() { ((AsteriskPBX) pbx).addListener(this); } @@ -44,8 +40,7 @@ public void startListener() * Stops the listener. */ @Override - public void close() - { + public void close() { ((AsteriskPBX) pbx).removeListener(this); } @@ -54,35 +49,29 @@ public void close() * try-with-resource of JRE7. Whilst the parent class is Autoclosable we * can't always use it directly in a try block (e.g. it is the base class). * In those cases you can use this class. - * + * * @author bsutton */ - public class AutoClose implements java.lang.AutoCloseable - { + public class AutoClose implements java.lang.AutoCloseable { EventListenerBaseClass listener; - public AutoClose(final EventListenerBaseClass listener) - { + public AutoClose(final EventListenerBaseClass listener) { this(listener, true); } - public AutoClose(final EventListenerBaseClass listener, final boolean sendEvents) - { - if (listener == null) - { + public AutoClose(final EventListenerBaseClass listener, final boolean sendEvents) { + if (listener == null) { throw new IllegalArgumentException("listener may not be null"); //$NON-NLS-1$ } this.listener = listener; - if (sendEvents) - { + if (sendEvents) { listener.startListener(); } } @Override - public void close() - { + public void close() { this.listener.close(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java index 1483da224..5a29a3a36 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/HoldAtAgi.java @@ -3,67 +3,56 @@ import org.asteriskjava.pbx.EndPoint; import org.asteriskjava.pbx.TechType; -public class HoldAtAgi implements EndPoint -{ +public class HoldAtAgi implements EndPoint { @Override - public int compareTo(EndPoint arg0) - { + public int compareTo(EndPoint arg0) { // TODO Auto-generated method stub return 0; } @Override - public boolean isSame(EndPoint rhs) - { + public boolean isSame(EndPoint rhs) { return rhs instanceof HoldAtAgi; } @Override - public boolean isLocal() - { + public boolean isLocal() { return false; } @Override - public boolean isSIP() - { - return false; + public boolean isSIP() { + return false; } @Override - public String getFullyQualifiedName() - { + public String getFullyQualifiedName() { return ""; } @Override - public String getSimpleName() - { + public String getSimpleName() { return ""; } @Override - public String getSIPSimpleName() - { + public String getSIPSimpleName() { return ""; } @Override - public boolean isUnknown() - { + public boolean isUnknown() { return false; } @Override - public TechType getTech() - { + public TechType getTech() { return null; } @Override - public boolean isEmpty() - { + public boolean isEmpty() { return true; } // Logger logger = LogManager.getLogger(); diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java index 278fee9ca..af751a4fd 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/MonitorCall.java @@ -1,7 +1,5 @@ package org.asteriskjava.pbx.internal.managerAPI; -import java.util.concurrent.atomic.AtomicLong; - import org.asteriskjava.pbx.Call; import org.asteriskjava.pbx.PBXFactory; import org.asteriskjava.pbx.asterisk.wrap.actions.MonitorAction; @@ -9,20 +7,19 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class MonitorCall -{ +import java.util.concurrent.atomic.AtomicLong; + +public class MonitorCall { private static final Log logger = LogFactory.getLog(MonitorCall.class); private static final AtomicLong id = new AtomicLong(); private String file = null; - public MonitorCall(final Call call) - { + public MonitorCall(final Call call) { super(); - try - { + try { this.setFile(); final MonitorAction monitorAction = new MonitorAction(call.getRemoteParty(), this.file, "gsm", true); @@ -30,20 +27,16 @@ public MonitorCall(final Call call) pbx.sendAction(monitorAction, 1000); - } - catch (final Exception e) - { + } catch (final Exception e) { MonitorCall.logger.error(e, e); } } - public String getFilename() - { + public String getFilename() { return this.file + ".gsm"; } - private void setFile() - { + private void setFile() { long no = System.currentTimeMillis(); no = no / 1000; final String unq = Long.toHexString(no); diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java index 87a476d80..0ba6c5eaa 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateBaseClass.java @@ -1,39 +1,23 @@ package org.asteriskjava.pbx.internal.managerAPI; -import java.util.HashMap; -import java.util.HashSet; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - import org.asteriskjava.live.ManagerCommunicationException; import org.asteriskjava.lock.Locker.LockCloser; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.NewChannelListener; -import org.asteriskjava.pbx.PBX; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.asterisk.wrap.actions.OriginateAction; -import org.asteriskjava.pbx.asterisk.wrap.events.BridgeEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.DialBeginEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.DialEndEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.HangupEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.LinkEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.ManagerEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.NewChannelEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.OriginateResponseEvent; -import org.asteriskjava.pbx.asterisk.wrap.events.UnlinkEvent; +import org.asteriskjava.pbx.asterisk.wrap.events.*; import org.asteriskjava.pbx.asterisk.wrap.response.ManagerResponse; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public abstract class OriginateBaseClass extends EventListenerBaseClass -{ +import java.util.HashMap; +import java.util.HashSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +public abstract class OriginateBaseClass extends EventListenerBaseClass { /* * this class generates and issues ActionEvents to asterisk through the @@ -81,8 +65,7 @@ public abstract class OriginateBaseClass extends EventListenerBaseClass private final AtomicInteger managerEventsSeen = new AtomicInteger(); - protected OriginateBaseClass(final NewChannelListener listener, final Channel monitor, final Channel monitor2) - { + protected OriginateBaseClass(final NewChannelListener listener, final Channel monitor, final Channel monitor2) { super("NewOrginateClass", PBXFactory.getActivePBX()); pbx = (AsteriskPBX) PBXFactory.getActivePBX(); this.listener = listener; @@ -98,20 +81,18 @@ protected OriginateBaseClass(final NewChannelListener listener, final Channel mo * @param local * @param target * @param myVars - * @param callerId the caller id to set when initiating this call. + * @param callerId the caller id to set when initiating this call. * @param hideCallerId * @param context * @return */ OriginateResult originate(final EndPoint local, final EndPoint target, final HashMap myVars, - final CallerID callerID, final Integer timeout, final boolean hideCallerId, final String context) - { + final CallerID callerID, final Integer timeout, final boolean hideCallerId, final String context) { OriginateBaseClass.logger.info("originate called"); this.originateSeen = false; this.channelSeen = false; - if (this.hungup) - { + if (this.hungup) { // the monitored channel already hungup so just return false and // shutdown return null; @@ -131,15 +112,11 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has Integer localTimeout = timeout; - if (timeout == null) - { + if (timeout == null) { localTimeout = 30000; - try - { + try { localTimeout = settings.getDialTimeout() * 1000; - } - catch (final Exception e) - { + } catch (final Exception e) { OriginateBaseClass.logger.error("Invalid dial timeout value"); } } @@ -151,13 +128,10 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has // a channel as the doco talks about 'dialing the channel'. I suspect // this // may be part of asterisk's sloppy terminology. - if (local.isLocal()) - { + if (local.isLocal()) { originate.setEndPoint(local); originate.setOption("/n"); - } - else - { + } else { originate.setEndPoint(local); } @@ -166,13 +140,10 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has originate.setPriority(1); // Set the caller id. - if (hideCallerId) - { + if (hideCallerId) { // hide callerID originate.setCallingPres(32); - } - else - { + } else { originate.setCallerId(callerID); } @@ -180,15 +151,13 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has originate.setAsync(true); originate.setTimeout(localTimeout); - try - { + try { // Just add us as an asterisk event listener. this.startListener(); response = pbx.sendAction(originate, localTimeout); OriginateBaseClass.logger.info("Originate.sendAction completed"); - if (response.getResponse().compareToIgnoreCase("Success") != 0) - { + if (response.getResponse().compareToIgnoreCase("Success") != 0) { OriginateBaseClass.logger .error("Error Originating call" + originate.toString() + " : " + response.getMessage());//$NON-NLS-2$ throw new ManagerCommunicationException(response.getMessage(), null); @@ -196,43 +165,29 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has // wait the set timeout +1 second to allow for // asterisk to start the originate - if (!originateLatch.await(localTimeout + 1000, TimeUnit.MILLISECONDS)) - { + if (!originateLatch.await(localTimeout + 1000, TimeUnit.MILLISECONDS)) { logger.error("Originate Latch timed out"); } - } - catch (final InterruptedException e) - { + } catch (final InterruptedException e) { OriginateBaseClass.logger.debug(e, e); - } - catch (final Exception e) - { + } catch (final Exception e) { OriginateBaseClass.logger.error(e, e); - } - finally - { + } finally { this.close(); } - if (this.originateSuccess) - { + if (this.originateSuccess) { this.result.setSuccess(true); this.result.setChannelData(this.newChannel); OriginateBaseClass.logger.info("new channel ok: " + this.newChannel); - } - else - { + } else { OriginateBaseClass.logger.warn("originate failed to connect endPoint: " + local + " to ext " + target); //$NON-NLS-2$ - if (this.newChannel != null) - { - try - { + if (this.newChannel != null) { + try { logger.warn("Hanging up"); pbx.hangup(this.newChannel); - } - catch (IllegalArgumentException | IllegalStateException | PBXException e) - { + } catch (IllegalArgumentException | IllegalStateException | PBXException e) { logger.error(e, e); } @@ -242,24 +197,19 @@ OriginateResult originate(final EndPoint local, final EndPoint target, final Has return this.result; } - void abort(final String reason) - { + void abort(final String reason) { OriginateBaseClass.logger.warn("Aborting originate "); this.originateSuccess = false; this.result.setAbortReason(reason); this.hungup = true; - if (this.newChannel != null) - { + if (this.newChannel != null) { OriginateBaseClass.logger.warn("Aborted, Hangup up on the way out"); this.result.setChannelHungup(true); PBX pbx = PBXFactory.getActivePBX(); - try - { + try { pbx.hangup(this.newChannel); - } - catch (IllegalArgumentException | IllegalStateException | PBXException e) - { + } catch (IllegalArgumentException | IllegalStateException | PBXException e) { logger.error(e, e); } @@ -269,9 +219,8 @@ void abort(final String reason) } @Override - public HashSet> requiredEvents() - { - HashSet> required = new HashSet<>(); + public HashSet> requiredEvents() { + HashSet> required = new HashSet<>(); required.add(OriginateResponseEvent.class); required.add(BridgeEvent.class); @@ -293,39 +242,30 @@ void abort(final String reason) * time. */ @Override - public void onManagerEvent(final ManagerEvent event) - { - try (LockCloser closer = this.withLock()) - { + public void onManagerEvent(final ManagerEvent event) { + try (LockCloser closer = this.withLock()) { managerEventsSeen.getAndIncrement(); - if (event instanceof HangupEvent) - { + if (event instanceof HangupEvent) { final HangupEvent hangupEvt = (HangupEvent) event; final Channel hangupChannel = hangupEvt.getChannel(); - if (channelId.equals(hangupEvt.getUniqueId())) - { + if (channelId.equals(hangupEvt.getUniqueId())) { this.originateSuccess = false; OriginateBaseClass.logger.warn("Dest channel " + this.newChannel + " hungup"); originateLatch.countDown(); } - if ((this.monitorChannel1 != null) && (hangupChannel.isSame(this.monitorChannel1))) - { + if ((this.monitorChannel1 != null) && (hangupChannel.isSame(this.monitorChannel1))) { this.originateSuccess = false; this.hungup = true; - if (this.newChannel != null) - { + if (this.newChannel != null) { OriginateBaseClass.logger.warn("hanging up " + this.newChannel); this.result.setChannelHungup(true); PBX pbx = PBXFactory.getActivePBX(); - try - { + try { logger.warn("Hanging up"); pbx.hangup(this.newChannel); - } - catch (IllegalArgumentException | IllegalStateException | PBXException e) - { + } catch (IllegalArgumentException | IllegalStateException | PBXException e) { logger.error(e, e); } @@ -333,22 +273,17 @@ public void onManagerEvent(final ManagerEvent event) OriginateBaseClass.logger.warn("notify channel 1 hungup"); originateLatch.countDown(); } - if ((this.monitorChannel2 != null) && (hangupChannel.isSame(this.monitorChannel2))) - { + if ((this.monitorChannel2 != null) && (hangupChannel.isSame(this.monitorChannel2))) { this.originateSuccess = false; this.hungup = true; - if (this.newChannel != null) - { + if (this.newChannel != null) { OriginateBaseClass.logger.warn("Hanging up channel " + this.newChannel); this.result.setChannelHungup(true); PBX pbx = PBXFactory.getActivePBX(); - try - { + try { pbx.hangup(this.newChannel); - } - catch (IllegalArgumentException | IllegalStateException | PBXException e) - { + } catch (IllegalArgumentException | IllegalStateException | PBXException e) { logger.error(e, e); } @@ -358,8 +293,7 @@ public void onManagerEvent(final ManagerEvent event) } } - if (event instanceof OriginateResponseEvent) - { + if (event instanceof OriginateResponseEvent) { OriginateBaseClass.logger.debug("response : " + this.newChannel); final OriginateResponseEvent response = (OriginateResponseEvent) event; @@ -367,20 +301,16 @@ public void onManagerEvent(final ManagerEvent event) + (response.isChannel() ? response.getChannel() : response.getEndPoint()) + " originateID:" + this.originateID); OriginateBaseClass.logger.debug("{" + response.getReason() + ":" + response.getResponse() + "}"); //$NON-NLS-2$ //$NON-NLS-3$ - if (this.originateID != null) - { - if (this.originateID.compareToIgnoreCase(response.getActionId()) == 0) - { + if (this.originateID != null) { + if (this.originateID.compareToIgnoreCase(response.getActionId()) == 0) { this.originateSuccess = response.isSuccess(); OriginateBaseClass.logger.info("OriginateResponse: matched actionId, success=" + this.originateSuccess + " channelSeen=" + this.channelSeen); this.originateSeen = true; - if (originateSuccess) - { - if (newChannel == null) - { + if (originateSuccess) { + if (newChannel == null) { this.newChannel = response.getChannel(); } channelSeen = newChannel != null; @@ -393,29 +323,22 @@ public void onManagerEvent(final ManagerEvent event) // the // NewChannelEvent doing the // notify. - if (this.channelSeen) - { + if (this.channelSeen) { OriginateBaseClass.logger.info("notify originate response event " + this.originateSuccess); originateLatch.countDown(); - } - else - { + } else { logger.error("Originate Response didn't contain the channel"); } } } - } - else - { + } else { OriginateBaseClass.logger.warn("actionid is null"); } } - if (event instanceof NewChannelEvent) - { + if (event instanceof NewChannelEvent) { final NewChannelEvent newState = (NewChannelEvent) event; - if (channelId.equalsIgnoreCase(newState.getChannel().getUniqueId())) - { + if (channelId.equalsIgnoreCase(newState.getChannel().getUniqueId())) { final Channel channel = newState.getChannel(); OriginateBaseClass.logger.info("new channel event :" + channel + " context = " + newState.getContext() //$NON-NLS-2$ @@ -425,19 +348,15 @@ public void onManagerEvent(final ManagerEvent event) } } - if (event instanceof BridgeEvent) - { - if (((BridgeEvent) event).isLink()) - { + if (event instanceof BridgeEvent) { + if (((BridgeEvent) event).isLink()) { final BridgeEvent bridgeEvent = (BridgeEvent) event; Channel channel = bridgeEvent.getChannel1(); - if (bridgeEvent.getChannel1().isLocal()) - { + if (bridgeEvent.getChannel1().isLocal()) { channel = bridgeEvent.getChannel2(); } if (channelId.equalsIgnoreCase(bridgeEvent.getChannel1().getUniqueId()) - || channelId.equalsIgnoreCase(bridgeEvent.getChannel2().getUniqueId())) - { + || channelId.equalsIgnoreCase(bridgeEvent.getChannel2().getUniqueId())) { OriginateBaseClass.logger .info("new bridge event :" + channel + " channel1 = " + bridgeEvent.getChannel1() //$NON-NLS-2$ @@ -449,13 +368,10 @@ public void onManagerEvent(final ManagerEvent event) } - if (event instanceof DialEndEvent) - { - if (channelId.equalsIgnoreCase(((DialEndEvent) event).getDestChannel().getUniqueId())) - { + if (event instanceof DialEndEvent) { + if (channelId.equalsIgnoreCase(((DialEndEvent) event).getDestChannel().getUniqueId())) { String forward = ((DialEndEvent) event).getForward(); - if (forward != null && forward.length() > 0) - { + if (forward != null && forward.length() > 0) { logger.warn("DialEndEvent"); originateLatch.countDown(); } @@ -464,17 +380,14 @@ public void onManagerEvent(final ManagerEvent event) } } - private void handleId(Channel channel) - { + private void handleId(Channel channel) { - if ((this.newChannel == null) && !channel.isLocal()) - { + if ((this.newChannel == null) && !channel.isLocal()) { this.newChannel = channel; this.channelSeen = true; OriginateBaseClass.logger.info("new channel name " + channel); - if (this.listener != null) - { + if (this.listener != null) { /* * Update the phone channel to allow the call to be cancelled * before it's answered. @@ -482,8 +395,7 @@ private void handleId(Channel channel) this.listener.channelUpdate(channel); } - if (this.originateSeen) - { + if (this.originateSeen) { OriginateBaseClass.logger.info("notifying success 362"); originateLatch.countDown(); } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java index 9b3ef4e81..c2e544357 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateResult.java @@ -2,8 +2,7 @@ import org.asteriskjava.pbx.Channel; -public class OriginateResult -{ +public class OriginateResult { private boolean channelHungup = false; @@ -13,50 +12,41 @@ public class OriginateResult private String abortReason; - OriginateResult() - { + OriginateResult() { // not used } - public String getAbortReason() - { + public String getAbortReason() { return this.abortReason; } - void setAbortReason(final String reason) - { + void setAbortReason(final String reason) { this.abortReason = reason; } - public void setChannelData(final Channel channel) - { + public void setChannelData(final Channel channel) { this.newChannel = channel; } - public Channel getChannel() - { + public Channel getChannel() { return this.newChannel; } - public boolean isSuccess() - { + public boolean isSuccess() { return this.success; } - public void setSuccess(boolean success) - { + public void setSuccess(boolean success) { this.success = success; } - public boolean isChannelHungup() - { + public boolean isChannelHungup() { return this.channelHungup; } - public void setChannelHungup(boolean channel1Hungup) - { + public void setChannelHungup(boolean channel1Hungup) { this.channelHungup = channel1Hungup; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java index 038276faf..f82cd8841 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/OriginateToExtension.java @@ -1,32 +1,24 @@ package org.asteriskjava.pbx.internal.managerAPI; +import org.asteriskjava.pbx.*; + import java.util.HashMap; import java.util.Map; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.CallerID; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.ListenerPriority; -import org.asteriskjava.pbx.NewChannelListener; -import org.asteriskjava.pbx.PBXFactory; - -public class OriginateToExtension extends OriginateBaseClass -{ +public class OriginateToExtension extends OriginateBaseClass { /* * this class generates and issues ActionEvents to asterisk through the * manager. This is the asterisk coal face. */ - public OriginateToExtension(final NewChannelListener listener) - { + public OriginateToExtension(final NewChannelListener listener) { super(listener, null, null); } public OriginateResult originate(final EndPoint localHandset, final EndPoint targetExtension, final boolean autoAnswer, - final CallerID callerID, final String context) - { + final CallerID callerID, final String context) { /* * A new call is originated on the nominated channel to the specified * extension. @@ -36,8 +28,7 @@ public OriginateResult originate(final EndPoint localHandset, final EndPoint tar final AsteriskSettings profile = PBXFactory.getActiveProfile(); final HashMap myVars = new HashMap<>(1); - if (autoAnswer) - { + if (autoAnswer) { RedirectCall.setAutoAnswer(myVars, profile); } @@ -45,9 +36,8 @@ public OriginateResult originate(final EndPoint localHandset, final EndPoint tar } public OriginateResult originate(final EndPoint localHandset, final EndPoint targetExtension, final boolean autoAnswer, - final String context, final CallerID callerID, Integer timeout, final boolean hideCallerId, - Map channelVarsToSet) - { + final String context, final CallerID callerID, Integer timeout, final boolean hideCallerId, + Map channelVarsToSet) { /* * A new call is originated on the nominated channel to the specified * extension. @@ -57,12 +47,10 @@ public OriginateResult originate(final EndPoint localHandset, final EndPoint tar final AsteriskSettings profile = PBXFactory.getActiveProfile(); final HashMap myVars = new HashMap<>(1); - if (autoAnswer) - { + if (autoAnswer) { RedirectCall.setAutoAnswer(myVars, profile); } - if (channelVarsToSet != null) - { + if (channelVarsToSet != null) { myVars.putAll(channelVarsToSet); } @@ -70,8 +58,7 @@ public OriginateResult originate(final EndPoint localHandset, final EndPoint tar } @Override - public ListenerPriority getPriority() - { + public ListenerPriority getPriority() { return ListenerPriority.NORMAL; } diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java index f10db39c5..522191485 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectCall.java @@ -1,43 +1,34 @@ package org.asteriskjava.pbx.internal.managerAPI; -import java.util.HashMap; - -import org.asteriskjava.pbx.AgiChannelActivityAction; -import org.asteriskjava.pbx.AsteriskSettings; -import org.asteriskjava.pbx.Channel; -import org.asteriskjava.pbx.EndPoint; -import org.asteriskjava.pbx.PBXException; -import org.asteriskjava.pbx.PBXFactory; +import org.asteriskjava.pbx.*; import org.asteriskjava.pbx.agi.AgiChannelActivityDial; import org.asteriskjava.pbx.agi.AgiChannelActivityVoicemail; import org.asteriskjava.pbx.internal.core.AsteriskPBX; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class RedirectCall -{ +import java.util.HashMap; + +public class RedirectCall { /* * this class generates and issues ActionEvents to asterisk through the * manager. This is the asterisk coal face. */ private static final Log logger = LogFactory.getLog(RedirectCall.class); - static public void setAutoAnswer(final HashMap myVars, final AsteriskSettings settings) - { + static public void setAutoAnswer(final HashMap myVars, final AsteriskSettings settings) { myVars.put(AsteriskPBX.getSIPADDHeader(false, true), settings.getAutoAnswer()); RedirectCall.logger.debug("auto answer"); //$NON-NLS-1$ } public boolean redirect(final Channel channel, final EndPoint targetEndPoint, final String context, - final boolean autoAnswer) throws PBXException - { + final boolean autoAnswer) throws PBXException { // Set or clear the auto answer header. // Clearing is important as it may have been set during the // initial answer sequence. If we don't clear it then then transfer // target will be auto-answered, which is fun but bad. String sipHeader = ""; - if (autoAnswer) - { + if (autoAnswer) { sipHeader = PBXFactory.getActiveProfile().getAutoAnswer(); } @@ -51,19 +42,16 @@ public boolean redirect(final Channel channel, final EndPoint targetEndPoint, fi return true; } - public boolean redirectToVoicemail(final Channel channel, final EndPoint mailbox) throws PBXException - { + public boolean redirectToVoicemail(final Channel channel, final EndPoint mailbox) throws PBXException { redirect(channel, new AgiChannelActivityVoicemail(mailbox.getFullyQualifiedName())); return true; } - public void redirect(Channel channel, AgiChannelActivityAction channelActivityHold) throws PBXException - { + public void redirect(Channel channel, AgiChannelActivityAction channelActivityHold) throws PBXException { final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); - if (!pbx.moveChannelToAgi(channel)) - { + if (!pbx.moveChannelToAgi(channel)) { throw new PBXException("Channel: " + channel + " couldn't be moved to agi"); } if (!pbx.waitForChannelToQuiescent(channel, 3000)) diff --git a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java index 4a8df6d69..548938ed1 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java +++ b/src/main/java/org/asteriskjava/pbx/internal/managerAPI/RedirectToMeetMe.java @@ -8,18 +8,15 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -public class RedirectToMeetMe -{ +public class RedirectToMeetMe { private static final Log logger = LogFactory.getLog(RedirectToMeetMe.class); - public RedirectToMeetMe() - { + public RedirectToMeetMe() { super(); } public boolean redirectToMeetme(final Channel channel, final String room, String bridgeProfile, String userProfile) - throws PBXException - { + throws PBXException { final AsteriskPBX pbx = (AsteriskPBX) PBXFactory.getActivePBX(); /* * this procedure rediects the specified channel to the specified meetme @@ -31,8 +28,7 @@ public boolean redirectToMeetme(final Channel channel, final String room, String RedirectToMeetMe.logger.info("redirect to Meetme channel " + channel + " room " + room); - if (!pbx.moveChannelToAgi(channel)) - { + if (!pbx.moveChannelToAgi(channel)) { throw new PBXException("Channel: " + channel + " couldn't be moved to agi"); } channel.setCurrentActivityAction(new AgiChannelActivityMeetme(room, bridgeProfile, userProfile)); diff --git a/src/main/java/org/asteriskjava/pbx/util/LogTime.java b/src/main/java/org/asteriskjava/pbx/util/LogTime.java index a20fa42c1..2db86c5a1 100644 --- a/src/main/java/org/asteriskjava/pbx/util/LogTime.java +++ b/src/main/java/org/asteriskjava/pbx/util/LogTime.java @@ -7,15 +7,13 @@ /** * @author work shop */ -public class LogTime -{ +public class LogTime { private final Long dStartTime = System.currentTimeMillis(); /** * @return time taken from construction until now in milliseconds */ - public long timeTaken() - { + public long timeTaken() { return System.currentTimeMillis() - this.dStartTime; } } diff --git a/src/main/java/org/asteriskjava/tools/HtmlEventTracer.java b/src/main/java/org/asteriskjava/tools/HtmlEventTracer.java index 660ddc3d6..b60b0b0f9 100644 --- a/src/main/java/org/asteriskjava/tools/HtmlEventTracer.java +++ b/src/main/java/org/asteriskjava/tools/HtmlEventTracer.java @@ -1,5 +1,9 @@ package org.asteriskjava.tools; +import org.asteriskjava.live.DefaultAsteriskServer; +import org.asteriskjava.manager.ManagerEventListener; +import org.asteriskjava.manager.event.*; + import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; @@ -13,22 +17,6 @@ import java.util.List; import java.util.Map; -import org.asteriskjava.live.DefaultAsteriskServer; -import org.asteriskjava.manager.ManagerEventListener; -import org.asteriskjava.manager.event.AbstractParkedCallEvent; -import org.asteriskjava.manager.event.AntennaLevelEvent; -import org.asteriskjava.manager.event.BridgeEvent; -import org.asteriskjava.manager.event.DialEvent; -import org.asteriskjava.manager.event.HangupEvent; -import org.asteriskjava.manager.event.HoldEvent; -import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.NewChannelEvent; -import org.asteriskjava.manager.event.NewExtenEvent; -import org.asteriskjava.manager.event.NewStateEvent; -import org.asteriskjava.manager.event.PausedEvent; -import org.asteriskjava.manager.event.RenameEvent; -import org.asteriskjava.manager.event.UnpausedEvent; - /** * A diagnostic tool that creates an HTML file showing the state changing events * received from Asterisk on the Manager API. @@ -46,16 +34,14 @@ * * @version $Id$ */ -public class HtmlEventTracer implements ManagerEventListener -{ +public class HtmlEventTracer implements ManagerEventListener { private String filename = "trace.html"; private PrintWriter writer; private final List uniqueIds; private final List events; - private final Map, String> colors; + private final Map, String> colors; - public HtmlEventTracer() - { + public HtmlEventTracer() { uniqueIds = new ArrayList<>(); events = new ArrayList<>(); colors = new HashMap<>(); @@ -68,20 +54,15 @@ public HtmlEventTracer() colors.put(BridgeEvent.class, "#fff8ae"); // light yellow colors.put(HangupEvent.class, "#ff6c17"); // orange - try - { + try { writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(filename), StandardCharsets.UTF_8)); - } - catch (IOException e) - { + } catch (IOException e) { e.printStackTrace(); } } - public static void main(String[] args) throws Exception - { - if (args.length != 3) - { + public static void main(String[] args) throws Exception { + if (args.length != 3) { System.err.println("Usage: java org.asteriskjava.tools.HtmlEventTracer host username password"); System.exit(1); } @@ -96,43 +77,35 @@ public static void main(String[] args) throws Exception System.err.println("Event tracer successfully started. Press Ctrl-C to write trace file and exit."); - Runtime.getRuntime().addShutdownHook(new Thread() - { + Runtime.getRuntime().addShutdownHook(new Thread() { @Override - public void run() - { + public void run() { tracer.write(); server.shutdown(); } }); - while (true) - { + while (true) { Thread.sleep(1000); } } - public void onManagerEvent(ManagerEvent event) - { + public void onManagerEvent(ManagerEvent event) { events.add(event); System.out.println("> " + event); - for (String property : new String[]{"uniqueId", "uniqueId1", "uniqueId2", "srcUniqueId", "destUniqueId"}) - { + for (String property : new String[]{"uniqueId", "uniqueId1", "uniqueId2", "srcUniqueId", "destUniqueId"}) { String uniqueId; uniqueId = getProperty(event, property); - if (uniqueId != null && !uniqueIds.contains(uniqueId)) - { + if (uniqueId != null && !uniqueIds.contains(uniqueId)) { uniqueIds.add(uniqueId); } } } - public void write() - { + public void write() { writer.append(""); - for (String uniqueId : uniqueIds) - { + for (String uniqueId : uniqueIds) { writer.append(""); writer.println(""); - for (ManagerEvent event : events) - { + for (ManagerEvent event : events) { boolean print = false; StringBuilder line = new StringBuilder(); @@ -152,24 +124,19 @@ public void write() line.append("
    "); line.append(event.getDateReceived()); line.append(""); - for (String uniqueId : uniqueIds) - { + for (String uniqueId : uniqueIds) { String text; text = getText(uniqueId, event); - if (text == null) - { + if (text == null) { line.append(""); - } - else - { + } else { String color = getColor(event.getClass()); line.append(""); print = true; } } line.append(""); - if (print) - { + if (print) { writer.println(line.toString()); } } @@ -178,36 +145,27 @@ public void write() System.err.println("Trace file successfully written to " + filename + "."); } - private String getColor(Class< ? extends ManagerEvent> clazz) - { - for (Map.Entry, String> entry : colors.entrySet()) - { - if (entry.getKey().isAssignableFrom(clazz)) - { + private String getColor(Class clazz) { + for (Map.Entry, String> entry : colors.entrySet()) { + if (entry.getKey().isAssignableFrom(clazz)) { return entry.getValue(); } } return "#ffffff"; } - protected String getProperty(Object obj, String property) - { - try - { + protected String getProperty(Object obj, String property) { + try { BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()); - for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) - { - if (!propertyDescriptor.getName().equals(property)) - { + for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) { + if (!propertyDescriptor.getName().equals(property)) { continue; } final Object o = propertyDescriptor.getReadMethod().invoke(obj); return o != null ? o.toString() : null; } - } - catch (Exception e) - { + } catch (Exception e) { System.err.println("Unable to read property '" + property + "' from object " + obj + ": " + e.getMessage()); return null; } @@ -215,108 +173,74 @@ protected String getProperty(Object obj, String property) return null; } - protected String getText(String uniqueId, ManagerEvent event) - { + protected String getText(String uniqueId, ManagerEvent event) { String format = null; String[] properties = null; - if (uniqueId.equals(getProperty(event, "uniqueId"))) - { - if (event instanceof NewChannelEvent) - { + if (uniqueId.equals(getProperty(event, "uniqueId"))) { + if (event instanceof NewChannelEvent) { format = "%s
    %s"; properties = new String[]{"channel", "state"}; - } - else if (event instanceof NewStateEvent) - { + } else if (event instanceof NewStateEvent) { format = "%s
    %s"; properties = new String[]{"channel", "state"}; - } - else if (event instanceof NewExtenEvent) - { + } else if (event instanceof NewExtenEvent) { format = "%s,%s,%s
    %s(%s)"; properties = new String[]{"context", "extension", "priority", "application", "appData"}; - } - else if (event instanceof RenameEvent) - { + } else if (event instanceof RenameEvent) { format = "old: %s
    new: %s"; properties = new String[]{"oldname", "newname"}; - } - else if (event instanceof HoldEvent) - { + } else if (event instanceof HoldEvent) { format = "%s"; properties = new String[]{"status"}; - } - else if (event instanceof AbstractParkedCallEvent) - { + } else if (event instanceof AbstractParkedCallEvent) { format = "exten: %s
    from: %s"; properties = new String[]{"exten", "from"}; - } - else if (event instanceof HangupEvent) - { + } else if (event instanceof HangupEvent) { format = "%s
    %s (%s)"; properties = new String[]{"channel", "cause", "causeTxt"}; - } - else if (event instanceof AntennaLevelEvent) - { + } else if (event instanceof AntennaLevelEvent) { format = "%s"; properties = new String[]{"signal"}; - } - else if (event instanceof PausedEvent) - { + } else if (event instanceof PausedEvent) { format = "(%s) %s"; properties = new String[]{"header", "extension"}; - } - else if (event instanceof UnpausedEvent) - { + } else if (event instanceof UnpausedEvent) { format = "(%s) %s"; properties = new String[]{"header", "extension"}; } } - if (event instanceof BridgeEvent) - { - if (uniqueId.equals(getProperty(event, "uniqueId1"))) - { + if (event instanceof BridgeEvent) { + if (uniqueId.equals(getProperty(event, "uniqueId1"))) { format = "%s
    %s
    %s"; properties = new String[]{"uniqueId2", "channel2", "bridgeState"}; - } - else if (uniqueId.equals(getProperty(event, "uniqueId2"))) - { + } else if (uniqueId.equals(getProperty(event, "uniqueId2"))) { format = "%s
    %s
    %s"; properties = new String[]{"uniqueId1", "channel1", "bridgeState"}; } } - if (event instanceof DialEvent) - { - if (uniqueId.equals(getProperty(event, "srcUniqueId"))) - { + if (event instanceof DialEvent) { + if (uniqueId.equals(getProperty(event, "srcUniqueId"))) { format = "To: %s"; properties = new String[]{"destination"}; - } - else if (uniqueId.equals(getProperty(event, "destUniqueId"))) - { + } else if (uniqueId.equals(getProperty(event, "destUniqueId"))) { format = "From: %s"; properties = new String[]{"src"}; } } - if (format != null && properties != null) - { + if (format != null && properties != null) { String[] args = new String[properties.length]; - for (int i = 0; i < properties.length; i++) - { + for (int i = 0; i < properties.length; i++) { String value; value = getProperty(event, properties[i]); - if (value == null) - { + if (value == null) { args[i] = ""; - } - else - { + } else { value = value.replace("<", "<"); value = value.replace(">", ">"); args[i] = value; diff --git a/src/main/java/org/asteriskjava/tools/package.html b/src/main/java/org/asteriskjava/tools/package.html index 82bfc804c..ed5aa3e20 100644 --- a/src/main/java/org/asteriskjava/tools/package.html +++ b/src/main/java/org/asteriskjava/tools/package.html @@ -1,27 +1,27 @@ - +

    Tools for debugging Asterisk and Asterisk-Java.

    - \ No newline at end of file + diff --git a/src/main/java/org/asteriskjava/util/AstState.java b/src/main/java/org/asteriskjava/util/AstState.java index 6cdd3b2e3..afe67770d 100644 --- a/src/main/java/org/asteriskjava/util/AstState.java +++ b/src/main/java/org/asteriskjava/util/AstState.java @@ -11,8 +11,7 @@ * * @since 1.0.0 */ -public class AstState -{ +public class AstState { /* from include/asterisk/channel.h */ /** @@ -67,8 +66,7 @@ public class AstState private static final Map inverseStateMap; - static - { + static { final Map tmpInverseStateMap = new HashMap<>(); tmpInverseStateMap.put("Down", AST_STATE_DOWN); @@ -87,8 +85,7 @@ public class AstState private static final Pattern UNKNOWN_STATE_PATTERN = Pattern.compile("^Unknown \\((\\d+)\\)$"); - private AstState() - { + private AstState() { } @@ -98,28 +95,21 @@ private AstState() * @param str state as a descriptive text. * @return numeric state. */ - public static Integer str2state(String str) - { + public static Integer str2state(String str) { Integer state; - if (str == null) - { + if (str == null) { return null; } state = inverseStateMap.get(str); - if (state == null) - { + if (state == null) { Matcher matcher = UNKNOWN_STATE_PATTERN.matcher(str); - if (matcher.matches()) - { - try - { + if (matcher.matches()) { + try { state = Integer.valueOf(matcher.group(1)); - } - catch (NumberFormatException e) - { + } catch (NumberFormatException e) { // should not happen as the pattern requires \d+ for the state. throw new IllegalArgumentException("Unable to convert state '" + str + "' to integer representation", e); } diff --git a/src/main/java/org/asteriskjava/util/AstUtil.java b/src/main/java/org/asteriskjava/util/AstUtil.java index b2736e103..0f0383b27 100644 --- a/src/main/java/org/asteriskjava/util/AstUtil.java +++ b/src/main/java/org/asteriskjava/util/AstUtil.java @@ -12,13 +12,11 @@ * @author srt * @version $Id$ */ -public class AstUtil -{ +public class AstUtil { private static final Set TRUE_LITERALS; private static final Set NULL_LITERALS; - static - { + static { TRUE_LITERALS = new HashSet<>(20); TRUE_LITERALS.add("yes"); TRUE_LITERALS.add("true"); @@ -43,8 +41,7 @@ public class AstUtil NULL_LITERALS.add("(null)"); // appData in ListDialplanEvent } - private AstUtil() - { + private AstUtil() { // hide constructor } @@ -52,7 +49,7 @@ private AstUtil() * Checks if a String represents true or false * according to Asterisk's logic.
    * The original implementation is util.c is as follows:
    - * + * *
          *     int ast_true(const char *s)
          *     {
    @@ -70,7 +67,7 @@ private AstUtil()
          *         return 0;
          *     }
          * 
    - * + * *
    * To support the dnd property of * {@link org.asteriskjava.manager.event.ZapShowChannelsEvent} this method @@ -78,17 +75,14 @@ private AstUtil() * * @param o the Object (usually a String) to check for true. * @return true if s represents true, - * false otherwise. + * false otherwise. */ - public static boolean isTrue(Object o) - { - if (o == null) - { + public static boolean isTrue(Object o) { + if (o == null) { return false; } - if (o instanceof Boolean) - { + if (o instanceof Boolean) { return (Boolean) o; } @@ -99,10 +93,9 @@ public static boolean isTrue(Object o) * @param a an object * @param b an object to be compared with {@code a} for equality * @return {@code true} if the arguments are equal to each other and - * {@code false} otherwise + * {@code false} otherwise */ - public static boolean isEqual(Object a, Object b) - { + public static boolean isEqual(Object a, Object b) { return a == b || a != null && a.equals(b); } @@ -116,16 +109,14 @@ public static boolean isEqual(Object a, Object b) * @param s the string to parse * @return a String[] with name (index 0) and number (index 1) */ - public static String[] parseCallerId(String s) - { + public static String[] parseCallerId(String s) { final String[] result = new String[2]; final int lbPosition; final int rbPosition; String name; String number; - if (s == null) - { + if (s == null) { return result; } @@ -133,29 +124,24 @@ public static String[] parseCallerId(String s) rbPosition = s.lastIndexOf('>'); // no opening and closing brace? use value as CallerId name - if (lbPosition < 0 || rbPosition < 0) - { + if (lbPosition < 0 || rbPosition < 0) { name = s.trim(); - if (name.length() == 0) - { + if (name.length() == 0) { name = null; } result[0] = name; return result; } number = s.substring(lbPosition + 1, rbPosition).trim(); - if (number.length() == 0) - { + if (number.length() == 0) { number = null; } name = s.substring(0, lbPosition).trim(); - if (name.startsWith("\"") && name.endsWith("\"") && name.length() > 1) - { + if (name.startsWith("\"") && name.endsWith("\"") && name.length() > 1) { name = name.substring(1, name.length() - 1).trim(); } - if (name.length() == 0) - { + if (name.length() == 0) { name = null; } @@ -171,61 +157,58 @@ public static String[] parseCallerId(String s) * "<null>".
    * To find such replacements search for S_OR in Asterisk's * source code. You will find things like - * + * *
          * S_OR(chan->cid.cid_num, "<unknown>")
          * fdprintf(fd, "agi_callerid: %s\n", S_OR(chan->cid.cid_num, "unknown"));
          * 
    - * + *

    * and more... * * @param s the string to test, may be null. If s is not a - * string the only test that is performed is a check for - * null. + * string the only test that is performed is a check for + * null. * @return true if the s was null in Asterisk; - * false otherwise. + * false otherwise. */ - public static boolean isNull(Object s) - { - if (s == null) - { + public static boolean isNull(Object s) { + if (s == null) { return true; } - if (!(s instanceof String)) - { + if (!(s instanceof String)) { return false; } return NULL_LITERALS.contains(((String) s).toLowerCase(Locale.US)); } + /** * Converts a non-standard Asterisk boolean String value into something the Boolean class * String constructor recognizes. - * - * Asterisk can return various strings that represent truth values. + *

    + * Asterisk can return various strings that represent truth values. * This method converts them into standard True/False, or null if null. - * + * * @param value * @return true if the String is "true" or "yes" (case insensitive). - * false if the String is "false" or "no" (case insensitive). - * null if the String is null. + * false if the String is "false" or "no" (case insensitive). + * null if the String is null. * @throws IllegalArgumentException if any other value not listed above. */ - - public static String convertAsteriskBooleanStringToStandardBooleanString(String value) { - if (value == null) return null; - switch (value.toLowerCase()) - { - case "true": - case "yes": - return "True"; - case "false": - case "no": - return "False"; - default: - throw new IllegalArgumentException("value of:" + value + " was not recognized as a boolean"); - } - - } + + public static String convertAsteriskBooleanStringToStandardBooleanString(String value) { + if (value == null) return null; + switch (value.toLowerCase()) { + case "true": + case "yes": + return "True"; + case "false": + case "no": + return "False"; + default: + throw new IllegalArgumentException("value of:" + value + " was not recognized as a boolean"); + } + + } } diff --git a/src/main/java/org/asteriskjava/util/Base64.java b/src/main/java/org/asteriskjava/util/Base64.java index 3f053f778..e819c08d9 100644 --- a/src/main/java/org/asteriskjava/util/Base64.java +++ b/src/main/java/org/asteriskjava/util/Base64.java @@ -12,14 +12,14 @@ * and vice-versa.

    * From java.util.prefs. * - * @author Josh Bloch + * @author Josh Bloch */ public class Base64 { - + private Base64() { - + } - + /** * Translates the specified byte array into a Base64 string as per * Preferences.put(byte[]). @@ -40,21 +40,21 @@ public static String byteArrayToAltBase64(byte[] a) { private static String byteArrayToBase64(byte[] a, boolean alternate) { int aLen = a.length; - int numFullGroups = aLen/3; - int numBytesInPartialGroup = aLen - 3*numFullGroups; - int resultLen = 4*((aLen + 2)/3); + int numFullGroups = aLen / 3; + int numBytesInPartialGroup = aLen - 3 * numFullGroups; + int resultLen = 4 * ((aLen + 2) / 3); StringBuilder result = new StringBuilder(resultLen); char[] intToAlpha = alternate ? intToAltBase64 : intToBase64; // Translate all full groups from byte array elements to Base64 int inCursor = 0; - for (int i=0; i> 2]); - result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]); - result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]); + result.append(intToAlpha[(byte0 << 4) & 0x3f | (byte1 >> 4)]); + result.append(intToAlpha[(byte1 << 2) & 0x3f | (byte2 >> 6)]); result.append(intToAlpha[byte2 & 0x3f]); } @@ -68,8 +68,8 @@ private static String byteArrayToBase64(byte[] a, boolean alternate) { } else { // assert numBytesInPartialGroup == 2; int byte1 = a[inCursor++] & 0xff; - result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]); - result.append(intToAlpha[(byte1 << 2)&0x3f]); + result.append(intToAlpha[(byte0 << 4) & 0x3f | (byte1 >> 4)]); + result.append(intToAlpha[(byte1 << 2) & 0x3f]); result.append('='); } } @@ -84,11 +84,11 @@ private static String byteArrayToBase64(byte[] a, boolean alternate) { * in Table 1 of RFC 2045. */ private static final char[] intToBase64 = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; /** @@ -99,11 +99,11 @@ private static String byteArrayToBase64(byte[] a, boolean alternate) { * designed for use in environments where "case folding" occurs. */ private static final char[] intToAltBase64 = { - '!', '"', '#', '$', '%', '&', '\'', '(', ')', ',', '-', '.', ':', - ';', '<', '>', '@', '[', ']', '^', '`', '_', '{', '|', '}', '~', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '?' + '!', '"', '#', '$', '%', '&', '\'', '(', ')', ',', '-', '.', ':', + ';', '<', '>', '@', '[', ']', '^', '`', '_', '{', '|', '}', '~', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '?' }; /** @@ -111,7 +111,7 @@ private static String byteArrayToBase64(byte[] a, boolean alternate) { * into a byte array. * * @throws IllegalArgumentException if s is not a valid Base64 - * string. + * string. */ public static byte[] base64ToByteArray(String s) { return base64ToByteArray(s, false); @@ -122,35 +122,35 @@ public static byte[] base64ToByteArray(String s) { * into a byte array. * * @throws IllegalArgumentException or ArrayOutOfBoundsException - * if s is not a valid alternate representation - * Base64 string. + * if s is not a valid alternate representation + * Base64 string. */ public static byte[] altBase64ToByteArray(String s) { return base64ToByteArray(s, true); } private static byte[] base64ToByteArray(String s, boolean alternate) { - byte[] alphaToInt = alternate ? altBase64ToInt : base64ToInt; + byte[] alphaToInt = alternate ? altBase64ToInt : base64ToInt; int sLen = s.length(); - int numGroups = sLen/4; - if (4*numGroups != sLen) + int numGroups = sLen / 4; + if (4 * numGroups != sLen) throw new IllegalArgumentException( - "String length must be a multiple of four."); + "String length must be a multiple of four."); int missingBytesInLastGroup = 0; int numFullGroups = numGroups; if (sLen != 0) { - if (s.charAt(sLen-1) == '=') { + if (s.charAt(sLen - 1) == '=') { missingBytesInLastGroup++; numFullGroups--; } - if (s.charAt(sLen-2) == '=') + if (s.charAt(sLen - 2) == '=') missingBytesInLastGroup++; } - byte[] result = new byte[3*numGroups - missingBytesInLastGroup]; + byte[] result = new byte[3 * numGroups - missingBytesInLastGroup]; // Translate all full groups from base64 to byte array elements int inCursor = 0, outCursor = 0; - for (int i=0; i * Client code is not supposed to use this class. - * + * * @author srt * @version $Id$ */ -public class DateUtil -{ +public class DateUtil { private static final String DATE_TIME_PATTERN = "yy-MM-dd HH:mm:ss"; private static Date currentDate; - private DateUtil() - { + private DateUtil() { // hide constructor } /** * If set to a non null value uses the date given as current date on calls * to getDate(). Set to null to restore the normal behavior. - * + * * @param currentDate the date to return on calls to getDate() or - * null to return the real current date. + * null to return the real current date. */ - public static void overrideCurrentDate(Date currentDate) - { + public static void overrideCurrentDate(Date currentDate) { DateUtil.currentDate = currentDate; } /** * Returns the real current date or the date set with overrideCurrentDate(). - * + * * @return the real current date or the date set with overrideCurrentDate(). */ - public static Date getDate() - { - if (currentDate == null) - { + public static Date getDate() { + if (currentDate == null) { return new Date(); } return currentDate; @@ -72,46 +67,39 @@ public static Date getDate() /** * Converts a date in the form of "yy-MM-dd HH:mm:ss" to a Date object using * the default time zone. - * + * * @param s date string in the form of "yy-MM-dd HH:mm:ss" * @return the corresponding Java date object or null if it is - * not parsable. + * not parsable. */ - public static Date parseDateTime(String s) - { + public static Date parseDateTime(String s) { return parseDateTime(s, null); } /** * Converts a date in the form of "yy-MM-dd HH:mm:ss" to a Date object using * the given time zone. - * - * @param s date string in the form of "yy-MM-dd HH:mm:ss" + * + * @param s date string in the form of "yy-MM-dd HH:mm:ss" * @param tz the timezone to use or null for the default time - * zone. + * zone. * @return the corresponding Java date object or null if it is - * not parsable. + * not parsable. */ - public static Date parseDateTime(String s, TimeZone tz) - { + public static Date parseDateTime(String s, TimeZone tz) { DateFormat df; - if (s == null) - { + if (s == null) { return null; } df = new SimpleDateFormat(DATE_TIME_PATTERN); - if (tz != null) - { + if (tz != null) { df.setTimeZone(tz); } - try - { + try { return df.parse(s); - } - catch (ParseException e) - { + } catch (ParseException e) { return null; } } diff --git a/src/main/java/org/asteriskjava/util/Log.java b/src/main/java/org/asteriskjava/util/Log.java index 8084e60c0..dc2992ca7 100644 --- a/src/main/java/org/asteriskjava/util/Log.java +++ b/src/main/java/org/asteriskjava/util/Log.java @@ -21,12 +21,11 @@ *

    * Concrete instances of this interface are obtained by calling * {@link org.asteriskjava.util.LogFactory#getLog(Class)}. - * + * * @author srt * @see org.asteriskjava.util.LogFactory */ -public interface Log -{ +public interface Log { void debug(Object obj); void info(Object obj); diff --git a/src/main/java/org/asteriskjava/util/LogFactory.java b/src/main/java/org/asteriskjava/util/LogFactory.java index 300c905a7..b8d23004e 100644 --- a/src/main/java/org/asteriskjava/util/LogFactory.java +++ b/src/main/java/org/asteriskjava/util/LogFactory.java @@ -26,119 +26,96 @@ *

    * If you want to reuse Asterisk-Java's logging abstraction layer add a private * attribute to your class like this: - * + * *

      * private final Log logger = LogFactory.getLog(getClass());
      * 
    - * + *

    * and then use the methods defined in {@link org.asteriskjava.util.Log}: - * + * *

      * logger.error("Unable to create new instance of " + eventClass, ex);
      * 
    - * + *

    * Asterisk-Java's logging abstraction layer uses log4j when available and falls * back to java.util.logging otherwise. * * @author srt * @version $Id$ */ -public final class LogFactory -{ - private static Boolean slf4jLoggingAvailable = null; +public final class LogFactory { + private static Boolean slf4jLoggingAvailable = null; - /** - * Indicates if log4j is available on the classpath or not. If the check has - * not yet performed this is null. - */ - private static Boolean log4jLoggingAvailable = null; + /** + * Indicates if log4j is available on the classpath or not. If the check has + * not yet performed this is null. + */ + private static Boolean log4jLoggingAvailable = null; - /** - * Indicates if java.util.logging is available on the classpath or not. If - * the check has not yet performed this is null. - */ - private static Boolean javaLoggingAvailable = null; + /** + * Indicates if java.util.logging is available on the classpath or not. If + * the check has not yet performed this is null. + */ + private static Boolean javaLoggingAvailable = null; - private static ClassLoader classLoader = LogFactory.class.getClassLoader(); + private static ClassLoader classLoader = LogFactory.class.getClassLoader(); - private LogFactory() - { + private LogFactory() { - } + } - public static void setClassLoader(ClassLoader classLoader) - { - LogFactory.classLoader = classLoader; - } + public static void setClassLoader(ClassLoader classLoader) { + LogFactory.classLoader = classLoader; + } - /** - * Returns an instance of Log suitable for logging from the given class. - * - * @param clazz - * the class to create the logger for. - * @return the created logger. - */ - public synchronized static Log getLog(Class clazz) - { - if (slf4jLoggingAvailable == null) - { - try - { - classLoader.loadClass("org.slf4j.Logger"); - slf4jLoggingAvailable = Boolean.TRUE; - } - catch (Exception e) - { - slf4jLoggingAvailable = Boolean.FALSE; - } - } + /** + * Returns an instance of Log suitable for logging from the given class. + * + * @param clazz the class to create the logger for. + * @return the created logger. + */ + public synchronized static Log getLog(Class clazz) { + if (slf4jLoggingAvailable == null) { + try { + classLoader.loadClass("org.slf4j.Logger"); + slf4jLoggingAvailable = Boolean.TRUE; + } catch (Exception e) { + slf4jLoggingAvailable = Boolean.FALSE; + } + } - if (slf4jLoggingAvailable) - { - try - { - return new Slf4JLogger(clazz); - } - catch (Throwable e) - { - slf4jLoggingAvailable = Boolean.FALSE; - } - } + if (slf4jLoggingAvailable) { + try { + return new Slf4JLogger(clazz); + } catch (Throwable e) { + slf4jLoggingAvailable = Boolean.FALSE; + } + } - if (log4jLoggingAvailable == null) - { - try - { - classLoader.loadClass("org.apache.logging.log4j.Logger"); - log4jLoggingAvailable = Boolean.TRUE; - } - catch (Exception e) - { - log4jLoggingAvailable = Boolean.FALSE; - } - } + if (log4jLoggingAvailable == null) { + try { + classLoader.loadClass("org.apache.logging.log4j.Logger"); + log4jLoggingAvailable = Boolean.TRUE; + } catch (Exception e) { + log4jLoggingAvailable = Boolean.FALSE; + } + } - if (log4jLoggingAvailable) - { - return new Log4JLogger(clazz); - } + if (log4jLoggingAvailable) { + return new Log4JLogger(clazz); + } - if (javaLoggingAvailable == null) - { - try - { - classLoader.loadClass("java.util.logging.Logger"); - javaLoggingAvailable = Boolean.TRUE; - } - catch (Exception e) - { - javaLoggingAvailable = Boolean.FALSE; - } - } - if (javaLoggingAvailable) - { - return new JavaLoggingLog(clazz); - } - return new NullLog(); - } + if (javaLoggingAvailable == null) { + try { + classLoader.loadClass("java.util.logging.Logger"); + javaLoggingAvailable = Boolean.TRUE; + } catch (Exception e) { + javaLoggingAvailable = Boolean.FALSE; + } + } + if (javaLoggingAvailable) { + return new JavaLoggingLog(clazz); + } + return new NullLog(); + } } diff --git a/src/main/java/org/asteriskjava/util/MixMonitorDirection.java b/src/main/java/org/asteriskjava/util/MixMonitorDirection.java index 58a520155..93866ea93 100644 --- a/src/main/java/org/asteriskjava/util/MixMonitorDirection.java +++ b/src/main/java/org/asteriskjava/util/MixMonitorDirection.java @@ -3,28 +3,24 @@ /** * MixMonitorDirection Which part of the recording to mute: read, write or both * (from channel, to channel or both channels). - * + * * @author adrian.videanu */ -public enum MixMonitorDirection -{ +public enum MixMonitorDirection { FROM_CHANNEL("read"), TO_CHANNEL("write"), BOTH("both"); String stateName; - MixMonitorDirection(String name) - { + MixMonitorDirection(String name) { this.stateName = name; } - public String getStateName() - { + public String getStateName() { return stateName; } - public void setStateName(String stateName) - { + public void setStateName(String stateName) { this.stateName = stateName; } diff --git a/src/main/java/org/asteriskjava/util/ReflectionUtil.java b/src/main/java/org/asteriskjava/util/ReflectionUtil.java index 68e563033..0dfc844e0 100644 --- a/src/main/java/org/asteriskjava/util/ReflectionUtil.java +++ b/src/main/java/org/asteriskjava/util/ReflectionUtil.java @@ -26,13 +26,7 @@ import java.net.URISyntaxException; import java.net.URL; import java.net.URLDecoder; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -45,10 +39,8 @@ * * @author srt */ -public class ReflectionUtil -{ - private ReflectionUtil() - { +public class ReflectionUtil { + private ReflectionUtil() { // hide constructor } @@ -63,33 +55,26 @@ private ReflectionUtil() * @param clazz the class to return the getters for * @return a Map of attributes and their accessor methods (getters) */ - public static Map getGetters(final Class< ? > clazz) - { + public static Map getGetters(final Class clazz) { final Map accessors = new HashMap<>(); final Method[] methods = clazz.getMethods(); - for (Method method : methods) - { + for (Method method : methods) { String name = null; String methodName = method.getName(); - if (methodName.startsWith("get")) - { + if (methodName.startsWith("get")) { name = methodName.substring(3); - } - else if (methodName.startsWith("is")) - { + } else if (methodName.startsWith("is")) { name = methodName.substring(2); } - if (name == null || name.length() == 0) - { + if (name == null || name.length() == 0) { continue; } // skip methods with != 0 parameters - if (method.getParameterTypes().length != 0) - { + if (method.getParameterTypes().length != 0) { continue; } @@ -99,7 +84,7 @@ else if (methodName.startsWith("is")) return accessors; } - private final static ConcurrentHashMap, Map> setterMap = new ConcurrentHashMap<>(); + private final static ConcurrentHashMap, Map> setterMap = new ConcurrentHashMap<>(); /** * The main benefit here is that there will not be repeated errors when @@ -113,8 +98,7 @@ else if (methodName.startsWith("is")) * @param clazz * @return */ - public static Map getSetters(Class< ? > clazz) - { + public static Map getSetters(Class clazz) { return setterMap.computeIfAbsent(clazz, (c) -> { return getSettersInternal(c); }); @@ -131,23 +115,19 @@ public static Map getSetters(Class< ? > clazz) * @param clazz the class to return the setters for * @return a Map of attributes and their accessor methods (setters) */ - private static Map getSettersInternal(Class< ? > clazz) - { + private static Map getSettersInternal(Class clazz) { final Map accessors = new HashMap<>(); final Method[] methods = clazz.getMethods(); - for (Method method : methods) - { + for (Method method : methods) { String name; String methodName = method.getName(); - if (!methodName.startsWith("set")) - { + if (!methodName.startsWith("set")) { continue; } // skip methods with != 1 parameters - if (method.getParameterTypes().length != 1) - { + if (method.getParameterTypes().length != 1) { continue; } @@ -157,25 +137,19 @@ private static Map getSettersInternal(Class< ? > clazz) // if an event class implements a setter that exists in // ManagerEvent, then prefer the setter from the extending class Method existing = accessors.get(name); - if (existing != null) - { + if (existing != null) { logger.warn("multiple setters (case insensitive) exist for " + name + " on class(es) " + existing.getDeclaringClass() + " and " + method.getDeclaringClass()); } - if (existing == null) - { + if (existing == null) { // we don't have a mapping for this setter so add it. accessors.put(name, method); - } - else if (!method.getDeclaringClass().isAssignableFrom(existing.getDeclaringClass())) - { + } else if (!method.getDeclaringClass().isAssignableFrom(existing.getDeclaringClass())) { // we already have a mapping for this setter, but this one is // from an extending class so replace it. logger.warn("Preferring setter from extending class " + existing + " -> " + method); accessors.put(name, method); - } - else - { + } else { // there is already a mapping for this setter from class logger.warn("Preferring setter from extending class " + method + " -> " + existing); } @@ -191,50 +165,39 @@ else if (!method.getDeclaringClass().isAssignableFrom(existing.getDeclaringClass * @param s the original string * @return the string with all illegal characters stripped */ - public static String stripIllegalCharacters(String s) - { + public static String stripIllegalCharacters(String s) { char c; boolean needsStrip = false; StringBuilder sb; - if (s == null) - { + if (s == null) { return null; } - for (int i = 0; i < s.length(); i++) - { + for (int i = 0; i < s.length(); i++) { c = s.charAt(i); - if (c >= '0' && c <= '9') - { + if (c >= '0' && c <= '9') { // continue } // NOPMD - else if (c >= 'a' && c <= 'z') - { + else if (c >= 'a' && c <= 'z') { // continue } // NOPMD - else - { + else { needsStrip = true; break; } } - if (!needsStrip) - { + if (!needsStrip) { return s; } sb = new StringBuilder(s.length()); - for (int i = 0; i < s.length(); i++) - { + for (int i = 0; i < s.length(); i++) { c = s.charAt(i); - if (c >= '0' && c <= '9') - { + if (c >= '0' && c <= '9') { sb.append(c); - } - else if (c >= 'a' && c <= 'z') - { + } else if (c >= 'a' && c <= 'z') { sb.append(c); } } @@ -248,19 +211,15 @@ else if (c >= 'a' && c <= 'z') * * @param s fully qualified name of the class to check. * @return true if the class is available, false - * otherwise. + * otherwise. */ - public static boolean isClassAvailable(String s) - { + public static boolean isClassAvailable(String s) { final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - try - { + try { classLoader.loadClass(s); return true; - } - catch (ClassNotFoundException e) - { + } catch (ClassNotFoundException e) { return false; } } @@ -273,35 +232,23 @@ public static boolean isClassAvailable(String s) * @param s fully qualified name of the class to instantiate. * @return the new instance or null on failure. */ - public static Object newInstance(String s) - { + public static Object newInstance(String s) { final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - try - { - Class< ? > clazz = classLoader.loadClass(s); - Constructor< ? > constructor = clazz.getConstructor(); + try { + Class clazz = classLoader.loadClass(s); + Constructor constructor = clazz.getConstructor(); return constructor.newInstance(); - } - catch (ClassNotFoundException e) - { + } catch (ClassNotFoundException e) { return null; - } - catch (IllegalAccessException e) - { + } catch (IllegalAccessException e) { return null; - } - catch (InstantiationException e) - { + } catch (InstantiationException e) { return null; - } - catch (NoSuchMethodException e) - { + } catch (NoSuchMethodException e) { // no default constructor return null; - } - catch (InvocationTargetException e) - { + } catch (InvocationTargetException e) { // constructor threw an exception return null; } @@ -318,34 +265,25 @@ public static Object newInstance(String s) * @return */ @SuppressWarnings("unchecked") - public static Set> loadClasses(String packageName, Class baseClassOrInterface) - { + public static Set> loadClasses(String packageName, Class baseClassOrInterface) { Set> result = new HashSet<>(); - try - { + try { Set classNames = getClassNamesFromPackage(packageName); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - for (String className : classNames) - { - try - { - Class< ? > clazz = classLoader.loadClass(packageName + "." + className); - if (!Modifier.isAbstract(clazz.getModifiers()) && baseClassOrInterface.isAssignableFrom(clazz)) - { + for (String className : classNames) { + try { + Class clazz = classLoader.loadClass(packageName + "." + className); + if (!Modifier.isAbstract(clazz.getModifiers()) && baseClassOrInterface.isAssignableFrom(clazz)) { result.add((Class) clazz); } - } - catch (Throwable e) - { + } catch (Throwable e) { logger.error(e, e); } } logger.info("Loaded " + result.size()); - } - catch (Exception e) - { + } catch (Exception e) { logger.error(e, e); } @@ -361,8 +299,7 @@ public static Set> loadClasses(String packageName, Class baseCla * @throws IOException * @throws URISyntaxException */ - private static Set getClassNamesFromPackage(String packageName) throws IOException, URISyntaxException - { + private static Set getClassNamesFromPackage(String packageName) throws IOException, URISyntaxException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Enumeration packageURLs; Set names = new HashSet(); @@ -370,11 +307,9 @@ private static Set getClassNamesFromPackage(String packageName) throws I packageName = packageName.replace(".", "/"); packageURLs = classLoader.getResources(packageName); - while (packageURLs.hasMoreElements()) - { + while (packageURLs.hasMoreElements()) { URL packageURL = packageURLs.nextElement(); - if (packageURL.getProtocol().equals("jar")) - { + if (packageURL.getProtocol().equals("jar")) { String jarFileName; Enumeration jarEntries; @@ -384,14 +319,11 @@ private static Set getClassNamesFromPackage(String packageName) throws I jarFileName = URLDecoder.decode(packageURL.getFile(), "UTF-8"); jarFileName = jarFileName.substring(5, jarFileName.indexOf("!")); logger.info(">" + jarFileName); - try (JarFile jf = new JarFile(jarFileName);) - { + try (JarFile jf = new JarFile(jarFileName);) { jarEntries = jf.entries(); - while (jarEntries.hasMoreElements()) - { + while (jarEntries.hasMoreElements()) { entryName = jarEntries.nextElement().getName(); - if (entryName.startsWith(packageName) && entryName.endsWith(".class")) - { + if (entryName.startsWith(packageName) && entryName.endsWith(".class")) { entryName = entryName.substring(packageName.length() + 1, entryName.lastIndexOf('.')); names.add(entryName); } @@ -399,18 +331,14 @@ private static Set getClassNamesFromPackage(String packageName) throws I } // loop through files in classpath - } - else - { + } else { URI uri = new URI(packageURL.toString()); File folder = new File(uri.getPath()); // won't work with path which contains blank (%20) // File folder = new File(packageURL.getFile()); File[] files = folder.listFiles(); - if (files != null) - { - for (File actual : files) - { + if (files != null) { + for (File actual : files) { String entryName = actual.getName(); entryName = entryName.substring(0, entryName.lastIndexOf('.')); names.add(entryName); @@ -421,11 +349,9 @@ private static Set getClassNamesFromPackage(String packageName) throws I // clean up Iterator itr = names.iterator(); - while (itr.hasNext()) - { + while (itr.hasNext()) { String name = itr.next(); - if (name.equals("package") || name.endsWith(".") || name.length() == 0) - { + if (name.equals("package") || name.endsWith(".") || name.length() == 0) { itr.remove(); } } diff --git a/src/main/java/org/asteriskjava/util/ServerSocketFacade.java b/src/main/java/org/asteriskjava/util/ServerSocketFacade.java index c0fc5020b..f142ac96d 100644 --- a/src/main/java/org/asteriskjava/util/ServerSocketFacade.java +++ b/src/main/java/org/asteriskjava/util/ServerSocketFacade.java @@ -23,15 +23,14 @@ * TCP/IP sockets.

    * It hides the details of the underlying I/O system used for server socket * communication. - * + * * @author srt * @version $Id$ */ -public interface ServerSocketFacade -{ +public interface ServerSocketFacade { /** * Waits for a new incoming connection. - * + * * @return the new connection. * @throws IOException if an I/O error occurs when waiting for a connection. */ @@ -39,7 +38,7 @@ public interface ServerSocketFacade /** * Unbinds and closes the server socket. - * + * * @throws IOException if the server socket cannot be closed. */ void close() throws IOException; @@ -48,7 +47,7 @@ public interface ServerSocketFacade * Connection is dropped if it stales on read longer than the timeout. * * @param socketReadTimeout the read timeout value to be used in - * milliseconds. + * milliseconds. * @see java.net.Socket#setSoTimeout(int) * @since 3.0.0 */ diff --git a/src/main/java/org/asteriskjava/util/SocketConnectionFacade.java b/src/main/java/org/asteriskjava/util/SocketConnectionFacade.java index a383c253c..4169057be 100644 --- a/src/main/java/org/asteriskjava/util/SocketConnectionFacade.java +++ b/src/main/java/org/asteriskjava/util/SocketConnectionFacade.java @@ -24,19 +24,18 @@ * communication over TCP/IP sockets.

    * It hides the details of the underlying I/O system used for socket * communication. - * + * * @author srt * @version $Id$ */ -public interface SocketConnectionFacade -{ +public interface SocketConnectionFacade { /** * Reads a line of text from the socket connection. The current thread is * blocked until either the next line is received or an IOException * encounters.

    * Depending on the implementation different newline delimiters are used * ("\r\n" for the Manager API and "\n" for AGI). - * + * * @return the line of text received excluding the newline delimiter. * @throws IOException if the connection has been closed. */ @@ -44,17 +43,17 @@ public interface SocketConnectionFacade /** * Sends a given String to the socket connection. - * + * * @param s the String to send. * @throws IOException if the String cannot be sent, maybe because the - * connection has already been closed. + * connection has already been closed. */ void write(String s) throws IOException; /** * Flushes the socket connection by sending any buffered but yet unsent * data. - * + * * @throws IOException if the connection cannot be flushed. */ void flush() throws IOException; @@ -64,22 +63,22 @@ public interface SocketConnectionFacade * frees all associated ressources.

    * When calling close() any Thread currently blocked by a call to readLine() * will be unblocked and receive an IOException. - * + * * @throws IOException if the socket connection cannot be closed. */ void close() throws IOException; /** * Returns the connection state of the socket. - * + * * @return true if the socket successfuly connected to a - * server + * server */ boolean isConnected(); /** * Returns the local address this socket connection. - * + * * @return the local address this socket connection. * @since 0.2 */ @@ -87,7 +86,7 @@ public interface SocketConnectionFacade /** * Returns the local port of this socket connection. - * + * * @return the local port of this socket connection. * @since 0.2 */ @@ -95,7 +94,7 @@ public interface SocketConnectionFacade /** * Returns the remote address of this socket connection. - * + * * @return the remote address of this socket connection. * @since 0.2 */ @@ -103,7 +102,7 @@ public interface SocketConnectionFacade /** * Returns the remote port of this socket connection. - * + * * @return the remote port of this socket connection. * @since 0.2 */ diff --git a/src/main/java/org/asteriskjava/util/internal/FileTrace.java b/src/main/java/org/asteriskjava/util/internal/FileTrace.java index 36aa210dd..9fd442998 100644 --- a/src/main/java/org/asteriskjava/util/internal/FileTrace.java +++ b/src/main/java/org/asteriskjava/util/internal/FileTrace.java @@ -1,5 +1,9 @@ package org.asteriskjava.util.internal; +import org.asteriskjava.util.DateUtil; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; @@ -12,15 +16,10 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; -import org.asteriskjava.util.DateUtil; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; - /** * Writes a trace file to the file system. */ -public class FileTrace implements Trace -{ +public class FileTrace implements Trace { public static final String TRACE_DIRECTORY_PROPERTY = "org.asteriskjava.trace.directory"; protected static final String FILE_PREFIX = "aj-trace"; protected static final String FILE_SUFFIX = ".txt"; @@ -34,15 +33,13 @@ public class FileTrace implements Trace private boolean exceptionLogged = false; private RandomAccessFile randomAccessFile; - public FileTrace(Socket socket) throws IOException - { + public FileTrace(Socket socket) throws IOException { randomAccessFile = new RandomAccessFile(getFile(socket), "rw"); channel = randomAccessFile.getChannel(); print(getHeader(socket)); } - private String getHeader(Socket socket) - { + private String getHeader(Socket socket) { final StringBuilder sb = new StringBuilder(); sb.append("Local: "); sb.append(socket.getLocalAddress()); @@ -59,8 +56,7 @@ private String getHeader(Socket socket) return sb.toString(); } - private File getFile(Socket socket) - { + private File getFile(Socket socket) { final String directory = System.getProperty(TRACE_DIRECTORY_PROPERTY, System.getProperty("java.io.tmpdir")); final String fileName = getFileName(socket); @@ -68,8 +64,7 @@ private File getFile(Socket socket) return new File(directory, fileName); } - private String getFileName(Socket socket) - { + private String getFileName(Socket socket) { final StringBuilder sb = new StringBuilder(FILE_PREFIX); sb.append("_"); sb.append(df.format(DateUtil.getDate())); @@ -85,50 +80,37 @@ private String getFileName(Socket socket) return sb.toString(); } - public synchronized void received(String s) - { - try - { + public synchronized void received(String s) { + try { print(format("<<< ", s)); - } - catch (IOException e) - { + } catch (IOException e) { logException(e); } } - public synchronized void sent(String s) - { - try - { + public synchronized void sent(String s) { + try { print(format(">>> ", s)); - } - catch (IOException e) - { + } catch (IOException e) { logException(e); } } - private void logException(IOException e) - { + private void logException(IOException e) { // avoid excessive failure logging - if (exceptionLogged) - { + if (exceptionLogged) { return; } logger.warn("Unable to write trace to disk", e); exceptionLogged = true; } - protected String format(String prefix, String s) - { + protected String format(String prefix, String s) { final StringBuilder sb = new StringBuilder(df.format(DateUtil.getDate())); final String filler = String.format("%" + sb.length() + "s", ""); String[] lines = s.split("\n"); - for (int i = 0; i < lines.length; i++) - { - if (i != 0) - { + for (int i = 0; i < lines.length; i++) { + if (i != 0) { sb.append(filler); } sb.append(" "); @@ -139,36 +121,28 @@ protected String format(String prefix, String s) return sb.toString(); } - protected void print(String s) throws IOException - { + protected void print(String s) throws IOException { final CharBuffer charBuffer = CharBuffer.allocate(s.length()); charBuffer.put(s); charBuffer.flip(); print(charset.encode(charBuffer)); } - private void print(ByteBuffer byteBuffer) throws IOException - { + private void print(ByteBuffer byteBuffer) throws IOException { int bytesWritten = 0; - while (bytesWritten < byteBuffer.remaining()) - { + while (bytesWritten < byteBuffer.remaining()) { // Loop if only part of the buffer contents get written. bytesWritten = channel.write(byteBuffer); - if (bytesWritten == 0) - { + if (bytesWritten == 0) { throw new IOException("Unable to write trace to channel. Media may be full."); } } } - public void close() - { - try - { + public void close() { + try { randomAccessFile.close(); - } - catch (IOException e) - { + } catch (IOException e) { logException(e); } } diff --git a/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java b/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java index 61b1f3448..7cf742460 100644 --- a/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java +++ b/src/main/java/org/asteriskjava/util/internal/JavaLoggingLog.java @@ -17,21 +17,20 @@ package org.asteriskjava.util.internal; +import org.asteriskjava.util.Log; + import java.util.logging.Level; import java.util.logging.Logger; -import org.asteriskjava.util.Log; - /** * Implementation of {@link Log} that maps to the Logger of the * java.util.logging package. *

    * Kindly donated by Sun's Steve Drach. - * + * * @author drach */ -public class JavaLoggingLog implements Log -{ +public class JavaLoggingLog implements Log { /** * The underlying commons-logging Log object to use. */ @@ -40,104 +39,77 @@ public class JavaLoggingLog implements Log /** * Creates a new JavaLoggingLog obtained from java.util.logging for the * given class. - * + * * @param clazz the class to log for. */ - public JavaLoggingLog(Class< ? > clazz) - { + public JavaLoggingLog(Class clazz) { log = Logger.getLogger(clazz.getName()); } - public void debug(Object obj) - { + public void debug(Object obj) { StackTraceElement ste = getInvokerSTE(); - if (ste != null) - { + if (ste != null) { log.logp(Level.FINE, ste.getClassName(), ste.getMethodName(), obj.toString()); - } - else - { + } else { log.fine(obj.toString()); } } - public void info(Object obj) - { + public void info(Object obj) { StackTraceElement ste = getInvokerSTE(); - if (ste != null) - { + if (ste != null) { log.logp(Level.INFO, ste.getClassName(), ste.getMethodName(), obj.toString()); - } - else - { + } else { log.info(obj.toString()); } } - public void warn(Object obj) - { + public void warn(Object obj) { StackTraceElement ste = getInvokerSTE(); - if (ste != null) - { + if (ste != null) { log.logp(Level.WARNING, ste.getClassName(), ste.getMethodName(), obj.toString()); - } - else - { + } else { log.warning(obj.toString()); } } - public void warn(Object obj, Throwable ex) - { + public void warn(Object obj, Throwable ex) { StackTraceElement ste = getInvokerSTE(); - if (ste != null) - { + if (ste != null) { log.logp(Level.WARNING, ste.getClassName(), ste.getMethodName(), obj.toString(), ex); - } - else - { + } else { log.log(Level.WARNING, obj.toString(), ex); } } - public void error(Object obj) - { + public void error(Object obj) { StackTraceElement ste = getInvokerSTE(); - if (ste != null) - { + if (ste != null) { log.logp(Level.SEVERE, ste.getClassName(), ste.getMethodName(), obj.toString()); - } - else - { + } else { log.severe(obj.toString()); } } - public void error(Object obj, Throwable ex) - { + public void error(Object obj, Throwable ex) { StackTraceElement ste = getInvokerSTE(); - if (ste != null) - { + if (ste != null) { log.logp(Level.SEVERE, ste.getClassName(), ste.getMethodName(), obj.toString(), ex); - } - else - { + } else { log.log(Level.SEVERE, obj.toString(), ex); } } - private StackTraceElement getInvokerSTE() - { + private StackTraceElement getInvokerSTE() { StackTraceElement[] stack = (new Throwable()).getStackTrace(); - if (stack.length > 2) - { + if (stack.length > 2) { return stack[2]; } @@ -145,22 +117,17 @@ private StackTraceElement getInvokerSTE() } @Override - public boolean isDebugEnabled() - { + public boolean isDebugEnabled() { return log.isLoggable(Level.FINE); } @Override - public void debug(Object e, Throwable e2) - { + public void debug(Object e, Throwable e2) { StackTraceElement ste = getInvokerSTE(); - if (ste != null) - { + if (ste != null) { log.logp(Level.FINE, ste.getClassName(), ste.getMethodName(), e.toString(), e2); - } - else - { + } else { log.log(Level.FINE, e.toString(), e2); } } diff --git a/src/main/java/org/asteriskjava/util/internal/LocationAwareWrapper.java b/src/main/java/org/asteriskjava/util/internal/LocationAwareWrapper.java index 33a7c03cf..3bd3df9b7 100644 --- a/src/main/java/org/asteriskjava/util/internal/LocationAwareWrapper.java +++ b/src/main/java/org/asteriskjava/util/internal/LocationAwareWrapper.java @@ -4,430 +4,367 @@ import org.slf4j.Marker; import org.slf4j.spi.LocationAwareLogger; -public class LocationAwareWrapper implements Logger -{ +public class LocationAwareWrapper implements Logger { private String FQCN; private LocationAwareLogger logger; - public LocationAwareWrapper(String FQCN, LocationAwareLogger logger) - { + public LocationAwareWrapper(String FQCN, LocationAwareLogger logger) { this.FQCN = FQCN; this.logger = logger; } @Override - public String getName() - { + public String getName() { return logger.getName(); } @Override - public boolean isTraceEnabled() - { + public boolean isTraceEnabled() { return logger.isTraceEnabled(); } @Override - public void trace(String msg) - { + public void trace(String msg) { logger.log(null, FQCN, LocationAwareLogger.TRACE_INT, msg, null, null); } @Override - public void trace(String format, Object arg) - { + public void trace(String format, Object arg) { logger.trace(format, arg); } @Override - public void trace(String format, Object arg1, Object arg2) - { + public void trace(String format, Object arg1, Object arg2) { logger.trace(format, arg1, arg2); } @Override - public void trace(String format, Object... arguments) - { + public void trace(String format, Object... arguments) { logger.trace(format, arguments); } @Override - public void trace(String msg, Throwable t) - { + public void trace(String msg, Throwable t) { logger.log(null, FQCN, LocationAwareLogger.TRACE_INT, msg, null, t); } @Override - public boolean isTraceEnabled(Marker marker) - { + public boolean isTraceEnabled(Marker marker) { return logger.isTraceEnabled(marker); } @Override - public void trace(Marker marker, String msg) - { + public void trace(Marker marker, String msg) { logger.log(marker, FQCN, LocationAwareLogger.TRACE_INT, msg, null, null); } @Override - public void trace(Marker marker, String format, Object arg) - { + public void trace(Marker marker, String format, Object arg) { logger.trace(marker, format, arg); } @Override - public void trace(Marker marker, String format, Object arg1, Object arg2) - { + public void trace(Marker marker, String format, Object arg1, Object arg2) { logger.trace(marker, format, arg1, arg2); } @Override - public void trace(Marker marker, String format, Object... arguments) - { + public void trace(Marker marker, String format, Object... arguments) { logger.trace(marker, format, arguments); } @Override - public void trace(Marker marker, String msg, Throwable t) - { + public void trace(Marker marker, String msg, Throwable t) { logger.log(marker, FQCN, LocationAwareLogger.TRACE_INT, msg, null, t); } @Override - public boolean isDebugEnabled() - { + public boolean isDebugEnabled() { return logger.isDebugEnabled(); } @Override - public void debug(String msg) - { + public void debug(String msg) { logger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, msg, null, null); } @Override - public void debug(String format, Object arg) - { + public void debug(String format, Object arg) { logger.debug(format, arg); } @Override - public void debug(String format, Object arg1, Object arg2) - { + public void debug(String format, Object arg1, Object arg2) { logger.debug(format, arg1, arg2); } @Override - public void debug(String format, Object... arguments) - { + public void debug(String format, Object... arguments) { logger.debug(format, arguments); } @Override - public void debug(String msg, Throwable t) - { + public void debug(String msg, Throwable t) { logger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, msg, null, t); } @Override - public boolean isDebugEnabled(Marker marker) - { + public boolean isDebugEnabled(Marker marker) { return logger.isDebugEnabled(marker); } @Override - public void debug(Marker marker, String msg) - { + public void debug(Marker marker, String msg) { logger.log(marker, FQCN, LocationAwareLogger.DEBUG_INT, msg, null, null); } @Override - public void debug(Marker marker, String format, Object arg) - { + public void debug(Marker marker, String format, Object arg) { logger.debug(marker, format, arg); } @Override - public void debug(Marker marker, String format, Object arg1, Object arg2) - { + public void debug(Marker marker, String format, Object arg1, Object arg2) { logger.debug(marker, format, arg1, arg2); } @Override - public void debug(Marker marker, String format, Object... arguments) - { + public void debug(Marker marker, String format, Object... arguments) { logger.debug(marker, format, arguments); } @Override - public void debug(Marker marker, String msg, Throwable t) - { + public void debug(Marker marker, String msg, Throwable t) { logger.log(marker, FQCN, LocationAwareLogger.DEBUG_INT, msg, null, t); } @Override - public boolean isInfoEnabled() - { + public boolean isInfoEnabled() { return logger.isInfoEnabled(); } @Override - public void info(String msg) - { + public void info(String msg) { logger.log(null, FQCN, LocationAwareLogger.INFO_INT, msg, null, null); } @Override - public void info(String format, Object arg) - { + public void info(String format, Object arg) { logger.info(format, arg); } @Override - public void info(String format, Object arg1, Object arg2) - { + public void info(String format, Object arg1, Object arg2) { logger.info(format, arg1, arg2); } @Override - public void info(String format, Object... arguments) - { + public void info(String format, Object... arguments) { logger.info(format, arguments); } @Override - public void info(String msg, Throwable t) - { + public void info(String msg, Throwable t) { logger.log(null, FQCN, LocationAwareLogger.INFO_INT, msg, null, t); } @Override - public boolean isInfoEnabled(Marker marker) - { + public boolean isInfoEnabled(Marker marker) { return logger.isInfoEnabled(marker); } @Override - public void info(Marker marker, String msg) - { + public void info(Marker marker, String msg) { logger.log(marker, FQCN, LocationAwareLogger.INFO_INT, msg, null, null); } @Override - public void info(Marker marker, String format, Object arg) - { + public void info(Marker marker, String format, Object arg) { logger.info(marker, format, arg); } @Override - public void info(Marker marker, String format, Object arg1, Object arg2) - { + public void info(Marker marker, String format, Object arg1, Object arg2) { logger.info(marker, format, arg1, arg2); } @Override - public void info(Marker marker, String format, Object... arguments) - { + public void info(Marker marker, String format, Object... arguments) { logger.info(marker, format, arguments); } @Override - public void info(Marker marker, String msg, Throwable t) - { + public void info(Marker marker, String msg, Throwable t) { logger.log(marker, FQCN, LocationAwareLogger.INFO_INT, msg, null, t); } @Override - public boolean isWarnEnabled() - { + public boolean isWarnEnabled() { return logger.isWarnEnabled(); } @Override - public void warn(String msg) - { + public void warn(String msg) { logger.log(null, FQCN, LocationAwareLogger.WARN_INT, msg, null, null); } @Override - public void warn(String format, Object arg) - { + public void warn(String format, Object arg) { logger.warn(format, arg); } @Override - public void warn(String format, Object arg1, Object arg2) - { + public void warn(String format, Object arg1, Object arg2) { logger.warn(format, arg1, arg2); } @Override - public void warn(String format, Object... arguments) - { + public void warn(String format, Object... arguments) { logger.warn(format, arguments); } @Override - public void warn(String msg, Throwable t) - { + public void warn(String msg, Throwable t) { logger.log(null, FQCN, LocationAwareLogger.WARN_INT, msg, null, t); } @Override - public boolean isWarnEnabled(Marker marker) - { + public boolean isWarnEnabled(Marker marker) { return logger.isWarnEnabled(marker); } @Override - public void warn(Marker marker, String msg) - { + public void warn(Marker marker, String msg) { logger.log(marker, FQCN, LocationAwareLogger.WARN_INT, msg, null, null); } @Override - public void warn(Marker marker, String format, Object arg) - { + public void warn(Marker marker, String format, Object arg) { logger.warn(marker, format, arg); } @Override - public void warn(Marker marker, String format, Object arg1, Object arg2) - { + public void warn(Marker marker, String format, Object arg1, Object arg2) { logger.warn(marker, format, arg1, arg2); } @Override - public void warn(Marker marker, String format, Object... arguments) - { + public void warn(Marker marker, String format, Object... arguments) { logger.warn(marker, format, arguments); } @Override - public void warn(Marker marker, String msg, Throwable t) - { + public void warn(Marker marker, String msg, Throwable t) { logger.log(marker, FQCN, LocationAwareLogger.WARN_INT, msg, null, t); } @Override - public boolean isErrorEnabled() - { + public boolean isErrorEnabled() { return logger.isErrorEnabled(); } @Override - public void error(String msg) - { + public void error(String msg) { logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, msg, null, null); } @Override - public void error(String format, Object arg) - { + public void error(String format, Object arg) { logger.error(format, arg); } @Override - public void error(String format, Object arg1, Object arg2) - { + public void error(String format, Object arg1, Object arg2) { logger.error(format, arg1, arg2); } @Override - public void error(String format, Object... arguments) - { + public void error(String format, Object... arguments) { logger.error(format, arguments); } @Override - public void error(String msg, Throwable t) - { + public void error(String msg, Throwable t) { logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, msg, null, t); } @Override - public boolean isErrorEnabled(Marker marker) - { + public boolean isErrorEnabled(Marker marker) { return logger.isErrorEnabled(marker); } @Override - public void error(Marker marker, String msg) - { + public void error(Marker marker, String msg) { logger.log(marker, FQCN, LocationAwareLogger.ERROR_INT, msg, null, null); } @Override - public void error(Marker marker, String format, Object arg) - { + public void error(Marker marker, String format, Object arg) { logger.error(marker, format, arg); } @Override - public void error(Marker marker, String format, Object arg1, Object arg2) - { + public void error(Marker marker, String format, Object arg1, Object arg2) { logger.error(marker, format, arg1, arg2); } @Override - public void error(Marker marker, String format, Object... arguments) - { + public void error(Marker marker, String format, Object... arguments) { logger.error(marker, format, arguments); } @Override - public void error(Marker marker, String msg, Throwable t) - { + public void error(Marker marker, String msg, Throwable t) { logger.log(marker, FQCN, LocationAwareLogger.ERROR_INT, msg, null, t); } diff --git a/src/main/java/org/asteriskjava/util/internal/Log4JLogger.java b/src/main/java/org/asteriskjava/util/internal/Log4JLogger.java index 97775a2b6..d9ea34c9b 100644 --- a/src/main/java/org/asteriskjava/util/internal/Log4JLogger.java +++ b/src/main/java/org/asteriskjava/util/internal/Log4JLogger.java @@ -1,12 +1,12 @@ /* * 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. @@ -16,14 +16,14 @@ package org.asteriskjava.util.internal; -import java.io.Serializable; - import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.spi.AbstractLogger; import org.asteriskjava.util.Log; +import java.io.Serializable; + /** * Implementation of {@link Log} that maps directly to a Log4J * Logger. @@ -32,207 +32,190 @@ * the usual manner, as outlined in the Log4J documentation. *

    * More or less "stolen" from Apache's commons-logging. - * + * * @author Scott Sanders * @author Rod Waldhoff * @author Robert Burrell Donkin * @version $Id$ */ -public class Log4JLogger implements Log, Serializable -{ - - // ------------------------------------------------------------- Attributes - - /** - * The serial version identifier. - */ - private static final long serialVersionUID = 3545240215095883829L; - - /** The fully qualified name of the Log4JLogger class. */ - private static final String FQCN = Log4JLogger.class.getName(); - - /** Log to this logger */ - private transient final AbstractLogger logger; - - /** - * Base constructor. - */ - public Log4JLogger(Class clazz) - { - this.logger = (AbstractLogger) LogManager.getLogger(clazz.getName()); - } - - // --------------------------------------------------------- Implementation - - /** - * Log a message to the Log4j Logger with TRACE priority. - * Currently logs to DEBUG level in Log4J. - */ - public void trace(Object message) - { - logger.logIfEnabled(FQCN, Level.TRACE, null, message, (Throwable) null); - } - - /** - * Log an error to the Log4j Logger with TRACE priority. - * Currently logs to DEBUG level in Log4J. - */ - public void trace(Object message, Throwable t) - { - logger.logIfEnabled(FQCN, Level.TRACE, null, message, t); - } - - /** - * Log a message to the Log4j Logger with DEBUG priority. - */ - @Override - public void debug(Object message) - { - logger.logIfEnabled(FQCN, Level.DEBUG, null, message, (Throwable) null); - } - - /** - * Log an error to the Log4j Logger with DEBUG priority. - */ - @Override - public void debug(Object message, Throwable t) - { - logger.logIfEnabled(FQCN, Level.DEBUG, null, message, t); - } - - /** - * Log a message to the Log4j Logger with INFO priority. - */ - @Override - public void info(Object message) - { - logger.logIfEnabled(FQCN, Level.INFO, null, message, (Throwable) null); - - } - - /** - * Log an error to the Log4j Logger with INFO priority. - */ - public void info(Object message, Throwable t) - { - logger.logIfEnabled(FQCN, Level.INFO, null, message, t); - } - - /** - * Log a message to the Log4j Logger with WARN priority. - */ - @Override - public void warn(Object message) - { - logger.logIfEnabled(FQCN, Level.WARN, null, message, (Throwable) null); - } - - /** - * Log an error to the Log4j Logger with WARN priority. - */ - @Override - public void warn(Object message, Throwable t) - { - logger.logIfEnabled(FQCN, Level.WARN, null, message, t); - } - - /** - * Log a message to the Log4j Logger with ERROR priority. - */ - @Override - public void error(Object message) - { - logger.logIfEnabled(FQCN, Level.ERROR, null, message, (Throwable) null); - } - - /** - * Log an error to the Log4j Logger with ERROR priority. - */ - @Override - public void error(Object message, Throwable t) - { - logger.logIfEnabled(FQCN, Level.ERROR, null, message, t); - } - - /** - * Log a message to the Log4j Logger with FATAL priority. - */ - public void fatal(Object message) - { - logger.logIfEnabled(FQCN, Level.FATAL, null, message, (Throwable) null); - } - - /** - * Log an error to the Log4j Logger with FATAL priority. - */ - public void fatal(Object message, Throwable t) - { - logger.logIfEnabled(FQCN, Level.FATAL, null, message, t); - } - - /** - * Return the native Logger instance we are using. - */ - public final Logger getLogger() - { - return logger; - } - - /** - * Check whether the Log4j Logger used is enabled for DEBUG - * priority. - */ - @Override - public boolean isDebugEnabled() - { - return logger.isDebugEnabled(); - } - - /** - * Check whether the Log4j Logger used is enabled for ERROR - * priority. - */ - public boolean isErrorEnabled() - { - return logger.isErrorEnabled(); - - } - - /** - * Check whether the Log4j Logger used is enabled for FATAL - * priority. - */ - public boolean isFatalEnabled() - { - return logger.isFatalEnabled(); - - } - - /** - * Check whether the Log4j Logger used is enabled for INFO - * priority. - */ - public boolean isInfoEnabled() - { - return logger.isInfoEnabled(); - } - - /** - * Check whether the Log4j Logger used is enabled for TRACE - * priority. For Log4J, this returns the value of - * isDebugEnabled() - */ - public boolean isTraceEnabled() - { - return logger.isDebugEnabled(); - } - - /** - * Check whether the Log4j Logger used is enabled for WARN - * priority. - */ - public boolean isWarnEnabled() - { - return logger.isWarnEnabled(); - } +public class Log4JLogger implements Log, Serializable { + + // ------------------------------------------------------------- Attributes + + /** + * The serial version identifier. + */ + private static final long serialVersionUID = 3545240215095883829L; + + /** + * The fully qualified name of the Log4JLogger class. + */ + private static final String FQCN = Log4JLogger.class.getName(); + + /** + * Log to this logger + */ + private transient final AbstractLogger logger; + + /** + * Base constructor. + */ + public Log4JLogger(Class clazz) { + this.logger = (AbstractLogger) LogManager.getLogger(clazz.getName()); + } + + // --------------------------------------------------------- Implementation + + /** + * Log a message to the Log4j Logger with TRACE priority. + * Currently logs to DEBUG level in Log4J. + */ + public void trace(Object message) { + logger.logIfEnabled(FQCN, Level.TRACE, null, message, (Throwable) null); + } + + /** + * Log an error to the Log4j Logger with TRACE priority. + * Currently logs to DEBUG level in Log4J. + */ + public void trace(Object message, Throwable t) { + logger.logIfEnabled(FQCN, Level.TRACE, null, message, t); + } + + /** + * Log a message to the Log4j Logger with DEBUG priority. + */ + @Override + public void debug(Object message) { + logger.logIfEnabled(FQCN, Level.DEBUG, null, message, (Throwable) null); + } + + /** + * Log an error to the Log4j Logger with DEBUG priority. + */ + @Override + public void debug(Object message, Throwable t) { + logger.logIfEnabled(FQCN, Level.DEBUG, null, message, t); + } + + /** + * Log a message to the Log4j Logger with INFO priority. + */ + @Override + public void info(Object message) { + logger.logIfEnabled(FQCN, Level.INFO, null, message, (Throwable) null); + + } + + /** + * Log an error to the Log4j Logger with INFO priority. + */ + public void info(Object message, Throwable t) { + logger.logIfEnabled(FQCN, Level.INFO, null, message, t); + } + + /** + * Log a message to the Log4j Logger with WARN priority. + */ + @Override + public void warn(Object message) { + logger.logIfEnabled(FQCN, Level.WARN, null, message, (Throwable) null); + } + + /** + * Log an error to the Log4j Logger with WARN priority. + */ + @Override + public void warn(Object message, Throwable t) { + logger.logIfEnabled(FQCN, Level.WARN, null, message, t); + } + + /** + * Log a message to the Log4j Logger with ERROR priority. + */ + @Override + public void error(Object message) { + logger.logIfEnabled(FQCN, Level.ERROR, null, message, (Throwable) null); + } + + /** + * Log an error to the Log4j Logger with ERROR priority. + */ + @Override + public void error(Object message, Throwable t) { + logger.logIfEnabled(FQCN, Level.ERROR, null, message, t); + } + + /** + * Log a message to the Log4j Logger with FATAL priority. + */ + public void fatal(Object message) { + logger.logIfEnabled(FQCN, Level.FATAL, null, message, (Throwable) null); + } + + /** + * Log an error to the Log4j Logger with FATAL priority. + */ + public void fatal(Object message, Throwable t) { + logger.logIfEnabled(FQCN, Level.FATAL, null, message, t); + } + + /** + * Return the native Logger instance we are using. + */ + public final Logger getLogger() { + return logger; + } + + /** + * Check whether the Log4j Logger used is enabled for DEBUG + * priority. + */ + @Override + public boolean isDebugEnabled() { + return logger.isDebugEnabled(); + } + + /** + * Check whether the Log4j Logger used is enabled for ERROR + * priority. + */ + public boolean isErrorEnabled() { + return logger.isErrorEnabled(); + + } + + /** + * Check whether the Log4j Logger used is enabled for FATAL + * priority. + */ + public boolean isFatalEnabled() { + return logger.isFatalEnabled(); + + } + + /** + * Check whether the Log4j Logger used is enabled for INFO + * priority. + */ + public boolean isInfoEnabled() { + return logger.isInfoEnabled(); + } + + /** + * Check whether the Log4j Logger used is enabled for TRACE + * priority. For Log4J, this returns the value of + * isDebugEnabled() + */ + public boolean isTraceEnabled() { + return logger.isDebugEnabled(); + } + + /** + * Check whether the Log4j Logger used is enabled for WARN + * priority. + */ + public boolean isWarnEnabled() { + return logger.isWarnEnabled(); + } } diff --git a/src/main/java/org/asteriskjava/util/internal/NullLog.java b/src/main/java/org/asteriskjava/util/internal/NullLog.java index ca6e1bff5..445080be5 100644 --- a/src/main/java/org/asteriskjava/util/internal/NullLog.java +++ b/src/main/java/org/asteriskjava/util/internal/NullLog.java @@ -23,52 +23,42 @@ *

    * This logger is only used if neither log4j nor java.util.logging are available * which should not happen anyway as Asterisk-Java depends on at least JDK 1.5. - * + * * @author srt * @version $Id$ */ -public class NullLog implements Log -{ +public class NullLog implements Log { /** * Creates a new NullLog. */ - public NullLog() - { + public NullLog() { } - public void debug(Object obj) - { + public void debug(Object obj) { } - public void info(Object obj) - { + public void info(Object obj) { } - public void warn(Object obj) - { + public void warn(Object obj) { } - public void warn(Object obj, Throwable ex) - { + public void warn(Object obj, Throwable ex) { } - public void error(Object obj) - { + public void error(Object obj) { } - public void error(Object obj, Throwable ex) - { + public void error(Object obj, Throwable ex) { } @Override - public boolean isDebugEnabled() - { + public boolean isDebugEnabled() { return false; } @Override - public void debug(Object e, Throwable e2) - { + public void debug(Object e, Throwable e2) { } } diff --git a/src/main/java/org/asteriskjava/util/internal/ServerSocketFacadeImpl.java b/src/main/java/org/asteriskjava/util/internal/ServerSocketFacadeImpl.java index 5d9bbc64f..ccef0449c 100644 --- a/src/main/java/org/asteriskjava/util/internal/ServerSocketFacadeImpl.java +++ b/src/main/java/org/asteriskjava/util/internal/ServerSocketFacadeImpl.java @@ -16,14 +16,14 @@ */ package org.asteriskjava.util.internal; +import org.asteriskjava.util.ServerSocketFacade; +import org.asteriskjava.util.SocketConnectionFacade; + import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; -import org.asteriskjava.util.ServerSocketFacade; -import org.asteriskjava.util.SocketConnectionFacade; - /** * Default implementation of the ServerSocketFacade interface using standard @@ -32,20 +32,17 @@ * @author srt * @version $Id$ */ -public class ServerSocketFacadeImpl implements ServerSocketFacade -{ +public class ServerSocketFacadeImpl implements ServerSocketFacade { private ServerSocket serverSocket; private int socketReadTimeout = SocketConnectionFacadeImpl.MAX_SOCKET_READ_TIMEOUT_MILLIS; public ServerSocketFacadeImpl(int port, int backlog, InetAddress bindAddress) - throws IOException - { + throws IOException { this.serverSocket = new ServerSocket(port, backlog, bindAddress); } - public SocketConnectionFacade accept() throws IOException - { + public SocketConnectionFacade accept() throws IOException { Socket socket; socket = serverSocket.accept(); @@ -53,13 +50,11 @@ public SocketConnectionFacade accept() throws IOException return new SocketConnectionFacadeImpl(socket, socketReadTimeout); } - public void close() throws IOException - { + public void close() throws IOException { serverSocket.close(); } - public void setSocketReadTimeout(int socketReadTimeout) - { + public void setSocketReadTimeout(int socketReadTimeout) { this.socketReadTimeout = socketReadTimeout; } } diff --git a/src/main/java/org/asteriskjava/util/internal/Slf4JLogger.java b/src/main/java/org/asteriskjava/util/internal/Slf4JLogger.java index 3374debb9..0f208f44f 100644 --- a/src/main/java/org/asteriskjava/util/internal/Slf4JLogger.java +++ b/src/main/java/org/asteriskjava/util/internal/Slf4JLogger.java @@ -1,12 +1,12 @@ /* * 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. @@ -16,13 +16,13 @@ package org.asteriskjava.util.internal; -import java.io.Serializable; - import org.asteriskjava.util.Log; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.spi.LocationAwareLogger; +import java.io.Serializable; + /** * Implementation of {@link org.asteriskjava.util.Log} that maps to a SLF4J * Logger. @@ -30,30 +30,31 @@ * * @version $Id$ */ -public class Slf4JLogger implements Log, Serializable -{ +public class Slf4JLogger implements Log, Serializable { /** * The serial version identifier. */ private static final long serialVersionUID = 0L; - /** Log to this logger */ + /** + * Log to this logger + */ private transient Logger logger = null; static String FQCN = Slf4JLogger.class.getName(); - /** Logger name */ - private Class< ? > clazz = null; + /** + * Logger name + */ + private Class clazz = null; - public Slf4JLogger() - { + public Slf4JLogger() { } /** * Base constructor. */ - public Slf4JLogger(Class< ? > clazz) - { + public Slf4JLogger(Class clazz) { this.clazz = clazz; this.logger = getLogger(); } @@ -62,80 +63,70 @@ public Slf4JLogger(Class< ? > clazz) * Log a message to the SLF4J Logger with TRACE priority. * Currently logs to DEBUG level in SLF4J. */ - public void trace(Object message) - { + public void trace(Object message) { getLogger().trace(message.toString()); } /** * Log an error to the SLF4J Logger with TRACE priority. */ - public void trace(Object message, Throwable t) - { + public void trace(Object message, Throwable t) { getLogger().trace(message.toString(), t); } /** * Log a message to the SLF4J Logger with DEBUG priority. */ - public void debug(Object message) - { + public void debug(Object message) { getLogger().debug(message.toString()); } /** * Log an error to the SLF4J Logger with DEBUG priority. */ - public void debug(Object message, Throwable t) - { + public void debug(Object message, Throwable t) { getLogger().debug(message.toString(), t); } /** * Log a message to the SLF4J Logger with INFO priority. */ - public void info(Object message) - { + public void info(Object message) { getLogger().info(message.toString()); } /** * Log an error to the SLF4J Logger with INFO priority. */ - public void info(Object message, Throwable t) - { + public void info(Object message, Throwable t) { getLogger().info(message.toString(), t); } /** * Log a message to the SLF4J Logger with WARN priority. */ - public void warn(Object message) - { + public void warn(Object message) { getLogger().warn(message.toString()); } /** * Log an error to the SLF4J Logger with WARN priority. */ - public void warn(Object message, Throwable t) - { + public void warn(Object message, Throwable t) { getLogger().warn(message.toString(), t); } /** * Log a message to the SLF4J Logger with ERROR priority. */ - public void error(Object message) - { + public void error(Object message) { getLogger().error(message.toString()); } /** * Log an error to the SLF4J Logger with ERROR priority. */ - public void error(Object message, Throwable t) - { + public void error(Object message, Throwable t) { getLogger().error(message.toString(), t); } @@ -144,8 +135,7 @@ public void error(Object message, Throwable t) *

    * Currently uses the ERROR priority in SLF4J. */ - public void fatal(Object message) - { + public void fatal(Object message) { getLogger().error(message.toString()); } @@ -154,22 +144,18 @@ public void fatal(Object message) *

    * Currently uses the ERROR priority in SLF4J. */ - public void fatal(Object message, Throwable t) - { + public void fatal(Object message, Throwable t) { getLogger().error(message.toString(), t); } /** * Return the native Logger instance we are using. */ - public final Logger getLogger() - { - if (logger == null) - { + public final Logger getLogger() { + if (logger == null) { logger = LoggerFactory.getLogger(clazz); } - if (logger instanceof LocationAwareLogger) - { + if (logger instanceof LocationAwareLogger) { return new LocationAwareWrapper(FQCN, (LocationAwareLogger) logger); } return this.logger; @@ -179,8 +165,7 @@ public final Logger getLogger() * Check whether the SLF4J Logger used is enabled for DEBUG * priority. */ - public boolean isDebugEnabled() - { + public boolean isDebugEnabled() { return getLogger().isDebugEnabled(); } @@ -188,8 +173,7 @@ public boolean isDebugEnabled() * Check whether the SLF4J Logger used is enabled for ERROR * priority. */ - public boolean isErrorEnabled() - { + public boolean isErrorEnabled() { return getLogger().isErrorEnabled(); } @@ -198,8 +182,7 @@ public boolean isErrorEnabled() * priority. For SLF4J, this returns the value of * isErrorEnabled() */ - public boolean isFatalEnabled() - { + public boolean isFatalEnabled() { return isErrorEnabled(); } @@ -207,8 +190,7 @@ public boolean isFatalEnabled() * Check whether the SLF4J Logger used is enabled for INFO * priority. */ - public boolean isInfoEnabled() - { + public boolean isInfoEnabled() { return getLogger().isInfoEnabled(); } @@ -216,8 +198,7 @@ public boolean isInfoEnabled() * Check whether the SLF4J Logger used is enabled for TRACE * priority. */ - public boolean isTraceEnabled() - { + public boolean isTraceEnabled() { return getLogger().isDebugEnabled(); } @@ -225,8 +206,7 @@ public boolean isTraceEnabled() * Check whether the SLF4J Logger used is enabled for WARN * priority. */ - public boolean isWarnEnabled() - { + public boolean isWarnEnabled() { return getLogger().isWarnEnabled(); } } diff --git a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java index 9ef606a43..178a39dea 100644 --- a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java +++ b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java @@ -16,12 +16,13 @@ */ package org.asteriskjava.util.internal; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; +import org.asteriskjava.util.SocketConnectionFacade; +import org.asteriskjava.util.internal.streamreader.FastScanner; +import org.asteriskjava.util.internal.streamreader.FastScannerFactory; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocketFactory; +import java.io.*; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; @@ -30,21 +31,13 @@ import java.util.NoSuchElementException; import java.util.regex.Pattern; -import javax.net.SocketFactory; -import javax.net.ssl.SSLSocketFactory; - -import org.asteriskjava.util.SocketConnectionFacade; -import org.asteriskjava.util.internal.streamreader.FastScanner; -import org.asteriskjava.util.internal.streamreader.FastScannerFactory; - /** * Default implementation of the SocketConnectionFacade interface using java.io. * * @author srt * @version $Id$ */ -public class SocketConnectionFacadeImpl implements SocketConnectionFacade -{ +public class SocketConnectionFacadeImpl implements SocketConnectionFacade { public static final Pattern CRNL_PATTERN = Pattern.compile("\r\n"); public static final Pattern NL_PATTERN = Pattern.compile("\n"); private Socket socket; @@ -58,15 +51,14 @@ public class SocketConnectionFacadeImpl implements SocketConnectionFacade * Creates a new instance for use with the Manager API that uses CRNL * ("\r\n") as line delimiter. >>>>>>> refs/heads/release-1.1 * - * @param host the foreign host to connect to. - * @param port the foreign port to connect to. - * @param ssl true to use SSL, false otherwise. - * @param timeout 0 incidcates default + * @param host the foreign host to connect to. + * @param port the foreign port to connect to. + * @param ssl true to use SSL, false otherwise. + * @param timeout 0 incidcates default * @param readTimeout see {@link Socket#setSoTimeout(int)} * @throws IOException if the connection cannot be established. */ - public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeout, int readTimeout) throws IOException - { + public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeout, int readTimeout) throws IOException { this(host, port, ssl, timeout, readTimeout, StandardCharsets.UTF_8, CRNL_PATTERN); } @@ -74,18 +66,17 @@ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeou * Creates a new instance for use with the Manager API that uses the given * encoding and CRNL ("\r\n") as line delimiter. * - * @param host the foreign host to connect to. - * @param port the foreign port to connect to. - * @param ssl true to use SSL, false otherwise. - * @param timeout 0 incidcates default + * @param host the foreign host to connect to. + * @param port the foreign port to connect to. + * @param ssl true to use SSL, false otherwise. + * @param timeout 0 incidcates default * @param readTimeout see {@link Socket#setSoTimeout(int)} - * @param encoding the encoding used for transmission of strings (all - * connections should use the same encoding) + * @param encoding the encoding used for transmission of strings (all + * connections should use the same encoding) * @throws IOException if the connection cannot be established. */ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeout, int readTimeout, Charset encoding) - throws IOException - { + throws IOException { this(host, port, ssl, timeout, readTimeout, encoding, CRNL_PATTERN); } @@ -93,18 +84,17 @@ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeou * Creates a new instance for use with the Manager API that uses UTF-8 as * encoding and the given line delimiter. * - * @param host the foreign host to connect to. - * @param port the foreign port to connect to. - * @param ssl true to use SSL, false otherwise. - * @param timeout 0 incidcates default - * @param readTimeout see {@link Socket#setSoTimeout(int)} + * @param host the foreign host to connect to. + * @param port the foreign port to connect to. + * @param ssl true to use SSL, false otherwise. + * @param timeout 0 incidcates default + * @param readTimeout see {@link Socket#setSoTimeout(int)} * @param lineDelimiter a {@link Pattern} for matching the line delimiter - * for the socket + * for the socket * @throws IOException if the connection cannot be established. */ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeout, int readTimeout, - Pattern lineDelimiter) throws IOException - { + Pattern lineDelimiter) throws IOException { this(host, port, ssl, timeout, readTimeout, StandardCharsets.UTF_8, lineDelimiter); } @@ -112,36 +102,31 @@ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeou * Creates a new instance for use with the Manager API that uses the given * encoding and line delimiter. * - * @param host the foreign host to connect to. - * @param port the foreign port to connect to. - * @param ssl true to use SSL, false otherwise. - * @param timeout 0 incidcates default - * @param readTimeout see {@link Socket#setSoTimeout(int)} - * @param encoding the encoding used for transmission of strings (all - * connections should use the same encoding) + * @param host the foreign host to connect to. + * @param port the foreign port to connect to. + * @param ssl true to use SSL, false otherwise. + * @param timeout 0 incidcates default + * @param readTimeout see {@link Socket#setSoTimeout(int)} + * @param encoding the encoding used for transmission of strings (all + * connections should use the same encoding) * @param lineDelimiter a {@link Pattern} for matching the line delimiter - * for the socket + * for the socket * @throws IOException if the connection cannot be established. */ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeout, int readTimeout, Charset encoding, - Pattern lineDelimiter) throws IOException - { + Pattern lineDelimiter) throws IOException { Socket socket; - if (ssl) - { + if (ssl) { socket = SSLSocketFactory.getDefault().createSocket(); - } - else - { + } else { socket = SocketFactory.getDefault().createSocket(); } socket.setSoTimeout(readTimeout); socket.connect(new InetSocketAddress(host, port), timeout); initialize(socket, encoding, lineDelimiter); - if (System.getProperty(Trace.TRACE_PROPERTY, "false").equalsIgnoreCase("true")) - { + if (System.getProperty(Trace.TRACE_PROPERTY, "false").equalsIgnoreCase("true")) { trace = new FileTrace(socket); } } @@ -153,22 +138,19 @@ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeou * @param socket the underlying socket. * @throws IOException if the connection cannot be initialized. */ - SocketConnectionFacadeImpl(Socket socket) throws IOException - { + SocketConnectionFacadeImpl(Socket socket) throws IOException { this(socket, MAX_SOCKET_READ_TIMEOUT_MILLIS); } /** * Creates a new instance for use with FastAGI that uses NL ("\n") as line delimiter. * - * @param socket the underlying socket. + * @param socket the underlying socket. * @param timeout 0 indicates default, -1 indicates infinite timeout (not recommended) * @throws IOException if the connection cannot be initialized. */ - SocketConnectionFacadeImpl(Socket socket, int timeout) throws IOException - { - if (timeout == -1) - { + SocketConnectionFacadeImpl(Socket socket, int timeout) throws IOException { + if (timeout == -1) { timeout = 0; } else if (timeout == 0) { timeout = MAX_SOCKET_READ_TIMEOUT_MILLIS; @@ -177,11 +159,12 @@ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeou initialize(socket, StandardCharsets.UTF_8, NL_PATTERN); } - /** 3 hrs = 3 * 3660 * 1000 */ + /** + * 3 hrs = 3 * 3660 * 1000 + */ public static final int MAX_SOCKET_READ_TIMEOUT_MILLIS = 10800000; - private void initialize(Socket socket, Charset encoding, Pattern pattern) throws IOException - { + private void initialize(Socket socket, Charset encoding, Pattern pattern) throws IOException { this.socket = socket; InputStream inputStream = socket.getInputStream(); @@ -194,79 +177,62 @@ private void initialize(Socket socket, Charset encoding, Pattern pattern) throws } @Override - public String readLine() throws IOException - { + public String readLine() throws IOException { String line = null; - try - { + try { line = scanner.next(); - } - catch (IllegalStateException e) - { + } catch (IllegalStateException e) { // throw new IOException("No more lines available", e); // JDK6 throw new IOException("No more lines available: " + e.getMessage()); - } - catch (NoSuchElementException e) - { + } catch (NoSuchElementException e) { // throw new IOException("No more lines available", e); // JDK6 throw new IOException("No more lines available: " + e.getMessage()); } - if (trace != null) - { + if (trace != null) { trace.received(line); } return line; } - public void write(String s) throws IOException - { + public void write(String s) throws IOException { writer.write(s); - if (trace != null) - { + if (trace != null) { trace.sent(s); } } - public void flush() throws IOException - { + public void flush() throws IOException { writer.flush(); } - public void close() throws IOException - { + public void close() throws IOException { socket.close(); scanner.close(); // close the trace only if it was activated (the object is not null) - if (trace != null) - { + if (trace != null) { trace.close(); } } - public boolean isConnected() - { + public boolean isConnected() { return socket.isConnected(); } - public InetAddress getLocalAddress() - { + public InetAddress getLocalAddress() { return socket.getLocalAddress(); } - public int getLocalPort() - { + public int getLocalPort() { return socket.getLocalPort(); } - public InetAddress getRemoteAddress() - { + public InetAddress getRemoteAddress() { return socket.getInetAddress(); } - public int getRemotePort() - { + public int getRemotePort() { return socket.getPort(); } } diff --git a/src/main/java/org/asteriskjava/util/internal/Trace.java b/src/main/java/org/asteriskjava/util/internal/Trace.java index eb8314908..924d0a9ce 100644 --- a/src/main/java/org/asteriskjava/util/internal/Trace.java +++ b/src/main/java/org/asteriskjava/util/internal/Trace.java @@ -3,8 +3,7 @@ /** * Interface for tracing network traffic. */ -public interface Trace -{ +public interface Trace { /** * Name of the system property to enable tracing.

    * To enable tracing add -Dorg.asteriskjava.trace=true to the vm parameters when running Asterisk-Java. @@ -13,17 +12,19 @@ public interface Trace /** * Writes data that has been received from the network to the trace. + * * @param s the String that has been received. */ void received(String s); /** * Writes data that has been sent to the network to the trace. + * * @param s the String that has been sent. */ void sent(String s); - - + + /** * Closes allocated resources by trace implementation. */ diff --git a/src/main/java/org/asteriskjava/util/internal/package.html b/src/main/java/org/asteriskjava/util/internal/package.html index e3b52ed3f..c9cec1a4a 100644 --- a/src/main/java/org/asteriskjava/util/internal/package.html +++ b/src/main/java/org/asteriskjava/util/internal/package.html @@ -1,28 +1,28 @@ - +

    Provides private implementations for interfaces defined in the - org.asteriskjava.util package.

    + org.asteriskjava.util package.

    - \ No newline at end of file + diff --git a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java index 89ce1888c..5ca4eebde 100644 --- a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java +++ b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScanner.java @@ -3,8 +3,7 @@ import java.io.Closeable; import java.io.IOException; -public interface FastScanner extends Closeable -{ +public interface FastScanner extends Closeable { String next() throws IOException; } diff --git a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerCrNl.java b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerCrNl.java index c6d48e826..cdbfac239 100644 --- a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerCrNl.java +++ b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerCrNl.java @@ -1,39 +1,30 @@ package org.asteriskjava.util.internal.streamreader; -public class FastScannerCrNl extends FastScannerNl -{ +public class FastScannerCrNl extends FastScannerNl { private char crChar = '\r'; private boolean seenReturn = false; - public FastScannerCrNl(Readable reader) - { + public FastScannerCrNl(Readable reader) { super(reader); } - protected String getLine(boolean endOfLine) - { + protected String getLine(boolean endOfLine) { // iterate the builder looking for the delimiter chars - for (int i = start; i < end; i++) - { - if (cbuf.get(i) == crChar) - { + for (int i = start; i < end; i++) { + if (cbuf.get(i) == crChar) { // flag that we've encountered the first of the two delimiter // characters seenReturn = true; - } - else if (seenReturn && cbuf.get(i) == nlChar) - { + } else if (seenReturn && cbuf.get(i) == nlChar) { // we've seen both of the delimiter characters, package up the // data and return it... - if (i == start) - { + if (i == start) { // back track to remove a /r in the last packet result.setLength(result.length() - 1); } - if (i > start) - { + if (i > start) { // append the data to the StringBuilder result.append(cbuf.subSequence(start, start + (i - start) - 1)); } @@ -50,15 +41,12 @@ else if (seenReturn && cbuf.get(i) == nlChar) seenReturn = false; return tmp; - } - else - { + } else { // clear the delimiter seen flag seenReturn = false; } } - if (end >= start) - { + if (end >= start) { // we've hit the end of the buffer, add the data to the // StringBuilder and return null so as to get // the next part of the line diff --git a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerFactory.java b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerFactory.java index 130a2baec..10c48ac77 100644 --- a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerFactory.java +++ b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerFactory.java @@ -1,29 +1,24 @@ package org.asteriskjava.util.internal.streamreader; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + import java.io.IOException; import java.util.NoSuchElementException; import java.util.Scanner; import java.util.regex.Pattern; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; - -public class FastScannerFactory -{ +public class FastScannerFactory { private static final Log logger = LogFactory.getLog(FastScannerFactory.class); private static volatile boolean useLegacyScanner = false; - public static FastScanner getReader(Readable reader, Pattern pattern) - { - if (!useLegacyScanner) - { - if (pattern.pattern().equals("\r\n")) - { + public static FastScanner getReader(Readable reader, Pattern pattern) { + if (!useLegacyScanner) { + if (pattern.pattern().equals("\r\n")) { return new FastScannerCrNl(reader); } - if (pattern.pattern().equals("\n")) - { + if (pattern.pattern().equals("\n")) { return new FastScannerNl(reader); } } @@ -38,32 +33,24 @@ public static FastScanner getReader(Readable reader, Pattern pattern) } - public static void useLegacyScanner(boolean b) - { + public static void useLegacyScanner(boolean b) { useLegacyScanner = b; } - private static FastScanner getWrappedScanner(final Scanner scanner) - { - return new FastScanner() - { + private static FastScanner getWrappedScanner(final Scanner scanner) { + return new FastScanner() { @Override - public String next() throws IOException - { - try - { + public String next() throws IOException { + try { return scanner.next(); - } - catch (NoSuchElementException e) - { + } catch (NoSuchElementException e) { return null; } } @Override - public void close() - { + public void close() { scanner.close(); } diff --git a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java index 3370fe5d9..a24327aa9 100644 --- a/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java +++ b/src/main/java/org/asteriskjava/util/internal/streamreader/FastScannerNl.java @@ -1,6 +1,8 @@ - package org.asteriskjava.util.internal.streamreader; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; + import java.io.BufferedWriter; import java.io.Closeable; import java.io.File; @@ -11,11 +13,7 @@ import java.nio.file.StandardOpenOption; import java.util.concurrent.atomic.AtomicReference; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; - -public class FastScannerNl implements FastScanner -{ +public class FastScannerNl implements FastScanner { private static final Log logger = LogFactory.getLog(FastScannerNl.class); private static final int BUFFER_SIZE = 8192; @@ -35,22 +33,19 @@ public class FastScannerNl implements FastScanner private BufferedWriter writer; - public FastScannerNl(Readable reader) - { + public FastScannerNl(Readable reader) { this.readableReference.set(reader); // createFileWriter(); } - public String next() throws IOException - { + public String next() throws IOException { int bytes = 0; // check for a line in the buffer String line = getLine(false); - if (line == null) - { + if (line == null) { // doing this instead of a synchronized block to avoid a possible // deadlock between calling readable.read() and a call to close() on // another thread, which it appears that Asterisk-Java permits @@ -58,8 +53,7 @@ public String next() throws IOException Readable readable = readableReference.get(); // read from the stream to the buffer - while (readable != null && (bytes = readable.read(cbuf)) > -1) - { + while (readable != null && (bytes = readable.read(cbuf)) > -1) { // writeToFile(bytes); // set buffer position to 0 @@ -70,10 +64,8 @@ public String next() throws IOException // try to get a line from the buffer line = getLine(bytes >= 0); - if (line != null) - { - if (isFirst && line.length() == 0) - { + if (line != null) { + if (isFirst && line.length() == 0) { // if the first character of the stream is the line // terminator, try again line = getLine(bytes >= 0); @@ -85,22 +77,18 @@ public String next() throws IOException } // clear the first line flag isFirst = false; - if (line == null) - - { + if (line == null) { // the line is empty, get the contents from the StringBuilder if any String tmp = result.toString(); result.setLength(0); // if the reader is closed and there is no output - if (readableReference.get() == null && tmp.length() == 0) - { + if (readableReference.get() == null && tmp.length() == 0) { return null; } // if at the end of the inputStream and there is no output - if (bytes == -1 && tmp.length() == 0) - { + if (bytes == -1 && tmp.length() == 0) { return null; } return tmp; @@ -109,15 +97,11 @@ public String next() throws IOException } - protected String getLine(boolean endOfLine) - { + protected String getLine(boolean endOfLine) { // iterate the buffer, looking for the end character - for (int i = start; i < end; i++) - { - if (cbuf.get(i) == nlChar) - { - if (i > start) - { + for (int i = start; i < end; i++) { + if (cbuf.get(i) == nlChar) { + if (i > start) { // add the buffer contents up to i to the output buffer result.append(cbuf.subSequence(start, start + (i - start))); } @@ -133,8 +117,7 @@ protected String getLine(boolean endOfLine) } } - if (end >= start) - { + if (end >= start) { // we've hit the end of the buffer, copy the contents to the // StringBuilder, then return null so we'll loop again and get the // next part @@ -145,21 +128,16 @@ protected String getLine(boolean endOfLine) return null; } - public void close() - { + public void close() { // synchronized (sync) // { if (closed) return; - if (readableReference.get() instanceof Closeable) - { - try - { + if (readableReference.get() instanceof Closeable) { + try { ((Closeable) readableReference.get()).close(); // closeFileWriter(); - } - catch (IOException ioe) - { + } catch (IOException ioe) { logger.error(ioe, ioe); } } @@ -169,29 +147,23 @@ public void close() } @SuppressWarnings("unused") - private void createFileWriter() - { - try - { + private void createFileWriter() { + try { logfile = File.createTempFile(this.getClass().getSimpleName(), "txt"); writer = Files.newBufferedWriter(logfile.toPath(), Charset.defaultCharset(), StandardOpenOption.APPEND); - } - catch (IOException e) - { + } catch (IOException e) { e.printStackTrace(); } } @SuppressWarnings("unused") - private void writeToFile(int bytes) throws IOException - { + private void writeToFile(int bytes) throws IOException { String lines = new StringBuffer().append(cbuf, 0, bytes).toString(); writer.append(lines, 0, bytes); } @SuppressWarnings("unused") - private void closeFileWriter() throws IOException - { + private void closeFileWriter() throws IOException { writer.flush(); writer.close(); } diff --git a/src/main/java/org/asteriskjava/util/package.html b/src/main/java/org/asteriskjava/util/package.html index 73afd0d9c..b855f4a09 100644 --- a/src/main/java/org/asteriskjava/util/package.html +++ b/src/main/java/org/asteriskjava/util/package.html @@ -1,30 +1,30 @@ - +

    Provides various utility classes used throughout the library.

    Client code is generally not supposed to use classes or interfaces in this packages - with the exception of the logging support if they want to reuse Asterisk-Java's - logging abstraction layer.

    + with the exception of the logging support if they want to reuse Asterisk-Java's + logging abstraction layer.

    - \ No newline at end of file + diff --git a/src/test/java/org/asteriskjava/fastagi/HelloAgiScript.java b/src/test/java/org/asteriskjava/fastagi/HelloAgiScript.java index b12c10cb6..e0f85762a 100644 --- a/src/test/java/org/asteriskjava/fastagi/HelloAgiScript.java +++ b/src/test/java/org/asteriskjava/fastagi/HelloAgiScript.java @@ -18,19 +18,16 @@ /** * Test script for use with the ResourceBundleMappingStrategyTest. - * + * * @author srt * @version $Id$ */ -public class HelloAgiScript implements AgiScript -{ - public HelloAgiScript() - { +public class HelloAgiScript implements AgiScript { + public HelloAgiScript() { } - public void service(AgiRequest request, AgiChannel channel) throws AgiException - { + public void service(AgiRequest request, AgiChannel channel) throws AgiException { channel.streamFile("tt-monkeysintro"); } } diff --git a/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java b/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java index 1d1cd65e5..411678e29 100644 --- a/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java +++ b/src/test/java/org/asteriskjava/fastagi/SimpleAgiRequest.java @@ -16,13 +16,12 @@ */ package org.asteriskjava.fastagi; +import org.asteriskjava.AsteriskVersion; + import java.net.InetAddress; import java.util.Map; -import org.asteriskjava.AsteriskVersion; - -public class SimpleAgiRequest implements AgiRequest -{ +public class SimpleAgiRequest implements AgiRequest { InetAddress localAddress; int localPort; InetAddress remoteAddress; @@ -30,48 +29,39 @@ public class SimpleAgiRequest implements AgiRequest private String script; private AsteriskVersion asteriskVersion = AsteriskVersion.ASTERISK_13; - public SimpleAgiRequest() - { + public SimpleAgiRequest() { this.script = "hello.agi"; } - public SimpleAgiRequest(String script) - { + public SimpleAgiRequest(String script) { this.script = script; } - public Map getRequest() - { + public Map getRequest() { throw new UnsupportedOperationException(); } - public String getScript() - { + public String getScript() { return script; } - public String getRequestURL() - { + public String getRequestURL() { throw new UnsupportedOperationException(); } - public String getChannel() - { + public String getChannel() { throw new UnsupportedOperationException(); } - public String getUniqueId() - { + public String getUniqueId() { throw new UnsupportedOperationException(); } - public String getType() - { + public String getType() { throw new UnsupportedOperationException(); } - public String getLanguage() - { + public String getLanguage() { throw new UnsupportedOperationException(); } @@ -82,142 +72,115 @@ public String getLanguage() * Caller ID. * * @return the Caller*ID number, for example "1234", if no Caller*ID is set - * or it is "unknown" null is returned. + * or it is "unknown" null is returned. * @deprecated as of 0.3, use {@link #getCallerIdNumber()} instead. */ - public String getCallerId() - { + public String getCallerId() { throw new UnsupportedOperationException(); } - public String getCallerIdNumber() - { + public String getCallerIdNumber() { throw new UnsupportedOperationException(); } - public String getCallerIdName() - { + public String getCallerIdName() { throw new UnsupportedOperationException(); } - public String getDnid() - { + public String getDnid() { throw new UnsupportedOperationException(); } - public String getRdnis() - { + public String getRdnis() { throw new UnsupportedOperationException(); } - public String getContext() - { + public String getContext() { throw new UnsupportedOperationException(); } - public String getExtension() - { + public String getExtension() { throw new UnsupportedOperationException(); } - public Integer getPriority() - { + public Integer getPriority() { throw new UnsupportedOperationException(); } - public Boolean getEnhanced() - { + public Boolean getEnhanced() { throw new UnsupportedOperationException(); } - public String getAccountCode() - { + public String getAccountCode() { throw new UnsupportedOperationException(); } - public Integer getCallingAni2() - { + public Integer getCallingAni2() { throw new UnsupportedOperationException(); } - public Integer getCallingPres() - { + public Integer getCallingPres() { throw new UnsupportedOperationException(); } - public Integer getCallingTns() - { + public Integer getCallingTns() { throw new UnsupportedOperationException(); } - public Integer getCallingTon() - { + public Integer getCallingTon() { throw new UnsupportedOperationException(); } - public String getParameter(String name) - { + public String getParameter(String name) { throw new UnsupportedOperationException(); } - public String[] getParameterValues(String name) - { + public String[] getParameterValues(String name) { throw new UnsupportedOperationException(); } - public Map getParameterMap() - { + public Map getParameterMap() { throw new UnsupportedOperationException(); } - public String[] getArguments() - { + public String[] getArguments() { throw new UnsupportedOperationException(); } - public InetAddress getLocalAddress() - { + public InetAddress getLocalAddress() { return localAddress; } - public void setLocalAddress(InetAddress localAddress) - { + public void setLocalAddress(InetAddress localAddress) { this.localAddress = localAddress; } - public int getLocalPort() - { + public int getLocalPort() { return localPort; } - public void setLocalPort(int localPort) - { + public void setLocalPort(int localPort) { this.localPort = localPort; } - public InetAddress getRemoteAddress() - { + public InetAddress getRemoteAddress() { return remoteAddress; } - public void setRemoteAddress(InetAddress remoteAddress) - { + public void setRemoteAddress(InetAddress remoteAddress) { this.remoteAddress = remoteAddress; } - public int getRemotePort() - { + public int getRemotePort() { return remotePort; } - public void setRemotePort(int remotePort) - { + public void setRemotePort(int remotePort) { this.remotePort = remotePort; } @Override - public AsteriskVersion getAsteriskVersion() - { + public AsteriskVersion getAsteriskVersion() { return asteriskVersion; } } diff --git a/src/test/java/org/asteriskjava/manager/internal/A.java b/src/test/java/org/asteriskjava/manager/internal/A.java index d657fe93c..748606381 100644 --- a/src/test/java/org/asteriskjava/manager/internal/A.java +++ b/src/test/java/org/asteriskjava/manager/internal/A.java @@ -18,12 +18,10 @@ import org.asteriskjava.manager.event.UserEvent; -public class A extends UserEvent -{ +public class A extends UserEvent { private static final long serialVersionUID = 3545240219457894199L; - public A(Object source) - { + public A(Object source) { super(source); } } diff --git a/src/test/java/org/asteriskjava/manager/internal/AnnotatedAction.java b/src/test/java/org/asteriskjava/manager/internal/AnnotatedAction.java index f476b5c4c..c68cd2e9c 100644 --- a/src/test/java/org/asteriskjava/manager/internal/AnnotatedAction.java +++ b/src/test/java/org/asteriskjava/manager/internal/AnnotatedAction.java @@ -19,8 +19,7 @@ import org.asteriskjava.manager.AsteriskMapping; import org.asteriskjava.manager.action.AbstractManagerAction; -public class AnnotatedAction extends AbstractManagerAction -{ +public class AnnotatedAction extends AbstractManagerAction { private static final long serialVersionUID = 1L; private String property1; private String property2; @@ -28,52 +27,43 @@ public class AnnotatedAction extends AbstractManagerAction @AsteriskMapping("property-3") // annotated field private String property3; - public AnnotatedAction() - { + public AnnotatedAction() { } - public AnnotatedAction(String property1, String property2, String property3) - { + public AnnotatedAction(String property1, String property2, String property3) { this.property1 = property1; this.property2 = property2; this.property3 = property3; } @Override - public String getAction() - { + public String getAction() { return "Custom"; } @AsteriskMapping("property-1") // annotated getter - public String getProperty1() - { + public String getProperty1() { return property1; } - public void setProperty1(String property1) - { + public void setProperty1(String property1) { this.property1 = property1; } - public String getProperty2() - { + public String getProperty2() { return property2; } @AsteriskMapping("property-2") // annotated setter - public void setProperty2(String property2) - { + public void setProperty2(String property2) { this.property2 = property2; } - public String getProperty3() - { + public String getProperty3() { return property3; } - public void setProperty3(String property3) - { + public void setProperty3(String property3) { this.property3 = property3; } -} \ No newline at end of file +} diff --git a/src/test/java/org/asteriskjava/manager/internal/BEvent.java b/src/test/java/org/asteriskjava/manager/internal/BEvent.java index 51c34c70d..a3895ac00 100644 --- a/src/test/java/org/asteriskjava/manager/internal/BEvent.java +++ b/src/test/java/org/asteriskjava/manager/internal/BEvent.java @@ -18,12 +18,10 @@ import org.asteriskjava.manager.event.UserEvent; -public class BEvent extends UserEvent -{ +public class BEvent extends UserEvent { private static final long serialVersionUID = 3545240219457894199L; - public BEvent(Object source) - { + public BEvent(Object source) { super(source); } } diff --git a/src/test/java/org/asteriskjava/manager/internal/EEvent.java b/src/test/java/org/asteriskjava/manager/internal/EEvent.java index f8bc5ef17..30ca8790c 100644 --- a/src/test/java/org/asteriskjava/manager/internal/EEvent.java +++ b/src/test/java/org/asteriskjava/manager/internal/EEvent.java @@ -17,31 +17,30 @@ package org.asteriskjava.manager.internal; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.UserEvent; public class EEvent - extends ManagerEvent { + extends ManagerEvent { - private static final long serialVersionUID = 3545240219457894199L; + private static final long serialVersionUID = 3545240219457894199L; - private Boolean line; + private Boolean line; - public EEvent(Object source) { - super(source); - } + public EEvent(Object source) { + super(source); + } - public Boolean getLineAsBoolean() { - return line; - } + public Boolean getLineAsBoolean() { + return line; + } - public void setLine(Boolean line) { - this.line = line; - if (line == null) { - super.setLine(null); - } else if (line) { - super.setLine(1); - } else { - super.setLine(0); - } - } + public void setLine(Boolean line) { + this.line = line; + if (line == null) { + super.setLine(null); + } else if (line) { + super.setLine(1); + } else { + super.setLine(0); + } + } } diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java index d3c8f0a0f..e4bc3332b 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderMock.java @@ -16,61 +16,51 @@ */ package org.asteriskjava.manager.internal; -import java.io.IOException; - import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.SocketConnectionFacade; -public class ManagerReaderMock implements ManagerReader -{ +import java.io.IOException; + +public class ManagerReaderMock implements ManagerReader { public int setSocketCalls = 0; public int dieCalls = 0; public int runCalls = 0; - public ManagerReaderMock() - { + public ManagerReaderMock() { } - public void registerEventClass(Class< ? extends ManagerEvent> event) - { + public void registerEventClass(Class event) { throw new UnsupportedOperationException(); } - public void setSocket(SocketConnectionFacade socket) - { + public void setSocket(SocketConnectionFacade socket) { setSocketCalls++; } - public void expectResponseClass(String actionId, Class< ? extends ManagerResponse> responseClass) - { + public void expectResponseClass(String actionId, Class responseClass) { } - public void die() - { + public void die() { dieCalls++; } - public boolean isDead() - { + public boolean isDead() { return false; } - public void run() - { + public void run() { runCalls++; } - public IOException getTerminationException() - { + public IOException getTerminationException() { return null; } @Override - public void deregisterEventClass(Class< ? extends ManagerEvent> eventClass) - { + public void deregisterEventClass(Class eventClass) { } } diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerWriterMock.java b/src/test/java/org/asteriskjava/manager/internal/ManagerWriterMock.java index 670d8fe8c..6dedf480c 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerWriterMock.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerWriterMock.java @@ -16,8 +16,6 @@ */ package org.asteriskjava.manager.internal; -import java.io.IOException; - import org.asteriskjava.AsteriskVersion; import org.asteriskjava.manager.action.ChallengeAction; import org.asteriskjava.manager.action.LoginAction; @@ -30,8 +28,9 @@ import org.asteriskjava.util.DateUtil; import org.asteriskjava.util.SocketConnectionFacade; -public class ManagerWriterMock implements ManagerWriter -{ +import java.io.IOException; + +public class ManagerWriterMock implements ManagerWriter { private static final String CHALLENGE = "12345"; private static final long CONNECT_LATENCY = 50; private static final long RESPONSE_LATENCY = 20; @@ -48,53 +47,39 @@ public class ManagerWriterMock implements ManagerWriter public int logoffActionsSent = 0; public int otherActionsSent = 0; - public ManagerWriterMock() - { + public ManagerWriterMock() { } - public void setTargetVersion(AsteriskVersion version) - { + public void setTargetVersion(AsteriskVersion version) { } - public void setDispatcher(Dispatcher dispatcher) - { + public void setDispatcher(Dispatcher dispatcher) { this.dispatcher = dispatcher; } - public void setExpectedKey(String key) - { + public void setExpectedKey(String key) { this.expectedKey = key; } - public void setExpectedUsername(String username) - { + public void setExpectedUsername(String username) { this.expectedUsername = username; } - public void setSendResponse(boolean sendResponse) - { + public void setSendResponse(boolean sendResponse) { this.sendResponse = sendResponse; } - public void setSendProtocolIdentifierReceivedEvent(boolean sendConnectEvent) - { + public void setSendProtocolIdentifierReceivedEvent(boolean sendConnectEvent) { this.sendProtocolIdentifierReceivedEvent = sendConnectEvent; } - public void setSocket(SocketConnectionFacade socket) - { - if (sendProtocolIdentifierReceivedEvent) - { - Thread future = new Thread(new Runnable() - { - public void run() - { - try - { + public void setSocket(SocketConnectionFacade socket) { + if (sendProtocolIdentifierReceivedEvent) { + Thread future = new Thread(new Runnable() { + public void run() { + try { Thread.sleep(CONNECT_LATENCY); - } - catch (InterruptedException e) - { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } ProtocolIdentifierReceivedEvent protocolIdentifierReceivedEvent; @@ -108,22 +93,18 @@ public void run() } } - public void sendAction(ManagerAction action, String internalActionId) throws IOException - { - if (action instanceof ChallengeAction) - { + public void sendAction(ManagerAction action, String internalActionId) throws IOException { + if (action instanceof ChallengeAction) { ChallengeAction challengeAction = (ChallengeAction) action; String authType = challengeAction.getAuthType(); - if (!authType.equals("MD5")) - { + if (!authType.equals("MD5")) { throw new RuntimeException("Expected authType 'MD5' got '" + authType + "'"); } challengeActionsSent++; - if (sendResponse) - { + if (sendResponse) { ChallengeResponse challengeResponse; challengeResponse = new ChallengeResponse(); @@ -131,41 +112,33 @@ public void sendAction(ManagerAction action, String internalActionId) throws IOE challengeResponse.setChallenge(CHALLENGE); dispatchLater(challengeResponse); } - } - else if (action instanceof LoginAction) - { + } else if (action instanceof LoginAction) { LoginAction loginAction = (LoginAction) action; String username = loginAction.getUsername(); String key = loginAction.getKey(); String authType = loginAction.getAuthType(); - if (!"MD5".equals(authType)) - { + if (!"MD5".equals(authType)) { throw new RuntimeException("Expected authType 'MD5' got '" + authType + "'"); } - if (!expectedUsername.equals(username)) - { + if (!expectedUsername.equals(username)) { throw new RuntimeException("Expected username '" + expectedUsername + "' got '" + username + "'"); } loginActionsSent++; - if (sendResponse) - { + if (sendResponse) { ManagerResponse loginResponse; // let testReconnectWithKeepAliveAfterAuthenticationFailure // succeed after // 3 unsuccessful attempts - if (key.equals(expectedKey) || loginActionsSent > 2) - { + if (key.equals(expectedKey) || loginActionsSent > 2) { loginResponse = new ManagerResponse(); loginResponse.setResponse("Success"); - } - else - { + } else { loginResponse = new ManagerError(); loginResponse.setResponse("Error"); loginResponse.setMessage("Authentication failed"); @@ -173,13 +146,10 @@ else if (action instanceof LoginAction) loginResponse.setActionId(ManagerUtil.addInternalActionId(action.getActionId(), internalActionId)); dispatchLater(loginResponse); } - } - else if (action instanceof LogoffAction) - { + } else if (action instanceof LogoffAction) { logoffActionsSent++; - if (sendResponse) - { + if (sendResponse) { ManagerResponse response; response = new ManagerResponse(); @@ -187,13 +157,10 @@ else if (action instanceof LogoffAction) response.setResponse("Success"); dispatchLater(response); } - } - else - { + } else { otherActionsSent++; - if (sendResponse) - { + if (sendResponse) { ManagerResponse response; response = new ManagerResponse(); @@ -204,18 +171,12 @@ else if (action instanceof LogoffAction) } } - private void dispatchLater(final ManagerResponse response) - { - Thread future = new Thread(new Runnable() - { - public void run() - { - try - { + private void dispatchLater(final ManagerResponse response) { + Thread future = new Thread(new Runnable() { + public void run() { + try { Thread.sleep(RESPONSE_LATENCY); - } - catch (InterruptedException e) - { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } dispatcher.dispatchResponse(response, null); diff --git a/src/test/java/org/asteriskjava/manager/internal/MyUserEvent.java b/src/test/java/org/asteriskjava/manager/internal/MyUserEvent.java index aedd4176a..86f785fee 100644 --- a/src/test/java/org/asteriskjava/manager/internal/MyUserEvent.java +++ b/src/test/java/org/asteriskjava/manager/internal/MyUserEvent.java @@ -16,51 +16,45 @@ */ package org.asteriskjava.manager.internal; -import java.util.Map; - import org.asteriskjava.manager.event.UserEvent; -public class MyUserEvent extends UserEvent -{ +import java.util.Map; + +public class MyUserEvent extends UserEvent { private static final long serialVersionUID = 3689913989471418169L; private String stringMember; - private Map mapMember; - - public MyUserEvent(Object source) - { + private Map mapMember; + + public MyUserEvent(Object source) { super(source); } /** * @return the mapMember */ - public Map getMapMember() - { + public Map getMapMember() { return mapMember; } /** * @param mapMember the mapMember to set */ - public void setMapMember(Map mapMember) - { + public void setMapMember(Map mapMember) { this.mapMember = mapMember; } /** * @return the stringMember */ - public String getStringMember() - { + public String getStringMember() { return stringMember; } /** * @param stringMember the stringMember to set */ - public void setStringMember(String stringMember) - { + public void setStringMember(String stringMember) { this.stringMember = stringMember; } } diff --git a/src/test/java/org/asteriskjava/manager/internal/UserEventC.java b/src/test/java/org/asteriskjava/manager/internal/UserEventC.java index 389ca1318..89716a2ce 100644 --- a/src/test/java/org/asteriskjava/manager/internal/UserEventC.java +++ b/src/test/java/org/asteriskjava/manager/internal/UserEventC.java @@ -18,12 +18,10 @@ import org.asteriskjava.manager.event.UserEvent; -public class UserEventC extends UserEvent -{ +public class UserEventC extends UserEvent { private static final long serialVersionUID = 3545240219457894199L; - public UserEventC(Object source) - { + public UserEventC(Object source) { super(source); } } diff --git a/src/test/java/org/asteriskjava/manager/internal/UserEventDEvent.java b/src/test/java/org/asteriskjava/manager/internal/UserEventDEvent.java index 0e4324b79..4bf60f1d0 100644 --- a/src/test/java/org/asteriskjava/manager/internal/UserEventDEvent.java +++ b/src/test/java/org/asteriskjava/manager/internal/UserEventDEvent.java @@ -18,12 +18,10 @@ import org.asteriskjava.manager.event.UserEvent; -public class UserEventDEvent extends UserEvent -{ +public class UserEventDEvent extends UserEvent { private static final long serialVersionUID = 3545240219457894199L; - public UserEventDEvent(Object source) - { + public UserEventDEvent(Object source) { super(source); } } From e0fab33a1c29e0aa73d25e920644ba17dae9fe60 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Fri, 2 Sep 2022 22:04:26 +0200 Subject: [PATCH 511/802] Add dependabot --- .github/dependabot.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..b76b89570 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "daily" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" From 211a111433c0dc70b74ce953014747e331816672 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 20 Sep 2022 12:48:33 +1000 Subject: [PATCH 512/802] cleanup --- src/test/java/org/asteriskjava/manager/internal/EEvent.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/org/asteriskjava/manager/internal/EEvent.java b/src/test/java/org/asteriskjava/manager/internal/EEvent.java index f8bc5ef17..3501950ee 100644 --- a/src/test/java/org/asteriskjava/manager/internal/EEvent.java +++ b/src/test/java/org/asteriskjava/manager/internal/EEvent.java @@ -17,7 +17,6 @@ package org.asteriskjava.manager.internal; import org.asteriskjava.manager.event.ManagerEvent; -import org.asteriskjava.manager.event.UserEvent; public class EEvent extends ManagerEvent { From cb283e0377d6d104105caaf037ecf8ea1fae8b92 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 20 Sep 2022 12:48:49 +1000 Subject: [PATCH 513/802] allow setting dtmf duration on playDtmfAction --- .../manager/action/PlayDtmfAction.java | 156 ++++++++++-------- 1 file changed, 87 insertions(+), 69 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java b/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java index db4b9c175..0085810c1 100644 --- a/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java @@ -17,8 +17,10 @@ package org.asteriskjava.manager.action; /** - * The PlayDTMFAction plays a DTMF digit on the specified channel.

    - * It is definied in apps/app_senddtmf.c.

    + * The PlayDTMFAction plays a DTMF digit on the specified channel. + *

    + * It is definied in apps/app_senddtmf.c. + *

    * Available since Asterisk 1.2.8 * * @since 0.3 @@ -27,80 +29,96 @@ */ public class PlayDtmfAction extends AbstractManagerAction { - /** - * Serializable version identifier - */ - private static final long serialVersionUID = 9002288048692675696L; + /** + * Serializable version identifier + */ + private static final long serialVersionUID = 9002288048692675696L; - private String channel; - private String digit; + private String channel; + private String digit; + private Integer duration = null; - /** - * Creates a new empty PlayDtmfAction. - */ - public PlayDtmfAction() - { + /** + * Creates a new empty PlayDtmfAction. + */ + public PlayDtmfAction() + { - } + } - /** - * Creates a new PlayDtmfAction that sends the given DTMF digit to the given channel. - * - * @param channel the name of the channel to send the digit to. - * @param digit the DTML digit to play. - */ - public PlayDtmfAction(String channel, String digit) - { - this.channel = channel; - this.digit = digit; - } + /** + * Creates a new PlayDtmfAction that sends the given DTMF digit to the given + * channel. + * + * @param channel + * the name of the channel to send the digit to. + * @param digit + * the DTML digit to play. + */ + public PlayDtmfAction(String channel, String digit) + { + this.channel = channel; + this.digit = digit; + } - /** - * Returns the name of this action, i.e. "PlayDTMF". - */ - @Override - public String getAction() - { - return "PlayDTMF"; - } + /** + * Returns the name of this action, i.e. "PlayDTMF". + */ + @Override + public String getAction() + { + return "PlayDTMF"; + } - /** - * Returns the name of the channel to send the digit to. - * - * @return the name of the channel to send the digit to. - */ - public String getChannel() - { - return channel; - } + /** + * Returns the name of the channel to send the digit to. + * + * @return the name of the channel to send the digit to. + */ + public String getChannel() + { + return channel; + } - /** - * Sets the name of the channel to send the digit to. - * - * @param channel the name of the channel to send the digit to. - */ - public void setChannel(String channel) - { - this.channel = channel; - } + /** + * Sets the name of the channel to send the digit to. + * + * @param channel + * the name of the channel to send the digit to. + */ + public void setChannel(String channel) + { + this.channel = channel; + } - /** - * Returns the DTMF digit to play. - * - * @return the DTMF digit to play. - */ - public String getDigit() - { - return digit; - } + /** + * Returns the DTMF digit to play. + * + * @return the DTMF digit to play. + */ + public String getDigit() + { + return digit; + } - /** - * Sets the DTMF digit to play. - * - * @param digit the DTMF digit to play. - */ - public void setDigit(String digit) - { - this.digit = digit; - } + /** + * Sets the DTMF digit to play. + * + * @param digit + * the DTMF digit to play. + */ + public void setDigit(String digit) + { + this.digit = digit; + } + + public void setDuration(Integer duration) + { + this.duration = duration; + } + + public Integer getDuration() + { + return duration; + } } From ad0f6c50b3a1051a40c3f4205ae256bc0baf4589 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 20 Sep 2022 12:49:46 +1000 Subject: [PATCH 514/802] for version 3.31.0 --- README.md | 2 +- pom.xml | 2 +- src/main/java/META-INF/MANIFEST.MF | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 src/main/java/META-INF/MANIFEST.MF diff --git a/README.md b/README.md index 3ef75df8e..d6b953a27 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.30.0 + 3.31.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 17d816a45..5f8291f44 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ - 3.30.0 + 3.31.0 UTF-8 diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 000000000..5e9495128 --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + From c49d258546fc39318cb01a6b086b89b5b1a0ea12 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Sat, 3 Sep 2022 00:06:43 +0200 Subject: [PATCH 515/802] Add tests for fastagi commands --- .../fastagi/command/AbstractAgiCommand.java | 113 ++++++----- .../fastagi/command/AgiCommand.java | 30 ++- .../fastagi/command/AnswerCommand.java | 33 ++-- .../fastagi/command/AsyncAgiBreakCommand.java | 34 ++-- .../fastagi/command/BridgeCommand.java | 39 ++-- .../fastagi/command/ChannelStatusCommand.java | 46 +++-- .../fastagi/command/ConfbridgeCommand.java | 34 +++- .../command/ControlStreamFileCommand.java | 103 +++++----- .../fastagi/command/DatabaseDelCommand.java | 35 ++-- .../command/DatabaseDelTreeCommand.java | 36 ++-- .../fastagi/command/DatabaseGetCommand.java | 40 ++-- .../fastagi/command/DatabasePutCommand.java | 37 ++-- .../fastagi/command/DialCommand.java | 52 +++-- .../fastagi/command/ExecCommand.java | 50 ++--- .../fastagi/command/GetDataCommand.java | 46 ++--- .../command/GetFullVariableCommand.java | 49 +++-- .../fastagi/command/GetOptionCommand.java | 60 +++--- .../fastagi/command/GetVariableCommand.java | 41 ++-- .../fastagi/command/GosubCommand.java | 27 ++- .../fastagi/command/HangupCommand.java | 44 ++--- .../fastagi/command/MeetmeCommand.java | 35 +++- .../fastagi/command/NoopCommand.java | 32 ++-- .../fastagi/command/QueueCommand.java | 41 ++-- .../fastagi/command/ReceiveCharCommand.java | 45 ++--- .../fastagi/command/ReceiveTextCommand.java | 46 ++--- .../fastagi/command/RecordFileCommand.java | 85 +++------ .../fastagi/command/SayAlphaCommand.java | 40 ++-- .../fastagi/command/SayDateTimeCommand.java | 82 +++----- .../fastagi/command/SayDigitsCommand.java | 48 +++-- .../fastagi/command/SayNumberCommand.java | 45 ++--- .../fastagi/command/SayPhoneticCommand.java | 46 ++--- .../fastagi/command/SayTimeCommand.java | 44 ++--- .../fastagi/command/SendImageCommand.java | 36 ++-- .../fastagi/command/SendTextCommand.java | 32 ++-- .../fastagi/command/SetAutoHangupCommand.java | 46 ++--- .../fastagi/command/SetCallerIdCommand.java | 31 ++- .../fastagi/command/SetContextCommand.java | 31 ++- .../fastagi/command/SetExtensionCommand.java | 37 ++-- .../fastagi/command/SetMusicOffCommand.java | 32 ++-- .../fastagi/command/SetMusicOnCommand.java | 45 ++--- .../fastagi/command/SetPriorityCommand.java | 38 ++-- .../fastagi/command/SetVariableCommand.java | 36 ++-- .../command/SpeechActivateGrammarCommand.java | 35 ++-- .../fastagi/command/SpeechCreateCommand.java | 33 ++-- .../SpeechDeactivateGrammarCommand.java | 35 ++-- .../fastagi/command/SpeechDestroyCommand.java | 32 ++-- .../command/SpeechLoadGrammarCommand.java | 39 ++-- .../command/SpeechRecognizeCommand.java | 34 ++-- .../fastagi/command/SpeechSetCommand.java | 33 ++-- .../command/SpeechUnloadGrammarCommand.java | 35 ++-- .../fastagi/command/StreamFileCommand.java | 22 +-- .../fastagi/command/TddModeCommand.java | 38 ++-- .../fastagi/command/VerboseCommand.java | 32 ++-- .../fastagi/command/WaitForDigitCommand.java | 43 ++--- .../asteriskjava/fastagi/command/package.html | 3 +- .../command/AbstractAgiCommandTest.java | 177 ++++++++++++++---- .../fastagi/command/AnswerCommandTest.java | 34 ++++ .../command/AsyncAgiBreakCommandTest.java | 34 ++++ .../fastagi/command/BridgeCommandTest.java | 50 +++++ .../command/ChannelStatusCommandTest.java | 46 +++++ .../command/ConfbridgeCommandTest.java | 48 +++++ .../command/ControlStreamFileCommandTest.java | 83 ++++++++ .../command/DatabaseDelCommandTest.java | 46 +++++ .../command/DatabaseDelTreeCommandTest.java | 46 +++++ .../command/DatabaseGetCommandTest.java | 34 ++++ .../command/DatabasePutCommandTest.java | 34 ++++ .../fastagi/command/DialCommandTest.java | 48 +++++ .../fastagi/command/ExecCommandTest.java | 85 ++++++--- .../fastagi/command/GetDataCommandTest.java | 95 +++++++--- .../command/GetFullVariableCommandTest.java | 46 +++++ .../fastagi/command/GetOptionCommandTest.java | 46 +++++ .../fastagi/command/GosubCommandTest.java | 46 +++++ .../fastagi/command/HangupCommandTest.java | 46 +++++ .../fastagi/command/MeetmeCommandTest.java | 46 +++++ .../fastagi/command/NoopCommandTest.java | 34 ++++ .../fastagi/command/QueueCommandTest.java | 34 ++++ .../command/ReceiveCharCommandTest.java | 46 +++++ .../command/ReceiveTextCommandTest.java | 46 +++++ .../command/RecordFileCommandTest.java | 46 +++++ .../fastagi/command/SayAlphaCommandTest.java | 46 +++++ .../command/SayDateTimeCommandTest.java | 74 ++++++++ .../fastagi/command/SayDigitsCommandTest.java | 46 +++++ .../fastagi/command/SayNumberCommandTest.java | 46 +++++ .../command/SayPhoneticCommandTest.java | 46 +++++ .../fastagi/command/SayTimeCommandTest.java | 50 +++++ .../fastagi/command/SendImageCommandTest.java | 34 ++++ .../fastagi/command/SendTextCommandTest.java | 34 ++++ .../command/SetAutoHangupCommandTest.java | 34 ++++ .../command/SetCallerIdCommandTest.java | 34 ++++ .../command/SetContextCommandTest.java | 34 ++++ .../command/SetExtensionCommandTest.java | 34 ++++ .../command/SetMusicOffCommandTest.java | 34 ++++ .../command/SetMusicOnCommandTest.java | 46 +++++ .../command/SetPriorityCommandTest.java | 34 ++++ .../command/SetVariableCommandTest.java | 34 ++++ .../SpeechActivateGrammarCommandTest.java | 34 ++++ .../command/SpeechCreateCommandTest.java | 34 ++++ .../SpeechDeactivateGrammarCommandTest.java | 34 ++++ .../command/SpeechDestroyCommandTest.java | 34 ++++ .../command/SpeechLoadGrammarCommandTest.java | 34 ++++ .../command/SpeechRecognizeCommandTest.java | 46 +++++ .../fastagi/command/SpeechSetCommandTest.java | 34 ++++ .../SpeechUnloadGrammarCommandTest.java | 34 ++++ .../command/StreamFileCommandTest.java | 58 ++++++ .../fastagi/command/TddModeCommandTest.java | 34 ++++ .../fastagi/command/VerboseCommandTest.java | 34 ++++ .../command/WaitForDigitCommandTest.java | 46 +++++ 107 files changed, 3387 insertions(+), 1341 deletions(-) create mode 100644 src/test/java/org/asteriskjava/fastagi/command/AnswerCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/AsyncAgiBreakCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/BridgeCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/ChannelStatusCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/ConfbridgeCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/ControlStreamFileCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/DatabaseDelCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/DatabaseDelTreeCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/DatabaseGetCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/DatabasePutCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/DialCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/GetFullVariableCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/GetOptionCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/GosubCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/HangupCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/MeetmeCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/NoopCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/QueueCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/ReceiveCharCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/ReceiveTextCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/RecordFileCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SayAlphaCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SayDateTimeCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SayDigitsCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SayNumberCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SayPhoneticCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SayTimeCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SendImageCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SendTextCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SetAutoHangupCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SetCallerIdCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SetContextCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SetExtensionCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SetMusicOffCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SetMusicOnCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SetPriorityCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SetVariableCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SpeechActivateGrammarCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SpeechCreateCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SpeechDeactivateGrammarCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SpeechDestroyCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SpeechLoadGrammarCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SpeechRecognizeCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SpeechSetCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/SpeechUnloadGrammarCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/StreamFileCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/TddModeCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/VerboseCommandTest.java create mode 100644 src/test/java/org/asteriskjava/fastagi/command/WaitForDigitCommandTest.java diff --git a/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java b/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java index 844ee0ef7..595984897 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/AbstractAgiCommand.java @@ -1,102 +1,97 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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 org.asteriskjava.AsteriskVersion; import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; import java.io.Serializable; +import static java.lang.String.format; +import static java.lang.System.identityHashCode; +import static org.asteriskjava.AsteriskVersion.ASTERISK_1_4; +import static org.asteriskjava.util.LogFactory.getLog; + /** - * Abstract base class that provides some convenience methods for implementing - * AgiCommand classes. + * Abstract base class that provides some convenience methods for implementing {@link AgiCommand} classes. * * @author srt - * @version $Id$ */ public abstract class AbstractAgiCommand implements Serializable, AgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3257849874518456633L; + + private static final Log logger = getLog(AbstractAgiCommand.class); + private AsteriskVersion asteriskVersion; - private static final Log logger = LogFactory.getLog(AbstractAgiCommand.class); + AsteriskVersion getAsteriskVersion() { + if (asteriskVersion == null) { + logger.warn("Asterisk Version isn't known, returning 1.4"); + return ASTERISK_1_4; + } + return asteriskVersion; + } + + public void setAsteriskVersion(AsteriskVersion asteriskVersion) { + this.asteriskVersion = asteriskVersion; + } public abstract String buildCommand(); + @Override + public String toString() { + return format("%s[command='%s', systemHashcode=%d]", getClass().getName(), buildCommand(), identityHashCode(this)); + } + /** - * Escapes and quotes a given String according to the rules set by - * Asterisk's AGI. + * 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 + * @param string the string to escape and quote + * @return the escaped and quoted string */ - protected String escapeAndQuote(String s) { - String tmp; - - if (s == null) { + protected String escapeAndQuote(String string) { + if (string == null) { return "\"\""; } - tmp = s; - tmp = tmp.replaceAll("\\\\", "\\\\\\\\"); - tmp = tmp.replaceAll("\\\"", "\\\\\""); - tmp = tmp.replaceAll("\\\n", ""); // filter newline - return "\"" + tmp + "\""; // add quotes + string = string.replaceAll("\\\\", "\\\\\\\\"); + string = string.replaceAll("\\\"", "\\\\\""); + string = string.replaceAll("\\\n", ""); + return format("\"%s\"", string); } - protected String escapeAndQuote(String[] options) { - if (options == null) { + /** + * Escapes and quotes a given strings according to the rules set by Asterisk's AGI. + * + * @param strings the strings to escape and quote + * @return the escaped and quoted joined string + */ + protected String escapeAndQuote(String[] strings) { + if (strings == null) { return escapeAndQuote((String) null); } final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < options.length; i++) { + for (int i = 0; i < strings.length; i++) { if (i > 0) { sb.append(","); } - sb.append(options[i]); + sb.append(strings[i]); } return escapeAndQuote(sb.toString()); } - - @Override - public String toString() { - StringBuilder sb; - - sb = new StringBuilder(getClass().getName()).append("["); - sb.append("command='").append(buildCommand()).append("', "); - sb.append("systemHashcode=").append(System.identityHashCode(this)).append("]"); - - return sb.toString(); - } - - public void setAsteriskVersion(AsteriskVersion asteriskVersion) { - this.asteriskVersion = asteriskVersion; - } - - AsteriskVersion getAsteriskVersion() { - if (asteriskVersion == null) { - logger.warn("Asterisk Version isn't known, returning 1.4"); - return AsteriskVersion.ASTERISK_1_4; - } - return asteriskVersion; - } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/AgiCommand.java b/src/main/java/org/asteriskjava/fastagi/command/AgiCommand.java index 8f9dedb51..73dc10242 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/AgiCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/AgiCommand.java @@ -1,35 +1,31 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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 org.asteriskjava.AsteriskVersion; /** - * AgiCommand that can be sent to Asterisk via the Asterisk Gateway Interface.

    - * This interface contains only one method that transforms the command to a - * String representation understood by Asterisk. + * AgiCommand that can be sent to Asterisk via the Asterisk Gateway Interface (AGI).

    + * This interface contains only one method that transforms the command to a string representation understood by Asterisk. * * @author srt - * @version $Id$ */ public interface AgiCommand { - /** - * Returns a string suitable to be sent to asterisk.

    + * Returns a string suitable to be sent to asterisk. * * @return a string suitable to be sent to asterisk. */ diff --git a/src/main/java/org/asteriskjava/fastagi/command/AnswerCommand.java b/src/main/java/org/asteriskjava/fastagi/command/AnswerCommand.java index 7539ab407..c9c7337ed 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/AnswerCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/AnswerCommand.java @@ -1,37 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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.

    - * Returns -1 on channel failure, or 0 if successful. + * AGI Command: ANSWER (Asterisk 18) + *

    + * Answer channel. * * @author srt - * @version $Id$ */ public class AnswerCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3762248656229053753L; - /** - * Creates a new AnswerCommand. - */ public AnswerCommand() { super(); } diff --git a/src/main/java/org/asteriskjava/fastagi/command/AsyncAgiBreakCommand.java b/src/main/java/org/asteriskjava/fastagi/command/AsyncAgiBreakCommand.java index 3d26ce33e..e646b2044 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/AsyncAgiBreakCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/AsyncAgiBreakCommand.java @@ -1,36 +1,32 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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. + * AGI Command ASYNCAGI BREAK + *

    + * Interrupts expected flow of Async AGI commands and returns control to previous source (typically, the PBX dialplan). + *

    + * See: AGI Command ASYNCAGI BREAK (Asterisk 18) * * @author srt - * @version $Id$ */ public class AsyncAgiBreakCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 1L; - /** - * Creates a new AsyncAgiBreakCommand. - */ public AsyncAgiBreakCommand() { super(); } diff --git a/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java index fe5da6c37..758f6ffd2 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/BridgeCommand.java @@ -1,18 +1,36 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.asteriskjava.AsteriskVersion; +import static org.asteriskjava.AsteriskVersion.ASTERISK_13; +/** + * This is not a real AGI command. + *

    + * It uses EXEC command and add bridge application features. + *

    + * See: AGI Command EXEC (Asterisk 18)
    + * See: Application Bridge (Asterisk 18) + */ public class BridgeCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3762248656229053753L; - private String options; - private String channel; - /** - * Creates a new AnswerCommand. - */ + private final String channel; + private final String options; + public BridgeCommand(String channel, String options) { super(); this.channel = channel; @@ -23,7 +41,7 @@ public BridgeCommand(String channel, String options) { public String buildCommand() { String command = "EXEC " + escapeAndQuote("bridge") + " " + escapeAndQuote(channel); if (options != null && options.length() > 0) { - if (getAsteriskVersion().isAtLeast(AsteriskVersion.ASTERISK_13)) { + if (getAsteriskVersion().isAtLeast(ASTERISK_13)) { command += "," + escapeAndQuote(options); } else { command += "|" + escapeAndQuote(options); @@ -31,6 +49,5 @@ public String buildCommand() { } return command; - } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/ChannelStatusCommand.java b/src/main/java/org/asteriskjava/fastagi/command/ChannelStatusCommand.java index 2327f41c0..a36063127 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/ChannelStatusCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/ChannelStatusCommand.java @@ -1,24 +1,26 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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.

    + * AGI Command: CHANNEL STATUS + *

    + * Returns the status of the specified channel. + * If no channel name is given the returns the status of the current channel. + *

    * Return values: *

      *
    • 0 Channel is down and available @@ -30,19 +32,16 @@ *
    • 6 Line is up *
    • 7 Line is busy *
    + *

    + * See: AGI Command CHANNEL STATUS (Asterisk 18) * * @author srt - * @version $Id$ */ public class ChannelStatusCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3904959746380281145L; /** - * The name of the channel to query or null for the current - * channel. + * The name of the channel to query or null for the current channel. */ private String channel; @@ -66,8 +65,7 @@ public ChannelStatusCommand(String channel) { /** * Returns the name of the channel to query. * - * @return the name of the channel to query or null for the - * current channel. + * @return the name of the channel to query or null for the current channel. */ public String getChannel() { return channel; @@ -76,8 +74,7 @@ public String getChannel() { /** * Sets the name of the channel to query. * - * @param channel the name of the channel to query or null - * for the current channel. + * @param channel the name of the channel to query or null for the current channel. */ public void setChannel(String channel) { this.channel = channel; @@ -85,7 +82,6 @@ public void setChannel(String channel) { @Override public String buildCommand() { - return "CHANNEL STATUS" - + (channel == null ? "" : " " + escapeAndQuote(channel)); + return "CHANNEL STATUS" + (channel == null ? "" : " " + escapeAndQuote(channel)); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/ConfbridgeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/ConfbridgeCommand.java index 16e1bba33..60f6a70c9 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/ConfbridgeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/ConfbridgeCommand.java @@ -1,18 +1,36 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.asteriskjava.AsteriskVersion; +/** + * This is not a real AGI command. + *

    + * It uses EXEC command and add confbridge application features. + *

    + * See: AGI Command EXEC (Asterisk 18)
    + * See: Application ConfBridge (Asterisk 18) + */ public class ConfbridgeCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3762248656229053753L; - private String room; - private String profile; - /** - * Creates a new AnswerCommand. - */ + private final String room; + private final String profile; + public ConfbridgeCommand(String room, String profile) { super(); this.room = room; diff --git a/src/main/java/org/asteriskjava/fastagi/command/ControlStreamFileCommand.java b/src/main/java/org/asteriskjava/fastagi/command/ControlStreamFileCommand.java index be77a36ab..696c71ff4 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/ControlStreamFileCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/ControlStreamFileCommand.java @@ -1,40 +1,34 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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.

    - * If offset is provided then the audio will seek to sample offset before play - * starts.

    - * 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.

    - * Remember, the file extension must not be included in the filename.

    - * Available since Asterisk 1.2 + * AGI Command: CONTROL STREAM FILE + *

    + * Send the given file, allowing playback to be controlled by the given digits, if any. + * Use double quotes for the digits if you wish none to be permitted. + * If offsetms is provided then the audio will seek to offsetms before play starts. + * 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. Returns the position where playback was terminated as endpos. + *

    + * See: AGI Command CONTROL STREAM FILE (Asterisk 18) * * @author srt - * @version $Id$ - * @since 0.2 */ public class ControlStreamFileCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3978141041352128820L; /** @@ -59,9 +53,8 @@ public class ControlStreamFileCommand extends AbstractAgiCommand { 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. + * 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. */ @@ -72,13 +65,11 @@ public ControlStreamFileCommand(String file) { } /** - * Creates a new ControlStreamFileCommand, streaming from the beginning. It - * uses the default digit "#" for forward and "*" for rewind and does not - * support pausing. + * 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. + * @param escapeDigits contains the digits that allow the user to interrupt this command. */ public ControlStreamFileCommand(String file, String escapeDigits) { super(); @@ -89,13 +80,11 @@ public ControlStreamFileCommand(String file, String escapeDigits) { /** * Creates a new ControlStreamFileCommand, streaming from the given offset. - * It uses the default digit "#" for forward and "*" for rewind and does not - * support pausing. + * 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 null if you don't want the - * user to interrupt. + * @param escapeDigits contains the digits that allow the user to interrupt this command. + * May be null 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) { @@ -110,17 +99,16 @@ public ControlStreamFileCommand(String file, String escapeDigits, int 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 null if you don't want the - * user to interrupt. + * @param escapeDigits contains the digits that allow the user to interrupt this command. + * May be null 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 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) { + public ControlStreamFileCommand( + String file, String escapeDigits, int offset, String forwardDigit, String rewindDigit, String pauseDigit + ) { super(); this.file = file; this.escapeDigits = escapeDigits; @@ -160,8 +148,7 @@ public String getEscapeDigits() { /** * Sets the digits that allow the user to interrupt this command. * - * @param escapeDigits the digits that allow the user to interrupt this - * command or null for none. + * @param escapeDigits the digits that allow the user to interrupt this command or null for none. */ public void setEscapeDigits(String escapeDigits) { this.escapeDigits = escapeDigits; @@ -186,9 +173,9 @@ public void setOffset(int offset) { } /** - * Returns the digit for fast forward. + * Returns the digit for fast-forward. * - * @return the digit for fast forward. + * @return the digit for fast-forward. */ public String getForwardDigit() { return forwardDigit; @@ -213,9 +200,9 @@ public String getPauseDigit() { } /** - * Sets the control digits for fast forward and rewind. + * Sets the control digits for fast-forward and rewind. * - * @param forwardDigit the digit for fast forward. + * @param forwardDigit the digit for fast-forward. * @param rewindDigit the digit for rewind. */ public void setControlDigits(String forwardDigit, String rewindDigit) { @@ -224,14 +211,13 @@ public void setControlDigits(String forwardDigit, String rewindDigit) { } /** - * Sets the control digits for fast forward, rewind and pause. + * Sets the control digits for fast-forward, rewind and pause. * - * @param forwardDigit the digit for fast forward. + * @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) { + public void setControlDigits(String forwardDigit, String rewindDigit, String pauseDigit) { this.forwardDigit = forwardDigit; this.rewindDigit = rewindDigit; this.pauseDigit = pauseDigit; @@ -239,17 +225,14 @@ public void setControlDigits(String forwardDigit, String rewindDigit, @Override public String buildCommand() { - StringBuilder sb; - - sb = new StringBuilder("CONTROL STREAM FILE "); + StringBuilder sb = new StringBuilder("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) { + } else if (forwardDigit != null || rewindDigit != null || pauseDigit != null) { sb.append(" 0"); } diff --git a/src/main/java/org/asteriskjava/fastagi/command/DatabaseDelCommand.java b/src/main/java/org/asteriskjava/fastagi/command/DatabaseDelCommand.java index efc51f7aa..1c94366ac 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/DatabaseDelCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/DatabaseDelCommand.java @@ -1,33 +1,31 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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.

    + * AGI Command: DATABASE DEL + *

    + * Deletes an entry in the Asterisk database for a given family and key.
    * Returns 1 if successful, 0 otherwise. + *

    + * See: AGI Command DATABASE DEL (Asterisk 18) * * @author srt - * @version $Id$ */ public class DatabaseDelCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** @@ -100,7 +98,6 @@ public void setKeyTree(String keyTree) { @Override public String buildCommand() { - return "DATABASE DELTREE " + escapeAndQuote(family) - + (keyTree == null ? "" : " " + escapeAndQuote(keyTree)); + return "DATABASE DEL " + escapeAndQuote(family) + (keyTree == null ? "" : " " + escapeAndQuote(keyTree)); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/DatabaseDelTreeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/DatabaseDelTreeCommand.java index 45aefcc6b..17e438797 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/DatabaseDelTreeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/DatabaseDelTreeCommand.java @@ -1,34 +1,31 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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. + * AGI Command: DATABASE DELTREE *

    + * Deletes a family or specific keytree within a family in the Asterisk database.
    * Returns 1 if successful, 0 otherwise. + *

    + * See: AGI Command DATABASE DELTREE (Asterisk 18) * * @author srt - * @version $Id$ */ public class DatabaseDelTreeCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** @@ -83,7 +80,7 @@ public void setFamily(String family) { } /** - * Returns the the keytree to delete. + * Returns the keytree to delete. * * @return the keytree to delete. */ @@ -94,8 +91,7 @@ public String getKeyTree() { /** * Sets the keytree to delete. * - * @param keyTree the keytree to delete, null to delete the - * whole family. + * @param keyTree the keytree to delete, null to delete the whole family. */ public void setKeyTree(String keyTree) { this.keyTree = keyTree; diff --git a/src/main/java/org/asteriskjava/fastagi/command/DatabaseGetCommand.java b/src/main/java/org/asteriskjava/fastagi/command/DatabaseGetCommand.java index e8f1d802d..740d0a4d6 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/DatabaseGetCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/DatabaseGetCommand.java @@ -1,34 +1,31 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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.

    - * Returns 0 if is not set. Returns 1 if the variable is set and returns the - * value in parenthesis.

    - * Example return code: 200 result=1 (testvariable) + * AGI Command: DATABASE GET + *

    + * Retrieves an entry in the Asterisk database for a given family and key.
    + * Returns 0 if is not set. Returns 1 if the variable is set and returns the value in parentheses. + *

    + * See: AGI Command DATABASE GET (Asterisk 18) * * @author srt - * @version $Id$ */ public class DatabaseGetCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** @@ -72,7 +69,7 @@ public void setFamily(String family) { } /** - * Returns the the key to retrieve. + * Returns the key to retrieve. * * @return the key to retrieve. */ @@ -91,7 +88,6 @@ public void setKey(String key) { @Override public String buildCommand() { - return "DATABASE GET " + escapeAndQuote(family) + " " - + escapeAndQuote(key); + return "DATABASE GET " + escapeAndQuote(family) + " " + escapeAndQuote(key); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/DatabasePutCommand.java b/src/main/java/org/asteriskjava/fastagi/command/DatabasePutCommand.java index 57cc7baab..808edddf8 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/DatabasePutCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/DatabasePutCommand.java @@ -1,33 +1,31 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Adds or updates an entry in the Asterisk database for a given family, key, - * and value.

    + * AGI Command: DATABASE PUT + *

    + * Adds or updates an entry in the Asterisk database for a given family, key, and value.
    * Returns 1 if successful, 0 otherwise. + *

    + * See: AGI Command DATABASE PUT (Asterisk 18) * * @author srt - * @version $Id$ */ public class DatabasePutCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** @@ -78,7 +76,7 @@ public void setFamily(String family) { } /** - * Returns the the key to set. + * Returns the key to set. * * @return the key to set. */ @@ -115,7 +113,6 @@ public void setValue(String value) { @Override public String buildCommand() { - return "DATABASE PUT " + escapeAndQuote(family) + " " - + escapeAndQuote(key) + " " + escapeAndQuote(value); + return "DATABASE PUT " + escapeAndQuote(family) + " " + escapeAndQuote(key) + " " + escapeAndQuote(value); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java index 0f5c3d8d7..e306f8e46 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/DialCommand.java @@ -1,22 +1,42 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.asteriskjava.AsteriskVersion; import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; +import static org.asteriskjava.AsteriskVersion.ASTERISK_10; +import static org.asteriskjava.util.LogFactory.getLog; + +/** + * This is not a real AGI command. + *

    + * It uses EXEC command and add dial application features. + *

    + * See: AGI Command EXEC (Asterisk 18)
    + * See: Application Dial (Asterisk 18) + */ public class DialCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3762248656229053753L; - private String options; - private String target; - private int timeout; - private final Log logger = LogFactory.getLog(getClass()); - - /** - * Creates a new AnswerCommand. - */ + + private final Log logger = getLog(getClass()); + + private final String target; + private final int timeout; + private final String options; + public DialCommand(String target, int timeout, String options) { super(); this.target = target; @@ -28,12 +48,11 @@ public DialCommand(String target, int timeout, String options) { public String buildCommand() { String separator = "|"; - if (getAsteriskVersion().isAtLeast(AsteriskVersion.ASTERISK_10)) { + if (getAsteriskVersion().isAtLeast(ASTERISK_10)) { separator = ","; } - String command = "EXEC " + escapeAndQuote("dial") + " " + escapeAndQuote(target) + separator - + escapeAndQuote("" + timeout); + String command = "EXEC " + escapeAndQuote("dial") + " " + escapeAndQuote(target) + separator + escapeAndQuote("" + timeout); if (options != null && options.length() > 0) { command += separator + escapeAndQuote(options); } @@ -41,6 +60,5 @@ public String buildCommand() { logger.info(command); return command; - } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/ExecCommand.java b/src/main/java/org/asteriskjava/fastagi/command/ExecCommand.java index f842e92b4..636bc0f36 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/ExecCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/ExecCommand.java @@ -1,33 +1,33 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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 static java.lang.String.format; + /** - * Executes an application with the given options.

    - * Returns whatever the application returns, or -2 if the application was not - * found. + * AGI Command: EXEC + *

    + * Executes an application with the given options.
    + * Returns whatever the application returns, or -2 if the application was not found. + *

    + * See: EXEC (Asterisk 18) * * @author srt - * @version $Id$ */ public class ExecCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3904959746380281145L; /** @@ -40,22 +40,11 @@ public class ExecCommand extends AbstractAgiCommand { */ private String[] options; - /** - * Creates a new ExecCommand. - * - * @param application the name of the application to execute. - */ public ExecCommand(String application) { super(); this.application = application; } - /** - * Creates a new ExecCommand. - * - * @param application the name of the application to execute. - * @param options the options to pass to the application. - */ public ExecCommand(String application, String... options) { super(); this.application = application; @@ -100,7 +89,6 @@ public void setOptions(String... options) { @Override public String buildCommand() { - return "EXEC " + escapeAndQuote(application) + " " - + escapeAndQuote(options); + return format("EXEC %s %s", escapeAndQuote(application), escapeAndQuote(options)); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/GetDataCommand.java b/src/main/java/org/asteriskjava/fastagi/command/GetDataCommand.java index 7734914b7..64bd2c31d 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/GetDataCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/GetDataCommand.java @@ -17,25 +17,22 @@ package org.asteriskjava.fastagi.command; /** - * Stream the given file, and recieve DTMF data. The user may interrupt the - * streaming by starting to enter digits. + * AGI Command: GET DATA *

    - * Returns the digits recieved from the channel at the other end. + * Stream the given file, and receive DTMF data. The user may interrupt the streaming by starting to enter digits.
    + * Returns the digits received from the channel at the other end. *

    - * Input ends when the timeout is reached, the maximum number of digits is read - * or the user presses #. + * Input ends when the timeout is reached, the maximum number of digits is read or the user presses #. + *

    + * See: AGI Command GET DATA (Asterisk 18) * * @author srt - * @version $Id$ */ public class GetDataCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3978141041352128820L; - private static final int DEFAULT_MAX_DIGITS = 1024; private static final int DEFAULT_TIMEOUT = 0; + private static final int DEFAULT_MAX_DIGITS = 1024; /** * The name of the file to stream. @@ -45,8 +42,7 @@ public class GetDataCommand extends AbstractAgiCommand { /** * The timeout in milliseconds to wait for data. *

    - * 0 means standard timeout value, -1 means "ludicrous time" (essentially - * never times out). + * 0 means standard timeout value, -1 means "ludicrous time" (essentially never times out). */ private long timeout; @@ -58,8 +54,7 @@ public class GetDataCommand extends AbstractAgiCommand { private int maxDigits; /** - * Creates a new GetDataCommand with default timeout and maxDigits set to - * 1024. + * Creates a new GetDataCommand with default timeout and maxDigits set to 1024. * * @param file the name of the file to stream, must not include extension. */ @@ -77,8 +72,7 @@ public GetDataCommand(String file) { * @param file the name of the file to stream, must not include extension. * @param timeout the timeout in milliseconds to wait for data. *

    - * 0 means standard timeout value, -1 means "ludicrous time" - * (essentially never times out). + * 0 means standard timeout value, -1 means "ludicrous time" (essentially never times out). */ public GetDataCommand(String file, long timeout) { super(); @@ -93,8 +87,7 @@ public GetDataCommand(String file, long timeout) { * @param file the name of the file to stream, must not include extension. * @param timeout the timeout in milliseconds to wait for data. *

    - * 0 means standard timeout value, -1 means "ludicrous time" - * (essentially never times out). + * 0 means standard timeout value, -1 means "ludicrous time" (essentially never times out). * @param maxDigits the maximum number of digits to read. *

    * Must be in [1..1024]. @@ -102,9 +95,7 @@ public GetDataCommand(String file, long timeout) { */ public GetDataCommand(String file, long timeout, int maxDigits) throws IllegalArgumentException { super(); - if (maxDigits < 1 || maxDigits > 1024) { - throw new IllegalArgumentException("maxDigits must be in [1..1024]"); - } + validateMaxDigits(maxDigits); this.file = file; this.timeout = timeout; @@ -145,8 +136,7 @@ public long getTimeout() { * * @param timeout the timeout in milliseconds to wait for data. *

    - * 0 means standard timeout value, -1 means "ludicrous time" - * (essentially never times out). + * 0 means standard timeout value, -1 means "ludicrous time" (essentially never times out). */ public void setTimeout(long timeout) { this.timeout = timeout; @@ -170,9 +160,7 @@ public int getMaxDigits() { * @throws IllegalArgumentException if maxDigits is not in [1..1024] */ public void setMaxDigits(int maxDigits) throws IllegalArgumentException { - if (maxDigits < 1 || maxDigits > 1024) { - throw new IllegalArgumentException("maxDigits must be in [1..1024]"); - } + validateMaxDigits(maxDigits); this.maxDigits = maxDigits; } @@ -187,4 +175,10 @@ public String buildCommand() { } return "GET DATA " + escapeAndQuote(file) + " " + timeout + " " + maxDigits; } + + private static void validateMaxDigits(int maxDigits) { + if (maxDigits < 1 || maxDigits > 1024) { + throw new IllegalArgumentException("maxDigits must be in [1..1024]"); + } + } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/GetFullVariableCommand.java b/src/main/java/org/asteriskjava/fastagi/command/GetFullVariableCommand.java index d3048734c..a5277cbaa 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/GetFullVariableCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/GetFullVariableCommand.java @@ -1,40 +1,34 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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 value of the given channel varible and understands complex - * variable names and builtin variables, unlike the GetVariableCommand.

    - * You can also use this command to use custom Asterisk functions. Syntax is - * "func(args)".

    - * Returns 0 if the variable is not set or channel does not exist. Returns 1 if - * the variable is set and returns the variable in parenthesis.

    - * Available since Asterisk 1.2

    + * AGI Command: GET FULL VARIABLE + *

    + * Evaluates the given expression against the channel specified by channelname, or the current channel if channelname is not provided.
    + * Unlike GET VARIABLE, the expression is processed in a manner similar to dialplan evaluation, + * allowing complex and built-in variables to be accessed, e.g. The time is ${EPOCH}
    + * Returns 0 if no channel matching channelname exists, 1 otherwise.
    * Example return code: 200 result=1 (testvariable) + *

    + * See: AGI Command GET FULL VARIABLE (Asterisk 18) * * @author srt - * @version $Id$ - * @see org.asteriskjava.fastagi.command.GetVariableCommand - * @since 0.2 */ public class GetFullVariableCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** @@ -69,7 +63,7 @@ public GetFullVariableCommand(String variable, String channel) { /** * Returns the name of the variable to retrieve. * - * @return the the name of the variable to retrieve. + * @return the name of the variable to retrieve. */ public String getVariable() { return variable; @@ -77,8 +71,7 @@ public String getVariable() { /** * Sets the name of the variable to retrieve.

    - * You can also use custom dialplan functions (like "func(args)") as - * variable. + * You can also use custom dialplan functions (like "func(args)") as variable. * * @param variable the name of the variable to retrieve. */ @@ -87,7 +80,7 @@ public void setVariable(String variable) { } /** - * Returns the the name of the channel. + * Returns the name of the channel. * * @return the name of the channel. */ diff --git a/src/main/java/org/asteriskjava/fastagi/command/GetOptionCommand.java b/src/main/java/org/asteriskjava/fastagi/command/GetOptionCommand.java index 03020cbef..edce75aa6 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/GetOptionCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/GetOptionCommand.java @@ -1,39 +1,32 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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, and waits for the user to press one of the given - * digits. If none of the esacpe digits is pressed while streaming the file this - * command waits for the specified timeout still waiting for the user to press a - * digit. Streaming always begins at the beginning.

    - * Returns 0 if no 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. - *
    + * AGI Command: GET OPTION + *

    + * Behaves similar to STREAM FILE but used with a timeout option.
    * Remember, the file extension must not be included in the filename. + *

    + * See: AGI Command GET OPTION (Asterisk 18) * * @author srt - * @version $Id$ - * @see org.asteriskjava.fastagi.command.StreamFileCommand + * @see StreamFileCommand */ public class GetOptionCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3978141041352128820L; /** @@ -55,8 +48,7 @@ public class GetOptionCommand extends AbstractAgiCommand { * Creates a new GetOptionCommand with a default timeout of 5 seconds. * * @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 escapeDigits contains the digits that the user is expected to press. */ public GetOptionCommand(String file, String escapeDigits) { super(); @@ -69,10 +61,8 @@ public GetOptionCommand(String file, String escapeDigits) { * Creates a new GetOptionCommand with the given timeout. * * @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. + * @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 escape digits was presses while streaming. */ public GetOptionCommand(String file, String escapeDigits, long timeout) { super(); @@ -118,8 +108,7 @@ public void setEscapeDigits(String escapeDigits) { } /** - * Returns the timeout to wait if none of the defined esacpe digits was - * presses while streaming. + * Returns the timeout to wait if none of the defined escape digits was presses while streaming. * * @return the timeout in milliseconds. */ @@ -128,10 +117,9 @@ public long getTimeout() { } /** - * Sets the timeout to wait if none of the defined esacpe digits was presses - * while streaming. + * Sets the timeout to wait if none of the defined escape digits was presses while streaming. * - * @param timeout the timeout in milliks,seconds. + * @param timeout the timeout in millis,seconds. */ public void setTimeout(long timeout) { this.timeout = timeout; @@ -139,8 +127,6 @@ public void setTimeout(long timeout) { @Override public String buildCommand() { - return "GET OPTION " + escapeAndQuote(file) + " " - + escapeAndQuote(escapeDigits) - + (timeout < 0 ? "" : " " + timeout); + return "GET OPTION " + escapeAndQuote(file) + " " + escapeAndQuote(escapeDigits) + (timeout < 0 ? "" : " " + timeout); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/GetVariableCommand.java b/src/main/java/org/asteriskjava/fastagi/command/GetVariableCommand.java index 394db6cb8..1dcf263d3 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/GetVariableCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/GetVariableCommand.java @@ -1,36 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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 value of the given channel varible.

    - * Since Asterisk 1.2 you can also use this command to use custom Asterisk - * functions. Syntax is "func(args)".

    - * Returns 0 if the variable is not set. Returns 1 if the variable is set and - * returns the variable in parenthesis.

    - * Example return code: 200 result=1 (testvariable) + * AGI Command: GET VARIABLE + *

    + * Gets a channel variable. + *

    + * See: AGI Command GET VARIABLE (Asterisk 18) * * @author srt - * @version $Id$ */ public class GetVariableCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** @@ -51,7 +45,7 @@ public GetVariableCommand(String variable) { /** * Returns the name of the variable to retrieve. * - * @return the the name of the variable to retrieve. + * @return the name of the variable to retrieve. */ public String getVariable() { return variable; @@ -59,8 +53,7 @@ public String getVariable() { /** * Sets the name of the variable to retrieve.

    - * Since Asterisk 1.2 you can also use custom dialplan functions (like - * "func(args)") as variable. + * Since Asterisk 1.2 you can also use custom dialplan functions (like "func(args)") as variable. * * @param variable the name of the variable to retrieve. */ diff --git a/src/main/java/org/asteriskjava/fastagi/command/GosubCommand.java b/src/main/java/org/asteriskjava/fastagi/command/GosubCommand.java index 22311a118..73015b708 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/GosubCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/GosubCommand.java @@ -1,11 +1,26 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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; /** - * Calls a subroutine from dialplan. - *
    - * Example return code: 200 result=0 Gosub complete - *
    - * This command is available since Asterisk 1.6. + * AGI Command: GOSUB + *

    + * Cause the channel to execute the specified dialplan subroutine. + *

    + * See: AGI Command GOSUB (Asterisk 18) * * @author fadishei * @since 1.0.0 @@ -30,7 +45,7 @@ public class GosubCommand extends AbstractAgiCommand { /** * an optional list of arguments to be passed to the subroutine. - * They will accessible in the form of ${ARG1}, ${ARG2}, etc in the subroutine body. + * They will be accessible in the form of ${ARG1}, ${ARG2}, etc in the subroutine body. */ private String[] arguments; diff --git a/src/main/java/org/asteriskjava/fastagi/command/HangupCommand.java b/src/main/java/org/asteriskjava/fastagi/command/HangupCommand.java index 270baccb5..274eaa0f4 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/HangupCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/HangupCommand.java @@ -1,37 +1,34 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Hangs up the specified channel. If no channel name is given, hangs up the - * current channel. + * AGI Command: HANGUP + *

    + * Hangs up the specified channel. If no channel name is given, hangs up the current channel. + *

    + * See: AGI Command HANGUP (Asterisk 18) * * @author srt - * @version $Id$ */ public class HangupCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3904959746380281145L; /** - * The name of the channel to hangup or null for the current - * channel. + * The name of the channel to hangup or null for the current channel. */ private String channel; @@ -55,8 +52,7 @@ public HangupCommand(String channel) { /** * Returns the name of the channel to hangup. * - * @return the name of the channel to hangup or null for the - * current channel. + * @return the name of the channel to hangup or null for the current channel. */ public String getChannel() { return channel; @@ -65,8 +61,7 @@ public String getChannel() { /** * Sets the name of the channel to hangup. * - * @param channel the name of the channel to hangup or null - * for the current channel. + * @param channel the name of the channel to hangup or null for the current channel. */ public void setChannel(String channel) { this.channel = channel; @@ -74,7 +69,6 @@ public void setChannel(String channel) { @Override public String buildCommand() { - return "HANGUP" - + (channel == null ? "" : " " + escapeAndQuote(channel)); + return "HANGUP" + (channel == null ? "" : " " + escapeAndQuote(channel)); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/MeetmeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/MeetmeCommand.java index 7a1b324fd..328bde93c 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/MeetmeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/MeetmeCommand.java @@ -1,16 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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; +/** + * This is not a real AGI command. + *

    + * It uses EXEC command and add meetme application features. + *

    + * See: AGI Command EXEC (Asterisk 18)
    + * See: Application MeetMe (Asterisk 18) + */ public class MeetmeCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3762248656229053753L; - private String room; - private String options; - /** - * Creates a new AnswerCommand. - */ + private final String room; + private final String options; + public MeetmeCommand(String room, String options) { super(); this.room = room; @@ -25,6 +43,5 @@ public String buildCommand() { } return command; - } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/NoopCommand.java b/src/main/java/org/asteriskjava/fastagi/command/NoopCommand.java index fa0c1d90a..f3b3de077 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/NoopCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/NoopCommand.java @@ -1,36 +1,32 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** + * AGI Command: NOOP + *

    * Does nothing. + *

    + * See: AGI Command NOOP (Asterisk 18) * * @author srt - * @version $Id$ */ public class NoopCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3762248656229053753L; - /** - * Creates a new NoopCommand. - */ public NoopCommand() { super(); } diff --git a/src/main/java/org/asteriskjava/fastagi/command/QueueCommand.java b/src/main/java/org/asteriskjava/fastagi/command/QueueCommand.java index 1b606e383..8452a8466 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/QueueCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/QueueCommand.java @@ -1,17 +1,33 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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; +/** + * This is not a real AGI command. + *

    + * It uses EXEC command and add queue application features. + *

    + * See: AGI Command EXEC (Asterisk 18)
    + * See: Application Queue (Asterisk 18) + */ public class QueueCommand extends AbstractAgiCommand { - - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3762248656229053753L; - private String queue; + private final String queue; - /** - * Creates a new AnswerCommand. - */ public QueueCommand(String queue) { super(); this.queue = queue; @@ -20,13 +36,6 @@ public QueueCommand(String queue) { @Override public String buildCommand() { - String command = "EXEC " + escapeAndQuote("queue") + " " + escapeAndQuote(queue); - // if (options != null && options.length() > 0) - // { - // command += " " + escapeAndQuote(options); - // } - - return command; - + return "EXEC " + escapeAndQuote("queue") + " " + escapeAndQuote(queue); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/ReceiveCharCommand.java b/src/main/java/org/asteriskjava/fastagi/command/ReceiveCharCommand.java index 422763e34..e26c34c84 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/ReceiveCharCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/ReceiveCharCommand.java @@ -1,36 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Receives a character of text on a channel.

    - * Specify timeout to be the maximum time to wait for input in milliseconds, or - * 0 for infinite.

    - * Most channels do not support the reception of text.

    - * Returns the decimal value of the character if one is received, or 0 if the - * channel does not support text reception. Returns -1 only on error/hangup. + * AGI Command: RECEIVE CHAR + *

    + * Receives one character from channels supporting it. + *

    + * See: AGI CommandRECEIVE CHAR (Asterisk 18) * * @author srt - * @version $Id$ */ public class ReceiveCharCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** @@ -39,8 +33,7 @@ public class ReceiveCharCommand extends AbstractAgiCommand { private int timeout; /** - * Creates a new ReceiveCharCommand with a default timeout of 0 meaning to - * wait for ever. + * Creates a new ReceiveCharCommand with a default timeout of 0 meaning to wait forever. */ public ReceiveCharCommand() { super(); @@ -50,8 +43,7 @@ public ReceiveCharCommand() { /** * Creates a new ReceiveCharCommand. * - * @param timeout the milliseconds to wait for the channel to receive a - * character. + * @param timeout the milliseconds to wait for the channel to receive a character. */ public ReceiveCharCommand(int timeout) { super(); @@ -70,8 +62,7 @@ public int getTimeout() { /** * Sets the milliseconds to wait for the channel to receive a character. * - * @param timeout the milliseconds to wait for the channel to receive a - * character. + * @param timeout the milliseconds to wait for the channel to receive a character. */ public void setTimeout(int timeout) { this.timeout = timeout; diff --git a/src/main/java/org/asteriskjava/fastagi/command/ReceiveTextCommand.java b/src/main/java/org/asteriskjava/fastagi/command/ReceiveTextCommand.java index c43589293..3f1454ab4 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/ReceiveTextCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/ReceiveTextCommand.java @@ -1,37 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Receives a string of text on a channel.

    - * Specify timeout to be the maximum time to wait for input in milliseconds, or - * 0 for infinite.

    - * Most channels do not support the reception of text.

    - * Returns -1 for failure or 1 for success, and the string in parentheses.

    - * Available since Asterisk 1.2. + * AGI Command: RECEIVE TEXT + *

    + * Receives text from channels supporting it. + *

    + * See: AGI Command RECEIVE TEXT (Asterisk 18) * * @author srt - * @version $Id$ - * @since 0.2 */ public class ReceiveTextCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** @@ -40,8 +33,7 @@ public class ReceiveTextCommand extends AbstractAgiCommand { private int timeout; /** - * Creates a new ReceiveTextCommand with a default timeout of 0 meaning to - * wait for ever. + * Creates a new ReceiveTextCommand with a default timeout of 0 meaning to wait forever. */ public ReceiveTextCommand() { super(); @@ -51,8 +43,7 @@ public ReceiveTextCommand() { /** * Creates a new ReceiveTextCommand. * - * @param timeout the milliseconds to wait for the channel to receive the - * text. + * @param timeout the milliseconds to wait for the channel to receive the text. */ public ReceiveTextCommand(int timeout) { super(); @@ -71,8 +62,7 @@ public int getTimeout() { /** * Sets the milliseconds to wait for the channel to receive the text. * - * @param timeout the milliseconds to wait for the channel to receive the - * text. + * @param timeout the milliseconds to wait for the channel to receive the text. */ public void setTimeout(int timeout) { this.timeout = timeout; diff --git a/src/main/java/org/asteriskjava/fastagi/command/RecordFileCommand.java b/src/main/java/org/asteriskjava/fastagi/command/RecordFileCommand.java index 52f18a6b1..d4bc84fb4 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/RecordFileCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/RecordFileCommand.java @@ -1,40 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Record to a file until a given dtmf digit in the sequence is received. + * AGI Command: RECORD FILE *

    - * Returns -1 on hangup or error. + * Records to a given file. *

    - * The format will specify what kind of file will be recorded. The timeout is - * the maximum record time in milliseconds, or -1 for no timeout. Offset samples - * is optional, and if provided will seek to the offset without exceeding the - * end of the file. "maxSilence" is the number of seconds of maxSilence allowed - * before the function returns despite the lack of dtmf digits or reaching - * timeout. + * See: AGI Command RECORD FILE (Asterisk 18) * * @author srt - * @version $Id$ */ public class RecordFileCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3978141041352128820L; /** @@ -63,13 +53,12 @@ public class RecordFileCommand extends AbstractAgiCommand { private int offset; /** - * Wheather a beep should be played before recording. + * Whether a beep should be played before recording. */ private boolean beep; /** - * The amount of silence (in seconds) to allow before returning despite the - * lack of dtmf digits or reaching timeout. + * The amount of silence (in seconds) to allow before returning despite the lack of dtmf digits or reaching timeout. */ private int maxSilence; @@ -78,10 +67,8 @@ public class RecordFileCommand extends AbstractAgiCommand { * * @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 escapeDigits contains the digits that allow the user to end recording. + * @param timeout the maximum record time in milliseconds, or -1 for no timeout. */ public RecordFileCommand(String file, String format, String escapeDigits, int timeout) { super(); @@ -99,18 +86,16 @@ public RecordFileCommand(String file, String format, String escapeDigits, int ti * * @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 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 true if a beep should be played before - * recording. + * @param beep true 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. */ - public RecordFileCommand(String file, String format, String escapeDigits, int timeout, int offset, boolean beep, - int maxSilence) { + public RecordFileCommand( + String file, String format, String escapeDigits, int timeout, int offset, boolean beep, int maxSilence + ) { super(); this.file = file; this.format = format; @@ -169,8 +154,7 @@ public String getEscapeDigits() { /** * Sets the digits that allow the user to end recording. * - * @param escapeDigits the digits that allow the user to end recording or - * null for none. + * @param escapeDigits the digits that allow the user to end recording or null for none. */ public void setEscapeDigits(String escapeDigits) { this.escapeDigits = escapeDigits; @@ -188,8 +172,7 @@ public int getTimeout() { /** * Sets the maximum record time in milliseconds. * - * @param timeout the maximum record time in milliseconds, or -1 for no - * timeout. + * @param timeout the maximum record time in milliseconds, or -1 for no timeout. */ public void setTimeout(int timeout) { this.timeout = timeout; @@ -216,8 +199,7 @@ public void setOffset(int offset) { /** * Returns true if a beep should be played before recording. * - * @return true if a beep should be played before recording, - * false if not. + * @return true if a beep should be played before recording, false if not. */ public boolean getBeep() { return beep; @@ -226,30 +208,25 @@ public boolean getBeep() { /** * Set to true to play a beep before recording. * - * @param beep true if a beep should be played before - * recording, false if not. + * @param beep true if a beep should be played before recording, false if not. */ public void setBeep(boolean beep) { this.beep = beep; } /** - * Returns the amount of silence (in seconds) to allow before returning - * despite the lack of dtmf digits or reaching timeout. + * Returns the amount of silence (in seconds) to allow before returning despite the lack of dtmf digits or reaching timeout. * - * @return the amount of silence (in seconds) to allow before returning - * despite the lack of dtmf digits or reaching timeout. + * @return the amount of silence (in seconds) to allow before returning despite the lack of dtmf digits or reaching timeout. */ int getMaxSilence() { return maxSilence; } /** - * Sets the amount of silence (in seconds) to allow before returning despite - * the lack of dtmf digits or reaching timeout. + * Sets the amount of silence (in seconds) to allow before returning despite the lack of dtmf digits or reaching timeout. * - * @param maxSilence the amount of silence (in seconds) to allow before - * returning despite the lack of dtmf digits or reaching timeout. + * @param maxSilence the amount of silence (in seconds) to allow before returning despite the lack of dtmf digits or reaching timeout. */ void setMaxSilence(int maxSilence) { this.maxSilence = maxSilence; diff --git a/src/main/java/org/asteriskjava/fastagi/command/SayAlphaCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SayAlphaCommand.java index ae793d5d4..efbcb1250 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SayAlphaCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SayAlphaCommand.java @@ -1,34 +1,33 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this text except in compliance with the License. - * You may obtain a copy of the License at + * 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. + * 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; /** + * AGI Command: SAY ALPHA + *

    * Say a given character string, returning early if any of the - * given DTMF digits are received on the channel.

    + * given DTMF digits are received on the channel.
    * 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/hangup. + *

    + * See: AGI Command SAY ALPHA * * @author srt - * @version $Id$ */ public class SayAlphaCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256721797012404276L; /** @@ -55,8 +54,7 @@ public SayAlphaCommand(String text) { * Creates a new SayAlphaCommand. * * @param text the text to say. - * @param escapeDigits contains the digits that allow the user to interrupt - * this command. + * @param escapeDigits contains the digits that allow the user to interrupt this command. */ public SayAlphaCommand(String text, String escapeDigits) { super(); @@ -94,8 +92,7 @@ public String getEscapeDigits() { /** * Sets the digits that allow the user to interrupt this command. * - * @param escapeDigits the text that allow the user to interrupt this - * command or null for none. + * @param escapeDigits the text that allow the user to interrupt this command or null for none. */ public void setEscapeDigits(String escapeDigits) { this.escapeDigits = escapeDigits; @@ -103,7 +100,6 @@ public void setEscapeDigits(String escapeDigits) { @Override public String buildCommand() { - return "SAY ALPHA " + escapeAndQuote(text) + " " - + escapeAndQuote(escapeDigits); + return "SAY ALPHA " + escapeAndQuote(text) + " " + escapeAndQuote(escapeDigits); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/SayDateTimeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SayDateTimeCommand.java index bf0f54fbb..eaebfb45e 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SayDateTimeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SayDateTimeCommand.java @@ -1,36 +1,34 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** + * AGI Command: SAY DATETIME + *

    * Say a given time, returning early if any of the given DTMF digits are * pressed.

    * 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/hangup.

    * Available since Asterisk 1.2. + *

    + * See: AGI Command SAY DATETIME (Asterisk 18) * * @author srt - * @version $Id$ - * @since 0.2 */ public class SayDateTimeCommand extends AbstractAgiCommand { - /** - * Serial version identifier - */ private static final long serialVersionUID = -976344744239948036L; private static final String DEFAULT_FORMAT = "ABdY 'digits/at' IMp"; @@ -43,8 +41,7 @@ public class SayDateTimeCommand extends AbstractAgiCommand { /** * Creates a new SayDateTimeCommand that says the given time. * - * @param time the time to say in seconds elapsed since 00:00:00 on January - * 1, 1970, Coordinated Universal Time (UTC) + * @param time the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC) */ public SayDateTimeCommand(long time) { super(); @@ -52,13 +49,10 @@ public SayDateTimeCommand(long time) { } /** - * Creates a new SayDateTimeCommand that says the given time and allows - * interruption by one of the given escape digits. + * Creates a new SayDateTimeCommand that says the given time and allows interruption by one of the given escape digits. * - * @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 null for none. + * @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 null for none. */ public SayDateTimeCommand(long time, String escapeDigits) { super(); @@ -67,13 +61,10 @@ public SayDateTimeCommand(long time, String escapeDigits) { } /** - * Creates a new SayDateTimeCommand that says the given time in the given - * format and allows interruption by one of the given escape digits. + * Creates a new SayDateTimeCommand that says the given time in the given format and allows interruption by one of the given escape digits. * - * @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 null for none. + * @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 null for none. * @param format the format the time should be said in */ public SayDateTimeCommand(long time, String escapeDigits, String format) { @@ -84,17 +75,12 @@ public SayDateTimeCommand(long time, String escapeDigits, String format) { } /** - * Creates a new SayDateTimeCommand that says the given time in the given - * format and timezone and allows interruption by one of the given escape - * digits. + * Creates a new SayDateTimeCommand that says the given time in the given format and timezone and allows interruption by one of the given escape digits. * - * @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 null for none. + * @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 null 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". + * @param timezone the timezone to use when saying the time, for example "UTC" or "Europe/Berlin". */ public SayDateTimeCommand(long time, String escapeDigits, String format, String timezone) { @@ -106,23 +92,19 @@ public SayDateTimeCommand(long time, String escapeDigits, String format, } /** - * Returns the time to say in seconds elapsed since 00:00:00 on January 1, - * 1970, Coordinated Universal Time (UTC). + * Returns the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC). * - * @return the time to say in seconds elapsed since 00:00:00 on January 1, - * 1970, Coordinated Universal Time (UTC) + * @return the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC) */ public long getTime() { return time; } /** - * Returns the time to say in seconds elapsed since 00:00:00 on January 1, - * 1970, Coordinated Universal Time (UTC).

    + * Returns the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC).

    * This property is mandatory. * - * @param time the time to say in seconds elapsed since 00:00:00 on January - * 1, 1970, Coordinated Universal Time (UTC) + * @param time the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC) */ public void setTime(long time) { this.time = time; @@ -140,8 +122,7 @@ public String getEscapeDigits() { /** * Sets the digits that allow the user to interrupt this command. * - * @param escapeDigits the digits that allow the user to interrupt this - * command or null for none. + * @param escapeDigits the digits that allow the user to interrupt this command or null for none. */ public void setEscapeDigits(String escapeDigits) { this.escapeDigits = escapeDigits; @@ -182,8 +163,7 @@ public String getTimezone() { * /usr/share/zoneinfo on your Asterisk server.

    * Defaults to machine default. * - * @param timezone the timezone to use when saying the time, for example - * "UTC" or "Europe/Berlin". + * @param timezone the timezone to use when saying the time, for example "UTC" or "Europe/Berlin". */ public void setTimezone(String timezone) { this.timezone = timezone; diff --git a/src/main/java/org/asteriskjava/fastagi/command/SayDigitsCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SayDigitsCommand.java index 890dd448b..e08277da2 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SayDigitsCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SayDigitsCommand.java @@ -1,34 +1,32 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this digits except in compliance with the License. - * You may obtain a copy of the License at + * 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. + * 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; /** - * Say a given digit string, returning early if any of the given DTMF digits are - * received on the channel.

    - * 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/hangup. + * AGI Command: SAY DIGIT + *

    + * Say a given digit string, returning early if any of the given DTMF digits are received on the channel.
    + * 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/hangup. + *

    + * See: AGI Command SAY DIGIT (Asterisk 18) * * @author srt - * @version $Id$ */ public class SayDigitsCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3907207173934101552L; /** @@ -37,8 +35,7 @@ public class SayDigitsCommand extends AbstractAgiCommand { private String digits; /** - * When one of these digits is pressed while saying the digits the command - * returns. + * When one of these digits is pressed while saying the digits the command returns. */ private String escapeDigits; @@ -56,8 +53,7 @@ public SayDigitsCommand(String digits) { * Creates a new SayDigitsCommand. * * @param digits the digits to say. - * @param escapeDigits the digits that allow the user to interrupt this - * command. + * @param escapeDigits the digits that allow the user to interrupt this command. */ public SayDigitsCommand(String digits, String escapeDigits) { super(); @@ -95,8 +91,7 @@ public String getEscapeDigits() { /** * Sets the digits that allow the user to interrupt this command. * - * @param escapeDigits the digits that allow the user to interrupt this - * command or null for none. + * @param escapeDigits the digits that allow the user to interrupt this command or null for none. */ public void setEscapeDigits(String escapeDigits) { this.escapeDigits = escapeDigits; @@ -104,7 +99,6 @@ public void setEscapeDigits(String escapeDigits) { @Override public String buildCommand() { - return "SAY DIGITS " + escapeAndQuote(digits) + " " - + escapeAndQuote(escapeDigits); + return "SAY DIGITS " + escapeAndQuote(digits) + " " + escapeAndQuote(escapeDigits); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/SayNumberCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SayNumberCommand.java index be49c6596..488ee21b9 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SayNumberCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SayNumberCommand.java @@ -1,34 +1,32 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this number except in compliance with the License. - * You may obtain a copy of the License at + * 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. + * 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; /** - * Say a given number, returning early if any of the given DTMF number are - * received on the channel.

    - * 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/hangup. + * AGI Command: SAY NUMBER + *

    + * Say a given number, returning early if any of the given DTMF number are received on the channel.
    + * 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/hangup. + *

    + * See: AGI Command SAY NUMBER (Asterisk 18) * * @author srt - * @version $Id$ */ public class SayNumberCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3833744404153644087L; /** @@ -55,8 +53,7 @@ public SayNumberCommand(String number) { * Creates a new SayNumberCommand. * * @param number the number to say. - * @param escapeDigits contains the number that allow the user to - * interrupt this command. + * @param escapeDigits contains the number that allow the user to interrupt this command. */ public SayNumberCommand(String number, String escapeDigits) { super(); @@ -94,8 +91,7 @@ public String getEscapeDigits() { /** * Sets the number that allow the user to interrupt this command. * - * @param escapeDigits the number that allow the user to interrupt this - * command or null for none. + * @param escapeDigits the number that allow the user to interrupt this command or null for none. */ public void setEscapeDigits(String escapeDigits) { this.escapeDigits = escapeDigits; @@ -103,7 +99,6 @@ public void setEscapeDigits(String escapeDigits) { @Override public String buildCommand() { - return "SAY NUMBER " + escapeAndQuote(number) + " " - + escapeAndQuote(escapeDigits); + return "SAY NUMBER " + escapeAndQuote(number) + " " + escapeAndQuote(escapeDigits); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/SayPhoneticCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SayPhoneticCommand.java index 914b468f9..46d26b3b5 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SayPhoneticCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SayPhoneticCommand.java @@ -1,34 +1,31 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this text except in compliance with the License. - * You may obtain a copy of the License at + * 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. + * 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; /** - * Say a given character string with phonetics, returning early if any of the - * given DTMF digits are received on the channel.

    - * 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/hangup. + * AGI Command: SAY PHONETIC + *

    + * Say a given character string with phonetics, returning early if any of the given DTMF digits are received on the channel.
    + * 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/hangup. + *

    + * See: AGI Command SAY PHONETIC (Asterisk 18) * * @author srt - * @version $Id$ */ public class SayPhoneticCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256721797012404276L; /** @@ -42,7 +39,7 @@ public class SayPhoneticCommand extends AbstractAgiCommand { private String escapeDigits; /** - * Creates a new SayPhonticCommand. + * Creates a new SayPhoneticCommand. * * @param text the text to say. */ @@ -55,8 +52,7 @@ public SayPhoneticCommand(String text) { * Creates a new SayPhoneticCommand. * * @param text the text to say. - * @param escapeDigits contains the digits that allow the user to interrupt - * this command. + * @param escapeDigits contains the digits that allow the user to interrupt this command. */ public SayPhoneticCommand(String text, String escapeDigits) { super(); @@ -94,8 +90,7 @@ public String getEscapeDigits() { /** * Sets the digits that allow the user to interrupt this command. * - * @param escapeDigits the text that allow the user to interrupt this - * command or null for none. + * @param escapeDigits the text that allow the user to interrupt this command or null for none. */ public void setEscapeDigits(String escapeDigits) { this.escapeDigits = escapeDigits; @@ -103,7 +98,6 @@ public void setEscapeDigits(String escapeDigits) { @Override public String buildCommand() { - return "SAY PHONETIC " + escapeAndQuote(text) + " " - + escapeAndQuote(escapeDigits); + return "SAY PHONETIC " + escapeAndQuote(text) + " " + escapeAndQuote(escapeDigits); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/SayTimeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SayTimeCommand.java index c18721204..d25bec8c5 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SayTimeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SayTimeCommand.java @@ -1,36 +1,32 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this time except in compliance with the License. - * You may obtain a copy of the License at + * 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. + * 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; /** - * Say a given time, returning early if any of the given DTMF digits are - * received on the channel.

    - * Time is the number of seconds elapsed since 00:00:00 on January 1, 1970, - * Coordinated Universal Time (UTC).

    - * 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/hangup. + * AGI Command: SAY TIME + *

    + * Say a given time, returning early if any of the given DTMF digits are received on the channel.
    + * Time is the number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC).
    + * 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/hangup. + *

    + * See: AGI Command SAY TIME (Asterisk 18) * * @author srt - * @version $Id$ */ public class SayTimeCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256721797012404276L; /** @@ -57,8 +53,7 @@ public SayTimeCommand(long time) { * Creates a new SayTimeCommand. * * @param time the time to say in seconds since 00:00:00 on January 1, 1970. - * @param escapeDigits contains the digits that allow the user to interrupt - * this command. + * @param escapeDigits contains the digits that allow the user to interrupt this command. */ public SayTimeCommand(long time, String escapeDigits) { super(); @@ -96,8 +91,7 @@ public String getEscapeDigits() { /** * Sets the digits that allow the user to interrupt this command. * - * @param escapeDigits the time that allow the user to interrupt this - * command or null for none. + * @param escapeDigits the time that allow the user to interrupt this command or null for none. */ public void setEscapeDigits(String escapeDigits) { this.escapeDigits = escapeDigits; diff --git a/src/main/java/org/asteriskjava/fastagi/command/SendImageCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SendImageCommand.java index 1dcd01a3d..a747298dc 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SendImageCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SendImageCommand.java @@ -1,35 +1,33 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Sends the given image on a channel.

    - * Most channels do not support the transmission of images.

    - * Returns 0 if image is sent, or if the channel does not support image - * transmission. Returns -1 only on error/hangup.

    + * AGI Command: SEND IMAGE + *

    + * Sends the given image on a channel.
    + * Most channels do not support the transmission of images.
    + * Returns 0 if image is sent, or if the channel does not support image transmission. Returns -1 only on error/hangup.
    * Image names should not include extensions. + *

    + * See: AGI Command SEND IMAGE (Asterisk 18) * * @author srt - * @version $Id$ */ public class SendImageCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3904959746380281145L; /** diff --git a/src/main/java/org/asteriskjava/fastagi/command/SendTextCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SendTextCommand.java index 579105ee3..fe0d468d8 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SendTextCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SendTextCommand.java @@ -1,34 +1,32 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** + * AGI Command: SEND TEXT + *

    * Sends the given text on a channel.

    * Most channels do not support the transmission of text.

    - * Returns 0 if text is sent, or if the channel does not support text - * transmission. Returns -1 only on error/hangup. + * Returns 0 if text is sent, or if the channel does not support text transmission. Returns -1 only on error/hangup. + *

    + * See: AGI Command SEND TEXT (Asterisk 18) * * @author srt - * @version $Id$ */ public class SendTextCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3904959746380281145L; /** diff --git a/src/main/java/org/asteriskjava/fastagi/command/SetAutoHangupCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SetAutoHangupCommand.java index a3641f968..05e3586ba 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SetAutoHangupCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SetAutoHangupCommand.java @@ -1,34 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Cause the channel to automatically hangup at the given number of seconds in - * the future.

    - * Of course it can be hungup before then as well. Setting to 0 will cause the - * autohangup feature to be disabled on this channel. + * AGI Command: SET AUTOHANGUP + *

    + * Autohangup channel in some time. + *

    + * See: AGI Command SET AUTOHANGUP (Asterisk 18) * * @author srt - * @version $Id$ */ public class SetAutoHangupCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3257562923458443314L; /** @@ -39,8 +35,7 @@ public class SetAutoHangupCommand extends AbstractAgiCommand { /** * Creates a new SetAutoHangupCommand. * - * @param time the number of seconds before this channel is automatically - * hung up.

    + * @param time the number of seconds before this channel is automatically hung up.

    * 0 disables the autohangup feature. */ public SetAutoHangupCommand(int time) { @@ -49,11 +44,9 @@ public SetAutoHangupCommand(int time) { } /** - * Returns the number of seconds before this channel is automatically hung - * up. + * Returns the number of seconds before this channel is automatically hung up. * - * @return the number of seconds before this channel is automatically hung - * up. + * @return the number of seconds before this channel is automatically hung up. */ public int getTime() { return time; @@ -62,8 +55,7 @@ public int getTime() { /** * Sets the number of seconds before this channel is automatically hung up. * - * @param time the number of seconds before this channel is automatically - * hung up.

    + * @param time the number of seconds before this channel is automatically hung up.

    * 0 disables the autohangup feature. */ public void setTime(int time) { diff --git a/src/main/java/org/asteriskjava/fastagi/command/SetCallerIdCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SetCallerIdCommand.java index 529ed762b..b980232f0 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SetCallerIdCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SetCallerIdCommand.java @@ -1,31 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this time except in compliance with the License. - * You may obtain a copy of the License at + * 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. + * 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; /** - * Changes the callerid of the current channel. + * AGI Command: SET CALLERID + *

    + * Sets callerid for the current channel. + *

    + * See: AGI Command SET CALLERID (Asterisk 18) * * @author srt - * @version $Id$ */ public class SetCallerIdCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256721797012404276L; /** diff --git a/src/main/java/org/asteriskjava/fastagi/command/SetContextCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SetContextCommand.java index 90853be9b..045919a3a 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SetContextCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SetContextCommand.java @@ -1,31 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Sets the context for continuation upon exiting the application. + * AGI Command: SET CONTEXT + *

    + * Sets channel context. + *

    + * See: AGI Command SET CONTEXT (Asterisk 18) * * @author srt - * @version $Id$ */ public class SetContextCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** diff --git a/src/main/java/org/asteriskjava/fastagi/command/SetExtensionCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SetExtensionCommand.java index 7f061de21..8e13a1a99 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SetExtensionCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SetExtensionCommand.java @@ -1,31 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Sets the extension for continuation upon exiting the application. + * AGI Command: SET EXTENSION + *

    + * Changes channel extension. + *

    + * See: AGI Command SET EXTENSION (Asterisk 18) * * @author srt - * @version $Id$ */ public class SetExtensionCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** @@ -36,8 +35,7 @@ public class SetExtensionCommand extends AbstractAgiCommand { /** * Creates a new SetPriorityCommand. * - * @param extension the extension for continuation upon exiting the - * application. + * @param extension the extension for continuation upon exiting the application. */ public SetExtensionCommand(String extension) { super(); @@ -56,8 +54,7 @@ public String getExtension() { /** * Sets the extension for continuation upon exiting the application. * - * @param extension the extension for continuation upon exiting the - * application. + * @param extension the extension for continuation upon exiting the application. */ public void setExtension(String extension) { this.extension = extension; diff --git a/src/main/java/org/asteriskjava/fastagi/command/SetMusicOffCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SetMusicOffCommand.java index 0d405732c..cb5ee37c7 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SetMusicOffCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SetMusicOffCommand.java @@ -1,32 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Turns off music on hold on the current channel.

    - * Always returns 0. + * AGI Command: SET MUSIC + *

    + * Disable Music on hold generator. + *

    + * See: AGI Command SET MUSIC (Asterisk 18) * * @author srt - * @version $Id$ */ public class SetMusicOffCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3762248656229053753L; /** diff --git a/src/main/java/org/asteriskjava/fastagi/command/SetMusicOnCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SetMusicOnCommand.java index 3becd61c0..e2064320c 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SetMusicOnCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SetMusicOnCommand.java @@ -1,32 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Turns on music on hold on the current channel.

    - * Always returns 0. + * AGI Command: SET MUSIC + *

    + * Enable Music on hold generator. + *

    + * See: AGI Command SET MUSIC (Asterisk 18) * * @author srt - * @version $Id$ */ public class SetMusicOnCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3762248656229053753L; /** @@ -35,16 +33,14 @@ public class SetMusicOnCommand extends AbstractAgiCommand { private String musicOnHoldClass; /** - * Creates a new SetMusicOnCommand playing music from the default music on - * hold class. + * Creates a new SetMusicOnCommand playing music from the default music on hold class. */ public SetMusicOnCommand() { super(); } /** - * Creates a new SetMusicOnCommand playing music from the default music on - * hold class. + * Creates a new SetMusicOnCommand playing music from the default music on hold class. * * @param musicOnHoldClass the music on hold class to play music from. */ @@ -65,8 +61,7 @@ public String getMusicOnHoldClass() { /** * Sets the music on hold class to play music from. * - * @param musicOnHoldClass the music on hold class to play music from or - * null for the default class. + * @param musicOnHoldClass the music on hold class to play music from or null for the default class. */ public void setMusicOnHoldClass(String musicOnHoldClass) { this.musicOnHoldClass = musicOnHoldClass; @@ -74,8 +69,6 @@ public void setMusicOnHoldClass(String musicOnHoldClass) { @Override public String buildCommand() { - return "SET MUSIC ON" - + (musicOnHoldClass == null ? "" : " " - + escapeAndQuote(musicOnHoldClass)); + return "SET MUSIC ON" + (musicOnHoldClass == null ? "" : " " + escapeAndQuote(musicOnHoldClass)); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/SetPriorityCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SetPriorityCommand.java index b58abc391..24ebeeb2a 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SetPriorityCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SetPriorityCommand.java @@ -1,32 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Sets the priority for continuation upon exiting the application.

    - * Since Asterisk 1.2 SetPriorityCommand also supports labels. + * AGI Command: SET PRIORITY + *

    + * Set channel dialplan priority. + *

    + * See: AGI Command SET PRIORITY (Asterisk 18) * * @author srt - * @version $Id$ */ public class SetPriorityCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** @@ -37,8 +35,7 @@ public class SetPriorityCommand extends AbstractAgiCommand { /** * Creates a new SetPriorityCommand. * - * @param priority the priority or label for continuation upon exiting the - * application. + * @param priority the priority or label for continuation upon exiting the application. */ public SetPriorityCommand(String priority) { super(); @@ -57,8 +54,7 @@ public String getPriority() { /** * Sets the priority or label for continuation upon exiting the application. * - * @param priority the priority or label for continuation upon exiting the - * application. + * @param priority the priority or label for continuation upon exiting the application. */ public void setPriority(String priority) { this.priority = priority; diff --git a/src/main/java/org/asteriskjava/fastagi/command/SetVariableCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SetVariableCommand.java index 938528b3f..db9ee980b 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SetVariableCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SetVariableCommand.java @@ -1,31 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Sets the given channel varible to the given value. + * AGI Command: SET VARIABLE + *

    + * Sets a channel variable. + *

    + * See: AGI Command SET VARIABLE (Asterisk 18) * * @author srt - * @version $Id$ */ public class SetVariableCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** @@ -53,7 +52,7 @@ public SetVariableCommand(String variable, String value) { /** * Returns the name of the variable to set. * - * @return the the name of the variable to set. + * @return the name of the variable to set. */ public String getVariable() { return variable; @@ -88,7 +87,6 @@ public void setValue(String value) { @Override public String buildCommand() { - return "SET VARIABLE " + escapeAndQuote(variable) + " " - + escapeAndQuote(value); + return "SET VARIABLE " + escapeAndQuote(variable) + " " + escapeAndQuote(value); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/SpeechActivateGrammarCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SpeechActivateGrammarCommand.java index 7e9619f13..e8c56d9c4 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SpeechActivateGrammarCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SpeechActivateGrammarCommand.java @@ -1,40 +1,39 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Activates the specified grammar.

    - * Available since Asterisk 1.6. + * AGI Command: SPEECH ACTIVATE GRAMMAR + *

    + * Activates a grammar. + *

    + * See: AGI Command SPEECH ACTIVATE GRAMMAR (Asterisk 18) * * @author srt - * @version $Id$ * @see org.asteriskjava.fastagi.command.SpeechLoadGrammarCommand * @see org.asteriskjava.fastagi.command.SpeechDeactivateGrammarCommand * @since 1.0.0 */ public class SpeechActivateGrammarCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 1L; + private String name; /** - * Creates a new SpeechActivateGrammarCommand that acitvates the given grammer. + * Creates a new SpeechActivateGrammarCommand that activates the given grammar. * * @param name the name of the grammar. */ diff --git a/src/main/java/org/asteriskjava/fastagi/command/SpeechCreateCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SpeechCreateCommand.java index 80f59e430..5f504be2f 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SpeechCreateCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SpeechCreateCommand.java @@ -1,36 +1,35 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Creates a speech object to be used by the other Speech AGI commands.

    - * Available since Asterisk 1.6. + * AGI Command: SPEECH CREATE + *

    + * Creates a speech object. + *

    + * See: AGI Command SPEECH CREATE (Asterisk 18) * * @author srt - * @version $Id$ * @see org.asteriskjava.fastagi.command.SpeechDestroyCommand * @see org.asteriskjava.fastagi.command.SpeechLoadGrammarCommand * @since 1.0.0 */ public class SpeechCreateCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 1L; + private String engine; /** diff --git a/src/main/java/org/asteriskjava/fastagi/command/SpeechDeactivateGrammarCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SpeechDeactivateGrammarCommand.java index 04c8fd02b..9d9f3f716 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SpeechDeactivateGrammarCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SpeechDeactivateGrammarCommand.java @@ -1,39 +1,38 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Deactivates the specified grammar.

    - * Available since Asterisk 1.6. + * AGI Command: SPEECH DEACTIVATE GRAMMAR + *

    + * Deactivates a grammar. + *

    + * See: AGI Command SPEECH DEACTIVATE GRAMMAR (Asterisk 18) * * @author srt - * @version $Id$ * @see org.asteriskjava.fastagi.command.SpeechActivateGrammarCommand * @since 1.0.0 */ public class SpeechDeactivateGrammarCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 1L; + private String name; /** - * Creates a new SpeechDeactivateGrammarCommand that deacitvates the given grammer. + * Creates a new SpeechDeactivateGrammarCommand that deactivates the given grammar. * * @param name the name of the grammar. */ diff --git a/src/main/java/org/asteriskjava/fastagi/command/SpeechDestroyCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SpeechDestroyCommand.java index d6590b05a..f4232b5ff 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SpeechDestroyCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SpeechDestroyCommand.java @@ -1,34 +1,32 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Destroys a speech object previously created by a {@link SpeechCreateCommand}.

    - * Available since Asterisk 1.6. + * AGI Command: SPEECH DESTROY + *

    + * Destroys a speech object. + *

    + * See: AGI Command SPEECH DESTROY (Asterisk 18) * * @author srt - * @version $Id$ * @see org.asteriskjava.fastagi.command.SpeechCreateCommand * @since 1.0.0 */ public class SpeechDestroyCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 1L; /** diff --git a/src/main/java/org/asteriskjava/fastagi/command/SpeechLoadGrammarCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SpeechLoadGrammarCommand.java index 6b312d4f6..d044464a0 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SpeechLoadGrammarCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SpeechLoadGrammarCommand.java @@ -1,44 +1,43 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Loads the specified grammar as the specified name.

    - * Available since Asterisk 1.6. + * AGI Command: SPEECH LOAD GRAMMAR + *

    + * Loads a grammar. + *

    + * See: AGI Command SPEECH LOAD GRAMMAR (Asterisk 18) * * @author srt - * @version $Id$ * @see org.asteriskjava.fastagi.command.SpeechUnloadGrammarCommand * @see org.asteriskjava.fastagi.command.SpeechActivateGrammarCommand * @since 1.0.0 */ public class SpeechLoadGrammarCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 1L; + private String name; private String path; /** - * Creates a new SpeechLoadGrammarCommand that loads the grammer from the given path and + * Creates a new SpeechLoadGrammarCommand that loads the grammar from the given path and * makes it available under the given name. * - * @param name the name of the grammar, used to activate the gammer later. + * @param name the name of the grammar, used to activate the grammar later. * @param path the path to the grammar. */ public SpeechLoadGrammarCommand(String name, String path) { @@ -56,7 +55,7 @@ public String getName() { } /** - * Sets the name of the grammar, used to activate the gammer later. + * Sets the name of the grammar, used to activate the grammar later. * * @param name the name of the grammar. */ diff --git a/src/main/java/org/asteriskjava/fastagi/command/SpeechRecognizeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SpeechRecognizeCommand.java index 3e58c38c5..8eab217b5 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SpeechRecognizeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SpeechRecognizeCommand.java @@ -1,33 +1,31 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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 back given prompt while listening for speech and dtmf.

    - * Available since Asterisk 1.6. + * AGI Command: SPEECH RECOGNIZE + *

    + * Recognizes speech. + *

    + * See: AGI Command SPEECH RECOGNIZE (Asterisk 18) * * @author srt - * @version $Id$ * @since 1.0.0 */ public class SpeechRecognizeCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 1L; private String prompt; @@ -35,7 +33,7 @@ public class SpeechRecognizeCommand extends AbstractAgiCommand { private int offset; /** - * Creates a new SpeechRecognizeCommand that plays the given prompt and listens for for speech and dtmf. + * Creates a new SpeechRecognizeCommand that plays the given prompt and listens for speech and dtmf. * * @param prompt the prompt to play. * @param timeout the maximum recognition time in milliseconds. diff --git a/src/main/java/org/asteriskjava/fastagi/command/SpeechSetCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SpeechSetCommand.java index 37dbd62e3..538d9c5a1 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SpeechSetCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SpeechSetCommand.java @@ -1,34 +1,33 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Sets a speech engine specific setting.

    - * Available since Asterisk 1.6. + * AGI Command: SPEECH SET + *

    + * Sets a speech engine setting. + *

    + * See: AGI Command SPEECH SET (Asterisk 18) * * @author srt - * @version $Id$ * @since 1.0.0 */ public class SpeechSetCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 1L; + private String name; private String value; diff --git a/src/main/java/org/asteriskjava/fastagi/command/SpeechUnloadGrammarCommand.java b/src/main/java/org/asteriskjava/fastagi/command/SpeechUnloadGrammarCommand.java index 13667a238..8e76bbbd5 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/SpeechUnloadGrammarCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/SpeechUnloadGrammarCommand.java @@ -1,39 +1,38 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Unloads the specified grammar.

    - * Available since Asterisk 1.6. + * AGI Command: SPEECH UNLOAD GRAMMAR + *

    + * Unloads a grammar. + *

    + * See: AGI Command SPEECH UNLOAD GRAMMAR (Asterisk 18) * * @author srt - * @version $Id$ * @see SpeechLoadGrammarCommand * @since 1.0.0 */ public class SpeechUnloadGrammarCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 1L; + private String name; /** - * Creates a new SpeechUnloadGrammarCommand that unloads the given grammer. + * Creates a new SpeechUnloadGrammarCommand that unloads the given grammar. * * @param name the name of the grammar. */ diff --git a/src/main/java/org/asteriskjava/fastagi/command/StreamFileCommand.java b/src/main/java/org/asteriskjava/fastagi/command/StreamFileCommand.java index 516c41368..91f3fdd12 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/StreamFileCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/StreamFileCommand.java @@ -17,27 +17,15 @@ package org.asteriskjava.fastagi.command; /** - * Plays the given file, allowing playback to be interrupted by the given - * digits, if any. + * AGI Command: STREAM FILE *

    - * If offset is provided then the audio will seek to sample offset before play - * starts. + * Sends audio file on channel. *

    - * 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. - *

    - * Remember, filename follows the same conventions and uses the same file path - * as dialplan applications like Playback or Background. The file extension must - * not be included in the filename. + * See: AGI Command STREAM FILE (Asterisk 18) * * @author srt - * @version $Id$ */ public class StreamFileCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3978141041352128820L; /** @@ -153,8 +141,6 @@ public void setOffset(int offset) { @Override public String buildCommand() { - return "STREAM FILE " + escapeAndQuote(file) + " " - + escapeAndQuote(escapeDigits) - + (offset < 0 ? "" : " " + offset); + return "STREAM FILE " + escapeAndQuote(file) + " " + escapeAndQuote(escapeDigits) + (offset < 0 ? "" : " " + offset); } } diff --git a/src/main/java/org/asteriskjava/fastagi/command/TddModeCommand.java b/src/main/java/org/asteriskjava/fastagi/command/TddModeCommand.java index 04c7cc028..fbcd15dbe 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/TddModeCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/TddModeCommand.java @@ -1,32 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Enable/Disable TDD transmission/reception on a channel.

    - * Returns 1 if successful, or 0 if channel is not TDD-capable. + * AGI Command: TDD MODE + *

    + * Toggles TDD mode (for the deaf). + *

    + * See: AGI Command TDD MODE (Asterisk 18) * * @author srt - * @version $Id$ */ public class TddModeCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3258411746401268532L; /** @@ -37,8 +35,7 @@ public class TddModeCommand extends AbstractAgiCommand { /** * Creates a new TDDModeCommand. * - * @param mode the mode to set, this can be one of "on", "off", "mate" or - * "tdd". + * @param mode the mode to set, this can be one of "on", "off", "mate" or "tdd". */ public TddModeCommand(String mode) { super(); @@ -57,8 +54,7 @@ public String getMode() { /** * Sets the mode to set. * - * @param mode the mode to set, this can be one of "on", "off", "mate" or - * "tdd". + * @param mode the mode to set, this can be one of "on", "off", "mate" or "tdd". */ public void setMode(String mode) { this.mode = mode; diff --git a/src/main/java/org/asteriskjava/fastagi/command/VerboseCommand.java b/src/main/java/org/asteriskjava/fastagi/command/VerboseCommand.java index 3207757c0..c9df38b99 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/VerboseCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/VerboseCommand.java @@ -1,32 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Sends a message to the Asterisk console via the verbose message system.

    - * Always returns 1. + * AGI Command: VERBOSE + *

    + * Logs a message to the asterisk verbose log. + *

    + * See: AGI Command VERBOSE (Asterisk 18) * * @author srt - * @version $Id$ */ public class VerboseCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3256719598056387384L; /** diff --git a/src/main/java/org/asteriskjava/fastagi/command/WaitForDigitCommand.java b/src/main/java/org/asteriskjava/fastagi/command/WaitForDigitCommand.java index f47d3eb23..7a861d15e 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/WaitForDigitCommand.java +++ b/src/main/java/org/asteriskjava/fastagi/command/WaitForDigitCommand.java @@ -1,34 +1,30 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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; /** - * Waits up to 'timeout' milliseconds for channel to receive a DTMF digit.

    - * Returns -1 on channel failure, 0 if no digit is received in the timeout, or - * the numerical value of the ascii of the digit if one is received. Use -1 for - * the timeout value if you desire the call to block indefinitely. + * AGI Command: WAIT FOR DIGIT + *

    + * Waits for a digit to be pressed. + *

    + * See: AGI Command WAIT FOR DIGIT (Asterisk 18) * * @author srt - * @version $Id$ */ public class WaitForDigitCommand extends AbstractAgiCommand { - /** - * Serial version identifier. - */ private static final long serialVersionUID = 3257562923458443314L; /** @@ -37,8 +33,7 @@ public class WaitForDigitCommand extends AbstractAgiCommand { private long timeout; /** - * Creates a new WaitForDigitCommand with a default timeout of -1 which - * blocks the channel indefinitely. + * Creates a new WaitForDigitCommand with a default timeout of -1 which blocks the channel indefinitely. */ public WaitForDigitCommand() { super(); @@ -48,8 +43,7 @@ public WaitForDigitCommand() { /** * Creates a new WaitForDigitCommand. * - * @param timeout the milliseconds to wait for the channel to receive a DTMF - * digit. + * @param timeout the milliseconds to wait for the channel to receive a DTMF digit. */ public WaitForDigitCommand(long timeout) { super(); @@ -68,8 +62,7 @@ public long getTimeout() { /** * Sets the milliseconds to wait for the channel to receive a DTMF digit. * - * @param timeout the milliseconds to wait for the channel to receive a DTMF - * digit. + * @param timeout the milliseconds to wait for the channel to receive a DTMF digit. */ public void setTimeout(long timeout) { this.timeout = timeout; diff --git a/src/main/java/org/asteriskjava/fastagi/command/package.html b/src/main/java/org/asteriskjava/fastagi/command/package.html index 97aea76f5..96eb51bd4 100644 --- a/src/main/java/org/asteriskjava/fastagi/command/package.html +++ b/src/main/java/org/asteriskjava/fastagi/command/package.html @@ -21,8 +21,7 @@ -

    Provides classes that represent the standard commands that can be sent - to an Asterisk server via the FastAGI.

    +

    Provides classes that represent the standard commands that can be sent to an Asterisk server via the FastAGI.

    diff --git a/src/test/java/org/asteriskjava/fastagi/command/AbstractAgiCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/AbstractAgiCommandTest.java index 7b2a83762..e0e0c0790 100644 --- a/src/test/java/org/asteriskjava/fastagi/command/AbstractAgiCommandTest.java +++ b/src/test/java/org/asteriskjava/fastagi/command/AbstractAgiCommandTest.java @@ -1,81 +1,186 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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 org.asteriskjava.AsteriskVersion; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static java.lang.String.format; +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.AsteriskVersion.ASTERISK_18; +import static org.asteriskjava.AsteriskVersion.ASTERISK_1_4; class AbstractAgiCommandTest { - private MyCommand myCommand; + @Test + void shouldBuildCommand() { + //given + MyCommand myCommand = new MyCommand("just a string"); + + //when + String actual = myCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("MY \"just a string\""); + } + + @Test + void shouldHandleNull() { + //given + MyCommand myCommand = new MyCommand(null); + + //when + String actual = myCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("MY \"\""); + } + + @Test + void shouldHandleEmptyString() { + //given + MyCommand myCommand = new MyCommand(""); + + //when + String actual = myCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("MY \"\""); + } + + @Test + void shouldEscapeAndQuoteWithStringContainingQuotes() { + //given + MyCommand myCommand = new MyCommand("\"John Doe\" is calling"); + + //given + String actual = myCommand.buildCommand(); + + //when + assertThat(actual).isEqualTo("MY \"\\\"John Doe\\\" is calling\""); + } @Test - void testEscapeAndQuote() { - myCommand = new MyCommand("just a string"); + void shouldEscapeAndQuoteWithStringContainingNewline() { + //given + MyCommand myCommand = new MyCommand("Caller is:\nJohn Doe"); - assertEquals("MY \"just a string\"", myCommand.buildCommand()); + //when + String actual = myCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("MY \"Caller is:John Doe\""); + } + + @Test + void shouldEscapedQuotesAJ192() { + //given + MyCommand myCommand = new MyCommand("first \\\" second \\\" third"); + + //when + String actual = myCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("MY \"first \\\\\\\" second \\\\\\\" third\""); } @Test - void testEscapeAndQuoteWithNullString() { - myCommand = new MyCommand(null); + void shouldFormatToString() { + //given + MyCommand myCommand = new MyCommand("just a string"); + + //when + String actual = myCommand.toString(); - assertEquals("MY \"\"", myCommand.buildCommand()); + //then + assertThat(actual).contains("command='MY \"just a string\"'"); } @Test - void testEscapeAndQuoteWithEmptyString() { - myCommand = new MyCommand(""); + void shouldHandleCommandWithMultipleStrings() { + //given + MyMultipleCommand myMultipleCommand = new MyMultipleCommand(new String[]{"first string", "another string"}); + + //when + String actual = myMultipleCommand.buildCommand(); - assertEquals("MY \"\"", myCommand.buildCommand()); + //then + assertThat(actual).isEqualTo("MY \"first string,another string\""); } @Test - void testEscapeAndQuoteWithStringContainingQuotes() { - myCommand = new MyCommand("\"John Doe\" is calling"); + void shouldHandleNullForArrayStrings() { + //given + MyMultipleCommand myMultipleCommand = new MyMultipleCommand(null); - assertEquals("MY \"\\\"John Doe\\\" is calling\"", myCommand.buildCommand()); + //when + String actual = myMultipleCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("MY \"\""); } @Test - void testEscapeAndQuoteWithStringContainingNewline() { - myCommand = new MyCommand("Caller is:\nJohn Doe"); + void shouldReturnDefaultAsteriskVersion() { + //given + MyCommand myCommand = new MyCommand("string"); + + //when + AsteriskVersion asteriskVersion = myCommand.getAsteriskVersion(); - assertEquals("MY \"Caller is:John Doe\"", myCommand.buildCommand()); + //then + assertThat(asteriskVersion).isEqualTo(ASTERISK_1_4); } @Test - void testEscapedQuotesAJ192() { - myCommand = new MyCommand("first \\\" second \\\" third"); + void shouldSetAsteriskVersion() { + //given + MyCommand myCommand = new MyCommand("string"); - assertEquals("MY \"first \\\\\\\" second \\\\\\\" third\"", myCommand.buildCommand()); + //when + myCommand.setAsteriskVersion(ASTERISK_18); + + //then + assertThat(myCommand.getAsteriskVersion()).isEqualTo(ASTERISK_18); + } + + private static class MyCommand extends AbstractAgiCommand { + private static final long serialVersionUID = 3976731484641833012L; + private final String command; + + public MyCommand(String command) { + this.command = command; + } + + @Override + public String buildCommand() { + return format("MY %s", escapeAndQuote(command)); + } } - public class MyCommand extends AbstractAgiCommand { + private static class MyMultipleCommand extends AbstractAgiCommand { private static final long serialVersionUID = 3976731484641833012L; - private String s; + private final String[] commands; - public MyCommand(String s) { - this.s = s; + public MyMultipleCommand(String[] commands) { + this.commands = commands; } @Override public String buildCommand() { - return "MY " + escapeAndQuote(s); + return format("MY %s", escapeAndQuote(commands)); } } } diff --git a/src/test/java/org/asteriskjava/fastagi/command/AnswerCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/AnswerCommandTest.java new file mode 100644 index 000000000..fa5afa247 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/AnswerCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class AnswerCommandTest { + @Test + void shouldBuildAnswerCommand() { + //given + AnswerCommand answerCommand = new AnswerCommand(); + + //when + String command = answerCommand.buildCommand(); + + //then + assertThat(command).isEqualTo("ANSWER"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/AsyncAgiBreakCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/AsyncAgiBreakCommandTest.java new file mode 100644 index 000000000..977807619 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/AsyncAgiBreakCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class AsyncAgiBreakCommandTest { + @Test + void shouldBuildAsyncAgiBreakCommand() { + //given + AsyncAgiBreakCommand asyncAgiBreakCommand = new AsyncAgiBreakCommand(); + + //when + String command = asyncAgiBreakCommand.buildCommand(); + + //then + assertThat(command).isEqualTo("ASYNCAGI BREAK"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/BridgeCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/BridgeCommandTest.java new file mode 100644 index 000000000..8ec408885 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/BridgeCommandTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.AsteriskVersion.ASTERISK_12; +import static org.asteriskjava.AsteriskVersion.ASTERISK_13; + +class BridgeCommandTest { + @Test + void shouldBuildBridgeCommand() { + //given + BridgeCommand bridgeCommand = new BridgeCommand("SIP/1234", "p"); + bridgeCommand.setAsteriskVersion(ASTERISK_13); + + //when + String actual = bridgeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"bridge\" \"SIP/1234\",\"p\""); + } + + @Test + void shouldBuildBridgeCommandForAsteriskLessThan13() { + //given + BridgeCommand bridgeCommand = new BridgeCommand("SIP/1234", "p"); + bridgeCommand.setAsteriskVersion(ASTERISK_12); + + //when + String actual = bridgeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"bridge\" \"SIP/1234\"|\"p\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/ChannelStatusCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/ChannelStatusCommandTest.java new file mode 100644 index 000000000..556e4d485 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/ChannelStatusCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class ChannelStatusCommandTest { + @Test + void shouldBuildChannelStatusCommandForCurrentChannel() { + //given + ChannelStatusCommand channelStatusCommand = new ChannelStatusCommand(); + + //when + String actual = channelStatusCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("CHANNEL STATUS"); + } + + @Test + void shouldBuildChannelStatusCommand() { + //given + ChannelStatusCommand channelStatusCommand = new ChannelStatusCommand("SIP/1234"); + + //when + String actual = channelStatusCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("CHANNEL STATUS \"SIP/1234\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/ConfbridgeCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/ConfbridgeCommandTest.java new file mode 100644 index 000000000..4e87f7a0e --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/ConfbridgeCommandTest.java @@ -0,0 +1,48 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.AsteriskVersion.ASTERISK_10; + +class ConfbridgeCommandTest { + @Test + void shouldBuildConfbridgeCommand() { + //given + ConfbridgeCommand confbridgeCommand = new ConfbridgeCommand("room", "fancybridge"); + + //when + String actual = confbridgeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"confbridge\" \"room\"|\"fancybridge\""); + } + + @Test + void shouldBuildConfbridgeCommandForAsteriskGreaterThan10() { + //given + ConfbridgeCommand confbridgeCommand = new ConfbridgeCommand("room", "fancybridge"); + confbridgeCommand.setAsteriskVersion(ASTERISK_10); + + //when + String actual = confbridgeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"confbridge\" \"room\",\"fancybridge\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/ControlStreamFileCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/ControlStreamFileCommandTest.java new file mode 100644 index 000000000..e01480c74 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/ControlStreamFileCommandTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class ControlStreamFileCommandTest { + @Test + void shouldBuildControlStreamFileCommand() { + //given + ControlStreamFileCommand controlStreamFileCommand = new ControlStreamFileCommand("some-file"); + + //when + String actual = controlStreamFileCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("CONTROL STREAM FILE \"some-file\" \"\""); + } + + @Test + void shouldBuildControlStreamFileCommandWithEscapeDigits() { + //given + ControlStreamFileCommand controlStreamFileCommand = new ControlStreamFileCommand("some-file", "15"); + + //when + String actual = controlStreamFileCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("CONTROL STREAM FILE \"some-file\" \"15\""); + } + + @Test + void shouldBuildControlStreamFileCommandWithOffset() { + //given + ControlStreamFileCommand controlStreamFileCommand = new ControlStreamFileCommand("some-file", "15", 10); + + //when + String actual = controlStreamFileCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("CONTROL STREAM FILE \"some-file\" \"15\" 10"); + } + + @Test + void shouldBuildControlStreamFileCommandWithControlDigits() { + //given + ControlStreamFileCommand controlStreamFileCommand = new ControlStreamFileCommand("some-file", "15", 10, "[", "]", "-"); + + //when + String actual = controlStreamFileCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("CONTROL STREAM FILE \"some-file\" \"15\" 10 [ ] -"); + } + + @Test + void shouldBuildControlStreamFileCommandWithOffsetSetToZeroWhenOnlyControlDigitsAreSet() { + //given + ControlStreamFileCommand controlStreamFileCommand = new ControlStreamFileCommand("some-file"); + controlStreamFileCommand.setControlDigits("[", "]"); + + //when + String actual = controlStreamFileCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("CONTROL STREAM FILE \"some-file\" \"\" 0 [ ]"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/DatabaseDelCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/DatabaseDelCommandTest.java new file mode 100644 index 000000000..7f97a4de1 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/DatabaseDelCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class DatabaseDelCommandTest { + @Test + void shouldBuildDatabaseDelCommandForFamilyOnly() { + //given + DatabaseDelCommand databaseDelCommand = new DatabaseDelCommand("family"); + + //when + String actual = databaseDelCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("DATABASE DEL \"family\""); + } + + @Test + void shouldBuildDatabaseDelCommandForFamilyAndKey() { + //given + DatabaseDelCommand databaseDelCommand = new DatabaseDelCommand("family", "key"); + + //when + String actual = databaseDelCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("DATABASE DEL \"family\" \"key\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/DatabaseDelTreeCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/DatabaseDelTreeCommandTest.java new file mode 100644 index 000000000..033597880 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/DatabaseDelTreeCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class DatabaseDelTreeCommandTest { + @Test + void shouldBuildDatabaseDelTreeCommandForFamilyOnly() { + //given + DatabaseDelTreeCommand databaseDelTreeCommand = new DatabaseDelTreeCommand("family"); + + //when + String actual = databaseDelTreeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("DATABASE DELTREE \"family\""); + } + + @Test + void shouldBuildDatabaseDelTreeCommandForFamilyAndKeyTree() { + //given + DatabaseDelTreeCommand databaseDelTreeCommand = new DatabaseDelTreeCommand("family", "keyTree"); + + //when + String actual = databaseDelTreeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("DATABASE DELTREE \"family\" \"keyTree\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/DatabaseGetCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/DatabaseGetCommandTest.java new file mode 100644 index 000000000..4a65e9e59 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/DatabaseGetCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class DatabaseGetCommandTest { + @Test + void shouldBuildDatabaseGetCommand() { + //given + DatabaseGetCommand databaseGetCommand = new DatabaseGetCommand("family", "key"); + + //when + String actual = databaseGetCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("DATABASE GET \"family\" \"key\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/DatabasePutCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/DatabasePutCommandTest.java new file mode 100644 index 000000000..b62c37250 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/DatabasePutCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class DatabasePutCommandTest { + @Test + void shouldBuildDatabasePutCommand() { + //given + DatabasePutCommand databasePutCommand = new DatabasePutCommand("family", "key", "value"); + + //when + String actual = databasePutCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("DATABASE PUT \"family\" \"key\" \"value\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/DialCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/DialCommandTest.java new file mode 100644 index 000000000..a68ab3266 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/DialCommandTest.java @@ -0,0 +1,48 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.AsteriskVersion.ASTERISK_10; + +class DialCommandTest { + @Test + void shouldBuildDialCommand() { + //given + DialCommand dialCommand = new DialCommand("PJSIP/alice", 30, "c"); + + //when + String actual = dialCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"dial\" \"PJSIP/alice\"|\"30\"|\"c\""); + } + + @Test + void shouldBuildDialCommandForAsteriskGreaterThan10() { + //given + DialCommand dialCommand = new DialCommand("PJSIP/alice", 30, "c"); + dialCommand.setAsteriskVersion(ASTERISK_10); + + //when + String actual = dialCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"dial\" \"PJSIP/alice\",\"30\",\"c\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/ExecCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/ExecCommandTest.java index 82414ee0b..09cf4d6c9 100644 --- a/src/test/java/org/asteriskjava/fastagi/command/ExecCommandTest.java +++ b/src/test/java/org/asteriskjava/fastagi/command/ExecCommandTest.java @@ -1,55 +1,82 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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 org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; class ExecCommandTest { - private ExecCommand execCommand; - @Test - void testDefault() { - execCommand = new ExecCommand("DIAL"); - assertEquals("EXEC \"DIAL\" \"\"", execCommand.buildCommand()); + void shouldExecApplicationWithoutOptions() { + //given + ExecCommand execCommand = new ExecCommand("DIAL"); + + //when + String actual = execCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"DIAL\" \"\""); } @Test - void testWithSingleOption() { - execCommand = new ExecCommand("DIAL", "SIP/1234"); - assertEquals("EXEC \"DIAL\" \"SIP/1234\"", execCommand.buildCommand()); + void shouldExecApplicationWithSingleOption() { + //given + ExecCommand execCommand = new ExecCommand("DIAL", "SIP/1234"); + + //when + String actual = execCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"DIAL\" \"SIP/1234\""); } @Test - void testWithMultipleOptionsSingleParameterPipeSeparated() { - execCommand = new ExecCommand("DIAL", "SIP/1234|30"); - assertEquals("EXEC \"DIAL\" \"SIP/1234|30\"", execCommand.buildCommand()); + void shouldExecWithMultipleOptionsSingleParameterPipeSeparated() { + //given + ExecCommand execCommand = new ExecCommand("DIAL", "SIP/1234|30"); + + //when + String actual = execCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"DIAL\" \"SIP/1234|30\""); } @Test - void testWithMultipleOptionsSingleParameterCommaSeparated() { - execCommand = new ExecCommand("DIAL", "SIP/1234,30"); - assertEquals("EXEC \"DIAL\" \"SIP/1234,30\"", execCommand.buildCommand()); + void shouldExecWithMultipleOptionsSingleParameterCommaSeparated() { + //given + ExecCommand execCommand = new ExecCommand("DIAL", "SIP/1234,30"); + + //when + String actual = execCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"DIAL\" \"SIP/1234,30\""); } @Test - void testWithMultipleOptionsMultipleParameters() { - execCommand = new ExecCommand("DIAL", "SIP/1234", "30"); - assertEquals("EXEC \"DIAL\" \"SIP/1234,30\"", execCommand.buildCommand()); + void shouldExecWithMultipleOptionsMultipleParameters() { + //given + ExecCommand execCommand = new ExecCommand("DIAL", "SIP/1234", "30"); + + //when + String actual = execCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"DIAL\" \"SIP/1234,30\""); } } diff --git a/src/test/java/org/asteriskjava/fastagi/command/GetDataCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/GetDataCommandTest.java index 04c0c83ac..1c78d5f5d 100644 --- a/src/test/java/org/asteriskjava/fastagi/command/GetDataCommandTest.java +++ b/src/test/java/org/asteriskjava/fastagi/command/GetDataCommandTest.java @@ -1,59 +1,94 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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 org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; class GetDataCommandTest { private GetDataCommand getDataCommand; @Test - void testDefault() { - getDataCommand = new GetDataCommand("VAR1"); - assertEquals("GET DATA \"VAR1\"", getDataCommand.buildCommand()); + void shouldBuildGetDataCommand() { + //given + GetDataCommand getDataCommand = new GetDataCommand("VAR1"); + + //when + String actual = getDataCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("GET DATA \"VAR1\""); } @Test - void testSetTimeout() { - getDataCommand = new GetDataCommand("VAR1"); + void shouldSetTimeoutWhenBuildGetDataCommand() { + //given + GetDataCommand getDataCommand = new GetDataCommand("VAR1"); getDataCommand.setTimeout(10000); - assertEquals(10000, getDataCommand.getTimeout()); - assertEquals(1024, getDataCommand.getMaxDigits()); - assertEquals("GET DATA \"VAR1\" 10000", getDataCommand.buildCommand()); + + //when + String actual = getDataCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("GET DATA \"VAR1\" 10000"); + assertThat(getDataCommand.getTimeout()).isEqualTo(10000); + assertThat(getDataCommand.getMaxDigits()).isEqualTo(1024); } @Test - void testSetMaxDigits() { - getDataCommand = new GetDataCommand("VAR1"); + void shouldSetMaxDigitsWhenBuildGetDataCommand() { + //given + GetDataCommand getDataCommand = new GetDataCommand("VAR1"); getDataCommand.setMaxDigits(10); - assertEquals(0, getDataCommand.getTimeout()); - assertEquals(10, getDataCommand.getMaxDigits()); - assertEquals("GET DATA \"VAR1\" 0 10", getDataCommand.buildCommand()); + + //when + String actual = getDataCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("GET DATA \"VAR1\" 0 10"); + assertThat(getDataCommand.getTimeout()).isEqualTo(0); + assertThat(getDataCommand.getMaxDigits()).isEqualTo(10); } @Test - void testSetTimeoutAndMaxDigits() { - getDataCommand = new GetDataCommand("VAR1"); + void shouldSetTimeoutAndSetMaxDigitsWhenBuildGetDataCommand() { + //given + GetDataCommand getDataCommand = new GetDataCommand("VAR1"); getDataCommand.setTimeout(10000); getDataCommand.setMaxDigits(20); - assertEquals(10000, getDataCommand.getTimeout()); - assertEquals(20, getDataCommand.getMaxDigits()); - assertEquals("GET DATA \"VAR1\" 10000 20", getDataCommand.buildCommand()); + + //when + String actual = getDataCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("GET DATA \"VAR1\" 10000 20"); + assertThat(getDataCommand.getTimeout()).isEqualTo(10000); + assertThat(getDataCommand.getMaxDigits()).isEqualTo(20); + } + + @ParameterizedTest + @ValueSource(ints = {0, 1025}) + void shouldThrowExceptionWhenMaxDigitsIsOutOfRange(int maxDigits) { + //when/then + assertThatThrownBy(() -> new GetDataCommand("VAR1", 10, maxDigits)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("maxDigits must be in [1..1024]"); } } diff --git a/src/test/java/org/asteriskjava/fastagi/command/GetFullVariableCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/GetFullVariableCommandTest.java new file mode 100644 index 000000000..85ad38d1e --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/GetFullVariableCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class GetFullVariableCommandTest { + @Test + void shouldBuildGetFullVariableCommand() { + //given + GetFullVariableCommand getFullVariableCommand = new GetFullVariableCommand("VAR"); + + //when + String actual = getFullVariableCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("GET FULL VARIABLE \"VAR\""); + } + + @Test + void shouldBuildGetFullVariableCommandWithChannel() { + //given + GetFullVariableCommand getFullVariableCommand = new GetFullVariableCommand("VAR", "SIP/1234"); + + //when + String actual = getFullVariableCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("GET FULL VARIABLE \"VAR\" \"SIP/1234\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/GetOptionCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/GetOptionCommandTest.java new file mode 100644 index 000000000..380d887f7 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/GetOptionCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class GetOptionCommandTest { + @Test + void shouldBuildGetOptionCommand() { + //given + GetOptionCommand getOptionCommand = new GetOptionCommand("file-name", "15"); + + //when + String actual = getOptionCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("GET OPTION \"file-name\" \"15\""); + } + + @Test + void shouldBuildGetOptionCommandWithTimeout() { + //given + GetOptionCommand getOptionCommand = new GetOptionCommand("file-name", "15", 30); + + //when + String actual = getOptionCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("GET OPTION \"file-name\" \"15\" 30"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/GosubCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/GosubCommandTest.java new file mode 100644 index 000000000..a282ed5e5 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/GosubCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class GosubCommandTest { + @Test + void shouldBuildGosubCommand() { + //given + GosubCommand gosubCommand = new GosubCommand("phones", "102", "1"); + + //when + String actual = gosubCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("GOSUB \"phones\" \"102\" \"1\""); + } + + @Test + void shouldBuildGosubCommandWithArguments() { + //given + GosubCommand gosubCommand = new GosubCommand("phones", "102", "1", "agr1", "agr2"); + + //when + String actual = gosubCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("GOSUB \"phones\" \"102\" \"1\" \"agr1,agr2\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/HangupCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/HangupCommandTest.java new file mode 100644 index 000000000..bd05d2e52 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/HangupCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class HangupCommandTest { + @Test + void shouldBuildHangupCommandForCurrentChannel() { + //given + HangupCommand hangupCommand = new HangupCommand(); + + //when + String actual = hangupCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("HANGUP"); + } + + @Test + void shouldBuildHangupCommand() { + //given + HangupCommand hangupCommand = new HangupCommand("SIP/1234"); + + //when + String actual = hangupCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("HANGUP \"SIP/1234\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/MeetmeCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/MeetmeCommandTest.java new file mode 100644 index 000000000..4bad219b2 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/MeetmeCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class MeetmeCommandTest { + @Test + void shouldBuildMeetmeCommand() { + //given + MeetmeCommand meetmeCommand = new MeetmeCommand("room", "Ac"); + + //when + String actual = meetmeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"meetme\" \"room\"|\"Ac\""); + } + + @Test + void shouldBuildMeetmeCommandWithoutOptions() { + //given + MeetmeCommand meetmeCommand = new MeetmeCommand("room", null); + + //when + String actual = meetmeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"meetme\" \"room\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/NoopCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/NoopCommandTest.java new file mode 100644 index 000000000..f6b3d39c8 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/NoopCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class NoopCommandTest { + @Test + void shouldBuildNoopCommand() { + //given + NoopCommand noopCommand = new NoopCommand(); + + //when + String actual = noopCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("NOOP"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/QueueCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/QueueCommandTest.java new file mode 100644 index 000000000..96413a4bf --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/QueueCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class QueueCommandTest { + @Test + void shouldBuildQueueCommand() { + //given + QueueCommand queueCommand = new QueueCommand("queue-name"); + + //when + String actual = queueCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("EXEC \"queue\" \"queue-name\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/ReceiveCharCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/ReceiveCharCommandTest.java new file mode 100644 index 000000000..682c3a8ca --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/ReceiveCharCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class ReceiveCharCommandTest { + @Test + void shouldBuildReceiveCharCommand() { + //given + ReceiveCharCommand receiveCharCommand = new ReceiveCharCommand(); + + //when + String actual = receiveCharCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("RECEIVE CHAR 0"); + } + + @Test + void shouldBuildReceiveCharCommandWithTimeout() { + //given + ReceiveCharCommand receiveCharCommand = new ReceiveCharCommand(20); + + //when + String actual = receiveCharCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("RECEIVE CHAR 20"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/ReceiveTextCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/ReceiveTextCommandTest.java new file mode 100644 index 000000000..ea7c21b89 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/ReceiveTextCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class ReceiveTextCommandTest { + @Test + void shouldBuildReceiveTextCommand() { + //given + ReceiveTextCommand receiveTextCommand = new ReceiveTextCommand(); + + //when + String actual = receiveTextCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("RECEIVE TEXT 0"); + } + + @Test + void shouldBuildReceiveCharCommandWithTimeout() { + //given + ReceiveTextCommand receiveTextCommand = new ReceiveTextCommand(20); + + //when + String actual = receiveTextCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("RECEIVE TEXT 20"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/RecordFileCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/RecordFileCommandTest.java new file mode 100644 index 000000000..051924f49 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/RecordFileCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class RecordFileCommandTest { + @Test + void shouldBuildRecordFileCommand() { + //given + RecordFileCommand recordFileCommand = new RecordFileCommand("some-file", "wav", "4", 10); + + //when + String actual = recordFileCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("RECORD FILE \"some-file\" \"wav\" \"4\" 10 0 s=0"); + } + + @Test + void shouldBuildRecordFileCommandWithOffsetBeepAndMaxSilence() { + //given + RecordFileCommand recordFileCommand = new RecordFileCommand("some-file", "wav", "4", 10, 10, true, 15); + + //when + String actual = recordFileCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("RECORD FILE \"some-file\" \"wav\" \"4\" 10 10 BEEP s=15"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SayAlphaCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SayAlphaCommandTest.java new file mode 100644 index 000000000..030bd1f4a --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SayAlphaCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SayAlphaCommandTest { + @Test + void shouldBuildSayAlphaCommand() { + //given + SayAlphaCommand sayAlphaCommand = new SayAlphaCommand("some text"); + + //when + String actual = sayAlphaCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY ALPHA \"some text\" \"\""); + } + + @Test + void shouldBuildSayAlphaCommandWithEscapeDigits() { + //given + SayAlphaCommand sayAlphaCommand = new SayAlphaCommand("some text", "8"); + + //when + String actual = sayAlphaCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY ALPHA \"some text\" \"8\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SayDateTimeCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SayDateTimeCommandTest.java new file mode 100644 index 000000000..8e60a24d5 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SayDateTimeCommandTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import java.time.Instant; + +import static org.assertj.core.api.Assertions.assertThat; + +class SayDateTimeCommandTest { + private final long time = Instant.parse("2022-09-03T11:48:30.00Z").getEpochSecond(); + + @Test + void shouldBuildSayDateTimeCommand() { + //given + SayDateTimeCommand sayDateTimeCommand = new SayDateTimeCommand(time); + + //when + String actual = sayDateTimeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY DATETIME 1662205710 \"\""); + } + + @Test + void shouldBuildSayDateTimeCommandWithEscapeDigits() { + //given + SayDateTimeCommand sayDateTimeCommand = new SayDateTimeCommand(time, "1"); + + //when + String actual = sayDateTimeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY DATETIME 1662205710 \"1\""); + } + + @Test + void shouldBuildSayDateTimeCommandWithEscapeDigitsAndFormat() { + //given + SayDateTimeCommand sayDateTimeCommand = new SayDateTimeCommand(time, "1", "Y k"); + + //when + String actual = sayDateTimeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY DATETIME 1662205710 \"1\" \"Y k\""); + } + + @Test + void shouldBuildSayDateTimeCommandWithEscapeDigitsAndDefaultFormatAndTimezons() { + //given + SayDateTimeCommand sayDateTimeCommand = new SayDateTimeCommand(time, "1", null, "Poland"); + + //when + String actual = sayDateTimeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY DATETIME 1662205710 \"1\" \"ABdY 'digits/at' IMp\" \"Poland\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SayDigitsCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SayDigitsCommandTest.java new file mode 100644 index 000000000..e15572b12 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SayDigitsCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SayDigitsCommandTest { + @Test + void shouldBuildSayDigitsCommand() { + //given + SayDigitsCommand sayDigitsCommand = new SayDigitsCommand("1234"); + + //when + String actual = sayDigitsCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY DIGITS \"1234\" \"\""); + } + + @Test + void shouldBuildSayDigitsCommandWithEscapeDigit() { + //given + SayDigitsCommand sayDigitsCommand = new SayDigitsCommand("1234", "90"); + + //when + String actual = sayDigitsCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY DIGITS \"1234\" \"90\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SayNumberCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SayNumberCommandTest.java new file mode 100644 index 000000000..3b313e458 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SayNumberCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SayNumberCommandTest { + @Test + void shouldBuildSayNumberCommand() { + //given + SayNumberCommand sayNumberCommand = new SayNumberCommand("5426"); + + //when + String actual = sayNumberCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY NUMBER \"5426\" \"\""); + } + + @Test + void shouldBuildSayNumberCommandWithEscapeDigits() { + //given + SayNumberCommand sayNumberCommand = new SayNumberCommand("5426", "98"); + + //when + String actual = sayNumberCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY NUMBER \"5426\" \"98\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SayPhoneticCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SayPhoneticCommandTest.java new file mode 100644 index 000000000..f1c6a24e4 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SayPhoneticCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SayPhoneticCommandTest { + @Test + void shouldBuildSayPhonetic() { + //given + SayPhoneticCommand sayPhoneticCommand = new SayPhoneticCommand("some text"); + + //when + String actual = sayPhoneticCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY PHONETIC \"some text\" \"\""); + } + + @Test + void shouldBuildSayPhoneticWithEscapeDigits() { + //given + SayPhoneticCommand sayPhoneticCommand = new SayPhoneticCommand("some text", "89"); + + //when + String actual = sayPhoneticCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY PHONETIC \"some text\" \"89\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SayTimeCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SayTimeCommandTest.java new file mode 100644 index 000000000..88e2d953d --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SayTimeCommandTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import java.time.Instant; + +import static org.assertj.core.api.Assertions.assertThat; + +class SayTimeCommandTest { + private final long time = Instant.parse("2022-09-03T11:48:30.00Z").getEpochSecond(); + + @Test + void shouldBuildSayTimeCommand() { + //given + SayTimeCommand sayTimeCommand = new SayTimeCommand(time); + + //when + String actual = sayTimeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY TIME 1662205710 \"\""); + } + + @Test + void shouldBuildSayTimeCommandWithEscapeDigits() { + //given + SayTimeCommand sayTimeCommand = new SayTimeCommand(time, "89"); + + //when + String actual = sayTimeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SAY TIME 1662205710 \"89\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SendImageCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SendImageCommandTest.java new file mode 100644 index 000000000..15debddf5 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SendImageCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SendImageCommandTest { + @Test + void shouldBuildSendImageCommand() { + //given + SendImageCommand sendImageCommand = new SendImageCommand("image.png"); + + //when + String actual = sendImageCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SEND IMAGE \"image.png\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SendTextCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SendTextCommandTest.java new file mode 100644 index 000000000..a3b20a9a0 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SendTextCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SendTextCommandTest { + @Test + void shouldBuildSendTextCommand() { + //given + SendTextCommand sendTextCommand = new SendTextCommand("text to send"); + + //when + String actual = sendTextCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SEND TEXT \"text to send\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SetAutoHangupCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SetAutoHangupCommandTest.java new file mode 100644 index 000000000..064d96de5 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SetAutoHangupCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SetAutoHangupCommandTest { + @Test + void shouldBuildSetAutoHangupCommand() { + //given + SetAutoHangupCommand setAutoHangupCommand = new SetAutoHangupCommand(5); + + //when + String actual = setAutoHangupCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SET AUTOHANGUP 5"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SetCallerIdCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SetCallerIdCommandTest.java new file mode 100644 index 000000000..72ba1a8d2 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SetCallerIdCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SetCallerIdCommandTest { + @Test + void shouldBuildSetAutoHangupCommand() { + //given + SetCallerIdCommand setCallerIdCommand = new SetCallerIdCommand("500333444"); + + //when + String actual = setCallerIdCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SET CALLERID \"500333444\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SetContextCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SetContextCommandTest.java new file mode 100644 index 000000000..813ada1cb --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SetContextCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SetContextCommandTest { + @Test + void shouldBuildSetContextCommand() { + //given + SetContextCommand setContextCommand = new SetContextCommand("phones"); + + //when + String actual = setContextCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SET CONTEXT \"phones\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SetExtensionCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SetExtensionCommandTest.java new file mode 100644 index 000000000..da901c843 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SetExtensionCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SetExtensionCommandTest { + @Test + void shouldBuildSetExtensionCommand() { + //given + SetExtensionCommand setExtensionCommand = new SetExtensionCommand("SIP/123"); + + //when + String actual = setExtensionCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SET EXTENSION \"SIP/123\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SetMusicOffCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SetMusicOffCommandTest.java new file mode 100644 index 000000000..4c2b92514 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SetMusicOffCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SetMusicOffCommandTest { + @Test + void shouldBuildSetMusicOffCommand() { + //given + SetMusicOffCommand setMusicOffCommand = new SetMusicOffCommand(); + + //when + String actual = setMusicOffCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SET MUSIC OFF"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SetMusicOnCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SetMusicOnCommandTest.java new file mode 100644 index 000000000..f93bf3390 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SetMusicOnCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SetMusicOnCommandTest { + @Test + void shouldBuildSetMusicOnCommand() { + //given + SetMusicOnCommand setMusicOnCommand = new SetMusicOnCommand(); + + //when + String actual = setMusicOnCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SET MUSIC ON"); + } + + @Test + void shouldBuildSetMusicOnCommandWithClass() { + //given + SetMusicOnCommand setMusicOnCommand = new SetMusicOnCommand("moh-class"); + + //when + String actual = setMusicOnCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SET MUSIC ON \"moh-class\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SetPriorityCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SetPriorityCommandTest.java new file mode 100644 index 000000000..d63844bc1 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SetPriorityCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SetPriorityCommandTest { + @Test + void shouldBuildSetPriorityCommand() { + //given + SetPriorityCommand setPriorityCommand = new SetPriorityCommand("1"); + + //when + String actual = setPriorityCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SET PRIORITY \"1\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SetVariableCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SetVariableCommandTest.java new file mode 100644 index 000000000..b3c5f1cfb --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SetVariableCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SetVariableCommandTest { + @Test + void shouldBuildSetVariableCommand() { + //given + SetVariableCommand setVariableCommand = new SetVariableCommand("name", "value"); + + //when + String actual = setVariableCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SET VARIABLE \"name\" \"value\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SpeechActivateGrammarCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SpeechActivateGrammarCommandTest.java new file mode 100644 index 000000000..ea1fe404c --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SpeechActivateGrammarCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SpeechActivateGrammarCommandTest { + @Test + void shouldBuildSpeechActivateGrammarCommand() { + //given + SpeechActivateGrammarCommand speechActivateGrammarCommand = new SpeechActivateGrammarCommand("grammar name"); + + //when + String actual = speechActivateGrammarCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SPEECH ACTIVATE GRAMMAR \"grammar name\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SpeechCreateCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SpeechCreateCommandTest.java new file mode 100644 index 000000000..5fc77aac6 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SpeechCreateCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SpeechCreateCommandTest { + @Test + void shouldBuildSpeechCreateCommand() { + //given + SpeechCreateCommand speechCreateCommand = new SpeechCreateCommand("engine"); + + //when + String actual = speechCreateCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SPEECH CREATE \"engine\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SpeechDeactivateGrammarCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SpeechDeactivateGrammarCommandTest.java new file mode 100644 index 000000000..40309be00 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SpeechDeactivateGrammarCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SpeechDeactivateGrammarCommandTest { + @Test + void shouldBuildSpeechDeactivateGrammarCommand() { + //given + SpeechDeactivateGrammarCommand speechDeactivateGrammarCommand = new SpeechDeactivateGrammarCommand("grammar"); + + //when + String actual = speechDeactivateGrammarCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SPEECH DEACTIVATE GRAMMAR \"grammar\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SpeechDestroyCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SpeechDestroyCommandTest.java new file mode 100644 index 000000000..d3e5f3a41 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SpeechDestroyCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SpeechDestroyCommandTest { + @Test + void shouldBuildSpeechDestroyCommand() { + //given + SpeechDestroyCommand speechDestroyCommand = new SpeechDestroyCommand(); + + //when + String actual = speechDestroyCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SPEECH DESTROY"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SpeechLoadGrammarCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SpeechLoadGrammarCommandTest.java new file mode 100644 index 000000000..24be43c8f --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SpeechLoadGrammarCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SpeechLoadGrammarCommandTest { + @Test + void shouldBuildSpeechLoadGrammarCommand() { + //given + SpeechLoadGrammarCommand speechLoadGrammarCommand = new SpeechLoadGrammarCommand("grammar-name", "/path/to/grammar"); + + //when + String actual = speechLoadGrammarCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SPEECH LOAD GRAMMAR \"grammar-name\" \"/path/to/grammar\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SpeechRecognizeCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SpeechRecognizeCommandTest.java new file mode 100644 index 000000000..4ac6d098a --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SpeechRecognizeCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SpeechRecognizeCommandTest { + @Test + void shouldBuildSpeechRecognizeCommand() { + //given + SpeechRecognizeCommand speechRecognizeCommand = new SpeechRecognizeCommand("prompt", 10); + + //when + String actual = speechRecognizeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SPEECH RECOGNIZE \"prompt\" 10 0"); + } + + @Test + void shouldBuildSpeechRecognizeCommandWithOffset() { + //given + SpeechRecognizeCommand speechRecognizeCommand = new SpeechRecognizeCommand("prompt", 10, 20); + + //when + String actual = speechRecognizeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SPEECH RECOGNIZE \"prompt\" 10 20"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SpeechSetCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SpeechSetCommandTest.java new file mode 100644 index 000000000..bc337efa3 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SpeechSetCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SpeechSetCommandTest { + @Test + void shouldBuildSpeechSetCommand() { + //given + SpeechSetCommand speechSetCommand = new SpeechSetCommand("name", "value"); + + //when + String actual = speechSetCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SPEECH SET \"name\" \"value\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/SpeechUnloadGrammarCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/SpeechUnloadGrammarCommandTest.java new file mode 100644 index 000000000..1d2b0a84b --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/SpeechUnloadGrammarCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SpeechUnloadGrammarCommandTest { + @Test + void shouldBuildSpeechUnloadGrammarCommand() { + //given + SpeechUnloadGrammarCommand speechUnloadGrammarCommand = new SpeechUnloadGrammarCommand("name"); + + //when + String actual = speechUnloadGrammarCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("SPEECH UNLOAD GRAMMAR \"name\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/StreamFileCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/StreamFileCommandTest.java new file mode 100644 index 000000000..fba122f23 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/StreamFileCommandTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class StreamFileCommandTest { + @Test + void shouldBuildStreamFileCommand() { + //given + StreamFileCommand streamFileCommand = new StreamFileCommand("file"); + + //when + String actual = streamFileCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("STREAM FILE \"file\" \"\""); + } + + @Test + void shouldBuildStreamFileCommandWithEscapeDigits() { + //given + StreamFileCommand streamFileCommand = new StreamFileCommand("file", "45"); + + //when + String actual = streamFileCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("STREAM FILE \"file\" \"45\""); + } + + @Test + void shouldBuildStreamFileCommandWithEscapeDigitsAndOffset() { + //given + StreamFileCommand streamFileCommand = new StreamFileCommand("file", "45", 20); + + //when + String actual = streamFileCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("STREAM FILE \"file\" \"45\" 20"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/TddModeCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/TddModeCommandTest.java new file mode 100644 index 000000000..aa0fafc27 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/TddModeCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class TddModeCommandTest { + @Test + void shouldBuildTddModeCommand() { + //given + TddModeCommand tddModeCommand = new TddModeCommand("on"); + + //when + String actual = tddModeCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("TDD MODE \"on\""); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/VerboseCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/VerboseCommandTest.java new file mode 100644 index 000000000..ee63a8aba --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/VerboseCommandTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class VerboseCommandTest { + @Test + void shouldBuildVerboseCommand() { + //given + VerboseCommand verboseCommand = new VerboseCommand("message to print", 1); + + //when + String actual = verboseCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("VERBOSE \"message to print\" 1"); + } +} diff --git a/src/test/java/org/asteriskjava/fastagi/command/WaitForDigitCommandTest.java b/src/test/java/org/asteriskjava/fastagi/command/WaitForDigitCommandTest.java new file mode 100644 index 000000000..299a4f113 --- /dev/null +++ b/src/test/java/org/asteriskjava/fastagi/command/WaitForDigitCommandTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class WaitForDigitCommandTest { + @Test + void shouldBuildWaitForDigitCommand() { + //given + WaitForDigitCommand waitForDigitCommand = new WaitForDigitCommand(); + + //when + String actual = waitForDigitCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("WAIT FOR DIGIT -1"); + } + + @Test + void shouldBuildWaitForDigitCommandWithTimeout() { + //given + WaitForDigitCommand waitForDigitCommand = new WaitForDigitCommand(10); + + //when + String actual = waitForDigitCommand.buildCommand(); + + //then + assertThat(actual).isEqualTo("WAIT FOR DIGIT 10"); + } +} From 1b6d315bdd0b468a13f61ce115b712d6d146a63c Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Sat, 24 Sep 2022 08:23:56 +0200 Subject: [PATCH 516/802] Remove gradle --- build.gradle | 157 ---------------------- gradle/wrapper/gradle-wrapper.jar | Bin 51010 -> 0 bytes gradle/wrapper/gradle-wrapper.properties | 6 - gradlew | 164 ----------------------- gradlew.bat | 90 ------------- settings.gradle | 1 - 6 files changed, 418 deletions(-) delete mode 100644 build.gradle delete mode 100644 gradle/wrapper/gradle-wrapper.jar delete mode 100644 gradle/wrapper/gradle-wrapper.properties delete mode 100755 gradlew delete mode 100644 gradlew.bat delete mode 100644 settings.gradle diff --git a/build.gradle b/build.gradle deleted file mode 100644 index ecdeb7043..000000000 --- a/build.gradle +++ /dev/null @@ -1,157 +0,0 @@ -apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'idea' -apply plugin: 'eclipse' -apply plugin: 'signing' - -group = 'org.asteriskjava' -version = '2.0.0.CI-SNAPSHOT' - -description = """Asterisk-Java""" - -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -repositories { - - maven { url "http://repo.maven.apache.org/maven2" } -} - -dependencies { - compile group: 'log4j', name: 'log4j', version:'1.2.17' - compile group: 'org.apache.commons', name: 'commons-lang3', version:'3.1' - compile group: 'org.slf4j', name: 'slf4j-api', version:'1.7.9' - compile group: 'com.google.guava', name: 'guava', version:'30.1-jre' - testCompile group: 'org.easymock', name: 'easymock', version:'3.3' - testCompile group: 'junit', name: 'junit', version:'4.12' - testCompile group: 'ch.qos.logback', name: 'logback-classic', version:'1.1.2' -} - -test { - testLogging { - events 'started', 'passed' - } -} - -task javadocJar(type: Jar) { - classifier = 'javadoc' - from javadoc -} - -task sourcesJar(type: Jar) { - classifier = 'sources' - from sourceSets.main.allSource -} - -artifacts { - archives javadocJar, sourcesJar -} - -signing { - required { gradle.taskGraph.hasTask("uploadArchives") } - sign configurations.archives -} - -def ossrhUsername = hasProperty('ossrhUsername') ? ossrhUsername : '' -def ossrhPassword = hasProperty('ossrhPassword') ? ossrhPassword : '' - -uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - - snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - - pom.project { - name 'Asterisk-Java' - packaging 'jar' - // optionally artifactId can be defined here - description 'The free Java library for Asterisk PBX integration.' - url 'https://github.com/asterisk-java/asterisk-java' - - scm { - connection 'scm:git:https://github.com/asterisk-java/asterisk-java.git' - developerConnection 'scm:git:https://github.com/asterisk-java/asterisk-java.git' - url 'https://github.com/asterisk-java/asterisk-java' - } - - licenses { - license { - name 'Apache 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.html' - } - } - - mailingLists { - mailingList { - name 'Asterisk-Java User List' - subscribe "http://lists.sourceforge.net/mailman/listinfo/asterisk-java-users" - unsubscribe "http://lists.sourceforge.net/mailman/listinfo/asterisk-java-users" - archive "http://sourceforge.net/mailarchive/forum.php?forum=asterisk-java-users" - } - mailingList { - name "Asterisk-Java Developer List" - subscribe "http://lists.sourceforge.net/mailman/listinfo/asterisk-java-devel" - unsubscribe "http://lists.sourceforge.net/mailman/listinfo/asterisk-java-devel" - archive "http://sourceforge.net/mailarchive/forum.php?forum=asterisk-java-devel" - } - } - - developers { - developer { - id 'srt' - name 'Stefan Reuter' - email 'stefan.reuter at reucon.com' - timezone '+1' - } - developer { - name 'Pierre-Yves Roger' - id 'partoutatis' - email 'partoutatis at users.sourceforge.net' - timezone '+1' - } - developer { - name 'John Hood' - id 'squinky86' - email 'john at asteriasgi.com' - organization 'Asteria Solutions Group, Inc.' - timezone '-6' - } - developer { - name 'Martin B. Smith' - id 'martins' - email 'martins at bebr.ufl.edu' - organization 'Bureau of Economic and Business Research, University of Florida' - timezone '-5' - } - developer { - name 'S. Brett Sutton' - id 'bsutton' - email 'bsutton at noojee.com.au' - organization 'Noojee Telephony Solutions Pty Ltd' - timezone '+10' - } - developer { - name 'Octavio Luna' - id 'itaqua' - email 'octavio.luna at gmail.com' - organization 'N4Utilus Take your Business to the Cloud' - timezone '-6' - } - developer { - name 'Zoumana TRAORE' - id 'zoumhussein' - email 'github at zoumanatraore dot fr' - timezone '+1' - } - } - } - } - } -} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 2322723c7ed5f591adfa4c87b6c51932f591249a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51010 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∓LFg$ z3XI^8)}x<8`5U&l3ds;F@+FtpQ7OC!>3AZ_T0$f!y^Rt`ot;J`StJq_Qs{o4Vju~3 zkS0qahjj01TnTvQH_cqh5 z-pq6;V8sNIoE|3GpbWB}oX`I#E-$VgRtBcI|CvOEsESMNJh2am(8$QWk~F3qM2oX1 z&wX;6A;G2b8kZDnzmGd{QrvAiQzAJ#(2`a)IBcckCbXUsp=1_uCUSVt;=z703`l5P zNRE_Er|RvCB;O>MV@XfvoZd z)rrT=?9~9NejgZ%Rd`zZL=%8T=F-0ZDY0@O>arLW6tH$+}g_}%=-{Wk>#P{-2 zSL@~|SHCTxccYr*=Yg1??6_oderuH3;uh=#1y9w{K;+jO&7o$K zoHR#2;r#TGLZgtO~a25*U(e`9JIp_Rxe4 z=FlX$uMDpIN~7or(+05frN>^F2YJ#PC&*DGwv__2;$J zykU6`xR9p~Nr>1vi9X*U-X~v~QSY_+jTTGv2}+0M#S9SC3haJdu|-iPE$9sB!<}m7 z{Pb{;9IP#fS6l!}PoO-YOoEKiC5ldhc#oQu+N5}93D7wp*`*CU2UFU#TVL?_%*Iln zzH&}YXlX(j+bAuzrATj~HZKkcdfpPqT`4e}PPAK>*wL8LD2y`(-7`$iAGi< z0G&sq0HAdb=$#g~B`I{6t3*{3D6IV+T6u5ryO$(}COT(1+^PVDow{r$jiN36zPH)n zCszO$+)vT+?H)_L);8E)uMlELG3TUa*-)W%L?Ro(qW6wmX1{!<`C>K+U7(;L^BFS7H;-um1OQM51^{6H?>UTrX>lW#v@y`L6g2x5 z8<^=k{l8xJM0pJftZyTpN#l(L$8x*Ird5pww-Af7)m;q)dZoD)x`u?LwVWS>k^S5mFh=t znOQ6DvUhHH6@Hm=*&<^K{3K_q*RC4KK6z<+NH@)U6f zi%K1wDmOlFG!I8jz!yqoWNbi<`r;oMkz_!WZ{2{aXHPfcT3Bl6}e7+sZt+GP%e9@nY_Kw*0Z;`MT7)-|T-R$TN0{}qq-$%l~8cqc& zn`vNuD^W#6(`LSP6ZEy;Fm6}qoW$BdL^=aA0%-t50a?_j+3Cj#P+cL0k@0?EdV8VS zoTFH}W1-kmi&filDUGH;9M8u#+y~tUl-1Txa4}tO+TB)%D~>1XyRM_G*00y84LE>^ z9X!rg0z&luJnSS#*fGpoPTK9fFh5unAskdo9Fh*=A0n4_POjwTEd{%EQLLIX2m?wu z*?mWauTYp>C3_Mrq``D&-`o(U-xu2kR_hV|@(m15^>#X@@cyob{Z_gBZCQ|w zg{xGb3$v$6-xKpUd2mMQowFD0Dlm{v>0Pip1ewzo9c{yJ?vT}Dazaka}+el@~BvI&hpU_-sR!@%HUqqXdJU-)RMiW`YO=d%blV78^ z)?uspeK3+euHkmo;wKRLW_6i-KSc#Dz05Ianm($b-=?VvKM8fn-xFYOB;jLoD1pP!6VM3^xX|7cXMo6bSnOlF}G{!&;+)YP|Eyb>1^+o-wl ztEbDnE$LeL$XH=P@$T`s)RXVotjw792t2tqU!xhZFT=L8L+Jr$!@T@gc1IivNvWgK zyCC12@p8fe#1JFYc=0)M6Gv8_QNuapQGZ;Cys#_UXn43E$dAcLCX#Z^3>3zXrZ@w- zk#o}XI!E!|?0l8>bBg1t1BasX#8KQ_G~?J!|NfAd%T>fg7X8o)$)uk^Zl^Ab=L*XC zZV~&2W1w?L4(V!?$Kv;FY^eB56oqT zzFT8EaFm~>+gk4<-D(*`Ah+B>UODT6wFNAqVw&4oyOquO0W;wjyvXouR;& z3}1i#=#3J|R>v|yp{d$XZn9ki@)Yams9V`iwWWrr z9(_~-{gKXGU*xoz>?*6X%6sS%ce(1ew%F*T;z~Adb8XaC z)W?l=_Bdgndd0u9JD|B~_p#~XJjd4ngbtep8 z>8>JIe7hTmd&FH|M?J{3TovzPjW;&K3Oh&i$mWPi zNE>mKoo5_XyoamSucL0tgx@`D;Ly+;!cZzb>0SQC?9Kw4p^x;-+Je{gbh2;9RcJ#L z7aR0LbI&b4R;TxU6rYk{(APuWS}-nQ?S)lTsBQk&+=5Fv#tBNMF7Ty8;jcV+fk7Yl z_S4Y@mdi?e(7 zvEW8H4J<%95Bj4xk_q4huP!wfpmO953D{No1v5sA0NL!-T6>x78{LI$R=Vh^Fx(Dm z9DBmG8*rnX-w5r7@L(^gI}1}Tdwl$PD!AN%d>jyX${7$qxrf~n__76!))dj1H7!#v zT~xq3Bj?i}5 zNSgn!O||`Y8KAZOzs8~plM^x&6JkoDVp3z{W7H$#Q+x7{6H^M;V{{7i%(C>%wT!Gy zjI0W_&MFW~}0<)+v?MHJqyB z*gA(mtNK>*cxRHfUc4=>u#A6p2#*aEWT2l%K10S@+27du&qh(G+G+>0toZq0<$={ z{j-IAaTrvy@l#rHg*-Rw8DTl~Z))4WUjO@z|F5qu-1q;#e0BfXn`&Tb_Ae&5f88E4 ze4oVi?Et0l?G4EAUvKBr|4Wu@;3!~YW%cc*BWY%B^z8)Y{B02Xp90-PMXhf)SY&Qs zsBo&L5Ua|qX}E)Y$2Fc*eo^olQ~ol9+5RCTj3q1GWN3kWpWdxJI_8;vyzOYlO|=-= zq=tLFqfHKvt5%1@%?(~3pHDE`5F%iR^W$X}_?{?0oTItDSa~B9PHqW)wEcITcH;9svsY~D7`RhOf&fZhURx=l^ z`bAt(y_LGlC-mOo;}4Br*;mJ;f{DuInk1|nxJ1xHt%Ipf)~Q-! z4&%+pd8%Vf%k7UC%|;w}L89R#*t2y_A%0b2vlg@q+|v~{sf*ACg1pKxZ81p8H;>zc9Vjs9@NqpaMk2{T7; zFx;ueQr&m7)(8Z)`ARPi!6$(4wkPuCy&Y!H5 z%gTEbRwinHfr^br3&}zjCo&C`w+mR_1i!hOgQPO#bAzau^Cl`$L_d?Vb+x!Li|5(DmLXlC& zD7xr71dqRe|0az5D{}u9g0gz{-)5@+$rT1h@cm`VEc9jCs1D_P&=z7LFeQr&BGiM_ z?_5G-1|;@iOUvaOjHsa5X3KNOi)Xxf_TdUN3?B?GAQ*6LY2CDKRhd#VEVU-Cb!jm{ zW`?uoM06GRU8(V7sGOa4Z!9Db7zY&ACYDrCqlEJ>>>jx#BK!(*QLmp!bd16wIEm#K z(+b@y+{q&<_!1R6eD|2&OP)RLLgMIQQ^Vr{EDGt9y7Vnj>m#5V}> z^(FPAV~}R<(e+b-t4L+pP?$yCqU*RB#QMP37R@8N>4n=4X3Q$4aln!oOd`GDkomT> zT59n5{CtJU2|z(%*jMV83yEhYStzGOOi3~kqL>h5z#3oy8(4LMkq~4UqQ75`&$eBg zxqwM-=k$O41-_xp)Vg;J+o!owS3XcSK~i~#xx zwU56E@0WEvL7lM@c{ZO}OP9*p;zhCNT0#6yU1Q&blr@$-94yf#l>aP_n<0A?K^f0& zlNL;w`gxX+hzuo((wp``KcdHjtg4(W25CIEeRT|t{0#rrhE z#}g49iRh$Jd%ZcW>0_`0}@`)qDdGFi_}oH6d7-lRF(jBoQKf z6)&HUA$n!Ws7&LJo4aShnL^9_O=S_I12uC)}B^^EJd=^{=W^{b1Zk_k2@ zFw9c+3dgNpH^qay@s*dfy6yhOrHCNvB-Ub+2;k;Mm1X z^1C>sV?ku%RE3w!B0#4L0m}BFoCLdATp{=6eJpp$VWRw)*w5@tC4eRc!elV;Q@?)O z;s6Jhawc3^waDPoUSP4>jsTF6Bo@GrpwZ*{+JHd}lBC#2Gzsvs9iZF%+Ka@VYeCLI z<>LM&7d7?SER%S74yAuy9z5qMfR_v;rAO$yPB2!pRRdh}(PXI2rnJ0XGp4;)=m;9G zEu=QZB*FrWA!y1@Vv6vBM5PCEi>BNwG|O}^Ncs3T-0)YncT`9*#(rmj|M$kj{lCe8 ze}ulmH*sTa@|_>Hdf#4z|7l5{sW>Hr^iAIww;AbK<=*D&Hu|aO${JGOi;9O7ghJFJ zAVG(27F`rUt2vKcCOubokEH+bxB&_!9jy0BxS4RSW>T|nq}kGx|t{r?M|~UH`nTUAesR=hbrA?NhGlm z`=Z6U7qk!-=7p9MuT6mPF0cdzKD7C+pp zZ$luN+A0J89XFjQqaBU*C>xG0=>5_KZrnL9__Dox5YiZ9QLUqi8oNHTHu(w~)IL|b zMs(cAKM-l?YxbBude1?on8vS}J&fG^{=&Pc+-fkI5EAWrtEq-&>hL-(AYYQOL*SLb zl*0<5vDv1;wpe?z4nntr!Mp^*cDlv3zf&Fo+a3|rEj@0oHrkT7{TXsIi6%8x91gMw zsv5iaJ;rDe=-}OR7R)@eKLxr)7{-TU4)#(GkcRKXkYA9M-AIWW7OgQ6@K7Dy$veGS9izAl~o`_3G zSEgrSk=v1~hNBYS@&4a{tiP@H-z&S5)wkdNw->X~e=PO?SmG07C&YmnkOO62 znerQ()UBvadoLT5ek>*Wh4|68)D*rsViv`w3NkXCTC`HOTmyQNGl)r`(DWZxPK_xAvi||fdoo$7=tKf zLpi4p5EX$rBAXQ+j`<1;l(mc;=@VpL2W>5|>u4=tmdmURY z1x%0&FyIf&xriwU}%(PZNo!>zOZV)6#LHM@p;qrpb+M|~aWcxK;tX&8)! z-JJ6h&%fafUNqCMp>M`8_Kwg@sDNb9|+`coA8FJg)8y_iuWJGcr{Ys zpg@4%%Ef6hh7NFm;nNKSc?Chgup}cIR`pyY!PuDAQddCE2gEflHngW%l|5>~SKWV$ zBl365YuDsGEau64J-WSedA)9BS8|&eJJ+Xg)P(ZB9i`u8UafaIyiHyXd}a9n{`$F@ zSPSY>l|w?1k7R%-i9w(mA$EJ~rfsQ>t*u!kBZdxVz~762v9w(R4eG*hA4uP&`kQWN zOwzGga`#W~ng_9`(xAI1cZ7$LWuF&g*KeEKk!C|rtS!CXtDqb1!F8SAS9?D?-er5E zpP$+Bc=7kpaTBf$Fq~?7pCNq6+}y|`vTvXCFrv3jB;W2J-+`Vao=M8x6nm?`iDcP| z0t?kcUkj|mkbwArmE^!&t7@}TXBmD6>x2)}y37EKpG{uWtdyQ4L^Em-=>>B|GyC zTAznqppu<)^f1j5+x%X3w?@LbEl1%$-Q6ZF(UHL)RPAmTQ6y)xF@F}U{b&$?=oNge zNJ&DUxAcDkWbEHWRCS3rlS=7Q;+R?2Uia;-*w4UTke9fD@p43D4v>J2Sg$q*}YoP zaqi@#;XpH40Xc@VaN)&=K`BPpaAKuhcOb+w3=a_v^=o_U3+_ZMqisWCCyvOfqv3A0 zXAD)F(`{wcOBX_)To?HJob-eZJ>&4~)>NI{6!I}gr3a=ZHkS-!aXh$gt*J48-Q@Xr z3DP-Nq(|9O#TLhzd^t3l;+VhLj}IDxnbul?Gu|05^n~xZ8DwYzf>Y%~xpHxV)5&~& z7H6SBb7A3fUTH#c4r7b|!;WX~35T;{Xt-``Ta5LJ0#s%X<9FspQCT#}Mm`3s6TicJ zfmI}y9e35H-io;;!U7GVG!?u57G(=481v{)!Vm624L5`0i zN`L*t9C72;D}E4VN)HD_J>;Z;bdQ6paPJ+Yc6T_W_fXIAYPxs}*n+umTfX#hQ)atWsNt%KvhC)$QkRyGH`xd**432VDb_u zYrz6W6y{QV6E0D9|AH~0J8-qAt3rli`P>ResEKP!W@Gr_rqH$nqgV%?&TYm=Z&*w9{#kox`@_7^iD%9Wt8e$A>;CM?F1~K$HAN?=#9LJ9ZZiP<$V1_f!E>&3tXEU$Mz+_CbAiB}9mZf=Ri@-Hv>m9L zy!rB-+|)?*$4Aw`s~=>lt?tYanJr}lPxOv+o|W0O7j!MaC+}4Vd@AheeVeu1@iM#2 zdAV};lc;I0iwj1Ht`9Il<9s2$z!jv>^DQ#nLl)1|2P>T62naHfWevPFokK1#y+iJu zIh{sU7A%LL%Dy4q6g*3eG41C9RO1Sxyg_FTi*FIn;IDMWj@*T~N01^LRpoiq$J^$! zbP4@Ydr*km-xSOhQb|X2_PD2jfkhJC#mgBP7F=TnJ8ElabnI4vNgJ6J$ZQL%GM;lg zFlbgGjVE#&4MA&@F_4A`9h=iw%+$O*j0-QrhbR;OP+Y5)!I$ic+PPcd;_uY;I1clA zV+I{#1@yz#L3a;cO=gePTuj0hQz^d0*sETZj6O8cL6vuWa>JHW<$#I83!;2+e-i#9_-lOkSpmc$aw-G0h3QANr^#+nhy73KyvW8Iif}e4<#Vb~N zv7E!{htG??IbDu_PMpIsS1_me(5q-4a~`!7W@IcWo-w~)5nl(*XO|PIl^P^#0ZPNu zom5EG-u&Aav1}GxuM;v@2$U+3c2PyAXsr)QbNCWHf%cHy4H)S_x~pnOVEnF?CSvk+ zmg|o%ge!UK&r6Pu@O7UId*_t8Jme=`BJ6ug^;%bOEMwbE_)h34xVRargAUA{nyX@5us z+h7$v=t$l9vmZglJM=uKBx)Q@JLpw`5z%u`NCcl)=jcXW5Z1+Xlzpl)Th+h6%zg$9 z@!$U4=j|`thHZgbJMoR#*1oHBw*P&N^6%A2qLP)&oGh}p_0o(SC%TQoHK-somW`1w zJ~TpxJ}Mf0D#48b#su|=`mA$*_72=mxK6jI{_}Y>Vb&U}Lyh>3fX5W~5yw>PQ%8eO zmG=jjYfW^zgb)N4qBfJG6?)Q+ z6(h0zix*g}A>Jvp7fRo(OL`>m#!CfGN&!a6GRwsJ61M-9K;f|$i)PUHX06Gx@`yFI zMbzO6tiOB{^#(<1+SzG+qOuqVtCY%{Vnb8}^_O7|$eh49~z_zJD8dz(G6 z+IL}@nBI^(YrRfo(}Ogi5Q?zRj$c*Xb-`7|K`6h z{0x=@LDXhd+D)1p_ApcIGd~TY2k?<2wz>OUH5b{f6LM{@T3eiJbL^o7_KT0J$e6rDEXn%7Bm_0X-OZPFZzd};ao`OK!2^3G>qRK`Uj2O4J}kE#^n z=?s2%*>o~_dZvb2Bae-w2qLe#+ z&m4|xs2a~8umik-`YCct)<#QkG3i{gH~>}f+~r{{$mQ?38nze?g2q5Toe9zt-G)sc zEZ2Gu9{mwtu?-=%e#eoeAK_VitiMMbnrg+lQGe}-H^Sc`Dl?^-XOfh~L|z=Lf(_?e zscR+)&v92M78d~hj2_r;(EzD8sp>dc2bd$2LfnhJf;9a0Y&QOUMvXho$>%1iKv9>l zg4RG7PZ%lATPOF*SE@R2tn;s&-M;<;+0J){SbyW_zsAS?8{7Q1%I2S(oszZ1|A3-9 zmB!@1>v(SN5n?^YU*PaJfg$80@ZdYSgdv25g-Xckfpxk|#0q=IhCykP2|Cw0nxZJt zlxW_*U)zIAy^&aKZ8aU-sgMZ#Bz8N8o0n@(8C_nN6Z;=m%~t^Xb{c%pdyt&;GkoP4 z^zps>13d|TX5)f(EMXSV_A7f?xC7V%?+7kqZSAB$(5Jv_iyKDa$z$%Rdin!)kr_L; zd4)%iNvRsn;w08+Dv}!2yTYg2chCfvn9w7MChwqAYU`}_7FianU^oL%!Ky(!`Qtn? zwNcslv7mFTokC#TUKzC#WPix|CQ(y?J@s1)UivqhIYhv`YQ+WW{Yjgwjm=l;6O z9_DePz%u7YO?R{2EeEMlAITXs3ATtSSzAWOn_k-5_L1UZ&D`>AnJYOp1`0uEm8WZ) zaWNi@nP$y0VFq}!n`SxIYY`0Edqno%hx(2T`fTXk*QdP9HEzzEHgyf$6q4F06naG% z!s>u?V~ZJK8q-&)c^{<)97wy7lpj%(Wj4R5P@aT{;FoVj60>0~*e8dsm-v_i;F5VhGdy zB$+-D7~enwy@c7`{CFNwijO7B5p@Af0DMSj4L`*-DPE}LBt!B{>}Xp!CA1C2c9t4F z2nl<;zK7~OFmD^NNB01vLdDcIMGvPFZC^R*wt{v28ddCZ*e{Il=Jm8KOOy48jR^k? zPeH%(HIB9KM}e?Po?jI*#gntYCCDdKU6$!zscwryR8l?_rKA0!iB*7q5}v}Egu@H4 z#v#A(1CLi>qErc`FY(tAx-f92f#@4&xYFQNL;yoJO}O-JA9APxs=4aB!Q?Kpl3OSj zqQ0fE9e2h1zg3`w?j!1P-~3nVw`PU(f6ShLRGt6idzCdD=9J+-6VS(Mg%F|pcX082 z4UpDRff5R2!JB`H`WA=@->dHYn-bWA5A3_C`-=}|WgmmX2kpbZ7JY4N5cmB5h- z^YnS~kTc`1x?h>gqHN%8rW%Q}6_?cF?CapGb>Xdfm8j4($!z!QC5;UQX@Pbd^Q0TY z)`&9*-=f)gMEMhd2nLb*1yBJj+>}^&j7G>bats-1#UxZ_5A_bD?#d4H@scLm$1Fy3 zH?zi*4{tzC*(!yhIt-Rw>eKVyEHs0P>fC4vei<*@rf%SA>S$D)@v0T&c>?YEj1eUu zD^a)r@`h@;B|=MmIhyRp79u@z9Ky+N^;3H;N9h;~DUr813q}PX_EdYaJ6V-0?rDMiQp90)MSS(nWE{F9n$mRw21MYFz|OVHY;;vej|8Xqbu;G%RG z>fOX$oO; zuFJOZEoU20ck8T+|7!3gT&R9?0I|s#qVMuW9V73 zP2@QayQmp`X4Ld^A#V-xQSXnR%yp?BF#jubcK8L_J%f$~|CTNuU84r%EV}N_k%bG6 zla9V(kIJ)p4;!KLRyd_nu&4b_RFaFP{CLH#v(C6Grw3kYR=ax?H>3_IqJEo;S?#n_ zC!D77NKH~U=B)>R`&0?SoYrY@A!KOq(vqAn`hs7M0jDJuIF6D8$wWbq?wpw!x3!!A zQ@CGGMNdk=#mUT9T@;715(yzHBsKx8Lri6Uk{*0~P65=|Vp2srrt{rhyZ_cJd7Ph- zZhnhJewP&d#MaYYc82W%@aAZhgA^p~tFxN-APJ&d%q@Yrx5!UIO**42{!uQ0wRMFC zUOwVGrbTYPhN9Sdst~ajds|Q(L|lEWz?S~I(9m(Z5a_C3W_{=RKA*3lo2#*V4siOO zmjz$QZPVenhjrp4nfXB_}aWJL3wLGfAf7Mh^o9PucL zuIEQ6E(^e18FpF^iW8m{bxWz3%DE>`wORIk9h1f24iT7obFnKS{pLAMzj6e)vY>P? zuYttaH|9rPjiq7RpVK%v{N<)bvbB3xnH=j*wDu~rpB%{5YH1DnsF(H~3hKv}pK*3q zF1w5@(W4i^2zD2_brbEuRuT?)49(pe~)HeoQBVVj4k*?}Sq{E9}s0C6Ie_58_9MHfr$sKv!^Guv& zQEB_6`&UeqVW~M){LS_j{Z~!ue}9ho|DhBU<+c9Oq;l7*)jLZ`HKgsjL{JD*SR?BY z6Po@)_JfS&dS(?1x)?TAHYOwa%KuX!6Ug%n{F)!;!U~80W#)`Knc04nHOB4o`Tp?% zy$!G9X;^d8H&7HD7i<-DUaB~o!C+YCVFlKV@B|{zMUnX3z3`KN>rPrQb-;N2KrY?F z>}s#TqH82TZ|8AjSariL6MTbleY$$RQJ$ZTFpJoad}u;7n6Jc*4v~*7j*sZ_sr7V) zC%c#^L6DsnQdv#2=Ig10i+)F4>@+yj9QrEjM^O6fm0n zLdY`(s>$G9&6|Ct#BoniEV%;(;)v^-K7gQ&Q^SkCwv7O$3I@f`V5vy;n_n&ig$)uE zU3=Ke5DqEdlj#C?Okb7gk+rqjF1W&IVP2dtlhH@xMfAv}2wO?qduh*;0}V_FRk+(g z0}L6AAANdW#D4p)Bp7;q{f0w65(asG25)I#r7ma*k)fc~;~2=BK%;grqW0!Lju=?^ zGZ0SHE6NqAT$_|sS^N%T4mWCaY^gW-5KBf4?@cPG_xNvAKM`|~Eaf*CZh`-AxAgx& z!G?c>#sB2@RsN|(T?_dJT!VE&`W5WD0o3{IQtCet)W0WHF>DhT3@%&E0!9wV<`U#1 zFqp+xi6s|E#92!}CDK}_-o{(WjRcR z_`DxQ`+(U(|5=FXuM3Md2iI!_R!dN-Fb#1}4};VYSYNAf-gRToEa^pwP77l}p))-m ztP7&mJn84eMxk@wHF$Q#rYm(-%U>a5KJOt@@)Q?<9JBLOugDJFtJn7uGVP$G=3NS% z>O)wg1OK6;c%zP8ZGqmM%z0zvDRk_q#I-4VQ{-puvCw!f{?Pwgai*GxC{vUa$wH*# zP-*YIs!BtCoYE+c(pSk*ldk#I{gM4mM9uD>$MYsRir?>eik z#y~mny^&?bBS7uluQ#5iDAn(}i!3Z|*B417zG=t+0f~zoqAW3xX2@FwULKpe#IGbM zp=5zIVO#A{vKlK5P*&-V=k(kDPqG-tAD^XW2f zKNKu{4zPmA^AE=}#3+BwQj#fwytKG9pHPZ1XJVJD9~DwaP;M+MrYRPuImj!qgzxBv z#aXMh*6qTP5N_O*@nE{Z>>C#@o)k3dtV$YXb~+Mk*JMQ_Y2|Nhw@fY?XQ^Lr=^xQG z0$u4wTg&0X#AZT28lb6|&pm%{yHAjOnolB#D`^(LL+4m`Zh`UD60RlZ&SD#7aloot zNuOc4^7`>`7Ql;@Mi`zyO<*CzOg) zN2Cpv=oXC;s)b3w@iS~!`L4&iwPm5!z?0KE0I#C$G@eKPNsl@0#%m9P3C-XUYSKzI z=cK;)Q1rEdw{%k~NXA!dLsa&5F*b+*=j1j7&iA}vr*~*9O7E&YfA;DNK9i58R^rXsbAC zK+tKRs?vkF_W-5`2lDU-BmJEWf)nf?;iv1|D9yI&Kp)y4J`if3>M)9hlVFGEV@&!2 z%pMWYvW8E2$&bF1rP5Z*JIH-yXYd8jTm`q+nXvVP{Nq07cK_g9ihN}ad}2%RnUfGX zAK73jS3W}Fyao1Rn8uMZWpcx>YMXLWez|bF`Z%pM()#oqHxj$^cb0}IIeKJKUYEAI zsJz{jDfOF&pnR?3KB{|P%390aROHV;9x8+!lSkm3FOmd)o$qQ{f_RU5F;h=_xRSft zs_edK)6r;l@N@)`A|>2nAgDfnqVs&wjTr(MxJG>dNJBj{k`O*oTx-eDiGqvw*J8RO zkk}zaPZ%-?MT#lTG&|#muqveFcOAFmGwdS8G9C48?qx(LgX{YXHv79)UP9nm2tEPd zwql!r5{r59>mS~WKb8p?iaXS|w=@kjv%4aZN6youB0K`3g+a99MuP+P6)?E3SsOHW zv#?rRXp`CTlNB4x&~Ud}?w;0R?*G&WZb5$$VFo>`kPx+#4Z&g%__*2M1I*wO4gO%5 zP>8)@uOHope*&#b+g6}QM@VHw_rzq1>tUyv+7Tn1IX0;XC@P>0WNa?%hD5$d}OR*0p= zvMy?Ze%G=*tF*f>5BwEOe&evWS3N7CdK?1PYj_36(0X~YzE$(Z3U-L(kFa7PB51PF zzw>9Gb&ZMuVe$r2Gly%6m~Mo4E~~F7fXlnhHMM^LT+SPH>P7N^#Nn4>!}a2(S5>J? zewP5;cOx8g&33-)cy%6a2K<05xWkn-#WtZw&9dUJ&e)tu7f_6R@VO_|8>r>2-m!?| z=!^^&j3D;5RGVZFt=%@_BcV?9`{|H5I+H*`5(YH>`Ar%Mgr;P(ivjO-kvW=nIbkeV zfCm0Maip9};T-D|?dvvTtBSw3|NKSJhV!vldVWJKsBfsn`Ckj@?+NziMh1@Gmw%45 z|J%m2FU&w(|pdf;tys~|H=iMNfNKSi1auHN{#OO}~Ka&`&f}w#SzQk2X zY2N`q$@h@U7?uV1s4q`4IJWMci)^mwssSErHGZLDxmh08CW=r5Utl|fuOJ~ndI^iF zShxg8Dzs(PtRoWq!3EQ*vQ}GSn^c$J9RFh=E_k;*ew>94AEhqu)>NEw=CF1XxS@Re z`{$}?HWkft4u!vOpml?VLJ*OGy_2Ns!?TI0=iCy1P(Y-4nK_~CSVhATWVKCS4)c}1T@rB4o2sE6k%H=S} zTjMirN{OeI1suq&#v&M1rOj(hAJ|A+cK=M5AL_MR?27az zm%Nx5viEvLlj*5e2@#VQ-2PeP0+65z^+*mlP(`T4fcfD_o)BXUn$bJ=>Zf*KG+qL8 zI>+KbX<0&Jp~vPxX{ka~5G5}zWTg-PCJbVICtn2wGf^kKSB?$$FB#`29G}(GI$?fuZRBf{b$b8KO3@pPadP4G> zyE6es(Xqum$9lW;w^xv%1P3L%en=t}8T3ul&je^Jt%G5gIWZmgp*$M};w`5iy*vn6 zvv1_+a6FXRJA4|?b$idVH%d8^Ms(K+OxEr3Ogo|758ocGd!p4=P+Q3f*KKF+1{UX` zxipo(E2(>>1DNKOc)_QVwas9R;(O2oezpy2w|Y=c1{y(`SWd)F9EcVQa9pb8Xcp(b zsR2<(!IjqMVn(8?9znjneU@T_OdNz5A7#VRB8iy17U*^B{}OF(dJ$Hb%Dbog733%r ziGv{7h*lr6?40oPiubiGTOF}8;V>4#|wI|xN;ySR}) zk_K27L&y6TgN}YSTYpVs8Bx&2gE@nxaP;BwMFh@Ld>c>SW7v;^A8Fb-7-46}Vu=1c zY@>N_^srSM8LLQhq$>Go|6&7@B8Wp+7V4zYb<_H(l##L!8i!Ewmas~70t zf3Chn^iN8@-K_XgR3mT&63YJMg^{>SqIfRyyA|e1l>9>Q@|4iZiBU=AS z;i*A*DlW8sb&cDbSkuB20)nX#h8vRjBH~*Hg@nZcfc1cfB=3`Aq>KloLcj-7idU*9 zm!W{3X%{wCkwY+qH9A!1mL zSaAS*Ti$GJUxAj2a$kW0+8APs@?{*AW1)@Xg)4a~M&|dR$!SBtk(p-Y9Aj4X4NxT7 zX+wsEW7&Zae}n2C31=pevTE6!8)JPyvYBU+G#YrHIuB9z*Z`#yql2@r^C&IVzC+aH z(XHF8M(NGVOG6eN_%&tZS>YPKMiuNeW~_&mFI~b`Bxd#838S7T0-C5zXG@-@`vIm6 z`1L@ZO1yNXXXrgEm}|VMN&RHS;5@5r?@RdPsaw{~W$ zHP+m7c-~rmt(KgJeI$mA>djz5Y6J6T6b>Exh-QFU!@ z#R8P(|I^u5KvlJMZA-UwH%fPxDBazSbT`u7-QC^Y-Hmj&fOH8WCGj8MtFK=4z26=G z9^;IC7=!gZYpuP{in-=|rVuigP*Q(klx_DJe|429<;MfM9O}1~D<)xmWq>u3t})2W z3B#7+Tzi`MjS7e`?2Bnt@q$v#8jI}%e`>h8FO>DAMH&qjeSUD_SqjVV(+m`p7;uV$ z)y(HkikS_NWChUa!-5yPX-*~2FyeSLEbYBX7BDPAl84IKnAD@VS{5EK>2u5#SbPLZ zbk6FF>l+u5s*00eY)}X_C~Oq!!?YNYJBG8oh*~JW{bW(nM~{xI1q?Ui7~erBx1jT` zzsx}H2DpXWabaSO6Q@L$4|`J^*5?cPG;!>v$^PPoZxgdl*XBdth7ns+?2w#nbNY}P zx@i@^O5p6oY}IUV1v0N$9mSlP;9SaC<()lv+t4LlZ{jUf^J03`vDlOiJJFCkSd))< zyQE4tQ-|KxTgvzyi@fUwJu}GXH=`hLs;XeHGd~8ejw(_RXxD)eW6Dz!1{txn9>Wq> zZqep52GsUn@GOGRxKl29hkCUr5!LDdR8&S<0%?sa7Wr)}S$2+&>HYXL9XS}NUJ%8- z9=sLU-!NlFbVzFoZfcyBaMGZ*J9nL%C^n?zV&N=q=9G)t-hoTVjgD1eHe1qmvK{6I z2lh%87M&44nC^jG;h`^-Wv1MM!m&Q!`e)LREP#Xl9A; zAa^Ps?g87NfwiOw2GffgUw^B1$WpJlY3&n(V4QR0U~S=*3Am#sC!iGyCv=n)+UuW)?`_Kl;_ zyHjgXRqG?&f-tXDA04zWlYOn1aS8&9o)Dxnvceoaq)qXqh>;^LxOs8Kj2LNpcQk#J zDM!x;flL4>vccuDa~Q1pJanTJN4_>!nFnXiKx9jv9{dEQDwsfoA$&NyYU3! zNp}EVM&x5@B+~YfP^?oXNAy#cJwoT$BFDm*w+M!MmHn&WT4PFq2reIM z5{jG$k;m(D<7P7^uSI<-Hr=qa%s(-=u74Omuk&nNsbsjeb;ae)te*OCcmtk4OvpM) z)u>-Fz6DxXy5hJWJ-Q9PJ~)r*io9<2iTV!A$8vkwQ=fPQDerk-w2D6X`j{3yAI3qVBA5 zk-EUIUy6v1A{g!#?0)J)L9eIOXGEWj4N@lexy+1DGCnRg@dfY*J}$(Yt&B*F*(zR! zJvChe*Q!2Wui4EQ_?(LHy<*8|;=#b*&|gvTe{`RLn3y${ zZdp*>;k*-L_KeW)HaB)QckCTYF$v?jU57P`7a45lNWn{wUBk4PubC0`bcXWvU0B{} z%3uSnw_#7W4O6F#h{Cz2t$WG@gc7g7jA2C^4JP>b@c|Ntz38^uT)hwSGCnEj;Dv(- zmO6h$Z|P{ou~(+8`~_<789ORnaQ({!4!Dz48O!cmOlB)33@ zt>CiK4UQwP$Sx}~u&nI18IJnbxaTz6LVDUL7=_t*sr?DD>7}n=({kBRllq(159n*$ zF#5(O=KHcvTWn`6{Cx7bM^Ws{w>u}OzA%&@`uPX}bsigJcP*vKN3ayawaI+Z6&EQ| z^U|2mwzrJKc7B!AOpg}V7+an&h}|1b!x%kCDBJ`CN(rHIoY4^E-_zKnk%}#DXD-2( zr6ylJRkwmiIGL8!O-w^^$H;0n-;fwJW}u_@g@n-sL+K&40FD~RyvlxLbsZ*7F*ri0 zxg?*GN>*j4c4d?~!~WED*Gg2KfK|7nh^F2XQE82od?dF}s(vU9<(vw^=5v@Xswk z<Zf}auN_~sd>S%ouuOxBH?dL{AgdImSp&`Q?HGD?o5Qcn-=JcPPP&7f_vM2 z_@>bObNsKwdLK{;7(x9#zr3H14zft%LNIHe6IKG24YRHxk$kV+U;Y`q@{`<9GVVbSRB6WTj%ZAR=yXvn90QhrVBMK}`tCu&gUNgG#m zZ#CRBQA5fHU30wW9{Z~z@Hzo*7YJ^cw)GQE!4%4h?xBL06NLp+X7{44vzVpc#)>@7 ziFjRi+7|+c6(1h?F36mGi*}#gkl~xP-pfzSNadsqrxQ!zqcVJ%B5z~LZ_fx$9;Rqa z=x2$&nq*VAZY8wD4>RN#v=pK3y?B=_y;TBxtbhq; z$AwOPg|7fN7b+9>hWk}rK>qAC-veIqb8jw!#4JbyKUXj@=e-M)4ha>|;3VD>zgh%$ zCt5jEvC2JlDhh=VNx53h3_j?3!i+Z(tlN-rxY>^nu$FODwH{LmUyVd`m=e6tRc26yA^+)~S z!}s|4n0!OT{LMCtcm6&2^Ww`uq-BytWMV|*NT&01HYRSW zi;AR6X{-oyI=wjFG@ltwvtvKaqr3)R>WP@pbcgMTn0l?gU$LQN{HB9%{w%oMG7 z^UVbHolx3Dh@vfbF@<18+aYOx*Fe}su12*l)#(Oh!w)V{EE==reZIrPaH0eC2^ur6hbT>vRnRQ zVycJqH5qo`P*Eid&=7FtsNRA;%aVzsHuYU4kb66*dy5i~4Z>%?a3wqbbJogX5Hi{< zOYeTM9Aogi&wzzCOmM8W8`3=_hy1CArH%?BPJmsRpwU zM@1j}iP-g%0)5~IL!j5DKqVt7p5E`;?CkmUv9!J#fr(E_?RMJj&N))XF`Ia5hjXn( zr|TkgjPAVBu0b+GK_c23m!fZaCay?W!<-^Uhho=Qnvf1M+3YD?cjcap1>LAEjz84P;H4F86BE4=*bt%rnv_TgDD; z{|*UOw0UUCHg`JM)mv(Iz(}JGeuGeq2CFrfu}!Z{ISVk~Y@2+RqlBitZ0DAcfX&15SAON{z@=w?Yq`N(CO|^cl&JPT+Mev3xNrLTCH??*|XQu7O1Vq zaLVDD>Xv4H@~SaxZCm34Z=Lte2cIY)R$T7BPw}3p8enhZBjI#Th4#%q z%~gIqzA$%&*th|bfLP!PT3jcp?I=+!^(qxYIB_o~#LjkISeE`!aHbcBCIl2_?)mj} z(gi~eCfr2anB!A=ZR#74!X=k`99@$VM=PtZl%}-dZV&^PGOZF)Sf5ef{)w|_*BaLjHc$Lxd5IpkxO`QdCtDlvj`7} z3D;+tH&XK6kAB0)^R?cu<=2#Mdf@XsLc9$FsXnd@HF9fhZQs0>m8xqPVxSk!Q(a*LBAIw?bOU2fP-mBfnEk&E)=eh6TLRZmo7jH^He5IqXG z5?inYo05|7bOC|-S-aLVxtVUTqMF-LD!3iT>D!{6>1Fj;ASfg*?127r+MzdR9a|1wgQ#r?-^dEl`D`*05&n=Eh~#+w@^HY+=j zUd9!2h#%Q5sFmKq6nD0q*+Jm!#kGbjVUTEc5Pm1T{;P(Poa!iVdI{%o_N$e3_T4qx z<&2K@`)AVq!QiOVSk;O9q#{c6C4^y4a3pB*u?kcS9}nDXhPX;L9a(xD`_SQP2phMT z3|8O0CsnUCGkv#i=tpQfa+dmmrRSqv^;hvY!nOl7P+H-hTl*S=kb>5oX#K{``6jjP z?kHzHaR@cZ5JHb#{kI_lmcRp7xy?IH^~&#@O7vq)@IrAyFi8kWHV?@Ubz(Xy7O{cQ zd6oz17&M&v)@`P@HG5VdeYcnu4OlQ`)tU5cG-6;u+R^z68@uUd;+JKN88We0Tq0e1 zMQO4_sIS%|&c|=onosYGNUoH?9b9JPacJ>G`V_$FN^v(5V}`aXQDf7NhMyn(sTK%IKH28EHe_zX)h`)fmaaPYx#b-{!w%JgwX9`0SjzwxBJ?(EkpV^<24M z!oNxP3qjA3b$y2R+4U+9E1Q!NW`48eMdfD-;v0I`z1hRZEbYy*>xzB*zC7&r)Q1m} z1deen%a?@sUKFAieeZeeA1jZ@qi-_@U%wc6W(+SPXY_vG3_jSxmB%DO9?a(gk3U#( zZerkIBGC_cQE>T$Y!ehg6lr9SJtzvYnLp=3Ru-SL6!s%AARTnrk##D_Y#MFiDj>LCU}EDB zrKds}Upz->YHlNg_8RZ(Bq|~_V=|1Zauo!#Jy1V!--@9T#Udq^gbvfdj$NHyfD~-c zPLcu^Hfr7&Ydm)wexef$ON=QyG0!8@i`}T>i94mxq`^@%;GIteoE-eCcmA)}{jURq z?~WL9$CBS1kf-76W9u}A6UdUi6_%*=$u~&@`>~K;03pMIKf)a=$D28%toH5YT!TKu z@e@q;LVU^!b;zgWT?W0j-Cg6fJ>l9Ndw=@ojXO}`<|09PW-N(reiV<2zb(1^RANA$ zHX$6GzH#vsRlb!{y2g~1Ru70j+f@o|Qytesl-hHLlsSXFWeeLR?M~Bx`rYUnofiAX zVLG)VuK5&lbNZJintXJ6^JYq=rw#VLkMXB$y!Ph@D~p@$)LUdpkPgS5JnPbMocd(0 z+s)k-?5`j}k5x_6*K3nsTe5W*bJi<-R;4~+(Fia2IBYPYcA~ zXAJ8a*Fax(2T1$OOkL>s%qwItdcvhHfW>O;7j+Bs_u~dfl1=%yfLw}L zFwdTG{ywb#kZbujC!S@BY7STmC=btJ#Tk-zyt9}|%0ysMf#J&Pjj5SLr)S;{2^0kx zQ`&n%C7~Et83gh_`ka<;yJ#K4n5&B^W!&RFJb#zrMW9!ir_#Ntez|CPYU%Mc)$Mw# zLdyff3ha$ATfj0=JaK9t?pmpEV~7-SDbZ*_#@Qqn6lST2@<2ZV%h?S=J9j+m6~w1J zQ22WAN-ke(*FI9tRwsf@!u3bt-gzP$*oWMF(@P{DR-8p0g!r)RVY=u^yLWAhLnS+I z#9AaG1iC1(=kYowu4_opm+1!d>f;y&X_18qDO#7gF+N6eQH-%Jg$& zWiE(VTg>(#UdoSx_9%;RDRQh7E+uC%h6cPya@*z(Naa*ofoCL~_@*1ihWGP=q)i(rrqk==%e{udWrhd}q3&k-B!xS2f z1T=<4%LE%q2yP3K1cOPvVt57lEdR&eR0btxGAJqu5$9|?3-aycX4#75Vtw{V;I@Se zBimlPfFdSh{wg@U&;{831H>?FTpxLJ!zBFFn7uK3{M4RaSbapBD?32g$q2FX09ko1)g0VC;!D(PV}X5}a)FICGA-H$61E zHI-1f`bZ&S>)W-@jGu)x|vJLySt0;g;#A z(vqp7%?7_u^vo0#T>KiqkQ4* z#Nkyyp@wpaO?NzZG9j9jrz$Xed>Ler=&n(hWrOX$Hzt{z0SM^a8kkjDlPlF#=HFLu zr0wacEh+g(j;xj&pOGmPOyKz!>j1yvXgT2Q-_D>Oz{gzyHrxR3?T&oh-I~hLryddx-MPE3( z3GzEn%W^zFH$H;|riGJyGksv_B*k&6U9Mj%x}h&p)G**M||7cB6@09MWq8ToBETXMG$aWYX>eQdiULP2bDW zRvs-7FDSx2WIWbSil+Og=v9UvyACtkxnsQ-AQ6#adb#Nxw?fR2EYmIlMA-n<4L|Xg89k3J;Ukf;@s+ z-C^vC5+a(%q=}jBF6uH1d34zVvw;PJ(4Z|ws1v7m>_^Ia-97)F1Cn{u{0S|Ff$c8} zEt78*HDt}1xU|*eX^gEb<*=mb5@}Nt`0*qW_*1#O?2=Qt&|5oIlV=Yp!zWFwM&#&X z-$X=*$CSbiJ%~x!1Tb%di4q)D{<{u^!ZXd&+z^80xQG6hMWRYxyc zkGgR*R)Ub#1)6ecA4cN1_7}~r3e(a}U*QylPGZXzI2eNV*z|eXsnT!>WJ?=G_#0L4 z4pJf#iL#iBpZZ`PQ4$Hd<4;QQP#4CZQ^ALg67(6+^H#xb7y2IwWZu7IChB#9$^rTe zeS?I`nBT#DGqDlEQ?5`ILOQn*w82m=oxVZQ51h^gTPq{5#hA^{%pLE>cZACTA?=Vy z$~fb6$0Z9Pd<0&8S(Q^H0$v};rgktzZEqLiWdSz}D8 zCLJeYf)=chAQzTF0fvTJYuIl#6Jf1hjeTH&e|Y8*+bEF*8pDeopXO9^+NQm;dv%E2 z$u)*+hntF&`ce+294>1erogQ0E|z?w1EYMAZJP(m1y{;R2e<+nkt1Tn*8?l5sL6-X z8(SnRafq38WflrvR9UZ9o(Kcn8prVxDcwao-;b6lC3i(icE5w3Yd1!QC54_DDsQQ& z<`6fRrM*0@KLABwSqW7qNY-et(}nZ`+`7Z$RcV@R>^8@S6hqxDz!Q7Y8A^SeTwDarBb8(7-t3mV(l+R44s`QHD3?SA_d&E)`D zH{30%t*mQ|gyG`q7leJdH6eLQxDj9wBawp4V_6m&B$TIT_2w7NiaoO4WIc9|)%wI2 zU8))0<~`=T$)2`#(1j$a?6S_+IvHsK#H}}tr@LG}d^xqGeU@vj)vxkCE!#j-5W^M+ z6B7wdpX!6^GqJ|8v!FyO+fv8{I7|jb_Brs%F>ASg@YiwlffC`Vp$PSC=Qs_Rx5uYn zobCLzsSH))q#0XXR9C6y?HJQ!R`d6iUifFnMVY{4HqdOQoE9w1n7pR$0^y zOj3A;lUuNQFtry}e7*vfyaO*G*9LCE zj%N}>u^wuz&eD_!E93I&i{tRp&0Xld=JJ3<2@B?1EPU2Ol-MphwVni6tkmE@q zF&H`>iL%=W!W)jxY6asNrXEc<*}3G52i|G@+$6LiiVY%*F#(ePL*!}LE}y&i33x{O zDO;Ri6rw~rNgKtxQ7jQ`6INGX8wm$JajYc}Z3s4eG;b8CkLj{<&Z#5G7eFPYj^B!g=i@}j27*5pT1eb#VX6{AbdvQ<;9hAgaIqykXKm>yGN*T;o_DRd_t(L9=-@e zs*>x%ywBb16!R8&yvywx1O#R(@Pc%z{ANZ9@|cgN-xwWqJFI%p(&*^Xr=WZ2#SRz^ z?S>}BLTR>icU{!2UDf*nW-21>4foky)2U<*28hqpHMvtY`^XOvaXcMq3<>diU>XG) z>Aqx$ympniXN|tY|N9sc^Ncg;n;Z2VV2oz}eT@r4re zy81bjS%DR1US$4WKlDg6bXi*IefMO%>8O{;B-6ZWqDtN{fba|?Qe%W7o?ewy#?RxA zqp3};9cFl#-a3ztM+Ss5mkjaN#8(l6 zT{vuFWlwEGIQS@(nIwBlQ!70?WinuvYr$|ijZ~jALTD3Awjr+w5n_UCoHWm13x(J> zvC0tzBLg#I>+3*Ux(zi7Wdia~Mc4^S1UT2TM|wNeSJ%5MyO5FFT8Y19)u*Wh6;q^w zyOvjW9Lf&<(h+OG4kvIabYfnfmt4&1MM6>uZQ>z>dp&QO^g|cq$$LDiz?( zk-EI@;r;+@^=v>8Yng>%VJzEZ3)7xzhMEa7Nh$pzd)`;R&6<~vvulF5)Shb}Pc!su z`7PP)YZuYgw*+^{S+C5cQVr~O{Crocq_aw#qXHL_9trYFINBlk65!QVxx-SUkoeZ$ zfw%A4d7mi{W|c>NR4ABQ_U%@7-ET1~+S`-+2o_zbd72&~wsFlHo~oJqirs`&5=w=( z61|@`If0 zwG%HrrAui2IgAd?u`@D|iyx6CDqXt#uo_Rf+OETr65}n%;9*p}6+DnxF4ZJpT%3+_ zjIsn4)bhDbPS!ocZ+A}!h+381&wb1KMpwz=&3s%iLX52PX|41Ty;U|kC_(O(=`J80 zp&S-$l+Oht*Y1I~uqnaK9t>(@h6k(CrGS;ofk_y7=)ozf#JQJJ^^Nun$iLw3%&XC* z(7zW%itg-P!aDK7u)>Ac`4B+Hrxh+Vf0SG`dTMUKDfgbti^^zlRAf^uzCX7t>Ek&{ z#szZ*Q+g&+0aw^ogH?h)Ci&|k?Y>&}9RIIW_%-~5U(x^mS_#%eUU30d8^ch4v_Jm- zTK(r(>3=LX4rQmM5gsJfAaj94!FoA$^fRez!4NAQ$rWg1$&>{qwX%A#$e?1t&rn^T zt%DfaNhev~?S@8d^0A$WK%u)92S?Rf~&Pc)Andr$0+%Mp0E#({d6&Mdvm~JM;a)y^+cp_~oO#P+dV2KlP z^k_*`ZhIA>X$iT49GYHECWdu2o)YtH>j2&Cq1i))AF(ENRR}=#*)jUIxO<`-?6Vp+ zW$>B2=1@#;##D`sy9kSXJ1sQViiUrEuc;h8i9*g>gL=i_NZ6^+d~!hsT6Ab=l`ytj z47TS1n->P~)Da>QPA_34n&av9d&Di1i_4*e8EThW-B8ITx}6tORAbhMqgqS1i7=<7 z>(pD-r*@B=Fj;Os#E0QXsbk`~v9DH>7KrkSq3h4Kx0xfOe~JWxJv2PuNb3nv>DzEd z-xdp{^?~(L9itD#bQ>9@h@q%R3};9IO2>n8PmTG&SK=vzL_$yeR<#=zkI{}@-$(oX zWR&4jbH1hNKrFW*ah$JM<9pncoTYcIZ|i|wg@^?_!kG2vVc*H^$G0$#CouJVDq1Rz zPdvg#Uaro<2`h@$`Sj6^cl$(LKp~`)C7UCrMkP-gGE}fgG{D3t^mPkkgE%vOQVi?O z3>#7A^D%M~KB@gk;fhjn728L%BH>Qpu;Le4ZEq}EQ+YV!$C6Z29P0CBlqi=@f%>)A z?af2Rr&Au~=TZ5DgZ7h+H4xTG%g0?UIM6Y|2kS~K$2g6fyPikvs*5nSHTs|nlp|@G zZj)Y|Q0hXgOjMt8Yy``$m-E#D1TLiYSCBIm&Fd2Ui23?L7aJ_ORXgguQ~c? z3Hgix5Q_!i{jcymV08F?Av`A3{BJP{9!U{F0XcaZ3Bjib-wFU`y8m2&+3x#=@a&!^8Swp^BGEsU0BoCnDbfDD z#COH~e<}!24gICy{@)9JPk-t#IXdyYvoiw7&l>Cg)K-4VxO=2* zTMVFC27HKq&;jnXUXFk|{DD#AM;rdyWIn|MEplE}2h>#tP@4L0csc-E@gMMnY_#>v z^c4UK@WPhn`r?+Brthr&42`p?vD^m$xdptX-wuR-T(w?Mkbi^*$nKiGvjqf^2^yQ} z^XTg8+uBNKTWA~pNOthF?z$CT&2Is9M*!IK{$6+d=YJ$nveC8z#3BMr9R|jR?*Izc z05$hN*ImX9*LWMyC76J^)BUJ8;9l!B43HN1L$^GAp2C294QBtV;$t?4!KeV&5DP#x zzlAORxN5!bQU8ekw=8OZuJQHiR?sH^UK#M%raIf`J#Qh^CAZX7{+sy3GXsey# zLA`+X#{tHYzjv)K;QZhZ?dP?$wELEID0bNnf4cz5h4A^@r%0F~kgB;XGCX#?yse?a}~J^qgU ztJy&y{EnLG#%SdmIKK@ zvi$QP@ifcKPdFXL|IT;c$IL&@dB4{0TjcQ5EHOU;KLY^&SI(HHDBnr}e*XWtz9n1v z>-skJoGbmUmEVM4o)&(ZdgVv)S}#K7-wOXY+5csQ{ls4S6#i*Cji2zPs=vYi0{eYG zNdNoW_^scbCa(C2nyB_KQ2!x~#nbvfO%U*tDOvMhF#YP=18AMqujvAwQa#mY|4HSq z{ZCZ?L#_QO{8ORvpYS-k{{;X2N&J)S_*1HG_Pa39Q_QD=2R|{_J%7ji_wol%d7cL0|KzFh{*CAN!Q)?rQ`_(V z=KS+;_0$daC+1DU|Bd1IBcK$X4{N7Q&j#7Va!BdZ~p9B+W zzY+YHCH{@A_GwF=dT9J43d;VC=(pGPpMGvnPrZL4N96s6{J;9>&u8FI8}anC@h6pc z;XhIRA9Lx`L$;r=n??Tw`+dOphaprcIy7SF#KPJ5NRtH_{|AO|Su+3t diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index cf497ceec..000000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Tue Jun 16 01:35:27 CDT 2015 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-all.zip diff --git a/gradlew b/gradlew deleted file mode 100755 index 91a7e269e..000000000 --- a/gradlew +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index aec99730b..000000000 --- a/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 553c1b13b..000000000 --- a/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'asterisk-java' From 59f816ebda1ba19c45818cf1042cd97d83703f09 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 4 Oct 2022 10:06:35 +1100 Subject: [PATCH 517/802] down grade logback for java version compatibility --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dc84b36d0..7e89fcd8a 100644 --- a/pom.xml +++ b/pom.xml @@ -129,7 +129,7 @@ ch.qos.logback logback-classic - 1.4.0 + 1.3.3 test From 5439515a291985cf968c0038903a28babe63146e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 23:08:05 +0000 Subject: [PATCH 518/802] Bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/nexus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nexus.yml b/.github/workflows/nexus.yml index 3cd1e8344..5ac2df329 100644 --- a/.github/workflows/nexus.yml +++ b/.github/workflows/nexus.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-18.04 steps: - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Java and Maven uses: actions/setup-java@v1 From fcbf45ef3a0b278770305c2875edf0bfcbcc108f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 23:08:12 +0000 Subject: [PATCH 519/802] Bump actions/setup-java from 1 to 3 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 1 to 3. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v1...v3) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/nexus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nexus.yml b/.github/workflows/nexus.yml index 3cd1e8344..8096e2b7b 100644 --- a/.github/workflows/nexus.yml +++ b/.github/workflows/nexus.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v2 - name: Install Java and Maven - uses: actions/setup-java@v1 + uses: actions/setup-java@v3 with: java-version: 1.8 From cc51a93c4581553fa38d0c7a1eb6764b4e8cb779 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 23:08:55 +0000 Subject: [PATCH 520/802] Bump junit-jupiter from 5.9.0 to 5.9.1 Bumps [junit-jupiter](https://github.com/junit-team/junit5) from 5.9.0 to 5.9.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.0...r5.9.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7e89fcd8a..8d6c7335e 100644 --- a/pom.xml +++ b/pom.xml @@ -111,7 +111,7 @@ org.junit.jupiter junit-jupiter - 5.9.0 + 5.9.1 test From 1476a72f401471bdd7f57b1ba700ad4babb60938 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 23:08:56 +0000 Subject: [PATCH 521/802] Bump nexus-staging-maven-plugin from 1.6.7 to 1.6.13 Bumps nexus-staging-maven-plugin from 1.6.7 to 1.6.13. --- updated-dependencies: - dependency-name: org.sonatype.plugins:nexus-staging-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7e89fcd8a..6e085358e 100644 --- a/pom.xml +++ b/pom.xml @@ -286,7 +286,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.7 + 1.6.13 true ossrh From c46dd1f09726530e70eb049d41087ae53d3229f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 23:09:03 +0000 Subject: [PATCH 522/802] Bump maven-gpg-plugin from 1.6 to 3.0.1 Bumps [maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 1.6 to 3.0.1. - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-1.6...maven-gpg-plugin-3.0.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7e89fcd8a..02135b355 100644 --- a/pom.xml +++ b/pom.xml @@ -262,7 +262,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.6 + 3.0.1 EA919AF2 From a26fa3ff6437e3842f59aff04ba5691e438ff94d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 23:09:12 +0000 Subject: [PATCH 523/802] Bump mockito-core from 4.7.0 to 4.8.0 Bumps [mockito-core](https://github.com/mockito/mockito) from 4.7.0 to 4.8.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.7.0...v4.8.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7e89fcd8a..d69671da4 100644 --- a/pom.xml +++ b/pom.xml @@ -123,7 +123,7 @@ org.mockito mockito-core - 4.7.0 + 4.8.0 test From 74fe52116fb1c3f7191a28283d55b1df14daa67c Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 4 Oct 2022 10:26:03 +1100 Subject: [PATCH 524/802] for version 3.32.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d6b953a27..e39f0b709 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.31.0 + 3.32.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 65109e808..a9f60af18 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,7 @@ - 3.31.0 + 3.32.0 UTF-8 From fdc63b429d9460fee300b4fcb77c6d5f743b7324 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 4 Oct 2022 10:33:05 +1100 Subject: [PATCH 525/802] revert gpg plugin version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a9f60af18..b6018a60d 100644 --- a/pom.xml +++ b/pom.xml @@ -262,7 +262,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 1.6 EA919AF2 From 468e70ba50fbd8b9ba9775502bc1cbe3e42a43a0 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 4 Oct 2022 10:33:17 +1100 Subject: [PATCH 526/802] for version 3.32.1-SNAPSHOT --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e39f0b709..40b936175 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.32.0 + 3.32.1-SNAPSHOT INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index b6018a60d..04a91f008 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,7 @@ - 3.32.0 + 3.32.1-SNAPSHOT UTF-8 From b53688d10c97e87b7509ef6c34176024219aad68 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 4 Oct 2022 10:33:44 +1100 Subject: [PATCH 527/802] for version 3.33.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 40b936175..bf185056e 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.32.1-SNAPSHOT + 3.33.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 04a91f008..f8be6d4c2 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,7 @@ - 3.32.1-SNAPSHOT + 3.33.0 UTF-8 From 1ef3befd5dc8956bef7211e417f7741a5420f3c0 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 4 Oct 2022 10:37:21 +1100 Subject: [PATCH 528/802] revert --- .github/workflows/nexus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nexus.yml b/.github/workflows/nexus.yml index f1f450621..5ac2df329 100644 --- a/.github/workflows/nexus.yml +++ b/.github/workflows/nexus.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v3 - name: Install Java and Maven - uses: actions/setup-java@v3 + uses: actions/setup-java@v1 with: java-version: 1.8 From 81844759b0c381138f87f6e9be4bfd421e3d1dd9 Mon Sep 17 00:00:00 2001 From: Robert Sutton Date: Tue, 4 Oct 2022 10:38:03 +1100 Subject: [PATCH 529/802] for version 3.34.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bf185056e..0a4d46f1b 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.33.0 + 3.34.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index f8be6d4c2..654cc625c 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,7 @@ - 3.33.0 + 3.34.0 UTF-8 From 763fdaf9ec7b45644ec78f531a837ccfcd7e3d75 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 02:05:00 +0000 Subject: [PATCH 530/802] Bump log4j-core from 2.18.0 to 2.19.0 Bumps log4j-core from 2.18.0 to 2.19.0. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 654cc625c..f85d40ae7 100644 --- a/pom.xml +++ b/pom.xml @@ -99,7 +99,7 @@ org.apache.logging.log4j log4j-core - 2.18.0 + 2.19.0 provided From 109e661501197dc900829e3721227c1cb6af2df9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 02:05:07 +0000 Subject: [PATCH 531/802] Bump bnd-maven-plugin from 3.2.0 to 6.3.1 Bumps [bnd-maven-plugin](https://github.com/bndtools/bnd) from 3.2.0 to 6.3.1. - [Release notes](https://github.com/bndtools/bnd/releases) - [Changelog](https://github.com/bndtools/bnd/blob/master/docs/ADDING_RELEASE_DOCS.md) - [Commits](https://github.com/bndtools/bnd/commits/6.3.1) --- updated-dependencies: - dependency-name: biz.aQute.bnd:bnd-maven-plugin dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 654cc625c..ff88e6353 100644 --- a/pom.xml +++ b/pom.xml @@ -147,7 +147,7 @@ biz.aQute.bnd bnd-maven-plugin - 3.2.0 + 6.3.1 From 245a641320a3644321ff12af1c80d58a6cf85c73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 02:05:11 +0000 Subject: [PATCH 532/802] Bump maven-surefire-plugin from 3.0.0-M4 to 3.0.0-M7 Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.0.0-M4 to 3.0.0-M7. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0-M4...surefire-3.0.0-M7) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 654cc625c..db00fb132 100644 --- a/pom.xml +++ b/pom.xml @@ -179,7 +179,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M4 + 3.0.0-M7 maven-assembly-plugin From e5f20234c2181920894866424983cce2f4d2abf9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 02:05:14 +0000 Subject: [PATCH 533/802] Bump slf4j-api from 2.0.0 to 2.0.3 Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 2.0.0 to 2.0.3. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_2.0.0...v_2.0.3) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 654cc625c..1d6079b5b 100644 --- a/pom.xml +++ b/pom.xml @@ -93,7 +93,7 @@ org.slf4j slf4j-api - 2.0.0 + 2.0.3 compile From e5d507808e412ebbff980f55ae8e708afdbd9ea2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Oct 2022 05:32:17 +0000 Subject: [PATCH 534/802] Bump maven-source-plugin from 2.4 to 3.2.1 Bumps [maven-source-plugin](https://github.com/apache/maven-source-plugin) from 2.4 to 3.2.1. - [Release notes](https://github.com/apache/maven-source-plugin/releases) - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-2.4...maven-source-plugin-3.2.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-source-plugin dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 654cc625c..8576fe812 100644 --- a/pom.xml +++ b/pom.xml @@ -93,7 +93,7 @@ org.slf4j slf4j-api - 2.0.0 + 2.0.3 compile @@ -211,7 +211,7 @@ org.apache.maven.plugins maven-source-plugin - 2.4 + 3.2.1 attach-sources From b6368873d52f7fc7c87fa983ddf267c0dcfea6bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Oct 2022 05:36:26 +0000 Subject: [PATCH 535/802] Bump maven-javadoc-plugin from 2.10.3 to 3.4.1 Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 2.10.3 to 3.4.1. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-2.10.3...maven-javadoc-plugin-3.4.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1d6079b5b..5f91b528e 100644 --- a/pom.xml +++ b/pom.xml @@ -211,7 +211,7 @@ org.apache.maven.plugins maven-source-plugin - 2.4 + 3.2.1 attach-sources @@ -224,7 +224,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.3 + 3.4.1 attach-javadocs From d3a3df5414de0181bffa3deac0dbb048420713e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Oct 2022 19:05:30 +0000 Subject: [PATCH 536/802] Bump maven-compiler-plugin from 3.2 to 3.10.1 Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.2 to 3.10.1. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.2...maven-compiler-plugin-3.10.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 02b7ba992..2f4f13a02 100644 --- a/pom.xml +++ b/pom.xml @@ -99,7 +99,7 @@ org.apache.logging.log4j log4j-core - 2.18.0 + 2.19.0 provided @@ -170,7 +170,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 1.8 1.8 From c718c88570b5db188a2affafcb9dc4ca631812ad Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Fri, 7 Oct 2022 21:55:17 +0200 Subject: [PATCH 537/802] Add maven wrapper --- .mvn/wrapper/maven-wrapper.jar | Bin 0 -> 59925 bytes .mvn/wrapper/maven-wrapper.properties | 18 ++ mvnw | 287 ++++++++++++++++++++++++++ mvnw.cmd | 187 +++++++++++++++++ 4 files changed, 492 insertions(+) create mode 100644 .mvn/wrapper/maven-wrapper.jar create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100755 mvnw create mode 100644 mvnw.cmd diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..bf82ff01c6cdae4a1bb754a6e062954d77ac5c11 GIT binary patch literal 59925 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

    dy!05UMhSKsK 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 VCNKd3JGtOvEm(5t0lFyE{{i--k}m)N literal 0 HcmV?d00001 diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 000000000..dc3affce3 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://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. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar diff --git a/mvnw b/mvnw new file mode 100755 index 000000000..b7f064624 --- /dev/null +++ b/mvnw @@ -0,0 +1,287 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.1.1 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="`/usr/libexec/java_home`"; export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + printf '%s' "$(cd "$basedir"; pwd)" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname $0)") +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) wrapperUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $wrapperUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + QUIET="--quiet" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + QUIET="" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" + fi + [ $? -eq 0 ] || rm -f "$wrapperJarPath" + elif command -v curl > /dev/null; then + QUIET="--silent" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + QUIET="" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L + fi + [ $? -eq 0 ] || rm -f "$wrapperJarPath" + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaSource="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=`cygpath --path --windows "$javaSource"` + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 000000000..474c9d6b7 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,187 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.1.1 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% From 218cb526079718e0aed2ef5d48dfa5ac98124d2c Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Fri, 7 Oct 2022 22:27:45 +0200 Subject: [PATCH 538/802] Fix maven javadoc plugin configuration property after update --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 735cea4dd..c6475bf01 100644 --- a/pom.xml +++ b/pom.xml @@ -234,8 +234,7 @@ - - -Xdoclint:none + none -Xdoclint:none -Xdoclint:none From 317eae926e8e1bba5221551c672f92486961acef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 8 Oct 2022 09:28:05 +0200 Subject: [PATCH 539/802] Bump maven-assembly-plugin from 2.5.3 to 3.4.2 (#404) * Bump maven-assembly-plugin from 2.5.3 to 3.4.2 Bumps [maven-assembly-plugin](https://github.com/apache/maven-assembly-plugin) from 2.5.3 to 3.4.2. - [Release notes](https://github.com/apache/maven-assembly-plugin/releases) - [Commits](https://github.com/apache/maven-assembly-plugin/compare/maven-assembly-plugin-2.5.3...maven-assembly-plugin-3.4.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-assembly-plugin dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Change maven assembly plugin from deprecated attached to single Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Piotr Olaszewski --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 99e2253fc..cbf8463c8 100644 --- a/pom.xml +++ b/pom.xml @@ -183,7 +183,7 @@ maven-assembly-plugin - 2.5.3 + 3.4.2 ${project.basedir}/src/main/assembly/bin.xml @@ -194,7 +194,7 @@ make-assembly package - attached + single @@ -262,7 +262,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.6 + 1.6 EA919AF2 From 331eaf7b4282158480c9d1f69798985f979bbdf4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 8 Oct 2022 14:20:42 +0200 Subject: [PATCH 540/802] Bump maven-jar-plugin from 2.5 to 3.3.0 (#397) * Bump maven-jar-plugin from 2.5 to 3.3.0 Bumps [maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 2.5 to 3.3.0. - [Release notes](https://github.com/apache/maven-jar-plugin/releases) - [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-2.5...maven-jar-plugin-3.3.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-jar-plugin dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Fix maven-jar-plugin configuration Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Piotr Olaszewski --- pom.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cbf8463c8..d220bf96e 100644 --- a/pom.xml +++ b/pom.xml @@ -139,9 +139,14 @@ org.apache.maven.plugins maven-jar-plugin - 2.5 + 3.3.0 - true + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + true + + From 80fd191a9ba75c9f12cfbb451501d9a764b2dbb7 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Sat, 8 Oct 2022 15:54:36 +0200 Subject: [PATCH 541/802] Fix maven-assembly-plugin coordinates --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 4dfdefd9b..cae2d34bd 100644 --- a/pom.xml +++ b/pom.xml @@ -187,6 +187,7 @@ 3.0.0-M7 + org.apache.maven.plugins maven-assembly-plugin 3.4.2 From fd28bb383be6899ad8bd7845cfd883b14b81b7ff Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Sat, 8 Oct 2022 15:55:10 +0200 Subject: [PATCH 542/802] Remove unused settings.xml file --- settings.xml | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 settings.xml diff --git a/settings.xml b/settings.xml deleted file mode 100644 index 7480a1434..000000000 --- a/settings.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - github - - - - - github - - - central - https://repo1.maven.org/maven2 - - true - - - true - - - - - - - - - github - ${env.GITHUB_USERNAME} - ${env.GITHUB_TOKEN} - - - \ No newline at end of file From 98d4641b4c5d02dc79e59b05911b4f4e0c2d543a Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Sun, 9 Oct 2022 18:26:28 +0200 Subject: [PATCH 543/802] Add missing fields for call parking events --- .editorconfig | 2 +- .../manager/event/AbstractParkedCallEvent.java | 9 +++++++++ .../manager/event/AbstractUnParkedEvent.java | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index f02d2801a..974f98cf2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,5 @@ [*.{java,html}] charset = utf-8 -indent_style = tab +indent_style = space indent_size = 4 trim_trailing_whitespace = true diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java index 2460aadc3..440cc94f8 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java @@ -42,6 +42,7 @@ public abstract class AbstractParkedCallEvent extends ManagerEvent { private String parkeeExten; private Integer parkeePriority; private String parkeeUniqueid; + private String parkeeLinkedid; // Previously: From private String parkerDialString; private String parkingLot; @@ -231,6 +232,14 @@ public void setParkeeUniqueid(String parkeeUniqueid) { this.parkeeUniqueid = parkeeUniqueid; } + public String getParkeeLinkedid() { + return parkeeLinkedid; + } + + public void setParkeeLinkedid(String parkeeLinkedid) { + this.parkeeLinkedid = parkeeLinkedid; + } + public String getParkerDialString() { return parkerDialString; } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractUnParkedEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractUnParkedEvent.java index 61cb00f85..73097dd9d 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractUnParkedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractUnParkedEvent.java @@ -37,6 +37,8 @@ public class AbstractUnParkedEvent extends AbstractParkedCallEvent { private String parkerExten; private String parkerPriority; private String parkerUniqueid; + private String parkerLinkedid; + private String parkerLanguage; /** * @param source @@ -140,4 +142,20 @@ public String getParkerUniqueid() { public void setParkerUniqueid(String parkerUniqueid) { this.parkerUniqueid = parkerUniqueid; } + + public String getParkerLinkedid() { + return parkerLinkedid; + } + + public void setParkerLinkedid(String parkerLinkedid) { + this.parkerLinkedid = parkerLinkedid; + } + + public String getParkerLanguage() { + return parkerLanguage; + } + + public void setParkerLanguage(String parkerLanguage) { + this.parkerLanguage = parkerLanguage; + } } From 78758492a671fb15a17e18ab9ce256947ea6fe93 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Sun, 9 Oct 2022 18:27:14 +0200 Subject: [PATCH 544/802] Remove duplicated parkingLot methods --- .../manager/event/AbstractParkedCallEvent.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java index 440cc94f8..373eae815 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractParkedCallEvent.java @@ -248,14 +248,6 @@ public void setParkerDialString(String parkerDialString) { this.parkerDialString = parkerDialString; } - public String getParkinglot() { - return parkingLot; - } - - public void setParkinglot(String parkinglot) { - this.parkingLot = parkinglot; - } - public String getParkingSpace() { return parkingSpace; } From 4c943bf243185485ed8c3608f054e1b5c38ee7b4 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Sun, 9 Oct 2022 22:04:53 +0200 Subject: [PATCH 545/802] Add includeContext, switch and ignorePattern to ListDialplanEvent and eventList to ShowDialplanCompleteEvent --- .../manager/event/ListDialplanEvent.java | 29 +++++++++++++++++++ .../event/ShowDialplanCompleteEvent.java | 9 ++++++ 2 files changed, 38 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/ListDialplanEvent.java b/src/main/java/org/asteriskjava/manager/event/ListDialplanEvent.java index e3fdae6b3..7e9740bed 100644 --- a/src/main/java/org/asteriskjava/manager/event/ListDialplanEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ListDialplanEvent.java @@ -23,6 +23,9 @@ public class ListDialplanEvent extends ResponseEvent { private String application; private String appData; private String registrar; + private String includeContext; + private String _switch; + private String ignorePattern; public ListDialplanEvent(Object source) { super(source); @@ -119,4 +122,30 @@ public String getRegistrar() { public void setRegistrar(String registrar) { this.registrar = registrar; } + + public String getIncludeContext() { + return includeContext; + } + + public void setIncludeContext(String includeContext) { + this.includeContext = includeContext; + } + + public String getSwitch() { + return _switch; + } + + public ListDialplanEvent setSwitch(String _switch) { + this._switch = _switch; + return this; + } + + public String getIgnorePattern() { + return ignorePattern; + } + + public ListDialplanEvent setIgnorePattern(String ignorePattern) { + this.ignorePattern = ignorePattern; + return this; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/ShowDialplanCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/ShowDialplanCompleteEvent.java index 22a96b50a..8aa8a55c4 100644 --- a/src/main/java/org/asteriskjava/manager/event/ShowDialplanCompleteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ShowDialplanCompleteEvent.java @@ -15,6 +15,7 @@ public class ShowDialplanCompleteEvent extends ResponseEvent { private static final long serialVersionUID = 1L; + private String eventList; private Integer listItems; private Integer listExtensions; private Integer listPriorities; @@ -24,6 +25,14 @@ public ShowDialplanCompleteEvent(Object source) { super(source); } + public String getEventList() { + return eventList; + } + + public void setEventList(String eventList) { + this.eventList = eventList; + } + /** * Returns the total number of list items reported. * From a322cab1de3050e8f668e3b0b788416035da105c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Oct 2022 07:41:38 +0200 Subject: [PATCH 546/802] Bump logback-classic from 1.3.3 to 1.3.4 (#414) * Bump logback-classic from 1.3.3 to 1.3.4 --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Use maven wrapper for run GitHub Actions maven commands * Fix dependency for Java 8 Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Piotr Olaszewski --- .github/dependabot.yml | 4 ++++ .github/workflows/ci.yml | 2 +- pom.xml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b76b89570..d15d5a9af 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,6 +4,10 @@ updates: directory: "/" schedule: interval: "daily" + ignore: + # As long as we support Java 8 + - dependency-name: "logback-classic" + update-types: [ "version-update:semver-major", "version-update:semver-minor" ] - package-ecosystem: "github-actions" directory: "/" schedule: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d59b779d..d783d316e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,4 +25,4 @@ jobs: java-version: ${{ matrix.java }} - name: Build - run: mvn clean package + run: ./mvnw clean package diff --git a/pom.xml b/pom.xml index cae2d34bd..001ea6b69 100644 --- a/pom.xml +++ b/pom.xml @@ -129,7 +129,7 @@ ch.qos.logback logback-classic - 1.3.3 + 1.3.4 test From fd57b4ea73230a8ffbfdbf5ece8b8f2959ebb602 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Tue, 11 Oct 2022 18:03:30 +0200 Subject: [PATCH 547/802] Add release drafter --- .editorconfig | 5 ++++- .github/release-drafter-master.yml | 29 +++++++++++++++++++++++++++ .github/workflows/ci.yml | 4 ++-- .github/workflows/release-drafter.yml | 21 +++++++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 .github/release-drafter-master.yml create mode 100644 .github/workflows/release-drafter.yml diff --git a/.editorconfig b/.editorconfig index f02d2801a..d70a9b032 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,8 @@ [*.{java,html}] charset = utf-8 -indent_style = tab +indent_style = space indent_size = 4 trim_trailing_whitespace = true + +[*.{yml, yaml}] +indent_size = 2 diff --git a/.github/release-drafter-master.yml b/.github/release-drafter-master.yml new file mode 100644 index 000000000..9de943152 --- /dev/null +++ b/.github/release-drafter-master.yml @@ -0,0 +1,29 @@ +name-template: $NEXT_MINOR_VERSION +tag-template: $NEXT_MINOR_VERSION +filter-by-commitish: true +commitish: master +template: | + ## What's Changed + + $CHANGES +categories: + - title: '💥 Breaking API Changes' + label: 'kind/breaking' + - title: '🚀 Features & Enhancements' + labels: + - 'kind/enhancement' + - 'kind/feature' + - title: '🐛 Bug Fixes' + label: 'kind/bug' + - title: '🧹 Refactor' + label: 'kind/refactor' + - title: '📝 Documentation' + label: 'kind/documentation' + - title: '📦 Dependency Updates' + label: 'kind/dependencies' + collapse-after: 5 +change-template: '* (#$NUMBER) $TITLE by @$AUTHOR' +exclude-labels: + - 'kind/question' + - 'kind/wontfix' + - 'meta/skip-changelog' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d783d316e..28c77817c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,12 +14,12 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v3.1.0 with: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v3.5.1 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 000000000..42bd03459 --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,21 @@ +name: Release Drafter + +on: + push: + branches: + - master + +permissions: + contents: read + +jobs: + update_release_draft: + permissions: + contents: write # for release-drafter to create a GitHub release + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v5.21.0 + with: + config-name: release-drafter-master.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 4d01df1db7bed744c6b00be39791c5d75ae3bc17 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Oct 2022 02:42:01 +0000 Subject: [PATCH 548/802] Bump release-drafter/release-drafter from 5.21.0 to 5.21.1 Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.21.0 to 5.21.1. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v5.21.0...v5.21.1) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 42bd03459..6daabb9c6 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -14,7 +14,7 @@ jobs: contents: write # for release-drafter to create a GitHub release runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v5.21.0 + - uses: release-drafter/release-drafter@v5.21.1 with: config-name: release-drafter-master.yml env: From b1ae0229581b20e1c0e4583c8c602e7d3d477471 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Oct 2022 03:02:32 +0000 Subject: [PATCH 549/802] Bump actions/setup-java from 3.5.1 to 3.6.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3.5.1 to 3.6.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3.5.1...v3.6.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/nexus.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28c77817c..a06c36870 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v3.5.1 + uses: actions/setup-java@v3.6.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/nexus.yml b/.github/workflows/nexus.yml index 5ac2df329..b726b44e1 100644 --- a/.github/workflows/nexus.yml +++ b/.github/workflows/nexus.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v3 - name: Install Java and Maven - uses: actions/setup-java@v1 + uses: actions/setup-java@v3.6.0 with: java-version: 1.8 From 3d2d97ac1740fa251517badf635c0d26afc8f6a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Oct 2022 02:03:00 +0000 Subject: [PATCH 550/802] Bump mockito-core from 4.8.0 to 4.8.1 Bumps [mockito-core](https://github.com/mockito/mockito) from 4.8.0 to 4.8.1. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.8.0...v4.8.1) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 001ea6b69..4fc5f1a32 100644 --- a/pom.xml +++ b/pom.xml @@ -123,7 +123,7 @@ org.mockito mockito-core - 4.8.0 + 4.8.1 test From a5daf0b2e886dff71c8d70b6760b9ec8ee1b67f0 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Sat, 29 Oct 2022 11:57:09 +0200 Subject: [PATCH 551/802] Add labels to dependabot --- .github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d15d5a9af..d5a770378 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,6 +4,8 @@ updates: directory: "/" schedule: interval: "daily" + labels: + - "kind/dependencies" ignore: # As long as we support Java 8 - dependency-name: "logback-classic" @@ -12,3 +14,5 @@ updates: directory: "/" schedule: interval: "daily" + labels: + - "kind/dependencies" From d0359c608847e5240b0cd46ad2cc2cb663f64faf Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Sat, 29 Oct 2022 12:01:47 +0200 Subject: [PATCH 552/802] Removed templates from release drafter --- .github/release-drafter-master.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/release-drafter-master.yml b/.github/release-drafter-master.yml index 9de943152..1be06ba3d 100644 --- a/.github/release-drafter-master.yml +++ b/.github/release-drafter-master.yml @@ -1,5 +1,3 @@ -name-template: $NEXT_MINOR_VERSION -tag-template: $NEXT_MINOR_VERSION filter-by-commitish: true commitish: master template: | From 4d2430e3761ccda15a91ad18039c1dcf3d58ee59 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Sat, 5 Nov 2022 09:21:54 +0100 Subject: [PATCH 553/802] Add issue management info to pom.xml --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 4fc5f1a32..33fa25ffb 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,11 @@ + + GitHub + https://github.com/asterisk-java/asterisk-java/issues + + Stefan Reuter From 290555abd2d3790a069bfcc83cfa6bc6e866c12c Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Fri, 11 Nov 2022 18:24:48 +0100 Subject: [PATCH 554/802] Introduce new release process based on GitHub Releases and Actions (#423) * Introduce new release process based on GitHub Releases and Actions * Introduce new release process based on GitHub Releases and Actions - use deploy profile * Introduce new release process based on GitHub Releases and Actions - cleanup --- .dart_tool/.gitignore | 1 - .github/workflows/nexus.yml | 28 ---- .github/workflows/release.yml | 67 ++++++++ pom.xml | 12 +- pubspec.lock | 278 ---------------------------------- pubspec.yaml | 12 -- triggerRelease.dart | 80 ---------- 7 files changed, 72 insertions(+), 406 deletions(-) delete mode 100644 .dart_tool/.gitignore delete mode 100644 .github/workflows/nexus.yml create mode 100644 .github/workflows/release.yml delete mode 100644 pubspec.lock delete mode 100644 pubspec.yaml delete mode 100755 triggerRelease.dart diff --git a/.dart_tool/.gitignore b/.dart_tool/.gitignore deleted file mode 100644 index b5a718a86..000000000 --- a/.dart_tool/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/package_config.json diff --git a/.github/workflows/nexus.yml b/.github/workflows/nexus.yml deleted file mode 100644 index b726b44e1..000000000 --- a/.github/workflows/nexus.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Release - -# Run workflow on tags -on: - push: - tags: - - '*' - -jobs: - release: - runs-on: ubuntu-18.04 - steps: - - name: Check out Git repository - uses: actions/checkout@v3 - - - name: Install Java and Maven - uses: actions/setup-java@v3.6.0 - with: - java-version: 1.8 - - - name: Release Maven package - uses: samuelmeuli/action-maven-publish@v1 - with: - gpg_private_key: ${{ secrets.gpg_private_key }} - gpg_passphrase: ${{ secrets.gpg_passphrase }} - nexus_username: ${{ secrets.nexus_username }} - nexus_password: ${{ secrets.nexus_password }} - diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..7448d3566 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,67 @@ +name: Release + +on: + release: + types: [ published ] + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v3.1.0 + + - name: Set up Java + uses: actions/setup-java@v3.6.0 + with: + java-version: 8 + distribution: temurin + server-id: ossrh + server-username: NEXUS_USERNAME + server-password: NEXUS_PASSWORD + gpg-passphrase: GPG_PASSPHRASE + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + + - name: Set artifact version + run: ./mvnw --batch-mode --define=generateBackupPoms=false --define=newVersion=${{ github.event.release.tag_name }} versions:set + + - name: Publish package + run: ./mvnw --batch-mode --activate-profiles=deploy deploy + env: + NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }} + NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + + update-versions: + needs: [ publish ] + permissions: + contents: write # for peter-evans/create-pull-request to create branch + pull-requests: write # for peter-evans/create-pull-request to create a PR + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v3.1.0 + with: + ref: master + fetch-depth: 0 + + - name: Update pom.xml version + run: ./mvnw --batch-mode --define=generateBackupPoms=false --define=newVersion=${{ github.event.release.tag_name }} versions:set + + - name: Update Maven version in README.md + run: sed --in-place 's/.*<\/version>/${{ github.event.release.tag_name }}<\/version>/g' README.md + + - name: Show diff + run: git diff + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v4.2.0 + with: + commit-message: Update versions to ${{ github.event.release.tag_name }} + title: Update versions to ${{ github.event.release.tag_name }} + body: Update versions to ${{ github.event.release.tag_name }} + branch: update-versions-${{ github.event.release.tag_name }} + delete-branch: true + labels: | + kind/documentation + meta/skip-changelog diff --git a/pom.xml b/pom.xml index 33fa25ffb..dc62168bb 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java - ${releaseVersion} + 3.34.0 Asterisk-Java The free Java library for Asterisk PBX integration. @@ -84,8 +84,6 @@ - 3.34.0 - UTF-8 @@ -310,13 +308,13 @@ - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - ossrh https://oss.sonatype.org/service/local/staging/deploy/maven2 + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + diff --git a/pubspec.lock b/pubspec.lock deleted file mode 100644 index c0143ffb5..000000000 --- a/pubspec.lock +++ /dev/null @@ -1,278 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.2" - args: - dependency: "direct main" - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.5.0" - basic_utils: - dependency: transitive - description: - name: basic_utils - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0-nullsafety.1" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.15.0" - convert: - dependency: transitive - description: - name: convert - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" - crypto: - dependency: transitive - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" - csv: - dependency: transitive - description: - name: csv - url: "https://pub.dartlang.org" - source: hosted - version: "5.0.0" - dcli: - dependency: "direct main" - description: - name: dcli - url: "https://pub.dartlang.org" - source: hosted - version: "0.51.5" - equatable: - dependency: transitive - description: - name: equatable - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - ffi: - dependency: transitive - description: - name: ffi - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - file: - dependency: transitive - description: - name: file - url: "https://pub.dartlang.org" - source: hosted - version: "6.1.0" - glob: - dependency: transitive - description: - name: glob - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - http: - dependency: transitive - description: - name: http - url: "https://pub.dartlang.org" - source: hosted - version: "0.13.0" - http_parser: - dependency: transitive - description: - name: http_parser - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.0" - ini: - dependency: transitive - description: - name: ini - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0-beta" - json_annotation: - dependency: transitive - description: - name: json_annotation - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.0" - logging: - dependency: transitive - description: - name: logging - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.10" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - path: - dependency: "direct main" - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.11.0" - pointycastle: - dependency: transitive - description: - name: pointycastle - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0-nullsafety.2" - posix: - dependency: transitive - description: - name: posix - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - pub_semver: - dependency: transitive - description: - name: pub_semver - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - pubspec2: - dependency: transitive - description: - name: pubspec2 - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" - random_string: - dependency: transitive - description: - name: random_string - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.0-nullsafety" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - uri: - dependency: transitive - description: - name: uri - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - uuid: - dependency: transitive - description: - name: uuid - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - validators2: - dependency: transitive - description: - name: validators2 - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" - vin_decoder: - dependency: transitive - description: - name: vin_decoder - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.0-nullsafety" - yaml: - dependency: transitive - description: - name: yaml - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.0" -sdks: - dart: ">=2.12.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml deleted file mode 100644 index 23958b051..000000000 --- a/pubspec.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: asterisk_java_installer -version: 1.0.0 -environment: - sdk: '>=2.12.0 <3.0.0' -dependencies: - dcli: '>=0.51.1' - args: ^2.0.0 - path: ^1.8.0 - - - - diff --git a/triggerRelease.dart b/triggerRelease.dart deleted file mode 100755 index 8399effad..000000000 --- a/triggerRelease.dart +++ /dev/null @@ -1,80 +0,0 @@ -#! /usr/bin/env dcli - -import 'dart:io'; - -import 'package:dcli/dcli.dart'; - -/// comment - -void main() { - int major = 0; - int minor = 0; - int rev = 0; - var dir = dirname(Script.current.pathToScript); - print(dir); - read(join(dir, "pom.xml")).forEach((line) { - if (line.contains("")) { - line = line.replaceFirst("-SNAPSHOT", ""); - var parts = line.split("."); - if (parts.length != 3) { - exit(1); - } - major = int.parse(parts[0].split(">")[1]); - minor = int.parse(parts[1]); - rev = int.parse(parts[2].split("<")[0]); - } - }); - - var postFix = ""; - if (confirm("Is this a SNAPSHOT release (y/n)?")) { - postFix = "-SNAPSHOT"; - rev++; - } else { - rev = 0; - minor++; - } - - String version = "$major.$minor.$rev$postFix"; - - replacePomVersion(join(dir, "pom.xml"), version); - replaceReadMeVersion(join(dir, "README.md"), version); - - 'git pull'.run; - 'git add .'.run; - 'git commit -m "for version $version"'.run; - 'git tag -a $version -m "$version"'.run; - 'git push origin'.run; - 'git push origin tag $version'.run; -} - -void replaceReadMeVersion(String path, String version) { - var tmp = '$path.tmp'; - if (exists(tmp)) { - delete(tmp); - } - read(path).forEach((line) { - if (line.contains("")) { - line = " $version"; - } - tmp.append(line); - }); - move(path, '$path.bak'); - move(tmp, path); - delete('$path.bak'); -} - -void replacePomVersion(String path, String version) { - var tmp = '$path.tmp'; - if (exists(tmp)) { - delete(tmp); - } - read(path).forEach((line) { - if (line.contains("")) { - line = " $version"; - } - tmp.append(line); - }); - move(path, '$path.bak'); - move(tmp, path); - delete('$path.bak'); -} From 1bbfc08cb91a9fbd173953f1b278cd5852cab7b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Nov 2022 18:26:25 +0100 Subject: [PATCH 555/802] Bump maven-gpg-plugin from 1.6 to 3.0.1 (#413) * Bump maven-gpg-plugin from 1.6 to 3.0.1 Bumps [maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 1.6 to 3.0.1. - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-1.6...maven-gpg-plugin-3.0.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Fix maven-gpg-plugin configuration Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Piotr Olaszewski --- pom.xml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index dc62168bb..b78ee5347 100644 --- a/pom.xml +++ b/pom.xml @@ -270,10 +270,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.6 - - EA919AF2 - + 3.0.1 sign-artifacts @@ -287,6 +284,7 @@ --pinentry-mode loopback + EA919AF2 From cf94863c71a73ab45ceebb7dedf8063ce1ca86a1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 11 Nov 2022 18:51:29 +0100 Subject: [PATCH 556/802] Update versions to 3.35.0 (#424) Co-authored-by: piotrooo --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0a4d46f1b..6402b3c67 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.34.0 + 3.35.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index b78ee5347..bdd2ceb55 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java - 3.34.0 + 3.35.0 Asterisk-Java The free Java library for Asterisk PBX integration. From ad547cc00ab32bd5339bffcc0a0b7a6e16a04fa9 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Mon, 14 Nov 2022 22:35:40 +0100 Subject: [PATCH 557/802] Add tests for AgiExecStartEvent --- .../manager/internal/EventBuilderImpl.java | 38 ++++++------ .../manager/internal/ResponseBuilderImpl.java | 32 +++++----- .../EventAttributesHelper.java} | 58 ++++++++++++------- .../manager/event/AgiExecStartEventTest.java | 43 ++++++++++++++ 4 files changed, 118 insertions(+), 53 deletions(-) rename src/main/java/org/asteriskjava/manager/{internal/AbstractBuilder.java => util/EventAttributesHelper.java} (76%) create mode 100644 src/test/java/org/asteriskjava/manager/event/AgiExecStartEventTest.java diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index b6d39812d..e7241e2f0 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -1,22 +1,22 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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.manager.internal; import org.asteriskjava.manager.event.*; +import org.asteriskjava.manager.util.EventAttributesHelper; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; import org.reflections.Reflections; @@ -33,7 +33,7 @@ * @version $Id$ * @see org.asteriskjava.manager.event.ManagerEvent */ -class EventBuilderImpl extends AbstractBuilder implements EventBuilder { +class EventBuilderImpl implements EventBuilder { private static final Set ignoredAttributes = new HashSet<>(Arrays.asList("event")); private Map> registeredEventClasses; private final Set eventClassNegativeCache = new HashSet<>(); @@ -41,7 +41,7 @@ class EventBuilderImpl extends AbstractBuilder implements EventBuilder { private static final Log logger = LogFactory.getLog(EventBuilderImpl.class); private final static Set> knownManagerEventClasses = new Reflections( - "org.asteriskjava.manager.event").getSubTypesOf(ManagerEvent.class); + "org.asteriskjava.manager.event").getSubTypesOf(ManagerEvent.class); EventBuilderImpl() { this.registeredEventClasses = new HashMap<>(); @@ -87,7 +87,7 @@ public final void registerEventClass(Class clazz) throws * @throws IllegalArgumentException if clazz is not a valid event class. */ public final void registerEventClass(String eventType, Class clazz) - throws IllegalArgumentException { + throws IllegalArgumentException { Constructor defaultConstructor; if (Modifier.isAbstract(clazz.getModifiers())) { @@ -131,8 +131,8 @@ public ManagerEvent buildEvent(Object source, Map attributes) { // Convert map of lists to list of maps - one map for each // PeerEntry event int peersAmount = attributes.get("listitems") != null - ? Integer.parseInt((String) attributes.get("listitems")) - : eventNames.size() - 1; // Last event is + ? Integer.parseInt((String) attributes.get("listitems")) + : eventNames.size() - 1; // Last event is // PeerlistComplete List> peersAttributes = new ArrayList<>(); for (Map.Entry attribute : attributes.entrySet()) { @@ -188,7 +188,7 @@ public ManagerEvent buildEvent(Object source, Map attributes) { if (eventClass == null) { if (eventClassNegativeCache.add(eventType)) { logger.info("No event class registered for event type '" + eventType + "', attributes: " + attributes - + ". Please report at https://github.com/asterisk-java/asterisk-java/issues"); + + ". Please report at https://github.com/asterisk-java/asterisk-java/issues"); } return null; } @@ -214,7 +214,7 @@ public ManagerEvent buildEvent(Object source, Map attributes) { // being passed around. for (Map peerAttrs : (List>) attributes.get("peersAttributes")) { PeerEntryEvent peerEntryEvent = new PeerEntryEvent(source); - setAttributes(peerEntryEvent, peerAttrs, ignoredAttributes); + EventAttributesHelper.setAttributes(peerEntryEvent, peerAttrs, ignoredAttributes); List peerEntryEvents = peersEvent.getChildEvents(); if (peerEntryEvents == null) { peerEntryEvents = new ArrayList<>(); @@ -224,7 +224,7 @@ public ManagerEvent buildEvent(Object source, Map attributes) { } peersEvent.setActionId(peersEvent.getChildEvents().get(0).getActionId()); } else { - setAttributes(event, attributes, ignoredAttributes); + EventAttributesHelper.setAttributes(event, attributes, ignoredAttributes); } // ResponseEvents are sent in response to a ManagerAction if the diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java index 8d4f5bccd..577843f08 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java @@ -1,27 +1,29 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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.manager.internal; import org.asteriskjava.manager.response.CommandResponse; import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; +import org.asteriskjava.manager.util.EventAttributesHelper; +import org.slf4j.Logger; import java.util.*; +import static org.slf4j.LoggerFactory.getLogger; /** * Default implementation of the ResponseBuilder interface. @@ -30,9 +32,11 @@ * @version $Id$ * @see org.asteriskjava.manager.response.ManagerResponse */ -class ResponseBuilderImpl extends AbstractBuilder implements ResponseBuilder { +class ResponseBuilderImpl implements ResponseBuilder { + private static final Logger logger = getLogger(ResponseBuilderImpl.class); + private static final Set ignoredAttributes = new HashSet<>(Arrays.asList( - "attributes", "proxyresponse", ManagerReader.COMMAND_RESULT_RESPONSE_KEY)); + "attributes", "proxyresponse", ManagerReader.COMMAND_RESULT_RESPONSE_KEY)); private static final String RESPONSE_KEY = "response"; private static final String PROXY_RESPONSE_KEY = "proxyresponse"; @@ -57,7 +61,7 @@ public ManagerResponse buildResponse(Class responseCl } } - setAttributes(response, attributes, ignoredAttributes); + EventAttributesHelper.setAttributes(response, attributes, ignoredAttributes); if (response instanceof CommandResponse) { final CommandResponse commandResponse = (CommandResponse) response; diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/util/EventAttributesHelper.java similarity index 76% rename from src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java rename to src/main/java/org/asteriskjava/manager/util/EventAttributesHelper.java index 62262be6e..5d8013dc1 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/util/EventAttributesHelper.java @@ -1,27 +1,45 @@ -package org.asteriskjava.manager.internal; +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.util; import org.asteriskjava.manager.event.UserEvent; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.AstUtil; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; import org.asteriskjava.util.ReflectionUtil; +import org.slf4j.Logger; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; +import static org.slf4j.LoggerFactory.getLogger; + /** - * Abstract base class for reflection based builders. + * @author Piotr Olaszewski */ -abstract class AbstractBuilder { - protected final Log logger = LogFactory.getLog(getClass()); +public class EventAttributesHelper { + private static final Logger logger = getLogger(EventAttributesHelper.class); + + private EventAttributesHelper() { + } - protected void setAttributes(Object target, Map attributes, Set ignoredAttributes) { + public static void setAttributes(Object target, Map attributes, Set ignoredAttributes) { Map setters; setters = ReflectionUtil.getSetters(target.getClass()); @@ -64,10 +82,10 @@ protected void setAttributes(Object target, Map attributes, Set< // intentional if (setter == null && !(target instanceof UserEvent) && !target.getClass().equals(ManagerResponse.class)) { logger.warn("Unable to set property '" + entry.getKey() + "' to '" + entry.getValue() + "' on " - + target.getClass().getName() - + ": no setter. Please report at https://github.com/asterisk-java/asterisk-java/issues"); + + target.getClass().getName() + + ": no setter. Please report at https://github.com/asterisk-java/asterisk-java/issues"); - for (Entry entry2 : attributes.entrySet()) { + for (Map.Entry entry2 : attributes.entrySet()) { logger.debug("Key: " + entry2.getKey() + " Value: " + entry2.getValue()); } } @@ -100,8 +118,8 @@ protected void setAttributes(Object target, Map attributes, Set< } else value = constructor.newInstance(entry.getValue()); } catch (Exception e) { logger.error("Unable to convert value: Called the constructor of " + dataType + " with value '" - + entry.getValue() + "' for the attribute '" + entry.getKey() + "'\n of event type " - + target.getClass().getName() + " with resulting error: " + e.getMessage(), e); + + entry.getValue() + "' for the attribute '" + entry.getKey() + "'\n of event type " + + target.getClass().getName() + " with resulting error: " + e.getMessage(), e); continue; } } @@ -109,12 +127,12 @@ protected void setAttributes(Object target, Map attributes, Set< setter.invoke(target, value); } catch (Exception e) { logger.error("Unable to set property '" + entry.getKey() + "' to '" + entry.getValue() + "' on " - + target.getClass().getName() + " " + e.getMessage(), e); + + target.getClass().getName() + " " + e.getMessage(), e); } } } - private Integer parseInteger(Entry entry) { + private static Integer parseInteger(Map.Entry entry) { Integer value; String stringValue = (String) entry.getValue(); if (stringValue != null && stringValue.length() > 0) { @@ -126,7 +144,7 @@ private Integer parseInteger(Entry entry) { } @SuppressWarnings("unchecked") - private Map parseMap(Map.Entry entry) { + private static Map parseMap(Map.Entry entry) { Map value; if (entry.getValue() instanceof List) { List list = (List) entry.getValue(); @@ -140,7 +158,7 @@ private Map parseMap(Map.Entry entry) { } @SuppressWarnings("unchecked") - private Object parseString(Map.Entry entry) { + private static Object parseString(Map.Entry entry) { Object value; value = entry.getValue(); if (AstUtil.isNull(value)) { @@ -159,7 +177,7 @@ private Object parseString(Map.Entry entry) { return value; } - private Double parseDouble(Map.Entry entry) { + private static Double parseDouble(Map.Entry entry) { Double value; String stringValue = (String) entry.getValue(); if (stringValue != null && stringValue.length() > 0) { @@ -170,7 +188,7 @@ private Double parseDouble(Map.Entry entry) { return value; } - private Long parseLong(Map.Entry entry) { + private static Long parseLong(Map.Entry entry) { Long value; String stringValue = (String) entry.getValue(); if (stringValue != null && stringValue.length() > 0) { @@ -181,7 +199,7 @@ private Long parseLong(Map.Entry entry) { return value; } - private Map buildMap(String... lines) { + private static Map buildMap(String... lines) { if (lines == null) { return null; } diff --git a/src/test/java/org/asteriskjava/manager/event/AgiExecStartEventTest.java b/src/test/java/org/asteriskjava/manager/event/AgiExecStartEventTest.java new file mode 100644 index 000000000..53861dff8 --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/AgiExecStartEventTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class AgiExecStartEventTest { + @Test + void shouldCreateEvent() { + //given + AgiExecStartEvent agiExecStartEvent = new AgiExecStartEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("linkedid", "1617757665.32"); + attributes.put("language", "en"); + + //when + setAttributes(agiExecStartEvent, attributes, new HashSet<>()); + + //then + assertThat(agiExecStartEvent.getLinkedid()).isEqualTo("1617757665.32"); + assertThat(agiExecStartEvent.getLanguage()).isEqualTo("en"); + } +} From 5cc44324a8919802ac12628010dbcae65cdf0d7e Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Mon, 14 Nov 2022 23:10:46 +0100 Subject: [PATCH 558/802] Add missing properties to ChanSpyStopEvent --- .../manager/event/ChanSpyStopEvent.java | 260 ++++++++++++------ .../manager/event/ChanSpyStopEventTest.java | 68 +++++ 2 files changed, 237 insertions(+), 91 deletions(-) create mode 100644 src/test/java/org/asteriskjava/manager/event/ChanSpyStopEventTest.java diff --git a/src/main/java/org/asteriskjava/manager/event/ChanSpyStopEvent.java b/src/main/java/org/asteriskjava/manager/event/ChanSpyStopEvent.java index e6ee38d8e..872cb74d6 100644 --- a/src/main/java/org/asteriskjava/manager/event/ChanSpyStopEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ChanSpyStopEvent.java @@ -1,200 +1,278 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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.manager.event; - public class ChanSpyStopEvent extends ManagerEvent { - /** - * Serial version identifier - */ private static final long serialVersionUID = 3256725065466000696L; - /** - * The name of the channel. - */ - private String spyeechannel; - - private String spyerUniqueId; - private String spyerLinkedId; + private String spyerChannel; private Integer spyerChannelState; - private Integer spyerPriority; - private String spyerContext; - private String spyerLanguage; private String spyerChannelStateDesc; - private String spyerExten; private String spyerCallerIdNum; + private String spyerCallerIdName; private String spyerConnectedLineNum; private String spyerConnectedLineName; - private String spyerCallerIdName; - private String spyerChannel; + private String spyerLanguage; + private String spyerAccountCode; + private String spyerContext; + private String spyerExten; + private Integer spyerPriority; + private String spyerUniqueId; + private String spyerLinkedId; + private String spyeeChannel; + private Integer spyeeChannelState; + private String spyeeChannelStateDesc; + private String spyeeCallerIdNum; + private String spyeeCallerIdName; + private String spyeeConnectedLineNum; + private String spyeeConnectedLineName; + private String spyeeLanguage; + private String spyeeAccountCode; + private String spyeeContext; + private String spyeeExten; + private Integer spyeePriority; + private String spyeeUniqueId; + private String spyeeLinkedId; public ChanSpyStopEvent(Object source) { super(source); } - - public String getSpyeeChannel() { - return spyeechannel; + public String getSpyerChannel() { + return spyerChannel; } - public void setSpyeeChannel(String channel) { - this.spyeechannel = channel; + public void setSpyerChannel(String spyerChannel) { + this.spyerChannel = spyerChannel; } - - public String getSpyeechannel() { - return spyeechannel; + public Integer getSpyerChannelState() { + return spyerChannelState; } - - public void setSpyeechannel(String spyeechannel) { - this.spyeechannel = spyeechannel; + public void setSpyerChannelState(Integer spyerChannelState) { + this.spyerChannelState = spyerChannelState; } - - public String getSpyerUniqueId() { - return spyerUniqueId; + public String getSpyerChannelStateDesc() { + return spyerChannelStateDesc; } - - public void setSpyerUniqueId(String spyerUniqueId) { - this.spyerUniqueId = spyerUniqueId; + public void setSpyerChannelStateDesc(String spyerChannelStateDesc) { + this.spyerChannelStateDesc = spyerChannelStateDesc; } - - public String getSpyerLinkedId() { - return spyerLinkedId; + public String getSpyerCallerIdNum() { + return spyerCallerIdNum; } + public void setSpyerCallerIdNum(String spyerCallerIdNum) { + this.spyerCallerIdNum = spyerCallerIdNum; + } - public void setSpyerLinkedId(String spyerLinkedId) { - this.spyerLinkedId = spyerLinkedId; + public String getSpyerCallerIdName() { + return spyerCallerIdName; } + public void setSpyerCallerIdName(String spyerCallerIdName) { + this.spyerCallerIdName = spyerCallerIdName; + } - public Integer getSpyerChannelState() { - return spyerChannelState; + public String getSpyerConnectedLineNum() { + return spyerConnectedLineNum; } + public void setSpyerConnectedLineNum(String spyerConnectedLineNum) { + this.spyerConnectedLineNum = spyerConnectedLineNum; + } - public void setSpyerChannelState(Integer spyerChannelState) { - this.spyerChannelState = spyerChannelState; + public String getSpyerConnectedLineName() { + return spyerConnectedLineName; } + public void setSpyerConnectedLineName(String spyerConnectedLineName) { + this.spyerConnectedLineName = spyerConnectedLineName; + } - public Integer getSpyerPriority() { - return spyerPriority; + public String getSpyerLanguage() { + return spyerLanguage; } + public void setSpyerLanguage(String spyerLanguage) { + this.spyerLanguage = spyerLanguage; + } - public void setSpyerPriority(Integer spyerPriority) { - this.spyerPriority = spyerPriority; + public String getSpyerAccountCode() { + return spyerAccountCode; } + public void setSpyerAccountCode(String spyerAccountCode) { + this.spyerAccountCode = spyerAccountCode; + } public String getSpyerContext() { return spyerContext; } - public void setSpyerContext(String spyerContext) { this.spyerContext = spyerContext; } + public String getSpyerExten() { + return spyerExten; + } - public String getSpyerLanguage() { - return spyerLanguage; + public void setSpyerExten(String spyerExten) { + this.spyerExten = spyerExten; } + public Integer getSpyerPriority() { + return spyerPriority; + } - public void setSpyerLanguage(String spyerLanguage) { - this.spyerLanguage = spyerLanguage; + public void setSpyerPriority(Integer spyerPriority) { + this.spyerPriority = spyerPriority; } + public String getSpyerUniqueId() { + return spyerUniqueId; + } - public String getSpyerChannelStateDesc() { - return spyerChannelStateDesc; + public void setSpyerUniqueId(String spyerUniqueId) { + this.spyerUniqueId = spyerUniqueId; } + public String getSpyerLinkedId() { + return spyerLinkedId; + } - public void setSpyerChannelStateDesc(String spyerChannelStateDesc) { - this.spyerChannelStateDesc = spyerChannelStateDesc; + public void setSpyerLinkedId(String spyerLinkedId) { + this.spyerLinkedId = spyerLinkedId; } + public String getSpyeeChannel() { + return spyeeChannel; + } - public String getSpyerExten() { - return spyerExten; + public void setSpyeeChannel(String spyeeChannel) { + this.spyeeChannel = spyeeChannel; + } + + public Integer getSpyeeChannelState() { + return spyeeChannelState; } + public void setSpyeeChannelState(Integer spyeeChannelState) { + this.spyeeChannelState = spyeeChannelState; + } - public void setSpyerExten(String spyerExten) { - this.spyerExten = spyerExten; + public String getSpyeeChannelStateDesc() { + return spyeeChannelStateDesc; } + public void setSpyeeChannelStateDesc(String spyeeChannelStateDesc) { + this.spyeeChannelStateDesc = spyeeChannelStateDesc; + } - public String getSpyerCallerIdNum() { - return spyerCallerIdNum; + public String getSpyeeCallerIdNum() { + return spyeeCallerIdNum; } + public void setSpyeeCallerIdNum(String spyeeCallerIdNum) { + this.spyeeCallerIdNum = spyeeCallerIdNum; + } - public void setSpyerCallerIdNum(String spyerCallerIdNum) { - this.spyerCallerIdNum = spyerCallerIdNum; + public String getSpyeeCallerIdName() { + return spyeeCallerIdName; } + public void setSpyeeCallerIdName(String spyeeCallerIdName) { + this.spyeeCallerIdName = spyeeCallerIdName; + } - public String getSpyerConnectedLineNum() { - return spyerConnectedLineNum; + public String getSpyeeConnectedLineNum() { + return spyeeConnectedLineNum; } + public void setSpyeeConnectedLineNum(String spyeeConnectedLineNum) { + this.spyeeConnectedLineNum = spyeeConnectedLineNum; + } - public void setSpyerConnectedLineNum(String spyerConnectedLineNum) { - this.spyerConnectedLineNum = spyerConnectedLineNum; + public String getSpyeeConnectedLineName() { + return spyeeConnectedLineName; } + public void setSpyeeConnectedLineName(String spyeeConnectedLineName) { + this.spyeeConnectedLineName = spyeeConnectedLineName; + } - public String getSpyerConnectedLineName() { - return spyerConnectedLineName; + public String getSpyeeLanguage() { + return spyeeLanguage; } + public void setSpyeeLanguage(String spyeeLanguage) { + this.spyeeLanguage = spyeeLanguage; + } - public void setSpyerConnectedLineName(String spyerConnectedLineName) { - this.spyerConnectedLineName = spyerConnectedLineName; + public String getSpyeeAccountCode() { + return spyeeAccountCode; } + public void setSpyeeAccountCode(String spyeeAccountCode) { + this.spyeeAccountCode = spyeeAccountCode; + } - public String getSpyerCallerIdName() { - return spyerCallerIdName; + public String getSpyeeContext() { + return spyeeContext; } + public void setSpyeeContext(String spyeeContext) { + this.spyeeContext = spyeeContext; + } - public void setSpyerCallerIdName(String spyerCallerIdName) { - this.spyerCallerIdName = spyerCallerIdName; + public String getSpyeeExten() { + return spyeeExten; } + public void setSpyeeExten(String spyeeExten) { + this.spyeeExten = spyeeExten; + } - public String getSpyerChannel() { - return spyerChannel; + public Integer getSpyeePriority() { + return spyeePriority; } + public void setSpyeePriority(Integer spyeePriority) { + this.spyeePriority = spyeePriority; + } - public void setSpyerChannel(String spyerChannel) { - this.spyerChannel = spyerChannel; + public String getSpyeeUniqueId() { + return spyeeUniqueId; } + public void setSpyeeUniqueId(String spyeeUniqueId) { + this.spyeeUniqueId = spyeeUniqueId; + } + + public String getSpyeeLinkedId() { + return spyeeLinkedId; + } + public void setSpyeeLinkedId(String spyeeLinkedId) { + this.spyeeLinkedId = spyeeLinkedId; + } } diff --git a/src/test/java/org/asteriskjava/manager/event/ChanSpyStopEventTest.java b/src/test/java/org/asteriskjava/manager/event/ChanSpyStopEventTest.java new file mode 100644 index 000000000..84046ce1c --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/ChanSpyStopEventTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.asteriskjava.manager.util.EventAttributesHelper; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class ChanSpyStopEventTest { + @Test + void shouldCreateEvent() { + //given + ChanSpyStopEvent chanSpyStopEvent = new ChanSpyStopEvent(new Object()); + Map attributes = new HashMap<>(); + attributes.put("spyeechannelstate", ""); + attributes.put("spyeeconnectedlinename", ""); + attributes.put("spyeelinkedid", "out-87066661337-009277"); + attributes.put("spyeelanguage", "en"); + attributes.put("spyeecontext", "cce"); + attributes.put("spyeeuniqueid", "out-87066661337-009277"); + attributes.put("spyeeconnectedlinenum", ""); + attributes.put("spyeecalleridnum", "87066661337"); + attributes.put("spyeraccountcode", ""); + attributes.put("spyeechannelstatedesc", "Up"); + attributes.put("spyeepriority", "1"); + attributes.put("spyeeaccountcode", ""); + attributes.put("spyeecalleridname", ""); + attributes.put("spyeeexten", "87066661337"); + + //when + EventAttributesHelper.setAttributes(chanSpyStopEvent, attributes, new HashSet<>()); + + //then + assertThat(chanSpyStopEvent.getSpyerAccountCode()).isEqualTo(""); + + assertThat(chanSpyStopEvent.getSpyeeChannelState()).isNull(); + assertThat(chanSpyStopEvent.getSpyeeConnectedLineName()).isNull(); + assertThat(chanSpyStopEvent.getSpyeeLinkedId()).isEqualTo("out-87066661337-009277"); + assertThat(chanSpyStopEvent.getSpyeeLanguage()).isEqualTo("en"); + assertThat(chanSpyStopEvent.getSpyeeUniqueId()).isEqualTo("out-87066661337-009277"); + assertThat(chanSpyStopEvent.getSpyeeConnectedLineNum()).isNull(); + assertThat(chanSpyStopEvent.getSpyeeCallerIdNum()).isEqualTo("87066661337"); + assertThat(chanSpyStopEvent.getSpyeeCallerIdName()).isNull(); + assertThat(chanSpyStopEvent.getSpyeeChannelStateDesc()).isEqualTo("Up"); + assertThat(chanSpyStopEvent.getSpyeePriority()).isEqualTo(1); + assertThat(chanSpyStopEvent.getSpyeeAccountCode()).isEqualTo(""); + assertThat(chanSpyStopEvent.getSpyeeCallerIdName()).isNull(); + assertThat(chanSpyStopEvent.getSpyeeExten()).isEqualTo("87066661337"); + } +} From 202e8fb92cc9514802ba34a360bf0bdf38dac7d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Nov 2022 02:00:49 +0000 Subject: [PATCH 559/802] Bump mockito-core from 4.8.1 to 4.9.0 Bumps [mockito-core](https://github.com/mockito/mockito) from 4.8.1 to 4.9.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.8.1...v4.9.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bdd2ceb55..151cbddba 100644 --- a/pom.xml +++ b/pom.xml @@ -126,7 +126,7 @@ org.mockito mockito-core - 4.8.1 + 4.9.0 test From 5ee9f0dbcbfd7c7b196fea20bd0911dadf20a561 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Tue, 15 Nov 2022 17:46:12 +0100 Subject: [PATCH 560/802] Add ChannelTalkingStartEvent and ChannelTalkingStopEvent events --- .../event/AbstractChannelTalkingEvent.java | 59 +++++++++++++++++++ .../event/ChannelTalkingStartEvent.java | 22 +++++++ .../event/ChannelTalkingStopEvent.java | 32 ++++++++++ .../event/ChannelTalkingStartEventTest.java | 53 +++++++++++++++++ .../event/ChannelTalkingStopEventTest.java | 55 +++++++++++++++++ 5 files changed, 221 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/event/AbstractChannelTalkingEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/ChannelTalkingStartEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/ChannelTalkingStopEvent.java create mode 100644 src/test/java/org/asteriskjava/manager/event/ChannelTalkingStartEventTest.java create mode 100644 src/test/java/org/asteriskjava/manager/event/ChannelTalkingStopEventTest.java diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractChannelTalkingEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractChannelTalkingEvent.java new file mode 100644 index 000000000..e2a278ab6 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/AbstractChannelTalkingEvent.java @@ -0,0 +1,59 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +public abstract class AbstractChannelTalkingEvent extends ManagerEvent { + private String language; + private String accountCode; + private String uniqueId; + private String linkedId; + + public AbstractChannelTalkingEvent(Object source) { + super(source); + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getAccountCode() { + return accountCode; + } + + public void setAccountCode(String accountCode) { + this.accountCode = accountCode; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } + + public String getLinkedId() { + return linkedId; + } + + public void setLinkedId(String linkedId) { + this.linkedId = linkedId; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/ChannelTalkingStartEvent.java b/src/main/java/org/asteriskjava/manager/event/ChannelTalkingStartEvent.java new file mode 100644 index 000000000..e305d69f3 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/ChannelTalkingStartEvent.java @@ -0,0 +1,22 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +public class ChannelTalkingStartEvent extends AbstractChannelTalkingEvent { + public ChannelTalkingStartEvent(Object source) { + super(source); + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/ChannelTalkingStopEvent.java b/src/main/java/org/asteriskjava/manager/event/ChannelTalkingStopEvent.java new file mode 100644 index 000000000..6e0968e5d --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/ChannelTalkingStopEvent.java @@ -0,0 +1,32 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +public class ChannelTalkingStopEvent extends AbstractChannelTalkingEvent { + private Long duration; + + public ChannelTalkingStopEvent(Object source) { + super(source); + } + + public Long getDuration() { + return duration; + } + + public void setDuration(Long duration) { + this.duration = duration; + } +} diff --git a/src/test/java/org/asteriskjava/manager/event/ChannelTalkingStartEventTest.java b/src/test/java/org/asteriskjava/manager/event/ChannelTalkingStartEventTest.java new file mode 100644 index 000000000..b51997795 --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/ChannelTalkingStartEventTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class ChannelTalkingStartEventTest { + @Test + void shouldCreateEvent() { + //given + ChannelTalkingStartEvent channelTalkingStartEvent = new ChannelTalkingStartEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("language", "en"); + attributes.put("accountcode", ""); + attributes.put("context", "phones"); + attributes.put("exten", "5"); + attributes.put("priority", "4"); + attributes.put("uniqueid", "1547252114.0"); + attributes.put("linkedid", "1547252114.0"); + + //when + setAttributes(channelTalkingStartEvent, attributes, new HashSet<>()); + + //then + assertThat(channelTalkingStartEvent.getLanguage()).isEqualTo("en"); + assertThat(channelTalkingStartEvent.getAccountCode()).isEqualTo(""); + assertThat(channelTalkingStartEvent.getContext()).isEqualTo("phones"); + assertThat(channelTalkingStartEvent.getExten()).isEqualTo("5"); + assertThat(channelTalkingStartEvent.getPriority()).isEqualTo(4); + assertThat(channelTalkingStartEvent.getUniqueId()).isEqualTo("1547252114.0"); + assertThat(channelTalkingStartEvent.getLinkedId()).isEqualTo("1547252114.0"); + } +} diff --git a/src/test/java/org/asteriskjava/manager/event/ChannelTalkingStopEventTest.java b/src/test/java/org/asteriskjava/manager/event/ChannelTalkingStopEventTest.java new file mode 100644 index 000000000..db0115041 --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/ChannelTalkingStopEventTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class ChannelTalkingStopEventTest { + @Test + void shouldCreateEvent() { + //given + ChannelTalkingStopEvent channelTalkingStopEvent = new ChannelTalkingStopEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("language", "en"); + attributes.put("accountcode", ""); + attributes.put("context", "phones"); + attributes.put("exten", "5"); + attributes.put("priority", "4"); + attributes.put("uniqueid", "1547252114.0"); + attributes.put("linkedid", "1547252114.0"); + attributes.put("duration", "6030"); + + //when + setAttributes(channelTalkingStopEvent, attributes, new HashSet<>()); + + //then + assertThat(channelTalkingStopEvent.getLanguage()).isEqualTo("en"); + assertThat(channelTalkingStopEvent.getAccountCode()).isEqualTo(""); + assertThat(channelTalkingStopEvent.getContext()).isEqualTo("phones"); + assertThat(channelTalkingStopEvent.getExten()).isEqualTo("5"); + assertThat(channelTalkingStopEvent.getPriority()).isEqualTo(4); + assertThat(channelTalkingStopEvent.getUniqueId()).isEqualTo("1547252114.0"); + assertThat(channelTalkingStopEvent.getLinkedId()).isEqualTo("1547252114.0"); + assertThat(channelTalkingStopEvent.getDuration()).isEqualTo(6030); + } +} From b6a4090dbeac32facd6c7f9ff89c9feaa0a9e3d7 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Tue, 15 Nov 2022 18:00:41 +0100 Subject: [PATCH 561/802] Add tests for AgentConnectEvent --- .../manager/event/AgentConnectEventTest.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/test/java/org/asteriskjava/manager/event/AgentConnectEventTest.java diff --git a/src/test/java/org/asteriskjava/manager/event/AgentConnectEventTest.java b/src/test/java/org/asteriskjava/manager/event/AgentConnectEventTest.java new file mode 100644 index 000000000..16cab6772 --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/AgentConnectEventTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class AgentConnectEventTest { + @Test + void shouldCreateEvent() { + //given + AgentConnectEvent agentConnectEvent = new AgentConnectEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("destexten", "600"); + attributes.put("destaccountcode", "441142993721"); + attributes.put("destchannelstatedesc", "Up"); + attributes.put("channelstate", "4"); + attributes.put("destuniqueid", ""); + attributes.put("calleridname", ""); + attributes.put("destconnectedlinename", ""); + attributes.put("destcalleridname", "202"); + attributes.put("priority", "4"); + attributes.put("destcalleridnum", "202"); + attributes.put("exten", "600"); + attributes.put("accountcode", ""); + attributes.put("connectedlinenum", "202"); + attributes.put("calleridnum", "07800656909"); + attributes.put("destpriority", "1"); + attributes.put("destcontext", ""); + attributes.put("channelstatedesc", "Ring"); + attributes.put("destchannel", ""); + attributes.put("connectedlinename", "202"); + attributes.put("destchannelstate", "6"); + attributes.put("destconnectedlinenum", ""); + attributes.put("interface", ""); + attributes.put("context", ""); + + //when + setAttributes(agentConnectEvent, attributes, new HashSet<>()); + + //then + assertThat(agentConnectEvent.getDestExten()).isEqualTo("600"); + assertThat(agentConnectEvent.getDestAccountCode()).isEqualTo("441142993721"); + assertThat(agentConnectEvent.getDestChannelStateDesc()).isEqualTo("Up"); + assertThat(agentConnectEvent.getChannelState()).isEqualTo(4); + assertThat(agentConnectEvent.getDestUniqueId()).isEqualTo(""); + assertThat(agentConnectEvent.getCallerIdName()).isEqualTo(""); + assertThat(agentConnectEvent.getDestConnectedLineName()).isEqualTo(""); + assertThat(agentConnectEvent.getDestCallerIdName()).isEqualTo("202"); + assertThat(agentConnectEvent.getPriority()).isEqualTo(4); + assertThat(agentConnectEvent.getDestCallerIdNum()).isEqualTo("202"); + assertThat(agentConnectEvent.getExten()).isEqualTo("600"); + assertThat(agentConnectEvent.getAccountcode()).isEqualTo(""); + assertThat(agentConnectEvent.getConnectedLineNum()).isEqualTo("202"); + assertThat(agentConnectEvent.getCallerIdNum()).isEqualTo("07800656909"); + assertThat(agentConnectEvent.getDestPriority()).isEqualTo("1"); + assertThat(agentConnectEvent.getDestContext()).isEqualTo(""); + assertThat(agentConnectEvent.getChannelStateDesc()).isEqualTo("Ring"); + assertThat(agentConnectEvent.getDestChannel()).isEqualTo(""); + assertThat(agentConnectEvent.getConnectedLineName()).isEqualTo("202"); + assertThat(agentConnectEvent.getDestChannelState()).isEqualTo("6"); + assertThat(agentConnectEvent.getDestConnectedLineNum()).isEqualTo(""); + assertThat(agentConnectEvent.getInterface()).isEqualTo(""); + assertThat(agentConnectEvent.getContext()).isEqualTo(""); + } +} From 8d51fe8831e533933a1bf5253b00bd05ef17490d Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Tue, 15 Nov 2022 18:30:12 +0100 Subject: [PATCH 562/802] Add missing tests --- .../manager/event/BridgeCreateEventTest.java | 41 ++++++++++++++++++ .../manager/event/BridgeEnterEventTest.java | 41 ++++++++++++++++++ .../event/ConfbridgeJoinEventTest.java | 43 +++++++++++++++++++ .../event/ConfbridgeLeaveEventTest.java | 43 +++++++++++++++++++ .../manager/event/HangupEventTest.java | 43 +++++++++++++++++++ .../manager/event/HangupRequestEventTest.java | 41 ++++++++++++++++++ .../manager/event/MusicOnHoldEventTest.java | 41 ++++++++++++++++++ 7 files changed, 293 insertions(+) create mode 100644 src/test/java/org/asteriskjava/manager/event/BridgeCreateEventTest.java create mode 100644 src/test/java/org/asteriskjava/manager/event/BridgeEnterEventTest.java create mode 100644 src/test/java/org/asteriskjava/manager/event/ConfbridgeJoinEventTest.java create mode 100644 src/test/java/org/asteriskjava/manager/event/ConfbridgeLeaveEventTest.java create mode 100644 src/test/java/org/asteriskjava/manager/event/HangupEventTest.java create mode 100644 src/test/java/org/asteriskjava/manager/event/HangupRequestEventTest.java create mode 100644 src/test/java/org/asteriskjava/manager/event/MusicOnHoldEventTest.java diff --git a/src/test/java/org/asteriskjava/manager/event/BridgeCreateEventTest.java b/src/test/java/org/asteriskjava/manager/event/BridgeCreateEventTest.java new file mode 100644 index 000000000..4921541f3 --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/BridgeCreateEventTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class BridgeCreateEventTest { + @Test + void shouldCreateEvent() { + //given + BridgeCreateEvent bridgeCreateEvent = new BridgeCreateEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("bridgevideosourcemode", "none"); + + //when + setAttributes(bridgeCreateEvent, attributes, new HashSet<>()); + + //then + assertThat(bridgeCreateEvent.getBridgevideosourcemode()).isNull(); + } +} diff --git a/src/test/java/org/asteriskjava/manager/event/BridgeEnterEventTest.java b/src/test/java/org/asteriskjava/manager/event/BridgeEnterEventTest.java new file mode 100644 index 000000000..75634cdc3 --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/BridgeEnterEventTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class BridgeEnterEventTest { + @Test + void shouldCreateEvent() { + //given + BridgeEnterEvent bridgeEnterEvent = new BridgeEnterEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("swapuniqueid", "GW1-1517402850.50086"); + + //when + setAttributes(bridgeEnterEvent, attributes, new HashSet<>()); + + //then + assertThat(bridgeEnterEvent.getSwapuniqueid()).isEqualTo("GW1-1517402850.50086"); + } +} diff --git a/src/test/java/org/asteriskjava/manager/event/ConfbridgeJoinEventTest.java b/src/test/java/org/asteriskjava/manager/event/ConfbridgeJoinEventTest.java new file mode 100644 index 000000000..c2a3006a8 --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/ConfbridgeJoinEventTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class ConfbridgeJoinEventTest { + @Test + void shouldCreateEvent() { + //given + ConfbridgeJoinEvent confbridgeJoinEvent = new ConfbridgeJoinEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("language", "en"); + attributes.put("linkedid", "1474881412.1"); + + //when + setAttributes(confbridgeJoinEvent, attributes, new HashSet<>()); + + //then + assertThat(confbridgeJoinEvent.getLanguage()).isEqualTo("en"); + assertThat(confbridgeJoinEvent.getLinkedId()).isEqualTo("1474881412.1"); + } +} diff --git a/src/test/java/org/asteriskjava/manager/event/ConfbridgeLeaveEventTest.java b/src/test/java/org/asteriskjava/manager/event/ConfbridgeLeaveEventTest.java new file mode 100644 index 000000000..5d07405cb --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/ConfbridgeLeaveEventTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class ConfbridgeLeaveEventTest { + @Test + void shouldCreateEvent() { + //given + ConfbridgeLeaveEvent confbridgeLeaveEvent = new ConfbridgeLeaveEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("language", "en"); + attributes.put("linkedid", "1475486824.3"); + + //when + setAttributes(confbridgeLeaveEvent, attributes, new HashSet<>()); + + //then + assertThat(confbridgeLeaveEvent.getLanguage()).isEqualTo("en"); + assertThat(confbridgeLeaveEvent.getLinkedId()).isEqualTo("1475486824.3"); + } +} diff --git a/src/test/java/org/asteriskjava/manager/event/HangupEventTest.java b/src/test/java/org/asteriskjava/manager/event/HangupEventTest.java new file mode 100644 index 000000000..d0929c63e --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/HangupEventTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class HangupEventTest { + @ParameterizedTest + @ValueSource(strings = {"False", "762377"}) + void shouldCreateEvent(String accountCode) { + //given + HangupEvent hangupEvent = new HangupEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("accountcode", accountCode); + + //when + setAttributes(hangupEvent, attributes, new HashSet<>()); + + //then + assertThat(hangupEvent.getAccountCode()).isEqualTo(accountCode); + } +} diff --git a/src/test/java/org/asteriskjava/manager/event/HangupRequestEventTest.java b/src/test/java/org/asteriskjava/manager/event/HangupRequestEventTest.java new file mode 100644 index 000000000..bad0c3377 --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/HangupRequestEventTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class HangupRequestEventTest { + @Test + void shouldCreateEvent() { + //given + HangupRequestEvent hangupRequestEvent = new HangupRequestEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("cause", "1"); + + //when + setAttributes(hangupRequestEvent, attributes, new HashSet<>()); + + //then + assertThat(hangupRequestEvent.getCause()).isEqualTo(1); + } +} diff --git a/src/test/java/org/asteriskjava/manager/event/MusicOnHoldEventTest.java b/src/test/java/org/asteriskjava/manager/event/MusicOnHoldEventTest.java new file mode 100644 index 000000000..c4d64ee5a --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/MusicOnHoldEventTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class MusicOnHoldEventTest { + @Test + void shouldCreateEvent() { + //given + MusicOnHoldEvent musicOnHoldEvent = new MusicOnHoldEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("class", "default"); + + //when + setAttributes(musicOnHoldEvent, attributes, new HashSet<>()); + + //then + assertThat(musicOnHoldEvent.getClassName()).isEqualTo("default"); + } +} From 8192a6d8d78757c44b66921794d505d78beec9eb Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Wed, 16 Nov 2022 07:59:50 +0100 Subject: [PATCH 563/802] Add recordFile field to ConfbridgeStartRecordAction --- .../action/ConfbridgeStartRecordAction.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/action/ConfbridgeStartRecordAction.java b/src/main/java/org/asteriskjava/manager/action/ConfbridgeStartRecordAction.java index b9feec800..ff92772c1 100644 --- a/src/main/java/org/asteriskjava/manager/action/ConfbridgeStartRecordAction.java +++ b/src/main/java/org/asteriskjava/manager/action/ConfbridgeStartRecordAction.java @@ -1,3 +1,18 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.action; /** @@ -7,13 +22,13 @@ * @version $Id$ */ public class ConfbridgeStartRecordAction extends AbstractManagerAction { - /** * Serializable version identifier */ private static final long serialVersionUID = 3059632508521358701L; private String conference; + private String recordFile; /** * Creates a new empty ConfbridgeStartRecordAction. @@ -51,4 +66,11 @@ public String getConference() { return conference; } + public String getRecordFile() { + return recordFile; + } + + public void setRecordFile(String recordFile) { + this.recordFile = recordFile; + } } From be237937b442d45629db42d0ff9fd7211962e9f5 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Thu, 17 Nov 2022 08:00:26 +0100 Subject: [PATCH 564/802] Add missing fields to SipShowPeerResponse --- .../manager/response/SipShowPeerResponse.java | 75 +++++++++++++++++++ .../response/SipShowPeerResponseTest.java | 43 +++++++++++ 2 files changed, 118 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java b/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java index 7d24d85d9..1ea7987b7 100644 --- a/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/SipShowPeerResponse.java @@ -1,3 +1,18 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.response; import java.util.Map; @@ -77,6 +92,11 @@ public class SipShowPeerResponse extends ManagerResponse { private String sipRtpEngine; private String sipComedia; private String mohsuggest; + private String namedPickupgroup; + private String sipRtcpMux; + private String description; + private String subscribecontext; + private String namedCallgroup; private Map chanVariable; @@ -614,6 +634,51 @@ public void setMohsuggest(String mohsuggest) { this.mohsuggest = mohsuggest; } + public String getNamedPickupgroup() { + return namedPickupgroup; + } + + public SipShowPeerResponse setNamedPickupgroup(String namedPickupgroup) { + this.namedPickupgroup = namedPickupgroup; + return this; + } + + public String getSipRtcpMux() { + return sipRtcpMux; + } + + public SipShowPeerResponse setSipRtcpMux(String sipRtcpMux) { + this.sipRtcpMux = sipRtcpMux; + return this; + } + + public String getDescription() { + return description; + } + + public SipShowPeerResponse setDescription(String description) { + this.description = description; + return this; + } + + public String getSubscribecontext() { + return subscribecontext; + } + + public SipShowPeerResponse setSubscribecontext(String subscribecontext) { + this.subscribecontext = subscribecontext; + return this; + } + + public String getNamedCallgroup() { + return namedCallgroup; + } + + public SipShowPeerResponse setNamedCallgroup(String namedCallgroup) { + this.namedCallgroup = namedCallgroup; + return this; + } + @Override public String toString() { StringBuilder builder = new StringBuilder(); @@ -745,6 +810,16 @@ public String toString() { builder.append(chanVariable); builder.append(", mohSuggest="); builder.append(mohsuggest); + builder.append(", namedPickupgroup="); + builder.append(namedPickupgroup); + builder.append(", sipRtcpMux="); + builder.append(sipRtcpMux); + builder.append(", description="); + builder.append(description); + builder.append(", subscribecontext="); + builder.append(subscribecontext); + builder.append(", namedCallgroup="); + builder.append(namedCallgroup); builder.append("]"); return builder.toString(); } diff --git a/src/test/java/org/asteriskjava/manager/response/SipShowPeerResponseTest.java b/src/test/java/org/asteriskjava/manager/response/SipShowPeerResponseTest.java index 9d12cedd4..d886a45f3 100644 --- a/src/test/java/org/asteriskjava/manager/response/SipShowPeerResponseTest.java +++ b/src/test/java/org/asteriskjava/manager/response/SipShowPeerResponseTest.java @@ -1,8 +1,29 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.response; +import org.asteriskjava.manager.util.EventAttributesHelper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; class SipShowPeerResponseTest { @@ -13,6 +34,28 @@ void setUp() { response = new SipShowPeerResponse(); } + @Test + void shouldCreateResponse() { + //given + SipShowPeerResponse sipShowPeerResponse = new SipShowPeerResponse(); + Map attributes = new HashMap<>(); + attributes.put("named pickupgroup", ""); + attributes.put("sip-rtcp-mux", "N"); + attributes.put("description", ""); + attributes.put("subscribecontext", ""); + attributes.put("named callgroup", ""); + + //when + EventAttributesHelper.setAttributes(sipShowPeerResponse, attributes, new HashSet<>()); + + //then + assertThat(sipShowPeerResponse.getNamedPickupgroup()).isBlank(); + assertThat(sipShowPeerResponse.getSipRtcpMux()).isEqualTo("N"); + assertThat(sipShowPeerResponse.getDescription()).isBlank(); + assertThat(sipShowPeerResponse.getSubscribecontext()).isBlank(); + assertThat(sipShowPeerResponse.getNamedCallgroup()).isBlank(); + } + @Test void testSetQualifyFreq() { response.setQualifyFreq("6000 ms"); From 956eadd399bc0c909d250861f407b48f9bfe41c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Nov 2022 02:00:36 +0000 Subject: [PATCH 565/802] Bump slf4j-api from 2.0.3 to 2.0.4 Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 2.0.3 to 2.0.4. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_2.0.3...v_2.0.4) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 151cbddba..203bcd730 100644 --- a/pom.xml +++ b/pom.xml @@ -96,7 +96,7 @@ org.slf4j slf4j-api - 2.0.3 + 2.0.4 compile From b39bce6b4b9bd3ef7f336cd3d23e15fcaae5d08f Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Fri, 18 Nov 2022 07:32:40 +0100 Subject: [PATCH 566/802] Add missing tests for AttendedTransferEvent --- .../event/AttendedTransferEventTest.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/test/java/org/asteriskjava/manager/event/AttendedTransferEventTest.java diff --git a/src/test/java/org/asteriskjava/manager/event/AttendedTransferEventTest.java b/src/test/java/org/asteriskjava/manager/event/AttendedTransferEventTest.java new file mode 100644 index 000000000..c8c333418 --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/AttendedTransferEventTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2004-2022 Asterisk-Java contributors + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class AttendedTransferEventTest { + @Test + void shouldCreateEvent() { + //given + AttendedTransferEvent attendedTransferEvent = new AttendedTransferEvent(new Object()); + + Map attributes = new HashMap<>(); + attributes.put("transfertargetcalleridname", ""); + attributes.put("secondbridgevideosourcemode", "none"); + attributes.put("transfertargetlinkedid", "1668752056.12"); + attributes.put("transfertargetpriority", "1"); + attributes.put("transfertargetcalleridnum", "102"); + attributes.put("origbridgevideosourcemode", "none"); + attributes.put("transfertargetconnectedlinenum", "103"); + attributes.put("transfertargetchannel", "SIP/102-0000000d"); + attributes.put("transfertargetcontext", "phones"); + attributes.put("transfertargetconnectedlinename", "J.Doe"); + attributes.put("transfertargetexten", ""); + attributes.put("transfertargetchannelstate", "6"); + attributes.put("transfertargetlanguage", "en"); + attributes.put("transfertargetaccountcode", ""); + attributes.put("transfertargetchannelstatedesc", "Up"); + + //when + setAttributes(attendedTransferEvent, attributes, new HashSet<>()); + + //then + assertThat(attendedTransferEvent.getTransferTargetCallerIDName()).isNull(); + assertThat(attendedTransferEvent.getSecondBridgeVideoSourceMode()).isNull(); + assertThat(attendedTransferEvent.getTransferTargetLinkedID()).isEqualTo("1668752056.12"); + assertThat(attendedTransferEvent.getTransferTargetPriority()).isEqualTo("1"); + assertThat(attendedTransferEvent.getTransferTargetCallerIDNum()).isEqualTo("102"); + assertThat(attendedTransferEvent.getOrigBridgeVideoSourceMode()).isNull(); + assertThat(attendedTransferEvent.getTransferTargetConnectedLineNum()).isEqualTo("103"); + assertThat(attendedTransferEvent.getTransferTargetChannel()).isEqualTo("SIP/102-0000000d"); + assertThat(attendedTransferEvent.getTransferTargetContext()).isEqualTo("phones"); + assertThat(attendedTransferEvent.getTransferTargetConnectedLineName()).isEqualTo("J.Doe"); + assertThat(attendedTransferEvent.getTransferTargetExten()).isBlank(); + assertThat(attendedTransferEvent.getTransferTargetChannelState()).isEqualTo("6"); + assertThat(attendedTransferEvent.getTransferTargetLanguage()).isEqualTo("en"); + assertThat(attendedTransferEvent.getTransferTargetAccountCode()).isBlank(); + assertThat(attendedTransferEvent.getTransferTargetChannelStateDesc()).isEqualTo("Up"); + } +} From 86e4fe993f44746a938c07ed2fa04868471a05db Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Fri, 18 Nov 2022 17:15:33 +0100 Subject: [PATCH 567/802] Add supported AMI version for Asterisk 20 --- .../internal/ManagerConnectionImpl.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 50cc2cb26..74931d84f 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2004-2006 Stefan Reuter + * Copyright 2004-2022 Asterisk-Java contributors * - * 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 + * 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. + * 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.manager.internal; @@ -50,7 +49,7 @@ import static org.asteriskjava.manager.ManagerConnectionState.*; /** - * Internal implemention of the ManagerConnection interface. + * Internal implementation of the ManagerConnection interface. * * @author srt * @version $Id$ @@ -79,6 +78,7 @@ public class ManagerConnectionImpl extends Lockable implements ManagerConnection "5.0", // Asterisk 16 "6.0", // Asterisk 17 "7.0", // Asterisk 18 + "10.0.0", // Asterisk 20 }; private static final AtomicLong idCounter = new AtomicLong(0); From e97f87c0ee24b79b040f995e00a7c99fae74ef55 Mon Sep 17 00:00:00 2001 From: piotrooo Date: Fri, 18 Nov 2022 16:24:31 +0000 Subject: [PATCH 568/802] Update versions to 3.36.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6402b3c67..7d3b07106 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.35.0 + 3.36.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 203bcd730..515cf4ab7 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java - 3.35.0 + 3.36.0 Asterisk-Java The free Java library for Asterisk PBX integration. From 72333f16e489628af6f6b1a8b24466cb7d58ad80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Nov 2022 03:24:32 +0000 Subject: [PATCH 569/802] Bump peter-evans/create-pull-request from 4.2.0 to 4.2.1 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.2.0 to 4.2.1. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v4.2.0...v4.2.1) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7448d3566..7456e0b93 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v4.2.0 + uses: peter-evans/create-pull-request@v4.2.1 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From fd251655c2693c3424f1205740f02b43319fe05a Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Thu, 24 Nov 2022 08:24:37 +0100 Subject: [PATCH 570/802] Add support for AMI versions 8.0 used by Asterisk 19 and 9.0 used by Asterisk 20 --- .../internal/ManagerConnectionImpl.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 74931d84f..7cfbb8a7c 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -67,18 +67,18 @@ public class ManagerConnectionImpl extends Lockable implements ManagerConnection // NOTE: identifier is AMI_VERSION, defined in include/asterisk/manager.h // AMI version consists of MAJOR.BREAKING.NON-BREAKING. private static final String[] SUPPORTED_AMI_VERSIONS = { - - "2.6", // Asterisk 13 - "2.7", // Asterisk 13.2 - "2.8", // Asterisk >13.5 - "2.9", // Asterisk >13.3 - "3.1", // Asterisk =14.3 - "3.2", // Asterisk 14.4.0 - "4.0", // Asterisk 15 - "5.0", // Asterisk 16 - "6.0", // Asterisk 17 - "7.0", // Asterisk 18 - "10.0.0", // Asterisk 20 + "2.6", // Asterisk 13 + "2.7", // Asterisk 13.2 + "2.8", // Asterisk >13.5 + "2.9", // Asterisk >13.3 + "3.1", // Asterisk =14.3 + "3.2", // Asterisk 14.4.0 + "4.0", // Asterisk 15 + "5.0", // Asterisk 16 + "6.0", // Asterisk 17 + "7.0", // Asterisk 18 + "8.0", // Asterisk 19 + "9.0", // Asterisk 20 }; private static final AtomicLong idCounter = new AtomicLong(0); From b50033a1d73afa3df3f30d53196f7307e44756f8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 24 Nov 2022 08:34:24 +0100 Subject: [PATCH 571/802] Update versions to 3.36.1 (#440) Co-authored-by: piotrooo --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7d3b07106..828efd16f 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.36.0 + 3.36.1 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index 515cf4ab7..d04ababf1 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java - 3.36.0 + 3.36.1 Asterisk-Java The free Java library for Asterisk PBX integration. From 210800d6c7cf876f958ea1e65fd8f5a88196d710 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Thu, 24 Nov 2022 17:25:32 +0100 Subject: [PATCH 572/802] Add asterisk 19 and 20 as a supported versions (#441) --- .../org/asteriskjava/AsteriskVersion.java | 97 ++++++++++--------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index c23969eac..ad4e250ae 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -26,10 +26,11 @@ * @version $Id$ * @since 0.2 */ -public class AsteriskVersion implements Comparable, Serializable -{ - private static final String VERSION_PATTERN_18 = "^\\s*Asterisk (GIT-)?18[-. ].*"; - private static final String VERSION_PATTERN_17 = "^\\s*Asterisk (GIT-)?17[-. ].*"; +public class AsteriskVersion implements Comparable, Serializable { + private static final String VERSION_PATTERN_20 = "^\\s*Asterisk (GIT-)?20[-. ].*"; + private static final String VERSION_PATTERN_19 = "^\\s*Asterisk (GIT-)?19[-. ].*"; + private static final String VERSION_PATTERN_18 = "^\\s*Asterisk (GIT-)?18[-. ].*"; + private static final String VERSION_PATTERN_17 = "^\\s*Asterisk (GIT-)?17[-. ].*"; private static final String VERSION_PATTERN_16 = "^\\s*Asterisk (GIT-)?16[-. ].*"; private static final String VERSION_PATTERN_15 = "^\\s*Asterisk (GIT-)?15[-. ].*"; private static final String VERSION_PATTERN_14 = "^\\s*Asterisk (GIT-)?14[-. ].*"; @@ -121,25 +122,40 @@ public class AsteriskVersion implements Comparable, Serializabl * * @since 2.1.0 */ - public static final AsteriskVersion ASTERISK_16 = new AsteriskVersion(1600, "Asterisk 16", VERSION_PATTERN_16, - VERSION_PATTERN_CERTIFIED_16); + public static final AsteriskVersion ASTERISK_16 = new AsteriskVersion(1600, "Asterisk 16", VERSION_PATTERN_16, VERSION_PATTERN_CERTIFIED_16); - /** - * Represents the Asterisk 17 series. - * - * @since 3.7.0 - */ - public static final AsteriskVersion ASTERISK_17 = new AsteriskVersion(1700, "Asterisk 17", VERSION_PATTERN_17); + /** + * Represents the Asterisk 17 series. + * + * @since 3.7.0 + */ + public static final AsteriskVersion ASTERISK_17 = new AsteriskVersion(1700, "Asterisk 17", VERSION_PATTERN_17); + + /** + * Represents the Asterisk 18 series. + * + * @since 3.13.0 + */ + public static final AsteriskVersion ASTERISK_18 = new AsteriskVersion(1800, "Asterisk 18", VERSION_PATTERN_18); - /** - * Represents the Asterisk 18 series. - * - * @since 3.13.0 - */ - public static final AsteriskVersion ASTERISK_18 = new AsteriskVersion(1800, "Asterisk 18", VERSION_PATTERN_18); + /** + * Represents the Asterisk 19 series. + * + * @since 3.36.2 + */ + public static final AsteriskVersion ASTERISK_19 = new AsteriskVersion(1900, "Asterisk 19", VERSION_PATTERN_19); + + /** + * Represents the Asterisk 20 series. + * + * @since 3.36.2 + */ + public static final AsteriskVersion ASTERISK_20 = new AsteriskVersion(2000, "Asterisk 20", VERSION_PATTERN_20); - private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ASTERISK_18, ASTERISK_17, ASTERISK_16, ASTERISK_15, ASTERISK_14, - ASTERISK_13, ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6}; + private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ + ASTERISK_20, ASTERISK_19, ASTERISK_18, ASTERISK_17, ASTERISK_16, ASTERISK_15, ASTERISK_14, ASTERISK_13, + ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6 + }; // current debian stable version, as of 09/10/2018 public static final AsteriskVersion DEFAULT_VERSION = ASTERISK_16; @@ -149,15 +165,13 @@ public class AsteriskVersion implements Comparable, Serializabl */ private static final long serialVersionUID = 1L; - private AsteriskVersion(int version, String versionString, String... patterns) - { + private AsteriskVersion(int version, String versionString, String... patterns) { this.version = version; this.versionString = versionString; this.patterns = new Pattern[patterns.length]; int i = 0; - for (String pattern : patterns) - { + for (String pattern : patterns) { this.patterns[i++] = Pattern.compile(pattern); } } @@ -168,27 +182,22 @@ private AsteriskVersion(int version, String versionString, String... patterns) * * @param o the version to compare to * @return true if this version is equal to or higher than the - * given version, false otherwise. + * given version, false otherwise. */ - public boolean isAtLeast(AsteriskVersion o) - { + public boolean isAtLeast(AsteriskVersion o) { return version >= o.version; } - public int compareTo(AsteriskVersion o) - { + public int compareTo(AsteriskVersion o) { return Integer.compare(version, o.version); } @Override - public boolean equals(Object o) - { - if (this == o) - { + public boolean equals(Object o) { + if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) - { + if (o == null || getClass() != o.getClass()) { return false; } @@ -198,14 +207,12 @@ public boolean equals(Object o) } @Override - public int hashCode() - { + public int hashCode() { return version; } @Override - public String toString() - { + public String toString() { return versionString; } @@ -216,14 +223,10 @@ public String toString() * @param coreLine * @return the detected version, or null if unknown */ - public static AsteriskVersion getDetermineVersionFromString(String coreLine) - { - for (AsteriskVersion version : knownVersions) - { - for (Pattern pattern : version.patterns) - { - if (pattern.matcher(coreLine).matches()) - { + public static AsteriskVersion getDetermineVersionFromString(String coreLine) { + for (AsteriskVersion version : knownVersions) { + for (Pattern pattern : version.patterns) { + if (pattern.matcher(coreLine).matches()) { return version; } } From bf1c7b00dd19de4afdfb39731b4fe4323bc03f5c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Nov 2022 07:34:36 +0100 Subject: [PATCH 573/802] Bump peter-evans/create-pull-request from 4.2.1 to 4.2.2 (#442) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.2.1 to 4.2.2. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v4.2.1...v4.2.2) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7456e0b93..06485fad0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v4.2.1 + uses: peter-evans/create-pull-request@v4.2.2 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From 1db611ed36bbe6b90bcf51282e1b6e66c49fb95c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 25 Nov 2022 18:10:43 +0100 Subject: [PATCH 574/802] Update versions to 3.37.0 (#443) Co-authored-by: piotrooo --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 828efd16f..cb768a53d 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.36.1 + 3.37.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index d04ababf1..b4fd524ba 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java - 3.36.1 + 3.37.0 Asterisk-Java The free Java library for Asterisk PBX integration. From 9ef44422b64689381297c6ca4c618ca36e201626 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Nov 2022 18:29:05 +0100 Subject: [PATCH 575/802] Bump peter-evans/create-pull-request from 4.2.2 to 4.2.3 (#445) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.2.2 to 4.2.3. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v4.2.2...v4.2.3) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 06485fad0..e3711f4a3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v4.2.2 + uses: peter-evans/create-pull-request@v4.2.3 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From 82b313d4f49171c33cc253130d64157285a41022 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Nov 2022 18:29:55 +0100 Subject: [PATCH 576/802] Bump slf4j-api from 2.0.4 to 2.0.5 (#444) Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 2.0.4 to 2.0.5. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_2.0.4...v_2.0.5) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b4fd524ba..04a30460a 100644 --- a/pom.xml +++ b/pom.xml @@ -96,7 +96,7 @@ org.slf4j slf4j-api - 2.0.4 + 2.0.5 compile From d2caeed9b9499a58d1e0feeef968bde7d0b87e3a Mon Sep 17 00:00:00 2001 From: Christof Lauber Date: Wed, 30 Nov 2022 18:30:37 +0100 Subject: [PATCH 577/802] Add asterisk 18 certified a supported version (#446) (#447) Co-authored-by: Christof Lauber --- src/main/java/org/asteriskjava/AsteriskVersion.java | 3 ++- src/test/java/org/asteriskjava/AsteriskVersionTest.java | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index ad4e250ae..04c9b103a 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -39,6 +39,7 @@ public class AsteriskVersion implements Comparable, Serializabl private final String versionString; private final Pattern patterns[]; + private static final String VERSION_PATTERN_CERTIFIED_18 = "^\\s*Asterisk certified/(GIT-)?18[-. ].*"; private static final String VERSION_PATTERN_CERTIFIED_16 = "^\\s*Asterisk certified/(GIT-)?16[-. ].*"; private static final String VERSION_PATTERN_CERTIFIED_13 = "^\\s*Asterisk certified/((SVN-branch|GIT)-)?13[-. ].*"; @@ -136,7 +137,7 @@ public class AsteriskVersion implements Comparable, Serializabl * * @since 3.13.0 */ - public static final AsteriskVersion ASTERISK_18 = new AsteriskVersion(1800, "Asterisk 18", VERSION_PATTERN_18); + public static final AsteriskVersion ASTERISK_18 = new AsteriskVersion(1800, "Asterisk 18", VERSION_PATTERN_18, VERSION_PATTERN_CERTIFIED_18); /** * Represents the Asterisk 19 series. diff --git a/src/test/java/org/asteriskjava/AsteriskVersionTest.java b/src/test/java/org/asteriskjava/AsteriskVersionTest.java index 8e3255528..24f28bace 100644 --- a/src/test/java/org/asteriskjava/AsteriskVersionTest.java +++ b/src/test/java/org/asteriskjava/AsteriskVersionTest.java @@ -31,5 +31,8 @@ void test15() { void test18() { assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 18.1.0").equals(AsteriskVersion.ASTERISK_18)); } - + @Test + void testCertified18() { + assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk certified/18.9-cert2").equals(AsteriskVersion.ASTERISK_18)); + } } From e3ed51adef6cb85775c8dd4aa60df1ad8860247c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Dec 2022 07:29:34 +0100 Subject: [PATCH 578/802] Bump bnd-maven-plugin from 6.3.1 to 6.4.0 (#448) Bumps [bnd-maven-plugin](https://github.com/bndtools/bnd) from 6.3.1 to 6.4.0. - [Release notes](https://github.com/bndtools/bnd/releases) - [Changelog](https://github.com/bndtools/bnd/blob/master/docs/ADDING_RELEASE_DOCS.md) - [Commits](https://github.com/bndtools/bnd/compare/6.3.1...6.4.0) --- updated-dependencies: - dependency-name: biz.aQute.bnd:bnd-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 04a30460a..7ea627691 100644 --- a/pom.xml +++ b/pom.xml @@ -155,7 +155,7 @@ biz.aQute.bnd bnd-maven-plugin - 6.3.1 + 6.4.0 From 7562c7255dd24a82df6cd6e681a1d908535a81ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Dec 2022 07:30:13 +0100 Subject: [PATCH 579/802] Bump actions/setup-java from 3.6.0 to 3.7.0 (#449) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3.6.0 to 3.7.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3.6.0...v3.7.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a06c36870..0e12265e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v3.6.0 + uses: actions/setup-java@v3.7.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e3711f4a3..1a20b4833 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v3.1.0 - name: Set up Java - uses: actions/setup-java@v3.6.0 + uses: actions/setup-java@v3.7.0 with: java-version: 8 distribution: temurin From c76d359ac7185ed9bbe0b6e5f128b22a182451e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Dec 2022 08:36:19 +0100 Subject: [PATCH 580/802] Bump actions/setup-java from 3.7.0 to 3.9.0 (#454) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3.7.0 to 3.9.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3.7.0...v3.9.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e12265e6..d89bd8016 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v3.7.0 + uses: actions/setup-java@v3.9.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1a20b4833..f8a526c65 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v3.1.0 - name: Set up Java - uses: actions/setup-java@v3.7.0 + uses: actions/setup-java@v3.9.0 with: java-version: 8 distribution: temurin From f72be1b182ba792a9323254b42a69b744c37816c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Dec 2022 08:38:47 +0100 Subject: [PATCH 581/802] Bump actions/checkout from 3.1.0 to 3.2.0 (#452) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.1.0...v3.2.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d89bd8016..01806b2be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v3.1.0 + uses: actions/checkout@v3.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f8a526c65..009006b06 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.1.0 + uses: actions/checkout@v3.2.0 - name: Set up Java uses: actions/setup-java@v3.9.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.1.0 + uses: actions/checkout@v3.2.0 with: ref: master fetch-depth: 0 From e14ab24c6913365c727f5e66f21165588be850cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Dec 2022 08:39:44 +0100 Subject: [PATCH 582/802] Bump mockito-core from 4.9.0 to 4.10.0 (#453) Bumps [mockito-core](https://github.com/mockito/mockito) from 4.9.0 to 4.10.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.9.0...v4.10.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7ea627691..968964d20 100644 --- a/pom.xml +++ b/pom.xml @@ -126,7 +126,7 @@ org.mockito mockito-core - 4.9.0 + 4.10.0 test From 303901083157d09e8a70e5f72f2161dab02a9c2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Dec 2022 08:40:12 +0100 Subject: [PATCH 583/802] Bump slf4j-api from 2.0.5 to 2.0.6 (#451) Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 2.0.5 to 2.0.6. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_2.0.5...v_2.0.6) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 968964d20..77c740049 100644 --- a/pom.xml +++ b/pom.xml @@ -96,7 +96,7 @@ org.slf4j slf4j-api - 2.0.5 + 2.0.6 compile From c86f695617e041d67ad05ca8910fe30aff48cfcf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Jan 2023 07:13:06 +0100 Subject: [PATCH 584/802] Bump assertj-core from 3.23.1 to 3.24.2 (#463) Bumps assertj-core from 3.23.1 to 3.24.2. --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 77c740049..01d920c41 100644 --- a/pom.xml +++ b/pom.xml @@ -120,7 +120,7 @@ org.assertj assertj-core - 3.23.1 + 3.24.2 test From 9eead3e582f49edd54989adb0acbd310dafd92e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Jan 2023 07:13:22 +0100 Subject: [PATCH 585/802] Bump junit-jupiter from 5.9.1 to 5.9.2 (#460) Bumps [junit-jupiter](https://github.com/junit-team/junit5) from 5.9.1 to 5.9.2. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.1...r5.9.2) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 01d920c41..707d4c86c 100644 --- a/pom.xml +++ b/pom.xml @@ -114,7 +114,7 @@ org.junit.jupiter junit-jupiter - 5.9.1 + 5.9.2 test From fc7776936e55c4b821f6598589aaf54e34a4ce74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Jan 2023 07:13:43 +0100 Subject: [PATCH 586/802] Bump release-drafter/release-drafter from 5.21.1 to 5.22.0 (#456) Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.21.1 to 5.22.0. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v5.21.1...v5.22.0) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 6daabb9c6..5d5dba7f2 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -14,7 +14,7 @@ jobs: contents: write # for release-drafter to create a GitHub release runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v5.21.1 + - uses: release-drafter/release-drafter@v5.22.0 with: config-name: release-drafter-master.yml env: From 98ae4ed70506ba463a4af918d4c1aabfeaa3c164 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Jan 2023 07:13:59 +0100 Subject: [PATCH 587/802] Bump actions/checkout from 3.2.0 to 3.3.0 (#458) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.2.0...v3.3.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01806b2be..f97669add 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v3.2.0 + uses: actions/checkout@v3.3.0 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 009006b06..9338b2968 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.2.0 + uses: actions/checkout@v3.3.0 - name: Set up Java uses: actions/setup-java@v3.9.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.2.0 + uses: actions/checkout@v3.3.0 with: ref: master fetch-depth: 0 From e4de10deb218f96a2d5507384e9c1fc63328fc2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 07:25:42 +0100 Subject: [PATCH 588/802] Bump maven-surefire-plugin from 3.0.0-M7 to 3.0.0-M8 (#461) Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.0.0-M7 to 3.0.0-M8. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0-M7...surefire-3.0.0-M8) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 707d4c86c..fe6e80e2f 100644 --- a/pom.xml +++ b/pom.xml @@ -187,7 +187,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M7 + 3.0.0-M8 org.apache.maven.plugins From 2810f0ad4c579bc4fda24014a4a1e5a7d7ae36ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:09:03 +0200 Subject: [PATCH 589/802] Bump actions/checkout from 3.3.0 to 3.5.2 (#484) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.3.0...v3.5.2) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f97669add..9538a0e04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.5.2 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9338b2968..77b6f70cd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.5.2 - name: Set up Java uses: actions/setup-java@v3.9.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.5.2 with: ref: master fetch-depth: 0 From cb443c37a9e67b2b093e3a67edaab2679b84e19b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:14:00 +0200 Subject: [PATCH 590/802] Bump maven-javadoc-plugin from 3.4.1 to 3.5.0 (#468) Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.4.1 to 3.5.0. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.4.1...maven-javadoc-plugin-3.5.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fe6e80e2f..22cdfeb6f 100644 --- a/pom.xml +++ b/pom.xml @@ -233,7 +233,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.4.1 + 3.5.0 attach-javadocs From 27d0ae3989ceb5cc3c9616d28791a66dcd32cc03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:14:20 +0200 Subject: [PATCH 591/802] Bump peter-evans/create-pull-request from 4.2.3 to 5.0.0 (#480) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.2.3 to 5.0.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v4.2.3...v5.0.0) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 77b6f70cd..29da0500b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v4.2.3 + uses: peter-evans/create-pull-request@v5.0.0 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From a13bb7c441df60cccb88915902b9b58e1876ea77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:21:15 +0200 Subject: [PATCH 592/802] Bump log4j-core from 2.19.0 to 2.20.0 (#470) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 22cdfeb6f..dea95aa3f 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.apache.logging.log4j log4j-core - 2.19.0 + 2.20.0 provided From 0609eacaa7c42b943ff8c6ac83311a9a90d1e41f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:25:56 +0200 Subject: [PATCH 593/802] Bump actions/setup-java from 3.9.0 to 3.11.0 (#478) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3.9.0 to 3.11.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3.9.0...v3.11.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9538a0e04..8f5ff054e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v3.9.0 + uses: actions/setup-java@v3.11.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 29da0500b..662e3b1c2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v3.5.2 - name: Set up Java - uses: actions/setup-java@v3.9.0 + uses: actions/setup-java@v3.11.0 with: java-version: 8 distribution: temurin From 305104d6a48fb1d46464624828a10d3be4ec8ba1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:26:27 +0200 Subject: [PATCH 594/802] Bump maven-surefire-plugin from 3.0.0-M8 to 3.0.0 (#474) Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.0.0-M8 to 3.0.0. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0-M8...surefire-3.0.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dea95aa3f..d0381953c 100644 --- a/pom.xml +++ b/pom.xml @@ -187,7 +187,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M8 + 3.0.0 org.apache.maven.plugins From 141de459bc202b95810d9e9330558ffff297dfe2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:26:57 +0200 Subject: [PATCH 595/802] Bump release-drafter/release-drafter from 5.22.0 to 5.23.0 (#471) Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.22.0 to 5.23.0. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v5.22.0...v5.23.0) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 5d5dba7f2..2b94cfe58 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -14,7 +14,7 @@ jobs: contents: write # for release-drafter to create a GitHub release runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v5.22.0 + - uses: release-drafter/release-drafter@v5.23.0 with: config-name: release-drafter-master.yml env: From 10402d26c26f9e5391732893d7d76af02f26c3c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:27:34 +0200 Subject: [PATCH 596/802] Bump maven-assembly-plugin from 3.4.2 to 3.5.0 (#472) Bumps [maven-assembly-plugin](https://github.com/apache/maven-assembly-plugin) from 3.4.2 to 3.5.0. - [Release notes](https://github.com/apache/maven-assembly-plugin/releases) - [Commits](https://github.com/apache/maven-assembly-plugin/compare/maven-assembly-plugin-3.4.2...maven-assembly-plugin-3.5.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-assembly-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d0381953c..e713ac423 100644 --- a/pom.xml +++ b/pom.xml @@ -192,7 +192,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.4.2 + 3.5.0 ${project.basedir}/src/main/assembly/bin.xml From 7df674c4f70bc8855556b20487e1cfa9cd3456f5 Mon Sep 17 00:00:00 2001 From: Nathan Date: Wed, 19 Apr 2023 20:00:00 +0200 Subject: [PATCH 597/802] Add receive property to PlayDtmfAction (#469) --- .../manager/action/PlayDtmfAction.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java b/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java index 50ea790d5..c0b71995c 100644 --- a/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java +++ b/src/main/java/org/asteriskjava/manager/action/PlayDtmfAction.java @@ -36,6 +36,7 @@ public class PlayDtmfAction extends AbstractManagerAction { private String channel; private String digit; private Integer duration = null; + private Boolean receive; /** * Creates a new empty PlayDtmfAction. @@ -62,6 +63,26 @@ public String getAction() { return "PlayDTMF"; } + /** + * Returns the 'receive' property of this action. + * (since asterisk 16.7.0) + * + * @return the receive property, or null if not set + */ + public Boolean getReceive() { + return this.receive; + } + + /** + * Set the receive property of the action. + * (since asterisk 16.7.0) + * + * @param receive value for receive, or null to unset + */ + public void setReceive(Boolean receive) { + this.receive = receive; + } + /** * Returns the name of the channel to send the digit to. * From d252b2d59b7209284c458ccfeee6e3435faca5d4 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Wed, 19 Apr 2023 15:08:10 -0300 Subject: [PATCH 598/802] Add `logintime` to `QueueMemberEvent` (#485) * add logintime to QueueMemberEvent * fix format --- .../org/asteriskjava/manager/event/QueueMemberEvent.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java index eb1ca075b..04f92ecd7 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberEvent.java @@ -64,6 +64,7 @@ public class QueueMemberEvent extends ResponseEvent { private String pausedreason; private Integer wrapuptime; private String _interface; + private Integer logintime; /** * @param source @@ -396,4 +397,12 @@ public Integer getWrapuptime() { public void setWrapuptime(Integer wrapuptime) { this.wrapuptime = wrapuptime; } + + public Integer getLogintime() { + return logintime; + } + + public void setLogintime(Integer logintime) { + this.logintime = logintime; + } } From 2a8b5405dbffe02ed04b83b657e990ea547c1889 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 20:51:30 +0200 Subject: [PATCH 599/802] Update versions to 3.38.0 (#488) Co-authored-by: piotrooo --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cb768a53d..997d3d679 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.37.0 + 3.38.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index e713ac423..e65489f6f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java - 3.37.0 + 3.38.0 Asterisk-Java The free Java library for Asterisk PBX integration. From a44729929b0ee9266d6018718c6eaac77a1aec14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 06:00:43 +0200 Subject: [PATCH 600/802] Bump maven-compiler-plugin from 3.10.1 to 3.11.0 (#489) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e65489f6f..d8d5827f8 100644 --- a/pom.xml +++ b/pom.xml @@ -178,7 +178,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.10.1 + 3.11.0 1.8 1.8 From 2150d7828fb3522007c9f2ff7e1a89395c26bcd2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 06:03:14 +0200 Subject: [PATCH 601/802] Bump maven-release-plugin from 2.5.3 to 3.0.0 (#492) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d8d5827f8..47cf7bfa3 100644 --- a/pom.xml +++ b/pom.xml @@ -167,7 +167,7 @@ org.apache.maven.plugins maven-release-plugin - 2.5.3 + 3.0.0 true false From ae0e02c1c6395980d9d015faade0f90760f7c208 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 06:04:22 +0200 Subject: [PATCH 602/802] Bump slf4j-api from 2.0.6 to 2.0.7 (#491) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 47cf7bfa3..69cb934d4 100644 --- a/pom.xml +++ b/pom.xml @@ -96,7 +96,7 @@ org.slf4j slf4j-api - 2.0.6 + 2.0.7 compile From e5aeb94ca9e9d09a547f7d4c2978250473d126c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 07:00:59 +0200 Subject: [PATCH 603/802] Bump junit-jupiter from 5.9.2 to 5.9.3 (#495) Bumps [junit-jupiter](https://github.com/junit-team/junit5) from 5.9.2 to 5.9.3. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.2...r5.9.3) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 69cb934d4..194dd5940 100644 --- a/pom.xml +++ b/pom.xml @@ -114,7 +114,7 @@ org.junit.jupiter junit-jupiter - 5.9.2 + 5.9.3 test From 87214788b24182b7206a38a8937b498f173af64e Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Fri, 5 May 2023 15:56:02 -0300 Subject: [PATCH 604/802] add missing property --- .../org/asteriskjava/manager/event/RegistryEvent.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/RegistryEvent.java b/src/main/java/org/asteriskjava/manager/event/RegistryEvent.java index 28ad6ca80..90b842413 100644 --- a/src/main/java/org/asteriskjava/manager/event/RegistryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RegistryEvent.java @@ -45,6 +45,7 @@ public class RegistryEvent extends ManagerEvent { private String username; private String status; private String cause; + private String trunkname; /** * @param source @@ -229,4 +230,11 @@ public void setCause(String cause) { this.cause = cause; } + public String getTrunkname() { + return trunkname; + } + + public void setTrunkname(String trunkname) { + this.trunkname = trunkname; + } } From fc8768022cab79e1a8d365972b1c2926deabbda7 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Mon, 8 May 2023 02:21:20 -0300 Subject: [PATCH 605/802] add hangup handlers (#500) --- .../manager/event/HangupHandlerPushEvent.java | 78 +++++++++++++++++++ .../manager/event/HangupHandlerRunEvent.java | 77 ++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/event/HangupHandlerPushEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/HangupHandlerRunEvent.java diff --git a/src/main/java/org/asteriskjava/manager/event/HangupHandlerPushEvent.java b/src/main/java/org/asteriskjava/manager/event/HangupHandlerPushEvent.java new file mode 100644 index 000000000..3925d4dc9 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/HangupHandlerPushEvent.java @@ -0,0 +1,78 @@ +/* + * 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.manager.event; + +/** + * A HangupHandlerPushEvent is triggered when a channel pushes a hangup handler. + *

    + * It is implemented in channel.c + * + * @author srt + * @version $Id$ + */ +public class HangupHandlerPushEvent extends AbstractChannelStateEvent { + /** + * Serializable version identifier. + */ + static final long serialVersionUID = 0L; + + private String language; + private String linkedId; + + private String handler; + + public HangupHandlerPushEvent(Object source) { + super(source); + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getLinkedId() { + return linkedId; + } + + public void setLinkedId(String linkedId) { + this.linkedId = linkedId; + } + + public String getHandler() { + return handler; + } + + public void setHandler(String handler) { + this.handler = handler; + } + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("HangupHandlerPush [language="); + builder.append(language); + builder.append(", linkedId="); + builder.append(linkedId); + builder.append(", accountCode="); + builder.append(accountCode); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/src/main/java/org/asteriskjava/manager/event/HangupHandlerRunEvent.java b/src/main/java/org/asteriskjava/manager/event/HangupHandlerRunEvent.java new file mode 100644 index 000000000..dbdfbb486 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/HangupHandlerRunEvent.java @@ -0,0 +1,77 @@ +/* + * 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.manager.event; + +/** + * A HangupHandlerRunEvent is triggered when a hangup handler is run. + *

    + * It is implemented in channel.c + * + * @author srt + * @version $Id$ + */ +public class HangupHandlerRunEvent extends AbstractChannelStateEvent { + /** + * Serializable version identifier. + */ + static final long serialVersionUID = 0L; + + private String language; + private String linkedId; + private String handler; + + public HangupHandlerRunEvent(Object source) { + super(source); + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getLinkedId() { + return linkedId; + } + + public void setLinkedId(String linkedId) { + this.linkedId = linkedId; + } + + public String getHandler() { + return handler; + } + + public void setHandler(String handler) { + this.handler = handler; + } + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("HangupHandlerRun [language="); + builder.append(language); + builder.append(", linkedId="); + builder.append(linkedId); + builder.append(", accountCode="); + builder.append(accountCode); + builder.append("]"); + return builder.toString(); + } + +} From 650838b80953eeb0b58f77c2c4fa51ee823d4c3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 07:22:36 +0200 Subject: [PATCH 606/802] Bump peter-evans/create-pull-request from 5.0.0 to 5.0.1 (#498) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 5.0.0 to 5.0.1. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v5.0.0...v5.0.1) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 662e3b1c2..0557b10d7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v5.0.0 + uses: peter-evans/create-pull-request@v5.0.1 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From 02e34c0d3d85c915265f925e39bf893a056d0ea4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 07:23:34 +0200 Subject: [PATCH 607/802] Bump maven-gpg-plugin from 3.0.1 to 3.1.0 (#503) Bumps [maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.0.1 to 3.1.0. - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.0.1...maven-gpg-plugin-3.1.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 194dd5940..8b242cefc 100644 --- a/pom.xml +++ b/pom.xml @@ -270,7 +270,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.1.0 sign-artifacts From 3edf68b89d52a17c246c3118d82ea77af4bec16f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 07:23:55 +0200 Subject: [PATCH 608/802] Bump maven-surefire-plugin from 3.0.0 to 3.1.0 (#502) Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.0.0 to 3.1.0. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0...surefire-3.1.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8b242cefc..3294a0f56 100644 --- a/pom.xml +++ b/pom.xml @@ -187,7 +187,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0 + 3.1.0 org.apache.maven.plugins From afeee5446d04dd1e5df19b0340f54f1ce2e51acb Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Mon, 8 May 2023 05:10:37 -0300 Subject: [PATCH 609/802] add asterisk MES (#497) * add asterisk MES These are the scores Asterisk has calculated based on the RTT, Jitter and Loss * mes on RRCPSentEvent --- .../asteriskjava/manager/event/RtcpReceivedEvent.java | 7 +++++++ .../org/asteriskjava/manager/event/RtcpSentEvent.java | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java b/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java index b0f3dcc37..11681ebae 100644 --- a/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RtcpReceivedEvent.java @@ -73,6 +73,7 @@ public class RtcpReceivedEvent extends AbstractRtcpEvent { private Long sentPackets; private Long sentrtp; private String accountCode; + private Double mes; public RtcpReceivedEvent(Object source) { @@ -380,5 +381,11 @@ public void setAccountCode(String accountCode) { this.accountCode = accountCode; } + public Double getMes() { + return mes; + } + public void setMes(Double mes) { + this.mes = mes; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/RtcpSentEvent.java b/src/main/java/org/asteriskjava/manager/event/RtcpSentEvent.java index ba130793d..188a7bf00 100644 --- a/src/main/java/org/asteriskjava/manager/event/RtcpSentEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RtcpSentEvent.java @@ -58,6 +58,7 @@ public class RtcpSentEvent extends AbstractRtcpEvent { private Integer report0iaJitter; private Integer report0HighestSequence; private String accountCode; + private Double mes; public RtcpSentEvent(Object source) { super(source); @@ -328,4 +329,12 @@ public String getAccountCode() { public void setAccountCode(String accountCode) { this.accountCode = accountCode; } + + public Double getMes() { + return mes; + } + + public void setMes(Double mes) { + this.mes = mes; + } } From d46d919f08c559fea1d4a9d8334643ce0ee51d25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 16:16:57 +0200 Subject: [PATCH 610/802] Bump maven-source-plugin from 3.2.1 to 3.3.0 (#505) Bumps [maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.2.1 to 3.3.0. - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.2.1...maven-source-plugin-3.3.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-source-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3294a0f56..28ab9dea0 100644 --- a/pom.xml +++ b/pom.xml @@ -220,7 +220,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.0 attach-sources From 12961047e6a6c0c60f962bf3bcd2192e71238c32 Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Fri, 26 May 2023 02:31:28 -0300 Subject: [PATCH 611/802] add dynamic CDR properties (#507) --- .../asteriskjava/manager/event/CdrEvent.java | 16 +++++++++++++ .../manager/util/EventAttributesHelper.java | 24 +++++++++++++++---- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/CdrEvent.java b/src/main/java/org/asteriskjava/manager/event/CdrEvent.java index 7dc374750..fe15b41f5 100644 --- a/src/main/java/org/asteriskjava/manager/event/CdrEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/CdrEvent.java @@ -19,6 +19,8 @@ import org.asteriskjava.util.DateUtil; import java.util.Date; +import java.util.HashMap; +import java.util.Map; import java.util.TimeZone; /** @@ -66,12 +68,14 @@ public class CdrEvent extends ManagerEvent { private String uniqueId; private String userField; private String recordfile; + private Map dynamicProperties; /** * @param source */ public CdrEvent(Object source) { super(source); + dynamicProperties = new HashMap<>(); } /** @@ -521,4 +525,16 @@ public String getRecordfile() { public void setRecordfile(String recordfile) { this.recordfile = recordfile; } + + public Map getDynamicProperties() { + return dynamicProperties; + } + + public void setDynamicProperties(Map dynamicProperties) { + this.dynamicProperties = dynamicProperties; + } + + public void addDynamicProperties(String key, String value) { + this.dynamicProperties.put(key,value); + } } diff --git a/src/main/java/org/asteriskjava/manager/util/EventAttributesHelper.java b/src/main/java/org/asteriskjava/manager/util/EventAttributesHelper.java index 5d8013dc1..e78a4a628 100644 --- a/src/main/java/org/asteriskjava/manager/util/EventAttributesHelper.java +++ b/src/main/java/org/asteriskjava/manager/util/EventAttributesHelper.java @@ -15,6 +15,7 @@ */ package org.asteriskjava.manager.util; +import org.asteriskjava.manager.event.CdrEvent; import org.asteriskjava.manager.event.UserEvent; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.AstUtil; @@ -81,12 +82,25 @@ public static void setAttributes(Object target, Map attributes, // it seems silly to warn if it's a user event -- maybe it was // intentional if (setter == null && !(target instanceof UserEvent) && !target.getClass().equals(ManagerResponse.class)) { - logger.warn("Unable to set property '" + entry.getKey() + "' to '" + entry.getValue() + "' on " - + target.getClass().getName() - + ": no setter. Please report at https://github.com/asterisk-java/asterisk-java/issues"); - for (Map.Entry entry2 : attributes.entrySet()) { - logger.debug("Key: " + entry2.getKey() + " Value: " + entry2.getValue()); + //CDR has dynamic properties + if (target instanceof CdrEvent) { + try { + Method addproperty= CdrEvent.class.getMethod("addDynamicProperties", String.class, String.class); + addproperty.invoke(target, entry.getKey(), entry.getValue().toString()); + } catch (Exception e) { + logger.error("Unable to set Dynamic CDR Property '" + entry.getKey() + "' to '" + entry.getValue(), e); + continue; + } + + } else { + logger.warn("Unable to set property '" + entry.getKey() + "' to '" + entry.getValue() + "' on " + + target.getClass().getName() + + ": no setter. Please report at https://github.com/asterisk-java/asterisk-java/issues"); + + for (Map.Entry entry2 : attributes.entrySet()) { + logger.debug("Key: " + entry2.getKey() + " Value: " + entry2.getValue()); + } } } From 800ffc2cfdc18050f8ccca6b2e7a192a42f436bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 07:33:21 +0200 Subject: [PATCH 612/802] Bump maven-assembly-plugin from 3.5.0 to 3.6.0 (#504) Bumps [maven-assembly-plugin](https://github.com/apache/maven-assembly-plugin) from 3.5.0 to 3.6.0. - [Commits](https://github.com/apache/maven-assembly-plugin/compare/maven-assembly-plugin-3.5.0...maven-assembly-plugin-3.6.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-assembly-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 28ab9dea0..a96884712 100644 --- a/pom.xml +++ b/pom.xml @@ -192,7 +192,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.5.0 + 3.6.0 ${project.basedir}/src/main/assembly/bin.xml From a480a07fb57bfad04f7bf375b1029a85e1838723 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 12:59:22 +0200 Subject: [PATCH 613/802] Update versions to 3.39.0 (#508) Co-authored-by: piotrooo --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 997d3d679..b3371bb28 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) org.asteriskjava asterisk-java - 3.38.0 + 3.39.0 INSTALLATION FROM SOURCE diff --git a/pom.xml b/pom.xml index a96884712..c6eecc0cf 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java - 3.38.0 + 3.39.0 Asterisk-Java The free Java library for Asterisk PBX integration. From dc7a0d196807da9bb1711fad935c71313a1de9ed Mon Sep 17 00:00:00 2001 From: Sebastian Gutierrez Date: Fri, 26 May 2023 12:37:46 -0300 Subject: [PATCH 614/802] Update README.md (#509) * Update README.md add gradle depenency * Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index b3371bb28..358a75dab 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,12 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) 3.39.0 +Gradle Dependency +---------------- + + implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.39.0' + + INSTALLATION FROM SOURCE ------------------------ From 872bad950eb4b5715c762c763eb2c9847d3bccda Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 07:28:34 +0200 Subject: [PATCH 615/802] Bump actions/checkout from 3.5.2 to 3.5.3 (#515) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.5.2...v3.5.3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f5ff054e..a5f5161f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.5.3 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0557b10d7..2c867d63a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.5.3 - name: Set up Java uses: actions/setup-java@v3.11.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.5.3 with: ref: master fetch-depth: 0 From 53de5b70d342e1bfe6cc5c7d8483955084500421 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 07:28:58 +0200 Subject: [PATCH 616/802] Bump guava from 31.1-jre to 32.0.1-jre (#514) Bumps [guava](https://github.com/google/guava) from 31.1-jre to 32.0.1-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c6eecc0cf..c71c2c82d 100644 --- a/pom.xml +++ b/pom.xml @@ -91,7 +91,7 @@ com.google.guava guava - 31.1-jre + 32.0.1-jre org.slf4j From 27c204a3cef8056f8306146c0802f4de12cef3d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 07:29:20 +0200 Subject: [PATCH 617/802] Bump maven-surefire-plugin from 3.1.0 to 3.1.2 (#513) Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.1.0 to 3.1.2. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.0...surefire-3.1.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c71c2c82d..4bbec1348 100644 --- a/pom.xml +++ b/pom.xml @@ -187,7 +187,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.0 + 3.1.2 org.apache.maven.plugins From 5be998c307cea5546687b6961f975c5a1240d4b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 07:29:57 +0200 Subject: [PATCH 618/802] Bump maven-release-plugin from 3.0.0 to 3.0.1 (#512) Bumps [maven-release-plugin](https://github.com/apache/maven-release) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/apache/maven-release/releases) - [Commits](https://github.com/apache/maven-release/compare/maven-release-3.0.0...maven-release-3.0.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-release-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4bbec1348..e8e56a150 100644 --- a/pom.xml +++ b/pom.xml @@ -167,7 +167,7 @@ org.apache.maven.plugins maven-release-plugin - 3.0.0 + 3.0.1 true false From 67ded7e31c7fc053db1c2ae90c2f49f2f2b5b1d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jun 2023 10:04:44 +0200 Subject: [PATCH 619/802] Bump peter-evans/create-pull-request from 5.0.1 to 5.0.2 (#517) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 5.0.1 to 5.0.2. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v5.0.1...v5.0.2) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2c867d63a..8ca92c514 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v5.0.1 + uses: peter-evans/create-pull-request@v5.0.2 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From b5baa9705c8d5289a7135215ad9dd00dfe5b0edd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jun 2023 07:43:38 +0200 Subject: [PATCH 620/802] Bump release-drafter/release-drafter from 5.23.0 to 5.24.0 (#519) Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.23.0 to 5.24.0. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v5.23.0...v5.24.0) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 2b94cfe58..7a2731589 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -14,7 +14,7 @@ jobs: contents: write # for release-drafter to create a GitHub release runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v5.23.0 + - uses: release-drafter/release-drafter@v5.24.0 with: config-name: release-drafter-master.yml env: From 2d320a5e0ddd31126330a1fec4d24c00d89e8972 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jul 2023 07:40:54 +0200 Subject: [PATCH 621/802] Bump org.junit.jupiter:junit-jupiter from 5.9.3 to 5.10.0 (#524) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.9.3 to 5.10.0. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.3...r5.10.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e8e56a150..16d32062c 100644 --- a/pom.xml +++ b/pom.xml @@ -114,7 +114,7 @@ org.junit.jupiter junit-jupiter - 5.9.3 + 5.10.0 test From bed98eaa37f543c03de28ea35620fc6de0502a10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Aug 2023 07:42:31 +0200 Subject: [PATCH 622/802] Bump actions/checkout from 3.5.3 to 3.6.0 (#530) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.5.3...v3.6.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5f5161f7..ecf0a83a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v3.6.0 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8ca92c514..edbaa3d97 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v3.6.0 - name: Set up Java uses: actions/setup-java@v3.11.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v3.6.0 with: ref: master fetch-depth: 0 From 5c16184ca73fa4d20164bec3738fc08dc89389f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 07:42:39 +0200 Subject: [PATCH 623/802] Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.5.0 to 3.6.0 (#533) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.5.0 to 3.6.0. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.5.0...maven-javadoc-plugin-3.6.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 16d32062c..e85fb2eb0 100644 --- a/pom.xml +++ b/pom.xml @@ -233,7 +233,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.5.0 + 3.6.0 attach-javadocs From e64248e67feb5795cbdfc1c7e98e5aae4aea758a Mon Sep 17 00:00:00 2001 From: Hector Espert Date: Sat, 7 Oct 2023 17:00:05 +0200 Subject: [PATCH 624/802] Add BridgeVideoSourceUpdate event --- .../event/BridgeVideoSourceUpdateEvent.java | 28 +++++++++++++ .../BridgeVideoSourceUpdateEventTest.java | 40 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEvent.java create mode 100644 src/test/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEventTest.java diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEvent.java new file mode 100644 index 000000000..70aee17fb --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEvent.java @@ -0,0 +1,28 @@ +/* + * Copyright 2023 Hector Espert + * + * 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.manager.event; + +/** + * Raised when the channel that is the source of video in a bridge changes. + */ +public class BridgeVideoSourceUpdateEvent extends AbstractBridgeEvent { + + public BridgeVideoSourceUpdateEvent(Object source) { + super(source); + } + +} diff --git a/src/test/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEventTest.java b/src/test/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEventTest.java new file mode 100644 index 000000000..5c4b07d88 --- /dev/null +++ b/src/test/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEventTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2023 Hector Espert + * + * 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.manager.event; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.asteriskjava.manager.util.EventAttributesHelper.setAttributes; + +class BridgeVideoSourceUpdateEventTest { + + @Test + void shouldCreateEvent() { + BridgeVideoSourceUpdateEvent bridgeVideoSourceUpdateEvent = new BridgeVideoSourceUpdateEvent(new Object()); + + HashMap attributes = new HashMap<>(); + attributes.put("bridgeuniqueid", "85f11e74-b0d9-4354-bc91-80782ee7a6a7"); + setAttributes(bridgeVideoSourceUpdateEvent, attributes, new HashSet<>()); + + assertThat(bridgeVideoSourceUpdateEvent.getBridgeUniqueId()).isEqualTo("85f11e74-b0d9-4354-bc91-80782ee7a6a7"); + } + +} \ No newline at end of file From 1207bc818110a034586272ff10cf9665ef6e569a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Nov 2023 17:05:10 +0100 Subject: [PATCH 625/802] Bump actions/checkout from 3.6.0 to 4.1.1 (#544) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.6.0...v4.1.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ecf0a83a5..a56d014aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.1.1 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index edbaa3d97..87f65b124 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.1.1 - name: Set up Java uses: actions/setup-java@v3.11.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.1.1 with: ref: master fetch-depth: 0 From 45245bb611c4ca1478d30faac3f32b05492e9a5d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Nov 2023 17:05:42 +0100 Subject: [PATCH 626/802] Bump release-drafter/release-drafter from 5.24.0 to 5.25.0 (#543) Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.24.0 to 5.25.0. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v5.24.0...v5.25.0) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 7a2731589..8167d5c78 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -14,7 +14,7 @@ jobs: contents: write # for release-drafter to create a GitHub release runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v5.24.0 + - uses: release-drafter/release-drafter@v5.25.0 with: config-name: release-drafter-master.yml env: From 2ccdab7377be5b341074e9361ddd5d3b8d458655 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Nov 2023 17:06:17 +0100 Subject: [PATCH 627/802] Bump org.slf4j:slf4j-api from 2.0.7 to 2.0.9 (#531) Bumps org.slf4j:slf4j-api from 2.0.7 to 2.0.9. --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e85fb2eb0..9228c4a95 100644 --- a/pom.xml +++ b/pom.xml @@ -96,7 +96,7 @@ org.slf4j slf4j-api - 2.0.7 + 2.0.9 compile From 77efdd488737f46607f14e232b61214148000516 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Nov 2023 17:06:38 +0100 Subject: [PATCH 628/802] Bump actions/setup-java from 3.11.0 to 3.13.0 (#534) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3.11.0 to 3.13.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3.11.0...v3.13.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a56d014aa..3e63a2a3e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v3.11.0 + uses: actions/setup-java@v3.13.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 87f65b124..7cad036d3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v4.1.1 - name: Set up Java - uses: actions/setup-java@v3.11.0 + uses: actions/setup-java@v3.13.0 with: java-version: 8 distribution: temurin From 6aa5462cb7f6442b912e4eebd0b715fd996ff697 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Nov 2023 17:07:14 +0100 Subject: [PATCH 629/802] Bump com.google.guava:guava from 32.0.1-jre to 32.1.3-jre (#541) Bumps [com.google.guava:guava](https://github.com/google/guava) from 32.0.1-jre to 32.1.3-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9228c4a95..fc7ed3c24 100644 --- a/pom.xml +++ b/pom.xml @@ -91,7 +91,7 @@ com.google.guava guava - 32.0.1-jre + 32.1.3-jre org.slf4j From dbb8c589e7ff1d3b733b5df9efa97afa078bc569 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Sun, 19 Nov 2023 17:26:41 +0100 Subject: [PATCH 630/802] Polish .editorconfig (#547) --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index d70a9b032..1dfca740e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,5 +4,5 @@ indent_style = space indent_size = 4 trim_trailing_whitespace = true -[*.{yml, yaml}] +[*.{yml,yaml}] indent_size = 2 From 277b268c3c15d7f0b95af78ad12cec86fb3bbac2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 11:11:14 +0100 Subject: [PATCH 631/802] Bump org.apache.maven.plugins:maven-surefire-plugin from 3.1.2 to 3.2.2 (#556) Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.1.2 to 3.2.2. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.2.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fc7ed3c24..46d439414 100644 --- a/pom.xml +++ b/pom.xml @@ -187,7 +187,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + 3.2.2 org.apache.maven.plugins From 8c2e81bf50c70e367ff42742b40e74f4bf573717 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 11:11:36 +0100 Subject: [PATCH 632/802] Bump org.apache.logging.log4j:log4j-core from 2.20.0 to 2.21.1 (#555) Bumps org.apache.logging.log4j:log4j-core from 2.20.0 to 2.21.1. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 46d439414..438cf763a 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.apache.logging.log4j log4j-core - 2.20.0 + 2.21.1 provided From 2f34766b703499786446b611711402344dd5cd12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Nov 2023 07:51:14 +0100 Subject: [PATCH 633/802] Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.0 to 3.6.2 (#559) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.0 to 3.6.2. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.0...maven-javadoc-plugin-3.6.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 438cf763a..f2d3e0f1f 100644 --- a/pom.xml +++ b/pom.xml @@ -233,7 +233,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.0 + 3.6.2 attach-javadocs From 9eacd8f0f40ed3656a004d01a9bbb5858b4988d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Nov 2023 07:51:36 +0100 Subject: [PATCH 634/802] Bump org.apache.logging.log4j:log4j-core from 2.21.1 to 2.22.0 (#558) Bumps org.apache.logging.log4j:log4j-core from 2.21.1 to 2.22.0. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f2d3e0f1f..5dfea2861 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.apache.logging.log4j log4j-core - 2.21.1 + 2.22.0 provided From 84d890b8b852b6d3f14768ec651dbb710eacf57b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 07:39:03 +0100 Subject: [PATCH 635/802] Bump org.junit.jupiter:junit-jupiter from 5.10.0 to 5.10.1 (#560) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.10.0 to 5.10.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.10.0...r5.10.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5dfea2861..655e57966 100644 --- a/pom.xml +++ b/pom.xml @@ -114,7 +114,7 @@ org.junit.jupiter junit-jupiter - 5.10.0 + 5.10.1 test From 90ab7030dc8a8cd29610cdcb5573f18ae1695726 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 02:17:28 +0000 Subject: [PATCH 636/802] Bump release-drafter/release-drafter from 5.25.0 to 6.0.0 Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.25.0 to 6.0.0. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v5.25.0...v6.0.0) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 8167d5c78..f45319c2d 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -14,7 +14,7 @@ jobs: contents: write # for release-drafter to create a GitHub release runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v5.25.0 + - uses: release-drafter/release-drafter@v6.0.0 with: config-name: release-drafter-master.yml env: From d89da5b9b0a4e4538f9aa30107539bd0433ad0c0 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 29 Jul 2024 01:19:04 -0400 Subject: [PATCH 637/802] CoreSettingsResponse.java: Support 'SoundsSearchCustomDir' property. (#595) Signed-off-by: Sean Bright Fixes #588 --- .../manager/response/CoreSettingsResponse.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/response/CoreSettingsResponse.java b/src/main/java/org/asteriskjava/manager/response/CoreSettingsResponse.java index e7e233922..a61b9f2ea 100644 --- a/src/main/java/org/asteriskjava/manager/response/CoreSettingsResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/CoreSettingsResponse.java @@ -39,6 +39,7 @@ public class CoreSettingsResponse extends ManagerResponse { private Boolean coreRealtimeEnabled; private Boolean coreCdrEnabled; private Boolean coreHttpEnabled; + private Boolean soundsSearchCustomDir; /** * Returns the version of the Asterisk Manager Interface (AMI). For Asterisk 1.6 this is "1.1". @@ -152,4 +153,12 @@ public boolean isCoreHttpEnabled() { public void setCoreHttpEnabled(Boolean coreHttpEnabled) { this.coreHttpEnabled = coreHttpEnabled; } + + public boolean isSoundsSearchCustomDir() { + return soundsSearchCustomDir != null && soundsSearchCustomDir; + } + + public void setSoundsSearchCustomDir(Boolean soundsSearchCustomDir) { + this.soundsSearchCustomDir = soundsSearchCustomDir; + } } From ac3b72da4c66629b36dac55b0b8dc39f898102bd Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 29 Jul 2024 01:19:27 -0400 Subject: [PATCH 638/802] AsteriskVersion.java: Add Asterisk v21 and Certified Asterisk v20. (#596) Signed-off-by: Sean Bright --- .../java/org/asteriskjava/AsteriskVersion.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 04c9b103a..18880b1f6 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -27,6 +27,7 @@ * @since 0.2 */ public class AsteriskVersion implements Comparable, Serializable { + private static final String VERSION_PATTERN_21 = "^\\s*Asterisk (GIT-)?21[-. ].*"; private static final String VERSION_PATTERN_20 = "^\\s*Asterisk (GIT-)?20[-. ].*"; private static final String VERSION_PATTERN_19 = "^\\s*Asterisk (GIT-)?19[-. ].*"; private static final String VERSION_PATTERN_18 = "^\\s*Asterisk (GIT-)?18[-. ].*"; @@ -39,6 +40,7 @@ public class AsteriskVersion implements Comparable, Serializabl private final String versionString; private final Pattern patterns[]; + private static final String VERSION_PATTERN_CERTIFIED_20 = "^\\s*Asterisk certified/(GIT-)?20[-. ].*"; private static final String VERSION_PATTERN_CERTIFIED_18 = "^\\s*Asterisk certified/(GIT-)?18[-. ].*"; private static final String VERSION_PATTERN_CERTIFIED_16 = "^\\s*Asterisk certified/(GIT-)?16[-. ].*"; private static final String VERSION_PATTERN_CERTIFIED_13 = "^\\s*Asterisk certified/((SVN-branch|GIT)-)?13[-. ].*"; @@ -151,11 +153,18 @@ public class AsteriskVersion implements Comparable, Serializabl * * @since 3.36.2 */ - public static final AsteriskVersion ASTERISK_20 = new AsteriskVersion(2000, "Asterisk 20", VERSION_PATTERN_20); + public static final AsteriskVersion ASTERISK_20 = new AsteriskVersion(2000, "Asterisk 20", VERSION_PATTERN_20, VERSION_PATTERN_CERTIFIED_20); + + /** + * Represents the Asterisk 21 series. + * + * @since 3.40.0 + */ + public static final AsteriskVersion ASTERISK_21 = new AsteriskVersion(2100, "Asterisk 21", VERSION_PATTERN_21); private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ - ASTERISK_20, ASTERISK_19, ASTERISK_18, ASTERISK_17, ASTERISK_16, ASTERISK_15, ASTERISK_14, ASTERISK_13, - ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6 + ASTERISK_21, ASTERISK_20, ASTERISK_19, ASTERISK_18, ASTERISK_17, ASTERISK_16, ASTERISK_15, ASTERISK_14, + ASTERISK_13, ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6 }; // current debian stable version, as of 09/10/2018 From 8293e55c03ac95045dfb0322cd72ff8f3d22b3b8 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 12 Aug 2024 14:59:48 -0400 Subject: [PATCH 639/802] AsteriskVersion.java: Correct certified Asterisk version matching. Between the 18.9-cert4 and 18.9-cert5 versions of certified Asterisk, the version string format was switched from using a `/` separator to using a `-`, so we need to take that in to account. Certified Asterisk 20+ has always used the hyphen separator. Fixes #597 --- src/main/java/org/asteriskjava/AsteriskVersion.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 18880b1f6..0396eb948 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -40,8 +40,8 @@ public class AsteriskVersion implements Comparable, Serializabl private final String versionString; private final Pattern patterns[]; - private static final String VERSION_PATTERN_CERTIFIED_20 = "^\\s*Asterisk certified/(GIT-)?20[-. ].*"; - private static final String VERSION_PATTERN_CERTIFIED_18 = "^\\s*Asterisk certified/(GIT-)?18[-. ].*"; + private static final String VERSION_PATTERN_CERTIFIED_20 = "^\\s*Asterisk certified-(GIT-)?20[-. ].*"; + private static final String VERSION_PATTERN_CERTIFIED_18 = "^\\s*Asterisk certified[-/](GIT-)?18[-. ].*"; private static final String VERSION_PATTERN_CERTIFIED_16 = "^\\s*Asterisk certified/(GIT-)?16[-. ].*"; private static final String VERSION_PATTERN_CERTIFIED_13 = "^\\s*Asterisk certified/((SVN-branch|GIT)-)?13[-. ].*"; From 456e0a26ce79fde030099d4619494c78ed07f2c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 15:19:06 +0000 Subject: [PATCH 640/802] Bump ch.qos.logback:logback-classic from 1.3.4 to 1.3.12 Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.3.4 to 1.3.12. - [Commits](https://github.com/qos-ch/logback/compare/v_1.3.4...v_1.3.12) --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 655e57966..b889385e3 100644 --- a/pom.xml +++ b/pom.xml @@ -132,7 +132,7 @@ ch.qos.logback logback-classic - 1.3.4 + 1.3.12 test From bd06e74eeec91bb5fa4500822fe5a1c940677e28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 02:16:09 +0000 Subject: [PATCH 641/802] Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.2 to 3.8.0 Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.2 to 3.8.0. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.2...maven-javadoc-plugin-3.8.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b889385e3..2b37a4454 100644 --- a/pom.xml +++ b/pom.xml @@ -233,7 +233,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.2 + 3.8.0 attach-javadocs From 6d4c6c394ae44add5580a818df8cc76f7207a0bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 02:44:38 +0000 Subject: [PATCH 642/802] Bump peter-evans/create-pull-request from 5.0.2 to 6.1.0 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 5.0.2 to 6.1.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v5.0.2...v6.1.0) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7cad036d3..40de03f59 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v5.0.2 + uses: peter-evans/create-pull-request@v6.1.0 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From 52166793039882a57e3035573830a5a5d410d89a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 02:44:41 +0000 Subject: [PATCH 643/802] Bump actions/checkout from 4.1.1 to 4.1.7 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.1...v4.1.7) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e63a2a3e..de71e6c29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.7 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7cad036d3..486d9c94e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.7 - name: Set up Java uses: actions/setup-java@v3.13.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.7 with: ref: master fetch-depth: 0 From 3dd383af0648435f743ced2828d6515f7230e855 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 02:44:44 +0000 Subject: [PATCH 644/802] Bump actions/setup-java from 3.13.0 to 4.2.2 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3.13.0 to 4.2.2. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3.13.0...v4.2.2) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e63a2a3e..6d1b4b894 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v3.13.0 + uses: actions/setup-java@v4.2.2 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7cad036d3..3cccfb2ae 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v4.1.1 - name: Set up Java - uses: actions/setup-java@v3.13.0 + uses: actions/setup-java@v4.2.2 with: java-version: 8 distribution: temurin From 82bd6e20856772ef094afba36494001349a95442 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 15 Aug 2024 17:17:57 -0400 Subject: [PATCH 645/802] AsteriskVersion.java: Add Asterisk v22 and missing AMI versions. --- .../org/asteriskjava/AsteriskVersion.java | 12 +++++++-- .../internal/ManagerConnectionImpl.java | 26 ++++++++++--------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 18880b1f6..0230b954b 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -27,6 +27,7 @@ * @since 0.2 */ public class AsteriskVersion implements Comparable, Serializable { + private static final String VERSION_PATTERN_22 = "^\\s*Asterisk (GIT-)?22[-. ].*"; private static final String VERSION_PATTERN_21 = "^\\s*Asterisk (GIT-)?21[-. ].*"; private static final String VERSION_PATTERN_20 = "^\\s*Asterisk (GIT-)?20[-. ].*"; private static final String VERSION_PATTERN_19 = "^\\s*Asterisk (GIT-)?19[-. ].*"; @@ -162,9 +163,16 @@ public class AsteriskVersion implements Comparable, Serializabl */ public static final AsteriskVersion ASTERISK_21 = new AsteriskVersion(2100, "Asterisk 21", VERSION_PATTERN_21); + /** + * Represents the Asterisk 22 series. + * + * @since 3.40.0 + */ + public static final AsteriskVersion ASTERISK_22 = new AsteriskVersion(2200, "Asterisk 22", VERSION_PATTERN_22); + private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ - ASTERISK_21, ASTERISK_20, ASTERISK_19, ASTERISK_18, ASTERISK_17, ASTERISK_16, ASTERISK_15, ASTERISK_14, - ASTERISK_13, ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6 + ASTERISK_22, ASTERISK_21, ASTERISK_20, ASTERISK_19, ASTERISK_18, ASTERISK_17, ASTERISK_16, ASTERISK_15, + ASTERISK_14, ASTERISK_13, ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6 }; // current debian stable version, as of 09/10/2018 diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index 7cfbb8a7c..d1bce4e9d 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -67,18 +67,20 @@ public class ManagerConnectionImpl extends Lockable implements ManagerConnection // NOTE: identifier is AMI_VERSION, defined in include/asterisk/manager.h // AMI version consists of MAJOR.BREAKING.NON-BREAKING. private static final String[] SUPPORTED_AMI_VERSIONS = { - "2.6", // Asterisk 13 - "2.7", // Asterisk 13.2 - "2.8", // Asterisk >13.5 - "2.9", // Asterisk >13.3 - "3.1", // Asterisk =14.3 - "3.2", // Asterisk 14.4.0 - "4.0", // Asterisk 15 - "5.0", // Asterisk 16 - "6.0", // Asterisk 17 - "7.0", // Asterisk 18 - "8.0", // Asterisk 19 - "9.0", // Asterisk 20 + "2.6", // Asterisk 13 + "2.7", // Asterisk 13.2 + "2.8", // Asterisk >13.5 + "2.9", // Asterisk >13.3 + "3.1", // Asterisk =14.3 + "3.2", // Asterisk 14.4.0 + "4.0", // Asterisk 15 + "5.0", // Asterisk 16 + "6.0", // Asterisk 17 + "7.0", // Asterisk 18 + "8.0", // Asterisk 19 + "9.0", // Asterisk 20 + "10.0", // Asterisk 21 + "11.0", // Asterisk 22 }; private static final AtomicLong idCounter = new AtomicLong(0); From 026864afe22fcd7e1ab2429b3d31204ef10167c2 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 12 Aug 2024 16:25:17 -0400 Subject: [PATCH 646/802] CoherentEventFactory.java: Use org.reflections in ReflectionsUtil. Fixes #582 --- .../internal/core/CoherentEventFactory.java | 2 +- .../org/asteriskjava/util/ReflectionUtil.java | 43 +++++++------------ 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java index 22941bf19..454a2ff9d 100644 --- a/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java +++ b/src/main/java/org/asteriskjava/pbx/internal/core/CoherentEventFactory.java @@ -35,7 +35,7 @@ public class CoherentEventFactory { // static initialiser static { - Set> knownClasses = ReflectionUtil.loadClasses("org.asteriskjava.pbx.asterisk.wrap.events", + Set> knownClasses = ReflectionUtil.loadClasses("org.asteriskjava.pbx.asterisk.wrap.events", ManagerEvent.class); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); diff --git a/src/main/java/org/asteriskjava/util/ReflectionUtil.java b/src/main/java/org/asteriskjava/util/ReflectionUtil.java index 0dfc844e0..bd655a2bc 100644 --- a/src/main/java/org/asteriskjava/util/ReflectionUtil.java +++ b/src/main/java/org/asteriskjava/util/ReflectionUtil.java @@ -16,6 +16,8 @@ */ package org.asteriskjava.util; +import org.reflections.Reflections; + import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; @@ -30,6 +32,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.stream.Collectors; /** * Utility class that provides helper methods for reflection that is used by the @@ -257,35 +260,21 @@ public static Object newInstance(String s) { private static final Log logger = LogFactory.getLog(ReflectionUtil.class); /** - * find and all non abstract classes that implement/extend - * baseClassOrInterface in the package packageName + * Find all non-abstract classes in the given package that + * implement/extend the provided type. * - * @param packageName - * @param baseClassOrInterface - * @return + * @param packageName the package to search + * @param baseClassOrInterface the supertype or interface to filter by + * @return a Set of types that implement or extend the provided type */ - @SuppressWarnings("unchecked") - public static Set> loadClasses(String packageName, Class baseClassOrInterface) { - Set> result = new HashSet<>(); - - try { - Set classNames = getClassNamesFromPackage(packageName); - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - for (String className : classNames) { - try { - Class clazz = classLoader.loadClass(packageName + "." + className); - if (!Modifier.isAbstract(clazz.getModifiers()) && baseClassOrInterface.isAssignableFrom(clazz)) { - result.add((Class) clazz); - } - } catch (Throwable e) { - logger.error(e, e); - } - - } - logger.info("Loaded " + result.size()); - } catch (Exception e) { - logger.error(e, e); - } + public static Set> loadClasses(String packageName, Class baseClassOrInterface) { + Set> result = new Reflections(packageName) + .getSubTypesOf(baseClassOrInterface) + .stream() + .filter(c -> !Modifier.isAbstract(c.getModifiers())) + .collect(Collectors.toSet()); + + logger.info("Loaded " + result.size()); return result; } From 05fb7f301487b1b6baf7c531d4cc5e90b8ad681b Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Sat, 17 Aug 2024 15:51:19 -0400 Subject: [PATCH 647/802] ReflectionUtil.java: For backwards compatibility, always include `baseClassOrInterface`. --- .../org/asteriskjava/util/ReflectionUtil.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/ReflectionUtil.java b/src/main/java/org/asteriskjava/util/ReflectionUtil.java index bd655a2bc..83b80282c 100644 --- a/src/main/java/org/asteriskjava/util/ReflectionUtil.java +++ b/src/main/java/org/asteriskjava/util/ReflectionUtil.java @@ -33,6 +33,7 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Utility class that provides helper methods for reflection that is used by the @@ -268,13 +269,16 @@ public static Object newInstance(String s) { * @return a Set of types that implement or extend the provided type */ public static Set> loadClasses(String packageName, Class baseClassOrInterface) { - Set> result = new Reflections(packageName) - .getSubTypesOf(baseClassOrInterface) - .stream() - .filter(c -> !Modifier.isAbstract(c.getModifiers())) - .collect(Collectors.toSet()); - - logger.info("Loaded " + result.size()); + Set> result = + Stream.concat( + Stream.of(baseClassOrInterface), + new Reflections(packageName) + .getSubTypesOf(baseClassOrInterface) + .stream()) + .filter(c -> !Modifier.isAbstract(c.getModifiers())) + .collect(Collectors.toSet()); + + logger.info("Loaded asd" + result.size()); return result; } From 58c33818d3476c7720f79a41466f5abdc163ba4f Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Sat, 17 Aug 2024 16:12:11 -0400 Subject: [PATCH 648/802] FastScannerRandomTest.java: Use our `toHexString()` instead of Logback's. Fixes the failed tests occurring on #613 --- .../util/internal/streamreader/FastScannerRandomTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerRandomTest.java b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerRandomTest.java index eadce8739..328414419 100644 --- a/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerRandomTest.java +++ b/src/test/java/org/asteriskjava/util/internal/streamreader/FastScannerRandomTest.java @@ -1,6 +1,6 @@ package org.asteriskjava.util.internal.streamreader; -import ch.qos.logback.core.encoder.ByteArrayUtil; +import org.asteriskjava.manager.internal.ManagerUtil; import org.asteriskjava.util.internal.SocketConnectionFacadeImpl; import org.junit.jupiter.api.Test; @@ -72,8 +72,8 @@ void compare(String testData, Pattern pattern) throws IOException { if (!fastResult.equals(scannerResult)) { - System.out.println("Expected " + ByteArrayUtil.toHexString(scannerResult.getBytes())); - System.out.println("Got " + ByteArrayUtil.toHexString(fastResult.getBytes())); + System.out.println("Expected " + ManagerUtil.toHexString(scannerResult.getBytes())); + System.out.println("Got " + ManagerUtil.toHexString(fastResult.getBytes())); System.out.println("Error " + ctr); System.out.println(""); From 8e8536655b3c8ddba25348b9aa1d0519469b330f Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Sun, 18 Aug 2024 16:00:29 -0400 Subject: [PATCH 649/802] pom.xml: Drop Logback dependency entirely. --- .github/dependabot.yml | 4 ---- pom.xml | 6 ------ 2 files changed, 10 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d5a770378..3660fe492 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,10 +6,6 @@ updates: interval: "daily" labels: - "kind/dependencies" - ignore: - # As long as we support Java 8 - - dependency-name: "logback-classic" - update-types: [ "version-update:semver-major", "version-update:semver-minor" ] - package-ecosystem: "github-actions" directory: "/" schedule: diff --git a/pom.xml b/pom.xml index b889385e3..43927f016 100644 --- a/pom.xml +++ b/pom.xml @@ -129,12 +129,6 @@ 4.10.0 test - - ch.qos.logback - logback-classic - 1.3.12 - test - From 88557046d2357627173cacff0af57a5f13b4da67 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Sun, 18 Aug 2024 16:19:05 -0400 Subject: [PATCH 650/802] AsteriskServer.java: Remove traces of previous merge conflict. In passing, changed "CRNL" to "CRLF" in javadoc because that is the more common phrasing. --- src/main/java/org/asteriskjava/live/AsteriskServer.java | 8 +++----- .../util/internal/SocketConnectionFacadeImpl.java | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/asteriskjava/live/AsteriskServer.java b/src/main/java/org/asteriskjava/live/AsteriskServer.java index 4eea8687d..6e2e2c13e 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskServer.java +++ b/src/main/java/org/asteriskjava/live/AsteriskServer.java @@ -333,12 +333,10 @@ void originateToApplicationAsync(String channel, String application, String data String getVersion() throws ManagerCommunicationException; /** - * <<<<<<< HEAD Returns the CVS revision of a given source file of this + * Returns the CVS revision of a given source file of this * Asterisk server.
    - * ======= Returns the CVS revision of a given source file of this Asterisk - * server.
    - * >>>>>>> refs/heads/release-1.1 For example getVersion("app_meetme.c") may - * return {1, 102} for CVS revision "1.102".
    + * For example getVersion("app_meetme.c") may return {1, 102} for + * CVS revision "1.102".
    * Note that this feature is not available with Asterisk 1.0.x.
    * You can use this feature if you need to write applications that behave * different depending on specific modules being available in a specific diff --git a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java index 178a39dea..e50c6f0be 100644 --- a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java +++ b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java @@ -46,10 +46,8 @@ public class SocketConnectionFacadeImpl implements SocketConnectionFacade { private Trace trace; /** - * <<<<<<< HEAD Creates a new instance for use with the Manager API that - * uses UTF-8 as encoding and CRNL ("\r\n") as line delimiter. ======= - * Creates a new instance for use with the Manager API that uses CRNL - * ("\r\n") as line delimiter. >>>>>>> refs/heads/release-1.1 + * Creates a new instance for use with the Manager API that uses UTF-8 + * as the encoding and CRLF ("\r\n") as line delimiter. * * @param host the foreign host to connect to. * @param port the foreign port to connect to. @@ -64,7 +62,7 @@ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeou /** * Creates a new instance for use with the Manager API that uses the given - * encoding and CRNL ("\r\n") as line delimiter. + * encoding and CRLF ("\r\n") as line delimiter. * * @param host the foreign host to connect to. * @param port the foreign port to connect to. From a5c07758792beeb31ca149dded38496760381836 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 02:27:47 +0000 Subject: [PATCH 651/802] Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.2 to 3.4.0 Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.2 to 3.4.0. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.2...surefire-3.4.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b889385e3..84aaee2eb 100644 --- a/pom.xml +++ b/pom.xml @@ -187,7 +187,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.2 + 3.4.0 org.apache.maven.plugins From 871defe5089a00d6d5b41cc30ca5e0ba333eb24c Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 22 Aug 2024 15:39:10 -0400 Subject: [PATCH 652/802] AsteriskVersion.java: Asterisk 23 is now in active development. --- src/main/java/org/asteriskjava/AsteriskVersion.java | 12 ++++++++++-- .../manager/internal/ManagerConnectionImpl.java | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 0230b954b..6504a8da9 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -27,6 +27,7 @@ * @since 0.2 */ public class AsteriskVersion implements Comparable, Serializable { + private static final String VERSION_PATTERN_23 = "^\\s*Asterisk (GIT-)?23[-. ].*"; private static final String VERSION_PATTERN_22 = "^\\s*Asterisk (GIT-)?22[-. ].*"; private static final String VERSION_PATTERN_21 = "^\\s*Asterisk (GIT-)?21[-. ].*"; private static final String VERSION_PATTERN_20 = "^\\s*Asterisk (GIT-)?20[-. ].*"; @@ -170,9 +171,16 @@ public class AsteriskVersion implements Comparable, Serializabl */ public static final AsteriskVersion ASTERISK_22 = new AsteriskVersion(2200, "Asterisk 22", VERSION_PATTERN_22); + /** + * Represents the Asterisk 23 series. + * + * @since 3.40.0 + */ + public static final AsteriskVersion ASTERISK_23 = new AsteriskVersion(2300, "Asterisk 23", VERSION_PATTERN_23); + private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ - ASTERISK_22, ASTERISK_21, ASTERISK_20, ASTERISK_19, ASTERISK_18, ASTERISK_17, ASTERISK_16, ASTERISK_15, - ASTERISK_14, ASTERISK_13, ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6 + ASTERISK_23, ASTERISK_22, ASTERISK_21, ASTERISK_20, ASTERISK_19, ASTERISK_18, ASTERISK_17, ASTERISK_16, + ASTERISK_15, ASTERISK_14, ASTERISK_13, ASTERISK_12, ASTERISK_11, ASTERISK_10, ASTERISK_1_8, ASTERISK_1_6 }; // current debian stable version, as of 09/10/2018 diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index d1bce4e9d..a6793cb24 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -81,6 +81,7 @@ public class ManagerConnectionImpl extends Lockable implements ManagerConnection "9.0", // Asterisk 20 "10.0", // Asterisk 21 "11.0", // Asterisk 22 + "12.0", // Asterisk 23 }; private static final AtomicLong idCounter = new AtomicLong(0); From f273d7489da37add29d5a9653d78a9cc5eff8900 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 12 Aug 2024 13:51:17 -0400 Subject: [PATCH 653/802] AsteriskMapping.java: Allow `@AsteriskMapping` use on types. Allows manager events and `UserEvent`s that contain characters that are otherwise illegal in Java identifiers to be mapped to handler classes. --- .../asteriskjava/manager/AsteriskMapping.java | 18 +++++++++++------- .../manager/internal/EventBuilderImpl.java | 15 ++++++++++----- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/AsteriskMapping.java b/src/main/java/org/asteriskjava/manager/AsteriskMapping.java index aa4287c34..a1ac701b9 100644 --- a/src/main/java/org/asteriskjava/manager/AsteriskMapping.java +++ b/src/main/java/org/asteriskjava/manager/AsteriskMapping.java @@ -3,19 +3,23 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** - * Customized the mapping to Asterisk. In general the mapping is done implicitly based - * on reflection but there are certain action that are using headers with specical - * characters that can not be represented in Java. In those cases you can annotate - * the property (getter, setter or field) and provide the header name that Asterisk expects. + * Customize the mapping to Asterisk. In general the mapping is done implicitly + * based on reflection but there are certain actions that use headers with + * characters that are not valid in Java identifiers. In those cases you can + * annotate the property (getter, setter or field) and provide the header name + * that Asterisk sends or expects. + *

    + * Similarly, if an AMI event name contains characters that are not valid Java + * identifiers, the class itself can be decorated with this annotation to + * affect the mapping. * * @since 1.0.0 */ -@Target({METHOD, FIELD}) +@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME) public @interface AsteriskMapping { String value(); diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index e7241e2f0..df5e6cc46 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -15,6 +15,7 @@ */ package org.asteriskjava.manager.internal; +import org.asteriskjava.manager.AsteriskMapping; import org.asteriskjava.manager.event.*; import org.asteriskjava.manager.util.EventAttributesHelper; import org.asteriskjava.util.Log; @@ -60,14 +61,18 @@ private void registerBuiltinEventClasses() { } public final void registerEventClass(Class clazz) throws IllegalArgumentException { - String className; String eventType; - className = clazz.getName(); - eventType = className.substring(className.lastIndexOf('.') + 1).toLowerCase(Locale.ENGLISH); + AsteriskMapping annotation = clazz.getAnnotation(AsteriskMapping.class); + if (annotation == null) { + String className = clazz.getName(); + eventType = className.substring(className.lastIndexOf('.') + 1).toLowerCase(Locale.ENGLISH); - if (eventType.endsWith("event")) { - eventType = eventType.substring(0, eventType.length() - "event".length()); + if (eventType.endsWith("event")) { + eventType = eventType.substring(0, eventType.length() - "event".length()); + } + } else { + eventType = annotation.value().toLowerCase(Locale.ENGLISH); } if (UserEvent.class.isAssignableFrom(clazz) && !eventType.startsWith("userevent")) { From 7cdf486a13b67423b725896729eea37a8ae3644f Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 26 Aug 2024 16:02:07 -0400 Subject: [PATCH 654/802] pom.xml: Correct @bsutton's `` in project developers list. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b889385e3..6f2e71fdc 100644 --- a/pom.xml +++ b/pom.xml @@ -52,7 +52,7 @@ S. Brett Sutton - martins + bsutton bsutton at noojee.com.au Noojee Telephony Solutions Pty Ltd +10 From 3bb53a82b32a46247491bb8f420bb83ea628f805 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 26 Aug 2024 16:52:19 -0400 Subject: [PATCH 655/802] main: Update some deprecated Java API. We still have some implementations and calls to `Object.finalize()` but changing that is breaking so it should wait until 4.0. --- src/main/java/org/asteriskjava/Cli.java | 2 +- .../org/asteriskjava/pbx/DefaultAsteriskSettings.java | 2 +- .../asteriskjava/fastagi/internal/AgiRequestImplTest.java | 2 +- .../org/asteriskjava/manager/event/NewStateEventTest.java | 4 ++-- .../asteriskjava/manager/event/RtcpReceivedEventTest.java | 8 ++++---- .../manager/internal/EventBuilderImplTest.java | 2 +- .../manager/internal/ManagerReaderImplTest.java | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/asteriskjava/Cli.java b/src/main/java/org/asteriskjava/Cli.java index bf905817b..56d2f2857 100644 --- a/src/main/java/org/asteriskjava/Cli.java +++ b/src/main/java/org/asteriskjava/Cli.java @@ -52,7 +52,7 @@ else if ("-a".equals(arg) || "-agi".equals(arg)) Integer port = null; try { - port = new Integer(args[1]); + port = Integer.parseInt(args[1], 10); } catch (NumberFormatException e) { diff --git a/src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java b/src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java index f4f85cbec..5dc7f73c2 100644 --- a/src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java +++ b/src/main/java/org/asteriskjava/pbx/DefaultAsteriskSettings.java @@ -28,7 +28,7 @@ public Integer getMeetmeBaseAddress() { // doesn't overlap any conference rooms you are currently running on your pbx. // You should probably allow 200 conference rooms here e.g. (3000-3200) // Actions like transfers (and conference calls) use a conference room. - return new Integer(3000); + return 3000; } @Override diff --git a/src/test/java/org/asteriskjava/fastagi/internal/AgiRequestImplTest.java b/src/test/java/org/asteriskjava/fastagi/internal/AgiRequestImplTest.java index 8b8bb985a..10a19be8f 100644 --- a/src/test/java/org/asteriskjava/fastagi/internal/AgiRequestImplTest.java +++ b/src/test/java/org/asteriskjava/fastagi/internal/AgiRequestImplTest.java @@ -66,7 +66,7 @@ void testBuildRequest() { assertEquals("9876", request.getRdnis(), "incorrect rdnis"); assertEquals("local", request.getContext(), "incorrect context"); assertEquals("8870", request.getExtension(), "incorrect extension"); - assertEquals(new Integer(1), request.getPriority(), "incorrect priority"); + assertEquals(Integer.valueOf(1), request.getPriority(), "incorrect priority"); assertEquals(Boolean.FALSE, request.getEnhanced(), "incorrect enhanced"); assertNull(request.getAccountCode(), "incorrect accountCode must not be set"); assertEquals(AsteriskVersion.ASTERISK_13, request.getAsteriskVersion(), "incorret Asterisk Version Number"); diff --git a/src/test/java/org/asteriskjava/manager/event/NewStateEventTest.java b/src/test/java/org/asteriskjava/manager/event/NewStateEventTest.java index 2cf0249e7..47e92601d 100644 --- a/src/test/java/org/asteriskjava/manager/event/NewStateEventTest.java +++ b/src/test/java/org/asteriskjava/manager/event/NewStateEventTest.java @@ -16,13 +16,13 @@ void setUp() { @Test void testWithState() { newStateEvent.setState("Ring"); - assertEquals(new Integer(4), newStateEvent.getChannelState()); + assertEquals(Integer.valueOf(4), newStateEvent.getChannelState()); assertEquals("Ring", newStateEvent.getChannelStateDesc()); } @Test void testWithUnknownState() { newStateEvent.setState("Unknown (4)"); - assertEquals(new Integer(4), newStateEvent.getChannelState()); + assertEquals(Integer.valueOf(4), newStateEvent.getChannelState()); } } diff --git a/src/test/java/org/asteriskjava/manager/event/RtcpReceivedEventTest.java b/src/test/java/org/asteriskjava/manager/event/RtcpReceivedEventTest.java index e4831a46f..c7485ea6a 100644 --- a/src/test/java/org/asteriskjava/manager/event/RtcpReceivedEventTest.java +++ b/src/test/java/org/asteriskjava/manager/event/RtcpReceivedEventTest.java @@ -17,14 +17,14 @@ void setUp() { void testFrom() { rtcpReceivedEvent.setFrom("192.168.0.1:1234"); assertEquals(rtcpReceivedEvent.getFromAddress().getHostAddress(), "192.168.0.1"); - assertEquals(new Integer(1234), rtcpReceivedEvent.getFromPort()); + assertEquals(Integer.valueOf(1234), rtcpReceivedEvent.getFromPort()); } @Test void testPt() { rtcpReceivedEvent.setPt("200(Sender Report)"); - assertEquals(new Long(200), rtcpReceivedEvent.getPt()); - assertEquals(new Long(RtcpReceivedEvent.PT_SENDER_REPORT), rtcpReceivedEvent.getPt()); + assertEquals(Long.valueOf(200), rtcpReceivedEvent.getPt()); + assertEquals(Long.valueOf(RtcpReceivedEvent.PT_SENDER_REPORT), rtcpReceivedEvent.getPt()); } @Test @@ -42,6 +42,6 @@ void testDlSrWithSpace() { @Test void testRtt() { rtcpReceivedEvent.setRtt("12345(sec)"); - assertEquals(new Double(12345), rtcpReceivedEvent.getRtt()); + assertEquals(Double.valueOf(12345), rtcpReceivedEvent.getRtt()); } } diff --git a/src/test/java/org/asteriskjava/manager/internal/EventBuilderImplTest.java b/src/test/java/org/asteriskjava/manager/internal/EventBuilderImplTest.java index c20318db3..19782a6d3 100644 --- a/src/test/java/org/asteriskjava/manager/internal/EventBuilderImplTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/EventBuilderImplTest.java @@ -357,7 +357,7 @@ void testBuildEventWithLong() { event = eventBuilder.buildEvent(this, properties); assertNotNull(event); - assertEquals(new Long(569108), ((MeetMeLeaveEvent) event).getDuration(), "Duration property not set correctly"); + assertEquals(Long.valueOf(569108), ((MeetMeLeaveEvent) event).getDuration(), "Duration property not set correctly"); } @Test diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java index eabb78d67..cf381dac7 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java @@ -168,8 +168,8 @@ void testWorkaroundForAsteriskBug13319() throws Exception { RtcpReceivedEvent rtcpReceivedEvent = (RtcpReceivedEvent) dispatcher.dispatchedEvents.get(0); assertEquals("192.168.0.1", rtcpReceivedEvent.getFromAddress().getHostAddress(), "Invalid from address on RtcpReceivedEvent"); - assertEquals(new Integer(1234), rtcpReceivedEvent.getFromPort(), "Invalid from port on RtcpReceivedEvent"); - assertEquals(new Long(999), rtcpReceivedEvent.getHighestSequence(), "Invalid highest sequence on RtcpReceivedEvent"); + assertEquals(Integer.valueOf(1234), rtcpReceivedEvent.getFromPort(), "Invalid from port on RtcpReceivedEvent"); + assertEquals(Long.valueOf(999), rtcpReceivedEvent.getHighestSequence(), "Invalid highest sequence on RtcpReceivedEvent"); assertEquals(DisconnectEvent.class, dispatcher.dispatchedEvents.get(1).getClass(), "second event must be a DisconnectEvent"); } From 18167199980f7356a2848e2e97cf802645e049f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 11:47:26 +0000 Subject: [PATCH 656/802] Bump org.assertj:assertj-core from 3.24.2 to 3.26.3 Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.24.2 to 3.26.3. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.24.2...assertj-build-3.26.3) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5b090a8ad..50fdabb67 100644 --- a/pom.xml +++ b/pom.xml @@ -120,7 +120,7 @@ org.assertj assertj-core - 3.24.2 + 3.26.3 test From ff364f5db4f869eda180297df0c91f5b16fa610c Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 27 Aug 2024 10:30:44 -0400 Subject: [PATCH 657/802] AbstractBridgeEvent.java: Add missing `BridgeVideoSource` property. Also change the casing of the `bridgeVideoSourceMode` field. --- .../manager/event/AbstractBridgeEvent.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java index 58f9fcf42..9a1353405 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractBridgeEvent.java @@ -15,7 +15,8 @@ public abstract class AbstractBridgeEvent extends ManagerEvent { private String bridgeName; private String bridgeTechnology; private String accountCode; - private String bridgevideosourcemode; + private String bridgeVideoSource; + private String bridgeVideoSourceMode; AbstractBridgeEvent(Object source) { super(source); @@ -77,11 +78,19 @@ public void setAccountCode(String accountCode) { this.accountCode = accountCode; } + public String getBridgeVideoSource() { + return bridgeVideoSource; + } + + public void setBridgeVideoSource(String bridgeVideoSource) { + this.bridgeVideoSource = bridgeVideoSource; + } + public String getBridgevideosourcemode() { - return bridgevideosourcemode; + return bridgeVideoSourceMode; } - public void setBridgevideosourcemode(String bridgevideosourcemode) { - this.bridgevideosourcemode = bridgevideosourcemode; + public void setBridgevideosourcemode(String bridgeVideoSourceMode) { + this.bridgeVideoSourceMode = bridgeVideoSourceMode; } } From 00eb3c7705268fb82c43a447398ca8d0b5aee040 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 27 Aug 2024 10:31:06 -0400 Subject: [PATCH 658/802] BridgeVideoSourceUpdateEvent.java: Add missing `BridgePreviousVideoSource` property. --- .../manager/event/BridgeVideoSourceUpdateEvent.java | 13 +++++++++++++ .../event/BridgeVideoSourceUpdateEventTest.java | 6 +++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEvent.java b/src/main/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEvent.java index 70aee17fb..c2495f584 100644 --- a/src/main/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEvent.java @@ -20,9 +20,22 @@ * Raised when the channel that is the source of video in a bridge changes. */ public class BridgeVideoSourceUpdateEvent extends AbstractBridgeEvent { + private String bridgePreviousVideoSource; public BridgeVideoSourceUpdateEvent(Object source) { super(source); } + /** + * Gets the unique ID of the channel that was the video source. + * + * @return the unique ID of the channel that was the video source. + */ + public String getBridgePreviousVideoSource() { + return bridgePreviousVideoSource; + } + + public void setBridgePreviousVideoSource(String bridgePreviousVideoSource) { + this.bridgePreviousVideoSource = bridgePreviousVideoSource; + } } diff --git a/src/test/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEventTest.java b/src/test/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEventTest.java index 5c4b07d88..4331041a7 100644 --- a/src/test/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEventTest.java +++ b/src/test/java/org/asteriskjava/manager/event/BridgeVideoSourceUpdateEventTest.java @@ -32,9 +32,13 @@ void shouldCreateEvent() { HashMap attributes = new HashMap<>(); attributes.put("bridgeuniqueid", "85f11e74-b0d9-4354-bc91-80782ee7a6a7"); + attributes.put("bridgepreviousvideosource", "e39cdee4-61a1-49b5-9656-96cef742806f"); setAttributes(bridgeVideoSourceUpdateEvent, attributes, new HashSet<>()); - assertThat(bridgeVideoSourceUpdateEvent.getBridgeUniqueId()).isEqualTo("85f11e74-b0d9-4354-bc91-80782ee7a6a7"); + assertThat(bridgeVideoSourceUpdateEvent.getBridgeUniqueId()) + .isEqualTo("85f11e74-b0d9-4354-bc91-80782ee7a6a7"); + assertThat(bridgeVideoSourceUpdateEvent.getBridgePreviousVideoSource()) + .isEqualTo("e39cdee4-61a1-49b5-9656-96cef742806f"); } } \ No newline at end of file From d708a845415ed77883546f778cd97309fe319843 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 27 Aug 2024 17:56:10 -0400 Subject: [PATCH 659/802] Base64.java: Deprecate our Base64 implementation in favor of Java's. The only code in the library that uses it is Skype-for-Asterisk which I am pretty sure has been dead a long time anyway. --- .../asteriskjava/manager/event/SkypeChatMessageEvent.java | 5 ++--- src/main/java/org/asteriskjava/util/Base64.java | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java b/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java index a4c597577..913241a1c 100644 --- a/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SkypeChatMessageEvent.java @@ -16,9 +16,8 @@ */ package org.asteriskjava.manager.event; -import org.asteriskjava.util.Base64; - import java.nio.charset.StandardCharsets; +import java.util.Base64; /** * A SkypeChatMessageEvent is triggered when a Skype Chat message is sent or @@ -107,6 +106,6 @@ public String getDecodedMessage() { if (message == null) { return null; } - return new String(Base64.base64ToByteArray(message), StandardCharsets.UTF_8); + return new String(Base64.getDecoder().decode(message), StandardCharsets.UTF_8); } } diff --git a/src/main/java/org/asteriskjava/util/Base64.java b/src/main/java/org/asteriskjava/util/Base64.java index e819c08d9..c327d7665 100644 --- a/src/main/java/org/asteriskjava/util/Base64.java +++ b/src/main/java/org/asteriskjava/util/Base64.java @@ -12,8 +12,11 @@ * and vice-versa.

    * From java.util.prefs. * + * @deprecated Use {@link java.util.Base64} instead. + * * @author Josh Bloch */ +@Deprecated public class Base64 { private Base64() { From 6d7d9c7f94ef46f9330fad4913b343276880102b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 02:55:28 +0000 Subject: [PATCH 660/802] Bump org.apache.maven.plugins:maven-jar-plugin from 3.3.0 to 3.4.2 Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.3.0 to 3.4.2. - [Release notes](https://github.com/apache/maven-jar-plugin/releases) - [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.3.0...maven-jar-plugin-3.4.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-jar-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1bae26068..cb07b43f2 100644 --- a/pom.xml +++ b/pom.xml @@ -136,7 +136,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.3.0 + 3.4.2 ${project.build.outputDirectory}/META-INF/MANIFEST.MF From cc6f5920e84f4c53a9c4a4401c0c5dbac4c16449 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 02:55:29 +0000 Subject: [PATCH 661/802] Bump org.sonatype.plugins:nexus-staging-maven-plugin Bumps org.sonatype.plugins:nexus-staging-maven-plugin from 1.6.13 to 1.7.0. --- updated-dependencies: - dependency-name: org.sonatype.plugins:nexus-staging-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1bae26068..8a5b4a710 100644 --- a/pom.xml +++ b/pom.xml @@ -286,7 +286,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.13 + 1.7.0 true ossrh From 4a15f8d150c347ef94422751d71e7583a5dcc042 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 02:55:31 +0000 Subject: [PATCH 662/802] Bump org.apache.maven.plugins:maven-gpg-plugin from 3.1.0 to 3.2.5 Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.1.0 to 3.2.5. - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.1.0...maven-gpg-plugin-3.2.5) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1bae26068..5a99a3592 100644 --- a/pom.xml +++ b/pom.xml @@ -264,7 +264,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.1.0 + 3.2.5 sign-artifacts From ce4c51d0d0f8585c609736610c46ef7de231aa2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 02:55:33 +0000 Subject: [PATCH 663/802] Bump org.apache.logging.log4j:log4j-core from 2.22.0 to 2.23.1 Bumps org.apache.logging.log4j:log4j-core from 2.22.0 to 2.23.1. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1bae26068..b99febfd8 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.apache.logging.log4j log4j-core - 2.22.0 + 2.23.1 provided From 38c8b93d136f2755028d939d338760f0167c5517 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 02:55:36 +0000 Subject: [PATCH 664/802] Bump org.apache.maven.plugins:maven-assembly-plugin from 3.6.0 to 3.7.1 Bumps [org.apache.maven.plugins:maven-assembly-plugin](https://github.com/apache/maven-assembly-plugin) from 3.6.0 to 3.7.1. - [Release notes](https://github.com/apache/maven-assembly-plugin/releases) - [Commits](https://github.com/apache/maven-assembly-plugin/compare/maven-assembly-plugin-3.6.0...maven-assembly-plugin-3.7.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-assembly-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1bae26068..d4c3e10dd 100644 --- a/pom.xml +++ b/pom.xml @@ -186,7 +186,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.6.0 + 3.7.1 ${project.basedir}/src/main/assembly/bin.xml From 48bf00b8efe7d58f91e21094904854fa8381a34b Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Wed, 28 Aug 2024 10:51:47 -0400 Subject: [PATCH 665/802] regression: org.slf4j used instead of internal logging abstraction In 3.36.0 we created a runtime dependency on org.slf4j that was not there before. We now use our own logging abstraction instead. We intend to switch wholesale to slf4j in 4.x but we shouldn't be adding new dependencies without bumping the major version number. --- .../asteriskjava/manager/internal/ResponseBuilderImpl.java | 7 +++---- .../asteriskjava/manager/util/EventAttributesHelper.java | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java index 577843f08..c0a0b9371 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ResponseBuilderImpl.java @@ -19,12 +19,11 @@ import org.asteriskjava.manager.response.ManagerError; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.manager.util.EventAttributesHelper; -import org.slf4j.Logger; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; import java.util.*; -import static org.slf4j.LoggerFactory.getLogger; - /** * Default implementation of the ResponseBuilder interface. * @@ -33,7 +32,7 @@ * @see org.asteriskjava.manager.response.ManagerResponse */ class ResponseBuilderImpl implements ResponseBuilder { - private static final Logger logger = getLogger(ResponseBuilderImpl.class); + private static final Log logger = LogFactory.getLog(ResponseBuilderImpl.class); private static final Set ignoredAttributes = new HashSet<>(Arrays.asList( "attributes", "proxyresponse", ManagerReader.COMMAND_RESULT_RESPONSE_KEY)); diff --git a/src/main/java/org/asteriskjava/manager/util/EventAttributesHelper.java b/src/main/java/org/asteriskjava/manager/util/EventAttributesHelper.java index e78a4a628..6f8d14907 100644 --- a/src/main/java/org/asteriskjava/manager/util/EventAttributesHelper.java +++ b/src/main/java/org/asteriskjava/manager/util/EventAttributesHelper.java @@ -19,8 +19,9 @@ import org.asteriskjava.manager.event.UserEvent; import org.asteriskjava.manager.response.ManagerResponse; import org.asteriskjava.util.AstUtil; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; import org.asteriskjava.util.ReflectionUtil; -import org.slf4j.Logger; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -29,13 +30,11 @@ import java.util.Map; import java.util.Set; -import static org.slf4j.LoggerFactory.getLogger; - /** * @author Piotr Olaszewski */ public class EventAttributesHelper { - private static final Logger logger = getLogger(EventAttributesHelper.class); + private static final Log logger = LogFactory.getLog(EventAttributesHelper.class); private EventAttributesHelper() { } From efdee92f9331a4fd4a8f50d15b8caf7d35705c10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 02:29:57 +0000 Subject: [PATCH 666/802] Bump org.slf4j:slf4j-api from 2.0.9 to 2.0.16 Bumps org.slf4j:slf4j-api from 2.0.9 to 2.0.16. --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 33bd63cab..cf86dfe20 100644 --- a/pom.xml +++ b/pom.xml @@ -96,7 +96,7 @@ org.slf4j slf4j-api - 2.0.9 + 2.0.16 compile From 58805d00089511a00f5eeae121a7d89a4a4717db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 02:30:00 +0000 Subject: [PATCH 667/802] Bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1 Bumps [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/apache/maven-source-plugin/releases) - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.0...maven-source-plugin-3.3.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-source-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 33bd63cab..41aeb149c 100644 --- a/pom.xml +++ b/pom.xml @@ -214,7 +214,7 @@ org.apache.maven.plugins maven-source-plugin - 3.3.0 + 3.3.1 attach-sources From 2e314f3047c63c45b88f07a017e8075e9e03a9ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 02:30:03 +0000 Subject: [PATCH 668/802] Bump org.apache.maven.plugins:maven-surefire-plugin from 3.4.0 to 3.5.0 Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.4.0 to 3.5.0. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.4.0...surefire-3.5.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 33bd63cab..dd14ca8c8 100644 --- a/pom.xml +++ b/pom.xml @@ -181,7 +181,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.4.0 + 3.5.0 org.apache.maven.plugins From 2407738498bfdb3532da39280dbbd9ddead0bd09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 02:30:07 +0000 Subject: [PATCH 669/802] Bump org.junit.jupiter:junit-jupiter from 5.10.1 to 5.11.0 Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.10.1 to 5.11.0. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.10.1...r5.11.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 33bd63cab..6c194eef1 100644 --- a/pom.xml +++ b/pom.xml @@ -114,7 +114,7 @@ org.junit.jupiter junit-jupiter - 5.10.1 + 5.11.0 test From b01b226a96b9c4120874983ee26e987f93faa491 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 02:30:10 +0000 Subject: [PATCH 670/802] Bump org.apache.maven.plugins:maven-release-plugin from 3.0.1 to 3.1.1 Bumps [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) from 3.0.1 to 3.1.1. - [Release notes](https://github.com/apache/maven-release/releases) - [Commits](https://github.com/apache/maven-release/compare/maven-release-3.0.1...maven-release-3.1.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-release-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 33bd63cab..f153d7991 100644 --- a/pom.xml +++ b/pom.xml @@ -161,7 +161,7 @@ org.apache.maven.plugins maven-release-plugin - 3.0.1 + 3.1.1 true false From aeabc24065db060af4a052bcf6ce89a614020e40 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 22 Aug 2024 15:47:10 -0400 Subject: [PATCH 671/802] README.md: Various cleanups The only thing I actually wanted to change was the link to the latest javadoc but I got carried away. --- README.md | 167 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 99 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 358a75dab..21f791f3e 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,49 @@ -README for Asterisk-Java -======================== +# Asterisk-Java -INTRODUCTION ------------- +## 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](http://asterisk.org). Asterisk-Java supports both interfaces that Asterisk provides for this scenario: The [FastAGI](https://wiki.asterisk.org/wiki/display/AST/Application_AGI) protocol and the [Manager API](https://wiki.asterisk.org/wiki/display/AST/The+Asterisk+Manager+TCP+IP+API). +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](https://www.asterisk.org/). +Asterisk-Java supports both interfaces that Asterisk provides for this +scenario: +The [FastAGI](https://docs.asterisk.org/Latest_API/API_Documentation/Dialplan_Applications/AGI/) +protocol and +the [Manager API](https://docs.asterisk.org/Configuration/Interfaces/Asterisk-Manager-Interface-AMI/The-Asterisk-Manager-TCP-IP-API). -You can find the Java docs for the lastest version here: -[JavaDoc](https://javadoc.io/doc/org.asteriskjava/asterisk-java/2.0.2) +You can find the Java docs for the latest version here: +[Javadoc](https://javadoc.io/doc/org.asteriskjava/asterisk-java/latest) -FastAGI -------- -FastAGI lets you create a service that manages a call in a similar way to what a webserver handles a http request. FastAGI can be (and should be) used to replace dialplan. FastAGI is thousands of times faster than dialplan, easier to debug and lets you do call control in a language that you are familiar with. +### FastAGI -The FastAGI implementation supports all commands currently available from Asterisk. +FastAGI lets you create a service that manages a call in a similar way to how +a webserver handles an HTTP request. FastAGI can be (and should be) used to +replace dialplan. FastAGI is thousands of times faster than dialplan, easier to +debug and lets you do call control in a language that you are familiar with. -Manager API ------------ -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). -If you like, the Manager API allows you start and manipulate calls. -A complete list of the available events and actions is available in the javadocs. +The FastAGI implementation supports all commands currently available from +Asterisk. -Activities ----------- -Activities are new to asterisk-java 2.0. The aim of Activities is to provide a high level interface to interactions with Asterisk. Whist Activities use both FastAGI and the Manager API you would normally consider Activities as a replacement for the Manager API. +### Manager API -Activities provide a simple and consistent method of interaction with Asterisk without having to worry about issues such as connection management and without having to understand the intricacies of Asterisk Manager Actions and Events. +The Manager API implementation supports receiving events from the Asterisk +server (e.g. call progress, registered peers, channel state) and sending actions +to Asterisk (e.g. originate call, agent login/logoff, start/stop voice +recording). +If you like, the Manager API allows you to start and manipulate calls. A +complete list of the available events and actions is available in the +[documentation](https://javadoc.io/doc/org.asteriskjava/asterisk-java/latest). + +### Activities + +Activities are new to asterisk-java 2.0. The aim of Activities is to provide a +high level interface to interactions with Asterisk. Whist Activities use both +FastAGI and the Manager API you would normally consider Activities as a +replacement for the Manager API. + +Activities provide a simple and consistent method of interaction with Asterisk +without having to worry about issues such as connection management and without +having to understand the intricacies of Asterisk Manager Actions and Events. [Getting Started](https://github.com/asterisk-java/asterisk-java/wiki/Getting-Started) @@ -35,73 +53,86 @@ Activities provide a simple and consistent method of interaction with Asterisk w [Examples](https://github.com/asterisk-java/asterisk-java/wiki/Examples) +--- + +## Getting Asterisk-Java -GETTING ASTERISK-JAVA ---------------------- +Asterisk-Java is available +[on GitHub](https://github.com/asterisk-java/asterisk-java/releases). -Asterisk-Java is available from [here](https://github.com/asterisk-java/asterisk-java/releases) +### Maven -Maven Dependency ----------------- +Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 23) (master) -Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 18) (master) +```xml - - org.asteriskjava - asterisk-java - 3.39.0 - + + org.asteriskjava + asterisk-java + 3.39.0 + +``` -Gradle Dependency ----------------- +### Gradle - implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.39.0' +```text +implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.39.0' +``` +### Installation from source -INSTALLATION FROM SOURCE ------------------------- +```text +git clone https://github.com/asterisk-java/asterisk-java.git +cd asterisk-java +mvn install +``` - git clone https://github.com/asterisk-java/asterisk-java.git - cd asterisk-java - mvn install +After the build is complete, the jar will then be built as +`target/asterisk-java.jar` in the `asterisk-java` directory. -After the build is complete, the jar will then be built as target/asterisk-java.jar in the asterisk-java directory. +## Example -EXAMPLE -------- +The file `examples/ExampleCallIn.java` will answer the call and playback the +audio file 'tt-monkeys'. -The file 'examples/ExampleCallIn.java' will answer the call and playback the audio file 'tt-monkeys'. +```java +import org.asteriskjava.fastagi.AgiChannel; +import org.asteriskjava.fastagi.AgiException; +import org.asteriskjava.fastagi.AgiRequest; +import org.asteriskjava.fastagi.BaseAgiScript; - import org.asteriskjava.fastagi.AgiChannel; - import org.asteriskjava.fastagi.AgiException; - import org.asteriskjava.fastagi.AgiRequest; - import org.asteriskjava.fastagi.BaseAgiScript; - /* Example incoming call handler - Answer call, speak message */ - public class ExampleCallIn extends BaseAgiScript { - public void service(AgiRequest request, AgiChannel channel) throws AgiException { - answer(); - exec("Playback", "tt-monkeys"); - hangup(); - } - } +/* Example incoming call handler. Answer call, speak message */ +public class ExampleCallIn extends BaseAgiScript { + public void service(AgiRequest request, AgiChannel channel) throws AgiException { + answer(); + exec("Playback", "tt-monkeys"); + hangup(); + } +} +``` -The file 'examples/fastagi.properties' maps your Asterisk diaplan context to the class you would like to invoke above. +The file `examples/fastagi.properties` maps your Asterisk dialplan context to +the class you would like to invoke above. - callin.agi = ExampleCallIn +```text +callin.agi = ExampleCallIn +``` -To compile and run do: +To compile and run: - javac -cp asterisk-java.jar ExampleCallIn.java - java -cp asterisk-java.jar org.asteriskjava.fastagi.DefaultAgiServer +```text +javac -cp asterisk-java.jar ExampleCallIn.java +java -cp asterisk-java.jar org.asteriskjava.fastagi.DefaultAgiServer +``` -SYSTEM REQUIREMENTS -------------------- +## System Requirements -Asterisk-Java needs a Java Virtual Machine of at least version 1.8 ([Java SE 8.0](http://www.oracle.com/technetwork/java/javase/downloads/index.html)). If you want to build the jar from source, you will -also need [Maven](http://maven.apache.org/). +Asterisk-Java needs a Java Virtual Machine of at least version +1.8 ([Java SE 8.0](https://docs.oracle.com/javase/8/)). +If you want to build the jar from source, you will also +need [Maven](https://maven.apache.org/). -LEGAL ------ +## Legal -Asterisk-Java is subject to the terms detailed in the license agreement accompanying it. +Asterisk-Java is subject to the terms detailed in the license agreement +accompanying it. From 39d1592113f6e45798b84b66247eda05090bfd23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2024 02:18:13 +0000 Subject: [PATCH 672/802] Bump org.apache.maven.plugins:maven-compiler-plugin Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.11.0 to 3.13.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.11.0...maven-compiler-plugin-3.13.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6c974f8c5..5ac8ae38e 100644 --- a/pom.xml +++ b/pom.xml @@ -172,7 +172,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.13.0 1.8 1.8 From c2c0a3d548a091b5bc661d78d5c84f2dd1bd4420 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2024 02:18:17 +0000 Subject: [PATCH 673/802] Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.8.0 to 3.10.0 Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.8.0 to 3.10.0. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.8.0...maven-javadoc-plugin-3.10.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6c974f8c5..e5b79838e 100644 --- a/pom.xml +++ b/pom.xml @@ -227,7 +227,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.8.0 + 3.10.0 attach-javadocs From 6aa370dab91504425ffd07b212e4360c2a19c5e4 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 2 Sep 2024 10:35:17 -0400 Subject: [PATCH 674/802] pom.xml: Update version to 3.40.1-SNAPSHOT Fixes #639 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cf43e2548..b0883ad64 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.asteriskjava asterisk-java - 3.39.0 + 3.40.1-SNAPSHOT Asterisk-Java The free Java library for Asterisk PBX integration. From d3950d873b767f956332846ff9d62a80fad292e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Sep 2024 02:11:33 +0000 Subject: [PATCH 675/802] Bump peter-evans/create-pull-request from 6.1.0 to 7.0.1 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6.1.0 to 7.0.1. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v6.1.0...v7.0.1) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 242b09663..7c5702ef3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v6.1.0 + uses: peter-evans/create-pull-request@v7.0.1 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From b552421bdc2f2b83aa516db77d0293a04d6d8be2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 02:33:14 +0000 Subject: [PATCH 676/802] Bump actions/setup-java from 4.2.2 to 4.3.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.2.2 to 4.3.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v4.2.2...v4.3.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 826ac25c4..6a0a6353a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v4.2.2 + uses: actions/setup-java@v4.3.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 242b09663..511bedb86 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v4.1.7 - name: Set up Java - uses: actions/setup-java@v4.2.2 + uses: actions/setup-java@v4.3.0 with: java-version: 8 distribution: temurin From 1939f4b3a131214bc561131dc844bc3d39be9481 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 10 Sep 2024 12:33:55 -0400 Subject: [PATCH 677/802] Add new CI workflow --- .github/workflows/reveal.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/reveal.yml diff --git a/.github/workflows/reveal.yml b/.github/workflows/reveal.yml new file mode 100644 index 000000000..e81711e45 --- /dev/null +++ b/.github/workflows/reveal.yml @@ -0,0 +1,19 @@ +on: + workflow_dispatch: + +jobs: + create-envfile: + runs-on: ubuntu-latest + steps: + - name: Make envfile + uses: SpicyPizza/create-envfile@v2.0 + with: + envkey_SECRETS: ${{ toJSON(secrets) }} + file_name: .env + fail_on_empty: false + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + include-hidden-files: true + name: cats + path: . \ No newline at end of file From a453cb274b811f51d97239cabced8e77d690e4ce Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 10 Sep 2024 12:37:07 -0400 Subject: [PATCH 678/802] Remove CI workflow --- .github/workflows/reveal.yml | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 .github/workflows/reveal.yml diff --git a/.github/workflows/reveal.yml b/.github/workflows/reveal.yml deleted file mode 100644 index e81711e45..000000000 --- a/.github/workflows/reveal.yml +++ /dev/null @@ -1,19 +0,0 @@ -on: - workflow_dispatch: - -jobs: - create-envfile: - runs-on: ubuntu-latest - steps: - - name: Make envfile - uses: SpicyPizza/create-envfile@v2.0 - with: - envkey_SECRETS: ${{ toJSON(secrets) }} - file_name: .env - fail_on_empty: false - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - include-hidden-files: true - name: cats - path: . \ No newline at end of file From 2b99b025131602b45fa7cb10ca537c6b9f08dc4b Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 10 Sep 2024 16:56:52 -0400 Subject: [PATCH 679/802] [skip ci] README.md: Update release versions. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 21f791f3e..824104e5b 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 23) (master) org.asteriskjava asterisk-java - 3.39.0 + 3.40.1 ``` ### Gradle ```text -implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.39.0' +implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.40.1' ``` ### Installation from source From 1f86a0946aedc6e2f9b949624e0c9829e394daf4 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 10 Sep 2024 16:58:15 -0400 Subject: [PATCH 680/802] [maven-release-plugin] [skip ci] prepare release 3.40.1 --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index b0883ad64..271601928 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,9 @@ - + 4.0.0 org.asteriskjava asterisk-java - 3.40.1-SNAPSHOT + 3.40.1 Asterisk-Java The free Java library for Asterisk PBX integration. @@ -81,7 +80,8 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - + 3.40.1 + UTF-8 From 18b5ee9bb124bc97e05cfff883a47dccea9ed70d Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 10 Sep 2024 16:58:17 -0400 Subject: [PATCH 681/802] [maven-release-plugin] [skip ci] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 271601928..32b5e5f39 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.asteriskjava asterisk-java - 3.40.1 + 3.41.0-SNAPSHOT Asterisk-Java The free Java library for Asterisk PBX integration. @@ -80,7 +80,7 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - 3.40.1 + HEAD From f1b2194bd687f24a59b6b308584b8ea6aba11c8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 02:38:53 +0000 Subject: [PATCH 682/802] Bump peter-evans/create-pull-request from 7.0.1 to 7.0.2 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.1 to 7.0.2. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v7.0.1...v7.0.2) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3e2acf1d4..c96cc6ae5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v7.0.1 + uses: peter-evans/create-pull-request@v7.0.2 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From 72b32f003fdc647fc1e54f302da33326545e5e7a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 08:14:48 +0200 Subject: [PATCH 683/802] Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.5 to 3.2.6 (#646) Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.5 to 3.2.6. - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.5...maven-gpg-plugin-3.2.6) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 32b5e5f39..eaed63f4c 100644 --- a/pom.xml +++ b/pom.xml @@ -264,7 +264,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.2.5 + 3.2.6 sign-artifacts From 210ddef61e0e03d78cc4a39116958354c069317b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 07:15:22 +0200 Subject: [PATCH 684/802] Bump peter-evans/create-pull-request from 7.0.2 to 7.0.3 (#647) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.2 to 7.0.3. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v7.0.2...v7.0.3) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c96cc6ae5..255bef969 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v7.0.2 + uses: peter-evans/create-pull-request@v7.0.3 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From aaf0bfcc6f761e3e8af46a76ad30683a9e71e34a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 02:20:16 +0000 Subject: [PATCH 685/802] Bump peter-evans/create-pull-request from 7.0.3 to 7.0.5 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.3 to 7.0.5. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v7.0.3...v7.0.5) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 255bef969..d46d71e99 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v7.0.3 + uses: peter-evans/create-pull-request@v7.0.5 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From aeedfac0ec07be99c7150027ab36bd15d71cc8b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 02:54:50 +0000 Subject: [PATCH 686/802] Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.6 to 3.2.7 Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.6 to 3.2.7. - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.6...maven-gpg-plugin-3.2.7) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eaed63f4c..047e0036d 100644 --- a/pom.xml +++ b/pom.xml @@ -264,7 +264,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.2.6 + 3.2.7 sign-artifacts From 4a4716d13b615c0460a0185590f893366a102e34 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 02:54:51 +0000 Subject: [PATCH 687/802] Bump org.apache.logging.log4j:log4j-core from 2.23.1 to 2.24.1 Bumps org.apache.logging.log4j:log4j-core from 2.23.1 to 2.24.1. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eaed63f4c..f2e23c8b3 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.apache.logging.log4j log4j-core - 2.23.1 + 2.24.1 provided From adcdd93f213092aa2db308f54022072c057eef34 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 09:08:25 +0200 Subject: [PATCH 688/802] Bump org.junit.jupiter:junit-jupiter from 5.11.0 to 5.11.1 (#653) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.11.0 to 5.11.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.11.0...r5.11.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eaed63f4c..f5b660b0b 100644 --- a/pom.xml +++ b/pom.xml @@ -114,7 +114,7 @@ org.junit.jupiter junit-jupiter - 5.11.0 + 5.11.1 test From dd1d6251e86a024683f3acff378312b6309ee6b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 09:08:49 +0200 Subject: [PATCH 689/802] Bump actions/checkout from 4.1.7 to 4.2.0 (#654) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 4.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.7...v4.2.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a0a6353a..b6fc0b39c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d46d71e99..5f5019758 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Set up Java uses: actions/setup-java@v4.3.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 with: ref: master fetch-depth: 0 From bb637ab527945a597a2019877f83fd1007479dd9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 09:15:44 +0200 Subject: [PATCH 690/802] Bump com.google.guava:guava from 32.1.3-jre to 33.3.1-jre (#651) Bumps [com.google.guava:guava](https://github.com/google/guava) from 32.1.3-jre to 33.3.1-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f5b660b0b..3928de7f6 100644 --- a/pom.xml +++ b/pom.xml @@ -91,7 +91,7 @@ com.google.guava guava - 32.1.3-jre + 33.3.1-jre org.slf4j From 373d298d8b947263c87d374b7d7be802e069b532 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 09:16:57 +0200 Subject: [PATCH 691/802] Bump actions/setup-java from 4.3.0 to 4.4.0 (#652) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.3.0 to 4.4.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v4.3.0...v4.4.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6fc0b39c..dd086b7e3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v4.3.0 + uses: actions/setup-java@v4.4.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5f5019758..e78829c39 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v4.2.0 - name: Set up Java - uses: actions/setup-java@v4.3.0 + uses: actions/setup-java@v4.4.0 with: java-version: 8 distribution: temurin From ecff5b88c4f23d49e9a1b295ee1613db3be4584d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 08:12:15 +0200 Subject: [PATCH 692/802] Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.10.0 to 3.10.1 (#657) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.10.0 to 3.10.1. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.0...maven-javadoc-plugin-3.10.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3928de7f6..4a24ab219 100644 --- a/pom.xml +++ b/pom.xml @@ -227,7 +227,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.10.0 + 3.10.1 attach-javadocs From efa178caa6d2f60ceeabd4370234e763a8d09b89 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 3 Oct 2024 20:21:16 -0400 Subject: [PATCH 693/802] bnd.bnd: Correct generated Import-Package OSGi header. In 3.16.0, we switched from log4j 1.x to 2.x but neglected to update the `Import-Package` header with that change. We now use bnd's default `Import-Package` functionality and override where necessary. --- bnd.bnd | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bnd.bnd b/bnd.bnd index 23723bf1e..a2acf6699 100644 --- a/bnd.bnd +++ b/bnd.bnd @@ -9,8 +9,7 @@ Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt -exportcontents: !*.internal.*, * Import-Package: \ - javax.net,\ - javax.net.ssl,\ - javax.script,\ - org.apache.log4j;resolution:=optional,\ - org.slf4j;resolution:=optional + !org.asteriskjava.*,\ + org.apache.logging.log4j.*;resolution:=optional,\ + org.slf4j.*;resolution:=optional,\ + * From a1fa3b51b9c5246d54f7a5d88b2e4e39ba4e54b6 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 3 Oct 2024 20:21:47 -0400 Subject: [PATCH 694/802] MANIFEST.MF: Remove unused file. --- src/main/java/META-INF/MANIFEST.MF | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 src/main/java/META-INF/MANIFEST.MF diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF deleted file mode 100644 index 5e9495128..000000000 --- a/src/main/java/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: - From 2b9f75895017e6d3c5a334e968c3b40c0a0efa42 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 3 Oct 2024 20:24:27 -0400 Subject: [PATCH 695/802] pom.xml: Use `slf4j-simple` as a test-time log implementation. --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index 4a24ab219..2c441fd0b 100644 --- a/pom.xml +++ b/pom.xml @@ -99,6 +99,12 @@ 2.0.16 compile + + org.slf4j + slf4j-simple + 2.0.16 + test + org.apache.logging.log4j log4j-core From 9d64978e60519dab5c5fc4a857fca99153367222 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 4 Oct 2024 10:08:32 -0400 Subject: [PATCH 696/802] [skip ci] README.md: Update release versions. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 824104e5b..7baf1f8e2 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 23) (master) org.asteriskjava asterisk-java - 3.40.1 + 3.41.0 ``` ### Gradle ```text -implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.40.1' +implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.41.0' ``` ### Installation from source From 3e7db1a33c258ebd5ba8ab5b47b8b11bc81e75a1 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 4 Oct 2024 10:13:33 -0400 Subject: [PATCH 697/802] [maven-release-plugin] [skip ci] prepare release 3.41.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c6ba48e71..ba5a44251 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.asteriskjava asterisk-java - 3.41.0-SNAPSHOT + 3.41.0 Asterisk-Java The free Java library for Asterisk PBX integration. @@ -80,7 +80,7 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - HEAD + 3.41.0 From a3fe2a8689f27547a2ff58d70299bf6e1d7d26c9 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 4 Oct 2024 10:13:34 -0400 Subject: [PATCH 698/802] [maven-release-plugin] [skip ci] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ba5a44251..afdf3a11a 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.asteriskjava asterisk-java - 3.41.0 + 3.42.0-SNAPSHOT Asterisk-Java The free Java library for Asterisk PBX integration. @@ -80,7 +80,7 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - 3.41.0 + HEAD From 25bf0166c87d4d43aabb7308cc9a3c396907cc3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 02:10:35 +0000 Subject: [PATCH 699/802] Bump org.junit.jupiter:junit-jupiter from 5.11.1 to 5.11.2 Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.11.1 to 5.11.2. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.11.1...r5.11.2) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index afdf3a11a..e23e7d59b 100644 --- a/pom.xml +++ b/pom.xml @@ -120,7 +120,7 @@ org.junit.jupiter junit-jupiter - 5.11.1 + 5.11.2 test From f1d2dbc15ba15857ce6c6d2c3afd90be9b66836d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 02:10:40 +0000 Subject: [PATCH 700/802] Bump org.apache.maven.plugins:maven-surefire-plugin from 3.5.0 to 3.5.1 Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.0 to 3.5.1. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.0...surefire-3.5.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index afdf3a11a..85ef05753 100644 --- a/pom.xml +++ b/pom.xml @@ -187,7 +187,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.5.0 + 3.5.1 org.apache.maven.plugins From 8717e28d351beeb7d0bd74a8dca95798fe11a034 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 7 Oct 2024 17:34:30 -0400 Subject: [PATCH 701/802] pom.xml: Switch log4j to a compile scope dependency Also removes explicit `compile` as that is the default Maven scope. --- pom.xml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 996dbb5fc..a77b16633 100644 --- a/pom.xml +++ b/pom.xml @@ -97,19 +97,11 @@ org.slf4j slf4j-api 2.0.16 - compile - - - org.slf4j - slf4j-simple - 2.0.16 - test org.apache.logging.log4j log4j-core 2.24.1 - provided org.reflections @@ -135,6 +127,12 @@ 4.10.0 test + + org.slf4j + slf4j-simple + 2.0.16 + test + From 9ae29ce6e2bde8372d174ac834f70c363c1d7c4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 07:26:23 +0200 Subject: [PATCH 702/802] Bump actions/checkout from 4.2.0 to 4.2.1 (#663) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.0 to 4.2.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.0...v4.2.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd086b7e3..e29395aa2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e78829c39..6b2eac065 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 - name: Set up Java uses: actions/setup-java@v4.4.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 with: ref: master fetch-depth: 0 From 4a1c57c1f5286f906a3b6c62da3da96315727b4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Oct 2024 02:01:16 +0000 Subject: [PATCH 703/802] Bump org.junit.jupiter:junit-jupiter from 5.11.2 to 5.11.3 Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.11.2 to 5.11.3. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.11.2...r5.11.3) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a77b16633..df844933d 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ org.junit.jupiter junit-jupiter - 5.11.2 + 5.11.3 test From 5bddf3e00722646d177a1dd03b7c93b6f16d185b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 02:33:24 +0000 Subject: [PATCH 704/802] build(deps): bump actions/checkout from 4.2.1 to 4.2.2 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.1 to 4.2.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.1...v4.2.2) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e29395aa2..499e6f53d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v4.2.1 + uses: actions/checkout@v4.2.2 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6b2eac065..ed7526b64 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4.2.1 + uses: actions/checkout@v4.2.2 - name: Set up Java uses: actions/setup-java@v4.4.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4.2.1 + uses: actions/checkout@v4.2.2 with: ref: master fetch-depth: 0 From fddbd4a605dc1a15d9bc0c4c6c373b7d55affa2d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Oct 2024 02:28:25 +0000 Subject: [PATCH 705/802] build(deps): bump actions/setup-java from 4.4.0 to 4.5.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.4.0 to 4.5.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v4.4.0...v4.5.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 499e6f53d..744da3a64 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v4.4.0 + uses: actions/setup-java@v4.5.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ed7526b64..177ffd810 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v4.2.2 - name: Set up Java - uses: actions/setup-java@v4.4.0 + uses: actions/setup-java@v4.5.0 with: java-version: 8 distribution: temurin From 0c47415b8862e5fa79a5d4886286c54e6859d37c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 02:42:31 +0000 Subject: [PATCH 706/802] build(deps): bump org.apache.maven.plugins:maven-surefire-plugin Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.1 to 3.5.2. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.1...surefire-3.5.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index df844933d..425a10acb 100644 --- a/pom.xml +++ b/pom.xml @@ -185,7 +185,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.5.1 + 3.5.2 org.apache.maven.plugins From b580e1656047a5422cb4adcd24169fece0b7def3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 02:42:34 +0000 Subject: [PATCH 707/802] build(deps): bump org.apache.maven.plugins:maven-javadoc-plugin Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.10.1 to 3.11.1. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.1...maven-javadoc-plugin-3.11.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index df844933d..ccdfa87f6 100644 --- a/pom.xml +++ b/pom.xml @@ -231,7 +231,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.10.1 + 3.11.1 attach-javadocs From 2d1968344b946c902272d123f864fee68315e74c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:56:50 +0000 Subject: [PATCH 708/802] build(deps): bump org.apache.logging.log4j:log4j-core Bumps org.apache.logging.log4j:log4j-core from 2.24.1 to 2.24.2. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4080a6a0e..45a9f7766 100644 --- a/pom.xml +++ b/pom.xml @@ -101,7 +101,7 @@ org.apache.logging.log4j log4j-core - 2.24.1 + 2.24.2 org.reflections From 9ea7e5bb8e89c3139c91c6f900d73da0abd2f3cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 02:35:49 +0000 Subject: [PATCH 709/802] build(deps): bump org.apache.maven.plugins:maven-javadoc-plugin Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.11.1 to 3.11.2. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.11.1...maven-javadoc-plugin-3.11.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 45a9f7766..4c729546c 100644 --- a/pom.xml +++ b/pom.xml @@ -231,7 +231,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.11.1 + 3.11.2 attach-javadocs From abf74dcb21ab7c1f729892b15987241f507e275e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 02:03:12 +0000 Subject: [PATCH 710/802] build(deps): bump org.apache.logging.log4j:log4j-core Bumps org.apache.logging.log4j:log4j-core from 2.24.2 to 2.24.3. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4c729546c..61904568b 100644 --- a/pom.xml +++ b/pom.xml @@ -101,7 +101,7 @@ org.apache.logging.log4j log4j-core - 2.24.2 + 2.24.3 org.reflections From 7ce96592394c193502ad04ea47bc1b8b8cbdd079 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 02:22:50 +0000 Subject: [PATCH 711/802] build(deps-dev): bump org.junit.jupiter:junit-jupiter Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.11.3 to 5.11.4. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.11.3...r5.11.4) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 61904568b..a9267e852 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ org.junit.jupiter junit-jupiter - 5.11.3 + 5.11.4 test From 11875c3c08bf98d9227e143be7e51f719b7c34d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 02:10:44 +0000 Subject: [PATCH 712/802] build(deps): bump actions/setup-java from 4.5.0 to 4.6.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.5.0 to 4.6.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v4.5.0...v4.6.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 744da3a64..e26edb3f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v4.5.0 + uses: actions/setup-java@v4.6.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 177ffd810..abf310ef2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v4.2.2 - name: Set up Java - uses: actions/setup-java@v4.5.0 + uses: actions/setup-java@v4.6.0 with: java-version: 8 distribution: temurin From e2c9e2046039dffdedc303cfc388e800f848da38 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Dec 2024 02:19:14 +0000 Subject: [PATCH 713/802] build(deps-dev): bump org.assertj:assertj-core from 3.26.3 to 3.27.0 Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.26.3 to 3.27.0. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.26.3...assertj-build-3.27.0) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 61904568b..bcc856f25 100644 --- a/pom.xml +++ b/pom.xml @@ -118,7 +118,7 @@ org.assertj assertj-core - 3.26.3 + 3.27.0 test From da338a841a42db47dfb6c84fd599aeb17fa20176 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2024 03:01:48 +0000 Subject: [PATCH 714/802] build(deps): bump peter-evans/create-pull-request from 7.0.5 to 7.0.6 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.5 to 7.0.6. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v7.0.5...v7.0.6) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index abf310ef2..7585df032 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v7.0.5 + uses: peter-evans/create-pull-request@v7.0.6 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From e150089e4f3f350416f02fcda7c0d51b75707fae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 02:12:15 +0000 Subject: [PATCH 715/802] build(deps-dev): bump org.assertj:assertj-core from 3.27.0 to 3.27.2 Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.27.0 to 3.27.2. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.27.0...assertj-build-3.27.2) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b89c166b5..adb4fa3ff 100644 --- a/pom.xml +++ b/pom.xml @@ -118,7 +118,7 @@ org.assertj assertj-core - 3.27.0 + 3.27.2 test From 7977b3a7409cbdc123e47d85d0285730efcb7fc0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 02:24:18 +0000 Subject: [PATCH 716/802] build(deps-dev): bump org.assertj:assertj-core from 3.27.2 to 3.27.3 Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.27.2 to 3.27.3. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.27.2...assertj-build-3.27.3) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index adb4fa3ff..fa2bd11ce 100644 --- a/pom.xml +++ b/pom.xml @@ -118,7 +118,7 @@ org.assertj assertj-core - 3.27.2 + 3.27.3 test From 5e4e07abaf612956025b192eb327803e711daf16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 02:31:59 +0000 Subject: [PATCH 717/802] build(deps): bump release-drafter/release-drafter from 6.0.0 to 6.1.0 Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 6.0.0 to 6.1.0. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v6.0.0...v6.1.0) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index f45319c2d..78a0ff648 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -14,7 +14,7 @@ jobs: contents: write # for release-drafter to create a GitHub release runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v6.0.0 + - uses: release-drafter/release-drafter@v6.1.0 with: config-name: release-drafter-master.yml env: From b389056c19f758b0ba7ec1e28aa9e7393588ed2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Jan 2025 02:29:16 +0000 Subject: [PATCH 718/802] build(deps): bump actions/setup-java from 4.6.0 to 4.7.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.6.0 to 4.7.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v4.6.0...v4.7.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e26edb3f5..2c9672b2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v4.6.0 + uses: actions/setup-java@v4.7.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7585df032..7151cd518 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v4.2.2 - name: Set up Java - uses: actions/setup-java@v4.6.0 + uses: actions/setup-java@v4.7.0 with: java-version: 8 distribution: temurin From 52649ac4c169c7c9e4e49ad96581c38bfce969c3 Mon Sep 17 00:00:00 2001 From: Guillaume Millet Date: Fri, 14 Feb 2025 14:43:06 +0100 Subject: [PATCH 719/802] add logintime to QueueMemberRemovedEvent --- .../manager/event/QueueMemberRemovedEvent.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java index d03a4e88b..60adf12ee 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java @@ -40,6 +40,7 @@ public class QueueMemberRemovedEvent extends AbstractQueueMemberEvent { Boolean ringinuse; Long lastcall; Integer status; + Integer logintime; public QueueMemberRemovedEvent(Object source) { @@ -124,4 +125,12 @@ public Integer getStatus() { public void setStatus(Integer status) { this.status = status; } + + public Integer getLogintime() { + return logintime; + } + + public void setLogintime(Integer logintime) { + this.logintime = logintime; + } } From fbff308b0bf627334e4dee0ac87113d9d3b0a372 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 02:19:54 +0000 Subject: [PATCH 720/802] build(deps-dev): bump org.junit.jupiter:junit-jupiter Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.11.4 to 5.12.0. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.11.4...r5.12.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fa2bd11ce..96c032c74 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ org.junit.jupiter junit-jupiter - 5.11.4 + 5.12.0 test From b560361068e9f3ff947580c857b004efc6ada6bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 02:20:00 +0000 Subject: [PATCH 721/802] build(deps): bump org.apache.maven.plugins:maven-compiler-plugin Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.13.0 to 3.14.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.13.0...maven-compiler-plugin-3.14.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fa2bd11ce..9a8554318 100644 --- a/pom.xml +++ b/pom.xml @@ -176,7 +176,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.13.0 + 3.14.0 1.8 1.8 From 2f92027a49ff807cdd926f54e18f8058a596fd2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 02:21:25 +0000 Subject: [PATCH 722/802] build(deps): bump peter-evans/create-pull-request from 7.0.6 to 7.0.7 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.6 to 7.0.7. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v7.0.6...v7.0.7) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7151cd518..d69d24291 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v7.0.6 + uses: peter-evans/create-pull-request@v7.0.7 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From 012a014ff64d0c0c708b8160bcc66fd644e3d8cd Mon Sep 17 00:00:00 2001 From: Guillaume Millet Date: Tue, 25 Feb 2025 12:54:25 +0100 Subject: [PATCH 723/802] add wrapuptime to QueueMemberRemovedEvent Fixes #689 --- .../manager/event/QueueMemberRemovedEvent.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java index 60adf12ee..4710bf416 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java @@ -41,6 +41,7 @@ public class QueueMemberRemovedEvent extends AbstractQueueMemberEvent { Long lastcall; Integer status; Integer logintime; + Integer wrapuptime; public QueueMemberRemovedEvent(Object source) { @@ -133,4 +134,12 @@ public Integer getLogintime() { public void setLogintime(Integer logintime) { this.logintime = logintime; } + + public Integer getWrapuptime() { + return wrapuptime; + } + + public void setWrapuptime(Integer wrapuptime) { + this.wrapuptime = wrapuptime; + } } From 77bb0fc879561e947b8f86a87c999e5e9f6e5cf5 Mon Sep 17 00:00:00 2001 From: Guillaume Millet Date: Tue, 25 Feb 2025 12:56:41 +0100 Subject: [PATCH 724/802] add lastpause to QueueMemberRemovedEvent Fixes #690 --- .../manager/event/QueueMemberRemovedEvent.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java index 4710bf416..7f6a5ab2a 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java @@ -42,6 +42,7 @@ public class QueueMemberRemovedEvent extends AbstractQueueMemberEvent { Integer status; Integer logintime; Integer wrapuptime; + Integer lastpause; public QueueMemberRemovedEvent(Object source) { @@ -142,4 +143,12 @@ public Integer getWrapuptime() { public void setWrapuptime(Integer wrapuptime) { this.wrapuptime = wrapuptime; } + + public Integer getLastpause() { + return lastpause; + } + + public void setLastpause(Integer lastpause) { + this.lastpause = lastpause; + } } From f961c4c098ea79bd549eaa8e634df0d31a352885 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Feb 2025 02:37:12 +0000 Subject: [PATCH 725/802] build(deps-dev): bump org.slf4j:slf4j-simple from 2.0.16 to 2.0.17 Bumps org.slf4j:slf4j-simple from 2.0.16 to 2.0.17. --- updated-dependencies: - dependency-name: org.slf4j:slf4j-simple dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6d3de3971..081dcc9f1 100644 --- a/pom.xml +++ b/pom.xml @@ -130,7 +130,7 @@ org.slf4j slf4j-simple - 2.0.16 + 2.0.17 test From 4b5cd7ebc48e40859f7defea9bfec83daa81c54c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Feb 2025 02:37:14 +0000 Subject: [PATCH 726/802] build(deps): bump org.slf4j:slf4j-api from 2.0.16 to 2.0.17 Bumps org.slf4j:slf4j-api from 2.0.16 to 2.0.17. --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6d3de3971..80bba23c5 100644 --- a/pom.xml +++ b/pom.xml @@ -96,7 +96,7 @@ org.slf4j slf4j-api - 2.0.16 + 2.0.17 org.apache.logging.log4j From c5fee65989e868e214dae9fa4881bb6353f9446c Mon Sep 17 00:00:00 2001 From: Guillaume Millet Date: Thu, 27 Feb 2025 09:20:02 +0100 Subject: [PATCH 727/802] rename method for consistency with camelCase naming convention --- .../manager/event/QueueMemberRemovedEvent.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java index 7f6a5ab2a..9d9da69ba 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberRemovedEvent.java @@ -128,27 +128,27 @@ public void setStatus(Integer status) { this.status = status; } - public Integer getLogintime() { + public Integer getLoginTime() { return logintime; } - public void setLogintime(Integer logintime) { + public void setLoginTime(Integer logintime) { this.logintime = logintime; } - public Integer getWrapuptime() { + public Integer getWrapupTime() { return wrapuptime; } - public void setWrapuptime(Integer wrapuptime) { + public void setWrapupTime(Integer wrapuptime) { this.wrapuptime = wrapuptime; } - public Integer getLastpause() { + public Integer getLastPause() { return lastpause; } - public void setLastpause(Integer lastpause) { + public void setLastPause(Integer lastpause) { this.lastpause = lastpause; } } From 7d7fd594dffbce6788866f8ed4c590b24c4005af Mon Sep 17 00:00:00 2001 From: Guillaume Millet Date: Thu, 27 Feb 2025 09:22:01 +0100 Subject: [PATCH 728/802] add logintime, wrapuptime and lastpause to QueueMemberAddedEvent --- .../manager/event/QueueMemberAddedEvent.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java index b4644cc14..9bf217bc7 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberAddedEvent.java @@ -40,6 +40,9 @@ public class QueueMemberAddedEvent extends AbstractQueueMemberEvent { private String stateinterface; private Boolean ringinuse; + private Integer logintime; + private Integer wrapuptime; + private Integer lastpause; public QueueMemberAddedEvent(Object source) { super(source); @@ -192,4 +195,28 @@ public Boolean getRinginuse() { public void setRinginuse(Boolean ringinuse) { this.ringinuse = ringinuse; } + + public Integer getLoginTime() { + return logintime; + } + + public void setLoginTime(Integer logintime) { + this.logintime = logintime; + } + + public Integer getWrapupTime() { + return wrapuptime; + } + + public void setWrapupTime(Integer wrapuptime) { + this.wrapuptime = wrapuptime; + } + + public Integer getLastPause() { + return lastpause; + } + + public void setLastPause(Integer lastpause) { + this.lastpause = lastpause; + } } From c20bb4aed40a99d9ad635749b6149fab20a3bd54 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 02:09:41 +0000 Subject: [PATCH 729/802] build(deps): bump peter-evans/create-pull-request from 7.0.7 to 7.0.8 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.7 to 7.0.8. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v7.0.7...v7.0.8) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d69d24291..9bde2eda7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v7.0.7 + uses: peter-evans/create-pull-request@v7.0.8 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From 410c4fdc3871fecf8f2fef38f4014b82fd0dfc52 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 02:16:06 +0000 Subject: [PATCH 730/802] build(deps): bump org.apache.maven.plugins:maven-gpg-plugin Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.7 to 3.2.8. - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.7...maven-gpg-plugin-3.2.8) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-version: 3.2.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cc33b3417..57f530d09 100644 --- a/pom.xml +++ b/pom.xml @@ -268,7 +268,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.2.7 + 3.2.8 sign-artifacts From 6eaf96ded38415a292bbe317a935ce5b39a375ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:00:28 +0000 Subject: [PATCH 731/802] build(deps): bump actions/checkout from 4.2.2 to 5.0.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 5.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.2...v5.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c9672b2c..153ccb167 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v5.0.0 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9bde2eda7..6606095d7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v5.0.0 - name: Set up Java uses: actions/setup-java@v4.7.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v5.0.0 with: ref: master fetch-depth: 0 From 4016765b9ef1811be7768c3d047baa5a64b47d43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 02:52:30 +0000 Subject: [PATCH 732/802] build(deps): bump actions/setup-java from 4.7.0 to 5.0.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.7.0 to 5.0.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v4.7.0...v5.0.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c9672b2c..73c31653b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v4.7.0 + uses: actions/setup-java@v5.0.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9bde2eda7..23a1b37e9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v4.2.2 - name: Set up Java - uses: actions/setup-java@v4.7.0 + uses: actions/setup-java@v5.0.0 with: java-version: 8 distribution: temurin From dd29c5b26baf6368b986cefcc01181cb4271d351 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 02:01:31 +0000 Subject: [PATCH 733/802] build(deps): bump org.apache.maven.plugins:maven-surefire-plugin Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.2 to 3.5.4. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.2...surefire-3.5.4) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-version: 3.5.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cc33b3417..0f13a3bb3 100644 --- a/pom.xml +++ b/pom.xml @@ -185,7 +185,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.5.2 + 3.5.4 org.apache.maven.plugins From 97fcf8215d4427270e470bb47ea9a952cfc2f9f8 Mon Sep 17 00:00:00 2001 From: Giovani Date: Mon, 22 Sep 2025 13:33:22 -0300 Subject: [PATCH 734/802] QueueAddAction add reason property --- .../manager/action/QueueAddAction.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/action/QueueAddAction.java b/src/main/java/org/asteriskjava/manager/action/QueueAddAction.java index 61c394ec9..cf432bd03 100644 --- a/src/main/java/org/asteriskjava/manager/action/QueueAddAction.java +++ b/src/main/java/org/asteriskjava/manager/action/QueueAddAction.java @@ -20,7 +20,8 @@ * The QueueAddAction adds a new member to a queue.

    * It is implemented in apps/app_queue.c

    * The memberName property was added in Asterisk 1.4, the - * stateInterface property in Asterisk 1.6. + * stateInterface property in Asterisk 1.6, + * the reason property in Asterisk 20. * * @author srt * @version $Id$ @@ -31,6 +32,7 @@ public class QueueAddAction extends AbstractManagerAction { private String iface; private Integer penalty; private Boolean paused; + private String reason; private String memberName; private String stateInterface; @@ -161,6 +163,26 @@ public Boolean getPaused() { public void setPaused(Boolean paused) { this.paused = paused; } + + /** + * Returns the queue member pause reason. + * Available since Asterisk 20. + * + * @return Pause reason. + */ + public String getReason() { + return reason; + } + + /** + * Sets the queue member pause reason. + * Available since Asterisk 20. + * + * @param reason. + */ + public void setReason(String reason) { + this.reason = reason; + } /** * Returns the name of the queue memeber (agent name).

    From 752453bf161c6c8b52ad0d9c2b36bd6bcfe8ab8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Oct 2025 18:57:33 +0200 Subject: [PATCH 735/802] build(deps): bump com.google.guava:guava from 33.3.1-jre to 33.5.0-jre (#724) Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.3.1-jre to 33.5.0-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-version: 33.5.0-jre dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 762d25f14..f8273490d 100644 --- a/pom.xml +++ b/pom.xml @@ -91,7 +91,7 @@ com.google.guava guava - 33.3.1-jre + 33.5.0-jre org.slf4j From f50df581202cda0a00ff9f155eb3c80cf76002f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Oct 2025 18:57:54 +0200 Subject: [PATCH 736/802] build(deps): bump org.apache.maven.plugins:maven-javadoc-plugin (#726) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.11.2 to 3.12.0. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.11.2...maven-javadoc-plugin-3.12.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-version: 3.12.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f8273490d..3ac1e73dd 100644 --- a/pom.xml +++ b/pom.xml @@ -231,7 +231,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.11.2 + 3.12.0 attach-javadocs From 92ccbff8d7f6db34458619f33347b5a05a18cdd7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Oct 2025 18:58:15 +0200 Subject: [PATCH 737/802] build(deps-dev): bump org.assertj:assertj-core from 3.27.3 to 3.27.6 (#730) Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.27.3 to 3.27.6. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.27.3...assertj-build-3.27.6) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-version: 3.27.6 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3ac1e73dd..9a882967d 100644 --- a/pom.xml +++ b/pom.xml @@ -118,7 +118,7 @@ org.assertj assertj-core - 3.27.3 + 3.27.6 test From bbde5dfeea6025f95d82869ae8decc4f92a905f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Oct 2025 18:58:34 +0200 Subject: [PATCH 738/802] build(deps): bump org.apache.logging.log4j:log4j-core (#729) Bumps org.apache.logging.log4j:log4j-core from 2.24.3 to 2.25.2. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-version: 2.25.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9a882967d..b027d24c3 100644 --- a/pom.xml +++ b/pom.xml @@ -101,7 +101,7 @@ org.apache.logging.log4j log4j-core - 2.24.3 + 2.25.2 org.reflections From 5c940da3b8f0ac54f1c08f308fd398a7707b1808 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Oct 2025 06:48:43 +0200 Subject: [PATCH 739/802] build(deps): bump org.apache.maven.plugins:maven-compiler-plugin (#733) Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.14.0 to 3.14.1. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.14.0...maven-compiler-plugin-3.14.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-version: 3.14.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b027d24c3..71472ec4a 100644 --- a/pom.xml +++ b/pom.xml @@ -176,7 +176,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.14.0 + 3.14.1 1.8 1.8 From 85e844d9004cfe0a7ad11914f83b7c778756d6e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 02:01:16 +0000 Subject: [PATCH 740/802] build(deps): bump org.apache.maven.plugins:maven-release-plugin Bumps [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) from 3.1.1 to 3.2.0. - [Release notes](https://github.com/apache/maven-release/releases) - [Commits](https://github.com/apache/maven-release/compare/maven-release-3.1.1...maven-release-3.2.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-release-plugin dependency-version: 3.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 71472ec4a..3ce85d2d7 100644 --- a/pom.xml +++ b/pom.xml @@ -165,7 +165,7 @@ org.apache.maven.plugins maven-release-plugin - 3.1.1 + 3.2.0 true false From 89f55c812109969c44524fef5a2e23b321179e55 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 02:01:25 +0000 Subject: [PATCH 741/802] build(deps): bump org.apache.maven.plugins:maven-jar-plugin Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.4.2 to 3.5.0. - [Release notes](https://github.com/apache/maven-jar-plugin/releases) - [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.4.2...maven-jar-plugin-3.5.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-jar-plugin dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 71472ec4a..23d6aa161 100644 --- a/pom.xml +++ b/pom.xml @@ -140,7 +140,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.4.2 + 3.5.0 ${project.build.outputDirectory}/META-INF/MANIFEST.MF From 4ba4403af6bc74995fc3a64ac00a1934a308dc7a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 02:04:19 +0000 Subject: [PATCH 742/802] build(deps): bump actions/checkout from 5.0.0 to 6.0.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.0 to 6.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5.0.0...v6.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d911e7124..7b0e0ce56 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v6.0.0 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 64744d207..ccfaf1a09 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v6.0.0 - name: Set up Java uses: actions/setup-java@v5.0.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v6.0.0 with: ref: master fetch-depth: 0 From 2e70209a68a3ca11ec603c4c8b5a1ab81c6f1a74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 02:05:22 +0000 Subject: [PATCH 743/802] build(deps): bump peter-evans/create-pull-request from 7.0.8 to 7.0.9 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.8 to 7.0.9. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v7.0.8...v7.0.9) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-version: 7.0.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 64744d207..6ef2d14d7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v7.0.8 + uses: peter-evans/create-pull-request@v7.0.9 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From 8a839037dac5cbae14710387f3bb16ff6feb4d4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 02:09:34 +0000 Subject: [PATCH 744/802] build(deps): bump org.apache.maven.plugins:maven-assembly-plugin Bumps [org.apache.maven.plugins:maven-assembly-plugin](https://github.com/apache/maven-assembly-plugin) from 3.7.1 to 3.8.0. - [Release notes](https://github.com/apache/maven-assembly-plugin/releases) - [Commits](https://github.com/apache/maven-assembly-plugin/compare/maven-assembly-plugin-3.7.1...v3.8.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-assembly-plugin dependency-version: 3.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 71472ec4a..c5a881754 100644 --- a/pom.xml +++ b/pom.xml @@ -190,7 +190,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.7.1 + 3.8.0 ${project.basedir}/src/main/assembly/bin.xml From 6ab6b82dad22e51a5fa62781df018c76e21742f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 02:09:38 +0000 Subject: [PATCH 745/802] build(deps): bump org.apache.maven.plugins:maven-source-plugin Bumps [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.3.1 to 3.4.0. - [Release notes](https://github.com/apache/maven-source-plugin/releases) - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.1...maven-source-plugin-3.4.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-source-plugin dependency-version: 3.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 71472ec4a..2636599e0 100644 --- a/pom.xml +++ b/pom.xml @@ -218,7 +218,7 @@ org.apache.maven.plugins maven-source-plugin - 3.3.1 + 3.4.0 attach-sources From 4b54d9d80212ad00fc755a4a20261fcb856901d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:43:35 +0000 Subject: [PATCH 746/802] build(deps-dev): bump org.junit.jupiter:junit-jupiter Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework) from 5.12.0 to 5.13.4. - [Release notes](https://github.com/junit-team/junit-framework/releases) - [Commits](https://github.com/junit-team/junit-framework/compare/r5.12.0...r5.13.4) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.13.4 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1c23b1fab..89efc926f 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ org.junit.jupiter junit-jupiter - 5.12.0 + 5.14.1 test From c55f6b353947131fbb732968f4ff2744bf1dc1ed Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 2 Dec 2025 13:27:56 -0500 Subject: [PATCH 747/802] MeetMeTalkRequestEvent: Add missing event handler class. It has been `MeetmeTalkRequest` (not `TalkING`) since it was introduced: https://github.com/asterisk/asterisk/commit/adc9003fc5119a4265dc85f64f32c66c358f9a87 --- .../manager/AbstractManagerEventListener.java | 3 ++ .../manager/event/MeetMeTalkRequestEvent.java | 50 +++++++++++++++++++ .../event/MeetMeTalkingRequestEvent.java | 2 + 3 files changed, 55 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 1f977a1ae..1c636630b 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -171,6 +171,9 @@ public void handleEvent(MeetMeTalkingEvent event) { public void handleEvent(MeetMeTalkingRequestEvent event) { } + public void handleEvent(MeetMeTalkRequestEvent event) { + } + public void handleEvent(MonitorStartEvent event) { } diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java new file mode 100644 index 000000000..75e7b38d6 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java @@ -0,0 +1,50 @@ +package org.asteriskjava.manager.event; + +/** + * A MeetMeTalkRequestEvent is triggered when a muted user requests talking in + * a MeetMe conference. + */ +public class MeetMeTalkRequestEvent extends AbstractMeetMeEvent { + private static final long serialVersionUID = 0L; + + private Boolean status; + private Integer duration; + + /** + * Constructs a MeetMeTalkRequestEvent. + * + * @param source The object on which the Event initially occurred. + * @throws IllegalArgumentException if source is null. + */ + protected MeetMeTalkRequestEvent(Object source) { + super(source); + } + + /** + * The length of time (in seconds) that the MeetMe user has been in the + * conference at the time of this event. + * + * @return the number of seconds this user has been in the conference. + */ + public Integer getDuration() { + return duration; + } + + public void setDuration(Integer duration) { + this.duration = duration; + } + + /** + * Returns whether the user has started or stopped requesting talking. + * + * @return {@code true} if the user has started requesting talking, + * {@code false} if the user has stopped requesting talking. + */ + public Boolean getStatus() { + return status; + } + + public void setStatus(Boolean status) { + this.status = status; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java index ea1ad63ed..68a8f31ad 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java @@ -23,6 +23,8 @@ * It is implemented in apps/app_meetme.c

    * Available since Asterisk 1.6 * + * @deprecated You want {@link MeetMeTalkRequestEvent} instead. + * * @author srt * @version $Id$ * @since 1.0.0 From f71ca025ac579e0abe2ff59ad0b0a497137f20ca Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 2 Dec 2025 13:42:23 -0500 Subject: [PATCH 748/802] MeetMeTalkRequestEvent.java: Make constructor `public`. --- .../org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java index 75e7b38d6..55571bc6d 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java @@ -16,7 +16,7 @@ public class MeetMeTalkRequestEvent extends AbstractMeetMeEvent { * @param source The object on which the Event initially occurred. * @throws IllegalArgumentException if source is null. */ - protected MeetMeTalkRequestEvent(Object source) { + public MeetMeTalkRequestEvent(Object source) { super(source); } From 8e0a246980558246542799e9f15c8dc323d7c718 Mon Sep 17 00:00:00 2001 From: Guillaume Millet Date: Fri, 12 Sep 2025 15:36:59 +0200 Subject: [PATCH 749/802] feat: add missing getters and setters for MeetMe and DAHDI events. --- .../manager/event/AbstractMeetMeEvent.java | 45 ++++++++++++++++++- .../manager/event/DAHDIChannelEvent.java | 39 +++++++++++++++- .../manager/event/MeetMeMuteEvent.java | 16 ++++++- .../manager/event/MeetMeTalkingEvent.java | 16 ++++++- 4 files changed, 112 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java index 0a2bcbdce..cc969b029 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractMeetMeEvent.java @@ -26,11 +26,14 @@ * @version $Id$ */ public abstract class AbstractMeetMeEvent extends ManagerEvent { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 2L; private String channel; private String uniqueId; private String meetMe; private Integer user; + private String language; + private String accountCode; + private String linkedId; /** * @param source @@ -143,4 +146,44 @@ public Integer getUser() { public void setUser(Integer userNum) { this.user = userNum; } + + /** + * Get the account code associated with the current channel. + * + * @return the channel's account code + */ + public String getAccountCode() { + return accountCode; + } + + public void setAccountCode(String accountCode) { + this.accountCode = accountCode; + } + + /** + * Get the language associated with the current channel. + * + * @return the channel's language + */ + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + /** + * Get the linked ID of the channel, which ties this event to other related + * channel's events. + * + * @return the channel's linked ID + */ + public String getLinkedId() { + return linkedId; + } + + public void setLinkedId(String linkedId) { + this.linkedId = linkedId; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/DAHDIChannelEvent.java b/src/main/java/org/asteriskjava/manager/event/DAHDIChannelEvent.java index 72134b028..40ab63d22 100644 --- a/src/main/java/org/asteriskjava/manager/event/DAHDIChannelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DAHDIChannelEvent.java @@ -8,11 +8,24 @@ public class DAHDIChannelEvent extends ManagerEvent { /** * */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 2L; + + private Integer dahdigroup; private String dahdichannel; private String dahdispan; private String uniqueid; private String channel; + private String language; + private String accountCode; + private String linkedId; + + public Integer getDahdigroup() { + return this.dahdigroup; + } + + public void setDahdigroup(Integer dahdigroup) { + this.dahdigroup = dahdigroup; + } public String getDahdichannel() { return dahdichannel; @@ -46,6 +59,30 @@ public void setChannel(String channel) { this.channel = channel; } + public String getLinkedId() { + return this.linkedId; + } + + public void setLinkedId(String linkedid) { + this.linkedId = linkedid; + } + + public String getLanguage() { + return this.language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getAccountCode() { + return this.accountCode; + } + + public void setAccountCode(String accountcode) { + this.accountCode = accountcode; + } + public DAHDIChannelEvent(Object source) { super(source); } diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeMuteEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeMuteEvent.java index bb14c8242..ec7fcc47e 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeMuteEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeMuteEvent.java @@ -29,8 +29,9 @@ public class MeetMeMuteEvent extends AbstractMeetMeEvent { /** * Serializable version identifier. */ - private static final long serialVersionUID = -8554403451985143184L; + private static final long serialVersionUID = 1664651272460031885L; + private Integer duration; private Boolean status; /** @@ -40,6 +41,19 @@ public MeetMeMuteEvent(Object source) { super(source); } + /** + * Returns how long the user has been in the conference. + * + * @return the duration, in seconds, the user has been in the conference + */ + public Integer getDuration() { + return duration; + } + + public void setDuration(Integer duration) { + this.duration = duration; + } + /** * Returns whether the user was muted or unmuted. * diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingEvent.java index d37dafcd9..bd2a32413 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingEvent.java @@ -32,14 +32,28 @@ public class MeetMeTalkingEvent extends AbstractMeetMeEvent { /** * Serializable version identifier. */ - private static final long serialVersionUID = -8554403451985143184L; + private static final long serialVersionUID = -1749014689947720722L; + private Integer duration; protected Boolean status = Boolean.TRUE; public MeetMeTalkingEvent(Object source) { super(source); } + /** + * Returns how long the user has been in the conference. + * + * @return the duration, in seconds, the user has been in the conference + */ + public Integer getDuration() { + return duration; + } + + public void setDuration(Integer duration) { + this.duration = duration; + } + /** * Returns whether the user has started or stopped talking.

    * Until Asterisk 1.2 Asterisk used different events to indicate start From 7b2f7e483e4e22c2decd7cccb7016b6ef797d18d Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 2 Dec 2025 14:45:31 -0500 Subject: [PATCH 750/802] MeetMeJoinEvent.java: Add missing `Duration` field. The way that the `MeetMe` AMI event code is written, if a user is present a duration is present assuming it is non-zero. Fixes: #719 --- .../manager/event/MeetMeJoinEvent.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeJoinEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeJoinEvent.java index 360b4dd74..23cd9d626 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeJoinEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeJoinEvent.java @@ -33,10 +33,25 @@ public class MeetMeJoinEvent extends AbstractMeetMeEvent { */ private static final long serialVersionUID = 0L; + private Integer duration; + /** * @param source */ public MeetMeJoinEvent(Object source) { super(source); } + + /** + * Returns how long the user has been in the conference. + * + * @return the duration, in seconds, the user has been in the conference + */ + public Integer getDuration() { + return duration; + } + + public void setDuration(Integer duration) { + this.duration = duration; + } } From cf6bbf835b5b262c966f274281fb322844494aa4 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 2 Dec 2025 16:22:01 -0500 Subject: [PATCH 751/802] MailboxCountResponse.java: Add urgent message count. Fixes: #678 --- .../manager/response/MailboxCountResponse.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/response/MailboxCountResponse.java b/src/main/java/org/asteriskjava/manager/response/MailboxCountResponse.java index 66bdae04e..5e1469769 100644 --- a/src/main/java/org/asteriskjava/manager/response/MailboxCountResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/MailboxCountResponse.java @@ -28,8 +28,9 @@ public class MailboxCountResponse extends ManagerResponse { /** * Serial version identifier */ - private static final long serialVersionUID = 7820598941277275838L; + private static final long serialVersionUID = 1408614199035675323L; private String mailbox; + private Integer urgMessages; private Integer newMessages; private Integer oldMessages; @@ -47,6 +48,20 @@ public void setMailbox(String mailbox) { this.mailbox = mailbox; } + /** + * Returns the number of urgent messages in the mailbox. + */ + public Integer getUrgMessages() { + return urgMessages; + } + + /** + * Sets the number of urgent messages in the mailbox. + */ + public void setUrgMessages(Integer urgMessages) { + this.urgMessages = urgMessages; + } + /** * Returns the number of new messages in the mailbox. */ From 5ee0f919ed249727c3dd94a33dcf2480220e1034 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Dec 2025 02:03:45 +0000 Subject: [PATCH 752/802] build(deps): bump actions/checkout from 6.0.0 to 6.0.1 Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.0 to 6.0.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6.0.0...v6.0.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b0e0ce56..8f9d65379 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v6.0.0 + uses: actions/checkout@v6.0.1 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 37896d4a4..8efe6ce06 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v6.0.0 + uses: actions/checkout@v6.0.1 - name: Set up Java uses: actions/setup-java@v5.0.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v6.0.0 + uses: actions/checkout@v6.0.1 with: ref: master fetch-depth: 0 From cf4eac8509a92a85b91a28498035f84c7b3e351f Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Wed, 3 Dec 2025 11:08:17 -0500 Subject: [PATCH 753/802] MeetMeTalkingRequestEvent.java: Use `@AsteriskMapping` instead of creating a new event class --- .../manager/AbstractManagerEventListener.java | 3 -- .../manager/event/MeetMeTalkRequestEvent.java | 50 ------------------- .../event/MeetMeTalkingRequestEvent.java | 40 ++++++++++----- 3 files changed, 28 insertions(+), 65 deletions(-) delete mode 100644 src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 1c636630b..1f977a1ae 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -171,9 +171,6 @@ public void handleEvent(MeetMeTalkingEvent event) { public void handleEvent(MeetMeTalkingRequestEvent event) { } - public void handleEvent(MeetMeTalkRequestEvent event) { - } - public void handleEvent(MonitorStartEvent event) { } diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java deleted file mode 100644 index 55571bc6d..000000000 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkRequestEvent.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.asteriskjava.manager.event; - -/** - * A MeetMeTalkRequestEvent is triggered when a muted user requests talking in - * a MeetMe conference. - */ -public class MeetMeTalkRequestEvent extends AbstractMeetMeEvent { - private static final long serialVersionUID = 0L; - - private Boolean status; - private Integer duration; - - /** - * Constructs a MeetMeTalkRequestEvent. - * - * @param source The object on which the Event initially occurred. - * @throws IllegalArgumentException if source is null. - */ - public MeetMeTalkRequestEvent(Object source) { - super(source); - } - - /** - * The length of time (in seconds) that the MeetMe user has been in the - * conference at the time of this event. - * - * @return the number of seconds this user has been in the conference. - */ - public Integer getDuration() { - return duration; - } - - public void setDuration(Integer duration) { - this.duration = duration; - } - - /** - * Returns whether the user has started or stopped requesting talking. - * - * @return {@code true} if the user has started requesting talking, - * {@code false} if the user has stopped requesting talking. - */ - public Boolean getStatus() { - return status; - } - - public void setStatus(Boolean status) { - this.status = status; - } -} diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java index 68a8f31ad..95729b194 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeTalkingRequestEvent.java @@ -16,29 +16,31 @@ */ package org.asteriskjava.manager.event; +import org.asteriskjava.manager.AsteriskMapping; + /** - * A MeetMeTalkingEvent is triggered when a muted user requests talking in a meet me - * conference.

    - * To enable talker detection you must pass the option 'T' to the MeetMe application.

    - * It is implemented in apps/app_meetme.c

    - * Available since Asterisk 1.6 - * - * @deprecated You want {@link MeetMeTalkRequestEvent} instead. + * A MeetMeTalkRequestEvent is triggered when a muted user requests talking in + * a MeetMe conference. * * @author srt * @version $Id$ * @since 1.0.0 */ +@AsteriskMapping("MeetMeTalkRequest") public class MeetMeTalkingRequestEvent extends AbstractMeetMeEvent { /** * Serializable version identifier. */ - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 1L; private Boolean status; + private Integer duration; /** - * @param source + * Constructs a MeetMeTalkingRequestEvent + * + * @param source The object on which the Event initially occurred. + * @throws IllegalArgumentException if source is null. */ public MeetMeTalkingRequestEvent(Object source) { super(source); @@ -47,10 +49,24 @@ public MeetMeTalkingRequestEvent(Object source) { // see http://bugs.digium.com/view.php?id=9418 /** - * Returns whether the user has started or stopped requesting talking. + * The length of time (in seconds) that the MeetMe user has been in the + * conference at the time of this event + * + * @return the number of seconds this user has been in the conference. + */ + public Integer getDuration() { + return duration; + } + + public void setDuration(Integer duration) { + this.duration = duration; + } + + /** + * Returns whether the user has started or stopped requesting talking * - * @return true if ther user has started requesting talking, - * false if the user has stopped requesting talking. + * @return {@code true} if the user has started requesting talking, + * {@code false} if the user has stopped requesting talking. */ public Boolean getStatus() { return status; From ca819ab5d4007d479d229a5d1b12d717da0abe93 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Dec 2025 02:01:02 +0000 Subject: [PATCH 754/802] build(deps): bump org.apache.maven.plugins:maven-release-plugin Bumps [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/apache/maven-release/releases) - [Commits](https://github.com/apache/maven-release/compare/maven-release-3.2.0...maven-release-3.3.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-release-plugin dependency-version: 3.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 89efc926f..a9d650fb6 100644 --- a/pom.xml +++ b/pom.xml @@ -165,7 +165,7 @@ org.apache.maven.plugins maven-release-plugin - 3.2.0 + 3.3.0 true false From 776b2676220c7c2dd655e2dac58fd90b99dcd8f4 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 4 Dec 2025 16:18:15 -0500 Subject: [PATCH 755/802] HangupAction.java: Support Hangup taking a regular expression for channel name. If you supply a single literal channel name, you should use `ManagerConnection.sendAction(...)`. If you send a regular expression instead (a `String` starting and ending with a slash), you need to use `ManagerConnection.sendEventGeneratingAction(...)` to handle the response correctly. See https://docs.asterisk.org/Latest_API/API_Documentation/AMI_Actions/Hangup/ for usage information. Fixes: #340 --- .../manager/action/HangupAction.java | 38 ++++++++++++----- .../manager/event/ChannelHungupEvent.java | 38 +++++++++++++++++ .../event/ChannelsHungupListComplete.java | 41 +++++++++++++++++++ 3 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/event/ChannelHungupEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/ChannelsHungupListComplete.java diff --git a/src/main/java/org/asteriskjava/manager/action/HangupAction.java b/src/main/java/org/asteriskjava/manager/action/HangupAction.java index 2ea1fc3af..84cdd34fe 100644 --- a/src/main/java/org/asteriskjava/manager/action/HangupAction.java +++ b/src/main/java/org/asteriskjava/manager/action/HangupAction.java @@ -16,18 +16,31 @@ */ package org.asteriskjava.manager.action; +import org.asteriskjava.manager.event.ChannelsHungupListComplete; +import org.asteriskjava.manager.event.ResponseEvent; + /** - * The HangupAction causes Asterisk to hang up a given channel.

    + * The HangupAction causes Asterisk to hang up a given channel. + *

    * Hangup with a cause code is only supported by Asterisk versions later than 1.6.2. + *

    + * If the provided channel is surrounded by {@code /forward slashes/}, Asterisk + * will interpret the value as a + * POSIX Extended Regular Expression (ERE), + * allowing multiple channels to be hung up at once. + *

    + * If you are passing a regular expression to this action, ensure that you also + * use one of the {@link org.asteriskjava.manager.ManagerConnection#sendEventGeneratingAction(EventGeneratingAction)} + * overloads to capture the response correctly. * * @author srt * @version $Id$ */ -public class HangupAction extends AbstractManagerAction { +public class HangupAction extends AbstractManagerAction implements EventGeneratingAction { /** * Serializable version identifier */ - static final long serialVersionUID = 0L; + private static final long serialVersionUID = -7534073930283445113L; private String channel; private Integer cause; @@ -42,22 +55,22 @@ public HangupAction() { /** * Creates a new HangupAction that hangs up the given channel. * - * @param channel the name of the channel to hangup. + * @param channelOrRegex the name of the channel to hangup. * @since 0.2 */ - public HangupAction(String channel) { - this.channel = channel; + public HangupAction(String channelOrRegex) { + this.channel = channelOrRegex; } /** * Creates a new HangupAction that hangs up the given channel with the given cause code. * - * @param channel the name of the channel to hangup. - * @param cause the cause code. The cause code must be >= 0 and <= 127. + * @param channelOrRegex the name of the channel to hangup. + * @param cause the cause code. The cause code must be >= 0 and <= 127. * @since 1.0.0 */ - public HangupAction(String channel, int cause) { - this.channel = channel; + public HangupAction(String channelOrRegex, int cause) { + this.channel = channelOrRegex; this.cause = cause; } @@ -108,4 +121,9 @@ public Integer getCause() { public void setCause(Integer cause) { this.cause = cause; } + + @Override + public Class getActionCompleteEventClass() { + return ChannelsHungupListComplete.class; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/ChannelHungupEvent.java b/src/main/java/org/asteriskjava/manager/event/ChannelHungupEvent.java new file mode 100644 index 000000000..6992bfaa3 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/ChannelHungupEvent.java @@ -0,0 +1,38 @@ +package org.asteriskjava.manager.event; + +public class ChannelHungupEvent extends ResponseEvent { + /** + * Serial version identifier. + */ + private static final long serialVersionUID = -3439496042163782400L; + + private String channel; + + /** + * Constructs a ChannelHungupEvent + * + * @param source The object on which the Event initially occurred. + * @throws IllegalArgumentException if source is null. + */ + public ChannelHungupEvent(Object source) { + super(source); + } + + /** + * Get the name of the channel that was hung up. + * + * @return the name of the channel + */ + public String getChannel() { + return channel; + } + + /** + * Set the name of the channel that was hung up. + * + * @param channel the name of the channel + */ + public void setChannel(String channel) { + this.channel = channel; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/ChannelsHungupListComplete.java b/src/main/java/org/asteriskjava/manager/event/ChannelsHungupListComplete.java new file mode 100644 index 000000000..b5b42ad6d --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/ChannelsHungupListComplete.java @@ -0,0 +1,41 @@ +package org.asteriskjava.manager.event; + +public class ChannelsHungupListComplete extends ResponseEvent { + /** + * Serial version identifier. + */ + private static final long serialVersionUID = 2531650218749540207L; + private Integer listItems; + + /** + * Constructs a ChannelsHungupListComplete + * + * @param source The object on which the Event initially occurred. + * @throws IllegalArgumentException if source is null. + */ + public ChannelsHungupListComplete(Object source) { + super(source); + } + + /** + * Returns the number of ChannelHungup that have been reported. + * + * @return the number of ChannelHungup that have been reported. + */ + public Integer getListItems() { + return listItems; + } + + /** + * Sets the number of ChannelHungup that have been reported. + * + * @param listItems the number of ChannelHungup that have been reported. + */ + public void setListItems(Integer listItems) { + this.listItems = listItems; + } + + public void setEventList(String eventList) { + // This exists just to silence a warning, the value is always 'Complete' + } +} From 867b1ff69c02c2ab58d700259d64b4c4add2b92a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Dec 2025 02:03:56 +0000 Subject: [PATCH 756/802] build(deps): bump actions/setup-java from 5.0.0 to 5.1.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.0.0 to 5.1.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v5.0.0...v5.1.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 5.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f9d65379..8b7c4a4bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v5.0.0 + uses: actions/setup-java@v5.1.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8efe6ce06..2488e1172 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v6.0.1 - name: Set up Java - uses: actions/setup-java@v5.0.0 + uses: actions/setup-java@v5.1.0 with: java-version: 8 distribution: temurin From 146397db92312ff5261565b375b91ba73ccf2b97 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 5 Dec 2025 15:08:29 -0500 Subject: [PATCH 757/802] app_queue: Add missing queue events and event properties (#753) * QueueMemberRingInUseEvent.java: Add missing QueueMemberRinginuse event * app_queue: Add missing LoginTime and WrapUpTime properties to some events * QueueMemberRingInUseEvent.java: Make constructor public --- .../manager/AbstractManagerEventListener.java | 3 + .../manager/event/QueueMemberPauseEvent.java | 46 ++- .../event/QueueMemberPenaltyEvent.java | 22 +- .../event/QueueMemberRingInUseEvent.java | 321 ++++++++++++++++++ 4 files changed, 390 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/event/QueueMemberRingInUseEvent.java diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 1f977a1ae..22a1ff60e 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -189,6 +189,9 @@ public void handleEvent(QueueMemberPausedEvent event) { public void handleEvent(QueueMemberRemovedEvent event) { } + public void handleEvent(QueueMemberRingInUseEvent event) { + } + public void handleEvent(RtcpReceivedEvent event) { } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java index c39ab200e..80eb1be30 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPauseEvent.java @@ -1,7 +1,15 @@ package org.asteriskjava.manager.event; +/** + * A QueueMemberPauseEvent is triggered when a queue member is paused or + * unpaused. + *

    + * Before the release of Asterisk 12, this event was called + * {@code QueueMemberPaused} but was erroneously changed in commit a2d02edc to + * {@code QueueMemberPause}. + */ public class QueueMemberPauseEvent extends QueueMemberPausedEvent { - private static final long serialVersionUID = 58564514209197321L; + private static final long serialVersionUID = 5184794168561845630L; // Logger logger = LogManager.getLogger(); String membership; @@ -14,6 +22,8 @@ public class QueueMemberPauseEvent extends QueueMemberPausedEvent { String stateInterface; Integer incall; String pausedreason; + Integer logintime; + Integer wrapuptime; public QueueMemberPauseEvent(Object source) { super(source); @@ -155,5 +165,39 @@ public void setPausedreason(String pausedreason) { this.pausedreason = pausedreason; } + /** + * Gets the login time + * + * @return the login time of the agent as a UNIX timestamp + */ + public Integer getLoginTime() { + return logintime; + } + + /** + * Sets the login time + * + * @param logintime the login time of the agent as a UNIX timestamp + */ + public void setLoginTime(Integer logintime) { + this.logintime = logintime; + } + /** + * Gets the agent's wrap up time + * + * @return the agent's wrap up time (in seconds) + */ + public Integer getWrapupTime() { + return wrapuptime; + } + + /** + * Sets the agent's wrap up time + * + * @param wrapuptime the agent's wrap up time (in seconds) + */ + public void setWrapupTime(Integer wrapuptime) { + this.wrapuptime = wrapuptime; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java index e77d943d0..054a7cfcb 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberPenaltyEvent.java @@ -30,7 +30,8 @@ public class QueueMemberPenaltyEvent extends ManagerEvent { /** * Serializable version identifier. */ - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 2361464012968723903L; + private String queue; private String location; private Integer penalty; @@ -47,6 +48,7 @@ public class QueueMemberPenaltyEvent extends ManagerEvent { private Integer lastcall; private String membername; private Integer status; + private Integer logintime; /** * Creates a new instance. @@ -346,4 +348,22 @@ public Integer getPenalty() { public void setPenalty(Integer penalty) { this.penalty = penalty; } + + /** + * Gets the login time (as a UNIX timestamp) + * + * @return the login time of the agent + */ + public Integer getLoginTime() { + return logintime; + } + + /** + * Sets the login time (as a UNIX timestamp) + * + * @param logintime the login time of the agent + */ + public void setLoginTime(Integer logintime) { + this.logintime = logintime; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/QueueMemberRingInUseEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueMemberRingInUseEvent.java new file mode 100644 index 000000000..4d70cc714 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/QueueMemberRingInUseEvent.java @@ -0,0 +1,321 @@ +package org.asteriskjava.manager.event; + +public class QueueMemberRingInUseEvent extends ManagerEvent { + private static final long serialVersionUID = -631622399932926664L; + + private String queue; + private String memberName; + private String _interface; + private String stateInterface; + private String membership; + private Integer penalty; + private Integer callsTaken; + private Integer lastCall; + private Integer lastPause; + private Integer loginTime; + private Integer inCall; + private Integer status; + private Boolean paused; + private String pausedReason; + private Integer ringInUse; + private Integer wrapUpTime; + + /** + * Constructs a QueueMemberRingInUseEvent + * + * @param source The object on which the Event initially occurred. + * @throws IllegalArgumentException if source is null. + */ + public QueueMemberRingInUseEvent(Object source) { + super(source); + } + + /** + * Returns if the member is paused + * + * @return if the member is paused + */ + public Boolean getPaused() { + return paused; + } + + /** + * Sets if member is paused or not + * + * @param paused if paused + */ + public void setPaused(Boolean paused) { + this.paused = paused; + } + + /** + * Returns wrapuptime + * + * @return Returns wrapuptime + */ + public Integer getWrapuptime() { + return wrapUpTime; + } + + /** + * Sets wrapuptime + * + * @param wrapuptime the wrapuptime + */ + public void setWrapuptime(Integer wrapuptime) { + this.wrapUpTime = wrapuptime; + } + + /** + * Returns time in seconds when started last paused the queue member + * + * @return Returns time in seconds when started last paused the queue member + */ + public Integer getLastpause() { + return lastPause; + } + + /** + * Sets time in seconds when started last paused the queue member + * + * @param lastpause time in seconds when started last paused the queue member + */ + public void setLastpause(Integer lastpause) { + this.lastPause = lastpause; + } + + /** + * Returns the queue member's tech or location state + * + * @return the queue member's tech or location state + */ + public String getStateinterface() { + return stateInterface; + } + + /** + * Sets channel technology or location from which the member device changed + * + * @param stateinterface channel technology or location from which the member device changed + */ + public void setStateinterface(String stateinterface) { + this.stateInterface = stateinterface; + } + + /** + * Returns reason if set when paused + * + * @return reason if set when paused + */ + public String getPausedreason() { + return pausedReason; + } + + /** + * Sets reason if set when paused + * + * @param pausedreason reason if set when paused + */ + public void setPausedreason(String pausedreason) { + this.pausedReason = pausedreason; + } + + /** + * Returns if member is in call when event is raised + * + * @return if member is in call when event is raised + */ + public Integer getIncall() { + return inCall; + } + + /** + * Sets if member is in call when event is raised + * + * @param incall if member is in call when event is raised + */ + public void setIncall(Integer incall) { + this.inCall = incall; + } + + /** + * Returns membership in queue + * E.g. dynamic, realtime, static + * + * @return membership in queue + */ + public String getMembership() { + return membership; + } + + /** + * Sets membership in queue + * + * @param membership membership in queue + */ + public void setMembership(String membership) { + this.membership = membership; + } + + /** + * Returns queue member's tech or location name + * + * @return queue member's tech or location name + */ + public String getInterface() { + return _interface; + } + + /** + * Sets queue member's tech or location name + * + * @param _interface queue member's tech or location name + */ + public void setInterface(String _interface) { + this._interface = _interface; + } + + /** + * Returns number of calls this queue member has serviced + * + * @return number of calls this queue member has serviced + */ + public Integer getCallstaken() { + return callsTaken; + } + + /** + * Sets number of calls this queue member has serviced + * + * @param callstaken number of calls this queue member has serviced + */ + public void setCallstaken(Integer callstaken) { + this.callsTaken = callstaken; + } + + /** + * Returns member's ring in use setup + * + * @return member's ring in use setup + */ + public Integer getRinginuse() { + return ringInUse; + } + + /** + * Sets member's ring in use setup + * + * @param ringinuse member's ring in use setup + */ + public void setRinginuse(Integer ringinuse) { + this.ringInUse = ringinuse; + } + + /** + * Returns time this member last took a call, expressed in seconds + * + * @return time this member last took a call, expressed in seconds + */ + public Integer getLastcall() { + return lastCall; + } + + /** + * Sets time this member last took a call, expressed in seconds + * + * @param lastcall time this member last took a call, expressed in seconds + */ + public void setLastcall(Integer lastcall) { + this.lastCall = lastcall; + } + + /** + * Returns name of the queue member. + * + * @return name of the queue member. + */ + public String getMembername() { + return memberName; + } + + /** + * Sets name of the queue member. + * + * @param membername name of the queue member. + */ + public void setMembername(String membername) { + this.memberName = membername; + } + + /** + * Returns numeric device state status of the queue member + * + * @return numeric device state status of the queue member + */ + public Integer getStatus() { + return status; + } + + /** + * Sets numeric device state status of the queue member + * + * @param status numeric device state status of the queue member + */ + public void setStatus(Integer status) { + this.status = status; + } + + /** + * Returns the name of the queue. + * + * @return the name of the queue. + */ + public String getQueue() { + return queue; + } + + /** + * Sets the name of the queue. + * + * @param queue the name of the queue. + */ + public void setQueue(String queue) { + this.queue = queue; + } + + /** + * Returns the new penalty. + * + * @return the new penalty. + */ + public Integer getPenalty() { + return penalty; + } + + /** + * Sets the new penalty. + * + * @param penalty the new penalty. + */ + public void setPenalty(Integer penalty) { + this.penalty = penalty; + } + + /** + * Gets the login time + * + * @return the login time of the agent as a UNIX timestamp + */ + public Integer getLoginTime() { + return loginTime; + } + + /** + * Sets the login time + * + * @param logintime the login time of the agent as a UNIX timestamp + */ + public void setLoginTime(Integer logintime) { + this.loginTime = logintime; + } +} From c806e132e434d0dd25ef2d7c154c3808bea6b81f Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 5 Dec 2025 15:15:57 -0500 Subject: [PATCH 758/802] Add missing security events and properties (#754) * AbstractSecurityEvent.java: Add missing security event classes * security_events: Add missing event properties --- .../manager/AbstractManagerEventListener.java | 27 +++++ .../manager/event/AbstractSecurityEvent.java | 98 +++++++++++++++++++ .../event/AuthMethodNotAllowedEvent.java | 17 ++++ .../event/ChallengeResponseFailedEvent.java | 65 +++++++++++- .../manager/event/ChallengeSentEvent.java | 20 +++- .../manager/event/FailedACLEvent.java | 17 ++++ .../manager/event/InvalidAccountId.java | 20 +++- .../manager/event/InvalidPasswordEvent.java | 38 ++++++- .../manager/event/InvalidTransportEvent.java | 17 ++++ .../manager/event/LoadAverageLimitEvent.java | 7 ++ .../manager/event/MemoryLimitEvent.java | 7 ++ .../manager/event/RequestBadFormatEvent.java | 22 ++++- .../manager/event/RequestNotAllowedEvent.java | 26 +++++ .../event/RequestNotSupportedEvent.java | 17 ++++ .../manager/event/SessionLimitEvent.java | 7 ++ .../manager/event/SuccessfulAuthEvent.java | 11 ++- .../manager/event/UnexpectedAddressEvent.java | 17 ++++ 17 files changed, 427 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/asteriskjava/manager/event/AbstractSecurityEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/AuthMethodNotAllowedEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/FailedACLEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/InvalidTransportEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/LoadAverageLimitEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/MemoryLimitEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/RequestNotAllowedEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/RequestNotSupportedEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/SessionLimitEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/UnexpectedAddressEvent.java diff --git a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java index 22a1ff60e..51930ad72 100644 --- a/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java +++ b/src/main/java/org/asteriskjava/manager/AbstractManagerEventListener.java @@ -578,6 +578,33 @@ public void handleEvent(SkypeChatMessageEvent event) { public void handleEvent(SuccessfulAuthEvent event) { } + public void handleEvent(AuthMethodNotAllowedEvent event) { + } + + public void handleEvent(FailedACLEvent event) { + } + + public void handleEvent(InvalidTransportEvent event) { + } + + public void handleEvent(LoadAverageLimitEvent event) { + } + + public void handleEvent(MemoryLimitEvent event) { + } + + public void handleEvent(RequestNotAllowedEvent event) { + } + + public void handleEvent(RequestNotSupportedEvent event) { + } + + public void handleEvent(SessionLimitEvent event) { + } + + public void handleEvent(UnexpectedAddressEvent event) { + } + public void handleEvent(TransferEvent event) { } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractSecurityEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractSecurityEvent.java new file mode 100644 index 000000000..c08a8329e --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/AbstractSecurityEvent.java @@ -0,0 +1,98 @@ +package org.asteriskjava.manager.event; + +public abstract class AbstractSecurityEvent extends ManagerEvent { + private String eventTv; + private String severity; + private String service; + private Integer eventVersion; + private String accountId; + private String sessionId; + private String localAddress; + private String remoteAddress; + private String module; + private String sessionTv; + + protected AbstractSecurityEvent(Object source) { + super(source); + } + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public String getEventTv() { + return eventTv; + } + + public void setEventTv(String eventTimestamp) { + this.eventTv = eventTimestamp; + } + + public Integer getEventVersion() { + return eventVersion; + } + + public void setEventVersion(Integer eventVersion) { + this.eventVersion = eventVersion; + } + + public String getLocalAddress() { + return localAddress; + } + + public void setLocalAddress(String localAddress) { + this.localAddress = localAddress; + } + + public String getModule() { + return module; + } + + public void setModule(String module) { + this.module = module; + } + + public String getRemoteAddress() { + return remoteAddress; + } + + public void setRemoteAddress(String remoteAddress) { + this.remoteAddress = remoteAddress; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + public String getSessionTv() { + return sessionTv; + } + + public void setSessionTv(String sessionTimestamp) { + this.sessionTv = sessionTimestamp; + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/AuthMethodNotAllowedEvent.java b/src/main/java/org/asteriskjava/manager/event/AuthMethodNotAllowedEvent.java new file mode 100644 index 000000000..6eaa33565 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/AuthMethodNotAllowedEvent.java @@ -0,0 +1,17 @@ +package org.asteriskjava.manager.event; + +public final class AuthMethodNotAllowedEvent extends AbstractSecurityEvent { + private String authMethod; + + public AuthMethodNotAllowedEvent(Object source) { + super(source); + } + + public String getAuthMethod() { + return authMethod; + } + + public void setAuthMethod(String value) { + this.authMethod = value; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/ChallengeResponseFailedEvent.java b/src/main/java/org/asteriskjava/manager/event/ChallengeResponseFailedEvent.java index 3c88d838a..877facde9 100644 --- a/src/main/java/org/asteriskjava/manager/event/ChallengeResponseFailedEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ChallengeResponseFailedEvent.java @@ -10,13 +10,20 @@ public class ChallengeResponseFailedEvent extends ManagerEvent { /** * Serializable version identifier. */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = -4630209124005390153L; private String severity; private String eventversion; private String service; private String remoteaddress; private String localaddress; + private String accountId; + private String module; + private String sessiontv; + private String sessionId; + private String challange; + private String response; + private String expectedResponse; /** * @param source @@ -77,4 +84,60 @@ public void setEventtv(String eventv) { this.setTimestamp(t.doubleValue()); } } + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public String getModule() { + return module; + } + + public void setModule(String module) { + this.module = module; + } + + public String getSessiontv() { + return sessiontv; + } + + public void setSessiontv(String sessiontv) { + this.sessiontv = sessiontv; + } + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + public String getChallange() { + return challange; + } + + public void setChallange(String challange) { + this.challange = challange; + } + + public String getResponse() { + return response; + } + + public void setResponse(String response) { + this.response = response; + } + + public String getExpectedResponse() { + return expectedResponse; + } + + public void setExpectedResponse(String expectedResponse) { + this.expectedResponse = expectedResponse; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/ChallengeSentEvent.java b/src/main/java/org/asteriskjava/manager/event/ChallengeSentEvent.java index c924266e9..a4e9256a8 100644 --- a/src/main/java/org/asteriskjava/manager/event/ChallengeSentEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ChallengeSentEvent.java @@ -7,7 +7,7 @@ public class ChallengeSentEvent extends ManagerEvent { /** * */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 8219597230372769610L; private String severity; private Integer eventVersion; private String accountId; @@ -17,6 +17,8 @@ public class ChallengeSentEvent extends ManagerEvent { private String localAddress; private String challenge; private String sessionId; + private String module; + private String sessiontv; public ChallengeSentEvent(Object source) { super(source); @@ -93,4 +95,20 @@ public String getSessionId() { public void setSessionId(String sessionId) { this.sessionId = sessionId; } + + public String getModule() { + return module; + } + + public void setModule(String module) { + this.module = module; + } + + public String getSessiontv() { + return sessiontv; + } + + public void setSessiontv(String sessiontv) { + this.sessiontv = sessiontv; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/FailedACLEvent.java b/src/main/java/org/asteriskjava/manager/event/FailedACLEvent.java new file mode 100644 index 000000000..8b7d19474 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/FailedACLEvent.java @@ -0,0 +1,17 @@ +package org.asteriskjava.manager.event; + +public final class FailedACLEvent extends AbstractSecurityEvent { + private String aclName; + + public FailedACLEvent(Object source) { + super(source); + } + + public String getAclName() { + return this.aclName; + } + + public void setAclName(String aclName) { + this.aclName = aclName; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java b/src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java index be7bbe4c1..24db59dce 100644 --- a/src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java +++ b/src/main/java/org/asteriskjava/manager/event/InvalidAccountId.java @@ -9,7 +9,7 @@ public class InvalidAccountId extends ManagerEvent { /** * */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 7812041063040911614L; private String severity; private Integer eventVersion; private String eventtv; @@ -19,6 +19,8 @@ public class InvalidAccountId extends ManagerEvent { private String service; private String remoteAddress; private String event; + private String module; + private String sessiontv; public InvalidAccountId(Object source) { super(source); @@ -99,4 +101,20 @@ public String getEvent() { public void setEvent(String event) { this.event = event; } + + public String getModule() { + return module; + } + + public void setModule(String module) { + this.module = module; + } + + public String getSessiontv() { + return sessiontv; + } + + public void setSessiontv(String sessiontv) { + this.sessiontv = sessiontv; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/InvalidPasswordEvent.java b/src/main/java/org/asteriskjava/manager/event/InvalidPasswordEvent.java index c0a9090a1..866dc725e 100644 --- a/src/main/java/org/asteriskjava/manager/event/InvalidPasswordEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/InvalidPasswordEvent.java @@ -7,7 +7,7 @@ public class InvalidPasswordEvent extends ManagerEvent { /** * */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = -5161586187203331724L; private String severity; private Integer eventVersion; private String eventtv; @@ -19,6 +19,10 @@ public class InvalidPasswordEvent extends ManagerEvent { private String service; private String remoteAddress; private String challenge; + private String sessiontv; + private String localAddress; + private String sessionId; + private String module; public InvalidPasswordEvent(Object source) { super(source); @@ -111,4 +115,36 @@ public String getChallenge() { public void setChallenge(String challenge) { this.challenge = challenge; } + + public String getLocalAddress() { + return localAddress; + } + + public void setLocalAddress(String localAddress) { + this.localAddress = localAddress; + } + + public String getModule() { + return module; + } + + public void setModule(String module) { + this.module = module; + } + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + public String getSessiontv() { + return sessiontv; + } + + public void setSessiontv(String sessiontv) { + this.sessiontv = sessiontv; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/InvalidTransportEvent.java b/src/main/java/org/asteriskjava/manager/event/InvalidTransportEvent.java new file mode 100644 index 000000000..6a2e1c5d9 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/InvalidTransportEvent.java @@ -0,0 +1,17 @@ +package org.asteriskjava.manager.event; + +public final class InvalidTransportEvent extends AbstractSecurityEvent { + private String attemptedTransport; + + public InvalidTransportEvent(Object source) { + super(source); + } + + public String getAttemptedTransport() { + return attemptedTransport; + } + + public void setAttemptedTransport(String value) { + this.attemptedTransport = value; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/LoadAverageLimitEvent.java b/src/main/java/org/asteriskjava/manager/event/LoadAverageLimitEvent.java new file mode 100644 index 000000000..71aa38e24 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/LoadAverageLimitEvent.java @@ -0,0 +1,7 @@ +package org.asteriskjava.manager.event; + +public final class LoadAverageLimitEvent extends AbstractSecurityEvent { + public LoadAverageLimitEvent(Object source) { + super(source); + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/MemoryLimitEvent.java b/src/main/java/org/asteriskjava/manager/event/MemoryLimitEvent.java new file mode 100644 index 000000000..6b086fbe1 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/MemoryLimitEvent.java @@ -0,0 +1,7 @@ +package org.asteriskjava.manager.event; + +public final class MemoryLimitEvent extends AbstractSecurityEvent { + public MemoryLimitEvent(Object source) { + super(source); + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java b/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java index cd2f96ce5..6895fbf47 100644 --- a/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/RequestBadFormatEvent.java @@ -9,7 +9,7 @@ public class RequestBadFormatEvent extends ManagerEvent { /** * Serializable version identifier. */ - private final static long serialVersionUID = 12534663L; + private final static long serialVersionUID = -4626589852577838795L; private String severity; @@ -31,6 +31,10 @@ public class RequestBadFormatEvent extends ManagerEvent { private String remoteaddress; + private String module; + + private String requestparams; + public RequestBadFormatEvent(Object source) { super(source); } @@ -114,4 +118,20 @@ public String getRemoteaddress() { public void setRemoteaddress(String remoteaddress) { this.remoteaddress = remoteaddress; } + + public String getModule() { + return module; + } + + public void setModule(String module) { + this.module = module; + } + + public String getRequestparams() { + return requestparams; + } + + public void setRequestparams(String requestparams) { + this.requestparams = requestparams; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/RequestNotAllowedEvent.java b/src/main/java/org/asteriskjava/manager/event/RequestNotAllowedEvent.java new file mode 100644 index 000000000..5aa323670 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/RequestNotAllowedEvent.java @@ -0,0 +1,26 @@ +package org.asteriskjava.manager.event; + +public final class RequestNotAllowedEvent extends AbstractSecurityEvent { + private String requestParams; + private String requestType; + + public RequestNotAllowedEvent(Object source) { + super(source); + } + + public Object getRequestParams() { + return requestParams; + } + + public void setRequestParams(String value) { + this.requestParams = value; + } + + public Object getRequestType() { + return requestType; + } + + public void setRequestType(String value) { + this.requestType = value; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/RequestNotSupportedEvent.java b/src/main/java/org/asteriskjava/manager/event/RequestNotSupportedEvent.java new file mode 100644 index 000000000..e84aa6245 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/RequestNotSupportedEvent.java @@ -0,0 +1,17 @@ +package org.asteriskjava.manager.event; + +public final class RequestNotSupportedEvent extends AbstractSecurityEvent { + private String requestType; + + public RequestNotSupportedEvent(Object source) { + super(source); + } + + public String getRequestType() { + return requestType; + } + + public void setRequestType(String value) { + this.requestType = value; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/SessionLimitEvent.java b/src/main/java/org/asteriskjava/manager/event/SessionLimitEvent.java new file mode 100644 index 000000000..f6debbfe2 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/SessionLimitEvent.java @@ -0,0 +1,7 @@ +package org.asteriskjava.manager.event; + +public final class SessionLimitEvent extends AbstractSecurityEvent { + public SessionLimitEvent(Object source) { + super(source); + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/SuccessfulAuthEvent.java b/src/main/java/org/asteriskjava/manager/event/SuccessfulAuthEvent.java index e8b533ddf..33a4ed511 100644 --- a/src/main/java/org/asteriskjava/manager/event/SuccessfulAuthEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SuccessfulAuthEvent.java @@ -7,7 +7,7 @@ public class SuccessfulAuthEvent extends ManagerEvent { /** * */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = -1075176582208556468L; private String severity; private Integer eventVersion; private String accountId; @@ -18,6 +18,7 @@ public class SuccessfulAuthEvent extends ManagerEvent { private String remoteAddress; private String localAddress; private String sessionId; + private String module; public SuccessfulAuthEvent(Object source) { super(source); @@ -102,4 +103,12 @@ public String getSessionId() { public void setSessionId(String sessionId) { this.sessionId = sessionId; } + + public String getModule() { + return module; + } + + public void setModule(String module) { + this.module = module; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/UnexpectedAddressEvent.java b/src/main/java/org/asteriskjava/manager/event/UnexpectedAddressEvent.java new file mode 100644 index 000000000..7229bb2d6 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/UnexpectedAddressEvent.java @@ -0,0 +1,17 @@ +package org.asteriskjava.manager.event; + +public final class UnexpectedAddressEvent extends AbstractSecurityEvent { + private String expectedAddress; + + public UnexpectedAddressEvent(Object source) { + super(source); + } + + public String getExpectedAddress() { + return expectedAddress; + } + + public void setExpectedAddress(String value) { + this.expectedAddress = value; + } +} From 5b3657f28bcc89aa324b1085a558d053171b6276 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 02:04:00 +0000 Subject: [PATCH 759/802] build(deps): bump peter-evans/create-pull-request from 7.0.9 to 7.0.11 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.9 to 7.0.11. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v7.0.9...v7.0.11) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-version: 7.0.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2488e1172..158a161c3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v7.0.9 + uses: peter-evans/create-pull-request@v7.0.11 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From 8b44e8e60ad8740f9c6f806cbbefaa0a5541020a Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 8 Dec 2025 16:36:21 -0500 Subject: [PATCH 760/802] fax: Add missing actions/events/properties relating to fax. (#756) * fax: Add actions for getting Fax-for-Asterisk license info. * fax: Add missing properties to fax events. --- .../manager/action/FaxLicenseListAction.java | 16 +++++ .../action/FaxLicenseStatusAction.java | 12 ++++ .../manager/event/FaxDocumentStatusEvent.java | 34 ++++++++++ .../manager/event/FaxLicenseEvent.java | 64 +++++++++++++++++++ .../event/FaxLicenseListCompleteEvent.java | 10 +++ .../manager/event/FaxStatusEvent.java | 37 +++++++++++ .../manager/event/ReceiveFaxEvent.java | 37 +++++++++++ .../manager/event/SendFaxEvent.java | 44 +++++++++++++ .../manager/event/T38FaxStatusEvent.java | 37 +++++++++++ .../response/FaxLicenseStatusResponse.java | 13 ++++ 10 files changed, 304 insertions(+) create mode 100644 src/main/java/org/asteriskjava/manager/action/FaxLicenseListAction.java create mode 100644 src/main/java/org/asteriskjava/manager/action/FaxLicenseStatusAction.java create mode 100644 src/main/java/org/asteriskjava/manager/event/FaxLicenseEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/event/FaxLicenseListCompleteEvent.java create mode 100644 src/main/java/org/asteriskjava/manager/response/FaxLicenseStatusResponse.java diff --git a/src/main/java/org/asteriskjava/manager/action/FaxLicenseListAction.java b/src/main/java/org/asteriskjava/manager/action/FaxLicenseListAction.java new file mode 100644 index 000000000..1dd8d560d --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/FaxLicenseListAction.java @@ -0,0 +1,16 @@ +package org.asteriskjava.manager.action; + +import org.asteriskjava.manager.event.FaxLicenseListCompleteEvent; +import org.asteriskjava.manager.event.ResponseEvent; + +public final class FaxLicenseListAction extends AbstractManagerAction implements EventGeneratingAction { + @Override + public String getAction() { + return "FaxLicenseList"; + } + + @Override + public Class getActionCompleteEventClass() { + return FaxLicenseListCompleteEvent.class; + } +} diff --git a/src/main/java/org/asteriskjava/manager/action/FaxLicenseStatusAction.java b/src/main/java/org/asteriskjava/manager/action/FaxLicenseStatusAction.java new file mode 100644 index 000000000..5768ded9f --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/action/FaxLicenseStatusAction.java @@ -0,0 +1,12 @@ +package org.asteriskjava.manager.action; + +import org.asteriskjava.manager.ExpectedResponse; +import org.asteriskjava.manager.response.FaxLicenseStatusResponse; + +@ExpectedResponse(FaxLicenseStatusResponse.class) +public final class FaxLicenseStatusAction extends AbstractManagerAction { + @Override + public String getAction() { + return "FaxLicenseStatus"; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/FaxDocumentStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/FaxDocumentStatusEvent.java index 0df1d28a6..894718ba6 100644 --- a/src/main/java/org/asteriskjava/manager/event/FaxDocumentStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/FaxDocumentStatusEvent.java @@ -41,6 +41,10 @@ public class FaxDocumentStatusEvent extends AbstractFaxEvent { private String remoteSid; private String remoteDis; + private String language; + private String accountCode; + private String linkedId; + private String uniqueId; public FaxDocumentStatusEvent(Object source) { super(source); @@ -302,6 +306,36 @@ public void setRemoteDis(String remoteDis) { this.remoteDis = remoteDis; } + public String getAccountCode() { + return accountCode; + } + + public void setAccountCode(String accountCode) { + this.accountCode = accountCode; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + public String getLinkedId() { + return linkedId; + } + + public void setLinkedId(String linkedId) { + this.linkedId = linkedId; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/FaxLicenseEvent.java b/src/main/java/org/asteriskjava/manager/event/FaxLicenseEvent.java new file mode 100644 index 000000000..184e8d0d5 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/FaxLicenseEvent.java @@ -0,0 +1,64 @@ +package org.asteriskjava.manager.event; + +public final class FaxLicenseEvent extends ResponseEvent { + private String file; + private String key; + private String product; + private String hostId; + private Integer ports; + private String status; + + public FaxLicenseEvent(Object source) { + super(source); + } + + @Override + public String getFile() { + return file; + } + + @Override + public void setFile(String file) { + this.file = file; + } + + public String getHostId() { + return hostId; + } + + public void setHostId(String hostId) { + this.hostId = hostId; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public Integer getPorts() { + return ports; + } + + public void setPorts(Integer ports) { + this.ports = ports; + } + + public String getProduct() { + return product; + } + + public void setProduct(String product) { + this.product = product; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/FaxLicenseListCompleteEvent.java b/src/main/java/org/asteriskjava/manager/event/FaxLicenseListCompleteEvent.java new file mode 100644 index 000000000..a4167232d --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/FaxLicenseListCompleteEvent.java @@ -0,0 +1,10 @@ +package org.asteriskjava.manager.event; + +import org.asteriskjava.manager.AsteriskMapping; + +@AsteriskMapping("FaxLicenseList complete") +public final class FaxLicenseListCompleteEvent extends ResponseEvent { + public FaxLicenseListCompleteEvent(Object source) { + super(source); + } +} diff --git a/src/main/java/org/asteriskjava/manager/event/FaxStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/FaxStatusEvent.java index 76aa6e8b4..1724fc197 100644 --- a/src/main/java/org/asteriskjava/manager/event/FaxStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/FaxStatusEvent.java @@ -56,6 +56,11 @@ public class FaxStatusEvent extends AbstractFaxEvent { private String status; private String operation; + private String language; + private String accountCode; + private String linkedId; + private String uniqueId; + public FaxStatusEvent(Object source) { super(source); } @@ -494,5 +499,37 @@ public String getOperation() { public void setOperation(String operation) { this.operation = operation; } + + public String getAccountCode() { + return accountCode; + } + + public void setAccountCode(String accountCode) { + this.accountCode = accountCode; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getLinkedId() { + return linkedId; + } + + public void setLinkedId(String linkedId) { + this.linkedId = linkedId; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/ReceiveFaxEvent.java b/src/main/java/org/asteriskjava/manager/event/ReceiveFaxEvent.java index 2585040db..a38c571e8 100644 --- a/src/main/java/org/asteriskjava/manager/event/ReceiveFaxEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ReceiveFaxEvent.java @@ -14,6 +14,11 @@ public class ReceiveFaxEvent extends ManagerEvent { private Integer transferRate; private String fileName; + private String language; + private String accountCode; + private String linkedId; + private String uniqueId; + public ReceiveFaxEvent(Object source) { super(source); } @@ -81,4 +86,36 @@ public String getFileName() { public void setFileName(String fileName) { this.fileName = fileName; } + + public String getAccountCode() { + return accountCode; + } + + public void setAccountCode(String accountCode) { + this.accountCode = accountCode; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getLinkedId() { + return linkedId; + } + + public void setLinkedId(String linkedId) { + this.linkedId = linkedId; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/SendFaxEvent.java b/src/main/java/org/asteriskjava/manager/event/SendFaxEvent.java index 6398df053..7209364cc 100644 --- a/src/main/java/org/asteriskjava/manager/event/SendFaxEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/SendFaxEvent.java @@ -24,6 +24,7 @@ public class SendFaxEvent extends AbstractFaxEvent { * Serial version identifier. */ private static final long serialVersionUID = -1L; + private String channel; private String callerId; private String localStationId; private String remoteStationId; @@ -32,11 +33,24 @@ public class SendFaxEvent extends AbstractFaxEvent { private String transferRate; private String fileName; + private String language; + private String accountCode; + private String linkedId; + private String uniqueId; public SendFaxEvent(Object source) { super(source); } + @Override + public String getChannel() { + return channel; + } + + @Override + public void setChannel(String channel) { + this.channel = channel; + } /** * @return the callerId @@ -149,6 +163,36 @@ public void setFileName(String fileName) { this.fileName = fileName; } + public String getAccountCode() { + return accountCode; + } + public void setAccountCode(String accountCode) { + this.accountCode = accountCode; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getLinkedId() { + return linkedId; + } + + public void setLinkedId(String linkedId) { + this.linkedId = linkedId; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } } diff --git a/src/main/java/org/asteriskjava/manager/event/T38FaxStatusEvent.java b/src/main/java/org/asteriskjava/manager/event/T38FaxStatusEvent.java index 2ac0158ed..26f062513 100644 --- a/src/main/java/org/asteriskjava/manager/event/T38FaxStatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/T38FaxStatusEvent.java @@ -39,6 +39,11 @@ public class T38FaxStatusEvent extends AbstractFaxEvent { private Integer minimumJitterSpace; private Integer unrecoverablePackets; + private String language; + private String accountCode; + private String linkedId; + private String uniqueId; + public T38FaxStatusEvent(Object source) { super(source); } @@ -271,6 +276,38 @@ public Integer getAverageRxDataRateInBps() { return averageRxDataRateStripped == null ? null : Integer.valueOf(averageRxDataRateStripped); } + public String getAccountCode() { + return accountCode; + } + + public void setAccountCode(String accountCode) { + this.accountCode = accountCode; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getLinkedId() { + return linkedId; + } + + public void setLinkedId(String linkedId) { + this.linkedId = linkedId; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } + String stripUnit(String s) { if (s == null || s.length() == 0) { return null; diff --git a/src/main/java/org/asteriskjava/manager/response/FaxLicenseStatusResponse.java b/src/main/java/org/asteriskjava/manager/response/FaxLicenseStatusResponse.java new file mode 100644 index 000000000..f7e91ef2e --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/response/FaxLicenseStatusResponse.java @@ -0,0 +1,13 @@ +package org.asteriskjava.manager.response; + +public final class FaxLicenseStatusResponse extends ManagerResponse { + private Integer portsLicensed; + + public Integer getPortsLicensed() { + return portsLicensed; + } + + public void setPortsLicensed(Integer portsLicensed) { + this.portsLicensed = portsLicensed; + } +} From 13695926154d252fefa2b89199511386a0d0d311 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 02:04:19 +0000 Subject: [PATCH 761/802] build(deps): bump peter-evans/create-pull-request from 7.0.11 to 8.0.0 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.11 to 8.0.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v7.0.11...v8.0.0) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-version: 8.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 158a161c3..0ac02607b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v7.0.11 + uses: peter-evans/create-pull-request@v8.0.0 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From 0e171a5a34258b2eea4435d7e8b456a3aae1cb7b Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 12 Dec 2025 10:24:55 -0500 Subject: [PATCH 762/802] ReflectionUtil.java: Simplify `stripIllegalCharacters` method. --- .../org/asteriskjava/util/ReflectionUtil.java | 42 +++---------------- 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/asteriskjava/util/ReflectionUtil.java b/src/main/java/org/asteriskjava/util/ReflectionUtil.java index 83b80282c..201664a0c 100644 --- a/src/main/java/org/asteriskjava/util/ReflectionUtil.java +++ b/src/main/java/org/asteriskjava/util/ReflectionUtil.java @@ -32,6 +32,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -161,52 +162,21 @@ private static Map getSettersInternal(Class clazz) { return accessors; } + private static final Pattern ILLEGAL_CHARS = Pattern.compile("[^a-z0-9]+"); + /** - * Strips all illegal charaters from the given lower case string. Illegal - * characters are all characters that are neither characters ('a' to 'z') + * Strips all illegal characters from the given lower case string. Illegal + * characters are all characters that are neither alphabetic ('a' to 'z') * nor digits ('0' to '9'). * * @param s the original string * @return the string with all illegal characters stripped */ public static String stripIllegalCharacters(String s) { - char c; - boolean needsStrip = false; - StringBuilder sb; - if (s == null) { return null; } - - for (int i = 0; i < s.length(); i++) { - c = s.charAt(i); - if (c >= '0' && c <= '9') { - // continue - } // NOPMD - else if (c >= 'a' && c <= 'z') { - // continue - } // NOPMD - else { - needsStrip = true; - break; - } - } - - if (!needsStrip) { - return s; - } - - sb = new StringBuilder(s.length()); - for (int i = 0; i < s.length(); i++) { - c = s.charAt(i); - if (c >= '0' && c <= '9') { - sb.append(c); - } else if (c >= 'a' && c <= 'z') { - sb.append(c); - } - } - - return sb.toString(); + return ILLEGAL_CHARS.matcher(s).replaceAll(""); } /** From 211482535b1b885b1fab454faa24ddb89e3eb8b4 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 12 Dec 2025 11:58:03 -0500 Subject: [PATCH 763/802] ManagerReaderImpl.java: Fix javadoc references to `Dispatcher` methods. --- .../org/asteriskjava/manager/internal/ManagerReaderImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java index efbc00535..da22236ea 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java @@ -131,8 +131,8 @@ public void expectResponseClass(String internalActionId, Class Date: Fri, 12 Dec 2025 12:02:40 -0500 Subject: [PATCH 764/802] ManagerReaderImpl.java: Remove `RTCPSent`/`RTCPReceived` parsing workaround. Both the incorrect `RTCPSent` and `RTCPReceived` events and the commit that fixed them were included in Asterisk 1.6.0. There was never a release that included the broken events so there's no reason to continue working around it. If you're running a beta of Asterisk 1.6.0 that contains this bug, you should consider upgrading. --- .../manager/internal/ManagerReaderImpl.java | 31 ++++++------------- .../internal/ManagerReaderImplTest.java | 24 -------------- 2 files changed, 10 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java index da22236ea..c97f268ad 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerReaderImpl.java @@ -177,27 +177,16 @@ public void run() { continue; } - if (line.length() > 0) { - // begin of workaround for Astersik bug 13319 - // see AJ-77 - // Use this workaround only when line starts from "From " - // and "To " - int isFromAtStart = line.indexOf("From "); - int isToAtStart = line.indexOf("To "); - - int delimiterIndex = isFromAtStart == 0 || isToAtStart == 0 ? line.indexOf(" ") : line.indexOf(":"); - // end of workaround for Astersik bug 13319 - - int delimiterLength = 1; - - if (delimiterIndex > 0 && line.length() > delimiterIndex + delimiterLength) { - String name = line.substring(0, delimiterIndex).toLowerCase(Locale.ENGLISH).trim(); - String value = line.substring(delimiterIndex + delimiterLength).trim(); - - addToBuffer(buffer, name, value); - // TODO tracing - // logger.debug("Got name [" + name + "], value: [" + - // value + "]"); + if (!line.isEmpty()) { + String[] parts = line.split(":", 2); + if (parts.length == 2) { + parts[0] = parts[0].toLowerCase(Locale.ENGLISH).trim(); + parts[1] = parts[1].trim(); + if (!parts[0].isEmpty()) { + addToBuffer(buffer, parts[0], parts[1]); + // TODO tracing + // logger.debug("Got name [" + name + "], value: [" + value + "]"); + } } } diff --git a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java index cf381dac7..22bbb9f23 100644 --- a/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java +++ b/src/test/java/org/asteriskjava/manager/internal/ManagerReaderImplTest.java @@ -150,30 +150,6 @@ void testRunReceivingEventWithMapPropertyAndOnlyOneEntry() throws Exception { assertEquals(DisconnectEvent.class, dispatcher.dispatchedEvents.get(1).getClass(), "second event must be an DisconnectEvent"); } - @Test - void testWorkaroundForAsteriskBug13319() throws Exception { - when(socketConnectionFacade.readLine()) - .thenReturn("Event: RTCPReceived") - .thenReturn("From 192.168.0.1:1234") - .thenReturn("HighestSequence: 999") - .thenReturn("") - .thenReturn(null); - - managerReader.setSocket(socketConnectionFacade); - managerReader.run(); - - assertEquals(2, dispatcher.dispatchedEvents.size(), "not exactly two events dispatched"); - - assertEquals(RtcpReceivedEvent.class, dispatcher.dispatchedEvents.get(0).getClass(), "first event must be a RtcpReceivedEvent"); - - RtcpReceivedEvent rtcpReceivedEvent = (RtcpReceivedEvent) dispatcher.dispatchedEvents.get(0); - assertEquals("192.168.0.1", rtcpReceivedEvent.getFromAddress().getHostAddress(), "Invalid from address on RtcpReceivedEvent"); - assertEquals(Integer.valueOf(1234), rtcpReceivedEvent.getFromPort(), "Invalid from port on RtcpReceivedEvent"); - assertEquals(Long.valueOf(999), rtcpReceivedEvent.getHighestSequence(), "Invalid highest sequence on RtcpReceivedEvent"); - - assertEquals(DisconnectEvent.class, dispatcher.dispatchedEvents.get(1).getClass(), "second event must be a DisconnectEvent"); - } - // todo fix testRunReceivingUserEvent void XtestRunReceivingUserEvent() throws Exception { managerReader.registerEventClass(MyUserEvent.class); From 753e0e6795b7ecb32bf26602b0046d892d515e50 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 12 Dec 2025 14:50:12 -0500 Subject: [PATCH 765/802] CelEvent.java: Add missing CEL event types. --- src/main/java/org/asteriskjava/manager/event/CelEvent.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/event/CelEvent.java b/src/main/java/org/asteriskjava/manager/event/CelEvent.java index e8e25cacd..6eded008b 100644 --- a/src/main/java/org/asteriskjava/manager/event/CelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/CelEvent.java @@ -2,7 +2,8 @@ /** * Raised when a Channel Event Log is generated for a channel. - * https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+ManagerEvent_CEL + *

    + * Asterisk AMI Events: CEL */ public class CelEvent extends ManagerEvent { private static final long serialVersionUID = 1L; @@ -22,7 +23,11 @@ public class CelEvent extends ManagerEvent { public static final String CEL_EVENT_FORWARD = "FORWARD"; public static final String CEL_EVENT_LINKEDID_END = "LINKEDID_END"; public static final String CEL_EVENT_LOCAL_OPTIMIZE = "LOCAL_OPTIMIZE"; + public static final String CEL_EVENT_LOCAL_OPTIMIZE_BEGIN = "LOCAL_OPTIMIZE_BEGIN"; public static final String CEL_EVENT_USER_DEFINED = "USER_DEFINED"; + public static final String CEL_EVENT_STREAM_BEGIN = "STREAM_BEGIN"; + public static final String CEL_EVENT_STREAM_END = "STREAM_END"; + public static final String CEL_EVENT_DTMF = "DTMF"; private String eventName; private String accountCode; From e60a72923330b69567050d401205224cf13d3ea0 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 12 Dec 2025 15:14:56 -0500 Subject: [PATCH 766/802] general: Use consistent Locale across library. This is probably the wrong thing to do, but we sometimes use US and sometimes use English and I just wanted to pick one. --- src/main/java/org/asteriskjava/config/ConfigFileReader.java | 2 +- .../asteriskjava/manager/internal/ActionBuilderImpl.java | 2 +- .../org/asteriskjava/manager/internal/EventBuilderImpl.java | 6 +++--- .../asteriskjava/manager/response/GetConfigResponse.java | 4 ++-- src/main/java/org/asteriskjava/util/AstUtil.java | 4 ++-- src/main/java/org/asteriskjava/util/ReflectionUtil.java | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/asteriskjava/config/ConfigFileReader.java b/src/main/java/org/asteriskjava/config/ConfigFileReader.java index 3fde86bae..474266428 100644 --- a/src/main/java/org/asteriskjava/config/ConfigFileReader.java +++ b/src/main/java/org/asteriskjava/config/ConfigFileReader.java @@ -369,7 +369,7 @@ ConfigDirective parseDirective(String configfile, int lineno, String line) throw name = ""; } throw new MissingDirectiveParameterException(configfile, lineno, - "Directive '#%s' needs an argument (%s) at line %d of %s", name.toLowerCase(Locale.US), + "Directive '#%s' needs an argument (%s) at line %d of %s", name.toLowerCase(Locale.ENGLISH), "include".equalsIgnoreCase(name) ? "filename" : "/path/to/executable", lineno, configfile); } diff --git a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java index 77f05d445..01f440d4c 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ActionBuilderImpl.java @@ -293,7 +293,7 @@ private static String mapToAsterisk(Method getter) { // ok, no field } - return fieldName.toLowerCase(Locale.US); + return fieldName.toLowerCase(Locale.ENGLISH); } static String determineSetterName(String getterName) { diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index df5e6cc46..d007e63e8 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -112,7 +112,7 @@ public final void registerEventClass(String eventType, Class attributes) { return null; } - eventType = ((String) attributes.get("event")).toLowerCase(Locale.US); + eventType = ((String) attributes.get("event")).toLowerCase(Locale.ENGLISH); // Change in Asterisk 1.4 where the name of the UserEvent is sent as // property instead @@ -184,7 +184,7 @@ public ManagerEvent buildEvent(Object source, Map attributes) { return null; } - userEventType = ((String) attributes.get("userevent")).toLowerCase(Locale.US); + userEventType = ((String) attributes.get("userevent")).toLowerCase(Locale.ENGLISH); eventType = eventType + userEventType; } } diff --git a/src/main/java/org/asteriskjava/manager/response/GetConfigResponse.java b/src/main/java/org/asteriskjava/manager/response/GetConfigResponse.java index da4ec4a02..0c1f20b26 100644 --- a/src/main/java/org/asteriskjava/manager/response/GetConfigResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/GetConfigResponse.java @@ -54,7 +54,7 @@ public Map getCategories() { Map responseMap = super.getAttributes(); for (Entry response : responseMap.entrySet()) { String key = response.getKey(); - if (key.toLowerCase(Locale.US).contains("category")) { + if (key.toLowerCase(Locale.ENGLISH).contains("category")) { String[] keyParts = key.split("-"); // if it doesn't have at least category-XXXXXX, skip @@ -91,7 +91,7 @@ public Map getLines(int categoryNumber) { Map responseMap = super.getAttributes(); for (Entry response : responseMap.entrySet()) { String key = response.getKey(); - if (key.toLowerCase(Locale.US).contains("line")) { + if (key.toLowerCase(Locale.ENGLISH).contains("line")) { String[] keyParts = key.split("-"); // if it doesn't have at least line-XXXXXX-XXXXXX, skip diff --git a/src/main/java/org/asteriskjava/util/AstUtil.java b/src/main/java/org/asteriskjava/util/AstUtil.java index 0f0383b27..98640c110 100644 --- a/src/main/java/org/asteriskjava/util/AstUtil.java +++ b/src/main/java/org/asteriskjava/util/AstUtil.java @@ -86,7 +86,7 @@ public static boolean isTrue(Object o) { return (Boolean) o; } - return TRUE_LITERALS.contains(o.toString().toLowerCase(Locale.US)); + return TRUE_LITERALS.contains(o.toString().toLowerCase(Locale.ENGLISH)); } /** @@ -180,7 +180,7 @@ public static boolean isNull(Object s) { return false; } - return NULL_LITERALS.contains(((String) s).toLowerCase(Locale.US)); + return NULL_LITERALS.contains(((String) s).toLowerCase(Locale.ENGLISH)); } /** diff --git a/src/main/java/org/asteriskjava/util/ReflectionUtil.java b/src/main/java/org/asteriskjava/util/ReflectionUtil.java index 201664a0c..86a32e252 100644 --- a/src/main/java/org/asteriskjava/util/ReflectionUtil.java +++ b/src/main/java/org/asteriskjava/util/ReflectionUtil.java @@ -137,7 +137,7 @@ private static Map getSettersInternal(Class clazz) { } // OK seems to be an setter - name = methodName.substring("set".length()).toLowerCase(Locale.US); + name = methodName.substring("set".length()).toLowerCase(Locale.ENGLISH); // if an event class implements a setter that exists in // ManagerEvent, then prefer the setter from the extending class From 7177623adfe9f65c6aa536bb6f759402a0568d6f Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 12 Dec 2025 16:25:28 -0500 Subject: [PATCH 767/802] ManagerEvent.java: Provide access to any `ChanVariable:` headers. Fixes: #587 --- .../manager/event/ManagerEvent.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java b/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java index 13cce6f3d..1aaa100a1 100644 --- a/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/ManagerEvent.java @@ -37,7 +37,7 @@ public abstract class ManagerEvent extends EventObject { /** * Serializable version identifier. */ - static final long serialVersionUID = 2L; + private static final long serialVersionUID = 2L; protected String connectedLineNum; protected String connectedLineName; protected Integer priority; @@ -46,6 +46,7 @@ public abstract class ManagerEvent extends EventObject { protected String exten; protected String callerIdNum; protected String callerIdName; + protected Map channelVariables = Collections.emptyMap(); /** * Returns the Caller ID name of the caller's channel. @@ -127,6 +128,25 @@ public void setContext(String context) { this.context = context; } + /** + * Gets a map of channel variables sent with this manager event. + *

    + * These are only sent by Asterisk if it has been configured to do so in + * the manager configuration file (manager.conf). + * + * @return an unmodifiable map of channel variables and their values, never {@code null} + */ + public Map getChannelVariables() { + return channelVariables; + } + + public void setChanVariables(Map variables) { + if (variables == null) { + return; + } + this.channelVariables = Collections.unmodifiableMap(new HashMap<>(variables)); + } + protected String context; /** From 3e91b363a2b755ab060b7820fa8f1ec0b713cd41 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 12 Dec 2025 16:51:43 -0500 Subject: [PATCH 768/802] AsteriskVersion.java: Treat builds from Asterisk's `master` branch as latest release. --- src/main/java/org/asteriskjava/AsteriskVersion.java | 4 +++- .../asteriskjava/manager/internal/ManagerConnectionImpl.java | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index 734653f76..df18b2ae1 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -27,6 +27,8 @@ * @since 0.2 */ public class AsteriskVersion implements Comparable, Serializable { + private static final String VERSION_PATTERN_DEV = "^\\s*Asterisk GIT-master-.*"; + private static final String VERSION_PATTERN_23 = "^\\s*Asterisk (GIT-)?23[-. ].*"; private static final String VERSION_PATTERN_22 = "^\\s*Asterisk (GIT-)?22[-. ].*"; private static final String VERSION_PATTERN_21 = "^\\s*Asterisk (GIT-)?21[-. ].*"; @@ -176,7 +178,7 @@ public class AsteriskVersion implements Comparable, Serializabl * * @since 3.40.0 */ - public static final AsteriskVersion ASTERISK_23 = new AsteriskVersion(2300, "Asterisk 23", VERSION_PATTERN_23); + public static final AsteriskVersion ASTERISK_23 = new AsteriskVersion(2300, "Asterisk 23", VERSION_PATTERN_23, VERSION_PATTERN_DEV); private static final AsteriskVersion knownVersions[] = new AsteriskVersion[]{ ASTERISK_23, ASTERISK_22, ASTERISK_21, ASTERISK_20, ASTERISK_19, ASTERISK_18, ASTERISK_17, ASTERISK_16, diff --git a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java index a6793cb24..9feeac04b 100644 --- a/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/ManagerConnectionImpl.java @@ -82,6 +82,7 @@ public class ManagerConnectionImpl extends Lockable implements ManagerConnection "10.0", // Asterisk 21 "11.0", // Asterisk 22 "12.0", // Asterisk 23 + "13.0", // Asterisk Dev }; private static final AtomicLong idCounter = new AtomicLong(0); From 9952ff5a95998e7e75180be9218747df180a3672 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 02:01:18 +0000 Subject: [PATCH 769/802] build(deps): bump org.apache.maven.plugins:maven-release-plugin Bumps [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/apache/maven-release/releases) - [Commits](https://github.com/apache/maven-release/compare/maven-release-3.3.0...maven-release-3.3.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-release-plugin dependency-version: 3.3.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a9d650fb6..7b97a8f30 100644 --- a/pom.xml +++ b/pom.xml @@ -165,7 +165,7 @@ org.apache.maven.plugins maven-release-plugin - 3.3.0 + 3.3.1 true false From 042a640b9103eee34427e6f9af0ea7f236bd1b4d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 02:01:09 +0000 Subject: [PATCH 770/802] build(deps): bump org.apache.logging.log4j:log4j-core Bumps org.apache.logging.log4j:log4j-core from 2.25.2 to 2.25.3. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-version: 2.25.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7b97a8f30..ea3beefe2 100644 --- a/pom.xml +++ b/pom.xml @@ -101,7 +101,7 @@ org.apache.logging.log4j log4j-core - 2.25.2 + 2.25.3 org.reflections From b2e518b6b2f34ae778aa5386aa8dac09e1341a1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 02:01:17 +0000 Subject: [PATCH 771/802] build(deps-dev): bump org.junit.jupiter:junit-jupiter Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework) from 5.14.1 to 5.14.2. - [Release notes](https://github.com/junit-team/junit-framework/releases) - [Commits](https://github.com/junit-team/junit-framework/compare/r5.14.1...r5.14.2) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.14.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ea3beefe2..17c61d92a 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ org.junit.jupiter junit-jupiter - 5.14.1 + 5.14.2 test From dd57991747e00c6774e0f1255abe218a11bee365 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Jan 2026 02:52:40 +0000 Subject: [PATCH 772/802] build(deps): bump peter-evans/create-pull-request from 8.0.0 to 8.1.0 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 8.0.0 to 8.1.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v8.0.0...v8.1.0) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-version: 8.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ac02607b..43299d722 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v8.0.0 + uses: peter-evans/create-pull-request@v8.1.0 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From b70b160304e2b1e6eb19166666186d8ef3b6231e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 02:52:44 +0000 Subject: [PATCH 773/802] build(deps): bump actions/setup-java from 5.1.0 to 5.2.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.1.0 to 5.2.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v5.1.0...v5.2.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 5.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b7c4a4bd..edcc4aeb9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v5.1.0 + uses: actions/setup-java@v5.2.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ac02607b..ccfeb0b9a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v6.0.1 - name: Set up Java - uses: actions/setup-java@v5.1.0 + uses: actions/setup-java@v5.2.0 with: java-version: 8 distribution: temurin From 9be4db07cca8164dac4d4bc60805ca881c8ba834 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 02:52:49 +0000 Subject: [PATCH 774/802] build(deps): bump actions/checkout from 6.0.1 to 6.0.2 Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 6.0.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6.0.1...v6.0.2) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b7c4a4bd..6a695f7b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ac02607b..ccd63a186 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Set up Java uses: actions/setup-java@v5.1.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: ref: master fetch-depth: 0 From 0f941960667655abc158c1c0cc4e6e7f631f9f51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jan 2026 02:52:16 +0000 Subject: [PATCH 775/802] build(deps-dev): bump org.assertj:assertj-core from 3.27.6 to 3.27.7 Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.27.6 to 3.27.7. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.27.6...assertj-build-3.27.7) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-version: 3.27.7 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 17c61d92a..d15a1a6d3 100644 --- a/pom.xml +++ b/pom.xml @@ -118,7 +118,7 @@ org.assertj assertj-core - 3.27.6 + 3.27.7 test From c8f2702871cb2a914d02add0c0f13d9134f80dda Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Feb 2026 02:52:05 +0000 Subject: [PATCH 776/802] build(deps-dev): bump org.apache.maven.plugins:maven-compiler-plugin Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.14.1 to 3.15.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.14.1...maven-compiler-plugin-3.15.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-version: 3.15.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 17c61d92a..7c76cd2d3 100644 --- a/pom.xml +++ b/pom.xml @@ -176,7 +176,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.14.1 + 3.15.0 1.8 1.8 From d21807c9faadb16cd6a74e485760b6fd237a4793 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 02:52:21 +0000 Subject: [PATCH 777/802] build(deps-dev): bump org.junit.jupiter:junit-jupiter Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework) from 5.14.2 to 5.14.3. - [Release notes](https://github.com/junit-team/junit-framework/releases) - [Commits](https://github.com/junit-team/junit-framework/compare/r5.14.2...r5.14.3) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.14.3 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 17c61d92a..99d253141 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ org.junit.jupiter junit-jupiter - 5.14.2 + 5.14.3 test From 3a51d46533977d04c28c2d9411412692bd50372f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 02:52:26 +0000 Subject: [PATCH 778/802] build(deps-dev): bump org.apache.maven.plugins:maven-surefire-plugin Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.4 to 3.5.5. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.4...surefire-3.5.5) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-version: 3.5.5 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 17c61d92a..f7dfef399 100644 --- a/pom.xml +++ b/pom.xml @@ -185,7 +185,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.5.4 + 3.5.5 org.apache.maven.plugins From 4fd1efb9c8147a994ab68c37a7321538906a2234 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2026 02:52:33 +0000 Subject: [PATCH 779/802] build(deps): bump release-drafter/release-drafter from 6.1.0 to 7.1.1 Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 6.1.0 to 7.1.1. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v6.1.0...v7.1.1) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-version: 7.1.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 78a0ff648..025ff117c 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -14,7 +14,7 @@ jobs: contents: write # for release-drafter to create a GitHub release runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v6.1.0 + - uses: release-drafter/release-drafter@v7.1.1 with: config-name: release-drafter-master.yml env: From 39112fb4e65e46920b6d5a25786e77d357026d34 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:52:09 +0000 Subject: [PATCH 780/802] build(deps): bump org.apache.logging.log4j:log4j-core Bumps org.apache.logging.log4j:log4j-core from 2.25.3 to 2.25.4. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-version: 2.25.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 17c61d92a..08e429a9f 100644 --- a/pom.xml +++ b/pom.xml @@ -101,7 +101,7 @@ org.apache.logging.log4j log4j-core - 2.25.3 + 2.25.4 org.reflections From 9804e0b73e4ad3edc323fad057db970429a12f70 Mon Sep 17 00:00:00 2001 From: Guillaume Millet Date: Wed, 8 Apr 2026 15:13:07 +0200 Subject: [PATCH 781/802] Add getter and setter for qualify2xxOnly in ContactStatusDetail --- .../asteriskjava/manager/event/ContactStatusDetail.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java index efdb18a78..08fca1cd1 100644 --- a/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/ContactStatusDetail.java @@ -34,6 +34,7 @@ public class ContactStatusDetail extends ResponseEvent { private String path; private int qualifyFrequency; private Float qualifyTimeout; + private Boolean qualify2xxOnly; public String getAor() { return aor; @@ -151,6 +152,14 @@ public void setQualifyTimeout(String qualifyTimeout) { this.qualifyTimeout = Float.parseFloat(qualifyTimeout); } + public Boolean isQualify2xxOnly() { + return qualify2xxOnly; + } + + public void setQualify2xxOnly(Boolean qualify2xxOnly) { + this.qualify2xxOnly = qualify2xxOnly; + } + public ContactStatusDetail(Object source) { super(source); } From 6777ce3f753cd7144e30724425df53a7cc4e362c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 02:52:41 +0000 Subject: [PATCH 782/802] build(deps): bump peter-evans/create-pull-request from 8.1.0 to 8.1.1 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 8.1.0 to 8.1.1. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v8.1.0...v8.1.1) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-version: 8.1.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f6239f536..5934c759f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,7 +55,7 @@ jobs: run: git diff - name: Create Pull Request - uses: peter-evans/create-pull-request@v8.1.0 + uses: peter-evans/create-pull-request@v8.1.1 with: commit-message: Update versions to ${{ github.event.release.tag_name }} title: Update versions to ${{ github.event.release.tag_name }} From 627128f096d306ac58fabd02b62421eafb653692 Mon Sep 17 00:00:00 2001 From: Guillaume Millet Date: Fri, 17 Apr 2026 11:08:44 +0200 Subject: [PATCH 783/802] Add getter and setter for qualify2xxOnly in ContactList --- .../org/asteriskjava/manager/event/ContactList.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/manager/event/ContactList.java b/src/main/java/org/asteriskjava/manager/event/ContactList.java index 8d23aca21..a83958265 100644 --- a/src/main/java/org/asteriskjava/manager/event/ContactList.java +++ b/src/main/java/org/asteriskjava/manager/event/ContactList.java @@ -54,6 +54,7 @@ public class ContactList extends ResponseEvent { String objecttype; String pruneonboot; ContactStatusEnum status; + Boolean qualify2xxOnly; /** * Creates a new instance. @@ -213,6 +214,14 @@ public void setStatus(String status) { } + public Boolean isQualify2xxOnly() { + return qualify2xxOnly; + } + + public void setQualify2xxOnly(Boolean qualify2xxOnly) { + this.qualify2xxOnly = qualify2xxOnly; + } + @Override public String toString() { return "ContactList [qualifyTimeout=" + qualifyTimeout + ", callid=" + callid + ", regserver=" + regserver @@ -220,7 +229,7 @@ public String toString() { + authenticatequalify + ", objectname=" + objectname + ", useragent=" + useragent + ", uri=" + uri + ", viaaddr=" + viaaddr + ", qualifyfrequency=" + qualifyfrequency + ", path=" + path + ", endpoint=" + endpoint + ", viaport=" + viaport + ", outboundproxy=" + outboundproxy + ", actionId=" + actionId - + ", objecttype=" + objecttype + ", pruneonboot=" + pruneonboot + ", status=" + status + "]\n"; + + ", objecttype=" + objecttype + ", pruneonboot=" + pruneonboot + ", status=" + status + ", qualify2xxOnly=" + qualify2xxOnly + "]\n"; } } From 9ad2283b3299d789629b3490840b2fb42d8e4e7c Mon Sep 17 00:00:00 2001 From: Guillaume Millet Date: Fri, 17 Apr 2026 11:09:17 +0200 Subject: [PATCH 784/802] Add getter and setter for removeUnavailable and qualify2xxOnly in AorDetail --- .../asteriskjava/manager/event/AorDetail.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/org/asteriskjava/manager/event/AorDetail.java b/src/main/java/org/asteriskjava/manager/event/AorDetail.java index fa8f8cd8a..03fa0ce3c 100644 --- a/src/main/java/org/asteriskjava/manager/event/AorDetail.java +++ b/src/main/java/org/asteriskjava/manager/event/AorDetail.java @@ -40,6 +40,8 @@ public AorDetail(Object source) { private int totalContacts; private int contactsRegistered; private String endpointName; + private Boolean removeUnavailable; + private Boolean qualify2xxOnly; public String getObjectType() { return objectType; @@ -185,4 +187,20 @@ public void setEndpointName(String endpointName) { this.endpointName = endpointName; } + public Boolean isRemoveUnavailable() { + return removeUnavailable; + } + + public void setRemoveUnavailable(Boolean removeUnavailable) { + this.removeUnavailable = removeUnavailable; + } + + public Boolean isQualify2xxOnly() { + return qualify2xxOnly; + } + + public void setQualify2xxOnly(Boolean qualify2xxOnly) { + this.qualify2xxOnly = qualify2xxOnly; + } + } From 2f375b588cc30267e3a5e127936810943876436b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 02:52:28 +0000 Subject: [PATCH 785/802] build(deps): bump actions/setup-java from 5.2.0 to 5.3.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.2.0 to 5.3.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v5.2.0...v5.3.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 5.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4ad93e3d..8b5d69ace 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v5.2.0 + uses: actions/setup-java@v5.3.0 with: distribution: temurin java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f6239f536..1de1b9e8f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v6.0.2 - name: Set up Java - uses: actions/setup-java@v5.2.0 + uses: actions/setup-java@v5.3.0 with: java-version: 8 distribution: temurin From d7e22ff7b39928dceb90a2753c96b2dd927193d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 02:52:32 +0000 Subject: [PATCH 786/802] build(deps): bump release-drafter/release-drafter from 7.1.1 to 7.4.0 Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 7.1.1 to 7.4.0. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v7.1.1...v7.4.0) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-version: 7.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 025ff117c..54695614b 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -14,7 +14,7 @@ jobs: contents: write # for release-drafter to create a GitHub release runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v7.1.1 + - uses: release-drafter/release-drafter@v7.4.0 with: config-name: release-drafter-master.yml env: From 035676d4f6881b0d3dd95d1bb548238572adee9f Mon Sep 17 00:00:00 2001 From: Christof Lauber Date: Wed, 17 Jun 2026 11:33:32 +0200 Subject: [PATCH 787/802] Add asterisk 22 certified a supported version --- src/main/java/org/asteriskjava/AsteriskVersion.java | 3 ++- src/test/java/org/asteriskjava/AsteriskVersionTest.java | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/asteriskjava/AsteriskVersion.java b/src/main/java/org/asteriskjava/AsteriskVersion.java index df18b2ae1..051141420 100644 --- a/src/main/java/org/asteriskjava/AsteriskVersion.java +++ b/src/main/java/org/asteriskjava/AsteriskVersion.java @@ -44,6 +44,7 @@ public class AsteriskVersion implements Comparable, Serializabl private final String versionString; private final Pattern patterns[]; + private static final String VERSION_PATTERN_CERTIFIED_22 = "^\\s*Asterisk certified-(GIT-)?22[-. ].*"; private static final String VERSION_PATTERN_CERTIFIED_20 = "^\\s*Asterisk certified-(GIT-)?20[-. ].*"; private static final String VERSION_PATTERN_CERTIFIED_18 = "^\\s*Asterisk certified[-/](GIT-)?18[-. ].*"; private static final String VERSION_PATTERN_CERTIFIED_16 = "^\\s*Asterisk certified/(GIT-)?16[-. ].*"; @@ -171,7 +172,7 @@ public class AsteriskVersion implements Comparable, Serializabl * * @since 3.40.0 */ - public static final AsteriskVersion ASTERISK_22 = new AsteriskVersion(2200, "Asterisk 22", VERSION_PATTERN_22); + public static final AsteriskVersion ASTERISK_22 = new AsteriskVersion(2200, "Asterisk 22", VERSION_PATTERN_22, VERSION_PATTERN_CERTIFIED_22); /** * Represents the Asterisk 23 series. diff --git a/src/test/java/org/asteriskjava/AsteriskVersionTest.java b/src/test/java/org/asteriskjava/AsteriskVersionTest.java index 24f28bace..37fec6b02 100644 --- a/src/test/java/org/asteriskjava/AsteriskVersionTest.java +++ b/src/test/java/org/asteriskjava/AsteriskVersionTest.java @@ -31,8 +31,14 @@ void test15() { void test18() { assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk 18.1.0").equals(AsteriskVersion.ASTERISK_18)); } + @Test void testCertified18() { assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk certified/18.9-cert2").equals(AsteriskVersion.ASTERISK_18)); } + + @Test + void testCertified22() { + assertTrue(AsteriskVersion.getDetermineVersionFromString("Asterisk certified-22.8-cert2").equals(AsteriskVersion.ASTERISK_22)); + } } From c6d580e0004273ef7bc858047c30dad81eb36056 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jun 2026 02:52:15 +0000 Subject: [PATCH 788/802] build(deps): bump actions/checkout from 6.0.2 to 7.0.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.2 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6.0.2...v7.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4ad93e3d..2b6e6bbef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Check out code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v7.0.0 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f6239f536..8e9079681 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v7.0.0 - name: Set up Java uses: actions/setup-java@v5.2.0 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v7.0.0 with: ref: master fetch-depth: 0 From 97f811bd796725ee7259844ba6fdbddd128de382 Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Mon, 6 Jul 2026 08:41:57 +0200 Subject: [PATCH 789/802] Update release-drafter.yml --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 54695614b..9a019e555 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -3,7 +3,7 @@ name: Release Drafter on: push: branches: - - master + - main permissions: contents: read From 5e313e763024ff1da5725cdb545f653c1667c3ee Mon Sep 17 00:00:00 2001 From: Piotr Olaszewski Date: Mon, 6 Jul 2026 08:44:26 +0200 Subject: [PATCH 790/802] Update release-drafter-master.yml --- .github/release-drafter-master.yml | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/release-drafter-master.yml b/.github/release-drafter-master.yml index 1be06ba3d..ef2d4ba5a 100644 --- a/.github/release-drafter-master.yml +++ b/.github/release-drafter-master.yml @@ -1,24 +1,30 @@ filter-by-commitish: true -commitish: master +commitish: main template: | ## What's Changed $CHANGES categories: - title: '💥 Breaking API Changes' - label: 'kind/breaking' + when: + label: 'kind/breaking' - title: '🚀 Features & Enhancements' - labels: - - 'kind/enhancement' - - 'kind/feature' + when: + labels: + - 'kind/enhancement' + - 'kind/feature' - title: '🐛 Bug Fixes' - label: 'kind/bug' + when: + label: 'kind/bug' - title: '🧹 Refactor' - label: 'kind/refactor' + when: + label: 'kind/refactor' - title: '📝 Documentation' - label: 'kind/documentation' + when: + label: 'kind/documentation' - title: '📦 Dependency Updates' - label: 'kind/dependencies' + when: + label: 'kind/dependencies' collapse-after: 5 change-template: '* (#$NUMBER) $TITLE by @$AUTHOR' exclude-labels: From 7176bdb674a6b84911c65be44478e9aac613dcf0 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 6 Jul 2026 14:39:21 +0000 Subject: [PATCH 791/802] [skip ci] README.md: Update release versions. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7baf1f8e2..9cfadf4eb 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 23) (master) org.asteriskjava asterisk-java - 3.41.0 + 3.42.1 ``` ### Gradle ```text -implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.41.0' +implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.42.1' ``` ### Installation from source From 6b6b83800158762231f7e244474ebc1449a0115d Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 6 Jul 2026 14:42:04 +0000 Subject: [PATCH 792/802] [maven-release-plugin] [skip ci] prepare release 3.42.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8a2fb2676..07cc133da 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.asteriskjava asterisk-java - 3.42.0-SNAPSHOT + 3.42.1 Asterisk-Java The free Java library for Asterisk PBX integration. @@ -80,7 +80,7 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - HEAD + 3.42.1 From 3b8372dadc07131940fc7b43773c95403c37a7fd Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 6 Jul 2026 14:47:26 +0000 Subject: [PATCH 793/802] Revert "[maven-release-plugin] [skip ci] prepare release 3.42.1" This reverts commit 6b6b83800158762231f7e244474ebc1449a0115d. --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 07cc133da..8a2fb2676 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.asteriskjava asterisk-java - 3.42.1 + 3.42.0-SNAPSHOT Asterisk-Java The free Java library for Asterisk PBX integration. @@ -80,7 +80,7 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - 3.42.1 + HEAD From 173e5cb0ff971ce640b99050b70d9556aad679a0 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 6 Jul 2026 14:48:53 +0000 Subject: [PATCH 794/802] [maven-release-plugin] [skip ci] prepare release 3.42.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8a2fb2676..07cc133da 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.asteriskjava asterisk-java - 3.42.0-SNAPSHOT + 3.42.1 Asterisk-Java The free Java library for Asterisk PBX integration. @@ -80,7 +80,7 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - HEAD + 3.42.1 From b86ddbd9648bf4ec5df0d39ff0c999d9575c0d50 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 6 Jul 2026 14:48:55 +0000 Subject: [PATCH 795/802] [maven-release-plugin] [skip ci] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 07cc133da..678a5c23a 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.asteriskjava asterisk-java - 3.42.1 + 3.43.0-SNAPSHOT Asterisk-Java The free Java library for Asterisk PBX integration. @@ -80,7 +80,7 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - 3.42.1 + HEAD From bea9a9c3ce50e0c1a4fe0c9f0eb9ec6790a7b2e5 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 6 Jul 2026 11:07:15 -0400 Subject: [PATCH 796/802] README.md: Revert to 3.41.0 since we can't publish ATM. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9cfadf4eb..7baf1f8e2 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 23) (master) org.asteriskjava asterisk-java - 3.42.1 + 3.41.0 ``` ### Gradle ```text -implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.42.1' +implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.41.0' ``` ### Installation from source From a669b49821a0a5a8302a290e23eb4fc90aba7bbf Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Wed, 8 Jul 2026 19:04:30 +0000 Subject: [PATCH 797/802] pom.xml: Deploy using Portal OSSRH Staging API [Publishing By Using the Portal OSSRH Staging API](https://central.sonatype.org/publish/publish-portal-ossrh-staging-api/) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 678a5c23a..170c1dc44 100644 --- a/pom.xml +++ b/pom.xml @@ -294,7 +294,7 @@ true ossrh - https://oss.sonatype.org/ + https://ossrh-staging-api.central.sonatype.com/ true From 1af77a6d4042f4ad74ebb1c121b19aa2318a7f08 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Wed, 8 Jul 2026 19:07:49 +0000 Subject: [PATCH 798/802] [skip ci] README.md: Update release versions. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7baf1f8e2..10005d85a 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Asterisk-Java 3.x (Java 1.8 and Asterisk Version 10 thru 23) (master) org.asteriskjava asterisk-java - 3.41.0 + 3.42.2 ``` ### Gradle ```text -implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.41.0' +implementation group: 'org.asteriskjava', name: 'asterisk-java', version: '3.42.2' ``` ### Installation from source From c2d0b6140eee6d01065356004546b14dcd203ad6 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Wed, 8 Jul 2026 19:10:23 +0000 Subject: [PATCH 799/802] [maven-release-plugin] [skip ci] prepare release 3.42.2 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 170c1dc44..edff75f17 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.asteriskjava asterisk-java - 3.43.0-SNAPSHOT + 3.42.2 Asterisk-Java The free Java library for Asterisk PBX integration. @@ -80,7 +80,7 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - HEAD + 3.42.2 From 2a11ed6dd9c94dffb97776a23c59b7db7767eb65 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Wed, 8 Jul 2026 19:10:25 +0000 Subject: [PATCH 800/802] [maven-release-plugin] [skip ci] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index edff75f17..170c1dc44 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.asteriskjava asterisk-java - 3.42.2 + 3.43.0-SNAPSHOT Asterisk-Java The free Java library for Asterisk PBX integration. @@ -80,7 +80,7 @@ scm:git:git@github.com:asterisk-java/asterisk-java.git scm:git:git@github.com:asterisk-java/asterisk-java.git https://github.com/asterisk-java/asterisk-java - 3.42.2 + HEAD From ba53241644e624229cd914b17e4a8e6bd2a4526b Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Wed, 8 Jul 2026 16:08:58 -0400 Subject: [PATCH 801/802] pom.xml: Add myself to the POM Also updates Piotr's e-mail to follow the same format as the others --- pom.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 170c1dc44..30bea761a 100644 --- a/pom.xml +++ b/pom.xml @@ -71,9 +71,15 @@ Piotr Olaszewski piotrooo - piotroo89_at_gmail.com + piotroo89 at gmail.com +1 + + Sean Bright + seanbright + sean at seanbright.com + -5 + From 48d405a0729d29bf207d771915cd55fde10b5b10 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Wed, 8 Jul 2026 20:18:30 +0000 Subject: [PATCH 802/802] maven: Update maven wrapper to v3.3.4 --- .mvn/wrapper/maven-wrapper.jar | Bin 59925 -> 0 bytes .mvn/wrapper/maven-wrapper.properties | 21 +- mvnw | 462 +++++++++++++------------- mvnw.cmd | 376 ++++++++++----------- 4 files changed, 427 insertions(+), 432 deletions(-) delete mode 100644 .mvn/wrapper/maven-wrapper.jar diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index bf82ff01c6cdae4a1bb754a6e062954d77ac5c11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59925 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

    dy!05UMhSKsK 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 VCNKd3JGtOvEm(5t0lFyE{{i--k}m)N diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index dc3affce3..8dea6c227 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,18 +1,3 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# https://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. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar +wrapperVersion=3.3.4 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip diff --git a/mvnw b/mvnw index b7f064624..bd8896bf2 100755 --- a/mvnw +++ b/mvnw @@ -19,269 +19,277 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.1.1 -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir +# Apache Maven Wrapper startup batch script, version 3.3.4 # # Optional ENV vars # ----------------- -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output # ---------------------------------------------------------------------------- -if [ -z "$MAVEN_SKIP_RC" ] ; then +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x - if [ -f /usr/local/etc/mavenrc ] ; then - . /usr/local/etc/mavenrc - fi +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi fi +} -fi +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - JAVA_HOME="`/usr/libexec/java_home`"; export JAVA_HOME - else - JAVA_HOME="/Library/Java/Home"; export JAVA_HOME - fi - fi +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; esac -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" fi -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" fi -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" fi -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" fi -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true fi else - JAVACMD="`\\unset -f command; \\command -v java`" + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 fi fi -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" fi -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" fi +fi - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi fi - # end of workaround done - printf '%s' "$(cd "$basedir"; pwd)" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=$(find_maven_basedir "$(dirname $0)") -if [ -z "$BASE_DIR" ]; then - exit 1; + set -f fi -MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" - else - wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) wrapperUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $wrapperUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - QUIET="--quiet" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - QUIET="" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" - else - wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" - fi - [ $? -eq 0 ] || rm -f "$wrapperJarPath" - elif command -v curl > /dev/null; then - QUIET="--silent" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - QUIET="" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L - else - curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L - fi - [ $? -eq 0 ] || rm -f "$wrapperJarPath" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaSource="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaSource=`cygpath --path --windows "$javaSource"` - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaSource" ]; then - if [ ! -e "$javaClass" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaSource") - fi - if [ -e "$javaClass" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" fi -########################################################################################## -# End of extension -########################################################################################## - -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd index 474c9d6b7..5761d9489 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -1,187 +1,189 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.1.1 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.4 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

    "); writer.append(uniqueId.substring(0, uniqueId.lastIndexOf('.') + 1)); writer.append(""); @@ -142,8 +115,7 @@ public void write() writer.append("
    ").append(text).append("

    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

    JAnZN~eAq@9Fu z7~$!gHscR`DCa+MzS^|G3czg#ZbDOyX@sn-5Cz6uM1}F6M`Sk@1)>NmjHU=W@vReD zB}tZOR;0UL%m-ZG^@U=I<`b)O#1eamY2Z*B7dmRWUWg=uMNIU1WK_JEy*lFMc)3YDLzR(Sp{_jrhQhSFs8_euSQQ}PuY$iL%F2)^Bu@9}lKp>R{ z;$lj7ogr`oPv4h`3!BLi@={|p4$rBSQ;sE=Uc!}EAQbya)R~+~@M8+rB(-1ATaQ@T z<#GynjF$ESX?FI>ayW=<*w{s+SbLI(*bn(5--eJ|fuC(l<*ppLU*wU%$=@NBPx$1= zws%9wuT?H{PCz_K+c`J+MxLPZdh5FKdgmPd9J{0$+!^Rb|0;99n=<7Gq=OiNSpf^U_J6U5fb|BCBjPYs5 zjxnWvwU>?SZvJ3{RjXva8NTt8e!urXAeX%@HY_JE%KTfkK*qT zVou{371HE*8S(lps2F5Vw|CN8(2r_Z5s3g}MMWy02{E7Onnmk9|CQzSL=KWU}4}Ch#pLrVa??w za*SE&6wlkeb`|jGHLQUDce)HaLqCsbE*HwhW(Dq-P${QeK`z5l(cWlTf(;mWaAr3G2w6c2ucTEjnj^Rx^ z!%5MKFKs(2ahabu-%JF1w2Dh9xZ$U$^Xff4l?<%W?&#nAJk;U@6XTAFIjXt2 z-rO8?I(s2nzcgOj++Qj#3lTJYimk25|E))bI>)fcpPb zKofIlb8#FViQ%MTQH4|d3)q%J55hV*Y=KBx4kf*OrZjb->;gYg?;P317W$sbrP!~A zUEWmdDC7_TJ~2YW#AZ2Kc`B)y_YkZW)I9Yy zO57BGL5P=Y*hB|ufAM9u_&9yy&ILsE@{>5FrWAQrwsfYC)HvxLO2M(3>_jg0spzCZ z*|LBAu^Otm{A0!@Vx-Y}8iz40L^sh>EMi)3!a4D!v_$}*57e!wG=rL;!Ld2S0lhlk zr6sdaTnVK(JqO=YQ{B;9*$uP6_*x-uK#*dhNJ9rtJcOF>M7V-#K?sdTIC~5xu$HIk z!L~S+L3Jhg3YYEQ<#Agb@*TEzq=F7{b<3b5m>GY?DPBh$QhF5_cZq2&gXaeeT#fOe zJs7B0!>KTYj$JTVVtUKq%;3Vd;*ExPoiIbs56-8VNog~YXTb1;C+DX zN72I$JGeXeEEs&V!5u76$qv4rdV5r;L+FxFcjOmuA^BkXO#=}2h6eM{c{S{cUE=N3 zyEJ^EN#4-7T=9mOE)J4?7n&@9hEA#$(ycfi`d6i;;vO-#W%!fuVQUurU+<~9!zZj+0O+yna~6gFwKCC<@2hx# zA1|<4Wm}z6AEWQWR{t6{IXfUezz34X<7)I|ih9JnmexFcgXvX`7E-jxy4`wJ(X4x? zQ8lH=3R@5_@u4D(uQTPIOA7fsoM;wWDO@Jl#jWk2xK!2ZZ>DqVO^-^hQ?sBa70V_OU!c>_@N)Og`v~RN57b zPf)YM@3-+aHa-{Vg2;!y$d^2Vew}=f)&zY26stx-IA|ci>v(@k5$&ND+%JA7_5$do)w(zK zdhU5*9@-H5#1}i}kA0yC>9HR{;4q^$ir8;}w^K{;GH~33$iW`N<38{oAE3$jU_yAr z?3VFDTr0M4FNfH6#wQU>`ZYd{>aztnUJO`FvD*Tz66W$_N*4Y0jpZ*_HJ#b*v%`%4gqVWU*w4y zNMke&aDNMx&WGrE#1$>YU*bQBPj}b?f^&o3$OevOQ-tXOwFRV5w#AC$_sh06tv*Cc z20&{s6Zq1>l`ZvVdMCY~rrC2-@2>ZwI`P!rMuCdcd*BG*Jip$ZV~ z`_uf!m3C=T$R07NrTK*UjQJnaY|%0g09K-9zKJj`S|*w04MfX4toh6z{pMktR9{*U zO}HYi-l;s`S3k+bYz?d3)xYA~5*J|D)W{$lk6#sj|3g|Q{9p-Oy~fVRJhZ7^NN1jB zY^pK7v}d@~UKPXDdw4X3OGMV!l`< z@zEX{AXo*aqzw!`^&^GL1R^QGqxhyC*;n~;q4vamUa{9NcAUOeh}Z44LL9|f@vToB zvTf3A@txd?ohQyPeKOl8n`X<5)MMf>RhatJKF*h&o%q1cP+&;-NZOU#`DvOi_J^6z z=dyPVoBFsqp1>KE99YAy=?|CiXExK ze2SNF@NCg7RrS=jt`J@juNaskdfENh4|movD%U&(a#tV}R1~3M;{apema^7xcmkce z2Ol9pfQm72WN!{t9?Uryz7CKmjwY2LyvrU=zAJr3`3`0{2!pgktZXd~h}TQIIRyj- z!%99)*gUIS!@2iOTX6)n0XdJ(BX4gl{uHO$itlXP=Ni7uEt0JzefAoP1SgMYsgU-5 zEfBA>xjQ2w=$jB;K+gt|%KP$5OlN3=hp}$CUk1D>3b!CKzEEOAqHzWV2|A;R8NyP(r zIr1;c{0pK(S&@-xphLy4wTVV21KLyIUM-eU+`2M`;MnoHh%pL`yx=n~_ZqMQ!LPVI zeTnW{S^|B>^%eLuGoI98^6$ISAJ0}-@Mu>mij7quNta>hCR<-4Ox0`Bu!t^89Vsx@ z`HYRZ;)Gc0#5Y`w2Y^3l8vAP4wLQ7<6k_Xeu!>QQ86P6@RgdAu@0fy?*%-0iKC^|e zA$6zHG+R?ST&&ECnw=CS^IXCdn0cMO<|ttfqf+?v#CObR&M?dgM3NdpPBe^)WiF-+ zz48l9OA}@ZMLZ(Z8e7T_O>`e-3C7j@j9~SsvGkcgc+JDL-SZnIq`vnE(K@&!xGK06 zl5_$nob2hrt*VrgB=u31poLctE4{&zS_wF*O8?*y;nu--f*%G^k@(#%{TW5nW7it| z!5gfr^$$u&!PjrK4m}@wIra>eVPIe{zfLd-VF+55i9gS{eRU&AH8eSBW)y|~3}Yb| ze?gt3YCn~M;qrwWd&3#EEZz(TTCJhRy+rH*pF%ejzN5aO2_kYuL=Id{!<#Q{oH%;|-rE4wHnZ zFI0(tY4TcH4V!^agdDHCTvcq*714*p*>vOTKNr*bTO*y;$Vd_upz+ov2+zD+Wlh83 z-vVyU1hE&=W@|pUvf@@57An;Q&w3_gJ%Q-a1~TM} z^zcP8OzTT(hQx$MXZ> z5%r*I?EhdlLt5kGyz$X#X_aSFata62(bkFPct!3YXsJ#Mhn7H( z+I|FloGLMh2#YMt4tHKSacK>k^@T4nj@yt@Is+0DK+RqoL;@OR){k9$i3yUx*&Wgi zUJ$@H=@r5jb7&}EqS%|bKCLxmWArMHNdE)c^d@*Mx`{$p<7Pu*i#LIb9kvQi>lk47 zdlQe=W~RD$;$`BIRl{D0wNBGDrPF_k8YH{+i1}#obZ_wi8yt)=U^TNrc zXvEvTAq?Qqvj@G@Fr_&v#N$A-y>F3!{V(=T9;&(j6lPhtA>?yriglM-B{AcTY|UfRd3bx ztw)%xOD-)LSBl}L1;;KrjiSuybe3F?&|VQ)$#R0HQdh7Nm`dqI788a<9J|7j^}dov zyd~RZ$(?BQDLQ^8F7XW*oN^bI)M&nv*F?zyr2R^GS@I@jQ@i5Al3z7nX_l|l!At%C z*8cR8D0NY0tX(R9>DlT0sC(LXj7{%^-%7@={Rces!*3CO+ZdY#=4L?~&3=@z>*M&n zh;LZjhC+~gr$;PrUAm@p13v9y+fSOa^ltT?7wkSucOaKk_n%qma|Ekne6dkED|eCh7RGYv@Z9ScPQV5 z8tqA1-U|`P3qEEGzH3c5d%oZXRQa&-v8c%YWP-oENNuxuIZU>>qgYY-yz+(Ud|cju zZI@GilSmR9VhCirK-Zs_9UxN<_^b0l%}FV^Jn9~Ogajla7lodRa3W#I(`+dOuQDlh(( zi6Xg!j(nW*Isj_BDT@)NmwgE-brDAp&^k^k=;;53-r%I%C%1694zZ4HP>5BZ1@pVe zrVoLw^oqu!gIES~_+iLIHycR5ncILc2270Ba&VZufjpC9x_$C2=7P4#JYua^Jdf*+ z*b(Dhcku#sJG2ETenB|(P#4m`iz8ZB@i+EO#}o~Zz!{QDX2}9bW_!hkY)cXKC=CPu zwYqBUljnP7Ah(^U$e~0CD`Pjz!w)il!%@7TNpj}IPlHGlkARfqBOFQyI}QjEvyq`Q z)caHS*c-4sykTwcxuznR#n>$fFu!?)+K=&__6CefJH+NTR?I3(G;vBF=+JPo@RJ>>m{uI=N}*^Oxez%;33#i&%@;wlnCzV1yH+{Mn1^9NNG8dd&C3ev4}iU!-`Le$m2C^zLOP2J_0Qsr!sg;$di|h97n>I z0g+SG(~6W4IR(^kyaIKql>+hc#yZK5wlKGX0;@}*ZcG$JyW%F3KYGsTE`sP7+eHxl zv~fUo&5q8KTLUZn(VLWyQIA49%|Dj~WH)t>srY0-b{A1tG4q`Pd~!Eh1E_64o?}Me z1vD8ig5eg_u_zR~?4eBMYw$7Ff5}e1h8&gcW1W%G6DcWD9Zze%Sbu-4YjrbBT0NGl z>XN-^+R7Xm8%e~go8#rA>8)Z{*02S)Wijy|4xjqRu6M?+k3;%M702cvl)Z@_rm1Z| z7R6S@1hD5q=QqMtr;6$psKOgdwTj&dLT{f1-3>oQL2OrNU+hUUwwJi~AWN&*i%35V zb)UMJ`C=agV{am9HT}awAoH1Ap~(EyDt5R587A(>hRYYv3dJ?#-Xe1;cf7SUD0jSj zt9VYs+~&r74c2RXwKKjtUIpgqAwQ`OdoSK9t|RlzOr|VnsIuQvf8))nYBEZ%0kx-F z#doJOkWH#8J{*dFP8F-|6*KQCjQ^#D5{eg)F8&yk8S|GM8mTt09NUyW=9K3ljy~&) zDeV$l+a&rXE^I41K)hfkxWv6}5+f3qwv~MdF^l{g_q9n(NK9`l{e+oJzO4t^Bxd37 z5m0s}7O4 zKGLu^F38dnvutJR@QC}{B=#nrNIEbxY}Y~J8H$hqBwi*eX@4^@M`|$fzUE7u^d-Lb zCO$)T;$BI2nt0+UC?90it!TFJ#GfjbTHq1e+axoRO-lDcXoxG#nQTiD^{6hu`kw5T zgbI{>5Felg*d@te2#j5a)U{)koQbAVTdf4csDU)%;HfCzc zEyc+##E|HYmpWkO?gW02FS(c7kRl(D{a}m@Prl5w%cK#pj{Kt4wLFxSc zDSrvJo+WLIOXwtcfatCAmjqP)l5@EYrSlI^`G+F^6~!f2sQl;I`DfYrZ{Q^gO6TvS z^52I1$>I`qV;bKNA^uA?+4)o4hV1-!-;4O!gZ!@)m#CYRVt}3hBRl^WyhK51`WLGF zzcQ`VU0mu`{Ipd0OIxY@rPNtRv(>_(OG23A-q zVM|)6>!FW$X$j@mq~BY*HCOt@eGr=)VMg5qGi%ZHh(J=YJZ)+d`Yv?L!hK?Uc?z8b ztd^&cT71&WQy8V{mZxwxFpuRad=Vkj%TxFgLW<_$s|neWnumXHWv1QCFec!c%TqW- z85=H7;T?5rReE_U4F3S{$g!O84?-=r{XJ+|`1cyNXpI|fvf2RJ0=;Zq1Yoc1s9To< zz|O$1iUE8nJDZjc;5Tu%1`A;EY-pZ4p?RMU<;pU zy@jx=E&h?Qqb53Y0F`oz;{?B@jt4)n`j zr?07UZ2E%EGFLzj^2y2Rt03~)8g@%ty7DCl3waYFUFm|3feSiT`hpGw2|1u8`^e2X zvRc4*t96xMIO)ooe7cs-OLcVeh`>)Ea7;W-8cqILM?lZa(VN%=^wEldeomTz-nWjx z5W1l=otm3AIL6>!PE^Obzog{=U80Ym?_s>)UtL3)zFmCy*VhPK(!0*y(AV1bMjB5; zk|@%5=vWwPzerr9KSTcA+RcytlG^-m{cXhuZrpus>Ysz?vPoz}fBlG4KVo40Che|& zN6abDFRdY@-CcNTP}6lZbxBLL)&`BnfFEY&M)+2J0O$JP1hyeHcS*k%80Y$ML}j4u zOXkXaQmMwpsJ|<#_F};>#%VqA(#b+Ns|04K5y3yISPBkmulN`nbBrx^cN)hqu0wss z2kGuK4%K$2c-Am}sbNcdsdd?Gshf?6$+~sf3~0IuJ7-BtG-@$s#?lbA(joS=HHVlZ z%}q{;<%D|h2Ex0=zP9Gg_}hq>(_F1W^oeOA-rx$*9{UPV(p*R~V6FiN&m#xOf3E^k zJ`cAQt8m5rNv5SG-%@w-uwn}|vsUs2*&}Jmw+FsZRO85UM~ofz(@>_i^!fp-0gmzn!RBVHoHgKOCGCM560;c1jpc(KFui09jd*M;x2 z0(g&I)fK*vV5%$p@c*l>n()gF>iRTY*S8>kJ?i=e?peG${Rg5eRb3V~h^Pxo8R~kW zoz>gwYwZMqk*YH50*X*&R{sB^GHbjwrM@z2zFnEM1k?}WD|&aJvJ!kL57GbGmEr3p zsBD<3?Eho!J;0+XzW(vK*<=9`6pagp%cf9bG=#4TDk2@xM2#W}Qbe$eilV5XqI+lV zz1z|^4M^K08wo`qp(rA(y@FydD4-}VU z^p{Wf@AmHttj3XTE3R+JPV4;sU)tmHV?4sR?22M76O+GV6dd!=+=1&Nr%=}zm=k3S zM=AVbEr7Te=E%qbVHw%wGO|}r53~fH38Gf{L>XJ)6>?C{aB8Dtl|_1!W*7Jr)5{0l zfiD_8#O;CoAiIjmjb1F$$Em$~da!G-NAN+=yHwH(_9X|UKG?sVUho{)`9vh7x11-U ziQ`G`;6#gR@G?+6%6K-3iQp|!wx}zMfP2}4pE34OHa>JW3)Aow;@i#GqKn|^#6PF@ z%;}zQJwM_YpJK6~=de7|hx~Y`#5%EHj^;$`!VO$bYj@#!lqKyH#P=xEUT|t#PS-qW zwVQCU1A?NzDv}%PK})OrH?1&eH6?3di`My)Rtspo%Cr}q+OwzgR6dB~*%6zCcqSaO zp!v{$5#!jYz{e%?krpvNfvEB9D0}!croH6Uww^8yi9dBbU~2J*I0idP89Rr&v=dWw zl5`f6U>ANW32?2K6yrJi5Ui>VP1c84FBfb|cmt}O z%^t>;aL7~}Q`;kgu#)V7y_-44o!Awy*lpZr)ur(eh`rIqA=tiI2IM5gXayA)S*y(3e} zt)$-b-QG+qE#9+1c#_RmUNG4s*ArhU-dQq9-bXtp$!jEgm&qh?Zyk`Ulf4aAk`yrG zBd>rT>%e>0BUYqh(QJH}##;0TV-KS(J^UnaP_u*w-h|5a218zByBbh4edN|Znv%>rdO% ztt4O{FxTIWvc;1rV~^g-*y21`pai^|q<^h{Z(QZL&?@db2%Mn3pJepIA2n5nF+`eZ z{{{(!4m!ZQmJTr1)&VX-1g`=E)PIl$=>Xf4_>pHmM-uC>x&eiIKhI}59#};ul}aK!w2brtPRLZPjM?&2cD%0-yGmS`3Wm8JAmuak0bslvAx2 zVJV}!;)J$wDL2L;SG%d#!c@%6faP=<*J#G&@YqiGD9gjtV{(m~jC(+AQd?rM>OP-v zvW-VoBcL1L(Z}VB>h=nKzOfXLX{xbSGnNyg=0-HC@d{og(Tt~J39RA)6U)}75z{p^ab`Cp zda}&3YPt-wJEe&x98~jk)9g(_WeT7|Bksw$=9yGva)^%$jEAPG<^*A0fXIHe3yC%# zoMv7dWu7rzRr5As&LmH{;OsST2e_wfD5@FsnmRdqgCOS4bIpjk966dRYY4}T2bfPP zrnySyiN*!xEYc4zw{DY@)dS3T9f{^E2*0!&+WnM7bGwWY(~Ra`b3c+em1+|=XPdv9 z=yt7xeaO_Ywp||Mz0OqA+Y`aQz{@DP-em6?2qx!|@Br4Cp3lK}IDFvoo`(!Pm+c*| zdap|KUJ_**P5|1Oy=$Cz8e~PGmooOV+q)n_b(rW~Y+>P1*gVx+?)4UtcZ`cL#o+cn zVZE;I{S>Ru)3}!!&u%u(yAK08@1JR^&*Am{O@ZV@5(*!?D|{z=eJ2o1J_x~mP!otH z=m8hEFICb@=hN9Z-$W#-z&9PJUu5L?<{{*x8XZ4=Y`d&jpYZySK+qx9vMW~Ui_D`j zK2|~10duM4wwmk5Ol|Kt60IS7rfj^~R*!Kru<1?^{4k=}rSduaHhqAD&p;Wr_Z)l3 zKmIrse%En5$LA`Z_RiDO7~QZ+QmTmTq`&b>nA+3CAdE-IZk-~c9UnMOw#LP`x_N8o z9)rJU_ZSL<@k}@W+!DqdZG~^aO&*Wp;t&ba_)&l$Gch1ORiGp|bbZJQO(YRKTl9Ae zoIFE`X#(8=Fu~{nF(%5y0JpfrI(IK}$;U0OmNUg3aXp+{K+-x_=5>ol8$F=l5t{Vi zv*6&OglMoxGG@VRajvWhxsG)wVqLP>q9;+tsIC0k^~Nwxy2y~;^J>f zD4ow1dLpd#C?dw|7!yChf*xkCin~Sz>t4r5I8iNk5I8~mQq`y7k4BXa+{ZvBdKi5k z%nm)wUfILw3#}eTe=N#$k_AlOcS|ND_@^o#z%%$Prr32i7*f$Pw%FmWath)2X17Yf+OqSk^k`=x!>l<>&X+j`lcVQW;x&B5L^Us z=%dI^3+?(un0CJ@FGS_?jxMI7Js_!)Q;9pBx%wme;{e?(d1`>32VGZ0nUR~$Z^_n6 z+7&W$cGZe@`aJnx+>=plGv^aW_4ZVV!1 z#tgh8Z4B2wrJ6BD0hT+!xDwWhWKHL{Vc(1~MS2SZHD)aI7_-TX;CISw3@{c0e?bf% zX`}?3URV@a$Y1vpC89#dtfN)Pq6T(Z$kZTWg)CZOw+mUkNcOfu&JiEsKHM*o#Ya}H zj&fk7S$rF1W~(NCg0YQ@BQV}z+BXW=#0&EJVWgoHWRM0El8;~(CwGsA{Glp!Y_6R3Z3z!TIF2=>Eu(Ee^FOLBOci4~rZ> zCu{d>3;7bJi~$UhaM)o%BmtN>Sr5A2LAo$3588^?{C zk(!_i4&WLRj0#5V3qAZ%ST-vB?hL2)OERzGVL>}LNTfibuYtq*p*hfc4W?pvl)r}R zyjwO9H-E!U%RMZI?^1A3__4O@@r5bgOw@rSJfztWC*pi~4aDAUM=Cyk6-=d-!cT~XLifJ4D0_;riZ4yEXC=sWAacZ@~)k;1dF z`#)a$Jq0%!AMVEQ164{ki`V{0F`P!PZv6gs(4Q&B8ODFQ@dW_clkR*JP>-Y-V~wl2 z@dw&b|4K3D825DJ54MB;PB9)cjBXlTxQlhScxa!ymG6#z6I3+NRUQYyYHp z`+J8v`9i{n4(z4nsxjKNN&-J2#RwZ=^GRgMVKhtAnUG+tfdJ(9$@Cjhvfppn-y!>g z_7ofY3GjgB`8U}gly=2D9S*H899T~``;$pmF5-fPQOZQ~Y%|xq5K+?WG03;eoRCFD zq5X-iN9GjOyv1cs&!XIDN3BIObDnA57G;42d=Vc9#Rsymx2Z`Kmsw_-1u;ME=;$t3 zF8tlY0OlRaFlXSLt7Gh_9=YDB-Z_A^E!cZ+YP1*Z zy^nbzpSiWsIh5-y_13`YmkF5bts_&rHrKns3qi~SaBjpIv`>?~Z$}35AVm}zl)%NnCfpM^kRMdS#d>6r)FEM4Q%>?e{mW^HEyEcwg2uiry zcWopCFN&$YmsMYb>hr6<2i(3HjUEU&mv43!HAu|4$8I#_1#&+pUTpG}%=P6XI=P9v z@c@h9ET-+3>|5QqPSS6*Z#4AnaQJovs!)v(z`nQO$K^^TwoOr$&X!$kr&^VuWZy?r zv1IRDw-WOIqk4TiD0#AaDP8}!>cvg4zONE}d!j7w-jf-f)kyaJ$WMcr=tF0ifBvbU ziR+|J^CtjhL{IEgPPDD8ZFrFFKV9{wC;IzI6gl>hci^0WVCPHNT>p5R8~ii;w;+{8 zvKFbHl|(;UGsO<<2c+$6KX%fC0|4*=kl6#1(TTQ|wGB_uZ&#(7C#hoPWNOT z#4ZT8|8<*1@c`s6iTLaloHj@_j<_O_*v>hDM2m9*Nm;x^ z`!#_jBnHkw@T*T^rHO%yWooc<=1NeQox)rJh$aYQEDrL7LV5hb-C_lC8lNBv*s26fF2zS1Jx^{iz#HV>YHH2AX9h zvQhC@1h#glh^=--yqLw&eNj|_9l!*iVC&2OK-e94vAvvwh=E-Z__PDfPi>levv`?J z^Jt8wN_c)q(hbrhwa|M$VgGpBCyBe=%YH+wKcurz)umz%-AK72c4bsMH2tw+r z;;slzYEMsal9is|)HY@d-iYADY^Mbuf(@)6d?3-bwzGa>P_trj1-LJnasoso+@aw}CLS3i@QM!Y#scRNxV1yG zvB0W#f}NyTqmgi{(bx$<4xHSPf?K$T=idb;2ZtiN3SJl@Cv`G;vtjazHqmJ9El>XIQC1p|SK^<^7A^TEkx0GER`^o<<|2IIF*=30N8?^wt=8kIle}Lpx&q3bPI%HnZ zC5tp~4R4v=ms`-kAPb?YI))nVDj3QO{)14jcL+7QJydqVb!x$Fu7a7i_9|!PTm=h6 z!5s*+n*@aQ{OW%S%;bVR`G(nmf|sy!vRW%>q|~JI8cg>Ue5e+D?JD@RGnrrYf&)=j zc3KBAg$c=p-7PYO6Nn5i>`%#)WO56q7tX<~$_*rplu&lz-D=^ZuEO~?Rbm?Z-n#t4 z^&tGQTDZqm_`X`W(^dGIt&!90Adn{WT0WlFflbuHUtERX9_Q;S{7WnRozhR`;wnnu zMG7T@T#Vy+<*^fsa*A#%nvCj+Dg8y)$CQ3YZqY+U8VWls6WU)bYH}4-nnlG?R(=Ps z=MyNUbBi{iT3y;qtPq!~MX$7tZ)of_W@LWR2Qml6535B#yNbRxi@?JO9ZR-Z+>_jD z@j0US3?yy0oc1gp=PJI?EIwDFVrbE(-XOSWA&Kl=r7uTk$#Vd^B21-?XNslYW{Wm$q-zWwhFev+&MKCT)NGa)3a$=|&B>?>c zMT93vU2w*+goK0=bmq1u%}R!my^%7^O2&{~>fx+pCfVEdX;wnBc-F~D*@QZ&q!?(F zJof*3piy!nVze|-O8fs!6LnruQrq5tl+;?CQc0wdw03vN3ORx5Dv9DX)hMf|#s=MI z29$h;N!v!PWIG_u>7Kp3t(FLw6)Y{MT4Ux=X%q@5&_A+>kSba_RJ< zb|_N~ohm}$#){|KMj=B(y&a+6A(}gd6b#V>5KY(7VGpDer*cE7iYqiIF_ao*ONvf` zC)!nH7;ge1i<~!74PBZT8iBm*?Zx;L7@er01!`z^VhH@ZWIFKoqd@f#n785`);Le< z(|YJZ%XzJGT1MpjST{=J;EH`F{eKi^P^$m8Zq&kU>qeLM?N@x+iq# zMk}d0r2dJD>d=pNfUDg)bfgwsEpb^9wP~LcZgr$~5@bi}ObOM8o+w?0sz#SaW$6fQ zgfot&WkW9kz_FzTb26b%$=;#8gbo1Ep}q9TrO@pI^U&Y_Z`#Y1p(jAtY9^Gl|64P0 zVM zn~}8A$-tHm2$kNRSUSf>KN-y8DqWCRdJg~}pCma8@3!z#0e7617h?-j-mOd;VGQ`iZROwl!^ETQc5B~PL{SD-W$N7*1aWIHPxN<}rgt%sMR_@R&t9J7y( z+_H&fU<1A~rhAQ2&Mv!-JlVvuIc1NOVNx)*$J|qPf0R}Ifho%}Z&^M9#kSItvQbvX z%L=2c`aG#+Kx9F^$Szy1mObq%YY}Cu;B`55>C{VL<&Ex~)bbNuVp1#uQXmxmWX8ze6^p$U806H9;&*&iA~k75_iZX)lG9^YcExVB;zw7-e!b#L88P+Mv=P=-@w>O;XBkw^3|^1IJFW6W z0Lr_TN;^jKu&b39wkZrF)ynI%%Bw&}maeyQCWS{yUR-&%Qu$!zLPTq=p{tcXSEa{W z`EV=(DL4}=DdFW^QTVfzRJAgcSP4y~_QY;-7Q|J#RIem#Juz+nUorMpgjJwBs+P@m6pP|#Kb!D8otB>@AFvBk}5@8f|OSG zcJeMM%Z@BNR`)IH93weuEsm;gHQZT~G8$unt)u$Qt6RV!7dbjFD;(=-@ zw0YH=z?q4Hs@h!zdCk{a(y;1#4aYtdQFR#JOBL!Q8!MYp z^+28op3$ozE9=%;MOA%ktdG~K?&9X>0TQQXTFtDOz*f|nTeX_mXZvDoUuQ2B))@%(V24m(W_R5(J6ydL?#Wo(@Oqg) zOC?md*HedvW7QF*JLtkUiLuaP#!ByGtl}}omZIHNK_{p?nX!7}@~&~bdrIApb%*QI z9eg9W9#wWWMw{`xM@smF@X38VKS43m9>#)4&y;ZAaB?3!twPL!W34^GLgVfO9{`y-y+60A&Pmh$c7nSKv6(%L^`Y}=$tI?K~#E5DzAddEQ^Z6 z$xluRKNc3@*HFF0DvBcUUpmxbHXhUf8njJ@Y6uyayK+) zH1BfqUMb-n;djFj9FluL_#<-2pIkUm!v|d9y%s&mUz*R!Pe}>?5&pY=VC-hpdI#Ct z1G(!@lrs>ndev2bnhfmuMDq|r!*6KKkTZ=2zHI=Iz_1AW%3vTQROo-=w zQUDy%O`}5$jbl)ONjBgj2s&AG@w~4Db+~*Sy*C})BTM(sn z47vVw0+Qlg{|-!h&|kk7cKHI(Fjjw%?3k;uxD_)L*r!|nhoUz0QX3pvJ(QWIx!UiGKU(=}p!Fy#Uk!}}qDo*%RYrW_ZJX*l~D|a_~eie2>F|9Au_69BMey)YZYa{woLnNogF^ znAtd-a?p5wBL$@&a*!!=0KXVtWTiBYY`mh$Y2~1CR9g-jrx1{G(1^|^mV?H-VYh3h zaS_=&fx#|2lEs`QhjLwY=jf_AH&s#A>#>yCYBnRFn zv+T&VYGk$^nFg1)V+@h`$&rWb7~Vz!II8=}he5Azlb5ow^{lwc&{!*t~?69u> zL<)uqMjX;V4Br^-H?*Y-Qkq6IjctPZ&KylSO_zf@{ZM0P%NlDMYt>kslMhR2x~ge* z(;<`r+EUXb(6D%}=?(%?jWx}OY4co@2X?#0n)1lrsm2_+P0O0<0DXtjqNq*vS^Qn9 zvL;kg^G3$c%Wc}+1X;=7vk{)N5O~uYKzJSqIZf{)++NYN3xE%;@@o1H_CHWwPJUj> z@_UyrXx2ai1&8iq`C@XAinttdnDO^PSoTEJw&O?omP0LGakaX9m1j9R>=jq@4}irY z?s_c z(rh-DHSg)dKZ;d8%mhA?(i@MOAXENOkHcj>whQDDDa|XIpKSh|#qm1eD30b$aLDRw zMsdfguXzXTcJ(!XLiP^T2PazzURfD}1>86)WkvrL8SBS6Fw(M^k)bOald@v$iY-q5 zaYsf(dgiXUtV53ZaDHJtADgmb$I3xYzN-^1I<6I;b;NaXbYbICR^_ak)CYId5ofS? zK0amDt*h?s!)u9ehXXJnWffml*oW5>0MB42@XJzGUxPm?O~>l#mg#V;o{jS2izJ!V z^T;lTmuxj;UA#4%lx<;@GCCeg$~fxiR!xU(Jau%dZiQ_EZQEFNUpHm-HC9VW;FqVY zxnj)~Eq=y7XO1<~U}1EKV9gwu)HuL&%9?xN;7`IaMVY&1F`2Xhg+}(>bJrBEDTnWF zN|&Opsm$Vgh$YrEBBobxDr98uH7!|uk$X+Fk;6k>v)!}iW%9F_jIa3w4qRrlo$+zm zYraX-)*J-jJ*KY3KBlAOC)wAv_C(Lx1PVtSZS(S4HF<5CH2_;X2LrIZp0(2n1$#`_ z-oJJsk~NrefMLfc*=u!mZMkc0p=YfxMn#T#`Pxc~#9B%Su3a8wt9|O)jh?k@2u&uE zuZJ-*So>+V|jAaWD7bMsmDIbh#a4x*t`8fhS(w{At0Jvl{P_pE2#MhYTxrmow;*S*pSU0wGH zU-xbs2s0nEtX!_cLPfpW;+(sVE`5uMX1v%olX9uIbRqhb%L&;nebkmST`ejCSPKs5 z!elO6MkKe4wQ||=7;?E!Z@GnJTie(@H1^__SCy8XEs)vv zGzTszX!(SXrc z^6Zq>8LhL|k3rf&nlk8Uy`7wt)7E=o@^7dBNrcd7MagMhq@=}uYAg4&dZKLY2IARt zPbKXIR9nkEt)*>1{;dUE;b}!9vN8F07I3Sl72Qz`_`L;u$J6?DJMf?d{MysHuO0Y< z1w7(u{i7ZDqXe$+=~;hbJMbq9nC4lZ(hfwkMmpD@=UG3r9rz1?$nP3d^O`3aTU*Z9 zx+egjo=8c713im>C3G1I3{E6m%pf;j054w0+ji!iO!c3%`P; zLKZ6shTaXK4Uj!YZkC>k-2fOM6IvY4P4#@>*%h4N7>@{vlVQa3NvT>l?aYK8paRy+ z#dSr=d^UwZXE{4nyAgknu%7UBXp3O8eiD<;;A=NpO{JTYPfpc_Xy?!RxOq{+s2+QBCAE)yb!(Lhv<-%^(aFgFRX&xrHKDA>ILkL5}?H;lBcUQ9Azvl*B1G?KeRl zgYk%)v|k-{S~-TGK^P`dSrlm)d-`u_(zfW$hYEu<^An zOT<}KXrL6otG7Fd}(=2bMos_jo*!-U_C!+pKm|KZpCzYE!t*dY=NV6mzhmwK)RKER&-62J z+V~CEwR^iFrsv$=K~`0H2TFeP_6D??_$}LeeyZvn!@VO2uOnl5Cj-)wF`6k}?D-W- z>3lx0bbm{>GFJR&fcfC;FzVQlO~ z-$T9zp9hdw>G^`4OV77b^{w~#pvr8NN5fsdZQQpBuK84uRC;*#-nRpQ8(h9U+=p&! z<9y-dH;?lj#u(4vQ^75<|C+2gM5X<$i!Fz{HbhQy^9@xJ_te~z%bc6R^|9<4@Tj?$T!{Z-;__=;u z?rLo04~i3ksRmBb0uU^l2FeB5bkQA)vCMd3VqjokWFU(Qg|xAu*z?N+=K*g5PKgAv z1CwH) z;y0%T=LHw_5l({8^T7O;)Sw;=^btMUAh)Il%Yt=%L{A%nUP~4(66K&mmOse=^2(UT zb7QclhuAhHm9eKsAo*!X;tJR=fJdAKBU=}K2ZL7^a}|2l-*BMh6?~)d?Zpi=zcCbw zIN6J-d~+HOC}7*AIR|Dg%sXJtg$djQh^H~;bn`}&8WMBH^E=bLFMGd9$VRe_qd1tj z!;Di<8aYYcFU@iB{H`?Le|%FDF1NjX7skAOSDNGF`Q2&$6#wXi%WQA|pqRIRggGIe z&r1uO8@M9jQrkN)()fd-jpz5K75-l2j2FF-C&>9r0h*syw4$gbUYsI9Xx~Xret%lv z<-ps4uN6!^l5_}s5crx1;5XZ0j=^mWA1kiF-lV|Cd|r<6kCQJ*3*H-iq|m1*;By2B zib9`6mogqABq29X03c44u~J{;%PWnt&GkunH4)5j=FzIY2}u=~o%c+tn)hl_-Zm~D zZ-NegS5DqeB`NPCK7aJcA$ebC=WA-d-;-}pcoKX``FS`d61hAlzZ&*NLhGBqmf!2i zf1XgX^IuoC1A{nV{mkd91wGUP9JxA5xPn%f(s?S2T+y2{5XsFc z=%*wV4B+#Thk~&M=yN@vNOn{UE|<6LBG73P^~&6W9R(jDlem3=2Boz9YqwVLNt8Wv zs~jnTVdS~YF==X{Q!O~675qkiQpYYp<9o)0j!j8S7rmthS(u_0CTfKzw_z2cA$Gv( z1FVAI3e(xhzJ*zQKJK_3&kKhW3Q?hrVOn7h1y&2EXoZu=W)FW0Z<2%>w^REYmQ#4Y zl2rIGpYP-kq!nLSd~xwj(8H)}$9=3<7T-kK!%t>Ar}%2cRXjbZ_-Z~+`@l?a@`ut& zE-A^y-KmP!9az};G(}#d+C}M7G7A8K8&AMjB@d82NfNj3+bV9A|ecCt%;QPh$nNhQA^+1kMH#1Lg@<-B^2A7sBeF2mp@jz+mGB_lqr49e0v~-oCE?u9r zbQLJ25v8SDL1_*%yF2-#X;ptz9jiVEl=@3b)!pEbl&X9Ei&AxxqE@FRRVRT`f1*^4 z65qO#nI}5=;ylJ^43q{CrMgo< z=`b^UIQe5~;ZwtX!k2;4KuIZ_28W~+KJ#Cc!sjY#ctle8Tu>TFl)@9EY};sN_H^>c z)9Syk|G5DVx`;uNQvESFB&CKf|Dx1zG8PW{BsH82N`r_}Lpmt=nR$|vd(s;Ji6lhu zK#B*t2XYtb1_xFzm97ygC%f%L&LDf|wj<}ek83-TYY4A%+ldf=9@lmv9)fjlJCSmN zb#6Nm^m$CA|F`xOc?J{lFC;~t;qyHEyRxpH$g9ZJyISNe7`u7o0~o)G$Y)U&?V?Ba z!RTv5zJoEujQj#)yf^YEjH%2#*~zuE<;lwjEx!Q;N;$Y7o!pvSy&eK*-UwPZgB0#^BM|s`)fI3^a;s}QkdwufvwFFr zu3nq8dN~r7L6lZM3rY)_d8(7^X>0CWbKjZ21B-QxD<9FXFX;8pe1g&T2VJlPuhTPLdYlWHlWLS{(f!4oiH9}Wf74J z`7m}d)9vKGv`r6fdSp{QQ%D9Xj!lolE=zio7iNqFKo$DTrXoe%RGGA?h|iOQ%T3i$ z_Ch8zlbzh3_EhFm=RS2G5_z^H^wfAbB%!BBdUPO!mD;Bu@t>NR^b{n%prbjSr|t%& z2bh`SsrOi|pBCRdEpt>2_#O6zrHje?-b11u; zuLad@+U6NB-e6{`lLynbe70rZvt5~T6@n{{E#JW|Q@Q1PqIc?ySi{+ZS&}VBleQe< z^RA*4J{uopFZN|-nv>_HZL8R}Y}<=Wxl$6@RtLKzvTZrc_N+!ORdTjrQhD3cN!!-( zc~=shZQDR+HZ%J>d45`yjW5Bs1mAN^$(7V#ua|B~5jNud4haKfrJ~~h)+Dm>c~GJi z53FcEFSamqfRe`8i(f%AUyXqHZN3~I1{GT_!S^s@&)$k}Exsd+ZJmIx03Q^xZ3wsR zE_@pqi$2TPb0^|Mc{~@v_akG^Pr=v9*b67)yAB^1<%MI23p8HLv*N@ROBe|hu>SwL zFk>*p)2D6kN8JQh+l?8#xW8B_UNawX;K8oBV%2O%W2@&W8uQqfF7YzTNBnVP6aQ=;>&*L6T0?=3n+h7pA%ED55udHEa_P^w^|jU=8Dbd!4GQ*u^qtB2hrAMn zm@dx4Y`!tcKt`=fR9wb<)wt7bTqmfTu?RDfNZYq?vyICLx($y-PO~p*GQ!rC8^%j< z>Ee91(JF7J@EGXyUmjpzhSAsfrtvBHRu@2uacqWSI+5VmwHIcuWV5$S(E#)I_;hiB zYT_lN?o`d@R7nQ6Xo}&Qc`F=CC|xh1WM6(C7ObF^_cs@skC`7hu7(pui18IoQdaiI z)JwDZ9$XH*DM==@F%$LN;hGCxPGyR*n{~~Fxjo8Wkr`*NoDW3&un(iCzj#QLisfja zLs4A|?dn2-iwZ!kAFgy3)i|ZzkSwaL>XVg%Gkgko;}sogMy0;|1?*!GA`a$w3yz^8 zSZE1DVab!~BWc6C#VsQ&9zyjPDY(=K2H4P3Op;s1irL$$0el3XrXO{P3-O{9Z7_+k z(lnr;9O?)&{y0{uvRUbR@T!l32vp45NfGmfN?(l zZi35!t3k;`*&CO`Y`>I+hb6ZfQ;Zv_Z5T5V!8TxkI>aCSP?gIDXovYJ`~q<62s|I~ zTRXR6aqI%ZL7lo`#>6%~@s^G&S+bIOy2ULB2=e^gD0{s(<24F6^Yx3tta}g<^rhE+ zKxi=VYd>3Xi-8;2KtL61wE+y=b{h+SVxTALd0Fe{5MvNK@@#YFN|5;%XFhQpXEqP? zeC7E`>#MM9fUP(@hj2N9^+V3&BM6=&cmUzlB&~bnW|C9zd_9Wq5G+Uzilk|vr{1&L z^Q@xSG}d`Y4A4)~$nmUKT%OIzp7mU&=^EawATw_a2NhJ?8=yjz-asoNn3dmE47GX! z!1U%^A1m8up|(&!s9JjRV1c~m)KdjlKNR;?t1){%wwv)ERx{R4fI9_LsmJGQ2k|%f zPII|Kj72={Wwn9)k8j0mJC+r;nY0YzKl397dY)^6jYj+r*|DEr!CV7_D_)eFd&eY(C2Q61n} z$bvz41#iC%*A}zJ7Hsl1dgw+1`C8j>agV>z7s4iuKu+E|$T-IsVImt4{-{c00@)=$ z8>EE&*Q$!oHfFnwd)&s&oh!pIWM!mJq29iklA2F-i}xmQYmD(ilbZA;F7q^fO!(a-J+UmlIdzJ z(a<8$LYCTeXq`(nFVW1=6tyfJZce5EC>`nN(aeS9*H$)IPSMO|1OlNqzGrOvCdPKW z3kMp_#zE#vbDj4o$5iA2NwQ_?=0UjR<4f--AUVvRq=`ppOtib0OqDlyYPjU&`nEw3 zihx@;EPDqUHxItiv3BBSiWg$^1rZulThzlH>Cb-8+gH zr}0N%+s(1)vt|&l;ZNXxGsR*wz7}@tXA{CTAN<*5zR@B?SlBMF3}Wo@`6W&4ryq#kC!41Xc8J6Cz8=neUhrTV-5{2j-4d4RMuFq^u7uSgC#!iPok3*Gt zGYF%Dd>#giM@^C`f2gRfwg9}H0H~R0x_DgZ##`3?($LTH$xg*4%3#KdO@!fyU3qB_ zex<@JT3zCKx7gIV`G}7!S*D)^SvFA>-^66lFHyF$o4nyYUDMH)ce)_U^nR&sJX z^bCnXvP{1qSs%q;lCo^E)J^p3V_L(lZFESv(SsmRWGOd#RXc%|$@)5*z%h%!r!fNi zVgyLJAr(e7GTg@L5jsiWG5Ski?R5oZ#FI4xt!}5Q@ok8tNi!7crrT5-TZQi_1R6O{&4@3YvV!@m)en1V!8|Mm;) zR;!RA$Zi#~vx`+Pt-jMepQN9sKtIn+7AY1pT}MqqoQH@GP_c+hU^~pC3fT4CbCI*P zi2F`_uTc~*-?ZRX@BcD81MG+rrLMid#m;D%#Lm-UQ2G!mj=y$>_M>))_vf3F=Mf_!y24*zk`3?!{xK;f%NGW@6ioeERj^}Tkp&iqXIR&i; zaq=aDFOBDKpTWEGu1+C0Z?t(d$McBn7I z$fkzcY#f89=g3Y&jA10!5TV?|{)UG|*?VKLhkZM3?R)QvZV>e-K;+lS-?gd6_ORQO z$(QKF_OPS#VedVTubG0y@ej`6DSVLrh(lZnH+TswMN;4s82^$2A9PfM5a&l{@JsmR z`XX5s#3qx-E`=vaFL9O3jl$&wDE8t~$??amqLX5P7r1z}o0oJJ1H9D|1AISP#?>DF zT9mziQo5L|@y}ty=BHf#H<5=Jj$FmYULsD^L?Zb(Fm9YHhFTHOyCeZ|G2ru(#iR(X zZ-t_MxkubY)W(Si;VPahiY0Qhh1_Hzx7f(ndW4L6oY)2A-{%UtYU?%rv_#gsN@P9J zM$YxKWMB^O*KMQ^3$D zMNPmiOHuQ|jFlo@0E5FWMQv@Y6s`R@uO(~GS#>s@8k_c3lznimA|`3tm$2Q)KT^<& zKBz;(qPj=d@xgf%1ZpRGd19guk*gc-_&cLmH1@S#FNrOc1qGjZ-GPHNJ@0?<#APRplJ3SI0h$R}t`w3~`m1 z(MQabk)YWi>^B)=jd-z-xZa|cE@s8^FEhm3;`2V@h7Nf9GW6m4gg#<+8%#+M@frEv zd~d;R>}2N1FNJBR*F&;l&dpyTGyjn+9PIJ#oxd&Xk)-_BOg}$>71Gc7?kvE5 z&Z0!Q^N-0fzPsQA?m@4gRM1Pi&Q;JmOI**tL7jYocc9M5qGY)XhTE7ExW~a9Nd=b? z<|K)kuK9udWgPZf?kA!0(U5LRzSoi^r#bm|8G5#Ujd@UE;zmlaL%+d9_alEY%~&PY zZ&CFJT>2eZlwZEDP2r5o)dTdxhqy^%s(M3`UKP1EwnUq)Z*uF;aFdiX{lzSCGyl<} zzaM2EcSozrHB1BCC2o;H-A10wBNk)bMmaZ#v5i_n#T2>ASSMJ&&rw|dIkKMl zmrnjehCl3I<^L1`ZU-KA=sfNJv~z$h*lM#ymXFK-LYBCde?Qm%7RAorVNU*IM&P`_ z*uaAzAhke8U{c`0P6PtiDDJ>D7JBk)-e8+7K%1O&bdo@j@+ z`%yHtoWKu?8jN=Z{&od^$fCB$_iCdfQ({*zIQh>RL0_;qxKUx+1W6~jEC^vGe~1gK z8o?TnsL2v{K;d!+my7+iP$&Y3f{$6;r2o)jjkhnz& zJHOmNTEqADK`!m^~RI7gIz^#yNm=FSn(8%h_YQju*h^L|2v~-UeWzUQ1`@L z7Qu(fAqjdq5QJ)g;x1b1D$0u$_k|=cit0Q?%cAVF(Vi0VmZxYrSy^L&lON6~KDYRy z;_1j$t|W{N6x5f}&nm6rOR;C-YFF{4S=4{2;+ymxi&mVy{d@>78)MM3g>2iC92Alr87_miqZ_PiZj%f9@14 zqx7fJ!(}R%VwDy22sz}>s?D-qt};i~T>g_FQY-=ufqnD_V;_Ia*e7TwpFkph@(8{y z`2J?>Q*hd+9>x$K+jRxLMff84b~5%E21K6$_p?@fP?bNw2;Xz~jxx3zItM!~P9$WM zm6ugj7CE5k#dHxzyy%)y_Ey=i*lbO@2y}?#vIE%agI~NjA)~xUc}5@c5EKM6Nb1W* zCAr*fmdW6dLh+(oM)|qr=;0SyJv^?#M-SgSqaqG}ZtT(ilsPI?*sPz7fEJP};;f$4 z=@chslxLS;U4B~|r|zBUV;;-rl7y7I>ISK9cpd{y}?6kJitTVQtJ%krm{-sMlr z_&nt=McJNaindoq`J3hMmH!bW( zqvA<&P;3=X!-US-i1I@tsCWstTD<3~cuA(!n*FZ$ILh{7`%AG?BxY3JRyn`20EC88 zct_;|a>$>okDSVfv3bVts(jcYKv>Ky!GC)o@%Esl?a9Np9p4eg_KwH57@kgi3N+ij zVCN4VU=k4BTLT~zV1kjYi|E77v=)ZU3dV*&KOzMeBvGwwzBSbJ6rqJ8OP+db1WEzp zMBg)U*yM5J8HWIqwvVAiG7*MoM~wClW!Ja!7)tazlh^Tx0irX3gfY|#vdb|P)l_UI zg$}YZ@v!8Px%?F}J$Yza3Ay}Z{smIi9U$zd#kl<;61)7zDEneE%jSQ%#0hSGtn&y< zq}Y?j6EVVigo{idKb$Te)x>DnX46FRHCXtWCMQ?i(C{7xO)lmV8ukd%64GPILYKRa z28drB>0&V#n=K-b(aZ`D8P>Yb>2tto@ zeY!=+BWGB$^{oiE-Fqt3zq9psWiCDXdlX&~4`)zX^h3$|5sQRz8AxbyZ#-p)Gi<^( zW@7T?CX{V#71WrQY%H+xpF{x&Zq&&rwTZ%56=h%6qO92$=QH-@Td*i`BIQhDtMQ^a zh^85-f@cvpL8P6Deeb`U1K@I)3DN}5n?2yxAS|uXyGXGnTzXq;NoKz&+eh6eWBW)} z;iou7(wV#;PvaPr+FXzhyTt|I#C9$i0Y@7b(0r)9s2N6v} z8Ob*h_uVS`p%&P_MzB2E#+SQbzmTGUInsj5F(9^!on=iUV(`}wY@UzleY-K-Y_|e| z{7phwSvG^t(hWW6O>_v|Dx7HqPY{Ug-`qdwIPO2=EPb#3t@ji>T~DDL`j2F1@tEoV z9i|*1F^6#?>~!=H0y4IaVjy|wEjz;~&i^`L@5nVK5RKS$eB8)9V^)-X6&_|lW45Q` zg>gGT2Bzb0H>CAxdsKtz_{ByO!ZRCAJWw!pqETox8I?rWnh;Ae>a?lQ^Nh9JSPxS3 z!JVqHQ#W3tsO0qf08_#0z2P>#laJCH#u0e^3BpyQvrU)VOtPAsnJQIn!#sn$J!TdR zlsKj|RPzemyto5Bp}5VNl2~j6WSI9^p%z-9Ks?(l(#%pgaVBt_*~~^ujn@2LH}?^# zw%LC#Q*>_^0wGslp~v}pCoBs7ImN)U#GB%MoioL%EAa{JvaZAzFzvb$$V^*Z>C}y4 zPEe-`j8&FS+jGIU`XB=SmzA&_{Q^8;HYQoWz+$3V@nC0tVw8RTx5JaC=~JR?KW=X4 z`mM0IwIV?)$otR5E;MlNegn+>2NM1{s3YND@3mmCL&l#)GvW?_X@cWaxtw?bm>UWP zehG0RGgG@j8s-vfuR`Aa`_P&M+iTXjT^JXAQj_gfhZ}22+043Y7lD3 zd@x&FsESK9F)GRq2;y>8%yfyV$>K6`6=6Wb&WYh-k2Cn#C+-LCgUR9%3nN>ER1wxh zMLUJ{F0m$AGzt=7L}AMD6yC5XylY`dqQ6+6BXZ2fa`Z&hbYFrw#n4RSE8}|;#VJ#d zrMW-IA%8NDI2Qw{ds17TaoS66Y&SEb?3;&F^HR5Y0iR6xoGwCE&B<9JNKU9y{92}% zcVK%A)N89_U^(V8Y=fz%uud^7(|42aw%}ACQxFW=?<0q73ciIzgTxUoENI`-hvQ%L zx|OfQ9d?kzVgV-vxuq2AoQN?#6PI%1iuQwcPmXnZWq^M?y01d+PmHo}N2D)Q{aJ3myF-@ctHR%opxp9* za{amfYY`Dz9PN(x-{$sD?GO>CS1bvaBFcCBd8dfpL`22HUkj8*is&h~e|d+9g#QKd zu_DU$zo!Pess6uI{{grEqfThQ+GsJ>ph8L)B^HnQ14;1CQUk->fq@;8CIaKEV00gb zKbTHPB6tqLa)J}^lH_FsL8Tmk7I***{LLhMI~e;8Jr#?O6T>s}U&w!_@b@mWQG>`n zwFxxc2{2gvaSB?ey9l~C#fZ%OUHM<(>GwDhqF|2vBl+k+5+7MKgG_&aAq92N}4M~)O4E4ztnd123?iLk$kX778 z$#9D7%;J-a2bTDOA5!KP_iD!E0WVtc*K$Tf?pybao^w^>da~*W(+bWz;4+6>`4b`(lu2fg3ZW{nh4f!IQ zyYxNU+np|IX!l8359`^tvU{NZ*SgEjq^-XL%0}Rr#<`MAx~OBLogya_cT3ikty0iE zDRaxvaoUAY)=;*}E(Dp?oU$g+4m-tVnPuzBUM>3tJW_!WE$tybD*L5l2(V_^=Ll1e zCBIAz@~2najdH3~=9cHQg(<&@fN~UmC(Mpbjiv|7A4+wXKdN1Ww0p{pDEny$Lk*Ny zme+z(gG|?e@@JqvHhRi8l6P+TtL1OOFCzV1nOEQ<>ZZl%FC8Q-=Ep*96OVDr2 zA7D}nE*Xa~PdLT&%q1(AY*|W709IQ<8=UPhFAp4OOvzqW=UTSLy{ysFi^Sdh7x3b;sG=@=B}*))M!W3ODEoB>6SK3I9ds=_>R$G< zjXRJ33f!t5idvPJC7KDhD&4}JLmp#^w`ONn&8(VJ134u3I^(*~1>~UgR6Y8y^f+>> z@~V(b4JSIOOUkYar@E_}tSYTq6J>{H(TZBt^Hpzypj={9+*R+$R+BDPri)b!4;5us z9ZPjr$6FOx-5sGSWi?f&Yuh2AdG*-@!mf>s(b?5EyQ^=vG4E-|Y?f8+t`17lyt;_I z(#0I+skTyqyGp8G1@Qh1rd02lp;V)x#O7k$HP!>0?wT`6oDZnc!E>v5&4ZFYL{JTG zBdrNjXs4KyS+lNYW8ER-rS;vSAp)SInbeiY7VEmYmQh2RO^Vc z!;ez|)w*ikAV{|yVfw5##S$yE1GVeY#Tpcml3jbbyVhp$TCn(GTK~_jonN~U!EC8q zTPmAMZ6Q(3uB}T|YqzMit?t^0?B99q3K=eTFDv!gqV^@gaC^yx)T`C*vzkTiEhf&611Z%69zL@V0h*$i?tR$hfsmaa(5i z#qg(Ly9*A#)E?ryaHlRfC;WqQmQ&oG8UDS#XFaWlL7NQ!(S~2|Zo3Qrl$f$8<_*^J1-k6xFz3k*5Xh9H7&694^9PGL z;Y z?Cc{p0DzgmxCFrmix0#H*bW0a;wx#={=kE9i;Y&o#ZicB&rWi57)guywBJb)3uu?q zpXYUD;(=s6MFdG~>JUhOX0UFG_`n)IBnUBBABDg7nApS|`V?3YAs)1z1yd@nOkY58 zK4q^&Q;F&3{~9sfm-goxE8=HF9<(Np{xU!%n*J7yYQ(RPvf{`3$3uhlkM(^54=s)7>6sGD&T>5V={l_e^K|COy7N)$jDSaVpyjI#&qo>R0<}%_e zgr|hpy5j-}^MK4U8~zeCL@ty(vC_osodC$!9>=X+yUE{q}_x^vZy?1;R)%QOld3Q_Y=3j{57S@iw=oR(+*U5PZyRS z&?&KL<=(-}JCss}fE4mhh)aKGS9zz37{8A$_s(~Cy^43CrIVqp3Qz@m*C^g)9n>`T z&Mx+Z+xrRr zKS|Sbfx~y6!-r*S^6Q9_+P}C3&vzqwTJhZzyUC6@A{d*!F{g7fe zmnwnPslgQ3;|}Z)5%C-YWQ+R;244ui9KH^X@H`U6TUYzZA%4gMgWpyeJP<@Huon`o zFa{f160IC&BE{1R0f~{vn!+Xsa(03>8~t9D}!@ zE>J_~paQR}Jz}>=<)LeHouL_8Xd1i@(8!?6FsKbfnmcqaJZo@XPm*&&)oe8hrJ>~% zF)wrwSh&v-dLo}a!0vXj7q!r56o4HAg9ti&ygS@QKvNHB;a(z8^gu;;n5=}$QY8vs z?haol;+n0tXdtQJYJmdmC90tc8as$n-w_6TOKxz_#$XQb2-DLSHgB4cflu|Q1$ z6B$P^w1*0bBvB-ClOr<49hnrD4nImXme6amTojpWi_EQk(1N_3AYVy`#CwvFJ&wo& zYGgei4-qL=52J>7O3D#=S&KXwm!-3adUlD;kXrx3?wDd{buUMCceUCs0M3ieGy$p$ z9M%1`>YR=MS{Ec%R6WX8J*s*(a;IOi%+-?})f2Vq^AjNEYEW#J6q^k#)$5L$mmD?E zYBhV3;eW^Gu;(Bi6xDoftNFT?8Ul@2^CL_X->tO4<-S@}dxfp`irQ8)PVL0BI7GQC zYOCZ^Pph5DYOCV1>;k=;D>-YUj@qE3mS@*um$>Y*5rv$~UW?tK_KV#`$mC+LLt`Af z83Pah?94r|?!G#;VGvMrF=b?{t04!iqSq~hsftx5AmMsA*c)hhOb?=v?f_^;r^>p= z>YhZjzZ0WnqO8h54b=UDVtrIxcNkfL-N8vNcimxlHS}}V9p=LN zvo)QJ&WUF0YXB@+{-}!{#`77cIHLm{(YzxtEIQa09bA7hqN72h7-}5{AkZZGf-}0x z8C~dz&fwAMaXI61fh>vhQ;uk`DoSdMqnxd(if%!`X7yM)a7EZv6n)JWeQj|kD?8#O z5)5GyIilaP=x0=2^K4c0H)Oe2oUH;DE?(?hT;*JRo?~$_Up!D0h7d7Xn8g#T7SryJ zqZMZHf+GsExXHG-Y4OWuVHSfA|8HRy?_`TNQeoJeD89b<@wjZeSkjk^A+h8*$C6CG z_-|1R5TO)hU(&<2q(}XUX39&*G$~ke43sZD^VD4D(xLiNRKm6{L9Zm|((&rjGGw@h zyl4{x5uv5mYfC4?^D&czExk>UFn#HL1e>??B|*ZLLN#iVFnuXTuWem|ge^U!Ej=ip ziG+b+py?wygVdj4t3RWDK8lDLq@F0TIil*zVC^`AAix#8eTM^ zvJugfi)fB>js?_V8*+mhZ!oCykRX z8H^8X_^{#gR_vmB3rV2AAQNO{GS9$9snOPp?FRA-=HD3Dcub?S7kiL|1iBCoJXT?2 z9}x;kATY2o7k?x^+8PUm3G{9x$-rdLkq+Zxifx>buYHJiaW_`Rh#sZhQ>!(jF=*YpgPGF6rE5-^$B=UiK@n z(|kGycgimNM_=|=T(+NQ-YMJE*}V*erqkz%J7q&n$5W`Y=>*-hC2xTx-A~`9(~#IT zB7J95KIxnQOV?fLO@jyy*Ik``UeideX)IhP*yN_^RZY{)qDp1<@}@>-Q;Vl*1p=dj z>_QO1ddAqM-Pq&P^p>;fBTv)*WT3i>LT#mfyds0ts+M;VDVhG#ne`h8F^=)}`hO_w?PqUq(P{mktH&|WNwy0h6060#lYA#FEuK8-U`SN7#ny*E$ zS-a+Y$coxEFQJk&Q%e;&o8#QHnI&o73tv%^=GUe2=7Wyre|Ync6mw?mZlaPcJ=K=( z$>dv3rXV!l=<=2#M@yO7GMvKPU$)Ldsw&5Y@On?C`dbk zK4h|5;gxnUjc7@N#A1LHWU{(}t+Cdaoqa|GjzZ1e&1BJmt(#jn+u7$G0#3|iiwCyu zZryEXUvvoQ2a4DrvTJ=@2AQT3qx_hJTI)edRVw%x$+RaArXfQ*n8qSRQM>Mkt%fLS z*DtfM$3zfo5Y(kss)>VXR?0{m1pwhQA6H>DXq;nu;TvlJJ zLOoXwjJabCYcfG`?~Vq&YwlO~YZRx2y2I`V+(KekuSi9OF&+aNo~-p*Hh zuqH?BlYDg^?l|e~j)9UM3mPsTOW$Nl1^?`9&OnCSVA-{jj7c1G6gv)fSfE}bp)JA0 zVUof?WT*FGIj!fZ=VBnZSw2$4rS#SEK%|KB{2s@2{|3;N+WsQ=L60eA!klS_BS+{l zo27hnQ=oA&W_?nmfLka>RqvFfX{OF{0dCuL0Tw^`4vd8Z`RZuVC)pV|In&C#_&=sb zp;ua?MmtHYjaIwaT6YNcc5Myp>$EknuU8Gk+`zuV{~OuYnb6I%hhX2#9>)J$y5hgB z>J&uZrcOch?OJ!(cWB*V-$^feu?MshVBaNW+gWQqpUQ9Lhw%m;`-Tc;*+w?c=n@}J{!w|)@qWBJ}YyzSmssl@-2 ztGtAy+ZoXmn|Cw3MbW+O9g1Gz-G+@p+l*6COt<$Tq%=!rd$7S_O@4SwcxUy6l-PF! zY70LE7wvME!#h)HbP{JvR3RiKM?v@#L`-Pn!kA`A=|-$pQWF=UJ;&sE3Oo}^w+O8m zkmo3Px;v_N%~p(js$IyU}QA_fyt2&B>?3a1}W_wk1Uau z$P&@So=8(%KK@eC#F6#3$odF%2f=JO0%j**c8VtUL@;$8??H{U2zZumudzp21e|iW z1KKQJoej(1?pO6{%u2_1x3jiTL9|BnVz@vhGBTo|0f|8rCHka}J7T$k z7A7*HAP$mx-hYFV*cLSqBY|zvs9AONdNd|0(U@@x4a+D*zY~7T0K!C{5eTD3Ux~}z zZ5U}<^kdi*wuePQGP{qlv-W(63Wpy25hP)J6Ici?c@G?|}J6euPwX4GTH-oARj~>0Lx@0M_vvv6mgBwOScA*N> zqL^%JI2SH-64VkzJ}gRSYq%_}p&O=}4c!20F0r5Bz>dZS+Q~acYFI>mZ%_pI`OJtZ z@eXrW!&2GV@RicA!t9;~aI8I=&~$18m5JFc-QTM#tq7&$Ch0$QGo!kYyFsku2NoY(sw2H*3LdpI&Ho9<|WoS%I06P`-bz2Y`>cN65GYy~fW)&Sn3f#prh98EE`X(fV& z&|8;yPM~Qw921>QPpM6D@=mbHqbr);l(nY!Db&t3=C9nn^2t>bsAP~X(cCLvgiDlc z<&*y@nXPi=egv|wsG!(fweo9R5(Xq(`8ASzuxRCvwv|7w>S}=#t|f@Hs943yzhvLa zzYz6BZIvCyZ!{6E%C@b_UNz7JT6NNYfL1B8ZDHDlssSO&(rVovktOamXJ zHe(B13Y#G#20+>Hcn3hrj<8HYS@#YiE4Xou#*k4M6 zsc6yVoR*+L*F&w2ywUPe>olsspP~XSU&4j_WVz*|R0W8)Zjf0R9%A>{*_M1fI#&}r zfpY#!#`NjfK{>yvwmt{@3mtO)MRvrx zsI7lf0DG9tx3jJJv7xbw*dvrPYJyIST?&`TIaZODvuI@0I5s&3ZWap;)K9US%xq(K z#pRy)$TsFvV=C<9(zA`NlhxQ(^0l*V`D?yh^KIKa$`6_^ZnMLoUMw)Ts_g_a)hw_nw#v5LHb@NY;i=*Y+O{*y=fc|xk=Y6qr|oRk2JGzl zsyYQ+m)dq7>?q8|S{oD)J$GSk$k}!)Yr8>2A)J-)JSW?pFHuoY!hhkDB75oO6O&Q~ z$y*o!qGV#mS@W%2wB}or$U&|Bf7e3L7pg=BK$JD#vTZbY*L)k7dzGoem_y|hwuN@K zBfo8P+m5#1s8EMRq1qmS3#F6gwjHTvBNjQMvhBIHm(p706{}U=MdEK#t9-4teGdBp ztvgb{6Y6%hGhd=)RGE`cs>&VGzTQS0UfT}2sBMQ?MT%^CDQ!F04ia73cEsi0g&0i_ ztQWSILgnD{czC=Yq2{S|q@gE9? zSN+n;_kZ;C+Hd5dwcjLr`v0y)s;2>>to?>PKs~+oo4DNP3{@CcQ#pn0W;q{sFRqs4 zlHB8dNj?#>VK$1J-6+W?T_ed3C%z?;-17u{ zZb|Nyhi{i8_wI=gSF!i$CeoI0ohD?(-E??TM#uCLIpMzyJ9~JL+NiG9f|7hAHH1xV zhaKDb9ngvu)1F723HtKzXitmP)%+yPIyQ*RF}nCy!LMX)wlX+O06IW*VgalV@}7ZWx-b z-4A1lN7G@fgK)(j8Kk{|Nw9(8LHzf(ip1aoWNKR z#$?XwV9e23BMk1reS$cLE4hEiWY>pb7ru*UO0Dn<`= z!Gtr_@q$Yy;jn?E628f{>&Q-utD9kPyTGgaVRid0<_;IVpuce+1s;Z>1HBU6J_FB6 z_e%GAfOG~3?eTa2?8aQ3uHAR4o!xFsai`RYE6QEGi`061x!TjIp5ah)xe6WUDX&8{ zzmT-ActMYz*$Jpa;rry7rC#-7f^@3WxH^R*CYiOf$E$O3MGnbGZe0{bRW-y|fz5|% z&8bdxjiN4QP|L}>x+*R!VL*P70?sEX z(SIFUXI;ynm^_QUN@`PWpst-k9@=G2t%Pe-YEeY!PA_BcAWDIDU5<7m`x&|9Y474< zv_iKAtT?64#k)df>({{DpR!A5BH6Kw9*f2O>l!N{Z##RufR(We=-wrM3~CCc)kHd* zPef6i2eYbf4MldNoX76UaPeau>^3(}9?LnU>L>_2FWA`=1#AKHVzEi)M9h#JP&h{1{z32FuNauJnotNP-(|H@F+EXA8l}KE0 z!4Al$I@#}T_C3;g*-iTwkgC*r6^2B%n;(<%#d*iptL*H_0-n!@@Y|47Z;=5XP7bOv zFN2v@P>}(zKuVJpeu=4T7MGm3`Au=TZvmbZv$LlP_&h$JgT|Bb;F;=~(TjH%QRD#_$omWU zhxjAnXXBp=lN#YGjPBGuXBd*BX|?YKw-lFii?PSt z&HAoX6l_k=x6zi>Hwrv+Ja>DRi_Mxy$#Wms#m~&zqse)m<(Y)69*n+4G3!HycK7m8S(zrfS&psK;WpJYcK39ElH}{W!Gvt;6%B+w)0WK6MP;dqP9s z;rY(W1*6~2-YW3?ZP;+dW(I96k!?mdaor{rkjjUezEj}s={?yCUPL4DAG*X`FY#mO z1218`dZma+Jf1uz*WoS8C$iuz_2NlQ?;@LvpXl(;OI8eu)z=EVK5x|9EGH9O=50no z^fTMUyFwm-405l<2eu*?IF`F#!T`dz0ACZngOc2jWI?PnzgOUG^KJ}&VdL-sz7dhO zWwH+nyl;CC*l#ftt@3_IiL(ir?4ttj@4lX$juUvu-jj2D#|l-Ql*v9W@b&Zc@5LP! zjtT_)zQDH^e_!F0?jFhJdj~f2hpgVC0|Juo1GXP+Tjl%A%tHd!eOllfn)#XbT2aH~_y_h=FprN#{I+a&k#?PMQeou|Ne(4XPQ zu~43c97$hm7S*5aH>YFKGsw~3lMcUqUEuHQF9>WTl#r|ZxvBU=14ILW8h)Zt>8Mfe zug_Kd%f%T0#osD!g>d^f#O1s$N zuoT|< z&I=Cdguz@Dw2>E^;NpE8!QM2Mzi{!B?d*RA!QsL4gP-B1c)2P#BAHfjBKf7Ig&R6t z+=<5QhZUB*P;C_ZivFbKKq)vABXCW@b z%+wd7{0R630p`d64+KAA6}1y#R;BnuZ4lhHq%u&99PFw*pqe_~DmFdn zx5+t7(RB)CE)iPVlZ{i@aBCi)hC}*{fss68lzYE^xAr@h_hu<?w*Y86`;a1BJboo+Lj3N%nK_ zuAGCrJEO(D-D(BZZ`8)@orSj>b z{f=0<4{_*s&dhT1kgV*a_K#~3`)Eo7U`YVFI=*yBwrf(xZ@e>G9 zp+5+kfMY6u7wT{7UwJkOBBH;Q0{Dsi(g8q_JexpG&jLfCc)(y&;N98*7awS6{}dWw zqs_YkqY4+w8##ZtqI&SQS>821+gjByk1#LWMyot`rPkB0x-xcF+bp=!%EQv-HuTvyC-kaw=$2$rZEfdY(2H1FulkFkzpyoyZ;20@m#>vO}v^v``X3E46jn4&c{d zDkcJ7Q}F2XX+SMadj!yb%I@Hqs-ZVlYF}#KBi;}Z&&7+%S*DZqV601A9_UCgM8FpX zx46zh4=L;{I`ih@KxlXenHv$yoOnBi1qj5XwXu@`&?;7pLF)zpAdmOxq_Kx7Z`T3` zJEX7!W?}EuzH;%QoM%xw67C^6S+2A5&V%_`d^B$qLzE9pwkfY5Kk*YKuHX|@+V)jvHCkPKnEd zUMbfGI7=yL6ThZfQ_Ee%A`RtOY# z@linS@!AJW(!NAlOnySrw4W(5(N5MipO+#@#vF0EV6wzdtiUyvK-&|Cu<`7Celv<$ z3P{qlkb{s(Y!kAQB5AKPM#vm7LO>*7Uu2CI>w35tW}PxO?)Z@l+FX3Jh_W#)`d-1v zxY<6607m9h_H`N~b4V~UZuXZM%DZ!DK`j0who5ZR4wayT7c0EKIS3gp16KL?xLnu? zdUrlqyzCF52*&mO{O@)Io>c63a z>9eV)kD~u^)Y;T?mZu2mq|c@vY|X@2F87RgcrJ2#Dp2`vfJoHYe$UjnJh)KxKoK@L z6L{hAd)9gCP?E%q>sfAwlzVnKJ&!TZgK*9>XI#(ol#(^$dcM#+A5dCi#`Szn(Zr04 zBW;=iOd4Eh=RJoQryHfll_(&HiGgDoR!bXW$y59~5EJ8kxzM;YK}-fgxG(Taav>B- zg;-}Od`glB?~~*qT>)vwClA5Dd`TWO4CVmx5N=8r1f`FJma)m^R0@eWHup|pQcj>4;xa~DVs26l zciaS_=`^Rv{k(g>dXAtN?iZ2`;QoO8h+?>b>K!Nsu@nEDPH{|6Jws7@TdXz#OGa6R zI-Evo-y*dfOu$@$&}v087xjAb6F(}FT%q0!{2XWJxkc(-s!uyfAhb#wHOvv9M#(Q7 zpb-G)+WDzPS|4o)&CrC<8Z9hX!cQrA5<+X|!aV8(qunJJYS2iF38r6>R*m;do-lDj zt4XD_fjq^p15Ri=0ZnJBz#E}^AypO?;kyyv5_}&^akKD%R%W zPcVGiB4JVpFw`aHG|gi8G?U@Gg66b=#adKr^+1n>IZaD3d|Dg%38{8F%ru5i`#%`I zO6`CKsoauu>MFH=83rmRbQ~ksoqaAFBtrlN6;7Q?U}tkSIxY|W$UK+8E>_t%I9qA) zLu&QOL3SmDI@wj+v?b3aoQ<`0HiLl==jT(CLK4+gHlKirYvasAfLL=VXEh32#`eNf zXU%bW*g#Sk1=vFf-{)jcG1HbzxRSlez?+ylRHXX3gT0@Rd+Z0Oy)e({>>wrKV1MTG z2@v5}yqx#Qb@G!v95ip3xC3v1#NMRG91EO$l!F(Uz`c>bhmWN=62syNt{a_{!>72H zQn~ouqFf}OwmA4Q6QYlRXfq+6LeO4?KWNTyrhv{5WVlqPgMZ>7(RCOjwJv1VvHWKU zFQo-~?;JhHy^+$_2bk%P)h~fOdb1AwZaU}T)KyiVM@=V0Wk%BI(0$nJUamLckT=&? z#pU7CEnXz3gXbPT-KoE$=+7O67ts$o^uM|OV;YF!G4EA!L8LE}&mQl&5Q^}LKq`xa z;2sD8!>41F%kNo$toJxQdOp99O74LKKm2PW~^5h#PEj0Dpnkdn@GJB`y)I9sY1gHn8n zQD(9+#yR31DC0)3F_ms(Qd}M}*eLfUK@Tn@f7LsaA1+1+|I` z|I=v*|9Hhe%G9T*p-jo9`L6)zK8ODX%|C@~{8IfchkqgS-wgf>3_K|6#{G}R<&t60z?@g)f6?ZD(GRjt=-_|p2$;74^R@*8 z)}~~Jq;@a&A9VWvaQJ^rYjpo%lO|K6cd87W5&!~a0iPzyXI2JA1V*9H9}*-<36z=b z5~x%H<1FU%X6>LOaDx^QRaEQr`BG)z-hdlGyDcEi0t#yZBiRmtHCkXLxdcdgVE3s? zV2|ilJ@6z78<(V9XW$J-U|(8E1N+TMgG!34Y6HI`;hgu_U|S{__N(LpSg;Cd5Hh;a|bE!d~Upa_12^{UG~!TpH)i;G{O2fv_H zM9g2+_dqf|K``zmzvv-Z1kfEcAq7)cqa4CSD&t%tYZT(QFEj=foa+c($U^7G4)!60)!WnUkU(QlETg5O-NV3yZEGvNDj7^pB|S>7ub1Wab#rVvTEXE!Tm%^lIcXI zkSAeN$#~%)zQxUz@CA^?dRazYc6!wI(~Neda7E$wTKz@(A>7sT1FY_`t50 z-HmT2Anh5vxVU;nb!+WOHjefJcSOvboXLk3SHD#KVUjzlev_)ot^_MnT3r1Z{=kMw zw(9SMNo4>lQ!H4S>YvPIw(37j5Nrm>^WO zvBk9uYooPoX4Ps_m|VNMwvC|i6D6&vZIxZ>Np^ltaqWiM$Ld_7YPA~?XpWWI=gCj} z1OTd5`?{Q0*AMErDUP~qr7kN)sZgOY4tx{v5m$-oo>yFVR^8y}bvAx&dUeZ->#nVv zldNvtjiT&RP~D4)>+Zx~Ex>JcnlLGMRQEhl-8#dpZe7R(q3WJrj0+++)nTs+v@un6 z^~uuLJzV!VLE|S%Us3lcy5%}Mzp%LO>AH8LQ$%&^o=E|GPJZGi08rh!gK}Q6VlW>eI_Fc7O*pJ3cUq@YwX_$5Q#f2vZT#>S_K zCU!rBY%=*}L)D?`xydG0OQ}L^Y9_yYsCtEZXD>dzgD5ebMwy(W-oS;7lF6?asy?E= zm=YY+r%k~jlTR9|zN>!Ri{F3>h}9$Pwcyi+s$ZyIXw(2U^^h>BeCRiE>7u0mW+}-2 zG0P!!w)3loYMr&7biFbO6J3(Mp!Fd?)Gb3h9cH>Pf%Z9yxO+^gQ=6F2Z$yFcZHvp}&N77wZLg|55SPdPm=Goc+6xrw)b=sc zmgM=*ruPp%)V@gx6WZ^p_CEq9VS;IY5TFnyG8HVdkubs8N$^}im$Cr1ZEu@>ddZ=fI=V4!8RQ)E@5(3FSa?n`tyaO|BEO>r~yQ8ugE4gKz z%8gFBPNR>*z@xTUSvdEf#NI&csiVtq3XC&yjC`?loM$XXX>M~Ge${Y`s0YxBE(qeS zv$4oxtT8}k_#Cqjj7L;sJ4G_rIUp+=Pa&g^6yrJVUVv%F>v4Jfbz+;Ki_gVo5|P=L@D(^CEYE5`cGcj(3>_@GZ#h9g6oUv71Blz9b^K z_&i8)-ruqN#x8^;r>~dlJ3hT+;7}$H^{w-5_7|f3CRxBvmObPYKiYCs?t2=-&I^{X z^MT^C7N6NI*e;8bD88S?b(9W&mg4)@BKrsv_fp#Vl%aUNtlWVLrhoF6<2xJ&=86u?X5mk#g-0PeE$>xKqw0cYSM5DV~;ffR!h zIGsF+j|>o_auhxi8%jpXg@JM^0UBfK(7@$^8G#7mf?W$-k<2?Vhdjlv1G^TOFFOKm zlLSff*gcYb?kkdfUT=I0@U6%9z9dgL9UqipxF3~I9~y`T8iTDiez%x~80IRlY&Q-K zJQLWToP`1}QHj`eOc*nU20p^yKLED{4hoaXfeB-}nCJtC%!xjLGc*K36aCFYgBiiz z!GY#PAG9Uw5j;IOkf8CS*m6biOtj&AJHK^kaB%S4Am&fnG($^$CSMc0nEb>~0AQjI zUImZ^DD{NzB)PmVK8QBvj6M{Oo6!z71o~j7I)jS9kA9fRXG+6NWnpWng#GA}ahD`r z3S$Xc9O^=bncclZqW#D2*UhQ?Pgv3I>PhB=ucG)uYdGH08s36%6OS;(&l;wxs!{WZ zje{ddDW7i}rtVSqB^y_zrG{d56B>8^F!fdZeTUN7)DMM8B}L=T5{;{VX3fT5n;{hVwn%}#z|Htqp4jRI+eeg9QHpINDm*TA^*`;Z3hY1T-kLUM?4 zA>IaZJGFX;R-E>|q-K%Ah`(bmAX{>;*V_B1SQIoivnogjaq6AeUag+^qvI++qr{euzE06Ts8Vcymi7Dp7GJ6z6X`#xtQbcShb~1>> z_k-HI_@X@CNp`Tm6=vP2i}hNG-;NX8$0q4Iba{#B?mV!lefZGWJrv2wD-!`~9`_+& zZfw38fc=?f23j6}8Uedv3(RC+OiLD8L^Bf0!~Rp;&ZzL;P4&mU>hU5S{lr8Ro~PrX zM7@AL0y6B-$18e5Q=;SAB}A^&uhW50Txiu1124f;i6wED>PakzW0H&}67=NhKid?2 zrDi3rm@(8FF3qC7CAKAdQyO3zE4x8Uiu@;jt>-m&uY zr}8u8M1HG@k5ZJP^A#ZS#QBcr%egz{P`zhpENs?UD4%^Im~-^k(1n z@t#XJM^Ht*(-Rei{SINz^R@yjLyDJ+GB~}9`*^F>N!A{uFwNOub-e2nNk{U$uOR6s z)XQj6=hdQ+-nX&S_JHDj-yBQoe(h)6)8h0(Lv7+)O`Z=7m+v&im(9d<$^2AHR)k_z z`o{UnVMm*@5r{Nd@tto)GDM^ymA<=uu(Bm)ulOQ{59;B{xwyBxwA|O`^gW#ITMv)A zE`m>>EvM8TzLyf&*SdI})kywiBh}{lFNM0TNYp#qKgLXe>Vqr%{kNoA%73?M=TWqT zzg6)sVW&~$RS)h_gQdv7!RFuK$J``zdJqUY=m8&)o&E=`l1PSsZ(P1;G%~@v2FT`> zv}``IvRO>o{E^R>5W&dr6TrK;62A*~HaaaocC8~YRtXHVC>LHpHN!7UgkR+d+^qy= zrYM^k9=5{yQYB!$pc>ex1RhVN9yiL@p;f=(sa-HJnO48oOQL8{=v(N@9h zrOM!pAP|N(fGitwPH>J&sW2n+>xL~s_*c^PrY`9@#F(`07kiikkV59`BXzOfTi|0wRi7&o=Sm-od0|^nD-%n+*g$9#D!ZFLx zNSM5d5KanBfZf_WEQcP>YA=K41cDCpE#=4F#Jmx)UBh|urrk&TEpWbgCgKkQd+}P9&>BW`S&IZI#Ln*;7HNvCt^q^D!5E^H;#E#x;#yaN)-9 z>U?yc8u>?rS5_Zi4c3Y`gXLKu=T!IPDuq@nBDB<7eHJXwJF7>!tBc4c`hHk8y1lac zvTCU2c#G&yrTSWne6~vE)pzDPt2JIdKQ3Q(MLLbIUTooh^%}fAyNVLbt2x!~tlpzl zV-Q^W509ZrQtW;gU(?T7{fVRcJy!iDQaRcEBNykk9M#{j>d(oCxAFTx6~i~*nr?y&sx^I(@>>!vat0YBB3c6pnP_-k%_XwC=6tgh_hcwF6D@#g zCID{-gq`0#tj1fjvIg2B5(;X3NZ&-!npW}@zYan{%|^MfW{0VbmE?-^CHdm7B>9qC z@HOCjUXm}}D9M+X;F}L<2n7p<)jU@7R9&%+4h&HRFrj2*^81F>yj}BNFWzP{>jN_R z!eKRE)_mK`{iEdr7FHcr^Fz%KwLc;yTg|V+#1N<8LH+e>@aKAX?moV9OgwJ#&+7GgF%bXy7xM>x`#73}J zR7~3Y@+HhP@k7mk`@iA`7An<2)^4`VQiXcG9JO=raN{gvwDGM(a-cCVnYvLye&Q$E zwZfoHm0RrGH{AHaYxABV=(q7>62RMq{L%ot-2kxF&i%u^1HI#Y=cCy`zrFb>h>OXS z=(qPum`A1G-dntw6*|yw?^4Bk*HP&=Zfb&L*nxg~AEwevL~2sfn({0!4pEZXg9td%54oj}veP)QQ2F@f9%18e7E+vnq!ihMu( z&`S6LeIp~>Ke_+#yKQ_M+{wMrH6v6UFH6bK#ngywHW0XJgnBmqrU2ZgUMNgT3J4rA z<>yN+`B@xcW3x$qt{b6FQ*YN#69}wMPd1KvC;1Tqt18TN1YQpJe-XHIrMgpn6xHj2 zG@z?4SD$gH@2Khvarvsp66ZhEuXEJzg__L8#fIq7S_PUQasJ~X7Qievs`-|q2dgPSgr?J zX~&EPTE4Fu*qUf=CQ}2)O*0emUFfwmD(=a2fEK1 zwGT?Ae%>9$erng=C?0&_mYr-jtP{M@Q)W@zTNPf=1{Ak{zf|AV2XV1i=>Q%Q57! zdt~tl{cHViPp+U5`Zq}ck4%1P0G`eOc+}39jPRW98Eu>c+yssAxKa@1o>@oG2s)W@+fiu*PJUv_?LZ?un7WBZ;7I8Eo~MvYf<|~SSzU7wo$2}9>G_^{ zzKY9}N0>Ci^CyCE>$NyGVVtNL#~`eapbW zx^nOJiuXo!4-n4by~FLDNuh)iw7B98dBIxpxS5!@UcE;|+vN7PC8L#lpKy9#*1S*0 z4`CbYSvh&6f{tNum{Sd8)vimPgBBuWq@)W-gl-)m9F7)4%pzK!#B>9>P z@GZo*Ns=emNb(dFPxhXNPX}~oeDVl5z#v|AI!quZQFyrN2MWJj8YxNLWJ$b{n=L3j zNItz)b1SOc2L+3P`h&{5KQQ&GP!dUa`&Lp%!R!YUZB1%d6=ESK1oc5MZ12H*OK>#m z-{$t#+X z=Jg@CM+18XI!2tuFN;}JLS9xFDqkzBj>{@#GI63C(+n*X?;x{kisWfA7T+#-|5sJ zcj&uKU|PgA^k*oJwTP>~pQC>&7I8f~L_uT@6}7eaNZHXMuHiY$guo&$JwIG(_LjNr z(=$^n;(Bf}Jl9jK#3HU|K9;~r3p^`wJgs68*W=k@ra#v6wp1FRSzziI?)jCPq1^K? zR{9(c<9J+?N==l|+A{-l=hQKYg~j|FqsUaN8zf3Ss~XTEP3?s;D@M$kbf3cvY`kwe za5fTLHhPvnkB*%vJH57i{sKB$;_c<$;kk;p)LfqPUZi->N$I}O1JH_^E2@gO>MS%u zp0^e`?sIrOiuc~Mn8?lBq`rt44)0dQyCyA&m=y1;q9l2~zCCey`dspO->9Jq z!gk0^mcJs6_dEQR{v4|Jt3s*P$3Mb|Q2G4kJEVF3+o4o*`foJ+=*8(TCe>$%VV<6G zQIh_!mE>zuc_2Gi3G_CbFEBs}^tFm6RyV;_1;!?71^Z>ft^{rn6$-3DgzB!@a8^s-st(3>VGrj^QY z?=bo-p$!iYR>HYQXv4!ZN!zD>C`hFvtSaHVtO{UbXL&f9tArawgJp+T#pN4Ucfr=i z%u*%1E!9%ty=KPY=S1Ixe@08aogMzxjBYhi_+QaP*^w?*D&>*hxz0$Q5dq(F<03pc ziF>so`BoqsOErQzk4`n_MV>*5?_@`y&7cCf_`9IL2>u{ZhVsZkN8~pn@}o#9%0_`z ztj2r2)wxFX$-=LWl^{iD^#r4OtngSY+WhR%qsyy*(X0Q6%hUD}CtqXkBo(+?lV{ee zM!do3;t<#nVO}Cr(Ab(KHJJ1HduHR+JgL;QnF~DZ`oscHdCfo0+7q&C<+yy)hgqp5 zg)XH^ZNEfPun#ru{C(t6d%NZMfE+t4$A{#2&2oGMN8PEykym#$=*q{Ay33Wia$^I-2WMU27{ zL#bR?e*u*MYW=k%>nGLEuE)v;@xApV&08tmL7w8*f$zlwzK(h(rgb}SA6Z{tzr6lk zASq2+vaNnCIm8bsiQARxx8lySXLITwG`5pJ|AzjjZ8h?BpG)#Bb@-md_lqRoIvO7s z=vyB`3~YkkFtYx``p+BZ9kB^^)5wNy4N8(ZZJ-Tp<|f!3BOChRuMFU}hJ0aCX5cM1 z2;Q<`h`FPpVT1`nJ1Vw}Y#7&Ybpu!)-VGP-o|9~VhMOB^6EuDl8~5E-q4BW^cH78? zI~qKVw~Ov=n3n>mAwTgG0MJl2&~dPDQPrw3_-@CC@eCr%caChlyK!OT2Y9m(p;K)t zO^Hyu>>Am)4u4?V@x;nQ!bD#-J^{Ddk5U!2*(qw%_@YqSx*M_UsERa$k~{;8-Qp*Y zgrgUlxD3tt9`bzv?voIN4IJ>NUq)yCpj3i}R^3p{tH=N=QU)dqHI80_K&qk?{3n<{ z!vAFm6P;lmBv8^Q?Jj{NP`w>Dt;36iE8ts~O#VoT_MjHe;@=^0;EkR^g+>Sb3aMaE ziS~*1O&0(Dh_KxVim7G z@t+Z73v`85l5pjAfS41lvSXbBqv7eUN%!0>WdyE(FDH#Du5b>_Bvb7kxEsmvLvV~q z-a3eO*)5Om+(qVlnG~02uEVn6BksUzSgT--=L8;)aXHz9xW)%dCNrxfgzZu3bi&L< zus)s>?2{I4x2y&+&&^y!(VplBmf(IZcq=>>n_PG6Xf5a^rx1xJX374;rt-a;oj+A# z++^HlcrX}#K^>sExZm)=LO)TR3PZ)!T>RM*@1x$Qed`ieBza%0r5Gy6^Ec{Q|B;h`}!p_~WRqKp6K4qrvVF8()I#PDoqc)l8jcr^R+M1Pd}!Wy}ia6rg>B;kZ( zj&PHei8>NonLE6OQc=U3D5}&Nt_VLQtKrAVW#{`!>LPW~#Xvm%kEmMRGIBs;EZ4Q9 zs%Ed-MRog^>Y2pCy653{Yez34K>RTLfWdWNk?9WBQTys99#lo`(a~lKV(Hl#y)a+5@duBQvfR<@*T;$ShwOQGKKSBmvE*|QQlg*o3PU&t-?tb9OtAXcHV@_8hbfdt<-6RcW^ zHAQrObJeQjgk=-jPVb(fACtYRzgZnUBYV}kuwK$tB6N7Er0vSKDeV{~`tfLM+156L z98y=@)O-g_3mvlB3^gj!pwK!QX_NiBnq^8eeI3Z`)c>Kcaf(xT-PonPd9E+BbjDxAlZLwSH|Vr7pZGE z!U$?>ABKU;tuR1u-_F;feQ$q8UwaV7$Hna!269422nXavfC%e<$2?~rs@PplbW;}CPEPkwXXrx zkS=J->~@gmJ0@fa6ndqk{pI#IHf}*1gYr?Pw)PLnDIJ@Y)lNK>g+w%qS~w)F!=z>6 zjMq1ZEp@Ke0>qr%#4W!~qwslWafJM&N zy=Hd#IwGhEI_Nr+xUt@r#Enkn>qj`(k9Vvu%_nw`KVnXX>p>#sJ!wsb>#xsQ zf3rCmuCKPa^b_3ceH3g?hU@p|I@f=uuKy5TuOx;yq`>vRZ-CsRO(VWhc5blc>v(KP zRyQ~(p2XiQ-vG8|LqYZiS6sgHtz(mjL-c3ExSS2;W{w+HcXH`H)D80p%%z{`*wB!@ z0b3df#9hmO7ljyIx#8gr;IFmIL~hE4C;2bOVrts(5|vZk@CE^E8}`F^pKbUU#sR(o zx`%l`=^K7VTA7}WSulDV8&869YWBt)82Mc!n=WN<91eR)78*2r@isMNWs#jz=rmX>={TU@^T6f9!d z`D-PcFWh|P<~Fp&ha#oTQ^-LnZN3erc-PS!zJka4RIb>3zwF$+DrfWk#{X=RZ9u+r z^Ah*w8l-r0V%VB#Nyf)^{(8xlv0ECqfc)tv$yHm%pb(fY_|wkcDA_gwf1jcly+wlC#*u@nx$S(Iga{;O;ZcT+@@-e;I=9{A z*miBcR>|Wgf^P%!c2A{+;M-WvHlK-Z+qPu5^gixw?IL(|#kM`NW7`|fZ7(>sJt@FR zt?u5oPXxDy_+kF9oxfSK{o?JDwts}ubQh)Bek(bsG~4IGH0Kl1-oJtzS8QJ>JGVDE zwg(;CxkywU9h<11jA|EcZ?kQ0+fJjJfY-t_aXP`eZ{H5k#~j-qQnzo9%kz8lfB7FY z=-k_%K#`#7pDF9kqV2EPw!gA{KcMM16-)s#eM=q?^CI0@7vj4U-*1vUdw?Y0W|!nS zmr3&N(J+epDyc^`1}2E2e+yXj>`-BCpgY3?cC%f%JwSS6*0ez z;s8s<<@5{sr_D53l6Gf|?uK$}_aY4iIZE<^Rb=2NkAhiZ5%tm9GL;iezz4via3 zHyWN~arZCidYUK@D}#Sp${6zn-?HgQk}`*^ZO`Oil(KKxp)5TIz$C3ezWlP3pU*GN z()+?I$wQJve4v#7t%I!962UKq$5*BLYJF|iEQ0(L?ypNduY2Ck(sR>hxJ>>{DQ+Yh zlx0ivL~9=^H6|Jpy@ezses}Z9-^8`5#za#Dw%PgrO1-nacl*w@#S~QG>q7g@oj%3k>*??vpO%y$89q!YNU1fX_XEl}eIp#c!THq1{7W-@q!ljd z$JzP!rT)|XC4n<=c`^wtkc`I#&VYq}Xk!cevF*Trq5pCWkL#w`Vqp`b760Y28mrM9 z{@Wb>o2_j0yjU%5^nS?U-{$bIODmwYsr(6>|A_!`$5@LMmrPjQ?0*h^Nisyl1gdlY zySYyP_YVK(n*W2iyl@p!!o+YxCWqaA$O#Ka(OjnnY_LY9Sah@$TU-(72_1++fp&hd zG;lbWNgJ}o?jqS1JTAFAnN++Bk%oqe`0sYx<}XXOR9gsxYNsyGf3=m>;rBcDJ?^1^q&$O;Gp$sA+9+ zd6A82;P)3D&*^mVqCPs^A-M>&zf_VJEdT}k9MyOVd7-!NN9o~5c2KmRq%v6XgTC|E zGWImvSKDsW!O2<_?6^$+dl^5S_fMlrf0Xfq{KqW*Z-PwyS*Fj{Z_m0l;r^=(H@iNZ zrP~u8f0tpiQI{;ea~g@tI-J!8hi`HR_6P}_eGYT zk?`nLR=eQ;k@n{CO%(tC_-@h$Djq0xIgFIkif9x8@hUA8N?W9y0?K`3ITchugzP4> zNt3i`(u)?_rfmXM3P`y@G+v-0AfO_6fG3C-o~U^Ip0C+Wn)>$h{pXiHwmb8h*Sub@ zxnA>{bNw6QSu(N!I5WhKephf7@+X?UyW<6=%?3lUWvknFC zvUo;|E>giaJWvRg^2nEyyrLG_doLp2CVAWHku8Yq&BRjRNXh$vC1UgNZ5f6v?{ow_ zCVA&c-q}11%ldCoV~?B^_9{tUr=Eb@g)Hw0v-d;EdooIge~5w~^Ywn0oWCi z)*s;dTZK#R+EQeKgIu=)_D>?Y1}EUo5@zJ?1+A#R`?IUr^N`&$5>fw(D6yU$J&U47 zjNP-6!eWdV#KN%Lvxj-m?B%OtVjT&siA+Yr{9&FCD4fS^YGD}qiiw`T5OQ}*2*3@wUbKoopmlZWgX z-#2*kSr7XDT$bOo@^`VYyI8AizeVipN1{X+ zLXy8P&$6y&e_z>;X*{+v61|t7Z!N->G!7Ogq-Og^BLcoYfIc75ZQo$0Q8zpf;aQ94 zBSB;znD-*a*Jr>yUq5wj)L_V4dwd&#ebA^GqHR1$R$_vkj-&S>R&RutEKU>?RY|0CG#;<&po?BA0cHptSE_ zHmPh{w7WxBVD4WwyKH`$P1L%AvSnp7ghAnyLAOV2WsMbmqlL969ig5|5X<^!*7L+)E zV>=h6I|2UHxhPaEsdG_=Qz%LZor^*hEYi6s%P0Uzpebm5MoIAytog*VQcEzsb5Wil z{7B~l6J-ZXlvh}5nwU{u3yY4PGF?gH=%*;h@JhESC-KU$E1%-^FjKz9Yo4mWjC5EX zwkz<$S~$`fzE%Ti6y1VE98}S zP-X)FL*Y2#0W~2`8HNP+!UCo!%0&oMu7KV0n>fWtap^yOQd6cuqkI{ds*pq5JJEVM z#!&QuF4`UM{G+3MBA6lai1<_$vcrku6=lr!hss4NQ@TJbggHUlx_(u6rM;xIu_@Pv z#XO7BBD9uhgIJz&J7Ru&6YNPz!Dl${YZi`ON7zf>2RYJB@nOzmpiLjXY)fsc1)=>^<0O1~L4FK*AX?uk$+CsI+qTIz zOrg-yq3om1-FDP$JCkU8mtZtFk$w2mJ5-15JeckgWNrc2TPE2%%4=z-vb`%|+Uyn{ zoSJPPA}aPA!2S@i!N6q^L}xu^E8ZKqA1*4;PC^<=0+Kl61)+-|xG*o9iPv{A1!**} z&S_S=)#YqyWa)@F)##rB6F!c0OS3jux5ixsGHC9d#h!7jdz$qX>)|*yh{Mn;0d`ZG z^^En8I5wEW{8$UN{sJ0l_Lhctc2}D9AL~DI9Aq=f2L2{FIX!$UN3{Oq#|#T<9lJYC zeh7cB3Ri=UQJxJKghAz@K`R@AVuW&z#1mw%|4GVWmYF11v2Gs?k)sVyS)$Ivd-O}0Z%MM!``XQSKifJO~z zdZ)3`YyvwEX{g7AZ90{mhXc~k6%@3`x@`jeX00QI$AR0(A)Uhf1vh!l(wkWj$-uM0jF_Q87;c zzl2fmi3p<(@1SO}ZW76&VvymzPgWnsD^sDp*4~E%|H5qbF|mWXoMf@2sSdSBJq|@Q z4AgP8(^`16AFVZJsX?>4xr18Ix>yNMWVb_Q(I!6_)widqC)LlKCVV z>_y+?y(ox<+YqCbf!&klY~{SxJH*IfX;HTW1&?m$zBK3fygTCAh{!~TKMhrQka(wa zHmPlL$LBg9<6TU2BU-^hd3lT$@u|~ z)$dBc&?}>}>X(!!XfW&BLT+9g4jht{*G&h$ig|+j)AH`k8`2KMpoMYQYaB~S%Nw1S z+l~z(NMD)>Nl(jLgg=-g_&D5C{EdRllhF@H3KA)}hkr_orI79GdpAMMTjalwBs7>< zYFb`Z-mU^PG;q$%s|I0h`(oZ+0#dceqpp#SgNP%Ara2<9|5aIe$IPxPJLa8r{b-;J zO*7=?{Q$FzRuz!Or5*DA!fX}4Hm9Sja}$#5&KM-gm1cEe{?*^ry5Bz5yuZl^ot$CxUMz9G&4#sw$AY>v8vbG5MCR9zS%5hzGCjdN& z;)`ZCuBp9Vc0=*{>)2#ORorH{_Y2N{_)!kCySL;{R@^Xp{QKFIPz`lALI|V32Xow+ zZmQ|qc#SZ-M_8bWI)Q}bo@I4Ui3-gIMZBT0%`NPDp2*ZVOpRss#J?>1mwiiuSon0XH(|uHv1z#E_lU2R0Di{8 z({S*tDm)9VXkX4H02k!bT)`bx>xD#^EjBPCmRX8HCYT3GV!x3EW8 zR&2Cmi1t0A(bjm17La@wI1-|PtUpdn7EEkdn&0g2>Mw=PS^{}Qqd%EERL}gk(|@nz?{BegW7$Mw7%t3MV8pEPq_DW==3GDNIg~yHDVPJxBdCexr1{tSLw*?1 zY@WvB8S?NSFO+Qm7BR`chj)aM|9LJYWE-C5f7O4)e;)DXYw?bgCpO;ui1#VOM^7<9 z_65%r#2b}Xlv0#ggy9=oz~dE-FM2W>59!D*njm(SiYD-MbSqk7$Sp$8Pr1YvCi80F z*ThDr6}?q-vKTs)&K)CXip~|2)kHs@8`(t{h{^?xO0fY{Ff8R%7DuU!NGontEESK1 z(mRBRqOrIGJUoAkQKNV}4o=||)5PrJTd^JUj(*njS~pcZ++3VxF22WF3}smEw7!U; z`pt;Mf4bvhst}xN4I>BowH1QXtS?buaJmqj3?^ld2;!PncoyN=fai=LmUqW94-aJ} z9|xrgVnu6=>K}#WbRMeU2KcW+AS^4u>4%a2cwqn_(B3pxgV7iUC9nWCIijSt~S=Cd3h~$PXp{5bebm1+AH2l4rsIxu4u$o&(~%;Tmy?5YS1@;L3b6&XXkicN%CQHbXRxeRRb0C~RrnBp@sbjlD$_7OauO&=hy zm)9#iZSsEprX3HjAyn>4MTbLIaAQ0%DLTX^wK18W9gu&LD`-=({Cikj+ger(c$qPQ z$fgcZu2U?E7gV0WmBg^@^k%NyML&lNPzFTx3;H zkZYGxl(ob0)RK#y0q`^;eGlR}3-=ZPF_i=u{ZKkHgn|F>(wRB%ze;B=MgMo{%=}mB z%pUmvr*zg01q*SV1rKTlmChprdFiY+GH9Hb(pfN24#)w85^R*W@;8+Zmg1tNa~$sf zDV;~O(mAJ>&bMK4-DX+-6|cQiI`al9CZ&r4Q;nBSi>A`Kg@C+t?$znWl+FVvozZLo zFP&L>=`0M3mDf>}b>9kNWg5BY83@k^l*Ug8SOxbm08u)C(GR7wP{6bomga?EiXgOs zrCBEkXug!RA+YK8W1iJbB_ISE&m+fVI z>RGTaAks$LVH;Awe?(o(w!MvW;cr_=Dz?PLo=CUfXusJ$6cI-82>9YW)fM__5$yMg zlKnmlrHnmhVo#>qSK1x+MiKe|IGD2V(9JCTr$_LL9qnHIhL2JU|G0-8eI?zjY+}pO zS!Z@Dn*oKsoX2PPqTR&CXDPT4Gew~*!6Y_55^s4rTgNuAQ=%XjY4M(8r<%vxhIrfb zc({~MBa#<$3Z0tA`wj7a)8u9U=n19kDopI@boDv)1xE_T{VPz4 z6kUBAUN|sne;@CrLZhD9kVD_30rV-J6_O*qgZfu+FNWItvK_5)Lq=O=8Isk}(S@^< z9X-Ng^+~G(rCa?nmW|k|bbK&vg!39OT&Xj3%z>9PbS(NGhPZ;m?r_F1T-U)-tTD`S zY;^3y62~YmN=L_j{c?`C_;CSBD zaAzgRJVG)Uom0s}sdtjrVzl2Hb_w5ajlum-KrjORL)lwcVX+v=)GpmWo>8__- z4$ll^kqiv1EPCPLGP%m|wqf(FE|W3K^$a%b?6JBwhsByP`2H@&uejbi6r|aC*E>nB z)BGBqZtfH;2H33bUWA50jC&{!V2|LZd#&zq97r+T^OM|7L&`f9KbsjO?6B{*~n6KjaVg z6=9f_m5;7WyVpeQm_JTy0{N3;nm~3wLx@MqiTt9lSW6;^Rb%ilJUE+KrH z)R>u$UioLKEEAHMBN&5DI()WjG&t2Q!1E=j@Lnn%9%NW0GOiYLXLUaz0KF7o z^g}O|FAPFzsFy-nm z2Iime%juJiq*{nHt{F4h7NAEK6*7M1A^#f$Bd@)7daLh5yBh{#0j%gR`aFR&UI$nyEfm~{OhWj6kn z;XYb)-cRuLVaSGj25YjVmDw8V6(&|T$XbtOwbKUN*a8&MXx*;$m!fE;en`8=g|AIn z4~T882P{-%R_k#v{)72UtbCC5W9ygJ%joZP0^eIN6F2-IH-;(JA4SRfBacTB)(ujg z#+PAHsTB)wu&R?!9?DRq1aB)QK%=_atn8AMMl5<-SSc&E?F&6edls$AzOc9+J3qIX zSmhvmmi~whnQwbnBX^2CoZKh>L(XQDl)okATMH{=B~fy=79h8eldBqJyWZBphB}SR zBk63N$%7M&qU|=k|GVsM11RV}%ifk9DL}g$Dvt`@Hchr+4u3=UXu)gVT-&TB+}MJ* zJ!WC$RPZpcoQQY@J{>08)({C6FtNZO+ZVPAxZ^`0EKTZv$V*b&X^iyWQrnaMPpR!U zH%Y>!HrwxxRzCY+a1P7%VR+#~7&W-=%+8X;=y@QtT6;;TH*X+gabUOt&G|Q~#A6MT zeItENkQFn(az*ej$^MFD-)3PYtcbj1S=0<-*Ri&a2}lg;I!_GiN?z(%*zNyUV%Wg{ zBQ3nsk4wYVIFqdmU1WWJB-hzEHcOy@6*60bfDO@rB}~R%To#a6xx}1W)!Q4|F8>pU zLjY`p5%wKTHlfBc(z}rwJ5}3#iUPjWTGS%E|0gZ# z23f74+|kma)`Rc`EiLK+qk2GvhyRck^({#9p`^a0m1t~Q{xYh6Iqm@>(&C86TT6?h z4V*D)akR%WPY=n_UZcR%;^-F^pB)`Zi;2|^a*lV-%6kS8G4MeXbdgi~$Q)IZn6Jhg4o@0`_v!o{YXIaA(kBrAF4r*1##nNg4i%0&rVRM`D}3zJTL}>{qa6W0PZK=uy;1Fiot>qk0DMF zIdhX{_uMZCE_8Me3xazbACJ3fv|$j~T7j(-;tlM%!OA1bBJ~<0!*GODU@rv6vBtql ziLx$1evJC$ov=u@4OaFlFD0-l0(?lbPdf%H2b2TqRiI~7j_`L2%)s%3V~keea6nn1 zBgTD|1vY9$ET92xT{&>EErWnH8c-nJWOdtS5v*26oW~KD*c1ZR!Gi@pTN%COYi*?1 zSWpLI3myl)PQZ{3q^V-QgN!|=O#?J0*;}y#Ceq^7R{MQnag&z?WczG5f~E~w&_zAWGn%WOPDp-mc%UV>v&`|NU+I(5($Rd!AX!-ngCQkU;A{+8ta^bnI!ufL zXL(c*0rKEu?&Tb~m_1Lx<^@hu4{?zKXJwy} zbQslFF|{R@MRr?-u(-tv*FM@fy#*&H*$Z}Zoj^hEk!gRz7VHLOdvTOh-K41N;D1){ zW9KXCF7nFs3HL1})H3=4^?9ITGl8Q8fajv!F>Nc@a;^s;(AhJFovR-lNGYe6j*)v2qniG+pfiADh&O3@L z*xq9=#S3v#-WL{D&2~$9zgSp+?ZLNYEv$w?9Z42e%l3)v8LJDM`kwp9#9qqqq4c9WYF7)9pTu9p-(**^dum4 zJq1uuofvK*4^0(ebfLHpQa%);vpLzo}p`?nIgelHYSIt>H)o4lQ>IsDY(h4%S2DbhdRO{UIJPTE2&30V9!!CX zUYDn1>LF7Frq)eH)Gm2ch*3ef`p z-3)l5wUmqf6JXO9E|Uu%35$)cNCnT+yi%de^Q9-R;)GbI6qW$7DuU?Jyi#EU&$uSU zw{3;6FB%&oh;Gd*6`tZb+l2U&y%4iEjRzu#9?dHi{>igGis)<4eDOd$ts|!9YhKBR zJ?AJJLUcb48GSjb59+%yav?-&f##Kb<9Ok5iem|JrNg%1v2M zzI8r~q3C>->rb(xFT}Pa2noG>Z&ItrX9Ny`)zdwg?;Ob{`{VF(DSk6vRW^Tbyc+F( zm=cW#R6mAIjo&%^PY_Qb+wT(1{xykyUs&8es3ocodTgsd0Gy`W;*O3$6~yOW z6vVB)@w_RBjZ+12`(8oZ0Yjdwg@YMoxn+xM))^UWPU^6p*JW!J$KK2+`@ZZ_0^5u( zBc|O6aqLjWnyG8%v|~xUGeHhxD&?(=HOtqy+hHFYVe9rUa1Up!DOnR}$DWJ8aYTz9 z$yn34=A{JXaZZ5uc}FwW9A9%bfo*L9y`8bARV>=@t^nV{@lv~TK71YR$<@x;G zvSrKi3hJvi$ELV^3qZ=_T!wNe$2hiCbAL(hM((bNBR96?K+X!Z^Eif^sUc0pUF6;Y z_*kK0EV*}bx2EV)TcHnollrxttKm8#lgkg+Q92~FvkI=asju7lEL_K^uiLp3uH%ec zFT-_0B^M4Dv3DHgI*sn?aIcD|CJ1o6)vID17brn2w}xJz+F&%XlNl9t6?K85P%*oZ z8z^^U#Rl@y;JpG#71(YbOS_|t?IC%iofWETJlbK!Pu2>wo?ZMqA9V7{sdRbb5k^?|*`r%={PgpZ*>*4j_aYrm7$Vm}CK5IYoU%GhAkb}ga+*l}F~Z?e+5 zJ9HBAI!r+Aa!Ko+uuxI6CsFtu}(z@R) zR1??P zdvlZ=Wvo;+MyeXnOoE9yRdcJbM#rA#ac>zgxN0Lxy}v1^>eZ^(!DJJMcd=K&RN9j) z$Weo3m{>8RcUKskHC-H!y$t;Q}+cMrRd?|90p{=SP; z{f|`rlTH+aJ3$RxMZ{=;8|WbgI$20Zu{WufNrBsRL?IMT9T*r%*A)epNP*mDNKZB) zrL+y?b6>B(+6ibpKz~&VphodBvptTS5keD8?EQ?uJAtz`caoWq8+aF4r0tand`2)* z&4I7UlHn!C=YUAO%NA;62J{j&Xr6obh-}X-?4*gE%BbmAlU@T|BVQ78YwnJctH~rF z|7pX|nvoF_JrTJFJDFmx@k%wSo*sSt`4S}9HCYh%mf-nJ5cfgt2sqjB;Skpj*S__s zMi$l-{4RrLM1WymeMG_mO;F60e>}v!%8m1|(Gkg+A)XT+Xy-sg5uY96`7s~5IXWWw zWJp17!Gf3($)`iSqW9Va7NRI)X}t0E5btL1cHdnz-tZpqk%Tnv^1ee_Q6F!3=^!7* z8-)o7jhI=5SW^dZaUn*(|F*LVAEMa$0J9Kv6NpO+pCF(r+y$&!PHDB>Tkv-o*_Vpkv z-d`q&-tAHI|MMY5!-~e><7pA=vSrYB!F6pPjnEI^5g zD&C^)1gmKdJ3%l#@sYSRdl5;y4&#yfx5z5`(_9>HEvA%ypeJWhb}_#7f>wf?*}B+^ zJBG#mk)!eRJ(^c4?n!3dCz@u@D(-78PQiC2VlmMa?7b-3(Ml#qd zQ;ngQ#iZh@(5nzk$SK}gycZK`N4QMMm;@_+!&>|*Nu=F7P<+f-e5`~LfhJXa9B=tK zt#S%HHM9xbTzpn7#`5g`*X2oQ^p4^$;XWgT4y1UCe)L!9#7NSCG<%BK;KQc=E$6oWRz zp=2W=M)nQaeC4v3RPJHFV1>nEEw6@b$1y(na>%*`>y|>%35@a#m(|(HBeXCW*7@<) z@>E#2mfWxDnG?T`SCHlvY27hGXZx?fA zx?G7$@M2^&X^|*Zj+ZOZO~2TKKIoENIZdxvl~$$lQGoA`G$EJfl`8XSsPeIHGITXp zer~Tk0mP{hM33gRRh|d*fhb;8f~^v5^2G-tcy7%rRb59znlnv^%j{Kini15zQk6_Y znzK!aYgttp5SK#y^huM z>X5m5w^IE~gru!{9|dY(8n~nScvAI;8kN9sP9@MXLM3pUM&%7O%fPfiF3MFK3Q_y3 zxmK=ef$$#e5bc={y=<`7K*POwW1pH1#+nYnJ5dcVhhB3tRR`Xhg_>K*{T9X_ym7;9 zsTo%@4WPrkRhw((B-YFbi!aqB&_XTR$rV{O>$<2l0g!cy=9(8Q>C=cmYyT@R!r81ssudSz7%JsFc@!00t4-#vSX@so5K`eVM6v~TJ z6KkPGUe0cXsn=DhDShj1L|fESoLF}w(92p1ed~}FB9>Lmb+>Zh%jK;EO)1sg36v>N zN`31v+R|`_HOH~lL41@T;Vg;ZENPCDShrl0jANBWu*#Za+3PAvV&FvKs9JsN-XeTn zNQrfCMMTCzohHuP9QeuuQIX$^iu_3g=ac3*iFN0q;zUDIyg`v-D#0ru#ogJ#E@EO3 z-6Q3Y5PCg3c&}&<4zdOZAoRwl<~%Z^*&jVe!@Lw9X}X z%osctyaaMk%faJ#N3PSxVp8w}Nco8p`~dj3#-m@6g5TPL&^)g`!j6aD6hep43*>|h zAy_T!1X#Ys*@#l8jTB0-hR}#!H4!FzCv-SH)Y%;BX$##9U^ROeoP^L(?4u5)nnPJi zD4lrF`3EWVpe;0tkVb}%38CZJp(*%OPj=`D+{w$n8WM7cD%Ph&rxQX|$RKugnluGep!FFMr1vS^&gW7>l4JJ^;bnF z6V~@e)Omy}KL3IszOYFUUxfRWbAtF<0vX`b#^}c(_5JEI>!BTB%-1(r z-}OTYM)_Mm68X#CkH`*NobJt>E7ecY3~yME*!fcbq*OoOLdjv@^U0uI^{cfg25Y?) zY}K9u`y4|N6Z>gM{hIn`>JMoae?3j1Yj#5YW&-k`&Lu3> zTggB?_?%o4kJn3rds$XV`z}(+O^GGY=&ujN{Q;l47Yd!_5)7pezLZ@uSnQda;w~8n z->JSOkD_i+_TXFKC66YS%+;e*yBBpe6987u>uaxwTwXcfR$`-gQ8;gkDV`GaLI=O- zTk>2CwdWE`Ht5s>?!}-6z;gh6)kMu+Ldp0d3fHLRm%Ib$4}D86#!$PMSaMFMR^xsY z)Bv~`7T@UCM2(fAZ$0=!6s}P#DD42~Uwuo_v?3`j?U7j8NvBrpeyppR0MPDluqJA1 z=^Yd=3g^^PvrF$6lS+rUyPNnDovjoZcJLGn*h}-__=452((Q2kz-rY}^uGuHVs(yE z$oV?ftrE*%s=t1HOTjoeV~8NW*;)`c-H)ZVJ(#`B#Q=9G6wfX}Ja`i-Mm*j=jzdyo z?eteV<==w#6@}{9XMzbaM5m>o3Oy4<)uQjJQg6;wz4+TE*nj3E z*1*a8Mio<*aoL==`YfEb>o`-e)+meYZ_<8;y0jEkfwbSD+d$W=(d}eX4Vm`d_WRhk z*e-z|HYyKfG$z0x)nLzt1Ef{#W)QR`TzI3wIIW1nlbFO}`{!J#l>IHQlV zGqc@mwPP@KC^A1tr{nVMwS?HgzFAqyy+_E4Gr*}?_KRlwA6ELBRkIjQ)`}ncz*(+2_gZ3mjHsyTv4SP`w%L{U&x4U$lB7 z5=UmAz*#7m)VNH?XO8cjokTh(f=qDy>g)su{diil9lwhh{yPnl<97>{tQu|BlJiO( z(!tqYS<36WNsZ5RmOF#aFt#+H{{uzmW@nhl;ipk_ZpHVScHxsvmTdO7{GPkiq_)U( z-R`=}Lp84z@URb}KY4@}VhdLW-Znn@u=5S#H(KMY~=4wy?TTT!&lAE{wzuCn|0O zUN_s^33%OaceloC1ar5=YovKq2IBA`h7X z`8)8oo~8sxN-_Thob5bh&c`6;OZF=XnEzT>Jd!V{H^@cqMw6P5>Fw#g)2kvkJ8^P2 zvIq~6^N#u-a^7j8j4XtvIrT;X2w5V^va z|4puc%bddFg{OdvB?ouCXfFI9O1JRSuz0j5=;EVBKg)&R!k5O*fr8-Po#jiEeBC8q zlI(-pJ({L8xHs`Zyw4(H)op;}yI=NUz62qi+#4e$hqf#E#>>8ukpNBYXZfa^eJdp2 z63Mqf_RWsc!{%U$sa?dD?Q;_4wUVz?_Mr#=56X?QZ(}4tqm1u?AC-J>$i9~&MEN}o zLg)lSev*9WWgpr%lJ%8)b5n@_O4*O@zA3fYejH@;-z(Ev-_bNaAaU=A3(OwjmTu18xdGMBBC%AO!)!7fleD|1kofD_!o z!zT5r%!)A;4^))}sBI)N3*;pRQCY z_kqk!oJ?gQd5BCUO>Z_QQ(1$hlMPa34auf8`^uf5^{L>lG^wpKtNqpGHAtqF>Z@q1 zt|SkP_mj@UX zu>QD94PZXQgkZ=J?9{~^>|xnB6MY>{)*<%^>XNHL_WmTNa$cn+t3{>)C0(?luqVQ zrb=V|cWU$&9h!gvzt;W?f~baOQy9jmJ$R#bZ_Elg%pso?a&w&TAiNaXz(N6yoO`3- zuAqTv=#Uh8iG`qV-dRPuj^8w2B!x~&p<@)2j0++3F4n$6m*o&7KXFK3$$BrvyuOXR z9`iIO4)J*^^ZHI~eS0FL>p{#RWv##0ygprP)Ase4(WQi61v9|C9@A?le&}poZ`bp1 zeUTP=4d{L@um9*@tp1eOQ_*Rx>>FSsfK=!JN@7E&F4Be`_6^+#G(YsDVBU}-ZRp3- z{R7f%-Z0v}0e$p4aoWbs(Dj0QO@AS4!%k%b(tYAn%7+af$r~_drPG%-d}fi~Q{%w^ zDX&jJo=3y%_1EaUQ(X0Kif^v3mFm|;^VwbxqXfdaE3)ff!N~rYT#x0?XtA2q>oPZ1 zZhW=@t5sIi5VU}eTgXGTaN{n#BML1#5T-q>8xL-T0*X|pjo6x`_Z1sYhQ;@`QD@w? zp`YA<(bIc}l?HRe0&~LyQbUH^kg7r4o3vWrFv{34s)6)6_%)2iyLtOpKktY%ezQq4-(F}`4{q#l$-y;JCZA;YiR3$ za|;Z_lW&-}w6@5tP|VgXsCy^h5Y!e~Te@LQev3ugax)bQHQWwc`l;zy2ZlAcCEdb) z)Xc3d%xq=`D5*9cIs#Qh5tZjraT6Zo$w;wDsuW z-jls$4?cKsP~H-zfT%5yn7OrdYh`09NZ!KJwRJstC|&$p1gbo=Suag_0x!(VP^A#XqV^`7K z*h_A_g`iOZrOd|VjjQ%z(TDPdi`eKRFNxS#j(3cRm@I9T)A&pyc6Z3dD2g<(D5vrH z#si3aJW^lN@M(j?*2dSv;;BJ2i<#4S7DO1|+AicY{z0CfDXx&SZQHipQ2CuWCG)m0 zK0v_R5w}vd9U=;_DYCY`*V(-74BK`ZfI2EqY`>leEt0nlw&$sb*fyw!Q*|kx?IPZ# zx!Y+Nn`W=b+HN;*FOar7qt#%08LtNY#lhR36}NBOz5~g)UQ32(-u}G09SY%eC%)r? zZGVA?3c)9QwQ(pB<|?3qi2-8yyG^+en>R$xJ%v92eGTQZ67-ZDm&1*oSGZi z^HH!Pn?lVyhN_yYNtU>r9TRrUMCSgYW#^7X%8uDlnRYCuc#tV;#|rZfyR>5!&uJQW zICj8BIQ^sGF2_)O$Hgw@9e+qWevW3^PNUX#%sbmUcA|$m{UcA-PF`wSvUVmTSy?+} zw7Z=J_MI>WPn8l9HuOvs%sZ>4o#jz(_MOlLr%J&sd*@DywrhVE^R74TyIzXK%H4H> z=NN9qnkZnPx9hTP*98RTMM#R~-O0AyQUsK{n{EqAvlBjoMo7D}qugw}p~z0?YYLh$86uzhF}qf*?YQ^qv2*wEde3E}wCrtb+iOB#Oj`E#k@i}mByD@s zC>SI~^WMj7d#6Q^bN44Y?z zkf7E1xD9d*Xdt-;?9c=t4Cq_JxS9kTa6}(Kz=`%qystuL!FQgE2D3II8V3KGXdpW9 zaUwc!RWwxt^R&>bDb~O;i#C#gbG-(~6hevD24ORk<~vOpCCH0+3&W z26jP37&MOljRfyO84%_hnna-eS|s9f`u8}6FQ#yG+FH0~+-WKo(+PYr8|6MIk0)#` zF@cslGhFZYsBi{<0eywn@1QpLXHXmb6{n`#G=OHbK)k^i|C|}F*)H>`4FleT0=pqf z2CNPU5Mu@rzl=c?o{GpBQ07|XNc+K{0^k{hFp0PNKVT%0Z#j`$7$HXx7ZHG+rE_=J z@~WIs!C5p=U`=e2(gFCY3uWLCk)mHFf)^thL>WjyH`Bi^h&%*yYM|Vdw?jzkA^oF5 zLCzsl2=p)r4S@;WJf|smDFrVgVlyMeA_XBp+_)4%Dk7wOqM<}+DBDr7i-geK9N~FF z*h&cN34sP890A|<&=AfN!f9f2G{UACh0Fv(_?r-ZB7|lXP|}&7P_AVDO8+i`Pv#d9 zLG)^s)eeGYB_cfQ8iZ%XMZzPgq0&ocmwC0K2Ab6a4K(ZaNCVAUpf}L0hngB_*6e5l zrDSHgi9CalSt}x`V1JT@+!3J4&`EuTm9Tcuzbzz5Fd_+A03?ABdY@DKm{8s!YHvi6 ztc~81f$}b)WVa%eON8=G1cfuib}S+L##n~geSw;NI~Znni)BdAbo!SWx|J}%4%;rs^ z7Cv+VA19IV8gS^#cESjYpBp06euRK|&4aSF?&u&C93Bf9)y4S2SO zg`9R!`?n$vb@{{gXaE6g-0-~wu&gbW!uK|Ow%e%3=W{EVK}!t9|S+jZ;l(N63-$8J_cDVL0ZeY!+RPobNP% zCPxkpENr)P&Va{}k6-cFB**YX5@C2B`j;3Z$MBoL-UT^^!$kgKO_LnMvDyVWws1Mx zLXP1-g@qAfSQwXxJ__m3B^hy@2GS%M(E;FSj*OtOW>b!+eQ10W7Diry=LW3ck<~Gl zD3h&3`2762r1SCTC<@?G)} z;>S^2WaK%HpmJMevNc9M3)ek3 z+zjXIc(BN?8Y4M5>T}}uaWihv?wlJUjE=|C0TJRN5k`}eA8n3CKqVdx8y=%ZOw^w9;J8)g&`Ue|?UY@irIXQBhM^IU^w z297>MT#)Y3=cAc7`UlP#=}v{PW3I)6W-3piI!hI5Ob3e^A8Bi2?jU63))?qT%B^-_ zIc892!W#}|W3be8o*&Rc`x`Tr*ZX~__h`Oj7K(&`amaZW=afe^x+n6auRwSI=OeHV zfj<+iZ5CTk122{_&l4k2-h)gUgAU}&MAa;y?TmRJ#2+TdMd%Yd#_8(A*wRmm;=#wL z^*`v~+z&#)2P;Xy2RCTOEwbmqMq;Fm1s>ebv5#xmWNtn931NRnc<6r5|JksjejTALR6^PFe5ptN2cM-Bm`n*I4oyORVWW}eip?(g+ zIqnMXtb?{t`r&_&}=nB%-*;qkGkp(tlv7mW*QAWavIYlziF zF+Kz3G#>5oLZB(zsNIgor0RtL_Fbcrjh~68DX88~-#CH2z7RAU>x8pOYeB zR)r#z<9P-VAio}AD@E8Cjet~)M@_k~nWkaF!ovnC@rT=@={{@%_*3QKAUoksB1^L_9(V>( z5I9a4Oo-gqG~Yp5W5R=YW+DZsI9duOEI>|8fS$b&-~~nzmk}8h97Ry^6eGfw(Fp61 z$O)yC$Y_KOdIThS!d6Q11Ts-4?4*2AuR{NbN-+V`Q(u2dK>GhPRRlzfkfg zYBk~@70bjA@SF$Bt2s*wy+|&51p+6bC&t17`33R@@H7C@n&TovCT*q+p&%&8Nhc6= zEe}GjPlCq(y3>GkxGs>^o%9!^nFPJ_O`|q@6c#3%kQB5Y6Dp zP9hD{U(aCTT|~SQ0U11bJxTN&@^|vH(fmz>@5QkAEzVJp6ITDXOA}xe)%1_2C|^;O zpD4<=ysFYH7U3bG6ot?Bkmj3W2A?`eI0e<}o5s`>RH`YX;8cM<1yd`8ol*ezata64 zDR#oJbUXD0Ue;pjBzZ}bP`a2Ph@sz^p-|8ux{u@%L`Jx<=wi$&WGb4bo z88Df?;RlRCbH=l%k~7fDMQZs(l*o)m97eew@0Ykt6!8?H9gnTKGd?FWT1A|BD{yAs z1$r~@h{}jW%^VmlI<07CPC+CpnwjWzwW68nAs59jBRKa(1&1&*Lp-Zyk*Pmx1c=TW z&@88BJrvC;*kj0vSqpT6vzCFN=8Fr`%OU!#0MaDsPvky zDMv{_%DGUAT*|r0Affr9QiAi`zPxDXjsm^8Gl>FH8Ivt@7euo~Cn!e%w0$nAyqC_`@@3T9>V52se8;_i*)Cr z*8g<7wv`jKb2kwc`w5t-ykpFLnKr4FRWr5$kd%&-{RiygOo6wx!yv4+C9@F_{!(GcExDtl!HVD6<186Pi zfg~-!M0K=+Ew~e@U2tnmM)!{+?15A+3r0br1sNofULO}sgs=-9Bw@9#lg}h9cmn0J zU~z1@EXX57>IgN{ga~mp7HM*%_ZMse={gE}g?PY%rwQ`~mtk=%I7dOmmDW`Vmjf`F zv*4f5hkW)Z4V!(!!a}oxf33ji`{({sEyS62)R{Bd&}QKaR9*|Q7=-fLLW7-!XR*}_uOBEX5+4(F5yp*(`Zb~=(jsi4 zp=w6X9PT{GjdQZc7I(vAiB13FJ0j^v!7oll3aFYdrb5=M`J-O2eY6s6ABE}iYm>x} zZsBZoi67lX59(cKblcL1ZbJ*Frn{7EkflvF2-NT6utB)`1*6Ar;f(6YnZ=!2 z2AS0M7`;4Mf+rXjo~}XbgaQyy6N~^gY9MX&^5kBC_2ndly$YYK6*4Lf+B3Eg0{kwX z4=^7yjaQ^10-eY6GYGc>i1zJ-g=O)0T0{p2NZhi7uy|=c*|y7QV7=@{$iM6cz@CX% ztjoHgH7!d5XtHjx_HRMx3n|Z*JxTb`Q!)6f2p`omich`NGMYeK##e|VL%wCzgouiH zX>w#hunhAQm!63>Q&^G9_7H>!>?Kaz7pugV{Xk)tDC`%))OE$Oe~9)UL|fMt1H;1d z7JT@&{2@4}AQQBObwpi0jiMq^%X2AF%a;)BQG!J>VfhNsTTbbWWCFH0076sE%UNud zS-y@i(Q7uPYWW5t6`QK%I|)Jrb`dM?i%r!E6UniHN@T^Az*unw;d31W6|v&#u=pG9 z6qrYerOla?!7F;xzs_L30>-$`oRFbkfgIvjx}X-WxSuKrUnj-p9QdE$qxltfioTL~ zt!Tz;RSd6^2(L|qyq0*CHsiJaU%cq*j3&Eu#TOLqC`E%kq>D(Pvn1zfiW|*@7=dZq znJ%y~#T6EwN=9TG;yraM6rtves$Zn&sd*IkIEBIRxn$#Ih@A|1r~*%|z`0Dkz9*F5 z2?aAfg#W zNaaeXutj4R{jJ5;0q+%_^*JWl=k5yM_>Sy@uKWsa)NO+S}@$P+6`_KgF z>iY;x9nb0q@QlXn+>Xei?CJ+&R!mn<)W~A*4)7Kt<5tfB#2Z;BC5o#_wXeo;5KS2J zlo29Er+<3&#Q{O>U{X6EgRIl>%nl2V)kqg2=y_yaq=B?NvOf7gc@z&>t>^%)9%L-f zfquTr1Y3s(nXS?;SbVjMKs)ig0uXJ21!%xv_>Us%t?%PG9o6VXB)9bwR4eP5u=v+g z5&eZPfB^IvK;3jDPV+w2i-bclexMlK7p;f`c)ucphkQlTW*7LbgU*w$B%P<;h<1bM z@~xmQqgnpdEuzWgengtHi+>+RN{Q1^o;dbtmoBtEz|MiraB3%NJTO&(FiBD*RGZAwx3v&P zPx_Y(?rQfacj)EGddgIiRpqkA7|H5r$fFL6<~-4uNr+Qo6Qw>%WT7+l3?s6<1ZhtX zLKu$L@eL;G&%mMSQuTK&!-RxQ1JgJL zj0#T1(Ty;;Pq`ZyC~ZeF!afi}A5*oU`(6KcK+o+KJ3wG-N* z6N`RMSm}9pqwV+7TcOjU0kl@=ysLRD#3me?-gIW*fo^Nk7|!7_8pAm@Y!IGBd!%OP zoG#+uJUk18$Sf>aI6S?Y%QB8yqEumAy%|r$p(6Ff#t%{IO5b_a1J{Upf zOW1_{4q;RHSqeWz;dG1zOWOmHaRwaD!plr@=iLH~ysm_yYe19Q8QJc>0uR<*=w?&f zoqD#rZ`1&q3G43Olto)@Fi09TVqNkWHKlXra7- zZ(vh9ff?#e!9@0l#nSYUq4_m7h5MUQ2u`6) zoIgg16}|yhg@>ctk_z7s8;nM@YTlv>&yggBKSPqj@3=zktnv4mIGVefqxm`!n(sEC z`I0$W7oZU+6^E&`T`j&r{5Tb0!!!=91$V%tc7yPx*Wqc8Ly-|+g6wm=4SsfIavM4Q})Ra~cff6FX>sKg;80>(Kq`)_bz{`ZO=Ra6* zlLw}5ZXhYj$iyh?5+enf6lEEBh6?&HjN=W{ zwzyH0aTfZLC&feUG~)aPRu&T}))GAE_ieLy-6PcHSQ!K^S|02PL)@q6(NX!=WQjE1 zUNar?t(ics5ft9ob=MegJY$Vg`#F|PCq}7QvA%OK!Cn_{Hw~?HishzCZ6L>xn48{t<5Wi6{m|8)KP6o9H5?VPH&&040IAm12LpEdqx`p^SwI>3r(AiZr znADq)I*g)o;Va~3@7Hnatq8A1va0VksmamsYMde>Lpn~qjlz%OxolEzZVLa1hhK_Q zEeH>w_68m`sXe0Mfd_f`i8%Fk3P;fd90^uG!l4Moc(pe{Q8ocTo{gd)81W8}n=+OR z?ZA4R9=7^<1dVK}0cVD9w+dlHi$@X&!yoJoY(X@sy@(u?77if^fj9UkIJkZcyr}sJ zjq|3G4ZKFP+JV>b?LGB&oGWfoisv{HGN^q(sOEY+H-v@Y9Y*z**sQ#Z0$;)NnF*KH zBY}M=D{Hi=nYuW&AHr)f;;wztq!K$VycW|GG}#oV-c8|0@cfL!wN2qT!AX;caq2w? zuiJ>{q)9bJ!|V3)@O^RWy%hcxo^NBbvOht8#Dl5NU~4TagYo31BvDodQBPvCvJd~j zt$HtIWy|f9m36;Gv+{nB3nB-CXmvqLQ&tAMX?_rG%F5s^l$F6-C@b$pR<`^^FeKav z1QNr!jGoh`p8Cdmg;@$fUTKft>jB~%WDQvM5ez4wf^ z*z$24q^GESJn;3Nj`|-XDq#7v?)dizdeZV)VM79Dy@Gv-)>3N6<*P$yp<@!^Vid?5 zNMAlcF3+cUB^1x6#S3Lpyh@H8j9`Z{Q)!c4`NkytdolQwQ7}@J*C;&M)+SlK6$!YE z1XQfRvl^}O8YJMhXaXv{9E41wO;i%mU0zHsF6|-5xhYWK}AGG z6n8h--K0r+mzLgVT6#cl3bayhMMV)6@B700#smHSKW}!E2K@bg|G;+VeDmhbdvD&% z&QWv*!7xoM%)%qTx$gjT#OrwKe~RMh&lpOK?!!n-A>&X+(OAk6vF4((&PL=^Ht;BN zQuS%=)=Z8J%_3YwNlZflydVCRy~2OyfwhY6q%v-!GN@8i^`b4%CPf=50kbKwqSMCm z$P`2gXzgAR^F^>=7D`br!@Zu;&=>lmf@s`pC|3!=h~zp6_cosT$D&X1e1qm7YXPUn z!S|i9d5{dy;z7{0#X_%es=&6eL28Oe2;h|B!6uoo|fOS_D57SWU0fyFno zPPcfqiUc>K%nCA1s5!@KlL$r0GFIMAky|JdZdL?W6EA&%gkwEpx$3*Zh*uNh#Sz3Q z`#b%|YLf}?-C%&?4&dF#0Asay3VekE$7)ju3goExV-T+ROLja0W&DSL{zgCzg9u&c z0!}z>9Zt^hp{L7*ivEBT20|Zm7Q8RUb3G>vva>WSYyi&2aFC*V8(lp*dg(_PwInvD z;{68Rqwz+&;Ri)O(;;t^l|X2~Ja|DSbe8@4X|o-;jB<8=2Pxl~xW#aa|8+{=Pn+X# zKj6;jpKM0B<-hGzJ%*Vj0uw`)E&u2rLp;;WsyhIBbBT`}&Q7xfmqUS9JV zM3R@@9;;1r52ZqD*nQ7qq35gDIrZm}e#O3VPsI<5EZiy6Ajl^I%5z*;L`_VtmzZCgq zBi~Pb`EUXIQX`*#(ZBO8boj6HSNc1V?|go(AKx}XOIDu038Ab!e=FYZvuPY;^zx{G zvctbGzy%;`S}gK)_vH(mg;16+aLx(kA-7e#$`QB#m*Q#2H=A9H^ym`W>8b#<_TA;JF)55uRu9{LBew#^70q z$Bkzn9)z7W0ne>?vH6 zQ)`g!(D;7ZN~e6Uym`2Mfx(TC@|&FUR{YzJtQOhN-e^!6rS_9Apo$QIu`ZICwJXUM z8$25qmu-z$VmCPDQn^NcF-!-!iQMdG&_QnFN69Y=W3{<9`KdVh0&OKQ9(*UBa-@O? zL5ARIMs@ziyNLyopMI#?&D=t~Nnh5W8Khr1;~*kRCTO=Tl&_Ijs=r(25~O|_Rz_D} z%CDfa(>|w_$?-QD>I=sS-M&znh<~>sqeYp@-pIl$AQHEL*?Hmfdak!lD&0!=t+CLD+0AMkBb%E%~lsuR! z8#2S}n-jf;cZ6q~a@PbfntI&nsls()^)=sE%(|lli#u+z=Xs0gdG#KEhjr;WfVZ2B zt9Z_Hh}_Z3;^}ClPespnvgb>bRTH)YoStL2daIw}`3Ipb;m|~fI!sh!74_WcP^UVc zACHraW+O+6q&f&^cN~VvvU)ASR8-6j3~9l%vgVkqdMv6(Z37zMepSUgN}bKbm0#&F zP1GD&P45+k&I}ivBjN%PwSpjD1^UP;X8MNChtQ4CRnPm^tLha zg&hd$VSeOj^-Wnlj9mFd2w?h^tbRt`Fm*wzAwxJ}D9IGa$nnq#cpc^&0glxp?{I=n(+dZP3|U92T_!D;L5%G26C#E;5Ly@Ksd4tM^P)O=64_Sdvz z&*}JgKNB3!a5#WDxQ}cnCOGC%7`*37g#52X#Cw(zVIsJK@s_bNWe=Lyc94sw>t&gU zcXJT?QE-dPqL@S^NMyOlNIDASvdkP96<5oFhV3C zVcHqO@rUI3u~!&&W4QUehIfSLzY*b3PsN?UXV*M$G00DXpYqC=f(4ik(9B7>^T7MSYHvn}YGJMg3M2fd&c2cX*#97{^F3j?3z?USat1aKSkuX2-Na1epnj zHjHAU1Vg*bqFtt4XMokH#!-R+!)WAaZI-NEiCoQwU}&kb<|1#HvQ|w=)*bo{Ixcg@ zeFW4*`t3UDF8ZNe*x91!hxN6*P2XVC*TxZ7YwK~g=#N&-ovd%wHNAxAq+gI8nS*)> z%gQVYh`gSOeEBv#)66IRQiBXRX^fAo6g^3IJ`%01`JYizLpIA8$J;R$E)hc zdC_aJ>BmiQjE}vb@;Og}kFDCqWbbfqj2H5vUB%#e$B>8gyF#Bc(J>;};91taIlVZ= z$vesBy~u=!e5{84~tM)*$_e<|DKJ?() z)dtLe$U`uFn1*5s$PjG6?2~b)ZzwPNM4NAD81U5u*f+LUI5&Z-`Q55LnC!dEH^a9D zAYkAu|nkzxQ2l7|7# zBfyIzGzHK5Dgds|=Bo&UOJU%40o?ao&7W57p=4jT?{VL^7;rvofP0oa3>+CLjE^Jq z^t}aeAKH9xnc(DS893M*;tZ|^Q?6T*eLwk*(fxv2Dg&3sk%z#g4aU2VlK~T~lNQ5^ zX=7|@F=6~t31Hep01R?9$F17K$!Rmv=A@w`)|MCmUF2Z^DZqWmyzG<&%>cO`An&uK ztq+4-!azy@`94?kw^e&2IV~+MBkd4CE;T?FkcWY+$NOJ6?gqfeY-zj00GBd=(2eI^ z%GLa1)wU+5y^;2g9}|fhP(WL!eNG+*@Eg4UjibLmFZxfl`TK`KUPB=L!vRv^YW{20 z9!>U-^vC(H2T0-;-r}D`9s=o~Ng4qbrP<+}z?Xh}LG!2B{LV07%v1p|db{&p=Rz3e zNXh1=S5C9_k28?@x00jVl19}@I1~5=fQ$GZ#AASPOzVaXE6$9nl2fhdQPwn z#k&@PJo6J;ux50&x`jNr#ar`TmAI@Q20Cc*cz!JU4*n`6{sIq;hL8bn_8y?6(PuRt zSks6BKMWN7uIq1A3N6}-6VxGf!Qe9aq=x#3^&w24JeQP( zf5iZ3!A;oorXNNN{>W$nS7R9?qyE}9mplsp(mD5T46UZXfr2o!O2k{c9y)8XscQQG z%;4wAsTiTHq$D@6p^GH1>J?&2u=YumABuBNN4v`MqX_Edv@E(pdX!OKKdYAEl5^x@ z85_){enTrIc5K|c}`-YM7eHo3_r*T!ipwIFR+wrW`}Om{yf9|gZoM?&O!f; zr-|hZJlI?>a5!R<53$_Zjl^Q|hrPo23%Jk#tCsDOzr(HDBLHZ!0qAG)upjGf@aa@W z52g&XDHa37O%xeA#j54Fl#R+Jr2y5w89}&UdNX<0FPv9Vc$<=8Q+x*Uf$D>3^O#>b z;d~60&%X~3hLGofi9DFJ;&>M)#P&mi!FYoch_m3QA2=&ty9IjRYBM-wBF9xHa2y7L z0d(qjnCUhi)^Cr+Ns*@0L{1vb~H}?Chnx! zvv;T@^y(IRvmfl@0yd!Jj2266V9wa8 zRi&i;oCCC~ zQ~ay^cLXqCmx2bwd&t8e-jBDoHhf1lM+_yn{5k$YB>si4>+4P|8#6LxSvwr8=^KeLe6$Pr;)9fMU2J-wkN3h5ud2{|4go*j31)|06~O z#s4wo0TDPHPVg;GO8s5-!)_nR&gHZPIEDt6A42RV1_s9jhKB}&c5xi`eHWz!76l#% z1WC#;UxZ_QLuae!67>R)2B^~XLv z+~2YXehC3P4$DS@=zW4`G6Db(wEvqaK`}Twm?ne)2ge7~s05tadNJBRY|K(iIf7S+ z!6aL7#z`dv7utijnI$BM!7XvdQ4CU0?iEJO!J-wbR+Eum!76hTdWiz8Jy(J>dT(!(R;kU<)2)iK9P*ShcrOf`6x5(>LNiU!$z_ zLFpS&4yu%X+R0T)A0eiXwx!!oDl~n9J$+uJO6e<%Dv9a0+R|5^SfrG`wpSQ!W3?fi;vh4ND`Qs1 zf>L>$ zF(XsV2pGba5u}vnS1Kt3mi?I1XrDtyF&!M0u`5>0*ehqW5oD4PTgDR%9aH==UW>_i zJ1l-q9FjfWs)bTAM`e!78i$G*5|kN79;$98^*tw9UQ8NM>&&Y&uj#9G=JiIcGw|%FzVXrVQo)JUIM*YT#L=1m+ zh=RrJTDRfqBZkG5-I3j6iW_G0vY%vxaA%{w<8TX0sw4ZLnEi&7{VM8zlo895eFSk^ zINXf-5%0|?QFj-X`!1+U2Hlrt!rPB~&s&d4yG968I7`W8871)%;-sqx7) z(V256FXlWb=iE!7GATi5j)aLhl0B!$P&QU=M@r7FoR+)`f%095<}EpU$wRcw>Baj* zLE>{>`#))$b2R6NKHBCSGiaM@;d4*TJv~BOF?X1fduFdN{=taq#uXEGcdm%AtiA=9 z{@hU%Am)yC8?H!lh;r_v-06LE&Yfk@ITv4_$K%?=R7Y;In7c&ET?BuULFe41aAV%U znR_Ge$-Rv{iH_V&xc@>@av|*FA7pgS^+wYi&5uzQ&58=sWd#OHP9onTPq?N{?)P+c_C;BVZF zAx!v?_&b;fgX*H8V%`DOa7FWX-kW(J_R&4>b4GU+S7jgv(LL`+G4Bs4?^gh8VszK? z{zM#P5;OYSPWNExqi~Uh%&KkU?c0*f{wyJ|?G_3jm*C$9T|417Z5wpYMJo~=+lphw zZMDj_a>9-^(6(LC4Ycj?m~GES8fe>bPd-P0ocX8n?)M%F4FV^`N%_CQvx*CyX9hb9th`t-L@qcD;bp^s6J4pNHKr7d zEtpgQnO46hd@Ti+lZSc=oB({XTw@4pn)$r5U@;$4usC#n#I`TEqgRMK54L?%O2Nj0 zM++Lz{P!9#{p7*e>ZI94z%phR3$g$!D|CVR)r`h1J5vgp3%U!AVN8{70C|Eu(Le}C z3_Lk`jX73e<6r|v6Yd*;`$lMt5c#wQ$`pX-;vPp4yHW~{Z$D)_rWiD4`B}D~MV^z2 z*iN5>BSkO*{HvVp@wi(sJ~Zxxa<)UKTrvvfG^cD|wtacwev|{_0W{uzBYB9%+wmR$ zd~MUs#`iB`3VOnJV1L*4tnC=xhDSZy%NUzDwl|2|JLT<|q`QPId?B7mn7F;$zWs=4 z9J;oDwH+GPu*-RI`)^GA$e2&s{$IZEl)^!XG=@xAe^q#vyYLJEJ7#p}g%F2JDp(Iz zh!16#91{ygx8drOa3LYB@IpksEf!9d3MaxP%P^(|rSNhibdI5E3+EC96pR5>;nlHX z;dOFhDuNi|w!&MYWwh|Vn8Js`GU_bc#VduK1k9?nq!d0?_)PHtu;~kogoQ7WC%UQd zL8R~%#A)}l<|+J;+(cRO5><^>qrY@obkP|_Ly17lFBJ{z6(+vyD!RC6av!;irZeP{ zisti0i;BP*eSLn>a!=8+Ug6SljAHI0bf}k}NfZkd-Ach?(JGJOI)P$E_n?@+#G*&# zq6gu6$DkN?EusV~Qt)E;7D1S>mK( zwB4n@O#lnGr4%nMzPY#+&>l3PttAhGb`RbscK=a8F_lxS18jQel8B-x-q9;uHWyIa zQ;K&NKUs_+o`$(K2uAU<#QT535fWYeMjwtjQt?lKRtRVvDaC)63@o`0(CFI% zZz&l}9)eaf9Pj@N$C69%OW_I;G@}PUjk}pO395Sx0l`yJrpvat|t$%9$!M@ ztUUxm;tsEpN9iq}1%ggylRLy^CAml;-xvwQA%^8rNp-I!>aX@IY8N>j6MS$!jKZmB8b3e9{zYIo6 zDm|Sq9aefyH2apGuaw%6<4eZAw$hO%Php8=>39kkOD8CXtB-#%u~?cQGhP>s_jlGU01rXl-l`PM#Itv$-{nqbILH*O1-5S z2ED=`OYNmuHP5qoGib%6(lWlZt`s(XpCp#H$fZz(liSRyv_-1oE8R!oVrjQ*xK6Cf z%Tnoch|i=?ZDQ#WRt35AP0GTmkn1e{f|p9aqcm2nE2V63*|4&!!e8^sMv$9$tL!`u zDx5y507F{mnjn@9}nIb~M1wM>eT%2uYc^5>Q1aAlZDGe-LH zoK#kW5}uvWZ{|p`?0~K8NtTLKja>E;V%|sJ!cQza98>m|sb|U_EBlK}7*;+IDaG<3 zaycxu`1hl5$6eeP7zB{ZM^T(oJ`S&As6~RW9Nk0w`(pVt*>FYjS+%_><<9b}D=_7R1WRd#|`CMm`N-zOYK`Mu~nzDoTyI_{E{P8&L;Tl=M+K}=W z40x}|kd^9VsVF8deZ#M)z}wi)&Q&zR ztuzt4uofKPs@PWn)e!FfE1qYynJHGhpQ9`$+$uim6{g~YkXZ3<#pfI%{*)?yp&(X$ zx#Bq7>8O3hFBShqbmducCCtC6=`6QWiM7yE%aObCw8{~jt8#SZc;NU5V^^_qqFi|q zrDcODsq!+o6>MBjs!ZT3=T%}-$fUYl>7-=5SefFfyt-God@3tksYEXi=+q}xqIn2goHebBw6I#8$kJ6$PjpmcrlR^5cQrU?+F@q+RIfEmm!u$kaD!1nI5*GES2%oF&Ir{kMWkX3UgIO@DH7p(}Br%(*DVR&%jZ z1I=Xs3Qfjj{^Kb%vuozptO3_-Vl7saOdj@Qj5Dm}I^@hDzI!62W_``3nj+AN^%0hu zhsgtrp`WHex+1G9%ny6GKvuy8vU(_ikBn3B3Bjs8nNm|$QxQsp)%&GUXajlJ4{$Jm z?B}Ry7i;$0YPuM4sLnJP0BI-IykxKWGCUjz@u5@D_&2g#V(4_%Y+}e}3!T9-MrKUV zh6%$$=Oa)Ijj=HYwyu2yxHzri&d_9MD2|sx@x8+IqgL&yl+fIeBUAvb^$^1^bQO6} zQ$7THpVQnY4s5V2n7fIuUMBgCj?x~wH#9SBa>a)pp`0h@kU|*eUwPdHV(1Z>IfGP5 znzvdT@*?pHTK79s9dAbRC*=nfA4>_9gz9Qju|&&bid(1+UM6m#cD$AMR&b%+gs_VF z2ZD!g+*v!3x7W@N&4scbQ|siVTIjh10pIRs^DD;GUd79`S0Ug(MgYorI;Hm7+Ux6X z0vHXjcuVan@(?v@*W;~bV(cC|fdm#TldN@1wdk@E)`aWjHN5s(y`~P?*r`M{Ay@78 z+VVcZuB~P5Hm9~ttbJU@Ej>a)W8@nEc7fKuTKfhN!AYd3j9B}DR13={VU3yvY~)(Z z!Xz|uHT4O;T1*opG>Wx<%Z4k`)ULYI>dpdbRv9c)H_Yf8>ma?z3N8`rCYYUk9r_8t zsJntCQR=3{`?jg3#kz$?Dy1%&g57oK7G{Xdpm`>xZgt&;x>7La<)|lbsk@&%><7)p z)|1X;#iKRq9_3@|w9tIhye08?Hl?nru6@T=3nv)_uj|;cl>p&N;m0`htE6FzvvE$J zSzh;Y9jFs!m-F#;?@&ucDb%`msAw*puHIrcc-;qb-8;QP;(s6;b-&u`zB43814V6h ze@k`8P_eg+vDpnU;Ec2h;*PWA9fJ_{yQzA17{+!S7g~VGE9D&!CNt8u!^vRUb}W~7 zET&)rC+)bIAS1nV$9i7gaUVrkwdYcHxOe#LUqU_XRB6kOZ1P~HP}q@=w`o-DsDj%t zD*9NjubMLkxOTMd0JStPV-?$urx^-h%pI@GJJ2a4equ7_N}u6XcA$Tl*`HSMR?keZ z@AxIO5IR+=?}xNUWe(}d5HJ1F^^hbY^1F*RA_ypR3D;Rusmx0 zPKu?&7mQI*eK+r^f0A-rwdYgnU#)+?0UyvcA4d&V|2cW6)35&;Z?nPbe}g-01)`yh zWqq)B6YLGA8l-LzdxcqEx#0r5a%~M4vlio=4Oj3n4YT^j#!|y|Mmq4%tXv4pfs}^3 z8a6f#0tRUegNCi-Aq*PaeHb**gj*N``lO4JtId+zdxhD9eM$ z+j7Gj6w0)a)bK7P#CB%t3E8`BiF^BRIcla9%C|GRV?lxQ}a7W_~L%q2h>nWAexC^f? zrrusmX?&vb*=8N}GK{>&m&wERv-D$^nVId~2>lYKcH<9Juc(1s<9`vU1(|5BZDI$^ zG81rMg1zZ{qoPfidzVAOz3R zv`%b#z|(|zsX6R`7P20kO^@LFkG&~3l#IU5-Gl++oQknpkaIP?K^vXoGb3rhKEa&{y~5myLv}hSM!@X>nNd3t8&C$|7g2VEwhSxGiN3< z6b{gAj^UdxY#tv$6Q+LirFt{QA4x}8r991(46^w6jAr!JNk_!yD|N$l0&h3FOw^i} zO3hdIq1KF<&m^er8^q?-YV*nnYRwz8X0&4jwT)&n12wDmQc826Ijaqwl$Hs4^Ooik z@^BW5rMVJsQy`j~;5OAyGwa8*B5IH^fByt~^ScJ~H-FPB%=5|3pvb&DTl3!r^E+Aw z#g1+np|qTi;0nwz{lu>TtS8ABAQ^?Zs~TgM`5t1t=i5Z&`6drtZhEBYi)~qg$2VylM}?Y+fd7XTtB_-ZUoKL+8&~qIJwPl z;CdyJ6q|%-gZi20)7u&;rP8(=J|cuwJDAe;YTFy_=&UrdcX&(Nd*mSlsO>Y-qsBt# zwx1)c#jkDqi>eg1@hy(_{$l$Xa{EBQ{*(y^^q()m*FJ;-auSo;FW}oRYLANuliWU$ zVsI1QG^HIH*D;FavbE1NI1l|rTKfVD7uy|*;fj(eNBdH-{bsTKdc#s~zkyOhJjlY5 z+E)Sen;6(Q+t>3-`+XD#w~WHPxiZy)tNz@oy`0jX)1Kb}>qui`ElYa^d8pd$wRoR6 z&D~BtsUcYW+V-bUs{PAi`&)ARVU+Z7bnV}#0IL1BeEV9fK)c>^NI7T+y}fh!H!+N*yp;951t(0kPvEgA%yg54lKDaL$g)c%@?+ z`4gQTI9jOVs;Jt(lG1T)$I4Fh|0*eM-qLY9d8qas_+TDx^bU+ABh?O%IT<(On`?(3 z_~pqR87PBYmxIydN|Y0lJIX1DNw2MAr_rP}wgg{CCxwe02W%Zr8iEiW5#yf1!+giP z9q0zb^I;tyQewb6s&rtWwQzo4SCH26Jq3szKPZMPsw;4G92YxJ5j*=C6zRmA#KQSu z-spr??R<%NqjLzabe>Cba9_xaotH#W=TJ)L6`eD7p9|jD&ZyIwOdg_6=VH81RH6%;OZcGx-%(nTtl znAG_g-}!9k^L<3>e1Q@J{nwPvS9^uzbx}m>e47Hq&UX~U6@i19+RiV;&hMqpuaWy} zgM~VOF$o6CGI^cBLY;r|%5E@d^14Ll?$dd3_s}RJy_&N7{N1CwZUiy{Bhu~(=Gb;u zGKx^7V|SOh`w3}xH^q>M+jbu?$b}giOh@g0JC3HkfHSu46k8b{gF!S z`j3q{FaV?>CZ=C7s!R~O&Nfu1*fmn>5(#o7+SYXu10N@KT|p5vp(Wy?M>cSgx)xHH z+_i)iM$0V^r*y6Ax~=OVdRv+W;VoTvk%z|5T^sudK@%dhR>9S!bYb8UonQ|dNBnCkU5C5g?4A#SK5iiK z5qYRJx<2niqU(>7EMsbt0SWd!Lk#lo83%BsIkr8M`pCb>F*0`ao@?Yi=VJPouo2id=n$!Jen~yas71WV*w)=L2~U205;J z>hTkX?WGBMaqlZO<}e#d*$aJoHFO!8%dz*%SaI)h+umR0y|7e_e8dUL-v1hjh!KYE z%ON=X3T@0`&bKN1N{l3!bxWAIuRUhpUN+w;?_(H%QN(>1S5Y@A?)y{Phfdj5%E+wj zJ8oiN>mF=!L^sR{S1IF&ZtUSIA~x=xL}79_n8j7kg_c^i*HgNayHk25p~gk5F}jzL zhZ>`MWnW`-Gff*cOkvY`j_yZCcL(HdcdxK$Dl_rP=n}h2%#OSpEU{>U*xe>|gC!PC zV7S`4ACtQ~C4~G@RZ_ti4#U4Y*Y}>ADl3HBc2~I4fz2ljD3R>E_{&_#$U(@ z6EZpB;`vzZ16XlO@NCC(oD(it#R(Gu`_i{K;j*!K9>MbhCrpavgvqNpAs%_-8#rM~ zfD@+P$_bah%L&sEHtjx6n2z^!z?xpd30EfI`GgY^7IMOjhw*fCLgHRdm~|(fZ#iMM zn-k^$=XvWmVZlC5aI|uQvzZeX9^{1NpE=aUf+pab2m;YU1B{dPa?(?wFAR60;ArNBbAy7Sl7~(k#R34c2UT_K0xL) zcMZjjXHMv>)S2VZ`M9xX6m(TQr%{OZVZt!a`Ef)%w`V*;mS`U%WJ(;7&F*n(SgX&= zo)pAP;BjztOV^NGCZu>my0}Kd;U_VVQT_G z_$C5D=+$$`FwS;{WUoTSqYK?l-!pTbiA_D) z_Zm)_P;k(GU>F~x{T{f?3M)y+rZ2FU_DO%mZqr9Ge$+m^+@{Zsqe^SvPPOT`#A!R= z{9b;0gznZpP$t-P^fUDc`oXF1z-H>*lHS}aTq7xTo10C4hV89}#7S>g@8h*9oBkT( zYVG3yQ2u_A{+a%j_fnt?sK67uyniDvQC0s3?-Qwty~u;GaX8lQJ0E$X^zrx#wQui|f z!(J`#54_F$liT|P^8E=ay@%7X!gdhH`_5j$`$izE4fvAA@Qo%sF7-_zS-@SVNxb4q zrXbXC$)k84=Y*vL@Z5k0eZn=VoUqJ_=UPsDNVf0V&mQLoxr292|D#VfCK*gFgM4cFFPPE;)-;`+c!|xjawB2`?Jiuh^lO3=bUG zOi4vXH6p}!kVC#{q$uCPHcnpqRamWJe?y4i3}ewKrZD1ASA!V zsOL~F9-&;S{e}f&%0eXt=+hz)Yzt6sAEB(QK19IAYPdEa=u#9#N3l3#k;RvcP_o1E zyAbbCT1L{TtI9q_fmO9UJ6tQyro5pjuTT&U7v_-SXSeblyzGh=XsdOc&3&5NeF_E9 z@x!o+-50>KMRZS8+)(|?vzhJWc3(zGaEvcYavF_nx-NU%*tt>AHMd05V;eN%;8%I@e|1eT?{~^0!&@SH+#viJGpzP_#AQ`RV z8G+MlVi_?Vp36pxp6Rk@3dKhq1;&e>6xjo|jD!xy0bx|Q=MD-KJ)30DJ>-(>fL@O1 zNw;})*`rVp`j;0YLr<>yr9_9P48_z*o+>J}uVqonZpqWy7uaGnx92%@jV}`@Wc^U| z9F;tuQX+|6si+~KU>+h!sntJw~OajNqawO6oAmC)XhcCwpTaU@4BP ziRUHtN(#4Xe=OFE^c{X|S=KN=P1>sk9>)0ko_{g^DGvSVk)nQ3(x2}YR)jzAt%H_) zU((;AAd~U+?|Di8jRF!~-v4+9Lz%UK@#sPl?*(31om#u$b$F+X-no)Dk!9|?F%p-7 z`Mfvu3M(g!b9py=Wsb)#NHDI=TWs^@jqnDm_sV6}Pm)e{cJ8)st17lb_x^y<0U_oJ1{&!WD}kKWSkU`N-Je#q7hm7@PMx8aJ6^l0<&ul{4` zWlgQ=|6B6^L4}ZBb^HIJd{EW1<_Avk1kQx-OA8+uxi&D8cvZcaqg}I?iGeG{z~$}$ zRLl*P5!eP60dN(=0t!5EZD1t?!(4a~xXB$r`$gq&VN394^w38E9CPadNeXO1f@SP_ z0yW_86>h}(*|!~m5?t;QsMZ4LZ*IJg&5li-g>MO*7}%u+nphyM0i1dr7VrViJ}t0^ z0*Mc&-pJMf&6*QL^x2ovU}fqfOghr{5LRJ0g;Mm1a!!p{!ADCjR)kBi*;MWeK#=}-d*8_PK| zP8*SN7L&H28JDm?F(Y9}##AHENdlK3X524lYy?j0*x9Q?G9EV4(V3(EjBG+y%qUbd zwy~;*r=(G$nDMln@kAt}Cj&^`@FlXbxc|x-)cyugPiB8JZg%GR9CpR7&74g1k;h;o zR)Uy0PtKeZm6+Iq068+R6EjzdnK!vJPvmbyA~J77I+9Dk2xJ278@?1XJyNCw7ZW>w zCX_4C&s5!pE7G!%L=;;n)9%;^j^zXa#m<_O**p#$o%xcOdDxwKh+r^|&U^z-6i6JM z`2&y3da`VkN6fNISr|5(rDj3(qSUMyx8XXm)T}9T)+8h_DU)?2L7>WJxx}m`o-7Ql zZ}^gmqxl=M=w@f##V01t&Z>vnqZ!?-m*uP%qX4{a0+^lk3FplE8~Z#5$l3iU!7yk@ zY`}uCeC z{7;@;%r%#+mA+Li++sh>tdi;{B=#cEduDUVQ)BC;TiOO*+tl4w&dR}@Ifs?{{yr&8(GER?ETO~4af$_C{@ zNT#u}(WbZ+EXODF;wHlnPV6R9w&J@muH1%H40?YSvUmm zc4PeL*}!5Qo`+*ak6-r4@c!C2OW^cW04Cj*ey-=0>Mq&yHpO$i=j#=`=OF} zEO~dTHp~O){ZrM|>IQ5V=CvMHId!wKcNjA=#OEf~lR7U-W#X7Wsn7J4(Yp28eL{w$8IKXsj^Ld+g ztEgSe4va$r`rg1*zY8j^x9ZkZ{VIKhF9Z`ImZ7iT0uO5&eJ$Qm=wmQBz@gtS>W@k~ zxbOC<;idtf>X{@RdYw&gk@QB23>()^K#jyEy7Uip+?Q~Ic<5gl;-Md-^qj*hh+dn` zdxq?_BEWN^BsjdI?A{9v;qhLW{_iFET_}+H`lU=)arSdQdm-j9c;3FfvvQB$d z(!ARd^fpXy#Tz2mNqvyh`wp*oKc*N|#@FA#*>|Dul8DgReU~Z^5p>^71G;bF2;bEP zblv3xT>aFZC(X{%fjykI|6ge%ps6VXW5mEjDKH**)tOCsH);AMoNHGF}iPC$S+ptY~z zCkHRG1TPAbB8MIcP9_M<@?|qUm=olkK^%1&Ty76Kn7F9H)L!9^Pa?BduHfdN1eWZ@ zwA?^GCa464_CuotgH)zQYJ<;YYU9=p86LJo&;Csx0z4^=A?)%>oi-IbwuVrQDe)jbHuEXQWmB@ z*A`HlnPW>n!JCDl;o1V3y85-xIS5(v%Hi+ z%*v6n(kY^ENQtENM$#5zsFejnY;6HGuQ%&MBjyV;=64q3$Q~?apDSgO zIZ>r-3>Z+Q>|Ucv+35A|tPr!0uu~_@DzPCal743-{nbD`2YSe?QqCwAlQY4LAwn9J z&4FPE@Hwl^nEP2wf;WdqhwuVJljoGNa7Rx4h@72FYj|@Q#l)P0QVwP)fcHrQ(VQQ6 zDF?c7ZGlxEn3@}(J16%bxabMSMY#@mjGtk+;0%asaxohc=8xRFN95jaQZaY)h}=hv zLUYmatouUDEs=6TtaV?UTxjloUdnxjVyyb0)NO;d*|*<~LZ4)XZW{>?OgEn2HXiTr z_n~cx&C(6&1e_CI_diqb&+9orrhw|S&(5BCb|*@(^T3%8M}mEhe5`CFfA-_~nT zaND!wp@q_X{Y4v4(4+rnJR^TCJdhKpFQ=(A?); z(Ax?Af-X??puONJrh$hPpvHGk0a7U6U+^WxjVOQyb8a7ulLgMve(Hy5tnDKyT-tsy zHHe_tOzappf0p{tXMorE}nqM<568` z@myXkPLYZiQl_XbwD>kkXfNJubfLJV7hcX$oE~d0&M~^s;u;o4U1;%ca*D;Th{Xr& z#gG3lU1%|w3P7j}E&c|Z&QIz>i~qC~|5_-<`atJ^_&`RD! z;B|5Zb)h9+Aj{X(g_dCc=AMD*LQ64Xzb8I$wpBkhwQO?P%nCnB!cY?JU6uq7N29v3 zRJ^t4B3gyx%Wgu562okSwPow*EzuWASOonXWe;KduSY7|ijvtvaA=&nv1vI^D#QHE zhIhy&hT%{~M^d@Uo-8|Hnt!;^bY9sTW#5&N?lF68sSG%8cxOic1b^9Yy~4dtv0QMM zVG8tKr!njul;AIi%-!p>mycp?>MjQ_-0S3An>kn#@=3z(ZuBp zXR-VtPdTRU@68I^^^Wp%wLBXkyD)exua1>z=kA7Y!4qlay$GH<9^b!d1S3}b2csFv zs@Ql?O^J~!sQJFFIhW%rrmo;CW*{{Dp{oKyhP=*-hj^tzCbv~TEwyq$<=K?{N>m#g zOR;Yd4t(0Hq~Tk%m{m?ffc89a#xgR4+Ez#946$;7R5`m>*tj@KIx3fgx{k_w#ma}| zN_3YSZ;g_UO8Us^sH~2)SMJaU3$Q^dVM}hjb*xqjt>LVEiCU)etI8jvTBh>vs$o^o zoV;AZ5Rj@cy}5BQ%?Vb;*s3mcS6u-Ar))%m13jvy!*^)>?5b28K2vpX74B_QCPX-h zw^wb}2SJ6ptH322Kjj=%ep^+prwR;mpU4=5VAPs0_H&8zs@|;nvFa0)Z*qpG>T61i z@?F(@^&sFyOR3{|do@1#0 z{jq5p=L#|1eGyRE&&`@2a@#_c_E2u<2I{XvB`mLUap)!sA3Cr$bO1B%|G^GBOi-nT zQ0Glu_R!}{u%yrrEbZ*jKiH!{)ku2(+S>bB z(pg4QkC8NJED)%L5CZ$zwdI_nwpFa{QEEFWfmv-xp|kcNs?B7v_D`kuXNpw_d$|s} z4K)ni%<*-DSMYV`pbgBag}PCgTBu8)sf9CAcO2dE>#m>CN-wfj+HnjX%!2WJeSf^8 z1<+DI93f1lV3AHeUE2b^S5GTFwU@|)K&DaW~qK71u+5Oo%LxXhxN7fJEP>VesBG2^-rTJVL7aSiL#I!*1v13|4gm_ zuvd6sox$mj`rl)fdZ^3${{))`8X&R{EFYgZy8)|uTn&pGmYpP(4a=ESstvHWA6SRY zSa;eQ?$a9XhOd<&B{&-NSfv5xi3t&Xjsfur$Y{em4Zk#Cq#Tw}tpT?F1FaCz#xsZ< z2A8=SFKEP&e=4KKct_(*d*fWDh4e<~#|KXts|+Qf8rrx9KKm*5#tn=Y^hT($2T$P~ zjRAXOrkMdV4#47twr4c?&2<%+T;5v4e$U7@g z*k{y?JG&{+zVm7QOe{#bbSKjzylv;9%j4YjG4G)bLk}#s>Sv}l-_X2v_f!bV%gBcP4^I8VCT-kCSa?7uv(EXg)GSSmA261bGBfv($VtR=$7Zy7O)db-$@`o zjul&eP+DM~JT!r=9=Ej|8`AP4CFxJozn%11myB>{>!}c9de4H=X?Oa>iC{G(Y#4V;`Nbt8|@?^{M@w3~mhAL>gt8L>+s-SHXQw1K{ zPqPK8piQ^6WvaBRW=oHu3IL%E;&0ut@hct`tUd;2wJq8nKv(gT!;FrY-aNYoT-Z*MhI?PIA7S@yTT zW2X8Q-|;#I+dFJJEiuzNP{hOi(GIMO=vZR!n9Ddu>u|A%J}Kz9YX#r22^BESHGc;f z0R^MAJ9^}f$I-O7u-Vb^W~|upxzd5|&un?E12sh%q=ft(|CpIrd7aDbo%4y+VN&ej$qSQW&*_xjzQ=Bu6njRKmviiyIAYIanhA02SrBXA za}{eYY0ov3%QP|f+|Ojfv8N0Ps?7vVECH+w-nr)hvHqSP_dwK@!LSc3SZ)6o>j&h$ z94m&=cW;cccUZ5mbqSf@ytH>bf#7NeaQxnBEBL)LBcyfiT?pyhyNbH}!KwRR*mtC7 z7r5h95Q?|#`v4wB#eHAkZT77Deu3L>em}gNwI56Gf^%-t{_fon0dN^P0&v)Omwwn&fj8`X8J-bz2>@K!<2N;h?-4K6d2oFQ} z?vAzH9W3=Emik#fR_y-T*8RD?`-owpb)&aO4l>aQowYp{W=thxe-Ga?d~MHgmOGwu z_h5@p&lUEbORAX_)-(CUvU*b2_N21ZtOa^*Me0rVp0$P{)&mq96B=F)!lmd|27m@xbGk>dU= zX+PAAG|Z$gG~@nCX@4;VnVNBb8?nd!SN0!?(v15*+5gx6Z>TtPgtGq^$^y$M!Qacx zw7{c@aGc@BpF!jc>qq!wZTK^uV!*_bhH{RQkqdtU{2Ry5hHEJ{N)V*GD1{x4t&Hy} z6Eryvj&Q)0JpzBWG46+>F_zM`=)(m}y1)e`B55)l= z2VS!$G2H=2GKHg3vsW7W1Fl;sh;zYpA0Ar70!FPlg{M>=gR|iZvQ$)f0hJx1k}6Qy z+292wKEm?|cr3#8;7j;lLD`h=DCPSV1fTsaVC@Za6iYP6ii5R)!kkff#(`9?1IRF{ z&YX!TWDe#Llz8op&@J=enStjzJPuIP?0Ero4s^P_7e)!3Yw)a(uE?ARSw%bumjMcc zT)5JK(41l_BVWZI3~!WwqAD_{{ltpQdCsWFoX?PN?f}aC9r$PtY%--wDTl-psJ{sm z=EszO2wg6;ip_S?{!>=bxi$a+Rpw45?Pmjr%w34*nqDp`4nuIwTy%w?l`M$X4S+}H zt^!xACyl_t^AJ3i2#0Vyf^rZfG5r|Xv4GSwNi`t0kx)w-i58u^FSNQJCxAufVnFMD z1%#UmL)HDB;O-eG9RjVB2EhA+Jh=LKt3C|)B~8MUh=)GN9*N+Wl+1#driN(+XY^a@1bWD1VE?Z9e3RO#bS+_w>$F8KLA5c;@Mxdh)tom@O$+2E;9>mWv z8Z~(XuS&&(ic_X50GH>+1YSJGF&YMJvVcz9NX9?G=UO~OW82eE4wS@mXbTjG# z)&TSF=Eq?g8)4h=l$ry^H6&v5%8f1nt{MV@<=|Lx0^jqf#=NHxRG`quO)hjBsypu^ z9@2sL?N34~`T%|3V)25;DzSY6#c-EV#F$?(DN66+XX6w^CmX z7tBW#4ix8i5CM#?mY}`>)|r0<$jpDaSI~yCwG|0ocroXrUO_;9Vv{@ss(ySYAx2^C&g7 z`GQtzbH`9BVvlaKpv^A?BQ1FDCNL7Nczy?{EC8}-5eb)`55j+5Is{R5px@D^lj0$! zK!e}DV3F{u`g!NN6;qHT+u;DRI*a-KgGdbb@PEOeT z0Vh0iD<^E-!3mEZ<8YfKx|3Q?@XY4~^(;=%$AErA@$|cT(c)D2HS7jM`o){EDCiNC zxeZ}%if3_faKZrnTn-Y1xiU@-a$GE==T2;yhVNR6$Nfcm%o5LYo`b#~Y&U`*w`?xQ ztDhdb#Phe>f4KG@x(D|L+U&&22XM~9veKWMEP9Nwa7ewL{DM`#V2L_gT}aa`0s^qx z#KopuFw>%9!-A=5Eb85G%Q)alO^>J*bt}T$J)kvg29?Han0Hb0DeyHTkTVVgW4WM@ z)n>#=IP64C=aOLn1k?k)f;T;0eGLTzH^7$F*AV2uMS`!X%o#F!hr}55s2W0k&J3rT zrzZ?k|BTb#i_!YK*?J=lqj+xur^hCUTAWQAjW|74&L!jC-J@tT5qrIR3nEwAv{WN9 z52JODww@5--LJW|N8!5HEs?g-YCT#RMaaik!BtLeFVa3vK~{a#677)owhzNeITz8` z1oHuTI4kz)e1W&2r2FfX^(4ya#1&!6>9hX)h73mNuHS<& zg}@`>NhH>3h#y7bbiKM)@ckICW40E!v7^=~ZtH(u}?%k}L^ zxqd^g-`w}GT>nL`hmgxGpEae+dzKd(S9_1KZ;W@0TLCJPcM6bw08;DmqFeVpo*;TR z>fW^g&?x7Eu`OsA5bb{;}CA7-3!Wh9VhrnRv=&yxbv1MTNICb4rCc&xZp~Mn@w#h8F(9PV^Qki zK8bCVJqQc4jq;4aAqtI_!UCtfYXmY`aw@p&N%=8G`P$F~0v35l%CEhGf2T#xl-*~- zwHM@bkAdSLc;5~C)&GfpfmOFJal72hJWr!t4c>OIgop9AdllX$Z@V9b`y?dY+Xx?1 zE4Zr+eB8S!(By6R6K3EW2n_SF`y(@uMC~MoH)`WK3;QsJ#dyv#Y9r@bQ60~Dy+R&wX%smGvGE_#;pv9a25*aJ1^9_$8cxi<1QXRZj2|(RsYH zIUz8Gg;PsG6OZMV!ewgW%YZ*LF{Kss3zw!YS1K&p`|ttnOOdRfK7Q%Fn}#dfnfm4W z=@XVpJ}EF~RG&snVc#Y?ek_6<4J z!nuzU?iT5YOezI(Eq#EuW(WR|YojoWOZuL!)z&^Rgi!i_guMrR6vg{LzPpzkgkpsS z!+IgKC}P>aID?EpA>T&z{M2w;>}%e9xPtw7#>Xe3SB3fE?k{hqAt zvI(Pht!q$QSzn=DJK6Qq^b~!eUIht2mS~Ol>s4^j54ujrms9kmvi@Le;wW9^*`(>| z_FU=U+2(D?EKM(I^#e7E==)ocvQ$CJ?v3YJV5E*%oCZ%m0_mMY0Pcr_WbQ@*oi3)x z1n++Zp|2qH#I;q>lXnTiJhYY11mPKUfJ-Pc$>EUc#u-!a4aE6N_-#pqDKKohS!LFR zbpkw`WjF@gV;qMdSB0wGHcDU>xj{!03W$t3bVsYHgY^uAFg2J8bmg(jf<`GX~ z7zjcJ4)dfZkzDxM$>@Gdj}U2|VWBON@x43(8y4lcl#QThbcrCttrniEB0YWBFwY?Z zvbaRgtzx8S1jAD6ZPPsyJacJ#tkDNy=tdu~_sXIhrAY}b3(X(a2k_iYgBTC)iS&5b zqaWCQD8LpM_H0hho#`4Xd61LYXeg5o;r^&;A zka%=le@DC0!?bOr2hwF%dgs<$$*6XvU$5=vVPjnBx3&q3cd|RCr@x=R*LM}j9}R@~ zAnoVm3E{>ifaynguih^s8Yj)akuxrFWrVlEaTh70j2*6wp;{%nk{Hinhu&MxSm4T- z(HcvSx?1luIHM{RYm#DG2Ik3VZBoTY^28w-Z#y#H_FYDqAj+lxmQlDs#2hqsD>ccd)_-UnSc57Z)#QC_!cBDLm4?II7zgLkFwtqVx` z$;Pe3clH3)nfC*m?cVcX`?s3+lpWiw#4ZIv%8A2MgXgp$<*pW_yiPdB7(hrk9&tK6 z2cbZ|!21gVa6cTROhyVbsLRH3((QuK4X-#sKqZj+7&k-fqV?)&^lv@p zETG#PKSS${zgfWU(5|uH4u^&gHO#n*C)Ge+nBArX4GJdA=-)Ciz#IN3F+L0(+*s=B z3d-ObLtR}#16<>Da=nbtpZ2!Zmgr;&GqnF`&r^rTzafva5E}3OsDO|x%!NcGX)CpL zu<(wyWF!vO$Y>c#z1(}M_C`P|jI?JMzQ+s$fIq7mCU|UMKfN33>X@uwBu8A6kkaCxvV~dy8i=@&mIAc7=W&OV{{S_^ON~f7xmzbwj{X;?! zf0Fg1vVO2Nqsiuzf_^^9eU+5ix!0Ic9LaD|cE72)w*{o4NbNG*qMhj8 zFY0dexkYm!mj%BHQc*65gMKa0A|z97ulpL4fZPFzUUO1Q?QgIf^$)pl`G4 zD+S?kRIVRlyPAu%dJs?uwI)M*z)IG}!v6r?_j7S4b3!BVGIXr4V>LY9BY6LS_ZdV* zGG8aWWAUJq)f4Onq0evWZ6%4_o$S8dJ#tM~hv&zZh7l3QCM3HbaBH|0fn*EUmAapz zw|Pexo0#lQcQ^O+{A`EBcut0~Ny+Z5?i~?Y7GUVs!q}8#_ip#Wo}OP&T8>~)7@L}G zJZ5M;J*V2hrX?FbqoSwh*EX=}$!2FWx~J#2Hn17V=C$VVo}SZfV9CiG|D; z4Hxs#E+0)c8_WiVju-a8dj5tvYLegc2T>xJAD}I^?|;MNdU)bviCC9snyxxv$$Dl5 zq>>vHk0pDamOYQea&d-~@g39Hwz*sJG{_#m>?z_wTE6)ozIQUsv)pDBscD8=$vs=OZ;=O z3BkxIGMm~$97j17vG9FsaLUE9gRu%ic^Z=hHUrn1ut}tAO74JR)L?6vZca8UneAZj zvF~t`5X6Vue<%G2E>1bX6QJ{k#PXk=L;8m>0YWTtvN_2aBQx&KcoI4M#S>(t zW<1$0LB>6zoN*5?FPq_H_au97^xm8U{U5ZEykp2icCh4y!P#OLd1oR+%td$?0T{B2 zypP&IvP#gesj;4OP)S3)=?-st4tf~=OT}IA;vL}$-U1wkD7CE?Z*`Evw2bWX25fu9 z`%VZ7*ipMb^pP2IUiNhf1>r_4-;J@JzZuOv$i6YWHU+i_;Hj~UTgm9x?t}OFDBt}) z+#G>h_8F-e!H3V*ma9I@=9Jw`eXehV-Pbb-W>bRisOI|tL3a~LSqpjB>E_95PVtd$)2*qg^?b+BR4*a!x&O z18h3(02xR}BfiY}1`4Y?bTU?BbB^$ZK{@AGFczrEy-3TA2uS5$^VL{6x3`*m1-$F2 z1Xz@XW%xjH?vuIC77Rh{-pYx|RmsDDG|o!MO^!MDfbmVvE#~p z{c7+$hIJ$pDle7;VQ|1bvc-LU-t?%v*|_V6B1X_HXL-0)jtfs-y(6!_fY?AkTX>{| zyq8>g>+QVrpdp}o81}jY{+XP2%$4_5utyxNpCn1l@8ZfA+jf%qBT#dl?IqY6n z;Zt_69*bHmEK&=z1CoC^O-P7Z@j%}tJoEdKi&BdgmA{YFb^{O{MN7%sl6gW=ol^9g zt7ti2&6bN^j`f^jvs#w3A^t_DmE!KMqBC}c;;>lHS(ef^LUCHOt5|KgkD6U^rX5U& zhf5Z?O6-jka>=A%Dl+S_e<`Wtg%WqGV3wG+V3uUq(U5k9TG9}ZDxbB*vSg!876cMf zUGiPY4{Z{k2quR9C(7cK(#zD+u1LJuPF#9rC^1S?S{JR9{?}F7WEZD&U63%cF8GB= zaZ1?$S6OE}xU9P!Y%i_U_X2{l@vgE|yRc;s+M#!#6(HFuSJ@}QWM2od28$b~lwaj4 z?`j8@8gwtGl9O zP_cAHu`Bw=8ZXd@h+QOC#K{#mwdwL6L~v3l_+nSZLiejwT@_Es6%V&`dyo=}mlcY4 ziL0VH7;j@NH(@D)t72yx0zPcxJ`^P8QV`>Jx%^@JYRbeP5$shk$pilo{{V-7fFHIS z=`%kxK+F8GE$~pl{-GRIKmSB2=1IjrJeFOCl&T-|M%9Ku2QbY_#7b?+T=6drQGGcu zQaSv~Wq-Ni&y8gm+yJ!LDD%D(q~Ilo|0O?6IZnY^y!A)WxR4ODI{r=Ag}=$hCi{1) z{y;#gajJQ~tNZy6AZWMhf0rOeIidAkkIaO+WG72Y_8;;8P>GQX7 zO_KBe8B-ON9Yv+Gn_7t(<(dchaihq}C@nb#)BklZIN5{AmBT7;udIXGeSxqzDo2xt z)_E(bQ!pwBkx)4c?%<_iV&%OQ;77o4F|Cs3D2BW5=PJfk`IODk$|{Fa=}{|Hp~hxmuX1rg-oKb)_5lV)40a6F}| zzxQ{l<*L|N&tGf~Qa+SibAQc4%cGGJmNQb;JV72}M9uSfvmTssvS+b7uwzn9PE8S@ zwC#oNmZ@1@gBoF1P$W^VSr^M9q15LOk9O7kA6N8x&AxzCTO`!%uK5z}q4s)rB>FzR z7Ha{uMWXwetMOH-xvttNZS{Puj%LwIul)~Ci4hLI4Yd)uD6JzrrS`C^cC%IqT>WZy zBl?wc?T%RHLguNW-rH5XkDqgu@rfwj7VIM`W^F?4DP>uhTzk%4`#Z4z)&6{LT>3Hy zZ7svT&aumOEcC zBOon%Tu_h0gHyvo-J=P0m*Ja7edRjEtdkL#8OpVoA4MNo_YAfO)|J&&VZ=kDbd132 z>g!!duhgwG>#(r1ER)VdVS#fBcFOO>_mezzZvuLd7Ca*B{;wY6Rk}@~UIe20#QG_q zx;GF}4b|UY|0uke<^tYfu7r9uTB-M{^#)4wXmCYtah$8Zkc*sJUrul#e#EHyRZ9J~ zZuRQ}Qr*qi@k$@92LW@)M5=#Z-vw`hkWl{(u>FCr7wO0owtM+#5{rKG z9W=kad?I;xD`}ZxL@SmOmcJeCT5dN2dHFt@0J2w?AJ%r0`9~k6!At|UR_@{(1e#)8 zO-kE_(3Akl?k_iC{DbixOU7tFp=oj-rD?w0G(8AwsTfgdx<8iDHa)HBk$_ZRBCv-qS&-1MQlQoqm2k+6NcNOxd;Mu zH&vd}^qH&ajkaVqM}pe}l%{if)7gO3@JJ65h5Al0Pb;BZIH|M*W zt#)*62K!><=H{SQLhf;{<~O+L$<6PDpz-L`QTKx8F+wS?_(F88ILrsEt`*eeSh-G z$5;Mm6*|`7U_^AR%p@=W*g7T@~V*>sl4jWSkKRFA{Nn~!Cs}M$*Y#G zdVJM-V7eNKMaQZa$isgiksm-`#YERCd&J;cRT#up7Q}`TAYlVh4=1nMvTEBJSkgv6 z8`W;|@E?(suxfv_vg)%~o{_+CNIyaOEP2f( zYveT#JJ>Z~TdG6jvtZ%uiR3lI@rMzB;8=4vf1@W|GYx*NFI75KJ$sBcZU}2qwK9mW zy5`=1)I@VNK>szp@Dr2aIUz{J)m5x=7Vi1JcSq>_(~^Fv~YQLD!=dJww+$2$&aS2{ulQ)yoCF4q0m-0RM;h z${%j+S*z=-D4MpXAq|T`I*nr45Xu%e2z}FEKPBrwy7li6#jhpTeN1#fA$Z-L0C~;j zzTS5YgnfW}3~ss{!8bD?-bZ!&Dc%70Y(S^G-4olU#xz2bo4LJ^cY7z?0QVX}aW@Qb zmm_we+YP%plvnX(WKG3jHm>+e!iaqTYv=p9?^>SkPe^mz?LNZO1oJiBX9Ciyz8EeU zQJQf%f^O%x^~=T}!{|-vY1m;HHg!Hn>eZHSSXl%)Ezq%5EZ_8kxAl zr_^nLx>f7i@YHA)jCJjKYP{(-U?iCB}kU z$-#y}rb)RVQ5Z{~sZY=!a_YKt*uw*Eyd;f>ON z@QsGRMC!jGF3ZHiI&OC5sxX`t%yeIkzvl&gli+ZVg@d<6cM{&z7K0j}_N(KH-qa$4w}78C{sd{i6V4umoA*gtL`m`TwtbBbLn<}9ie%;1_!+%Ka=Mw$;WUktlV7;E~>m(3z1Gq9T# z+9cBSvuyCzW$tiqPMWyPb&o=yYI(~$HZRP!hW zvD7%w!P|s7&ZcEq?c~TgN>&6aF(=oF&MJ7v2>q zApON+l==>9BqU+1JViaBML5|g9tHz9O+Ck}d2|@7NYSFTyTaM%P?$@*k&8x}cC#HP zMoR~d$`oy(_M(%G0d~TmJiN z=z?f%k8MUkWUEuOW!ehuz0i&oZJqXB+vs4v_No}Ez0S&0N+CN+E?O@?6j$PH{p#{7T*8+cE`8#a`VZ*gSR;GK{6$9S(5h3pAGuXbvvAja7S2|n zhGAxG;@ytK*37{r(aSSNJ20&u(v(zVwo{Q+R~L(^U_z<3WM)n{x*)BY9juh3*K#`_fB{ZYx( zxd4^KHq6yt(2R81f%)HH`60^27UBU{nHTb4Lt7r;CYw!jwYA#Y+UKI6la+%()E*6D z#DC};Ln931G!*n+^a*tCtrckA?PQzhY6rEmI>cG!<7S5*ri0dhVAz6fn;oE)JG8~H z#hmM8TjuJQL*w6qf!s+X!)DLH`Yk~WydDyvp9VVFD|7WYeXKqk@qV-8P1B(T`7anR znGS7jovWu}zvzpI_lq6xX&p)~6mK{Pd6o`i?wqR|dX_s1jHOCIz9r;=&XDwKyo1N3 z^tEsse-c|;CIz9(;e)Ay!*5agoA!r7*j(6Dug`V&b6-vNopBE7&;eY}jlB-IS`_29 z5K^c6F2Z`Ax7N^U0rxz>c(2uxksI1pF#hJnOLN0Ep%s63Hh?DeC)gh8E~mG4se2^> z@f~(D7^cr|#ju;;G*YCQ%u^|*uoU^;VART zAX8GolsD#@ADSPt`w*YR8n*5c@(7)966Z&}gG`C=Q0u;cDV}bCwP%Va2A~U=;z2+3 zuT1d}qyHCEJUIw7{{AN`J&lx#BmrSVIGbC=!Lx?~gWT|7LpjL~wn70Ilo8MGZP~%X zqgdx4JLZEOZ_Z_l*&_@UVp8F-#pZeP(3}M`@m60#YRpvG62@|)SaC4*0;GOxF23&~ z(sx*N+my1L{G%*LZS_QI_vV)3kiBGljqjtx;EOK_QC1Aju?UVqv5FP1(&pXQy0r{N zIWB=6bh2G@t!dV5YbmJf&Z)B&l866@E}%=pex9`0huN!6_Uc^gaqC4ZLlmf$VOOtd zWweiMi7}x1?YUMq{tf}_6?Vi@@=%$r8oYIW6kHHexJIznL|Gf`Z$nw1OEG4oYGK*z zwReE%ow?Sx*hdV;nU~s#{w5D0O7DQTEk3;DP`K%rke1qZo1h=U_);}~qW%D6;-CF% z(^#O567@sk06dC*D3;xWZaYe7SQ0LTr|E}M9Suv(r3GoB;ZDQD=Ho$6ikaxr57n25 zsQreeDQHSTtnipH5ru|F+GXQp@7>n)e$(DnFA1t@I)WrMeF?uHbcu*)YSSi~iOgV` znlFc&HwB>?)>yC!2+d@+wb2Jc^MeFvuLp$Y7XUQ=P7#_*DU>&Qp?N*r`n9PJ@Y2!z zCItjlB7fmpp~D1g-|(CNB3Mw;gYmHR+_V=fE_>UvtqHmkY_sy)vCSpaXNV$hVH8p# zXy5C$&uAaow(n@a>$X#F`hVWQ|LvVj`j2h*_Nrm|K3g^eE+0Sti+l_LsfosA;s88~aasEk z8rUL=983SFU>KLRlKJm~0sKxDfQWA9B%Jsc5;(UpZ$>tRz8NCA86vv5Jtg{PPD$ne zq(tBR|3^t{Ht4}OTX^0Pq%B?W48em@!WNieTRs(}SFmKTwONo}-Gb+LL3#~)U0=h{ z{k2tiP7Bhufq1qGQXmn}Zb8}sbBuPm3gTRNHUcrswjE?)Vpli(^n=;g#i7*r4=8D_SNiboQg=siy!1lHF%#Q$>8Qn@w$ROY)gWgOqUx-#rW|(?F+WAXx zaI_S2m1VM77;8qe&%&Y746}xUvF|!Q9D6`NrWUw!16-d{E8MvQt^?E(ckYJk6Kah+ zzr+qvmpu{D*~z|~XMSRSWBw)zlRywU^W!GjlJuj3;j=&|Fz5M;Y@Ud9Z)OKVEA>ux zaGqy~Cq8R}5bC)+qsha6yraT?3eO}D?20z0=M~Qa*)xY@3UyWqo`+@6bF%00SavV_ z)cDPKgC?E|M3<-BIOG(ZvS&RHN%OqcqIXlwWwPh3Shk3LjIVbd2uQDgta>mj{QAe( zBEYEQVD}LX!iZ7qMw!LS>{g!V;yPS8h_4P!QP@10&4``Ez9h!R7+vho84_c4$>#elmWS}s2RN*vXvM14t+Igh z-D}9tl9Ya9 z`Uu28uK`JlN*~33KzHU&PYg(JgzM=uC_6bll_!do(--p$_}ALf)4d41OG#g0r27#& zCS)PtgK9YKXdDpJKSS;79mtJcgc#?YP}0x4(|;k(m zvFt%$#Ae!WMrN)i;5H?5XDlPDQD8?#X6^&bdvCPteN6T~Xbap)W9LY3I_>ZDmdoBE zo*SK~z&CGXZ&mvW;0GVP$7JucYz=XLaW}$XPDl)U>QYBt&x7Z5*qbHG;P|Cp$DRYj4)4*}K5w zhfr40k#(FrWW{9>BSM9T35?B{*&~9DAbWzGoye&`yX=?k#$3x1Ir~{P8w&?-eX8ae zf5aGnpquB0e(b^~v6>^nr+B4@8}Ut3Q0^}L+-bN1#zp>bKk z?&WXD!+(%W%tv)d%K16x4}{}dr3T!bpX-RsIm13=nC}zi+>1E+hNlv86(#p7HMe&_ z+VyOxK_})8#+*}9?wz@$19|--{Y*J`66c+Np{7B*mgmWNv)VHzA@316?>Q~+2_nF_*o?rqUCHytx)&3V^9neRwLB<_U0bgf z*ijz5J(fL$GH7`p5?Ek|67#;L$%Sv`w`jRYa2KATd^qE!q@txo&~3plI`u26mXsn>Dblo}XWEyE%MT8z6qRd5 z1)-oqNK~9sv^>~6uxFZ7g1ZR(Kn6uS@j5H8@2DunbL^rh#m_0lPiw_kO0!u;IH=4R zhu1CcCv=EmPwK@byiDw=7;TeM{E1S$S1aBfNWiwxV< zvZ)J8;ibJx`?QKc>2*r!Ag#1tTQpn*jM7_d9CsL{n9qH8e+v$X2KHvpQA_VaqWz3^ zHkzeqrthKWIE)ZWE_JtWGKr<7BEyG5HJxpKr zGhX=uI~J$Zg{#ZX!}qkk!KkjQR_CNRWbo;A-Fdvati-xLv~T>Dx;sG8pcHHtzf-Ln z&XauzymDQNRyQ@2Y)IXFN8Nnvz_ov^gX+Y(`^3R@OKon|eUec3AGyxZ>Yk^BIFc%1 zgI8T?-S#?SuxB!lhF$4;9VB>9zP-ua-3goAsk-alZYfmV0YYHZeI1ZKe9sRN`0S}Wc4>vGQIvb!p@V`C%NmfDc??}*JGH30L+UXomao3{>_GA zm;ko*YyEEWP?gnxh<9t1)qf3du*&Lxf}2;_bS@jxaJiwA*5C+8AKgkd*5GKk1f!}3 zm)Zam@}og^1vCuM8lWaWx|LTz0~F*(W3k)G$&Sryc&2l*(wK1L|w+;|M(Cbg*Su03yy(&n%rU}y9 zTLkI720_}rT9Ec&T53;#yAr-YrYnt`T%x?tscho5i3GE_5$a#xL!mQYdRQDxrxyI#S=|~O&2jgqyVeDk8 zd$N0hlVuPVGOg0w^XaW6hOu8#-J9I+MzBnK7@h($Po)~&jL4o?o59l1P7%kpe@!)h zF&#ab*G`@v#(qmRhnsix#J;3Z+Zj#~Pp5ib@&tM^Is{H8Tp0U3mF;2Q^kmsBkUvtb zH?0pM%pM$q*)l6E)!Jw6OYewcIIIKwjdKOoL7E}UyeJRmLH?ix7nZfWv6fj)<>}{ha$1_W7AJ&^iMxS?p*BX%z)XD$$p`^p^R($XN*!a z1_z}5PY^C#E1OXzXEe(h%YcuaTHNpq<|ST}Gd6NB{~l@#%frVxA=DY4$r*cF;oUM0 z5gJ}~LlGmcN5;8WmR-PpADMXtv|Hv)nOGLJ8<995a}stnL$WDf<8(si0y*;`E%ROg zPMebH7@7GPwVO;MR+|F_n6G5|Vi~rhh*~BFYWq(M?5tp+b!V=!BNQl^8)I1kkMLhR z!e5Axkhw1!-zJtb4{Dj868Hh*Ot7n7jKnAG#D#L^c`ftzU^tRt+N4Xg;_WMYduZNE z2yS*X&b9RM;Yr?Gz2m^m!jSynqw(JPvUj%Zov3-C;_L)wzxq7AK}4N-o*7tw6Xsm9 zb*~?Z`+KbSW$zyER=9(6DY_Sy;>SBluX?`-mDBreEGweE z#*4wl{?l$RdY4ZWft}<0@LdutlHwaA`+94>D?-GOh3NKO!y{wngqY_W+md&JZ*H{W zdqnm2c+J|Wg)PyAwqkS7>UqJIg0q#G|jYyo|{!sB9 zm3?1mzWp5fw{f0Wcs0N54H(Y_NsVD8oab3L$XRh()=fNn>RZKxtSNn>m8=Kkthrj& zjJ8N<)F2GV@`!SlN6vay%fc)QGDa4Qsbx+llCvs9yvXjYWbKV%rF=*ua-S8lwXTDfz)hIkko$J8(^B1 z$=Qusc6BIb3@hgh%K25v4VQENh-F#qG(RkaVgDS=q;zVj$N0qD-k67pm2+cw%j|&y z2=#9{+1b?G5tzKGgrMb9;T*X$$U~*frF{p%&W#sAOw4^)?5pHHC+9w;<~|&d4rCkW zjXy&TCr0R(Tj_{V56QVjYA&`r+ri)fY3-p-_E&1|vfO66TZa|cd2J#O&ujaIdEtu} zxqATA=A{S;xnIb+N7Y;?k^^VSQbjeU=bjBnpIy=~uNO`LRmgeW)jXK32hLK5NWpp6 z+ri^;7f=^DZ;YCEM<_TUFF9Jtdq~c^N6nkfQ96yYp;92_lax})dtS3$yxRKZm7oIr za-LVs!w3;%AWe+A88?0<=2eLU@Mw7rl+Z5gxzxN3d9UWfPQ^Y*;%nZ!A|G{xxcT{}7nl z3;Dz0JtYWA{vtVlmYP2$6iQ{&^6%%NxYRr)F(02}%g^qYpN%qA;f@aq!B>=dN&61S z&lC0hynyt1M^H39hE>M|m3JMkx;URoGhIc?Kp=G^nCbe6Jp2a(IXo%`1&q7 z%cT5Y@?pTU8lZxAY=KxXu%HuS>r>F>6m$!AIpGNfH$?X@h|>$u%ss7hMD&(Z!_~Mgg|ZRT$HfS}TOqe7;XEyjv+8X7?Kd3de|g;h5IcbfEM- zA)(L{trYs@!d$&Dg96RApEem=_)_5)g_xm3-KGcw3O^R*!jI*`clAPaLOib7kBp3) z#T1g&!tW_pSK-MvgkVAlgcS8ribPwn4=B1+)Qc{q^u(S4MOTRKBB=2%-Y2<%qUUts z8>dB&QBtMoKbr00wTg47bK`mxxnr4ca8aJks-k>Ed{ZkbrTFYOC;L0KXnE19qVs5V z)c4?Wg7xI#KR#{Uqv$ns-Ad8BGIy}wIc{j1x$JjfhiT!>XTQRQqdQso?6lJoQi~nM z9m}v7s9`S}P!@M354D5h%kWldTgh;tIGWt8n?%BsiU$`D1L#li7xh;l}r%5B@+VDS8ppN(+u0i8EKYa7UHXY zV5iXV?AVg~N?t5^7^#CN)%B965!#iyu##o&l5}_;rbP``NpsG-4nZ_aUI|DCFPF3e zqvS0F;taA}vY!{4);lsvPEm4q3H0Vy566!x9o0uJov4>$-R!HbSbGqZ(j`jieM;#) zdg)w(k!3*Vk@fwcL8u=^oa57@L_w)rFMXb3c`}F{m<@eyRA~(`uGUMJw_^NEDc!4- z?$ApyGPW@)rSHq7yY$kX1fU9PIr{lOv-(*tJw~z3qnwbB#+F5tMVE2u`H@$bUKUB= zL|56>v8)ahsbx1({kY38%sh0hV2MskOf8#GHns9AR7V{UiH@>4^HTYz^^6w7D; z-9{9hqspoknp13q=tJT++iaOb=2zJ}a@p&xrfv*Gk__B3oGQsy%8tw2fi#DZ2Cd{l z_WP*vd!m){r{!{-Df6;liKlA$v!L-Ae#AAQJX0z6%jMZTl+O?=RuIvxZGH%x>2sWO09|xNQZm38VhpO z47utqwF-Th4R#7cs?r=)X;s-lytHH$GH0jb8VOhjRnKZwPapwb6p^b;{w+#7IZSLZ zC8?^cYB}<4;KS*ts%CqH8K+der&pm@KD^2v6zVskhLWldR(*>`g%v0)f8i6Azf{Xr zXOU^p@{y~%s?|;+kLE})*sOL%yQ`sK4<;{Baz*dB?r}-$edZu1Iz6ESl!+t*e zBZ3mDmky|Y4il%(Y1QZm4-e&EmNKfLtPswP2NK8XD!n?lB{^&yjy1CyB6;}0K!ks< zSAW(Tt`9+YV)dVxy1YoQ!C?IGs-OuC{jvWVK|1g#o-YOIvv&mP^JRkc<%@Ve6r@9Q z1nICtkdACXaU<}Esqh>Tqa*zaZ4Xs&c<92=$l8 z`Hd6Qk?IvU663>0_@z1k7J5q7W%GR#ebWQN>=*|_2w8}jJPHr9y3hB$@7v##ZMDLA zN=)-u^86f@Qy9ixZ3DYve(r(XpTpQ|cB~k-EzIgMKOl^B;OQ2|wj(Y`p&$5?I}_1z zeT1whMH+zTmM|7*L5OLgo8}kv$KMM`;V8J8zey3G{sgvz3ehqT1YFi-v~{#c!N^#m zv~RRhFjXzMDGFhP(psW7wjH}>&>qelk?R2XksQ*8WrmKbwnug(Tr+3VatAbY={WWN=e9ca*~`$)^)h4rhY=31e_O%W2a zk6;{_{kxj|LqIzET+pOi9GN3pvYLZQ%A?N_uZKD<*ZiFRIoIbrE`_qriOYE$*+QG; zaKq>gif7N^$MwpYPU-JM`V&s8_x!wP^E~;nn3LW|DI9qjh|MC&lYkBV=^erCRSIPTK%fmwM_i-W0y>0(N%q!)faoI)aqU+=KJpIs{+!oi;QZF ziH`L#t1&V=c9W<2cDyEl1%2mN7gg`9apSb-ZYx|&t1jkD*hNgJeg|;0wD9oi4~Yny z3Dw_{o0mwaMhgwiXVqZ7w`~c8nqCxJc>r8HivHlmX|UK}H)^dB#?|rF zBKuHp%!F%ad_rT5(zsS@tS30{;MB&K2@~CYm)Q8Gs5U~rkJrYJZTx!qq{ib!)kl=G zFu3s)y&bN`v(_LqZFTv@Je_NKv^9|XujT$2wiokL%V#RfAJCT10m#nAy*w=-{gBMF zS^li(UapfjK5;pg@0U00%WDvGr%llE6&w*HrQiIf;Y~?RFM*-^pbLqmP4nP|1NYEy zmeL_(r~#WfI6u?$pQxr6?cMTCD=mQe_oGIU9d03w6*_j)w^p?11ezuptzPSOGal{ zW(gO)468_B2RZ#Ah4*rQf*ooPqxxlEw}&MV?3?y5O!{JbOncZ8z&zvH!$`G<^nFm# zzKrJiKh^!qq+%{m_ba+x;*sqH-KHx1-wi)(!X^9>n%mJ>&y;n>kh*;l^xR8VJ+mR``Op-^$~D9$G$Pvqo?>OhaEQ8 z$HGzP8RuC)3XaWeSGV=E;5Zin`n#>iNaE*9JAv$O>$BkO-x<_)TVD(3EnPrgxAj}# zoZJ;nyZ`+4@2o$)`3h96YhT4177(m`71KveFRbDXSdYB0#x|4_tbL7bSO?ezHMRl9`@h!M2AYw$ zpvJgh!A9Ho>_!g)zvF(_MvHgWgV@I6fOK+Aw~bJcCqIr5x@|VAEze7^Gm+9yrR`F1864;>k6Tfz6%a zc)g?0k{!>$Xkxfj$5VLF{$9xSGG62;Ax#2UL@M{K6< z1KaN%NDyk*o3|0{P2~ZCSuOy%_dA=DxQyD_b_ITcB}I zMFr#G3P8krD{9N`V7y~kL4D=;E3l^6ajqwnSN>LCK|4JarC$mXga$KV>&1PPtygy2 zdO4t*Tc)XJ3(D3Tx^0Dq{`KZgyzNhCa%x>$|<$ z+#U_SzWR2zSGTtU`DJa6gl(()DBE69x4|y4$tO5^pKWhx+jatWO{nOJ+ddGrZ66aT zK4IH8NcEGt?YmGa%#rX^XZ3AVs^KlEwug!Ob_ms};qeLEWqk9rkGdVxfOcN!vMJT} zSoijUfK6>pHB5AGzk@*W`19yKdJ?@PCld_-d7=4H`{x9Ondw=et^Fl>nl7bfaC+akAm+v zK9&K+qq-v20+e-BpVk4k3rk0+IK6-Bu2f-6X>-ESoVI0H8E=>$0L z1G7iH7>R!mT0NadJLeKNJ&po*wNetG{Heh zf3=hP{-F#g>FCZ@PedAxe)Eq2$iR1Ck$m(W7N%EX!TZsbc-{>N<1PX3e-}~8(U`Ii z%?ZG_hllY)^YDF2C8G)Fp+YBkp}hr$s|4DN^zqr#P6R!3A@oW>FR(QcmwKBEtW7{C z5r+RUy@25RDY$)C2I%vEUSO>NS_J67S(pgolYZ@OOh8{lg8yM<;tQx#MTpYa6f349 zEKRsDSo!n24(tr1Y3z#u=}Z^)CnOB_vP*xS_KXAP$F2ml58LH|^L02MQu7#`pTg;e zEeYq3aF%u?YZ9yugJ*pN8b%B%XIytYBkO{ko+WL3g1x7wBP-N{2SLra1;jvIw` z^>l=HF^ck!>KUgI^up>HS3t#XKNJ9l<$(U9dd6)f3>Wf$+y{XEga6~c2lU_hKkhF= z)1LoaXkal0ggZ;{EJK8#)d*j`Z8t(|-MKy>o&C`R2bSmla)6!h?1se5uIH6UHkx z0qyi`A+PR)95`3-I!-_rdUglf1r%W67$Kq73Lb5k6kcl>3L&ha>cT{qNotKA)p z?}yn|0B_LnZxA9b2w_Dw<1rt1E{j4&Q%I;+89#&2%;0F^f@tou(L9DmHhu{r^R*q? zF-2&eCo~jdQV2&wT@R{%d@bq6@l6!LXqO#q^@`(kw2ft7W?*xw=bA7NeMUv+{I8g6is>3b>tCvOP1li8!|mInE8NT#3(O*#z61BBriGP(jnG3gIL%1FmfzK?Y5e+gK>|ovMGO{|bnN8ktigQi(@+w^$rkWk3n84G1IKMbn>0ZMIv9dB`Oknb z1p+kf4+vTq>Xj7eluJ0EodU(q2n6(`nh!PKDc8Z*M$Aa_3HC4sN8J&73!d$W63%rZ zD4+5s=$Wzul-H7}1uCb!1rNq`KIqFSd!s4Nm*CTsPXOK-Qf=VLlvS2=fIpgp|{$a0>Lx4I!$g^#xVaT!_x8LhVfJ7jQUS zHdWJx5mnR1K?J7V25@p4s-{g82|R0V5+%X<}5su0_&7we3 z2GhJqy*`B0?i;2pL*Fp1$?h90C-xP>dsL*@D3xQq)4Bn5H**A@i2-5Ox2U@gU_I5{ zOj!K@{Il+6EJ^goUIepT1pUyug1%FVRY-UalNp|J-0J1D zh9H;OA|9A*v-=A|58x!`%tqalpZ|C!NH|*-AvCjbn%L?BIhuVXU;d-Lxq@_bI-Wg( z^nDjRO@ef6r63)jipLbBANC85p3k>CX*^WYIJ> zZmuFE!{{i1VBM0IeL11@jD_d60om7xYIbbE;k<)lMu=HE?Zx77YwW`8+wu3ZU|lXa zvhRk2Bd2Q~ZRFXr{|&j1BcEv_Zvb*APA9*DEJDn_J%oJR!t9ON8*_#TR(BwO7Y-Zw z?iS<+{snnXXO8>OlPYbcMFX-b5k+jK(E3pTh5Rs1q zOxvpzY>Bn#BPwday9lnpEm&H?r*Jh{BS`kGJCh221Y&I-;Sv%G{*2ZN&Qo}tRp_J? zN@4G`LezKz^W?d^klHQ0ir_*+etc5lu)=YmzZWM}DV!x2CUAyW3L?4-7bD_Ff;BOr z@VP#6p&CoVXWb^6_@b4gmsNNKuI2rTE|p>| zmt54rU3iZ0Sy5I}e4Mu^8ll(pE4nK@#_H`U8ccDqi&`xjPSnL%(a?q7qWKg_ElML; zV$n0AQe+uL8VAz0slIwqCW5vpMMbezA1mB}8IhuDitH|G!0RKeXf0k%f;Fnm&Sh)( z!m@B-`u|M!Jik49R zyi%Sgmuqe6s=SWyqpmR4D}S~8b&%MPL;|)^`TOqjHz<^gdHKN>F;6Q$PEkC_<1}|v zlK#OB=@nwY(Wz6vioOoBq6?gNs1=t}#%UEU99fsvU6KwJ22Wf!oe6)FX)r)z|jvqg0QQt8Zx48`V=eLvcnhUO?cZTJ`v8STSx(}U%TD=0{59-yB%+A;|fi$1U)o-;y_5Gt9bck!Q4LsS|yG9pXWcg3>(@X5GEW z^PT612rU^Q&}(5<(js;zn;2n5*#PXHnzD#ZV=2rOjbBlz4wlAD5C}t+J&cwdJbsB2 z=SUpIk=U8gc{=NERR}n`#=(`Okt-oWWGQy{f$hN)7qKJkn6(h~uK*>kFg!~hnv1k( zD$W{2WQMvDtFMTqcIyV!>I+Pzyxy%*c0ouc5H=;2psF>UA`nb)bbSubSAnGZXy!J&}*c}QcJHG5HJ zAoDAjo3_m{PfW}F3}N#;&0*G@Mcyxb55m~8!}xABB5z%oHFuHE?R&*(-P97~%i$VK`!1a;k0-+HF4p7T7H@)~zwy zXDHr5J!A6#O(7Q_fy?ct=3X3dT)c#T^2e1MWglm?;)R%}=~Hml!bR8>_-&pCNQZNz zxu@VE)LB7y}`P(cwZHteFP=>PN1?p_l7 z{&=2$^1Qb*@4WMwciyQxJ3G5dqT?LRIKW2eaS}K4`{>HrG?$y8mjVJ}2gDAKeGOW& z91F2e!NatSC0nRjkDa7x8H*O$LCaX&8pp=D#;#JdjFp*|u`j8bLCe^E%w5w?%h)u$ zYLw;>?%l?;jLlQDjI9IfMa~@Splh3!fdO%QXy43C%TOrJ`j5ZY}St=FACu>Ds2{nt;Tv ziDKe0Xo-FbS|$#JhiREeHdRYJ(Wq&eIQlj%6DRS8#BHvLQxz@IIAO}fg{oq0RWWft zZ%N$m5PAkN#S+65#S)KzwTLq(9;IuWVlM_HJ(l!r(pyl>mnoJs5gw*k($qG^l4y?2 z8cY&~gbr0P$%MCXl3kNFwO1_Z08^}e?MuqWSvuJcfkquzEU8#gEU5(w{mPk>PSLeZ zF;hT#d3saEB`D^{6ia^%9+-~f)6bJK&r=G{nL7i;@m>Du*VAtxbSew=NdJRkFt<7V z41m7>?HED%jS{sn%l67y^eB@{v z%Td;Y@IXJF&l*NKqDGFMk7?_dHJW$L8ZB+4`9#)KhtPYOyVRT0OX~u%&Srg(-32Ig zq3ci^m26Zx%)tLd^dLUQ|pM zm;9e`RrSjM7jBv%IxUB_{(^fA1rL}DdIL04IZVbP(qS^4{0p8c@Wi_f*OgZz3cQq8 zBm4^%6wu^iHekl##mItf1$&_L_wa7P=E+Fcf_vX>8dwWXAoR3H!3AQW>n^wuN-S}t^1@BQRdc~*0%V&S zgA2Za`(v@-?~sBUgla9xqkWEe&B3Ga9u=YRp7sbs3m>9;I!j@H$RB~A8t55O_&CEV zoDfpzsbP8f70$!yxw1#$(l!+fmm>JIM`56rKwv1b#EXiGg`3QU>mUIY(HMdY_Ykb2 zlqyHJ<#=xy;6Ly~kM+lZG}m%W2eBh`7kLcB_WhB#i_}Y-1B&JrttzfY+0H{0?9$u@ z59@M@Xi6)+z)G`7BKLf_+x9~%Z3C^m=x9*^LKm>mA%>z_OVKfh&}WNQ0Io&Hr5B;7 zx#%p|L7b)NJOxwBp66fmRS`x8iTX}VcZvnIY!`8U#gpKlDs9qnI&<-IiWyuSfXf?0 zi*qp>T0F#Bd=TDfG)2^V)=waF$Q7EvmVnZwrR&P}BU?+LIWLs%hlgdWl%^nRwn}5j z{eNVu^jN9AUA9UcmeNXx(AUqIt^jqkSH{nC7|Y?5IXs_UtBduOQQMb~CwGGJUj-VD>2Dt?Iy2OI7D@ zKWay*YOT|*zPRLXKVio*l-4?Z>=!FIJI&Oof#z-J4E7%^_OBem1H+}&ROI$Q;U2){ zB~UA@xXW3^Ln`h5Met}V1=UqxI#&wxo>DbB!v2pBu~ff?tEX%Ad1YQu{W-BY zb2XId|2V6({?&ih;FdxP1Oj!_HTTw_21-GicSz0S@Y2l^KE3NxlT&lPhSn0K7s2u1 z3^k4Bni>LQ4eTx+gK0hH?+O0<@aM+&d`2Tq%zR&P~Y&bI?S zBWimhDBe)pCs=VggM4d;8EVJ5);^-9uvVGdhSvHr*xUqKN~=8wPtI`P+Miu(Z%At> z**Xl)lq~NVQKw+n^$Av7ZP<0g40U5%>on|jDt6t3cGz_i!}jv6D>u|N1lOTz^pB@b zglz!i{pwEhLqh7_A|X@VckI^K$5f9BLO1)cwKT=IzPF)%khQ)qWNhrkT0{MFrurc; zCGIxO4qye>k0n?x4|mW@aOYG%jW^Y!wF6@Td3VDbrC{r&Z2=AA8>TniL|s{rGU0`W zRq(*U^9^gMkd#i}*%dVGZb0WLZBPd42D36y`!>Xh4XNe^jJ^XFugl#5OBoufEDh!G zZ&K=SLyNhgfr6D61n?}2s;<|h#_@ckUn8cp>T!>8yrFTnwQ(jyUs2wTZCqe(oJ%oj zr#zkU7~Z&oLJf^8t%}Q82&gTM8?bXT+|an)+_>49oVC%c#0a%E29wJf18R`{=_Ltl z^fxrtxi+S&wc{nF1PzU^m>bb@Rm}~JZ(AEtLcq{oQMNW-BtOd$RUt#;*OtaFz*4gA zE^S0keVaOCFX#|MQx9`fHz%64=>dvrXmYhS8OZe?#mqODVoft$n?~QJSkqE-(?Tbd zp~+-zTEj4$iZ!86Yp+<7)zY*dEKRXZP>d9ADz#vbs>U}o)tQ@6HPswjo6r-Gj;~sq zULjX|9Rc9ibQK#~zqK@7BLrtJv^}7?srhuvG}NrktY$TT3=ivtnyR?mMuda!oV6@uxxn(u9H-7rWQY?W-F^jJ!W!3k33Ge zcPi*-PPi|L6MBvXy~hc?HgZC5Z;%9fpA+tP1#RGjK7O3gcM#|wPUzo@69#y3!oVY( z@ZjChvX_grE6`%GM2C8Grjxv>!+V0V(@C=6!ri`_va9`SicT->3AEhACuRF{F49(t zCg2M_{mFqZllI0{+O~-9ETlsi%=ZNbN8+QLnON!C&SZl#gEQfvKO{R2BKreF#^BR3 zz7W{~E^&@$to94s@2(lX@LJoiUQw!#-xV*sj+_H#V|ztMTxaTI;@u>0>iq84Go))SW4-H8N=v) zk^a=p7t$f#FAN(n!k!>Axrkv{Lx-|r*m$NqY&+;PP8d7^v2gc+l_Q;=a;8mOU^I2Oj+G;NN|b5mt$GQfy$P zDRO6DX}`vZ3yiFctnVuw&@kcy@j1F*``Q{521-9YP+ll63?~~1auB=fvF}FS2HkFZ z^Hi3p8th|cGRf&IQMs6SJ5*i`UClA_%f#HTGB2pi&xm;d9;`FS7$)h(Q28$~Z4C-D zT&FO}fV@{{)T?N!VMDUvilG`dq!zBjR&t$%D;6I(5QbcZD=vgwzrhtB3fIuCU3ht+ zQWHDrrNqFfz^DyTInJ6AwL2<@iVlBB5j7=hA5O$NYKV#!qxKo4eNqhTEXAn9Mrpr< zQGTg&)X+;wfiaK8JRK7RG&2Bjkko{jAcDdl(D3v%#s^P5V*JGzAER}Eq`mpD4hya; z#Fzz6p1U~-gM?l>5_tFo4oz|cAazc7|Mz078-vpT4}Z)L77u@Hl+02RFUAfu9R5u_ ze4PO)OSe#wW?Jr&mBad1&VGDm;A_2<8W=kw_L@fX*Tso~C33 z(jiK5p53HiR=24aM%_Ld7~2xt(#66Slg6Q1WUCBqF&wNM#?o87oGmN^>r7erX0Jr1mXVr=kiC}wR`VSf1x=4rGg8x>7 zqYzvXm=l!~-&cxe!6;mM_;4~Xep39T^jhd8#4li1bQO2SY z#Up38Z@-JLA-TgW|Jsdg{I|r5W&7o$e^Y|u|7hp6{hBbGMB*4P{O%616Z|MB9=vhR zCCr4?#7h7V3myqu>B=6c7UL@bo_!LnMkz5Nd@K%1PcuqM5aq&y{EviDoFg!8s0)FC zJh<_bk0e@-WHA9xUmr|jeSlq^$97E2!Q;y~Aw^NOx1--{_%Gz>YWhj*$g^udJk z@zm!Arq0MqW<5y^&PPn$(>rw&i^M5ky+{ofQiIcIlttS}mB?BtWGF862;9nWftt;} zdcpgq9y6rY^iC~x2*b~J}!K; z&Ssp%?INcBX{0(Ym0{TC2d3$zNUY-;(jGNRX;LRR#k2{%)5bW2hh4gH=7TwJ_D=Hy z&?z)Tsn(FTqD^c^@3aky811?2orcu{RSa$RS(;O)6^dy`+ofhmE779&PHRxq>z#J8 zEnd#E^!bfG=^iYSA$^9JK3PonQXy=qc`4ebZ=^Du)tw=xC$@thn4T@A!*rB9--SyE z58v1sOVkMosBR}h64GJ(o}J8xtqDzFd?OtWPJoHr|B>QC6YoQqhZJv1#I5SE8B#)6 z;(9n%chgJNfpM?LU5f96Iea?WG749S`vP7#u)pV5T%`=<=n$&lyk9)dO^UzE9FN{> z#9k>g#zimH1ZKRDu{a|GqDNJTj1A-^hzy!-&eqj9?>mFOr?D+?z8J z0olr)($xlL{F>>K{S6RNXapo=-a}rhN||CCV&)LIm01SsW)IP4J2J;-PS%#FaOBMl zF%vs^(9KEZ$_jGkB8TwEeON*E&s?90)n*A5ADw}idC-s3R&F)&b^hPr{b=S+ZABWNCkJ_92QX9SF%Tfg{A$ z5Ssl89J$gCTQ(}pBd7FIQ(#VV&d~zgw}dWb*3Zc&50z(50a;wRr9pid+tssAPK}Yq z0YgqJ1}7y)Ij=c{N255YL8|c2xs-$312yYI#GG%%oX=SVsY0?yN8-d>LCpDE<6sKS zMo|CU-nl4TDF?Y)$QyDWGD^9u{hD(hC2UKs2QJ4ssop<#axPW{%~x0j9gw>qbSaE# z&0UW0Ke+Iz{<*ty%|JT9!o^%!%teO|g^~UNDb7FlNN%RH?8MwcF*i#MwlzrczWLn- zi}^i_Ql8W)ydO76%pWf157y#ij)k|VBJyEm<6uMnRzv>m;Cx^5SZO?Zi0GgZWlScpLH$hv4K2xR|WFlrQENGI0odM&>&Zw8D^oE;Jv;G_Gh9x~2(v z`4{L5?nBlJSk{IXJSv0~+)s$X1z2h@4h}7Fqo|&J3Pv)GM@SWZ1wOp3V46dCY=B;> z3oN)+@NMxVKoqL&tl(erQb`x;aFvb$dK{a8jH73Kg%1}#2W}B@`2mGfDIQhfLaf(3 zwu=j&=X)$>@F4LR_MkC?@o<-m$B-|@;4qlqu_oSf487uGhrE1?(gz!gsw_oWH`@P4xSc>~mG_e>R zKE=>W^?}8o6n{~65^AFcQQm~&@5oD?N%3{cWbq=d_-}HQICHy@$2-X-Jsv6`JK|DsY@{>C-rkVxqP5IbzZZNO0+7I4@%T zg9hHx#RE%M=6a%fxl49)DHe60h?jrq%cXeSCsh#QPlnP<=F)Q%B2}<-KZhIXs!8~l zxs>&SuM)y#1I=ZqGmk5`Erzm3%w>bg%M^|yh5XB&Et?4GszumJRrW$?nU6zwVlF9$ zTL~{5WU(a_XH$Ts7=oT$P+B-qwamu5fedBUhO#5UWswL_zO-T}%L^$>MVw)3oB|~d znlbHVw3XE&ESOchg?gzWu?*EpcPC@@{^b?r$HA&* zb=0-|TzDWL&E;P@geM>5{L6p0V^S)yyHDO=f52kzihw6suPWO6W2zTE3f-!|{VBUQ z;C+Sj@~JRaq*Ta=Kx<{YII#kEqihz0_0o!LLq%n9MLxx3N{bbZAr;jQ zVdTSD=fD#NT0*YC2Pi5&4ypKnvFY?q_Amk#llI`lZk3$}R^F{vx(0LQDquZ`w&e({ z+)^1;`5tZp>C`YPnab?S_egX6VZx@YMd1vMVmu9L7Avd7N{o9+f~%#1Wu*hkSzfGs!(4e5O8zSC#8O3GhF)q8to*R@YV|41GpJTSZbu*Iok^{D?8aCKa^@Oc(}VbT=CP<2AAYBX2jDGAaAL#dBdZ;MrDELAUS=*s%| zTC79+SAAK9%t_l=l`~ZRV3e9!S8T2N3)0mn5Z~&12N|mS2UquY2p;TZU~IX-DF%Mk zkMoA=vBA}&iO*`7SnXq}MhAvWVgTlHR(PSztJe;!-o(m$Xmul=!M2Fim3Si{{8@MN z4RdufX^JY)7+BM*rccdb=mG_p{c8r3m+W8j@PF*jKMxIRy!in&)2&yin$^sO8qHid zmXT{#;-SN{>>Q<`D<^oO^@yYYUtKD?oJVZU0R znEUBf8nJc}JG3hNLA+nWal(itpiI!uobc#oPIzn~Cp_-O2~YBzFfxS`Mm@+09_gUJ zIN>R}lkesty}YvUg~BB`y6<5@YDGq1W2{At)=8&UmS6(O>R_ojI`zNkh@ZGW8S2l4p{y@xmlmamD9Fs^<+T1p4_aL;_L&+ zU5B{y$T+!uaHHmH9~NduZ5}-WX171X548K{Wp?H|o9*)*!c*^A>`QU^%xVw7<%eLq z375Y@?3)pxbEthcF1>7cYeg76kY1Ox7a)FF-cc4GBRIv!j%Q{rDx;(w&X|3Zm> zoyFHlr&l_-N!LI>_QjoVC#Z<~ZR}*c0REC+VN<Tlf|heoH5PK;bcz)P{CO7M zUnhM=;Tu3!z4TFA_&yfys*^sa@MO?2z4UQgI8E(6!UpN2FDU#3=ykpHNn7}9EPSX= z`jWyw2i??5pSFen#=_lo(lvyyxDSLL<8x>D3O5#x-Lqd&_yka(Uiz{vd^rn$R408+ z;rl_b?^kW%ihUo~N#9U7?7QNuUizjj{ACt@q)z&l!as9xE4%2W@0{T)S^W)rN+*4X z@Rfr=IQ#MYws58VpV3LzDSR3T`u*4zzLeoVr<1;?aOk%(TQB|G7M{q$y>!wK6y6BJ z^5(B?;cu~UZ=LibgYz7CuQQ{elTevGx@p0 zX6vOt+rp=__|NO4UnqPnC`^xUw-A@w?__q#jbtk>-;tXHSTwyQhq~8&~dI0EIy{u~se~RHR)JcC(_-xRN zdRgBVzM6$E(MdNc+yY9}QB#tA2bd$r>}f3`0B!$yq5xBN8pS34sP9Zo#gx40DO_R2ju_}2QUzFy>8*Gu*FM(6kj@U|WXm3NZwSMb={q6d)X@lPV4 zl=4YFNWTf`o!da6ePvNmnGFGNfxo8-^j0Ui&uu8H2xZS3D#|LLoFnPWps)JMeHD~d zl()CR--m+Ux1*E%fX0Wy`_`xm_e13KBxDA~_Lci9Li9x==^gO*gTFtolWfrV2Kcdy zF3Co#i8zVxl1_S;IIRw_RQ(oPzo7~_zL2nXIJ>d|%7E)HYPVyYWe?z6;Iq4L`{{W2No%omUg#V?2 zFP$R%9~u6Sz-JHmfIpY;|59k$2u?ap_|v+AMriocy59kRS|1hvH1MYlCH!ea9m2SN zs{ZqUKkYG^tF?s`zgbejUTFa|q+dsQ3#A z|D;MkaMC%3e-4ZvocQPOg#VF>e~$3KV)$PHKUu|JNcg`fTa zC;S2x|03bnF#H;aFrlA{zm)KgtMn5mz0dGbzWzTs@$Xc={#yCIPx#+3{BMB2Tg6{S z_`fMM-JO#z5&rZ}Aa@OadS|%8PXF)zXL?Un|4YE1{vhE`e-QYWRQ%<@pFTpR08aXl z;bWRIJ-~@S{!aK)Rs0VLe<{Pq&CtX#D*g(>$6W)XL{7TG@OOZb=)~W3C;Si<{|ezp zGyG`aC#(1?2_MDD=qx8)W%$RyIP1hOz7u|}ihq^xUuO6(1OHDIe-+`srP58#vWnqf z2IHm^|D!wMf2H7CRuTTs4F6|`FlnKRznbuGDKuj^Cw)fvGtfW7qqg4}cj}*KX#MkN zz@IUg@MjDLeuIi10Q?z`s-p#SbF3yhOa{G2=C zm#O$)6MhrJZvy@$6@LxkzpBzrPWqPNzXyi1d}n-cC;ZP<{BH@LmG2Cc@8mHm{)>c< z@+F%21Sef5{F(PKk6OMn@4W;5%>F9=b>Po@nDn3dFz}OAd=v0zdZ-k{Nk1_BNniv4 zmCa9PPQDZVEEWF;!e7qtmjnM#6@M+^uT?37lYV0Od%?(X;_tr`zO3T^MEFSzKgl6X zS*YT#Bm8WYKIWuf7=9fXA3O0I?u7q}ivJ7Yzt8aB2Y!Q!zn<_vQ)pH%PWp}E|Lox4 z(d_fe!qg4Fg z3E!LHdjo&BivJSfPg7|JC*5TD3&7an#HW`0f8qzK_%{iEBg5Ya{7WkSM#A5tQa&eP z{SF>1&CSYp;)mY}KVHTEi|{iUex^h48>8ZHBK#tiKH#KV48I->YE`U$&T709{wWpz z7U7>~_~(J2tm1Db{Erlx-IwxiW7g|o$w_UzZ2odG5k1(FtwkGzn$V3K+MX_*d_Q|E-GO zh461M{2Rc(q~h-c{v2MVM>)A0;m<+;Jm*mjf6kry=Q(QsEO!I`95=$BWhzB*@;wZH9T*W# z{0(=)-=*5;9>Nb{`iB7jPZfU;;YX=d&so|0b505v^-lb>JK?MIXX_=xuVDBU4#9sR z!}r%q|E{dqRi32OXQC_U@ zsraXIU?nwq`N8Fayq6Oz?={MUq)ze#+GA8{v{bqy)icUF7L{YHm80POf^BjzSB{6f znv*5kq+dB3&)8O2Di@MC(#58OSFxbBvT9w`mMXLvc`#VKP-P(xX<0>v4tuVhmVQ-7 zaO#C#=2up4uHHpww97+Sr0NKEU^||eSI2`9JOhztaMcBHcgUt+wVeUDtgKyH8&rG7 z`An{M9eFsM22i^dS9vJ2Vr>}Q$`cFTR2vDNav%U6UHH|e3mk8*&2pK5-q^;M_?aRl>1^Cj}q7KG+can;mh13FWa z>J2@?>FnPkwA=#;chru{{J@sJ^50k$@@PSJ*_K!jUTneF=}yZ&LkuksSz8`*2s5>( zee3$QjFS4RJhmP!woEWe4lLIAwk)xw8uB|_{=&<@CA0+7kQS7BS;3u(a?rkM%yLr^ogz~2V+rEZ)~(Uj z)=)x_+2>eV6Ip=#t6ys&&KYmCwwANN5riiHfmK$t{qdEcCI{y|6ud_eK_s(mf-0|OsAqhDtw0Tc$@SqrI}z}*w>HLRjwnHdUr4+lMo z$6c7OQ7u+g@P1lhaRQyh>OBr@RRw6|JsaLO9lRGPIv^kb0k%`*rNwpc4N8DgNAB`> za1$N?A!k}WfzPPa6u3}jwYow+wYHEmn0_3>Y;W4nL9gWZ1H(`1@8m1B2FwL&y@7KJ zvO8f1viqGUCXf@tNO&(m+?4vmm|4U`In8#XXMG|(rAGNtd7S(WDeC~C{%chXzSopW z1{Z42tdBS!xIS}m6Lq+LM>bL`8@#`@t8S3!8HyjwZ0GRSE2wfI@byKy??8cx50V0$ zEc?PedaxD0l-W)=i3ZMTBn7lFM(Sa|k1yOSqD zeMpHx@!4)l4TbMBCM^F-M;1=}jjGP1&Ls6WlX6zoaVrr}0;&Pwfw;^@ZvmcGVj$=A z$I2Z*lTOfyn3GPZI5^mZM^n)A5tO`FYv2jRrh7_|7xj z^JvGuCt?PMYM)f*^zwa3VcuZSqoB#i`A9W|dFZ8x!T#8D2q-x3Y0B%ord@~ zPBV<&gpmy@1-%Z8r!< zfZ?fO{HQQGV%%UDH#Cfk48s77`FDeG!#f{kB9B!u=0B(~I$+FqBaHcO8pit!V*p`1 z2SSfC|3zSUX&5sUMn?>s>;d*X4dW8Sa3zfOpq-#BV2sl+FlrHl{b_A(egwma&@et^ z7y}6-4`c_u1&r~CMD=t&j7$vn=fr4X7%dvc6^8L3VY~yn0{RCS-WtZ23Zo;&cMRh@ z4dW`q7zB(3E+E)-fjclJs2B@+DvS;o3;Ghqg1#yS)}N{E4k78#!$it1|0&G0>ekcNKhCZ zF<8I9AXUS-#xNctj0#XQ=p$fI7fR)_;1z|@5#ub=r*=1-LfQEw5hskqPjK%0wh|v+_35M~6h9NMFk%Zv`nhAOd z7;_Pc^0Iio!sv*xlwmB@Fgh`eQG~Gtgko5n3XFLgMySH*h{5{x#ah3PwMNQ|2VrD_ zia@Ud;{^=^9X&BRV$?D{YBfE&FpQ@N<1FYR=x1Qe*DyX*7#%S_Wf-4o7~L4gXu`OG zJ(xVGKQI=k7)$gDqXWhg9N7SNcNGKcf|Qr1fw5#D=wT50QhA|<@wme1i18G|cuLdb z9)|G@VfcaOf~Z^;X&4I?Mn{b03}d;9f%QGoV*)UO(m-_%ZjBjr1}kYQO3*1{F$_+d zM`KSE`$9?3>&R2k7b1RegM>{}(pmNP=_Mun2Ex|}6#l1?Hd{$&v>Rr+|62oVEM^H| z9odWSf7c9SFcgNF+7jFqA?})~YFtc5q_cEmxMl_8uTj&~%blVBn$JOBV>i|i*g%1$ z+PUU0g~f8P7ncI8#d_2&d8yMD>tG9FacmuA z-J5X9%jgz@gZSt0SuV003KP6Pk}GT-PEW%!4YIcGZke+y8t5|+YEZs6pw}jb zqU(l#+w1xg^%`xuzBEYHm37Qxb)@dbY0S7Iq_e*8Y=G7q4JTi!6Dxmhpbfb(zx8#W-f1&^>QVT`mazklp7Tya+vMClFDC~0zLk2hg42OY} z?^1*|-KPn;As-{D(ry|F@J$b@;OYk;Hep>C*g3Qc>H(Nd6I2-JwrK%gxtAxyLYuNd zrJ&`7Zb#V#;#^#uc}b!u z&F$Xcu!Eqm$mTWN$x+u{o`Xs|e#5> z+%C*)cA?yNm7}CqtI6#e zO$>PGkL4M*+ck!LR%X}pD1=>OjI?o6dQ)vVw7Rrw5#tfw2KiZ~tJ@XL78$WEjUr{L zk<{GIpydAm{q5j(U&6Ammi+E+#6Z%l0CwL8m#xy7Kh~Ug4`f(qaJ!#Ger`%{QX}6T zZls-{BcyZ8mt&-@og<|4%=fa9HfoNL-qp)~NO|v5pz)v|k?{aZ3`M`!pBV7aA5vU} zw;jI;4_fqcOt%nyn{=ary^P{*2JJ<>m)hcyWCTg>C&|$Bxo0N9 zlZ^h#k`2n`wBz0IIT84agYk0=qM6DYyzt?KHXNJjOb5rjMSyXVWGKeV6odJkue2)z zsO1B6UY2u^8^iiElDnkFva-a!qxfH0@$)hGo2e5fp|44Z%bCsaNdNDR@*2#R)FXOO zj8=h)aV?j70oJn)BI8&e%gaT4Bx&`eB(ZMV6{Tc-3v|)Jg>;5l&~nvMwxV?si~T9x zh7RRo{SnDof7Qw*xDyRN!QG{|sZ@f8fl!R{#y0CB1HlLBXE{^|9+#J|zRonQlA z3G@S+OUcsM6zmU|a-LpWClJgYvInCm*Z1bEhtwh_fYk)B8f0+-1pF@mwk#ODAIb+~ zZ4kC%rbD>}n*ll(mg90gv@ zOrIAF!NGc5$XTQr;&2EX?rzsXhrG)_Ov8W3m%JPMCCOVTjF9Uw1GQOQXcvm5AnN5w zP$YB!2v^%`o|m^eOFMKMv7i9`vBFy+xKPe%x=9ZIbFXod)?Zee8#OVKT?_J8Z9M~w_SMM<8AZeeE}!p1~8V~g~; zOjRT7Q}zsux`MDDK)<8Nm$TYKD&928+cgy>JYL?I$jRLSDcyrmsUM6e^#oTN4Jn)W z>;_<^hn=v}Xn4nRTyVA8!=PqT>?vCI$+H^TNsB1~cHS%$mO_ZXos!rA?Y-d#;G)|@)D9~zP8atKncj}L0dRZ-pP7z65UTY+oacN7@=4P2m`|iNk@WW zIraQwvZ-%+ZU z|AU@K54|>0?1#KvkSDV*uy` zC(IfNf`85xPMEs}bb}M-O$QZ#u5rQ(zMx3Z+ng}}e$WC?8t4;FSnv?&MNkRoCr()C z0ony>=7dE&Xc9;Uy}=2K?*q*R9RYpB2}=fn0zieJ>zuIk3D7oBJ?IuEEE^9B1--@z z%kKuw1jU0s;Di+eKr2AGpszV$<)a{Ata=6nodddnrhtGQh$}V{g<4u;U!LZ>0M6PxPcQkHFClhcaG!yUF5w%mRr{D2UmBN zcX8S~--1rwA7ou&UDE|O+tkx@I{845HOpGi*OCDS`e~hP39`O#z1COWjmk|jbQqc( z6J-6)`du(?6FI^9H@l+y40ho-om$U>?}fWvXOE>Qtgi&S8VSe{{InSSIF9X;_iG2o z$QFFBN8WEnr?B-+xDL<}a$7HT;jP~(?|gOB%fUgxIl(2tO_+#2hLm|BxH=e}82f{2 znBxZ5@x%3UNKnYkkOd(d@sv87$%QNn+1MtBdy0^iycl8)7ekxW$a0XazwJTWG|ojm1H$$YJZ!|Wp_Op*9(0bk zI2#p*vO@-U%ovBlgTgw6bq#xtbCDlH5Wa8J8y*%fY(QJQuqSSd7ZDU@4hyC46w+=6 ziWfs3QZ_8PEgs#KyZDC{h1t=4UB&4iVfE&)N{6uBJ{O&f7}jD8%a%j9aGh`1nL&oI zcP(LWB9I+>D~7$t@}`{nVhH=nDDOiYbJ#74&dE_;dih{bIEN1-eFrV}GcCeJ@{ktc zw0frInzYb)8p0nj$_JF8CHy&uumgL75BY~r3!km(7QV;xCK(ns3#M{ao^1(R5im3&EeUE!SWa0B8FqvPdf-5HgkoaZ`0#b zRS&&Uz&;-ZjKn@5O#Lb_U~|R5mR_E zVu~SRydh$YIbswA+EySk7p_;@5oczvfX}0Qi-=|B2;5rk>_qcwl!9K43W_)p@#?{q z&|)80yby7jJWPkraaA@fsjDrINBlf6;tyq;5ZBpVHXGe#i+J!6^TCGzD$7>+U-zBv za=LSs`N8L^!vogS;i` zApCL4c%qlngQCQ!0a0UMDVl=uLewzwus@}rjWY6Ll#wMVr|9L3ps4z&mgp|df{Hpx z9x`pz>$s`~6?K)|PSa8oi27MAsHlG(!k%%gpfZE-eXw59L6B7nDtZ8U2rb&J4K12f zYD4pjo{kTRPFD*mdIjJPp`i3~R#0?CbV&?8&mqgOH{~a~9$q+jKKeMWZ4*BXo;b54 z`kW#9Lv!@IfcTiY8Fy@O#$qtOReGJr;WKc=;2~7ZEJKW&Ii?p$v6FS;3^Cqf%(Ld0 zk;I}t%Xt(pPRwDa-}Z}HBBufZ=iZ`dcmK=@dxn5EfgGH$cL9{qxyZRehjR}XrDX^* znkzN6Qc|{)ToQEn)5D*}l2L@izp^WAa`^AIEW}d&w3?C2T3c)n<^C%6euuC(%M$B~ zODTt4!TCY4aj{8ptuSH);R~@PuMtlf7#z{7XKCX8ox7^~>aV}-LB|a9MFXd>C9sQcKa51Lce(_~E zA1(fs_;-+mV#hX%JrRGw>2VR`uZZy%jZ%jEz8n+%o*4hV82_c>JskakPXd?VmO#x) zj&;W2tOV6+!AK+=7brVqQMC-Ks<_*^L-OcgA55< zLlQQCag3_DAz_EpY;;nSi)WvNXiGvUWhtz}kdPjdkVLZ1I~dL{p@_qXn(&G;IdDt3 zgtV|WrWgg21if4sl(;x?#gW0#nx<;_{@E7tP)$hON_kOcMr3!vH}Ne);s;{lJO8zN z;x)zY=EOf8!huDjl6WDBPapmIaC5kJy8Nl!;+r* zUnP+Aw9}d{V$u{bX`Ev6_~;MCB$Jr5Qt>84U-3zbOtL2>kk*OLIGiOZ3+bFe2_!Wq zp*vAdPr|3sPAVl}PWpgUwkBP5203HrW?R{HN+BKkqbxiPYnaV)7m_ zd5hvrj=toRoSJ+hIhPb|Uv-l!9fC!G;ga7>ez&daCSO#mZt{0f6pJg0qQS|(K-`ZE zn4%wKNVzv8r7IW#%z!DqIv5aDH{}sa${@-Ts&2}dkQB_tECKDRZpvh;x+&NjO7mK` zlapQ=mF8q;@9{)wtCADKG7-Zt6xu>TWT0>woQ@DydaB zHN_!V#ZjqQLTXkjts@c;-Tri}x~YY{B^5)sbs1IN)Jl{<>T9X*{jU;8{h(b5q<$)< zUQ$e+8hu$z{Z&l;PVuHif8>*PSK1?K_mS4^t8N;)Tx%#wAnoZi+;?bIH*Kt1b<^gM z%GR_+xM0I+zHi#PL58%g!D$=8xW+7>*0IyT7l1=KFAPw7-{*vV7}O5n7TCOp6D&75 zAs7u1N3F}HLFq4~FTuOp69qXPc0fJEZ49rI?LkLvM-TOtGn9!D`>3dVDJcCg{?UDM zLV6*)q5-6n1!;zvUI~Xb=9RKBFTGirVWywt&FLo{Lhunb!%Tmjx1_%gZx);BJfxQ^ zgEAh>aL-ugyy?q$lsr^288i;ve$$sRfj4CM8Rbk=8FR)wKw+CytzNDQ%6Kp1!%WM~NK`L@EiEqw8_W z;^Zp5{9aIY*X&-|{?0r1?EcyQ0H!|}4|nd_uDnOKD{Q0q#cZq;pqym;5JR@RIUDne zP;EbhS06RdkUhp-&eGH1lIS@u^&Pa?}l zkuWc0|4bgra`s=is&>rjLGEl+o6E|KA2WpUlXD(6Pg zLwL?&qq3Bp10#gWmK+!%G@g@>d*@g`g3EZju@) zw@8W9V9BlM5a|s>`refLJw>wpsYJr#)f7@FuRBHJ`1}#3{1GhDZWbvYGZAK*{Anyw{$fi$x|Md3HX>5A zDLtw zkfr9Rpqiw`f|o4?O%y>cld+Ao!Mgw-FDmgQGg2dP%0{2G(O z%YB6PE^BOMKk)RL^!q{OPnSpDlO4jr z>tXi10_Qo@aj`UrkMk?9CaDu*d6P01_JaP2T&`#+|3EB%TP%M~nUtQ5ewRIKD#!gI zzLAkL+faU8EdN?8|3nFYJ^CFb{ChQ=&^`2WeNg#db{G4nP>C(i3-<2hA@%JvE9%&N z;B4$A_LZ2~+L`*I{YA4K#S&Res{7iv80>p3_8njxS3l#GBctC!|4S@`J=$WAVS(yu zf|sBDC~{{n73~EqcQggYcN!KO?A1p34U8c12Kz~iy@eu$RHvNdK@wqMfnk`hLeXAT!bo`1F3VLs;T6D)49MPILVyW_G}d%%5^_HUrtHU`x`SUa@tW2mhxJk>r!9-8FUdQ)chET@Mhwe!gR z--Rc=f9*@PJMa)Rn%(^1sYdOQfwjBX`@5D}EFeeirk08KKx=b_+T7YV0fWj>n}=)I zI~bT?4@_rk%MkHZLv6LWwhVDLu%`}gwXHb8xz$?R0M=_}cADuptld-Qt+i)}i6;$Q zco*N=3u5gj)>@QdR2&|!ulF?6exsVD_FuwN%u?6OTGx$ath-60xl^w6h3n zj8?iA5$l#3>K0n+FvHSh7x5u=xNVDG-AB7&L`t;C$_sTj$U|jOkIQWhm7iSSU99iTnudOIEl|E0sRJ z=|u>A$4a#|sA)&j{^l$s@Uo&zJb9Qh8Mt;Fx1h|;rhg%O5#Sy;>I2h0LQW8ydzhP1 zU*cAWF3UX%WZ&jNhUUi%%_GES9K(UfxvUA`t3PXR+uW~taQJT$oWYio>VS3pS)STa3+A;^|H7sAv zb>yLZHJ|uTzI6W0=bPV$?EB2fV)Mu5W=sI$pCbeNH(zhYKx<(J<%bM5H2-aBzJbu0 zR+>bN?v7amXK1h@p z9Tt1`Y3*uh!Qhc_uY7qpt^b|~YBjVDX~hU8H!+1;N0NtZ+vZ0p;)+R(aLY+Y||U8C_>1%Xv_mUzmoJHah6wAw7K7!MLkSS_NkwO+oh z(T3J!ODj5!gc4Gg8UbQtl7Dn}FTYm2ve$|i!&udCZC0v&>&q0(s{YBK)^}RpcW~qO zKsmPXDYRZwyky(fAIYT3pbxH&eD1K@Wj2ptuNjTQeFM8wM)+`tkhlsPuEsrU!4Fzz z;!EoCgD?EP2K+3c;Q17c0TIC$(f^p8c2bQip`BFYu)m(!0L}(x1!A5hWljAd(&556Q}uEGvvt zNNoJ0pivIaI}VA}s)>!CtT2?s#-roDt$y(k7*D1huRIvj!5-sxndpbAzcN(A$6f** zUqphj^b?`f{12nAvSAXOdScs2w_@maL;fhQNHIxgGD*&C0zN~)?50B*z2UpSGJ1m| ze@;JYlfr`<71&!x?7s>4_x}sn`+fj>-_JB=13G*U60o-qB6~kZKkkagc;ur2&ms0y z0DDjVpTKO8L+B=kgm(a_EaE7VjUr)Insg(qGOw5w!K)|&?<1geoX66NB0w>)^7bxQ z7)lX%(=qma;q=UAyzp-h;8EKZoA6^e_e3@_$_$&n`4lUkVkv_^#j4O^ouODb>4l~MFgV5flEwOiV*R0+lchCLP-9K( zk606XIjxCU6Q4s?F@(UyUO1kJ2QX^Op12j!cA;8M+=F&EaSte%3`6a1A}xG(d`<$U zl{R}$v^sXQpN^9arYM+vEeURN)lhUF)|3_6PgU)*6y2PHtMT~!!r zYP4qGv2&%$Kar~5#DAQ2p41b0pVU*cGi7QL9%bX#8-kM_p`W2j=C4FwRIAb?e_~HT zt(b)6wv=D~Giyb_GQwr|ZCc%*WMa57#oa|en-p9;YtwM!i5*3_;r|zI9^vL`WySQh zGu#Ul*FisZ3N9YnX}F&d`!eBP{9m|gX-@iwfP6YRdm$gZE{E9&BK!0~WS^c|WYz>; zLqYgF0(t`H*|?z~l;@jZVB0M*I1CK%`M^cPE}YZI>74O`v5pwGH3gpolpsENjijk5 z_@p4qJ}FueVV(*vDn?oo$+gfAJ|9Sx8YP74>2rlDwaqm;E&V%9oON}+T7h+BB z=CnUzO@5SOP4+^p$zGaySz41ZyI^TeUP-YQI;~5wELu~TjAb_XvCzim$8grun>3T_ z5qU40Bg2D_PtmUhKMwH2Zl5WG|1AY#CY%hZ_QbGqodJAYoktR}=-SnLs0x2W`0wh2}Nq{7fNN17W1qGB2Hn4yVZ20f)Q^Z7$&_Rg6z=bSlnrrw#kd22fXO)x=SQC zED%EzSR%H%+%B!8gap0>hFzW~e%Vxnv%14jYM1_SL*Z6HJ)110b{VGtN~v9@{!6Kp zu?v0CsVrcOFWzxzLb0yNa^GZfy;~p zmC{?MN|Eov5jsK7T6)C$aDIch73UePS;VAulL%i^*egCgXX?MkBo6N}3Vz3@b%h;v z{Rx6EvIOt?fC4DNyM_Q9)NQj)be#$p3vgL;g$X8L?2)^w<|;S`U9$*J3(i5;^#rX{ zpu2Lwey{6Cfqt*+XFh#dOITr7%-xs0Ec?CV5WVYdxWDj03oI&lS6QNWgG~^iMDKS0 zzeVr%2r!!eTl8*EL7r|c{-ykG?EAV|%QRTzWvCy$?n-p5>y{~>qIVk}5WU+JNX$m8 z+blfb)(&*pA4BwRsc;M7u0Re>Drw5yRw{rcdJ(|)blEWGZrfS7-EaigsyE#Z`Rh%$ z(@cGFMoQ&8)1KU@vC0iec~f?Dsr<;o-WANvjtoHp7nit?zE_W7=*hKdK#gzIHs%RKEjKTu@U9G zrpGjbn-2H2rpLam>E2$Np12V1V@;nkSJRUsHGOVxO;3JC(^DpDdg>NUPwS-V^XtKV ztLf=8H9g}$a7dpy3hub3FYKe~i;ige;(pkw^0TJnOVE1uMorHF?PZnV_GtR@*>K-$ z`ig;YE8%WwdhSbbpCG@D%X!a5;vhoB)faT{7f`v%epS2oLS$@G?1B(%@Ab&|_;`H&=qrULh59y9{73W+ z`Y<0Dd>3gt&1RLnyu5Un&d(N7nE!{vWeTt92^Am@E68^0BFT5D!cJbSHmZQ)*tgz{CbK9t351jYnvBb@kL?g1)JOa(x3j6RUv4Qc2>X!+SF_v36o;VjGail_U}y zFhCNC4eufGm@9rmSmI+K@gzvF0(S6Ta(I7?Onf2n#l&GCk*`Q}W& zFd#{syoUt#QGOVfcn&0PfW!?+;tPlO&&b5z=V){4;rxA8~Bqb1K^! zI_Fe&dCz&j44qTcIR{siVi`(~3Aqk6%sJ;_31JQI;PCz$Ip?n=Ev-I;Y6c=UJ;}iU zg_0){qRs-ZwX~GVZ9|jL$9$7ezPwi6nN$xY?!B1S=6)l-*qwx?ZcQ{!>j4Lw`208> zUGW>ef2OvnZFo<)lZKYzVE=+2XB-sny^`AIc_Y5WofKDwlT?P24vl)RN}N)6613{) zh1EYlot;pb_lwjv(cc)}YwjfIO(OM}*JEB^e;19N`u$v9j4F`b-+LslP2P-$>r!(K z8#t4<${S_9-)f=BC!NVhJ;``?pC8U8tOwB4bFDPhnS9lge8CTvN^BdNj9pj|!=X8x z$-l}hME>B850->)iDa}Gto^+Qg4Q?|=dttSPO3Z(3jayI2V#C|7*ubc9N8X>3r?MeBa2y%3sTFH}Y zmm!Rdqf@K;^a5RL8=6`#Aa1H5`NpI^hPe7MsqOe<#BXq?z9!{N9c0PLT{Wp|%hHv| zbk5YBp42UV4$jnrp42`5kfd@-QNhqq<`y(?k*KAr)SuAocrQ3p?|4#wld14-+?iIv zlUB|jGUAKeX|*Jcv=EDi!+Se2EiA1$_JC_7C9O8?Nd`4Xc}E(X7kN8O2Q3YKK8~1D zMOs={K66(Ko?pXr)T?-It);P*_OgcIIU3K=C2Ypaz72;R;0ze^|F;c*S5vZUqLPnL+7uE=i|C=enFZ$ z=NDKY?{9e|U?nlUf8h-f zKF*vzqh7jO9zBaspU0GZUGaNlM*WOt3(y(Js*Sz=Eg3-mu><637VjO%+QBw9qXU0E z;j)0a?|)DI(2Qfwi~}x?6TH{_x(LrWV{>L)w4m*~WPIz)xZ#T5?6~z7{%dhT|FH|eHCzJtNNkKUW{4xj889a z$_%-ey-ccTicm1ivTZTTRx+x6kLB9(>L6TBseXA)rTXQn+jlMxlNK1Yyg5=|*LtkD zovQ;|m)N1XwPSP3gG`jnRdnt{N@s8N$UT|+Im+|6g?2ME_j+9Jd0-a0eGrCkRY%G+ z&fMSKxj*^yi`RiY@+#&%2o83Y(Y!kDyc&$Ih-CHh>gM9K6cqYde4Y!`&S-g?yX2LI z<{fb6?XH=(#iwtmUJ;YuvX|+|Y~E+Knt7L0RQn#QwyZh=^5s=_SAC|kyXyOztG-Yu z($-epsk!PGD@@xL&Ch`{pzXHsz?cONN54Z+wYhMmijDI-U*f^__t)RY|VpMX7 za*+iu6uek~4pbgQw&?{O8Ib=V12#Jqbi@AAKF)$}E*=4vD@|e8zv?U)<}AQK3@3%v zUZ+7=KywH^vf#~vi3N!mtwJwMO8l*(y?ktFr zOoCyxB`mbS>n@1#=_O%-iYPP-f+2&jN3OkpZOygQHLaiIx;BK*ple%8G2$;t`eWBN z;jcSc8;m1kJ=Q+Gwk;b!Yy(@{-X%A2x!0m5mBeD(R@>TZ`#_k`wF8{;0qocWxYrJr z2rGsOjT>P-YsVv;?GWW7*IrnAb=?$fE=yG+e9r&};cI`zZ_q(edH2scz45wg&UF=} zA|O@k@O2N{!r(&JHFvJVZc!>Wm5UJTFfK2x=v>!c>PAiy`nL~X*Au#?5tq^@`+(;?ky1y8piq@mr1yr>DzF-xte*{s` zkk(~=)5hzccCK#`kQaU3`d;gYqrO$3__nb1y=>0)cqIqH325tGKM_Lg4qfk!T0a9% zSL8`o=lUfwA9dH~<}J3aiV9u7-no9Y1S=)4F9QB5&UDrvj9QPXUwTF61!rNo#d7^$ zl5k-aXCd|zf}f`@6y+?eB}s%9HgFb(22m?)WKq+!@WN+op2GG_?hq9s3*ChYg_usp z)|V|S(xoC%ur?XE3Q6+@|=ZAa5Z^@;W$La$fB^K zWR3OtsE5mc699&)MZ?32M%zM*M!Sn5 zeEOyuYGY*47?-S6Xrh%Bgcsq0@S>T{qA4o3lm|1Mx3JYz*qS>;rO4u%#SMztH=mS( z6t`f2f)vXkwk3$Q8Im7*dbzk8EZDz2@`>UegYhD_fBn$nVZrhhj}I$;*A`m*uDck0 z@1`szU-6WC8WJHgw}Tm)sn=@tdfPmt`b2 zVe$%%jlW_rQ&P^e@pnMwsYGs<#T|YnwLK+O{IEJDjpfySn39ylmdr)AgD<%&$&4yV zCQ)8+*P~=@$%jA)zCEvGbJ^W_C5NI)b_XPQrQ~y4$<>lCVVbq1?ozP}_q*7V>pp$U zT6GCt$*)l*KLiqB!ZfGk4r4=0{*F~ofrgpW%+i`MrS~Czmb~^ZwiNR};FdlWT55!r zHjFN6>P2`sSxJ zed`QhRw^f|L?l#C2=Qr&^L0@P76Kih^KEDs)glruB>WsADr4LXU~8M-MkM_0 zeK17a7l5K?t{&kH^|lNV_Xh)OM0lU~_6!kKf`K(7L}l@Ch^VT79c<}#Q7b|uh$SK7 zfgqSOLfkN`g$P{fOy*oS6}2PGhs?Gi;=v$TNQBwZd^1E;4}v`uVNNoWLqv@rSe=N( zm5JL!67qszk3}TzOS}{!YN`&nO%uCl5s~;!;y)pxmI9^Og)0I}RF8%Tr-DG-$0O!6 zne$?ZsI4HWcF{6oPM0~OLPSUa@^HkQv2)xZ!upy$S87FQ1n%U>DKF|M5r*69&RLkp z<1K9}LxoR7B%Mq8BSbt*8Zx_&M9gbA@3{~W_^3UksT+X{Fp@%q^#OZHw_ZfDo_t>j zZ?|SzTw`Pxk47YSN$wTApe*V~Bqt{?2oZH9+Pqstdom*Va`N{fqFx|jgNT%flu04t z(I8?CBhtsE&kPZ~k{b*5FHk==?=Do^e8VH0|Cu%EQjc=rRYy?W*wBz?rcMZ8Nx6`6GJpLL^DG) zH^gIxXkiGKAs#nGOG7+ih$jv4lp$J4zqKLo_p~9}7~&a2JZp&OL!=ra%@FeqZ-F7w=Rfbq?h&6`DHv}lJH3aCaH$F<&LUPJ6N#C}5@FvLOmcgPU-~a_|_2L8RC0G{9uS1hPWyJel)~ShWJ_j z{bGn;4RK5U-8RH;hWOnOe;DFVL;PikJM!;uL;Tke{}`rbm^S%W&M}D8zIWG(2*ZFN)@xH&ox0+;4(Gp(xvdsr(O|~X^TiGEEvWq4lHKYpMv*pcN z{)PxChCD^D2`CMDShl8h@KjG2n%osba5H}+tL1Goos#HwyJ!k}akJsP4zsqO-dKd= z!LLL7T)SvSj9We}-X6jmkX6%%cDy;@@yp>6P-m1eEROntrq3zi*goiW=flF(K7sU^WMB$ za?IP>7QSee&ADieXAwqRyI)So#(hxb#aj`J?ku{K6``4!S!dP8gXEj_D1QG>zFAKz zzFGePrKna};d)kh)+naLgI?TD=0tlY)DG&2-@ z_v1m0RI@mCy@zqudB76pQ?~&n1ay$~hnS#42aC&t`d_UUSJ4+&S=<;2Aj@Jb4&5Wm zVqCnj7?&&5^yzy#Qx;poe9vO!W6uNS#kh#Y^B2!wQcg1;!RzD=c#z6iybZti$W&Gc zi%%+LEWQXLb6YL`T3`J25>5;$z&HOE;0FkB)3X?3!aWDgy2(0}@lM2=SJ%9nU#yw+ zu*~r$9&lp={?<(YH{&%)fVoqkjMf2VtjPh)eDrSE2Egu7+M46UtA7_>K#^;{7ZV&% z|s%S1y7ec8n!R~Vo#a|=eNQD~q#^-QkG34jxi z5%Q&ncvOBtV%{xLU#6NUZ$l?Ow}N*{pf_7m67|hS^Zp840WX?K{5%)iBI0u^Ungv+ zN0TL*$$14@wN4))6KK^iw-C)`f}<`D?1_7g-X%Zn#`FFb)g;F6E>W*FN~z31q8LKf z2678l=L+#ExPO1ZOaKT0wayRtsf8sw0$9>s#FJeR|9Aruc!{V_NmYslej4)b_RgbY z5Y+>$Vl8-kzPJEvibQAXETY5{MNYu6v-Gbk{+0WfA zle*`A4)!04N7~k&d)dVqNa(x=LgzW^&b=i&Sm)e7TqG!-R$XtMc@;${x?J}zN|Luj z)OCnwBXAMh52yEBd#Te{8K&{y~%qJ5&C#?4x05%0KRue|-9( z=l!PQOsx(R6;E1VX$wKouvn7$rZaP}D`CEP&Qiq?n=|uW7bmx(jzjz>0@p^ZSoEOX#y z$bp5ou2l6{ZG>&bYi@Jl5y1Xu<Y&BBpiU$*$3}@Hd}+cy+6V|L6<*vC*No*aw~j=Z4drnj?& z=R9Srm(xkSQx5#%54dv%AgT$vt(@11Lxg!iSW$-HBZB#;Cr5H{h?gUZh8Mk2{5i7m zI0UolMN!3{<3Yz?5$*UM@r!Z*yQhCD$_MP8uExqyc+oCfy`od9=PtSe=HIj`x~>;p zFNVZabJ4f>Wt}V=1{VEja~Ay^UG$?*KiZXjGW+4;>PY)nLRzchHhOWJ;$)S&_!<1h z4kI&vB`bzC7yGRli-W~u>J;}BVX{Xm9v58<#T@mrW=TUX9urdxLq3}A*R``aHku2Y z3df3+wJ%|QRPh=_Jb

    Nd3?n|}6;GdDNIMevMY--m=sa3MNtJEr?l>Sty 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

    AD{=N0n>+sdwR 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Ŕ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/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⪙Tf=uVaD$6QJSeS?cNKtA@GM;#zXhd@ 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