📄 call.java
字号:
// Call: Model a basic call
// $Id: Call.java,v 1.8 2003/11/13 11:34:59 cgm8 Exp $
/*
* Copyright (c) 1999 Carlos G Mendioroz.
*
* This file is part of D4J.
*
* D4J is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* D4J is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Report problems and direct all questions to:
*
* tron@acm.org
*/
package local.dialogic;
import java.util.*;
/**
* Call models a call, inbound or outbound, from the time
* the call exists in any way (remote line seizure for incoming
* calls, call placement in outgoing calls) upto call disposal,
* that may be well after call tear down.
* Channels are responsible for call creation for incoming calls
* via the Call(Channel) method, whether Call(number) is
* used for outbound call setup, using previously appointed
* channels for call placement.
*/
public class Call extends java.lang.Object
{
// Id engine
static Object lastIdLock = new Object();
static long lastId = 0;
// hash of groups(Vectors) of Channels
static Hashtable outChannels = new Hashtable();
// external logger (CDR ?)
static CallLogger logger = null;
// variables
long id;
Channel channel;
long startTime = 0;
long connectTime = 0;
long endTime = 0;
// To be defined how
String dialedNumber = null; // not null implies outgoing
String ani = null;
String dnis = null; // not null implies incoming ?
String caller = null; // Originating endpoint
int pulses = 0;
// External object for easy access/log
Object reference = null;
// Still some thinking needed
int state = 0;
public static final int NULL = 0;
public static final int INITIATED = 1; // AKA dialing
public static final int ALERTING = 2; // AKA ringing
public static final int QUEUED = 3;
public static final int CONNECTED = 4; // AKA talking
public static final int HOLD = 5;
public static final int FAILED = 6;
// Accessors
public long id() { return id; }
public Channel channel() { return channel; }
public long startTime() { return startTime; }
public long connectTime() { return connectTime; }
public long endTime() { return endTime; }
public String dnis() { return dnis; }
public int getState() { return state; }
public Object reference() { return reference; }
public String dialedNumber() { return dialedNumber; }
public String caller() { return caller; }
// Incoming call creation
Call(Channel aChannel) {
channel = aChannel;
startTime = new Date().getTime();
synchronized(lastIdLock) {
id = ++lastId;
}
state = INITIATED;
}
// Outgoing call setup
public Call(String number) {
Vector group = (Vector)outChannels.get("");
if (group == null) {
// No hope, no channels
throw new RuntimeException("No outgoing channels available!");
}
// XXX Here to implement outgoing policy, if any
Channel ch = null;
getChannel:
while (true) {
for (int i = 0; i < group.size(); i++) {
ch = (Channel)group.elementAt(i);
synchronized(ch) {
if (ch.getState() == Channel.FREE) {
// Ok!
ch.setState(Channel.OUTGOING);
break getChannel;
}
}
}
// No channels, let caller decide...
throw new RuntimeException("No outgoing channels available!");
}
setCall(number, ch);
}
public Call(String number, String groupId) {
Vector group = (Vector)outChannels.get(groupId);
if (group == null) {
// No hope, no channels
throw new RuntimeException("No outgoing channels available!");
}
// XXX Here to implement outgoing policy, if any
Channel ch = null;
getChannel:
while (true) {
for (int i = 0; i < group.size(); i++) {
ch = (Channel)group.elementAt(i);
synchronized(ch) {
if (ch.getState() == Channel.FREE) {
// Ok!
ch.setState(Channel.OUTGOING);
break getChannel;
}
}
}
// No channels, let caller decide...
throw new RuntimeException("No outgoing channels available!");
}
setCall(number, ch);
}
public Call(String number, Channel ch) {
boolean ok = false;
synchronized(ch) {
if (ch.getState() == Channel.FREE) {
// Ok!
ch.setState(Channel.OUTGOING);
ok = true;
}
}
if (!ok)
throw new RuntimeException("Channel not available!");
setCall(number, ch);
}
private void setCall(String number, Channel ch) {
this.startTime = System.currentTimeMillis();
this.channel = ch;
this.dialedNumber = number;
this.state = INITIATED;
try {
ch.dial(this, number);
} catch (ChannelException ce) {
// This call never existed ???
this.channel = null;
ch.clear();
this.state = FAILED;
throw ce;
}
synchronized(lastIdLock) {
id = ++lastId;
}
}
// Outgoing calls channel appoint
public static void setDialout(Channel aChannel)
{
setDialout(aChannel, "");
}
public static void setDialout(Channel aChannel, String groupId)
{
Vector group = (Vector)outChannels.get(groupId);
if (group == null) {
group = new Vector();
outChannels.put(groupId, group);
}
group.addElement(aChannel);
}
// Caller identification
public void setCaller(String aCaller) {
if (caller == null) // Kind of protect messing with it...
caller = aCaller;
}
// Reference handling
public void setReference(Object anObject) {
reference = anObject;
}
// Logger interface
public static void setLogger(CallLogger aLogger) {
logger = aLogger;
}
public void accept() {
if (state == INITIATED && dialedNumber == null) {
state = ALERTING;
channel.accept();
}
}
public void accept(int rings) {
if (state == INITIATED && dialedNumber == null) {
state = ALERTING;
channel.accept(rings);
connectTime = new Date().getTime();
state = CONNECTED;
}
}
public void answer() {
if ((state == ALERTING || state == INITIATED)
&& dialedNumber == null) {
channel.answer();
connectTime = new Date().getTime();
state = CONNECTED;
}
}
public void answer(int rings) {
if ((state == ALERTING || state == INITIATED)
&& dialedNumber == null) {
state = ALERTING;
channel.answer(rings);
connectTime = new Date().getTime();
state = CONNECTED;
}
}
public void reject(int reason) {
if (state == INITIATED && dialedNumber == null) {
channel.reject(reason);
state = FAILED;
}
}
// local clearing
public void clear() {
if (channel != null) {
Channel c = channel;
drop();
try {
c.clear();
} catch (ChannelException ce){};
}
state = NULL;
}
// remote connect
void connect() {
connectTime = new Date().getTime();
state = CONNECTED;
}
// remote clearing
synchronized void drop() {
if (channel != null) {
try {
pulses = channel.pulses(); // Just in case
} catch (Exception x) {
;
}
endTime = new Date().getTime();
if (logger != null) {
try {
logger.log(this);
} catch(Exception e) {
e.printStackTrace();
}
}
}
channel = null;
state = NULL;
}
public String ani() {
if (ani == null && channel != null) {
ani = channel.ani();
}
return ani;
}
public int pulses() {
if (channel != null) {
pulses = channel.pulses();
}
return pulses;
}
public String toString() {
return "Call " + id;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -