com.haulmont.cuba.web.sys.LinkHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.haulmont.cuba.web.sys.LinkHandler.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.sys;

import com.haulmont.cuba.core.app.DataService;
import com.haulmont.cuba.core.entity.AbstractSearchFolder;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.global.*;
import com.haulmont.cuba.gui.NoSuchScreenException;
import com.haulmont.cuba.gui.WindowManager.OpenType;
import com.haulmont.cuba.gui.components.Action;
import com.haulmont.cuba.gui.components.Component;
import com.haulmont.cuba.gui.components.DialogAction;
import com.haulmont.cuba.gui.components.Frame.MessageType;
import com.haulmont.cuba.gui.components.Window;
import com.haulmont.cuba.gui.config.WindowConfig;
import com.haulmont.cuba.gui.config.WindowInfo;
import com.haulmont.cuba.gui.exception.AccessDeniedHandler;
import com.haulmont.cuba.gui.exception.EntityAccessExceptionHandler;
import com.haulmont.cuba.gui.exception.NoSuchScreenHandler;
import com.haulmont.cuba.security.entity.User;
import com.haulmont.cuba.security.entity.UserSubstitution;
import com.haulmont.cuba.security.global.UserSession;
import com.haulmont.cuba.web.App;
import com.haulmont.cuba.web.AppUI;
import com.haulmont.cuba.web.actions.ChangeSubstUserAction;
import com.haulmont.cuba.web.actions.DoNotChangeSubstUserAction;
import com.haulmont.cuba.web.app.folders.Folders;
import com.vaadin.server.Page;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinService;
import com.vaadin.server.WrappedSession;
import com.vaadin.ui.JavaScript;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;

import javax.inject.Inject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Handles links from outside of the application.
 * <br> This bean is used particularly when a request URL contains one of
 * {@link com.haulmont.cuba.web.WebConfig#getLinkHandlerActions()} actions.
 */
@org.springframework.stereotype.Component(LinkHandler.NAME)
@Scope("prototype")
public class LinkHandler {

    public static final String NAME = "cuba_LinkHandler";

    private final Logger log = LoggerFactory.getLogger(LinkHandler.class);

    @Inject
    protected Messages messages;

    @Inject
    protected TimeSource timeSource;

    @Inject
    protected DataService dataService;

    @Inject
    protected Folders folders;

    @Inject
    protected Metadata metadata;

    @Inject
    protected AccessDeniedHandler accessDeniedHandler;
    @Inject
    protected NoSuchScreenHandler noSuchScreenHandler;
    @Inject
    protected EntityAccessExceptionHandler entityAccessExceptionHandler;

    protected App app;
    protected String action;
    protected Map<String, String> requestParams;

    public LinkHandler(App app, String action, Map<String, String> requestParams) {
        this.app = app;
        this.action = action;
        this.requestParams = requestParams;
    }

    /**
     * Check state of LinkHandler and application.
     *
     * @return true if application and LinkHandler in an appropriate state.
     */
    public boolean canHandleLink() {
        return app.getTopLevelWindow() instanceof Window.HasWorkArea;
    }

    /**
     * Called to handle the link.
     */
    public void handle() {
        try {
            String folderId = requestParams.get("folder");
            if (!StringUtils.isEmpty(folderId)) {
                AbstractSearchFolder folder = loadFolder(UUID.fromString(folderId));
                if (folder != null) {
                    folders.openFolder(folder);
                } else {
                    log.warn("Folder not found: {}", folderId);
                }
                return;
            }

            String screenName = requestParams.get("screen");
            if (screenName == null) {
                log.warn("ScreenId not found in request parameters");
                return;
            }

            WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME);
            final WindowInfo windowInfo = windowConfig.getWindowInfo(screenName);
            if (windowInfo == null) {
                log.warn("WindowInfo not found for screen: {}", screenName);
                return;
            }

            UUID userId = getUUID(requestParams.get("user"));
            UserSession userSession = app.getConnection().getSession();
            if (userSession == null) {
                log.warn("No user session");
                return;
            }

            if (!(userId == null || userSession.getCurrentOrSubstitutedUser().getId().equals(userId))) {
                substituteUserAndOpenWindow(windowInfo, userId);
            } else {
                openWindow(windowInfo, requestParams);
            }
        } catch (AccessDeniedException e) {
            accessDeniedHandler.handle(e, app.getWindowManager());
        } catch (NoSuchScreenException e) {
            noSuchScreenHandler.handle(e, app.getWindowManager());
        } catch (EntityAccessException e) {
            entityAccessExceptionHandler.handle(e, app.getWindowManager());
        } finally {
            VaadinRequest request = VaadinService.getCurrentRequest();
            WrappedSession wrappedSession = request.getWrappedSession();
            wrappedSession.removeAttribute(AppUI.LAST_REQUEST_PARAMS_ATTR);
            wrappedSession.removeAttribute(AppUI.LAST_REQUEST_ACTION_ATTR);
        }
    }

    protected void substituteUserAndOpenWindow(final WindowInfo windowInfo, UUID userId) {
        UserSession userSession = app.getConnection().getSession();
        final User substitutedUser = loadUser(userId, userSession.getUser());
        if (substitutedUser != null) {
            Map<String, String> currentRequestParams = new HashMap<>(requestParams);

            app.getWindowManager().showOptionDialog(messages.getMainMessage("toSubstitutedUser.title"),
                    getDialogMessage(substitutedUser), MessageType.CONFIRMATION_HTML,
                    new Action[] { new ChangeSubstUserAction(substitutedUser) {
                        @Override
                        public void doAfterChangeUser() {
                            super.doAfterChangeUser();
                            openWindow(windowInfo, currentRequestParams);
                        }

                        @Override
                        public void doRevert() {
                            super.doRevert();

                            JavaScript js = Page.getCurrent().getJavaScript();
                            js.execute("window.close();");
                        }

                        @Override
                        public String getCaption() {
                            return messages.getMainMessage("action.switch");
                        }
                    }, new DoNotChangeSubstUserAction() {
                        @Override
                        public void actionPerform(Component component) {
                            super.actionPerform(component);

                            JavaScript js = Page.getCurrent().getJavaScript();
                            js.execute("window.close();");
                        }

                        @Override
                        public String getCaption() {
                            return messages.getMainMessage("action.cancel");
                        }
                    } });
        } else {
            User user = loadUser(userId);
            app.getWindowManager().showOptionDialog(messages.getMainMessage("warning.title"),
                    getWarningMessage(user), MessageType.WARNING_HTML,
                    new Action[] { new DialogAction(DialogAction.Type.OK).withHandler(event -> {
                        JavaScript js = Page.getCurrent().getJavaScript();
                        js.execute("window.close();");
                    }) });
        }
    }

    protected UUID getUUID(String id) {
        if (StringUtils.isBlank(id))
            return null;

        UUID uuid;
        try {
            uuid = UUID.fromString(id);
        } catch (IllegalArgumentException e) {
            uuid = null;
        }
        return uuid;
    }

    protected String getWarningMessage(User user) {
        if (user == null)
            return messages.getMainMessage("warning.userNotFound");
        return messages.formatMainMessage("warning.msg",
                StringUtils.isBlank(user.getName()) ? user.getLogin() : user.getName());
    }

    protected User loadUser(UUID userId, User user) {
        if (user.getId().equals(userId))
            return user;
        LoadContext loadContext = new LoadContext(UserSubstitution.class);
        LoadContext.Query query = new LoadContext.Query("select su from sec$UserSubstitution us join us.user u "
                + "join us.substitutedUser su where u.id = :id and su.id = :userId and "
                + "(us.endDate is null or us.endDate >= :currentDate) and (us.startDate is null or us.startDate <= :currentDate)");
        query.setParameter("id", user);
        query.setParameter("userId", userId);
        query.setParameter("currentDate", timeSource.currentTimestamp());
        loadContext.setQuery(query);
        List<User> users = dataService.loadList(loadContext);
        return users.isEmpty() ? null : users.get(0);
    }

    protected User loadUser(UUID userId) {
        LoadContext<User> loadContext = new LoadContext<>(User.class);
        LoadContext.Query query = new LoadContext.Query("select u from sec$User u where u.id = :userId");
        query.setParameter("userId", userId);
        loadContext.setQuery(query);
        List<User> users = dataService.loadList(loadContext);
        return users.isEmpty() ? null : users.get(0);
    }

    protected String getDialogMessage(User user) {
        return messages.formatMainMessage("toSubstitutedUser.msg",
                StringUtils.isBlank(user.getName()) ? user.getLogin() : user.getName());
    }

    protected void openWindow(WindowInfo windowInfo, Map<String, String> requestParams) {
        String itemStr = requestParams.get("item");
        String openTypeParam = requestParams.get("openType");
        OpenType openType = OpenType.NEW_TAB;

        if (StringUtils.isNotEmpty(openTypeParam)) {
            try {
                openType = OpenType.valueOf(openTypeParam);
            } catch (IllegalArgumentException e) {
                log.warn("Unknown open type ({}) in request parameters", openTypeParam);
            }
        }

        if (itemStr == null) {
            app.getWindowManager().openWindow(windowInfo, openType, getParamsMap(requestParams));
        } else {
            EntityLoadInfo info = EntityLoadInfo.parse(itemStr);
            if (info == null) {
                log.warn("Invalid item definition: {}", itemStr);
            } else {
                Entity entity = loadEntityInstance(info);
                if (entity != null)
                    app.getWindowManager().openEditor(windowInfo, entity, openType, getParamsMap(requestParams));
                else
                    throw new EntityAccessException();
            }
        }
    }

    protected Map<String, Object> getParamsMap(Map<String, String> requestParams) {
        Map<String, Object> params = new HashMap<>();
        String paramsStr = requestParams.get("params");
        if (paramsStr == null)
            return params;

        String[] entries = paramsStr.split(",");
        for (String entry : entries) {
            String[] parts = entry.split(":");
            if (parts.length != 2) {
                log.warn("Invalid parameter: {}", entry);
                return params;
            }
            String name = parts[0];
            String value = parts[1];
            EntityLoadInfo info = EntityLoadInfo.parse(value);
            if (info != null) {
                Entity entity = loadEntityInstance(info);
                if (entity != null)
                    params.put(name, entity);
            } else if (Boolean.TRUE.toString().equals(value) || Boolean.FALSE.toString().equals(value)) {
                params.put(name, BooleanUtils.toBoolean(value));
            } else {
                params.put(name, value);
            }
        }
        return params;
    }

    protected Entity loadEntityInstance(EntityLoadInfo info) {
        if (info.isNewEntity()) {
            return metadata.create(info.getMetaClass());
        }

        @SuppressWarnings("unchecked")
        LoadContext<Entity> ctx = new LoadContext(info.getMetaClass()).setId(info.getId());
        if (info.getViewName() != null)
            ctx.setView(info.getViewName());
        Entity entity;
        try {
            entity = dataService.load(ctx);
        } catch (Exception e) {
            log.warn("Unable to load item: {}", info, e);
            return null;
        }
        return entity;
    }

    protected AbstractSearchFolder loadFolder(UUID folderId) {
        return dataService.load(new LoadContext<>(AbstractSearchFolder.class).setId(folderId));
    }
}