use of com.zimbra.cs.session.SoapSession in project zm-mailbox by Zimbra.
the class ZimbraSoapContext method beginWaitForNotifications.
public boolean beginWaitForNotifications(Continuation continuation, boolean includeDelegates) throws ServiceException {
mWaitForNotifications = true;
continuationResume = new ResumeContinuationListener(continuation);
Session session = SessionCache.lookup(mSessionInfo.sessionId, mAuthTokenAccountId);
if (!(session instanceof SoapSession))
return false;
SoapSession ss = (SoapSession) session;
SoapSession.RegisterNotificationResult result = ss.registerNotificationConnection(mSessionInfo.getPushChannel(!includeDelegates));
switch(result) {
case NO_NOTIFY:
return false;
case DATA_READY:
return false;
case BLOCKING:
return true;
default:
return false;
}
}
use of com.zimbra.cs.session.SoapSession in project zm-mailbox by Zimbra.
the class DocumentHandler method getSession.
/** Fetches a {@link Session} object to persist and manage state between
* SOAP requests. If no appropriate session already exists, a new one
* is created if possible.
*
* @param zsc The encapsulation of the SOAP request's <tt><context</tt>
* element.
* @param stype The type of session needed.
* @return An in-memory {@link Session} object of the specified type,
* referenced by the request's {@link ZimbraSoapContext} object,
* or <tt>null</tt>.
* @see SessionCache#SESSION_SOAP
* @see SessionCache#SESSION_ADMIN */
protected Session getSession(ZimbraSoapContext zsc, Session.Type stype) {
if (zsc == null || stype == null || !zsc.isNotificationEnabled()) {
return null;
}
String authAccountId = zsc.getAuthtokenAccountId();
if (authAccountId == null) {
return null;
}
// if they asked for a SOAP session on a remote host and it's a non-proxied request, we don't notify
boolean isLocal = zsc.isAuthUserOnLocalhost();
if (stype == Session.Type.SOAP && !isLocal && !zsc.isSessionProxied()) {
return null;
}
Session s = null;
// if the caller referenced a session of this type, fetch it from the session cache
SessionInfo sinfo = zsc.getSessionInfo();
if (sinfo != null) {
s = SessionCache.lookup(sinfo.sessionId, authAccountId);
if (s == null) {
// purge dangling references from the context's list of referenced sessions
ZimbraLog.session.info("requested session no longer exists: " + sinfo.sessionId);
zsc.clearSessionInfo();
} else if (s.getSessionType() != stype) {
// only want a session of the appropriate type
s = null;
}
}
// if there's no valid referenced session, create a new session of the requested type
if (s == null) {
try {
if (stype == Session.Type.SOAP) {
s = SoapSessionFactory.getInstance().getSoapSession(zsc).register();
} else if (stype == Session.Type.ADMIN) {
s = new AdminSession(authAccountId).register();
}
} catch (ServiceException e) {
ZimbraLog.session.info("exception while creating session", e);
}
if (s != null) {
zsc.recordNewSession(s.getSessionId());
}
}
// (note that if the requested account is remote, getDelegateSession returns null)
if (s instanceof SoapSession && zsc.isDelegatedRequest()) {
Session delegate = ((SoapSession) s).getDelegateSession(zsc.getRequestedAccountId());
if (delegate != null) {
s = delegate;
}
}
return s;
}
use of com.zimbra.cs.session.SoapSession in project zm-mailbox by Zimbra.
the class GetInfo method handle.
@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Account account = getRequestedAccount(zsc);
if (!canAccessAccount(zsc, account)) {
throw ServiceException.PERM_DENIED("can not access account");
}
// figure out the subset of data the caller wants (default to all data)
String secstr = request.getAttribute(AccountConstants.A_SECTIONS, null);
Set<Section> sections;
if (secstr != null) {
sections = EnumSet.noneOf(Section.class);
for (String sec : Splitter.on(',').omitEmptyStrings().trimResults().split(secstr)) {
sections.add(Section.lookup(sec));
}
} else {
sections = EnumSet.allOf(Section.class);
}
String rightsStr = request.getAttribute(AccountConstants.A_RIGHTS, null);
Set<Right> rights = null;
if (rightsStr != null) {
RightManager rightMgr = RightManager.getInstance();
rights = Sets.newHashSet();
for (String right : Splitter.on(',').omitEmptyStrings().trimResults().split(rightsStr)) {
rights.add(rightMgr.getUserRight(right));
}
}
Element response = zsc.createElement(AccountConstants.GET_INFO_RESPONSE);
response.addAttribute(AccountConstants.E_VERSION, BuildInfo.FULL_VERSION, Element.Disposition.CONTENT);
response.addAttribute(AccountConstants.E_ID, account.getId(), Element.Disposition.CONTENT);
response.addAttribute(AccountConstants.E_NAME, account.getUnicodeName(), Element.Disposition.CONTENT);
try {
response.addAttribute(AccountConstants.E_CRUMB, zsc.getAuthToken().getCrumb(), Element.Disposition.CONTENT);
} catch (AuthTokenException e) {
// shouldn't happen
ZimbraLog.account.warn("can't generate crumb", e);
}
long lifetime = zsc.getAuthToken().getExpires() - System.currentTimeMillis();
response.addAttribute(AccountConstants.E_LIFETIME, lifetime, Element.Disposition.CONTENT);
Provisioning prov = Provisioning.getInstance();
// bug 53770, return if the request is using a delegated authtoken issued to an admin account
AuthToken authToken = zsc.getAuthToken();
if (authToken.isDelegatedAuth()) {
Account admin = prov.get(AccountBy.id, authToken.getAdminAccountId());
if (admin != null) {
boolean isAdmin = AdminAccessControl.isAdequateAdminAccount(admin);
if (isAdmin) {
response.addAttribute(AccountConstants.E_ADMIN_DELEGATED, true, Element.Disposition.CONTENT);
}
}
}
try {
Server server = prov.getLocalServer();
if (server != null) {
response.addAttribute(AccountConstants.A_DOCUMENT_SIZE_LIMIT, server.getFileUploadMaxSize());
}
Config config = prov.getConfig();
if (config != null) {
long maxAttachSize = config.getMtaMaxMessageSize();
if (maxAttachSize == 0) {
maxAttachSize = -1;
/* means unlimited */
}
response.addAttribute(AccountConstants.A_ATTACHMENT_SIZE_LIMIT, maxAttachSize);
}
} catch (ServiceException e) {
}
if (sections.contains(Section.MBOX) && Provisioning.onLocalServer(account)) {
response.addAttribute(AccountConstants.E_REST, UserServlet.getRestUrl(account), Element.Disposition.CONTENT);
try {
Mailbox mbox = getRequestedMailbox(zsc);
response.addAttribute(AccountConstants.E_QUOTA_USED, mbox.getSize(), Element.Disposition.CONTENT);
Session s = (Session) context.get(SoapEngine.ZIMBRA_SESSION);
if (s instanceof SoapSession) {
// we have a valid session; get the stats on this session
response.addAttribute(AccountConstants.E_PREVIOUS_SESSION, ((SoapSession) s).getPreviousSessionTime(), Element.Disposition.CONTENT);
response.addAttribute(AccountConstants.E_LAST_ACCESS, ((SoapSession) s).getLastWriteAccessTime(), Element.Disposition.CONTENT);
response.addAttribute(AccountConstants.E_RECENT_MSGS, ((SoapSession) s).getRecentMessageCount(), Element.Disposition.CONTENT);
} else {
// we have no session; calculate the stats from the mailbox and the other SOAP sessions
long lastAccess = mbox.getLastSoapAccessTime();
response.addAttribute(AccountConstants.E_PREVIOUS_SESSION, lastAccess, Element.Disposition.CONTENT);
response.addAttribute(AccountConstants.E_LAST_ACCESS, lastAccess, Element.Disposition.CONTENT);
response.addAttribute(AccountConstants.E_RECENT_MSGS, mbox.getRecentMessageCount(), Element.Disposition.CONTENT);
}
} catch (ServiceException e) {
}
}
doCos(account, response);
Map<String, Object> attrMap = account.getUnicodeAttrs();
Locale locale = Provisioning.getInstance().getLocale(account);
if (sections.contains(Section.PREFS)) {
Element prefs = response.addUniqueElement(AccountConstants.E_PREFS);
GetPrefs.doPrefs(account, prefs, attrMap, null);
}
if (sections.contains(Section.ATTRS)) {
Element attrs = response.addUniqueElement(AccountConstants.E_ATTRS);
doAttrs(account, locale.toString(), attrs, attrMap);
}
if (sections.contains(Section.ZIMLETS)) {
Element zimlets = response.addUniqueElement(AccountConstants.E_ZIMLETS);
doZimlets(zimlets, account);
}
if (sections.contains(Section.PROPS)) {
Element props = response.addUniqueElement(AccountConstants.E_PROPERTIES);
doProperties(props, account);
}
if (sections.contains(Section.IDENTS)) {
Element ids = response.addUniqueElement(AccountConstants.E_IDENTITIES);
doIdentities(ids, account);
}
if (sections.contains(Section.SIGS)) {
Element sigs = response.addUniqueElement(AccountConstants.E_SIGNATURES);
doSignatures(sigs, account);
}
if (sections.contains(Section.DSRCS)) {
Element ds = response.addUniqueElement(AccountConstants.E_DATA_SOURCES);
doDataSources(ds, account);
}
if (sections.contains(Section.CHILDREN)) {
Element ca = response.addUniqueElement(AccountConstants.E_CHILD_ACCOUNTS);
doChildAccounts(ca, account, zsc.getAuthToken());
}
if (rights != null && !rights.isEmpty()) {
Element eRights = response.addUniqueElement(AccountConstants.E_RIGHTS);
doDiscoverRights(eRights, account, rights);
}
GetAccountInfo.addUrls(response, account);
for (GetInfoExt extension : extensions) {
extension.handle(zsc, response);
}
return response;
}
use of com.zimbra.cs.session.SoapSession in project zm-mailbox by Zimbra.
the class SoapEngine method generateResponseHeader.
/** Creates a <tt><context></tt> element for the SOAP Header containing
* session information and change notifications.<p>
*
* Sessions -- those passed in the SOAP request <tt><context></tt>
* block and those created during the course of processing the request -- are
* listed:<p>
* <tt><sessionId [type="admin"] id="12">12</sessionId></tt>
*
* @return A new <tt><context></tt> {@link Element}, or <tt>null</tt>
* if there is no relevant information to encapsulate. */
private Element generateResponseHeader(ZimbraSoapContext zsc) {
String authAccountId = zsc.getAuthtokenAccountId();
String requestedAccountId = zsc.getRequestedAccountId();
Element ctxt = zsc.createElement(HeaderConstants.CONTEXT);
boolean requiresChangeHeader = requestedAccountId != null;
try {
SessionInfo sinfo = zsc.getSessionInfo();
Session session = sinfo == null ? null : SessionCache.lookup(sinfo.sessionId, authAccountId);
if (session != null) {
// session ID is valid, so ping it back to the client:
ZimbraSoapContext.encodeSession(ctxt, session.getSessionId(), session.getSessionType());
if (session instanceof SoapSession) {
SoapSession soap = (SoapSession) session;
if (session.getTargetAccountId().equals(requestedAccountId)) {
requiresChangeHeader = false;
}
// put <refresh> blocks back for any newly-created SoapSession objects
if (sinfo.created || soap.requiresRefresh(sinfo.sequence)) {
ZimbraLog.session.debug("returning refresh block; reason=%s", sinfo.created ? "new session" : "sequence-based");
soap.putRefresh(ctxt, zsc);
}
// put <notify> blocks back for any SoapSession objects
soap.putNotifications(ctxt, zsc, sinfo.sequence);
// add any extension headers
SoapContextExtension.addExtensionHeaders(ctxt, zsc, soap);
}
}
// so encode it here as a last resort
if (requiresChangeHeader) {
try {
String explicitAcct = requestedAccountId.equals(authAccountId) ? null : requestedAccountId;
// send the <change> block
// <change token="555" [acct="4f778920-1a84-11da-b804-6b188d2a20c4"]/>
Mailbox mbox = DocumentHandler.getRequestedMailbox(zsc, false);
if (mbox != null) {
ctxt.addUniqueElement(HeaderConstants.E_CHANGE).addAttribute(HeaderConstants.A_CHANGE_ID, mbox.getLastChangeID()).addAttribute(HeaderConstants.A_ACCOUNT_ID, explicitAcct);
}
} catch (ServiceException e) {
// eat error for right now
}
}
return ctxt;
} catch (ServiceException e) {
ZimbraLog.session.info("ServiceException while putting soap session refresh data", e);
return null;
}
}
use of com.zimbra.cs.session.SoapSession in project zm-mailbox by Zimbra.
the class CrossServerNotification method getHandler.
@Override
public MessageHandler getHandler() {
return new MessageHandler() {
@Override
public void handle(Message m, String clientId) {
if (!(m instanceof CrossServerNotification)) {
return;
}
CrossServerNotification message = (CrossServerNotification) m;
Collection<Session> sessions = SessionCache.getSoapSessions(m.getRecipientAccountId());
if (sessions == null) {
log.warn("no active sessions for account %s", m.getRecipientAccountId());
return;
}
RemoteNotifications soapNtfn = null, jsonNtfn = null;
try {
org.dom4j.Document dom = org.dom4j.DocumentHelper.parseText(message.getPayload());
soapNtfn = new RemoteNotifications(Element.convertDOM(dom.getRootElement(), XMLElement.mFactory));
jsonNtfn = new RemoteNotifications(Element.convertDOM(dom.getRootElement(), JSONElement.mFactory));
} catch (DocumentException e) {
log.warn("cannot parse notification from %s", clientId, e);
return;
}
for (Session session : sessions) {
log.debug("notifying session %s", session.toString());
SoapSession ss = (SoapSession) session;
SoapProtocol responseProtocol = ss.getResponseProtocol();
if (responseProtocol == SoapProtocol.Soap11 || responseProtocol == SoapProtocol.Soap12) {
ss.addRemoteNotifications(soapNtfn);
} else if (responseProtocol == SoapProtocol.SoapJS) {
ss.addRemoteNotifications(jsonNtfn);
}
ss.forcePush();
}
}
};
}
Aggregations