org.asteriskjava.fastagi.internal.AgiReplyImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of asterisk-java Show documentation
Show all versions of asterisk-java Show documentation
The free Java library for Asterisk PBX integration.
/*
* Copyright 2004-2006 Stefan Reuter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.asteriskjava.fastagi.internal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.asteriskjava.fastagi.reply.AgiReply;
/**
* Default implementation of the AgiReply interface.
*
* @author srt
* @version $Id$
*/
public class AgiReplyImpl implements AgiReply
{
private static final Pattern STATUS_PATTERN = Pattern.compile("^(\\d{3})[ -]");
private static final Pattern RESULT_PATTERN = Pattern.compile("^200 result=(\\S+)");
private static final Pattern PARENTHESIS_PATTERN = Pattern.compile("^200 result=\\S* +\\((.*)\\)");
private static final Pattern ADDITIONAL_ATTRIBUTES_PATTERN = Pattern.compile("^200 result=\\S* +(\\(.*\\) )?(.+)$");
private static final Pattern SYNOPSIS_PATTERN = Pattern.compile("^\\s*Usage:\\s*(.*)\\s*$");
private static final String END_OF_PROPER_USAGE = "520 End of proper usage.";
/**
* Serial version identifier.
*/
private static final long serialVersionUID = 3256727294671337012L;
private List lines;
private String firstLine;
/**
* The result, that is the part directly following the "result=" string.
*/
private String result;
/**
* The status code.
*/
private Integer status;
/**
* Additional attributes contained in this reply, for example endpos.
*/
private Map attributes;
/**
* The contents of the parenthesis.
*/
private String extra;
/**
* In case of status == 520 (invalid command syntax) this attribute contains
* the synopsis of the command.
*/
private String synopsis;
/**
* In case of status == 520 (invalid command syntax) this attribute contains
* the usage of the command.
*/
private String usage;
AgiReplyImpl()
{
super();
this.status = null;
}
AgiReplyImpl(List lines)
{
this();
if (lines != null)
{
this.lines = new ArrayList<>(lines);
if (!lines.isEmpty())
{
firstLine = lines.get(0);
}
}
}
public String getFirstLine()
{
return firstLine;
}
public List getLines()
{
return lines;
}
public int getResultCode()
{
String result;
result = getResult();
if (result == null)
{
return -1;
}
try
{
return Integer.parseInt(result);
}
catch (NumberFormatException e)
{
return -1;
}
}
public char getResultCodeAsChar()
{
int resultCode;
resultCode = getResultCode();
if (resultCode < 0)
{
return 0x0;
}
return (char) resultCode;
}
public String getResult()
{
if (result != null)
{
return result;
}
final Matcher matcher = RESULT_PATTERN.matcher(firstLine);
if (matcher.find())
{
result = matcher.group(1);
}
else
result = "";
return result;
}
public int getStatus()
{
if (status != null)
{
return status;
}
if (firstLine == null)
{
return -1;
}
final Matcher matcher = STATUS_PATTERN.matcher(firstLine);
if (matcher.find())
{
status = Integer.parseInt(matcher.group(1));
return status;
}
return -1;
}
public String getAttribute(String name)
{
if (getStatus() != SC_SUCCESS)
{
return null;
}
if ("result".equalsIgnoreCase(name))
{
return getResult();
}
return getAttributes().get(name.toLowerCase(Locale.ENGLISH));
}
protected Map getAttributes()
{
if (attributes != null)
{
return attributes;
}
attributes = new HashMap<>();
final Matcher matcher = ADDITIONAL_ATTRIBUTES_PATTERN.matcher(firstLine);
if (matcher.find())
{
attributes.putAll(parseAttributes(matcher.group(2)));
}
return attributes;
}
Map parseAttributes(String s)
{
StringBuilder keyBuilder = new StringBuilder();
StringBuilder valueBuilder = new StringBuilder();
Map map = new HashMap<>();
boolean inKey = true;
boolean inQuotes = false;
char previousChar = 0x0;
for (int i = 0; i < s.length(); i++)
{
char c = s.charAt(i);
if (c == '=' && inKey)
{
inKey = false;
inQuotes = false;
}
else if (c == ' ' && !inKey && !inQuotes)
{
map.put(keyBuilder.toString().toLowerCase(Locale.ENGLISH), valueBuilder.toString());
keyBuilder.delete(0, keyBuilder.length());
valueBuilder.delete(0, valueBuilder.length());
inKey = true;
}
else if (c == '"' && !inKey)
{
if (previousChar == '\\')
{
valueBuilder.deleteCharAt(valueBuilder.length() - 1);
valueBuilder.append(c);
}
else
{
inQuotes = !inQuotes;
}
}
else
{
if (inKey)
{
keyBuilder.append(c);
}
else
{
valueBuilder.append(c);
}
}
previousChar = c;
}
if (keyBuilder.length() > 0)
{
map.put(keyBuilder.toString().toLowerCase(Locale.ENGLISH), valueBuilder.toString());
}
return map;
}
private boolean extraCreated;
public String getExtra()
{
if (getStatus() != SC_SUCCESS)
{
return null;
}
if (extraCreated)
{
return extra;
}
final Matcher matcher = PARENTHESIS_PATTERN.matcher(firstLine);
if (matcher.find())
{
extra = matcher.group(1);
}
extraCreated = true;
return extra;
}
public String getSynopsis()
{
if (getStatus() != SC_INVALID_COMMAND_SYNTAX)
{
return null;
}
if (synopsis == null && lines.size() > 1)
{
final String secondLine;
final Matcher synopsisMatcher;
secondLine = lines.get(1);
synopsisMatcher = SYNOPSIS_PATTERN.matcher(secondLine);
if (synopsisMatcher.find())
{
synopsis = synopsisMatcher.group(1);
}
}
return synopsis;
}
/**
* Returns the usage of the command sent if Asterisk expected a different
* syntax (getStatus() == SC_INVALID_COMMAND_SYNTAX).
*
* @return the usage of the command sent, null
if there were no
* syntax errors.
*/
public String getUsage()
{
if (usage == null)
{
StringBuilder usageSB;
usageSB = new StringBuilder();
for (int i = 2; i < lines.size(); i++)
{
String line;
line = lines.get(i);
if (END_OF_PROPER_USAGE.equals(line))
{
break;
}
usageSB.append(line.trim());
usageSB.append(" ");
}
usage = usageSB.toString().trim();
}
return usage;
}
@Override
public String toString()
{
StringBuilder sb;
sb = new StringBuilder("AgiReply[");
sb.append("status=").append(getStatus()).append(",");
if (status == SC_SUCCESS)
{
sb.append("result='").append(getResult()).append("',");
sb.append("extra='").append(getExtra()).append("',");
sb.append("attributes=").append(getAttributes()).append(",");
}
if (status == SC_INVALID_COMMAND_SYNTAX)
{
sb.append("synopsis='").append(getSynopsis()).append("',");
}
sb.append("systemHashcode=").append(System.identityHashCode(this));
sb.append("]");
return sb.toString();
}
}