Thread: [Asterisk-java-cvs] CVS: asterisk-java/src/java/net/sf/asterisk/fastagi/impl AGIWriterImpl.java,NONE
Brought to you by:
srt
From: Stefan R. <sr...@us...> - 2005-03-11 15:21:05
|
Update of /cvsroot/asterisk-java/asterisk-java/src/java/net/sf/asterisk/fastagi/impl In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21021/src/java/net/sf/asterisk/fastagi/impl Added Files: AGIWriterImpl.java RequestBuilderImpl.java AGIReaderImpl.java AGIChannelImpl.java ReplyBuilderImpl.java AGIRequestImpl.java Log Message: Refactored private implementation classes into impl subpackage --- NEW FILE: AGIWriterImpl.java --- /* * Copyright 2004-2005 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 net.sf.asterisk.fastagi.impl; import java.io.IOException; import net.sf.asterisk.fastagi.AGIException; import net.sf.asterisk.fastagi.AGINetworkException; import net.sf.asterisk.fastagi.AGIWriter; import net.sf.asterisk.fastagi.command.AGICommand; import net.sf.asterisk.io.SocketConnectionFacade; /** * Default implementation of the AGIWriter interface. * * @author srt * @version $Id: AGIWriterImpl.java,v 1.1 2005/03/11 15:20:50 srt Exp $ */ public class AGIWriterImpl implements AGIWriter { private SocketConnectionFacade socket; public AGIWriterImpl(SocketConnectionFacade socket) { this.socket = socket; } public void sendCommand(AGICommand command) throws AGIException { try { socket.write(command.buildCommand() + "\n"); socket.flush(); } catch (IOException e) { throw new AGINetworkException( "Unable to send command to Asterisk: " + e.getMessage(), e); } } } --- NEW FILE: RequestBuilderImpl.java --- /* * Copyright 2004-2005 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 net.sf.asterisk.fastagi.impl; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import net.sf.asterisk.fastagi.AGIRequest; import net.sf.asterisk.fastagi.RequestBuilder; /** * Default implementation of the AGIRequestBuilder interface. * * @author srt * @version $Id: RequestBuilderImpl.java,v 1.1 2005/03/11 15:20:50 srt Exp $ */ public class RequestBuilderImpl implements RequestBuilder { /** * Creates a new AGIRequestBuilderImpl. */ public RequestBuilderImpl() { } public AGIRequest buildRequest(final Collection lines) { AGIRequestImpl request; Map map; if (lines == null) { throw new IllegalArgumentException("Environment must not be null."); } request = new AGIRequestImpl(); map = buildMap(lines); request.setScript((String) map.get("network_script")); request.setRequestURL((String) map.get("request")); request.setChannel((String) map.get("channel")); request.setUniqueId((String) map.get("uniqueid")); request.setType((String) map.get("type")); request.setLanguage((String) map.get("language")); if (map.get("callerid") != null) { String rawCallerId = (String) map.get("callerid"); request.setCallerId(getCallerId(rawCallerId)); request.setCallerIdName(getCallerIdName(rawCallerId)); } request.setDnid((String) map.get("dnid")); request.setRdnis((String) map.get("rdnis")); request.setContext((String) map.get("context")); request.setExtension((String) map.get("extension")); if (map.get("priority") != null) { request.setPriority(new Integer((String) map.get("priority"))); } if (map.get("enhanced") != null) { if ("1.0".equals((String) map.get("enhanced"))) { request.setEnhanced(Boolean.TRUE); } else { request.setEnhanced(Boolean.FALSE); } } request.setAccountCode((String) map.get("accountcode")); return request; } /** * Builds a map containing variable names as key (with the "agi_" prefix * stripped) and the corresponding values.<br> * 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. */ private Map buildMap(final Collection lines) { Map map; Iterator lineIterator; map = new HashMap(); lineIterator = lines.iterator(); while (lineIterator.hasNext()) { String line; int colonPosition; String key; String value; line = (String) lineIterator.next(); colonPosition = line.indexOf(':'); // no colon on the line? if (colonPosition < 0) { continue; } // key doesn't start with agi_? if (!line.startsWith("agi_")) { continue; } // first colon in line is last character -> no value present? if (line.length() < colonPosition + 2) { continue; } key = line.substring(4, colonPosition).toLowerCase(); value = line.substring(colonPosition + 2); if (value.length() != 0) { map.put(key, value); } } return map; } private String getCallerId(final String rawCallerId) { int lbPosition; int rbPosition; lbPosition = rawCallerId.indexOf('<'); rbPosition = rawCallerId.indexOf('>'); if (lbPosition < 0 || rbPosition < 0) { return rawCallerId; } return rawCallerId.substring(lbPosition + 1, rbPosition); } private String getCallerIdName(final String rawCallerId) { int lbPosition; String callerIdName; lbPosition = rawCallerId.indexOf('<'); if (lbPosition < 0) { return null; } callerIdName = rawCallerId.substring(0, lbPosition).trim(); if (callerIdName.startsWith("\"") && callerIdName.endsWith("\"")) { callerIdName = callerIdName.substring(1, callerIdName.length() - 1); } if (callerIdName.length() == 0) { return null; } else { return callerIdName; } } } --- NEW FILE: AGIReaderImpl.java --- /* * Copyright 2004-2005 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 net.sf.asterisk.fastagi.impl; import java.io.IOException; import java.util.ArrayList; import java.util.List; import net.sf.asterisk.fastagi.AGIException; import net.sf.asterisk.fastagi.AGIHangupException; import net.sf.asterisk.fastagi.AGINetworkException; import net.sf.asterisk.fastagi.AGIReader; import net.sf.asterisk.fastagi.AGIRequest; import net.sf.asterisk.fastagi.ReplyBuilder; import net.sf.asterisk.fastagi.RequestBuilder; import net.sf.asterisk.fastagi.reply.AGIReply; import net.sf.asterisk.io.SocketConnectionFacade; /** * Default implementation of the AGIReader implementation. * * @author srt * @version $Id: AGIReaderImpl.java,v 1.1 2005/03/11 15:20:50 srt Exp $ */ public class AGIReaderImpl implements AGIReader { private SocketConnectionFacade socket; private ReplyBuilder replyBuilder; private RequestBuilder requestBuilder; public AGIReaderImpl(SocketConnectionFacade socket) { this.socket = socket; this.replyBuilder = new ReplyBuilderImpl(); this.requestBuilder = new RequestBuilderImpl(); } public AGIRequest readRequest() throws AGIException { AGIRequest request; String line; List lines; lines = new ArrayList(); try { while ((line = socket.readLine()) != null) { if (line.length() == 0) { break; } lines.add(line); } } catch (IOException e) { throw new AGINetworkException( "Unable to read request from Asterisk: " + e.getMessage(), e); } request = requestBuilder.buildRequest(lines); return request; } public AGIReply readReply() throws AGIException { AGIReply reply; List lines; String line; lines = new ArrayList(); try { line = socket.readLine(); } catch (IOException e) { throw new AGINetworkException( "Unable to read reply from Asterisk: " + e.getMessage(), e); } if (line == null) { throw new AGIHangupException(); } lines.add(line); // read synopsis and usage if statuscode is 520 if (line.startsWith(Integer .toString(AGIReply.SC_INVALID_COMMAND_SYNTAX))) { try { while ((line = socket.readLine()) != null) { lines.add(line); if (line.startsWith(Integer .toString(AGIReply.SC_INVALID_COMMAND_SYNTAX))) { break; } } } catch (IOException e) { throw new AGINetworkException( "Unable to read reply from Asterisk: " + e.getMessage(), e); } } reply = replyBuilder.buildReply(lines); return reply; } } --- NEW FILE: AGIChannelImpl.java --- /* * Copyright 2004-2005 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 net.sf.asterisk.fastagi.impl; import net.sf.asterisk.fastagi.AGIChannel; import net.sf.asterisk.fastagi.AGIException; import net.sf.asterisk.fastagi.AGIReader; import net.sf.asterisk.fastagi.AGIWriter; import net.sf.asterisk.fastagi.command.AGICommand; import net.sf.asterisk.fastagi.reply.AGIReply; import net.sf.asterisk.io.SocketConnectionFacade; /** * Default implementation of the AGIChannel interface. * * @author srt * @version $Id: AGIChannelImpl.java,v 1.1 2005/03/11 15:20:50 srt Exp $ */ public class AGIChannelImpl implements AGIChannel { private AGIWriter agiWriter; private AGIReader agiReader; private SocketConnectionFacade socket; public AGIChannelImpl(SocketConnectionFacade socket) { this.socket = socket; this.agiWriter = new AGIWriterImpl(socket); this.agiReader = new AGIReaderImpl(socket); } public AGIChannelImpl(AGIWriter agiWriter, AGIReader agiReader) { this.agiWriter = agiWriter; this.agiReader = agiReader; } public synchronized AGIReply sendCommand(AGICommand command) throws AGIException { AGIReply reply; agiWriter.sendCommand(command); reply = agiReader.readReply(); return reply; } } --- NEW FILE: ReplyBuilderImpl.java --- /* * Copyright 2004-2005 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 net.sf.asterisk.fastagi.impl; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sf.asterisk.fastagi.ReplyBuilder; import net.sf.asterisk.fastagi.reply.AGIReply; /** * Default implementation of the ReplyBuilder interface. * * @author srt * @version $Id: ReplyBuilderImpl.java,v 1.1 2005/03/11 15:20:50 srt Exp $ */ public class ReplyBuilderImpl implements ReplyBuilder { 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 ADDITIONAL_ATTRIBUTE_PATTERN = Pattern .compile("(\\S+)=(\\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."; public AGIReply buildReply(List lines) { String firstLine; AGIReply reply; Matcher matcher; if (lines.size() == 0) { return null; } reply = new AGIReply(); firstLine = (String) lines.get(0); matcher = STATUS_PATTERN.matcher(firstLine); if (matcher.find()) { reply.setStatus(Integer.parseInt(matcher.group(1))); } if (reply.getStatus() == AGIReply.SC_SUCCESS) { matcher = RESULT_PATTERN.matcher(firstLine); if (matcher.find()) { reply.setResult(matcher.group(1)); } matcher = PARENTHESIS_PATTERN.matcher(firstLine); if (matcher.find()) { reply.setExtra(matcher.group(1)); } matcher = ADDITIONAL_ATTRIBUTES_PATTERN.matcher(firstLine); if (matcher.find()) { String s; Matcher attributeMatcher; s = matcher.group(2); attributeMatcher = ADDITIONAL_ATTRIBUTE_PATTERN.matcher(s); while (attributeMatcher.find()) { String key; String value; key = attributeMatcher.group(1); value = attributeMatcher.group(2); reply.setAttribute(key, value); } } } else if (reply.getStatus() == AGIReply.SC_INVALID_COMMAND_SYNTAX) { StringBuffer usageSB; if (lines.size() > 1) { String secondLine; Matcher synopsisMatcher; secondLine = (String) lines.get(1); synopsisMatcher = SYNOPSIS_PATTERN.matcher(secondLine); if (synopsisMatcher.find()) { reply.setSynopsis(synopsisMatcher.group(1)); } } usageSB = new StringBuffer(); for (int i = 2; i < lines.size(); i++) { String line; line = (String) lines.get(i); if (END_OF_PROPER_USAGE.equals(line)) { break; } usageSB.append(line.trim()); usageSB.append(" "); } reply.setUsage(usageSB.toString().trim()); } return reply; } } --- NEW FILE: AGIRequestImpl.java --- /* * Copyright 2004-2005 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 net.sf.asterisk.fastagi.impl; import java.io.Serializable; import net.sf.asterisk.fastagi.AGIRequest; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; /** * Default implementation of the AGIRequest interface. * * @author srt * @version $Id: AGIRequestImpl.java,v 1.1 2005/03/11 15:20:50 srt Exp $ */ public class AGIRequestImpl implements Serializable, AGIRequest { /** * Serial version identifier. */ private static final long serialVersionUID = 3257001047145789496L; /** * The name of the script to execute. */ private String script; /** * The full URL of the request in the form agi://host[:port][/script] */ private String requestURL; /** * The name of the channel. */ private String channel; /** * The unique id of the channel. */ private String uniqueId; /** * The type of the channel, for example "SIP". */ private String type; /** * The language, for example "en". */ private String language; /** * The Caller*ID, for example "1234". */ private String callerId; /** * The Caller*ID Name, for example "John Doe". */ private String callerIdName; private String dnid; private String rdnis; /** * The context in the dial plan from which the AGI script was called. */ private String context; /** * The extension in the dial plan from which the AGI script was called. */ private String extension; /** * The priority in the dial plan from which the AGI script was called. */ private Integer priority; /** * Boolean.TRUE if this agi is passed audio (EAGI - Enhanced AGI).<br> * Enhanced AGI is currently not supported on FastAGI. */ private Boolean enhanced; /** * The account code set for the call. */ private String accountCode; /** * Creates a new AGIRequestImpl. */ public AGIRequestImpl() { } /** * Returns the name of the script to execute. * * @return the name of the script to execute. */ public String getScript() { return script; } /** * Sets the name of the script to execute. * * @param script the name of the script to execute. */ public void setScript(String script) { this.script = script; } /** * 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]. */ public String getRequestURL() { return requestURL; } /** * Sets the full URL of the request in the form agi://host[:port][/script]. * * @param requestURL the full URL of the request in the form * agi://host[:port][/script]. */ public void setRequestURL(String requestURL) { this.requestURL = requestURL; } /** * Returns the name of the channel. * * @return the name of the channel. */ public String getChannel() { return channel; } /** * Sets the name of the channel. * * @param channel the name of the channel. */ public void setChannel(String channel) { this.channel = channel; } /** * Returns the unqiue id of the channel. * * @return the unqiue id of the channel. */ public String getUniqueId() { return uniqueId; } /** * Sets the unqiue id of the channel. * * @param uniqueId the unqiue id of the channel. */ public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } /** * Returns the type of the channel, for example "SIP". * * @return the type of the channel, for example "SIP". */ public String getType() { return type; } /** * Sets the type of the channel, for example "SIP". * * @param type the type of the channel, for example "SIP". */ public void setType(String type) { this.type = type; } /** * Returns the language, for example "en". * * @return the language, for example "en". */ public String getLanguage() { return language; } /** * Sets the language, for example "en". * * @param language the language, for example "en". */ public void setLanguage(String language) { this.language = language; } /** * Returns the Caller*ID, for example "1234". * * @return the Caller*ID, for example "1234". */ public String getCallerId() { return callerId; } /** * Sets the Caller*ID, for example "1234". * * @param callerId the Caller*ID, for example "1234". */ public void setCallerId(String callerId) { this.callerId = callerId; } /** * Returns the the Caller*ID Name, for example "John Doe". * * @return the the Caller*ID Name, for example "John Doe". */ public String getCallerIdName() { return callerIdName; } /** * Sets the the Caller*ID Name, for example "John Doe". * * @param callerIdName the the Caller*ID Name, for example "John Doe". */ public void setCallerIdName(String callerIdName) { this.callerIdName = callerIdName; } public String getDnid() { return dnid; } public void setDnid(String dnid) { this.dnid = dnid; } public String getRdnis() { return rdnis; } public void setRdnis(String rdnis) { this.rdnis = rdnis; } /** * Returns the context in the dial plan from which the AGI script was * called. * * @return the context in the dial plan from which the AGI script was * called. */ public String getContext() { return context; } /** * Sets the context in the dial plan from which the AGI script was called. * * @param context the context in the dial plan from which the AGI script was * called. */ public void setContext(String context) { this.context = context; } /** * Returns the extension in the dial plan from which the AGI script was * called. * * @return the extension in the dial plan from which the AGI script was * called. */ public String getExtension() { return extension; } /** * Sets the extension in the dial plan from which the AGI script was called. * * @param extension the extension in the dial plan from which the AGI script * was called. */ public void setExtension(String extension) { this.extension = extension; } /** * Returns the priority in the dial plan from which the AGI script was * called. * * @return the priority in the dial plan from which the AGI script was * called. */ public Integer getPriority() { return priority; } /** * Sets the priority in the dial plan from which the AGI script was called. * * @param priority the priority in the dial plan from which the AGI script * was called. */ public void setPriority(Integer priority) { this.priority = priority; } /** * Returns wheather this agi is passed audio (EAGI - Enhanced AGI).<br> * Enhanced AGI is currently not supported on FastAGI. * * @return Boolean.TRUE if this agi is passed audio, Boolean.FALSE * otherwise. */ public Boolean getEnhanced() { return enhanced; } /** * Sets wheather this agi is passed audio. * * @param enhanced Boolean.TRUE if this agi is passed audio, Boolean.FALSE * otherwise. */ public void setEnhanced(Boolean enhanced) { this.enhanced = enhanced; } /** * Returns the account code set for the call. * * @return the account code set for the call. */ public String getAccountCode() { return accountCode; } /** * Sets the account code set for the call. * * @param accountCode the account code set for the call. */ public void setAccountCode(String accountCode) { this.accountCode = accountCode; } public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); } public boolean equals(Object o) { return EqualsBuilder.reflectionEquals(this, o); } public int hashCode() { return HashCodeBuilder.reflectionHashCode(this); } } |