handler.getSession(context);  if (needsAuth || needsAdminAuth) response = handler.proxyIfNecessary(request, context);
response = handler.proxyIfNecessary(request, context);
    Element dispatchRequest(Element request, Map<String, Object> context, ZimbraSoapContext zsc) {        SoapProtocol soapProto = zsc.getResponseProtocol();        if (request == null)            return soapProto.soapFault(ServiceException.INVALID_REQUEST("no document specified", null));        DocumentHandler handler = mDispatcher.getHandler(request);        if (handler == null)             return soapProto.soapFault(ServiceException.UNKNOWN_DOCUMENT(request.getQualifiedName(), null));        if (RedoLogProvider.getInstance().isSlave() && !handler.isReadOnly())            return soapProto.soapFault(ServiceException.NON_READONLY_OPERATION_DENIED());        if (!Config.userServicesEnabled() && !(handler instanceof AdminDocumentHandler))            return soapProto.soapFault(ServiceException.TEMPORARILY_UNAVAILABLE());        boolean needsAuth = handler.needsAuth(context);        boolean needsAdminAuth = handler.needsAdminAuth(context);        if (needsAuth || needsAdminAuth) {            AuthToken at = zsc != null ? zsc.getAuthToken() : null;            if (at == null)                return soapProto.soapFault(ServiceException.AUTH_REQUIRED());            if (needsAdminAuth && !at.isAdmin()) {                boolean ok = handler.domainAuthSufficient(context) && at.isDomainAdmin();                if (!ok)                    return soapProto.soapFault(ServiceException.PERM_DENIED("need admin token"));            }            // Make sure that the account is active and has not been deleted            // since the last request            try {                Account account = DocumentHandler.getRequestedAccount(zsc);                if (!account.getAccountStatus().equals(Provisioning.ACCOUNT_STATUS_ACTIVE)) {                    if (zsc.isDelegatedRequest())                        return soapProto.soapFault(AccountServiceException.ACCOUNT_INACTIVE(account.getName()));                    else                        return soapProto.soapFault(ServiceException.AUTH_EXPIRED());                }            } catch (ServiceException ex) {                return soapProto.soapFault(ex);            }        }                Element response = null;        try {            // fault in a session for this handler (if necessary) before executing the command            handler.getSession(context);            // try to proxy the request if necesary (don't proxy commands that don't require auth)            if (needsAuth || needsAdminAuth)                response = handler.proxyIfNecessary(request, context);            // if no proxy, execute the request locally            if (response == null)                response = handler.handle(request, context);        } catch (SoapFaultException e) {            response = e.getFault() != null ? e.getFault().detach() : soapProto.soapFault(ServiceException.FAILURE(e.toString(), e));             if (!e.isSourceLocal())                mLog.debug("handler exception", e);        } catch (ServiceException e) {            response = soapProto.soapFault(e);            mLog.info("handler exception", e);            // XXX: if the session was new, do we want to delete it?        } catch (Throwable e) {            // TODO: better exception stack traces during develope?            response = soapProto.soapFault(ServiceException.FAILURE(e.toString(), e));            if (e instanceof OutOfMemoryError)                Zimbra.halt("handler exception", e);            mLog.warn("handler exception", e);            // XXX: if the session was new, do we want to delete it?        }        return response;    }