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

Java tutorial

Introduction

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

Source

/*
 * Copyright 2016 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.data.Item;
import com.vaadin.server.FileDownloader;
import com.vaadin.server.Page;
import com.vaadin.server.StreamResource;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import edu.kit.dama.authorization.entities.GroupId;
import edu.kit.dama.authorization.entities.IAuthorizationContext;
import edu.kit.dama.authorization.entities.ReferenceId;
import edu.kit.dama.authorization.entities.Role;
import edu.kit.dama.authorization.entities.UserId;
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.content.mets.util.MetsBuilder;
import edu.kit.dama.mdm.content.util.DublinCoreHelper;
import edu.kit.dama.mdm.core.IMetaDataManager;
import edu.kit.dama.mdm.core.MetaDataManagement;
import edu.kit.dama.mdm.core.authorization.SecureMetaDataManager;
import edu.kit.dama.mdm.core.jpa.MetaDataManagerJpa;
import edu.kit.dama.rest.dataorganization.services.impl.util.PublicDownloadHandler;
import edu.kit.dama.staging.util.DataOrganizationUtils;
import edu.kit.dama.ui.admin.utils.UIComponentTools;
import edu.kit.dama.ui.admin.utils.UIHelper;
import edu.kit.dama.ui.commons.util.UIUtils7;
import edu.kit.dama.util.Constants;
import edu.kit.lsdf.adalapi.AbstractFile;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.core.Response;
import javax.xml.parsers.ParserConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author jejkal
 */
public class LandingPageComponent extends CustomComponent {

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

    private GridLayout mainLayout;

    public LandingPageComponent() {
    }

    public final void update(DigitalObject object, boolean privileged) {
        if (object == null) {
            UIUtils7.GridLayoutBuilder builder = new UIUtils7.GridLayoutBuilder(1, 1);
            builder.fill(new Label("Access to digital object not permitted."), 0, 0);
            mainLayout = builder.getLayout();
            mainLayout.setMargin(true);
            mainLayout.setSpacing(true);
            mainLayout.setStyleName("landing");
            HorizontalLayout hLayout = new HorizontalLayout(mainLayout);
            hLayout.setSizeFull();
            hLayout.setComponentAlignment(mainLayout, Alignment.MIDDLE_CENTER);
            setCompositionRoot(hLayout);
        } else {
            final TextField oidField = new TextField();
            Button searchButton = new Button("Search");
            Button metsButton = new Button("METS");
            final Button dcButton = new Button("DublinCore");
            Button dataButton = new Button("Download");
            VerticalLayout metadataDownloadButtons = new VerticalLayout(dcButton, metsButton);
            UIUtils7.GridLayoutBuilder builder = new UIUtils7.GridLayoutBuilder(3, 6);

            StreamResource metsResource = new StreamResource(() -> {
                try {
                    ByteArrayOutputStream bout = new ByteArrayOutputStream();
                    MetsBuilder.init(object).createMinimalMetsDocument(UserData.WORLD_USER).write(bout);
                    return new ByteArrayInputStream(bout.toByteArray());
                } catch (Exception ex) {
                    LOGGER.error("Failed to provide METS document.", ex);
                    UIComponentTools.showError(
                            "Failed to initialize METS document for download. Cause: " + ex.getMessage());
                    return null;
                }
            }, object.getDigitalObjectIdentifier() + ".mets.xml");

            StreamResource dcResource = new StreamResource(() -> {
                try {
                    ByteArrayOutputStream bout = new ByteArrayOutputStream();
                    DublinCoreHelper.writeDublinCoreDocument(object, UserData.WORLD_USER, bout);
                    return new ByteArrayInputStream(bout.toByteArray());
                } catch (ParserConfigurationException ex) {
                    LOGGER.error("Failed to provide DC document.", ex);
                    UIComponentTools
                            .showError("Failed to initialize DC document for download. Cause: " + ex.getMessage());
                    return null;
                }
            }, object.getDigitalObjectIdentifier() + ".dc.xml");

            StreamResource dataResource = new StreamResource(() -> {
                IMetaDataManager mdm = MetaDataManagement.getMetaDataManagement().getMetaDataManager();
                mdm.setAuthorizationContext(AuthorizationContext.factorySystemContext());
                try {
                    IAuthorizationContext ctx = new AuthorizationContext(new UserId(Constants.WORLD_USER_ID),
                            new GroupId(Constants.WORLD_USER_ID), Role.GUEST);
                    if (accessGranted(object, ctx) || accessGranted(object, UIHelper.getSessionContext())) {
                        Response response = new PublicDownloadHandler().prepareStream(object);
                        if (response.getStatus() == Response.Status.OK.getStatusCode()) {
                            return (InputStream) response.getEntity();
                        } else {
                            LOGGER.error("Preparation of the public download for object "
                                    + object.getDigitalObjectIdentifier() + " returned status "
                                    + response.getStatus() + ". Aborting.");
                        }
                    }
                    throw new IOException("Public access not available.");
                } catch (IOException ex) {
                    LOGGER.error(
                            "Failed to provide data stream for object " + object.getDigitalObjectIdentifier() + ".",
                            ex);
                    UIComponentTools.showError(
                            "Failed to initialize data stream for public download. Probably, the digital object is not publicly available.");
                    return null;
                }
            }, object.getDigitalObjectIdentifier() + ".zip");

            Map<String, String> dcElementMap = new HashMap<>();
            try {
                dcElementMap = DublinCoreHelper.createDublinCoreElementMap(object, UserData.WORLD_USER);
            } catch (ParserConfigurationException ex) {
                LOGGER.error(
                        "Failed to create DC metadata for object with id " + object.getDigitalObjectIdentifier(),
                        ex);
            }
            oidField.setValue(object.getDigitalObjectIdentifier());

            FileDownloader metsDownloader = new FileDownloader(metsResource);
            metsDownloader.extend(metsButton);

            FileDownloader dcDownloader = new FileDownloader(dcResource);
            dcDownloader.extend(dcButton);

            FileDownloader dataDownloader = new FileDownloader(dataResource);
            dataDownloader.extend(dataButton);

            oidField.setSizeFull();
            searchButton.setWidth("128px");

            searchButton.addClickListener((Button.ClickEvent event) -> {
                String oid = oidField.getValue();
                Page.getCurrent().setLocation(
                        URI.create(UIHelper.getWebAppUrl().toString() + "?landing&oid=" + oid).toString());
            });

            dcButton.setWidth("128px");
            metsButton.setWidth("128px");
            dataButton.setWidth("128px");

            metadataDownloadButtons.setComponentAlignment(dcButton, Alignment.TOP_LEFT);
            metadataDownloadButtons.setComponentAlignment(metsButton, Alignment.TOP_LEFT);

            //build layout
            Label oidLabel = new Label("<u>Object Id</u>", ContentMode.HTML);
            builder.fillRow(oidLabel, 0, 0, 1);
            oidLabel.addStyleName("myboldcaption");
            builder.addComponent(oidField, 0, 1, 2, 1).addComponent(searchButton, 2, 1);
            Label dcMetadataLabel = new Label("<u>DC Metadata</u>", ContentMode.HTML);
            builder.fillRow(dcMetadataLabel, 0, 2, 1);
            dcMetadataLabel.addStyleName("myboldcaption");

            Set<Map.Entry<String, String>> entries = dcElementMap.entrySet();

            Table dcTable = new Table();
            dcTable.setPageLength(entries.size() + 1);
            dcTable.addContainerProperty("dc:key", String.class, "-");
            dcTable.addContainerProperty("dc:value", String.class, "-");
            entries.forEach((entry) -> {
                Object newItemId = dcTable.addItem();
                Item row1 = dcTable.getItem(newItemId);
                row1.getItemProperty("dc:key").setValue(entry.getKey());
                row1.getItemProperty("dc:value").setValue(entry.getValue());
            });

            dcTable.setWidth("640px");
            dcTable.addStyleName("myboldcaption");
            builder.addComponent(dcTable, 0, 3, 2, 1);
            builder.addComponent(metadataDownloadButtons, 2, 3, 1, 1);

            builder.fillRow(new Label("<u>Data Access</u>", ContentMode.HTML), 0, 4, 1);
            long bytes = DataOrganizationUtils.getAssociatedDataSize(object.getDigitalObjectId());
            String formatted = AbstractFile.formatSize(bytes);
            Label oidDownloadLabel = new Label(
                    object.getDigitalObjectIdentifier() + ".zip (approx. " + formatted + ")");
            oidDownloadLabel.addStyleName("myboldcaption");
            builder.addComponent(oidDownloadLabel, 0, 5, 2, 1);
            builder.addComponent(dataButton, 2, 5, 1, 1);

            mainLayout = builder.getLayout();
            mainLayout.setRowExpandRatio(0, .1f);
            mainLayout.setRowExpandRatio(1, .1f);
            mainLayout.setRowExpandRatio(2, .6f);
            mainLayout.setRowExpandRatio(3, .1f);
            mainLayout.setRowExpandRatio(4, .1f);

            mainLayout.setColumnExpandRatio(0, .1f);
            mainLayout.setColumnExpandRatio(1, .8f);
            mainLayout.setColumnExpandRatio(2, .1f);
        }
        mainLayout.setMargin(true);
        mainLayout.setSpacing(true);
        mainLayout.setStyleName("landing");
        HorizontalLayout hLayout = new HorizontalLayout(mainLayout);
        hLayout.setSizeFull();
        hLayout.setComponentAlignment(mainLayout, Alignment.MIDDLE_CENTER);
        setCompositionRoot(hLayout);
    }

    private boolean accessGranted(DigitalObject object, IAuthorizationContext ctx) {
        String objectId = object.getDigitalObjectIdentifier();

        LOGGER.debug("Trying to get public content for digital object id with id {}", new Object[] { objectId });
        IMetaDataManager mdm = SecureMetaDataManager.factorySecureMetaDataManager(ctx);
        try {
            LOGGER.debug("Checking access for public context.");
            mdm.addProperty(MetaDataManagerJpa.JAVAX_PERSISTENCE_FETCHGRAPH, "DigitalObject.simple");
            object = mdm.findSingleResult("SELECT o FROM DigitalObject o WHERE o.digitalObjectIdentifier=?1",
                    new Object[] { objectId }, DigitalObject.class);
            if (object == null) {
                LOGGER.error("No published digital object for object id " + objectId + " found.");
                return false;
            }

            //check if single user grants are supported
            if (!ResourceServiceLocal.getSingleton().grantsAllowed(object.getSecurableResourceId(),
                    AuthorizationContext.factorySystemContext())) {
                //no single user grants allowed, check group permission
                try {
                    Role groupRole = (Role) ResourceServiceLocal.getSingleton().getReferenceRestriction(
                            new ReferenceId(object.getSecurableResourceId(), ctx.getGroupId()),
                            AuthorizationContext.factorySystemContext());
                    if (groupRole.atLeast(Role.GUEST)) {
                        return true;
                    }
                    throw new UnauthorizedAccessAttemptException(
                            "Public access not available. Granted group role < GUEST.");
                } catch (EntityNotFoundException ex) {
                    //not for this group
                    throw new UnauthorizedAccessAttemptException(
                            "Public access not available. Access on group level not allowed.");
                }
            }

            //check role for user WORLD
            Role publicRole = ResourceServiceLocal.getSingleton().getGrantRole(object.getSecurableResourceId(),
                    ctx.getUserId(), AuthorizationContext.factorySystemContext());

            if (!publicRole.atLeast(Role.GUEST)) {
                throw new UnauthorizedAccessAttemptException(
                        "Public access not available. Granted user role < GUEST.");
            }
            return true;
        } catch (UnauthorizedAccessAttemptException
                | edu.kit.dama.authorization.exceptions.EntityNotFoundException ex) {
            LOGGER.error("Failed to obtain object for object id " + objectId
                    + ". Object seems not to be publicly available.", ex);
            return false;
        } finally {
            mdm.close();
        }
    }

}