📄 muxprovider.java
字号:
package net.sourceforge.gjtapi.raw.mux;
/*
Copyright (c) 2002 8x8 Inc. (www.8x8.com)
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, provided that the above
copyright notice(s) and this permission notice appear in all copies of
the Software and that both the above copyright notice(s) and this
permission notice appear in supporting documentation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale, use
or other dealings in this Software without prior written authorization
of the copyright holder.
*/
import javax.telephony.*;
import javax.telephony.media.*;
import net.sourceforge.gjtapi.*;
import net.sourceforge.gjtapi.capabilities.*;
import net.sourceforge.gjtapi.raw.*;
import java.util.*;
import java.io.*;
/**
* This is a pluggable provider that multiplexes several other providers together.
* <P>Note that this decides which subprovider to delegate calls off to using Call, Address and
* Terminal to subprovider maps. In the case where a sub-provider does not return a full set of Address
* and Terminal information (throws ResourceUnavailableException for getAddresses() or allows dynamic
* addresses by returning "dynamicAddresses = t" in its capabilities Properties object), we may not have
* full delegation information. We have two options:
* <ol>
* <li>Broadcast all requests where the receiver isn't known
* <li>Catch all address and terminal mappings in Listener events.
* </ol>
* Currently we do both, with no tuning to try to determine if the extra cost of Listener interception
* is worth it. The three methods that provide broadcast are:
* <ul>
* <li>reportCallsOnAddress(String address, boolean flag)
* <li>reportCallsOnTerminal(String terminal, boolean flag)
* <li>reserveCallId(String address)
* </ul>
* Creation date: (2000-02-22 10:53:56)
* @author: Richard Deadman
*/
public class MuxProvider implements TelephonyProvider {
private final static String RESOURCE_NAME = "Mux.props";
private final static String PROVIDER_PREFIX = "Provider";
private final static String CLASS_PREFIX = "Class_";
private final static String PROPS_PREFIX = "Props_";
private final static int UNFLUSHED = 0;
private final static int FLUSHED = 1;
private final static int TOOBIG = 2;
private Map addToSub = new HashMap();
private int addrFlag = UNFLUSHED;
private int termFlag = UNFLUSHED;
private HashSet termData = new HashSet(); // Set of TermData holders.
private Map subToCaps = new HashMap(); // maps sub-providers to RawCapabilities sets
/**
* Set of MuxCallIds that hold 1 or more CallHolders. Each MuxCallId is a logical
* call possibly bridged across multiple low-level sub-providers.
**/
private Set calls = new HashSet();
private Map lowToLogicalMap = new HashMap();
private Map termToSub = new HashMap();
/**
* Add a MuxCallId and its backwards lookup holder to my call set.
* Creation date: (2000-09-26 16:13:08)
* @param ch net.sourceforge.gjtapi.raw.mux.CallHolder
* @param mci net.sourceforge.gjtapi.raw.mux.MuxCallId
*/
private void addCall(CallHolder ch, MuxCallId mci) {
this.getCalls().add(mci);
this.getLowToLogicalMap().put(ch, mci);
}
/**
* Forward to remote provider
*/
public void addListener(TelephonyListener rl) {
Iterator it = this.getSubProviders().iterator();
while (it.hasNext()) {
TelephonyProvider rp = ((TelephonyProvider)it.next());
rp.addListener(new MuxListener(rl, this, rp));
}
}
/**
* Allocate a media type resource to a sub-provider's terminal.
* Creation date: (2000-03-09 10:52:06)
* @param: terminal The terminal to be attached to media resources
* @param type A flag telling the type of media to attach. See RawProvider for static types.
* @param params Control paramters for the resource.
* @return: true if the media was allocated.
*/
public boolean allocateMedia(String terminal, int type, Dictionary params) {
TelephonyProvider rp = this.getTerminalSub(terminal);
if (((RawCapabilities)this.getSubToCaps().get(rp)).allocateMedia)
return rp.allocateMedia(terminal, type, params);
else
return true; // The rawProvider guaranteed that it does not need this call.
}
/**
* Forward answerCall to remote provider
*/
public void answerCall(CallId call, String address, String terminal) throws PrivilegeViolationException, ResourceUnavailableException,
MethodNotSupportedException, RawStateException {
CallHolder ch = ((MuxCallId)call).getLeg(address);
if (ch != null) {
ch.getTpi().answerCall(ch.getCall(), address, terminal);
}
}
/**
* attachMedia method comment.
*/
public boolean attachMedia(net.sourceforge.gjtapi.CallId call, java.lang.String address, boolean onFlag) {
CallHolder ch = ((MuxCallId)call).getLeg(address);
if (ch != null) {
return ch.getTpi().attachMedia(ch.getCall(), address, onFlag);
} else
return false;
}
/**
* beep method comment.
*/
public void beep(net.sourceforge.gjtapi.CallId call) {
Iterator it = ((MuxCallId)call).getCallHolders();
while (it.hasNext()) {
CallHolder ch = (CallHolder)it.next();
ch.getTpi().beep(ch.getCall());
}
}
/**
* Create a call from the given address and terminal to the remote address
*/
public CallId createCall(CallId id, String address, String term, String dest) throws ResourceUnavailableException, PrivilegeViolationException,
InvalidPartyException, InvalidArgumentException, RawStateException,
MethodNotSupportedException {
MuxCallId logicalCall = (MuxCallId)id;
CallHolder ch = logicalCall.getLeg(address);
if (ch == null) {
TelephonyProvider sub = this.getAddressSub(address);
if (sub == null)
throw new InvalidPartyException(InvalidPartyException.ORIGINATING_PARTY);
else {
ch = new CallHolder(sub.reserveCallId(address), sub);
logicalCall.addCall(ch);
}
}
return ch.getTpi().createCall(ch.getCall(), address, term, dest);
}
/**
* find a logical CallId for the given low-level call.
* Creation date: (2000-09-24 0:45:49)
* @param subCall Low-level CallId
* @param subTpi Low-level TelephonyProvider that holds the call, or null.
*/
MuxCallId findCall(CallId subCall, TelephonyProvider subTpi) {
// Check for the logical CallId in the backward lookup table
return this.findCall(new CallHolder(subCall, subTpi));
}
/**
* find a logical CallId for the given low-level call.
* Creation date: (2000-09-24 0:45:49)
* @param ch The CallHolder that represents the sub-call
*/
MuxCallId findCall(CallHolder ch) {
// Check for the logical CallId in the backward lookup table
return (MuxCallId)this.getLowToLogicalMap().get(ch);
}
/**
* Free a media type resource from a sub-provider's terminal.
* Creation date: (2000-03-09 10:52:06)
* @param: terminal The terminal to be freed from media resources
* @param type A flag telling the type of media to free. See RawProvider for static types.
* @return: true if the media was freed.
*/
public boolean freeMedia(String terminal, int type) {
TelephonyProvider rp = this.getTerminalSub(terminal);
if (((RawCapabilities)this.getSubToCaps().get(rp)).allocateMedia)
return rp.freeMedia(terminal, type);
else
return true; // The rawProvider guaranteed that it does not need this call.
}
/**
* Take the values pointed to by the existing and new and return the greatest common denominator in String
* format.
* Creation date: (2000-03-14 15:20:48)
* @author: Richard Deadman
* @param existing An existing value, a String of form "txxx" or "fxxx".
* @param update A new String representation of a boolean value.
*/
private Object gcd(Object existing, Object update) {
boolean oldFlag = false;
if ((existing instanceof String && ((String)existing).length() > 0 &&
Character.toLowerCase(((String)existing).charAt(0)) == 't') ||
(existing instanceof Boolean && ((Boolean)existing).booleanValue()))
// can stop now - already true
return existing;
// test if existing false and update exists -- replace with update
if ((update instanceof String && ((String)update).length() > 0) || (update instanceof Boolean)) {
return update;
}
// existing was false and update not valid
return existing;
}
/**
* Return the static set of addresses I manage, using lazy instantiation.
* Creation date: (2000-02-22 15:32:00)
* @author: Richard Deadman
* @return The set of know addresses I manage
*/
public String[] getAddresses() throws ResourceUnavailableException {
Map addMap = this.getAddToMap();
// test if we need to flush the addresses in
if (this.addrFlag == MuxProvider.UNFLUSHED) {
synchronized (this) {
if (this.addrFlag == MuxProvider.UNFLUSHED) { // double check
// ask each sub-provider
Iterator it = this.getSubProviders().iterator();
while (it.hasNext()) {
TelephonyProvider sub = (TelephonyProvider)it.next();
String[] subAddrs = null;
try {
subAddrs = sub.getAddresses();
} catch (ResourceUnavailableException rue) {
this.addrFlag = MuxProvider.TOOBIG; // mark as not all available
break;
}
int size = subAddrs.length;
for (int i = 0; i < size; i++) {
addMap.put(subAddrs[i], sub);
}
}
if (this.addrFlag == MuxProvider.UNFLUSHED)
this.addrFlag = FLUSHED;
}
}
}
// now test for too big
if (this.addrFlag == MuxProvider.TOOBIG) {
throw new ResourceUnavailableException(ResourceUnavailableException.UNKNOWN,
"Some Sub-TelephonyProviders cannot return all addresses");
}
// must now be set to FLUSHED
return (String[])addMap.keySet().toArray(new String[0]);
}
/**
* Return from the remote provider a set of address names associated with a terminal.
*/
public String[] getAddresses(String terminal) throws InvalidArgumentException {
TelephonyProvider sub = this.getTerminalSub(terminal);
String[] addrs = null;
if (sub != null) {
addrs = sub.getAddresses(terminal);
} else { // broadcast
boolean found = false;
Iterator it = this.getSubProviders().iterator();
while (it.hasNext() && !found) {
try {
sub = (TelephonyProvider)it.next();
addrs = sub.getAddresses(terminal);
// didn't throw exception -- success
found = true;
this.getTermToMap().put(terminal, sub);
} catch (InvalidArgumentException iae) {
// eat and move on to next provider
}
}
if (!found)
throw new InvalidArgumentException("No muxed subproviders know this Terminal: " + terminal);
}
// now map these to the sub-provider
if (addrs != null) {
Map addrMap = this.getAddToMap();
int size = addrs.length;
for (int i = 0; i < size; i++)
addrMap.put(addrs[i], sub);
}
// now return the set
return addrs;
}
/**
* Get the sub-provider mapped to by a certain Address
* Creation date: (2000-03-09 12:26:30)
* @author: Richard Deadman
* @return The subprovider that handles the address
* @param address A address name to find a subprovider for
*/
private TelephonyProvider getAddressSub(String address) {
return (TelephonyProvider)this.getAddToMap().get(address);
}
/**
* getAddressType method comment.
*/
public int getAddressType(java.lang.String name) {
TelephonyProvider sub = this.getAddressSub(name);
return sub.getAddressType(name);
}
/**
* Private accessor for the Address to Subprovider map
* Creation date: (2000-02-22 13:55:20)
* @author: Richard Deadman
* @return The map that maps addresses to sub-providers.
*/
private Map getAddToMap() {
return addToSub;
}
/**
* Find the call snapshot for a given call
*/
public CallData getCall(CallId id) {
Iterator it = ((MuxCallId)id).getCallHolders();
Map connections = new HashMap(); // map of address to best ConnectionData holde -- local if found
int state = Call.IDLE; // best known state.
// now collect all connections and not most active call
while (it.hasNext()) {
CallHolder ch = (CallHolder)it.next();
TelephonyProvider sub = ch.getTpi();
CallData call = sub.getCall(ch.getCall());
// test if any branches are ACTIVE
if (call.callState == Call.ACTIVE)
state = call.callState;
// now map these to the sub-provider
if ((call != null) && (call.connections != null)) {
Map addrMap = this.getAddToMap();
Map termMap = this.getTermToMap();
// record all Addresses and Terminals
int connSize = call.connections.length;
for (int i = 0; i < connSize; i++) {
ConnectionData cd = call.connections[i];
if (this.mapConnection(cd, sub)) {
// note the local connections, overriding any remote entry
// remote connections will be reported by other sub-providers
connections.put(cd.address, cd);
} else {
// only add to connections if no local yet found
if (!connections.containsKey(cd.address))
connections.put(cd.address, cd);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -