com.haulmont.cuba.web.AbstractConnection.java Source code

Java tutorial

Introduction

Here is the source code for com.haulmont.cuba.web.AbstractConnection.java

Source

/*
 * Copyright (c) 2008-2016 Haulmont.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package com.haulmont.cuba.web;

import com.haulmont.cuba.client.ClientUserSession;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.Configuration;
import com.haulmont.cuba.core.global.GlobalConfig;
import com.haulmont.cuba.core.global.Messages;
import com.haulmont.cuba.core.sys.AppContext;
import com.haulmont.cuba.core.sys.SecurityContext;
import com.haulmont.cuba.security.app.LoginService;
import com.haulmont.cuba.security.app.UserSessionService;
import com.haulmont.cuba.security.entity.User;
import com.haulmont.cuba.security.global.IpMatcher;
import com.haulmont.cuba.security.global.LoginException;
import com.haulmont.cuba.security.global.NoUserSessionException;
import com.haulmont.cuba.security.global.UserSession;
import com.vaadin.server.Page;
import com.vaadin.server.VaadinSession;
import com.vaadin.server.WebBrowser;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

/**
 * Abstract class that encapsulates common connection behaviour for web-client.
 *
 */
public abstract class AbstractConnection implements Connection {

    protected Logger log = LoggerFactory.getLogger(getClass());

    protected Map<ConnectionListener, Object> connListeners = new HashMap<>();
    protected Map<UserSubstitutionListener, Object> usListeners = new HashMap<>();

    protected boolean connected;

    protected LoginService loginService = AppBeans.get(LoginService.NAME);
    protected UserSessionService userSessionService = AppBeans.get(UserSessionService.NAME);
    protected Messages messages = AppBeans.get(Messages.NAME);

    @Override
    public boolean isConnected() {
        return connected;
    }

    @Override
    @Nullable
    public UserSession getSession() {
        return VaadinSession.getCurrent().getAttribute(UserSession.class);
    }

    protected void setSession(ClientUserSession clientUserSession) {
        VaadinSession.getCurrent().setAttribute(UserSession.class, clientUserSession);
    }

    @Override
    public boolean isAlive() {
        if (!isConnected()) {
            return false;
        }

        UserSession session = getSession();
        if (session == null) {
            return false;
        }

        try {
            userSessionService.getUserSession(session.getId());
        } catch (NoUserSessionException ignored) {
            return false;
        }

        return true;
    }

    @Override
    public void update(UserSession session) throws LoginException {
        ClientUserSession clientUserSession = new ClientUserSession(session);

        setSession(clientUserSession);

        connected = true;

        try {
            internalLogin(clientUserSession);
        } catch (LoginException | RuntimeException e) {
            internalLogout();
            throw e;
        } catch (Exception e) {
            internalLogout();
            throw new RuntimeException("Unable to login internal", e);
        }
    }

    protected void internalLogin(UserSession session) throws LoginException {
        AppContext.setSecurityContext(new SecurityContext(session));

        App app = App.getInstance();

        if (!StringUtils.isBlank(session.getUser().getIpMask())) {
            IpMatcher ipMatcher = new IpMatcher(session.getUser().getIpMask());
            if (!ipMatcher.match(app.getClientAddress())) {
                log.info(String.format("IP address %s is not permitted for user %s", app.getClientAddress(),
                        session.getUser().toString()));
                throw new LoginException(messages.getMessage(getClass(), "login.invalidIP"));
            }
        }

        session.setAddress(app.getClientAddress());
        String clientInfo = makeClientInfo();
        session.setClientInfo(clientInfo);

        if (Boolean.TRUE.equals(session.getUser().getTimeZoneAuto()))
            session.setTimeZone(detectTimeZone());

        fireConnectionListeners();

        if (log.isDebugEnabled()) {
            log.debug(String.format("Logged in: user=%s, ip=%s, clientInfo=%s", session.getUser().getLogin(),
                    app.getClientAddress(), clientInfo));
        }
    }

    protected String makeClientInfo() {
        Page page = AppUI.getCurrent().getPage();
        WebBrowser webBrowser = page.getWebBrowser();

        Configuration configuration = AppBeans.get(Configuration.NAME);
        GlobalConfig globalConfig = configuration.getConfig(GlobalConfig.class);
        String serverInfo = "Web (" + globalConfig.getWebHostName() + ":" + globalConfig.getWebPort() + "/"
                + globalConfig.getWebContextName() + ") ";

        return serverInfo + webBrowser.getBrowserApplication();
    }

    protected TimeZone detectTimeZone() {
        Page page = AppUI.getCurrent().getPage();
        WebBrowser webBrowser = page.getWebBrowser();

        int offset = webBrowser.getTimezoneOffset() / 1000 / 60;
        String hours = StringUtils.leftPad(String.valueOf(offset / 60), 2, '0');
        String mins = StringUtils.leftPad(String.valueOf(offset % 60), 2, '0');
        char sign = offset >= 0 ? '+' : '-';
        return TimeZone.getTimeZone("GMT" + sign + hours + mins);
    }

    @Override
    public void substituteUser(User substitutedUser) {
        setSession(new ClientUserSession(loginService.substituteUser(substitutedUser)));
        fireSubstitutionListeners();
    }

    @Override
    public String logout() {
        if (!connected)
            return null;
        internalLogout();
        try {
            fireConnectionListeners();
        } catch (LoginException e) {
            log.warn("Exception on logout:", e);
        }
        return null;
    }

    protected void internalLogout() {
        loginService.logout();

        AppContext.setSecurityContext(null);
        usListeners.clear();
        connected = false;
        setSession(null);
    }

    @Override
    public void addConnectionListener(ConnectionListener listener) {
        connListeners.put(listener, null);
    }

    @Override
    public void removeConnectionListener(ConnectionListener listener) {
        connListeners.remove(listener);
    }

    @Override
    public void addSubstitutionListener(UserSubstitutionListener listener) {
        usListeners.put(listener, null);
    }

    @Override
    public void removeSubstitutionListener(UserSubstitutionListener listener) {
        usListeners.remove(listener);
    }

    protected void fireConnectionListeners() throws LoginException {
        for (ConnectionListener listener : connListeners.keySet()) {
            listener.connectionStateChanged(this);
        }
    }

    protected void fireSubstitutionListeners() {
        for (UserSubstitutionListener listener : usListeners.keySet()) {
            listener.userSubstituted(this);
        }
    }
}