Package org.apache.ace.webui.vaadin

Source Code of org.apache.ace.webui.vaadin.AddArtifactWindow

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 org.apache.ace.webui.vaadin;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;

import org.apache.ace.client.repository.object.ArtifactObject;
import org.apache.ace.client.repository.repository.ArtifactRepository;
import org.apache.ace.connectionfactory.ConnectionFactory;
import org.apache.ace.webui.domain.OBREntry;
import org.apache.ace.webui.vaadin.UploadHelper.ArtifactDropHandler;
import org.apache.ace.webui.vaadin.UploadHelper.GenericUploadHandler;
import org.apache.ace.webui.vaadin.UploadHelper.UploadHandle;
import org.osgi.service.log.LogService;

import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.DragAndDropWrapper;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Upload;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.Reindeer;

/**
* Provides a dialog for uploading new artifacts to ACE, or selecting existing artifacts from the repository.
*/
abstract class AddArtifactWindow extends Window {
    private static final String PROPERTY_SYMBOLIC_NAME = "symbolic name";
    private static final String PROPERTY_VERSION = "version";
    private static final String PROPERTY_PURGE = "purge";

    private final String m_repositoryXML;
    private final File m_sessionDir;
    private final URL m_obrUrl;

    private final List<File> m_uploadedArtifacts = new ArrayList<File>();
    private final Button m_searchButton;
    private final Button m_addButton;
    private final Table m_artifactsTable;

    /**
     * Creates a new {@link AddArtifactWindow} instance.
     *
     * @param sessionDir
     *            the session directory to temporary place artifacts in;
     * @param obrUrl
     *            the URL of the OBR to use.
     */
    public AddArtifactWindow(File sessionDir, URL obrUrl, String repositoryXML) {
        super("Add artifact");

        m_sessionDir = sessionDir;
        m_obrUrl = obrUrl;
        m_repositoryXML = repositoryXML;

        setModal(true);
        setWidth("50em");
        setCloseShortcut(KeyCode.ESCAPE);

        m_artifactsTable = new Table("Artifacts in repository");
        m_artifactsTable.addContainerProperty(PROPERTY_SYMBOLIC_NAME, String.class, null);
        m_artifactsTable.addContainerProperty(PROPERTY_VERSION, String.class, null);
        m_artifactsTable.addContainerProperty(PROPERTY_PURGE, Button.class, null);
        m_artifactsTable.setSizeFull();
        m_artifactsTable.setSelectable(true);
        m_artifactsTable.setMultiSelect(true);
        m_artifactsTable.setImmediate(true);
        m_artifactsTable.setHeight("15em");

        final Table uploadedArtifacts = new Table("Uploaded artifacts");
        uploadedArtifacts.addContainerProperty(PROPERTY_SYMBOLIC_NAME, String.class, null);
        uploadedArtifacts.addContainerProperty(PROPERTY_VERSION, String.class, null);
        uploadedArtifacts.setSizeFull();
        uploadedArtifacts.setSelectable(false);
        uploadedArtifacts.setMultiSelect(false);
        uploadedArtifacts.setImmediate(true);
        uploadedArtifacts.setHeight("15em");

        final GenericUploadHandler uploadHandler = new GenericUploadHandler(m_sessionDir) {
            @Override
            public void updateProgress(long readBytes, long contentLength) {
                // TODO Auto-generated method stub
            }

            @Override
            protected void artifactsUploaded(List<UploadHandle> uploads) {
                for (UploadHandle handle : uploads) {
                    try {
                        URL artifact = handle.getFile().toURI().toURL();

                        Item item = uploadedArtifacts.addItem(artifact);
                        item.getItemProperty(PROPERTY_SYMBOLIC_NAME).setValue(handle.getFilename());
                        item.getItemProperty(PROPERTY_VERSION).setValue("");

                        m_uploadedArtifacts.add(handle.getFile());
                    }
                    catch (MalformedURLException e) {
                        showErrorNotification("Upload artifact processing failed", "<br />Reason: " + e.getMessage());
                        logError("Processing of " + handle.getFilename() + " failed.", e);
                    }
                }
            }
        };

        final Upload uploadArtifact = new Upload();
        uploadArtifact.setCaption("Upload Artifact");
        uploadHandler.install(uploadArtifact);

        final DragAndDropWrapper finalUploadedArtifacts = new DragAndDropWrapper(uploadedArtifacts);
        finalUploadedArtifacts.setDropHandler(new ArtifactDropHandler(uploadHandler));

        addListener(new Window.CloseListener() {
            public void windowClose(CloseEvent e) {
                for (File artifact : m_uploadedArtifacts) {
                    artifact.delete();
                }
            }
        });

        HorizontalLayout searchBar = new HorizontalLayout();
        searchBar.setMargin(false);
        searchBar.setSpacing(true);

        final TextField searchField = new TextField();
        searchField.setImmediate(true);
        searchField.setValue("");

        final IndexedContainer dataSource = (IndexedContainer) m_artifactsTable.getContainerDataSource();

        m_searchButton = new Button("Search", new ClickListener() {
            public void buttonClick(ClickEvent event) {
                String searchValue = (String) searchField.getValue();

                dataSource.removeAllContainerFilters();

                if (searchValue != null && searchValue.trim().length() > 0) {
                    dataSource.addContainerFilter(PROPERTY_SYMBOLIC_NAME, searchValue,
                        true /* ignoreCase */, false /* onlyMatchPrefix */);
                }
            }
        });
        m_searchButton.setImmediate(true);

        searchBar.addComponent(searchField);
        searchBar.addComponent(m_searchButton);

        m_addButton = new Button("Add", new ClickListener() {
            public void buttonClick(ClickEvent event) {
                // Import all "local" (existing) bundles...
                importLocalBundles(m_artifactsTable);
                // Import all "remote" (non existing) bundles...
                importRemoteBundles(m_uploadedArtifacts);

                close();
            }
        });
        m_addButton.setImmediate(true);
        m_addButton.setStyleName(Reindeer.BUTTON_DEFAULT);
        m_addButton.setClickShortcut(KeyCode.ENTER);

        VerticalLayout layout = (VerticalLayout) getContent();
        layout.setMargin(true);
        layout.setSpacing(true);

        layout.addComponent(searchBar);
        layout.addComponent(m_artifactsTable);
        layout.addComponent(uploadArtifact);
        layout.addComponent(finalUploadedArtifacts);
        // The components added to the window are actually added to the window's
        // layout; you can use either. Alignments are set using the layout
        layout.addComponent(m_addButton);
        layout.setComponentAlignment(m_addButton, Alignment.MIDDLE_RIGHT);

        searchField.focus();
    }

    /**
     * Shows this dialog on the parent window.
     *
     * @param parent
     *            the parent for this window, cannot be <code>null</code>.
     */
    public final void showWindow(Window parent) {
        try {
            // Fill the artifacts table with the data from the OBR...
            populateArtifactTable(m_artifactsTable, m_obrUrl);

            parent.addWindow(this);
        }
        catch (Exception e) {
            // We've not yet added this window to the given parent, so we cannot use #showErrorNotification here...
            parent.showNotification("Failed to retrieve OBR repository!", "Reason: <br/>" + e.getMessage(), Notification.TYPE_ERROR_MESSAGE);
            logError("Failed to retrieve OBR repository!", e);
        }
    }

    /**
     * Imports all local, i.e., that are already in our local OBR, bundles.
     *
     * @param artifacts
     *            the UI-table with artifacts to install, cannot be <code>null</code>.
     * @return the imported artifacts, never <code>null</code>.
     */
    final List<ArtifactObject> importLocalBundles(final Table artifacts) {
        final List<ArtifactObject> added = new ArrayList<ArtifactObject>();

        Set<?> selectedItems = (Set<?>) artifacts.getValue();
        if (selectedItems != null && !selectedItems.isEmpty()) {
            for (Object itemID : selectedItems) {
                try {
                    added.add(UploadHelper.importLocalBundle(getArtifactRepository(), createOBRUrl(itemID)));
                }
                catch (Exception exception) {
                    Item item = artifacts.getItem(itemID);

                    Object symbolicName = item.getItemProperty(PROPERTY_SYMBOLIC_NAME).getValue();
                    Object version = item.getItemProperty(PROPERTY_VERSION).getValue();

                    showErrorNotification("Import artifact failed", "Artifact " + symbolicName + " " + version
                        + "<br />could not be imported into the repository."
                        + "<br />Reason: " + exception.getMessage());

                    logError("Import of " + symbolicName + " " + version + " failed.", exception);
                }
            }
        }
        return added;
    }

    /**
     * Import remote bundles.
     *
     * @param uploadedArtifacts
     *            the list with uploaded artifacts, never <code>null</code>.
     * @return the list of imported bundles.
     */
    final List<ArtifactObject> importRemoteBundles(List<File> uploadedArtifacts) {
        List<ArtifactObject> added = new ArrayList<ArtifactObject>();

        StringBuffer errors = new StringBuffer();
        int failedImports = 0;
        for (File artifact : uploadedArtifacts) {
            try {
                added.add(UploadHelper.importRemoteBundle(getArtifactRepository(), artifact));
            }
            catch (Exception exception) {
                failedImports++;
                errors.append("<br />" + exception.getMessage());
                logError("Import of " + artifact.getAbsolutePath() + " failed.", exception);
            }
            finally {
                artifact.delete();
            }
        }
        if (failedImports > 0) {
            if (failedImports == uploadedArtifacts.size()) {
                showErrorNotification("All " + failedImports + " artifacts failed", (failedImports > 30 ? "See the server log for a full list of failures." : errors.toString()));
            }
            else {
                showWarningNotification("" + failedImports + "/" + uploadedArtifacts.size() + " artifacts failed", (failedImports > 30 ? "See the server log for a full list of failures." : errors.toString()));
            }
        }
        return added;
    }

    /**
     * Logs a given message + exception at the error level.
     * <p>
     * If there's no log service present, this method will silently ignore the log statement.
     * </p>
     *
     * @param aMessage
     *            the message to log;
     * @param aException
     *            the exception to log.
     */
    final void logError(String aMessage, Throwable aException) {
        LogService logger = getLogger();
        if (logger != null) {
            logger.log(LogService.LOG_ERROR, aMessage, aException);
        }
    }

    /**
     * Shows an error message on screen.
     *
     * @param aTitle
     *            the title of the error message;
     * @param aMessage
     *            the error message itself.
     */
    final void showErrorNotification(final String aTitle, final String aMessage) {
        getParent().showNotification(aTitle, aMessage, Notification.TYPE_ERROR_MESSAGE);
    }

    /**
     * @return the artifact repository.
     */
    protected abstract ArtifactRepository getArtifactRepository();

    /**
     * @param url
     *            the URL to connect to, cannot be <code>null</code>.
     * @return a valid {@link URLConnection} instance, never <code>null</code>.
     */
    protected abstract ConnectionFactory getConnectionFactory();

    /**
     * @return the log service.
     */
    protected abstract LogService getLogger();

    /**
     * Create a new button that delete an OBREntry on-click.
     *
     * @param entry
     *            The entry
     * @return The button
     */
    private Button createDeleteOBREntryButton(final OBREntry entry) {
        Button button = new Button("x");
        button.setStyleName(Reindeer.BUTTON_SMALL);
        button.setDescription("Delete " + entry.getName());

        button.addListener(new ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
                event.getButton().setEnabled(false);

                try {
                    int code = OBRUtil.deleteOBREntry(getConnectionFactory(), entry, m_obrUrl);
                    if (code == HttpServletResponse.SC_OK) {
                        m_artifactsTable.removeItem(entry.getUri());
                    }
                    else {
                        showErrorNotification("Failed to delete resource", "The OBR returned an unexpected response code: " + code);
                    }
                }
                catch (IOException e) {
                    showErrorNotification("Failed to delete resource", "Reason: " + e.getMessage());
                }

            }
        });

        return button;
    }

    private URL createOBRUrl(Object itemID) throws MalformedURLException {
        return new URL(m_obrUrl, String.valueOf(itemID));
    }

    /**
     * Gets the bundles.
     *
     * @param dataSource
     *            the datasource to fill;
     * @param obrBaseUrl
     *            the obr base url
     * @return the bundles
     * @throws Exception
     *             the exception
     */
    private void populateArtifactTable(Table dataSource, URL obrBaseUrl) throws Exception {
        // retrieve the repository.xml as a stream
        List<OBREntry> obrList = OBRUtil.getAvailableOBREntries(getConnectionFactory(), getArtifactRepository(), obrBaseUrl, m_repositoryXML);
        if (obrList.isEmpty()) {
            logError("No new data in OBR.");
            return;
        }

        // Create a list of all bundle names
        for (OBREntry entry : obrList) {
            Item item = dataSource.addItem(entry.getUri());
            item.getItemProperty(PROPERTY_SYMBOLIC_NAME).setValue(entry.getName());
            item.getItemProperty(PROPERTY_VERSION).setValue(entry.getVersion());
            item.getItemProperty(PROPERTY_PURGE).setValue(createDeleteOBREntryButton(entry));
        }
    }

    /**
     * Logs a given message at the error level.
     * <p>
     * If there's no log service present, this method will silently ignore the log statement.
     * </p>
     *
     * @param aMessage
     *            the message to log.
     */
    private void logError(String aMessage) {
        LogService logger = getLogger();
        if (logger != null) {
            logger.log(LogService.LOG_ERROR, aMessage);
        }
    }

    /** Shows a warning messsage on screen. */
    private void showWarningNotification(final String aTitle, final String aMessage) {
        getParent().showNotification(aTitle, aMessage, Notification.TYPE_WARNING_MESSAGE);
    }
}
TOP

Related Classes of org.apache.ace.webui.vaadin.AddArtifactWindow

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.