edu.kit.dama.ui.admin.AdminUIMainView.java Source code

Java tutorial

Introduction

Here is the source code for edu.kit.dama.ui.admin.AdminUIMainView.java

Source

/* 
 * Copyright 2015 Karlsruhe Institute of Technology.
 *
 * 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 edu.kit.dama.ui.admin;

import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.data.Property;
import com.vaadin.event.LayoutEvents;
import com.vaadin.server.DefaultErrorHandler;
import static com.vaadin.server.DefaultErrorHandler.doDefault;
import com.vaadin.server.ExternalResource;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.server.VaadinSession;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Image;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import edu.kit.dama.authorization.entities.ReferenceId;
import edu.kit.dama.authorization.entities.Role;
import edu.kit.dama.authorization.entities.impl.AuthorizationContext;
import edu.kit.dama.authorization.exceptions.EntityNotFoundException;
import edu.kit.dama.authorization.exceptions.UnauthorizedAccessAttemptException;
import edu.kit.dama.authorization.services.administration.ResourceServiceLocal;
import edu.kit.dama.mdm.base.DigitalObject;
import edu.kit.dama.mdm.base.UserData;
import edu.kit.dama.mdm.core.IMetaDataManager;
import edu.kit.dama.mdm.core.MetaDataManagement;
import edu.kit.dama.ui.admin.login.AbstractLoginComponent;
import edu.kit.dama.ui.admin.login.OrcidLoginComponent;
import edu.kit.dama.ui.admin.login.EmailPasswordLoginComponent;
import edu.kit.dama.ui.admin.utils.UIComponentTools;
import edu.kit.dama.ui.admin.utils.UIHelper;
import edu.kit.dama.ui.simon.panel.SimonMainPanel;
import edu.kit.dama.ui.simon.util.SimonConfigurator;
import edu.kit.dama.util.Constants;
import edu.kit.dama.util.DataManagerSettings;
import edu.kit.dama.util.StackTraceUtil;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.annotation.WebServlet;
import org.apache.commons.configuration.ConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Theme("mytheme")
@SuppressWarnings("serial")
public class AdminUIMainView extends UI {

    private static final Logger LOGGER = LoggerFactory.getLogger(AdminUIMainView.class);

    public enum VIEW {

        LOGIN, SIMON, INFORMATION, PROFILE, SETTINGS, LANDING
    }

    private VerticalLayout loginForm;
    private AbstractLoginComponent loginComponent;
    private AbstractLoginComponent[] loginComponents = null;
    private HorizontalLayout header = null;
    private Label title = null;
    private Image logo = null;
    private SimonMainPanel simonPanel = null;
    private ProfileView profileView = null;
    private InformationView informationView = null;
    private LoginInformationBar loginInformationBar = null;
    private DataManagerSettingsPanel datamanagerSettings = null;
    private LandingPageComponent landingPage;
    private VerticalLayout mainLayout;
    private Component viewComponent;
    private VIEW currentView;
    private boolean INITIALIZING = true;

    @WebServlet(value = "/*", asyncSupported = true)
    @VaadinServletConfiguration(productionMode = false, ui = AdminUIMainView.class, widgetset = "edu.kit.dama.ui.admin.AppWidgetSet")
    public static class Servlet extends VaadinServlet {

        @Override
        public void destroy() {
            //destroy also all metadata management instances on redeployment in order to close all database connections
            MetaDataManagement.getMetaDataManagement().destroy();
            super.destroy();
        }

    }

    @Override
    protected void init(VaadinRequest request) {
        try {
            //might be OAuth redirect
            String pendingAuthId = null;
            AbstractLoginComponent.AUTH_MODE type = AbstractLoginComponent.AUTH_MODE.LOGIN;
            if (VaadinSession.getCurrent().getAttribute("auth_pending") != null) {
                pendingAuthId = (String) VaadinSession.getCurrent().getAttribute("auth_pending");
            } else if (VaadinSession.getCurrent().getAttribute("registration_pending") != null) {
                pendingAuthId = (String) VaadinSession.getCurrent().getAttribute("registration_pending");
                type = AbstractLoginComponent.AUTH_MODE.REGISTRATION;
            }

            doBasicSetup();

            boolean isLandingPage = request.getParameter("landing") != null;
            String landingObjectId = request.getParameter("oid");
            //setup header
            setupHeader(isLandingPage, landingObjectId);

            //setup login form
            setupLoginForm(type, pendingAuthId, request);
            if (pendingAuthId != null && !type.equals(AbstractLoginComponent.AUTH_MODE.REGISTRATION)) {
                //auth will redirect to start page so we'll stop here
                return;
            }

            mainLayout = new VerticalLayout();
            mainLayout.setMargin(false);
            mainLayout.setSizeFull();

            //setup login bar
            loginInformationBar = new LoginInformationBar(this);
            loginInformationBar.reload();

            setContent(mainLayout);
            setSizeFull();
            if (isLandingPage) {
                //setup landing page
                LOGGER.debug("Showing landing page.");
                setupLandingPage(request);
            } else {
                refreshMainLayout();
            }
            INITIALIZING = false;
        } catch (Throwable t) {
            LOGGER.error("Failed to init app.", t);
        }
    }

    private void doBasicSetup() {
        //configure SiMon
        try {
            String path = DataManagerSettings.getSingleton()
                    .getStringProperty(DataManagerSettings.SIMON_CONFIG_LOCATION_ID, null);
            if (path == null || !new File(path).exists()) {
                throw new ConfigurationException("Configuration element '"
                        + DataManagerSettings.SIMON_CONFIG_LOCATION_ID + "' is not set or not a valid directory.");
            }
            File configLocation = new File(path);
            SimonConfigurator.getSingleton().setConfigLocation(configLocation);
        } catch (ConfigurationException ex) {
            LOGGER.error("Failed to initialize SimpleMonitoring", ex);
        }

        //set error handler in order to catch unhandled exceptions
        UI.getCurrent().setErrorHandler(new DefaultErrorHandler() {
            @Override
            public void error(com.vaadin.server.ErrorEvent event) {
                String cause = "<h3>An unexpected error has occured. Please reload the page.<br/>"
                        + "If the error persists, please contact an administrator.</h3>";

                Label errorLabel = new Label(cause, ContentMode.HTML);
                errorLabel.setDescription(StackTraceUtil.getCustomStackTrace(event.getThrowable(), false));
                LOGGER.error("An unhandled exception has occured!", event.getThrowable());
                // Display the error message in a custom fashion
                mainLayout.addComponent(errorLabel, 0);

                // Do the default error handling (optional)
                doDefault(event);
            }
        });
    }

    private void setupHeader(boolean landingPage, String landingObjectId) {
        if (!landingPage) {
            String repositoryName = DataManagerSettings.getSingleton()
                    .getStringProperty(DataManagerSettings.GENERAL_REPOSITORY_NAME, "Repository");
            title = new Label("<h1>" + repositoryName + " Administration</h1><h5>Build " + readVersion() + "</h5>",
                    ContentMode.HTML);
            title.setDescription("Click to return to main page.");
            title.setWidth("50%");
            title.addStyleName("title");
            title.addStyleName("myclickablecomponent");

            logo = new Image();
            String logoUrl;
            try {
                logoUrl = new URL(DataManagerSettings.getSingleton().getStringProperty(
                        DataManagerSettings.GENERAL_REPOSITORY_LOGO_URL,
                        "http://datamanager.kit.edu/dama/logo_default.png")).toString();
            } catch (MalformedURLException ex) {
                logoUrl = URI.create("http://datamanager.kit.edu/dama/logo_default.png").toString();
            }
            logo.setSource(new ExternalResource(logoUrl));

            header = new HorizontalLayout(logo, title);
            header.setComponentAlignment(logo, Alignment.MIDDLE_CENTER);
            header.setComponentAlignment(title, Alignment.MIDDLE_CENTER);
        } else {
            title = new Label(
                    "<h1>Landing Page for Object #" + landingObjectId + "</h1><h5>Build " + readVersion() + "</h5>",
                    ContentMode.HTML);
            title.setWidth("50%");
            title.addStyleName("title");
            title.addStyleName("myclickablecomponent");

            logo = new Image();
            String logoUrl;
            try {
                logoUrl = new URL(DataManagerSettings.getSingleton().getStringProperty(
                        DataManagerSettings.GENERAL_REPOSITORY_LOGO_URL,
                        "http://datamanager.kit.edu/dama/logo_default.png")).toString();
            } catch (MalformedURLException ex) {
                logoUrl = URI.create("http://datamanager.kit.edu/dama/logo_default.png").toString();
            }
            logo.setSource(new ExternalResource(logoUrl));

            header = new HorizontalLayout(logo, title);
            header.setComponentAlignment(logo, Alignment.MIDDLE_CENTER);
            header.setComponentAlignment(title, Alignment.MIDDLE_CENTER);
        }
    }

    private void setupLandingPage(VaadinRequest request) {
        String oid = (String) request.getParameter("oid");
        IMetaDataManager mdm = MetaDataManagement.getMetaDataManagement().getMetaDataManager();
        DigitalObject result = null;
        Role viewRole = Role.GUEST;
        boolean objectNotFound = false;
        boolean extendedAccess = false;
        try {
            mdm.setAuthorizationContext(AuthorizationContext.factorySystemContext());
            //check if object exists
            result = mdm.findSingleResult("SELECT o FROM DigitalObject o WHERE o.digitalObjectIdentifier=?1",
                    new Object[] { oid }, DigitalObject.class);
            if (result == null) {
                //object does not exist
                objectNotFound = true;
            } else {
                //object does exist, check permission for current context
                try {
                    viewRole = ResourceServiceLocal.getSingleton().getGrantRole(result.getSecurableResourceId(),
                            UIHelper.getSessionContext().getUserId(), AuthorizationContext.factorySystemContext());
                } catch (UnsupportedOperationException | EntityNotFoundException nogrants) {
                    //no grant found, check group role
                    try {
                        viewRole = (Role) ResourceServiceLocal.getSingleton().getReferenceRestriction(
                                new ReferenceId(result.getSecurableResourceId(), UIHelper.getSessionGroupId()),
                                AuthorizationContext.factorySystemContext());
                    } catch (EntityNotFoundException ex) {
                        viewRole = Role.NO_ACCESS;
                    }
                }
            }

            if (objectNotFound) {
                //object not found, if user logged in, show error...otherwise show login page
                if (UIHelper.getSessionUser().getDistinguishedName().equals(Constants.WORLD_USER_ID)) {
                    VaadinSession.getCurrent().setAttribute("from",
                            UIHelper.getWebAppUrl().toString() + "?landing&oid=" + oid);
                    updateView(VIEW.LOGIN);
                    return;
                } else {
                    throw new UnauthorizedAccessAttemptException("No object found for object id " + oid);
                }
            } else {
                //object not found, if role >= GUEST, show landing page...otherwise show login page if anonymous access
                if (!viewRole.atLeast(Role.GUEST)) {
                    VaadinSession.getCurrent().setAttribute("from",
                            UIHelper.getWebAppUrl().toString() + "?landing&oid=" + oid);
                    updateView(VIEW.LOGIN);
                    return;
                }
            }
            //http://localhost:8080/KITDM/?landing&oid=3b1243b2-df09-4a98-ad87-21b7cda74be9catch (UnauthorizedAccessAttemptException | ParserConfigurationException ex) {
        } catch (UnauthorizedAccessAttemptException ex) {
            //not found, should result in error page
            LOGGER.error("Failed to access digital object with id " + oid, ex);
            result = null;
        } finally {
            mdm.close();
        }

        if (landingPage == null) {
            landingPage = new LandingPageComponent();
        }
        landingPage.update(result, extendedAccess);
        updateView(VIEW.LANDING);
    }

    /**
     * Setup the login form including its logic.
     */
    private void setupLoginForm(AbstractLoginComponent.AUTH_MODE type, String pendingAuth, VaadinRequest request) {
        ComboBox authSelection = new ComboBox();
        authSelection.setWidth("400px");
        authSelection.setNullSelectionAllowed(false);
        authSelection.setStyleName("auth_selection");
        Label spacer = new Label("<br/>", ContentMode.HTML);
        spacer.setWidth("400px");

        String orcidClientId = DataManagerSettings.getSingleton()
                .getStringProperty(OrcidLoginComponent.ORCID_CLIENT_ID_PROPERTY, null);
        String orcidClientSecret = DataManagerSettings.getSingleton()
                .getStringProperty(OrcidLoginComponent.ORCID_CLIENT_SECRET_PROPERTY, null);

        /// String b2AccessClientId = DataManagerSettings.getSingleton().getStringProperty(B2AccessLoginComponent.B2ACCESS_CLIENT_ID_PROPERTY, null);
        // String b2AccessClientSecret = DataManagerSettings.getSingleton().getStringProperty(B2AccessLoginComponent.B2ACCESS_CLIENT_SECRET_PROPERTY, null);
        List<AbstractLoginComponent> components = new ArrayList<>();

        if (orcidClientId != null && !orcidClientId.equals("ORCID_CLIENT_ID") && orcidClientSecret != null
                && !orcidClientSecret.equals("ORCID_CLIENT_SECRET")) {
            components.add(new OrcidLoginComponent());
        }

        /*B2Access is currently not supported. 
        if (b2AccessClientId != null && b2AccessClientSecret != null) {
        components.add(new B2AccessLoginComponent());
        }*/
        components.add(new EmailPasswordLoginComponent());

        loginComponents = components.toArray(new AbstractLoginComponent[] {});

        //default login component has index 0
        loginComponent = loginComponents[0];
        for (AbstractLoginComponent component : loginComponents) {
            //add new login component
            authSelection.addItem(component.getLoginIdentifier());
            authSelection.setItemCaption(component.getLoginIdentifier(), component.getLoginLabel());

            if (pendingAuth != null && pendingAuth.equals(component.getLoginIdentifier())) {
                //login or registration process in pending, continue process
                loginComponent = component;
                try {
                    switch (type) {
                    case REGISTRATION:
                        loginComponent.doRegistration(request);
                        break;
                    default:
                        loginComponent.doLogin(request);
                        break;
                    }

                } catch (UnauthorizedAccessAttemptException ex) {
                    //failed to continue auth...cancel.
                    String message = "Failed to continue pending "
                            + (AbstractLoginComponent.AUTH_MODE.LOGIN.equals(type) ? "login" : "registration")
                            + " for authentication #" + pendingAuth + ".";
                    LOGGER.error(message, ex);
                    UIComponentTools.showError(message);
                    VaadinSession.getCurrent().setAttribute("auth_pending", null);
                    VaadinSession.getCurrent().setAttribute("registration_pending", null);
                    loginComponent.reset();
                }
            }
        }

        authSelection.select(loginComponent.getLoginIdentifier());

        authSelection.addValueChangeListener((Property.ValueChangeEvent event) -> {
            String value = (String) event.getProperty().getValue();
            if (value != null) {
                for (AbstractLoginComponent component : loginComponents) {
                    if (value.equals(component.getLoginIdentifier())) {
                        loginForm.replaceComponent(loginComponent, component);
                        loginComponent = component;
                    }
                }
            }
        });

        loginForm = new VerticalLayout(authSelection, spacer, loginComponent);
        loginForm.setComponentAlignment(authSelection, Alignment.TOP_CENTER);
        loginForm.setComponentAlignment(spacer, Alignment.TOP_CENTER);
        loginForm.setComponentAlignment(loginComponent, Alignment.TOP_CENTER);
    }

    /**
     * Update the view depending on the user selection.
     *
     * @param pView The new view.
     */
    public void updateView(VIEW pView) {
        currentView = pView;
        mainLayout.removeAllComponents();
        switch (pView) {
        case SIMON:
            loginInformationBar.setVisible(true);
            if (simonPanel == null) {
                simonPanel = new SimonMainPanel();
            }
            viewComponent = simonPanel;
            break;
        case INFORMATION:
            loginInformationBar.setVisible(true);
            if (informationView == null) {
                informationView = new InformationView();
            }
            viewComponent = informationView;
            break;
        case LOGIN:
            loginInformationBar.setVisible(false);
            viewComponent = loginForm;
            break;
        case PROFILE:
            loginInformationBar.setVisible(true);
            if (profileView == null) {
                profileView = new ProfileView();
            }
            profileView.reload();
            viewComponent = profileView;
            break;
        case SETTINGS:
            loginInformationBar.setVisible(true);
            if (datamanagerSettings == null) {
                datamanagerSettings = new DataManagerSettingsPanel();
            }
            /* if (!datamanagerSettings.getUserAdministrationTab().equals(datamanagerSettings.getMainComponentContainer().getSelectedTab())) {
                datamanagerSettings.getMainComponentContainer().setSelectedTab(datamanagerSettings.getUserAdministrationTab());
            }
            datamanagerSettings.getUserAdministrationTab().reload();*/
            viewComponent = datamanagerSettings;
            break;
        case LANDING:
            loginInformationBar.setVisible(false);
            if (landingPage == null) {
                landingPage = new LandingPageComponent();
            }
            viewComponent = landingPage;
            break;
        }

        mainLayout.addComponent(header);
        mainLayout.addComponent(loginInformationBar);
        mainLayout.addComponent(viewComponent);
        mainLayout.setExpandRatio(header, .09f);
        mainLayout.setExpandRatio(loginInformationBar, .11f);
        mainLayout.setExpandRatio(viewComponent, .8f);
        mainLayout.setComponentAlignment(header, Alignment.MIDDLE_CENTER);
        mainLayout.setComponentAlignment(viewComponent, Alignment.MIDDLE_CENTER);
        mainLayout.setComponentAlignment(loginInformationBar, Alignment.TOP_RIGHT);

        mainLayout.addLayoutClickListener((LayoutEvents.LayoutClickEvent event) -> {
            if (header.equals(event.getClickedComponent()) || title.equals(event.getClickedComponent())
                    || logo.equals(event.getClickedComponent())) {
                refreshMainLayout();
            }
        });
    }

    /**
     * Refresh the main layout depending on the logged in user. If nobody is
     * logged in, the login form will be shown. Otherwise, the main control
     * panel gets visible.
     */
    protected void refreshMainLayout() {
        LOGGER.debug("Refreshing main layout.");
        if (UserData.WORLD_USER.equals(UIHelper.getSessionUser())) {
            LOGGER.debug("Updating login view.");
            updateView(VIEW.LOGIN);
        } else {
            //logged in
            LOGGER.debug("Updating information view.");
            updateView(VIEW.INFORMATION);
        }
    }

    protected void sessionGroupChanged() {
        if (!INITIALIZING) {
            refreshMainLayout();
        }
    }

    /**
     * Perform Logout and switch view to login form.
     */
    protected void logout() {
        UIHelper.logout(UIHelper.getWebAppUrl().toString());
    }

    /**
     * @return the currentView
     */
    public VIEW getCurrentView() {
        if (currentView == null) {
            refreshMainLayout();
        }
        return currentView;
    }

    private String readVersion() {
        InputStream versionFile = null;
        String version = "UNKNOWN";
        try {
            versionFile = InformationView.class.getClassLoader().getResourceAsStream("version.txt");
            byte[] versionData = new byte[1024];
            int size = versionFile.read(versionData);
            version = new String(versionData, 0, size);
        } catch (IOException ex) {
            //failed to determine version number
        } finally {
            if (versionFile != null) {
                try {
                    versionFile.close();
                } catch (IOException ex) {
                }
            }
        }
        return version;
    }

}