session.access(); // modify the access times
}
SipApplicationRoutingRegion region = null;
Serializable newStateInfo = null;
SipApplicationRouterInfo info = null;
boolean targetedApp = false;
// If routing directive is NEW, we should treat this as a new request
// i.e. reset the Application Router state.
if (SipApplicationRoutingDirective.NEW.equals(
request.getRoutingDirective())){
Address initialPoppedRoute = request.getInitialPoppedRoute();
if (initialPoppedRoute != null && initialPoppedRoute.getParameter(AR_STATE) != null) {
try {
ApplicationRouterSelector.getInstance().setRouterContext();
ArInfo restoredArInfo = ArInfo.fromString(initialPoppedRoute.getParameter(AR_STATE));
newStateInfo = restoredArInfo.getStateInfo();
region = restoredArInfo.getRegion();
request.setInternalRoutingDirective(SipApplicationRoutingDirective.CONTINUE, null);
} finally {
ApplicationRouterSelector.getInstance().resetRouterContext();
}
if (m_logger.isLoggable(Level.FINEST)) {
m_logger.log(Level.FINEST, "routing based on restored AR routing info region {0} and stateinfo {1} ", new Object[] {region, newStateInfo});
}
} else {
// try the targeted request first
SipTargetedRequestInfo stri = TargettedRequestHandler.get(request);
//TODO. Complete formatting after review is done.
if (stri != null) {
String appName = stri.getApplicationName();
info = runtimeRouter.getNextApplication(
request,
region,
SipApplicationRoutingDirective.CONTINUE,
stri,
newStateInfo);
if (appName.equals(info.getNextApplicationName())) {
targetedApp = true;
} else {
if (m_logger.isLoggable(Level.FINEST)) {
m_logger.log(Level.FINEST,
"AR selected app {0} expected {1}, continuing non-targeted",
new Object[]{info.getNextApplicationName(), appName});
}
// no match in what the AR returns.
// let's skip this appname and continue with the normal selection.
// remove the parameter from the request to ensure that the request is no longer
// targeted
request.getRequestURI().removeParameter(URIImpl.SASID_PARAM);
}
}
// clear the stateInfo
request.setArInfo(new ArInfo(null,null));
region = determineRegion(request);
newStateInfo = null;
if (m_logger.isLoggable(Level.FINEST)) {
m_logger.log(Level.FINEST, "clearing the state info and setting intial region {0}", new Object[] {region});
}
}
} else {
// CONTINUE or REVERSE
// TODO: what about reverse, should we also reverse the regions?
region = request.getArInfo().getRegion();
newStateInfo = request.getArInfo().getStateInfo();
if (m_logger.isLoggable(Level.FINEST)) {
m_logger.log(Level.FINEST, "continueing internal routing: region {0} and stateinfo {1} ", new Object[] {region, newStateInfo});
}
}
SipApplicationRoutingDirective rDirective = request.getRoutingDirective();
boolean appSelectionComplete = true;
do {
// No match, cleanup and take another round in the Application Router
ApplicationRouterSelector.getInstance().setRouterContext();
// issue 192, guard for malicious application routers
try {
if (!targetedApp) {
if (m_logger.isLoggable(Level.FINEST)) {
m_logger.log(Level.FINEST, "non-targeted request to AR with region {0} and directive {1} ", new Object[] {region, rDirective});
}
info = runtimeRouter.getNextApplication(
request,
region,
rDirective,
null,
newStateInfo);
} else {
targetedApp = false; //only the first one is targeted
}
} catch (RuntimeException e) {
m_logger.log(Level.SEVERE,
"Application Router threw RuntimeException: " + e.getMessage(),
e);
sendARFailed(request);
// give up
return;
} finally {
ApplicationRouterSelector.getInstance().resetRouterContext();
}
if (info != null) {
newStateInfo = info.getStateInfo();
region = info.getRoutingRegion();
} else {
if (m_logger.isLoggable(Level.FINEST)) {
m_logger.log(Level.FINEST, "AR did not return any info. no application deployed??");
}
break;
}
rDirective = SipApplicationRoutingDirective.CONTINUE;
request.setArInfo(new ArInfo(newStateInfo, region));
request.setRegion(region);
if (modifyRouteSet(request, info, region)) {
break;
}
// else treat as NO_ROUTE and look for application name
String application = info.getNextApplicationName();
if (application == null) {
// if (m_logger.isLoggable(Level.FINE)){
// m_logger.log(Level.FINE,
// "Application Dispatcher: no application and NO_ROUTE");