org.jumpmind.vaadin.ui.common.ReadOnlyTextAreaDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.jumpmind.vaadin.ui.common.ReadOnlyTextAreaDialog.java

Source

/**
 * Licensed to JumpMind Inc under one or more contributor
 * license agreements.  See the NOTICE file distributed
 * with this work for additional information regarding
 * copyright ownership.  JumpMind Inc licenses this file
 * to you under the GNU General Public License, version 3.0 (GPLv3)
 * (the "License"); you may not use this file except in compliance
 * with the License.
 *
 * You should have received a copy of the GNU General Public License,
 * version 3.0 (GPLv3) along with this library; if not, see
 * <http://www.gnu.org/licenses/>.
 *
 * 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.jumpmind.vaadin.ui.common;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.jumpmind.db.model.Column;
import org.jumpmind.db.model.Table;
import org.jumpmind.db.platform.DatabaseInfo;
import org.jumpmind.db.platform.IDatabasePlatform;
import org.jumpmind.db.sql.ISqlTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.server.FileDownloader;
import com.vaadin.server.Resource;
import com.vaadin.server.StreamResource;
import com.vaadin.server.StreamResource.StreamSource;
import com.vaadin.ui.AbstractSelect;
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.ComboBox;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification.Type;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.Upload;
import com.vaadin.ui.Upload.Receiver;
import com.vaadin.ui.Upload.SucceededEvent;
import com.vaadin.ui.Upload.SucceededListener;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;

public class ReadOnlyTextAreaDialog extends ResizableWindow {

    private static final long serialVersionUID = 1L;

    final Logger log = LoggerFactory.getLogger(getClass());
    VerticalLayout wrapper;
    protected HorizontalLayout buttonLayout;
    protected TextArea textField;
    protected AbstractSelect displayBox;
    protected Button downloadButton;
    protected Table table;
    protected Column column;
    protected Object[] primaryKeys;
    protected IDatabasePlatform platform;

    public ReadOnlyTextAreaDialog(final String title, final String value, boolean isEncodedInHex) {
        this(title, value, null, null, null, isEncodedInHex, false);
    }

    public ReadOnlyTextAreaDialog(final String title, final String value, Table table, Object[] primaryKeys,
            IDatabasePlatform platform, boolean isEncodedInHex, boolean isLob) {
        super(title);
        this.table = table;
        this.primaryKeys = primaryKeys;
        this.platform = platform;
        this.column = table == null ? null : table.getColumnWithName(title);

        wrapper = new VerticalLayout();
        wrapper.setMargin(true);
        wrapper.setSizeFull();
        textField = new TextArea();
        textField.setSizeFull();
        textField.setWordwrap(false);
        wrapper.addComponent(textField);
        addComponent(wrapper, 1);

        buttonLayout = new HorizontalLayout();
        buttonLayout.addStyleName(ValoTheme.WINDOW_BOTTOM_TOOLBAR);
        buttonLayout.setSpacing(true);
        buttonLayout.setWidth(100, Unit.PERCENTAGE);
        addComponent(buttonLayout);

        if (value != null && isEncodedInHex) {
            displayBox = new ComboBox("Display As");
            displayBox.addItem("Hex");
            displayBox.addItem("Text");
            displayBox.addItem("Decimal");
            displayBox.setNullSelectionAllowed(false);
            displayBox.select("Hex");
            displayBox.addValueChangeListener(new ValueChangeListener() {

                private static final long serialVersionUID = 1L;

                @Override
                public void valueChange(ValueChangeEvent event) {
                    updateTextField((String) displayBox.getValue(), value);
                }
            });
            buttonLayout.addComponent(displayBox);
        }

        if (table != null && isLob) {
            buildUploadButton(title, value);
            buildDownloadButton(title);
        }

        Label spacer = new Label();
        buttonLayout.addComponent(spacer);
        buttonLayout.setExpandRatio(spacer, 1);

        Button closeButton = buildCloseButton();
        buttonLayout.addComponent(closeButton);
        buttonLayout.setComponentAlignment(closeButton, Alignment.BOTTOM_RIGHT);

        textField.setValue(value);
        textField.addTextChangeListener(new TextChangeListener() {

            private static final long serialVersionUID = 1L;

            @Override
            public void textChange(TextChangeEvent event) {
                if (displayBox != null) {
                    updateTextField((String) displayBox.getValue(), value);
                } else {
                    textField.setValue(value);
                }
            }
        });
    }

    @Override
    protected void grabFocus() {
    }

    @Override
    public void show() {
        super.show();
        selectAll();
    }

    private void buildUploadButton(String title, final String value) {
        final Button uploadButton = new Button("Upload");
        final Button viewTextButton = new Button("View Text");

        LobUploader lobUploader = new LobUploader();
        final Upload upload = new Upload("Upload new " + table.getColumnWithName(title).getMappedType(),
                lobUploader);
        upload.addSucceededListener(lobUploader);

        uploadButton.addClickListener(new ClickListener() {
            private static final long serialVersionUID = 1L;

            @Override
            public void buttonClick(ClickEvent event) {
                wrapper.replaceComponent(textField, upload);
                wrapper.setComponentAlignment(upload, Alignment.MIDDLE_CENTER);
                buttonLayout.replaceComponent(uploadButton, viewTextButton);
            }
        });

        viewTextButton.addClickListener(new ClickListener() {
            private static final long serialVersionUID = 1L;

            @Override
            public void buttonClick(ClickEvent event) {
                wrapper.replaceComponent(upload, textField);
                wrapper.setComponentAlignment(textField, Alignment.TOP_LEFT);
                buttonLayout.replaceComponent(viewTextButton, uploadButton);
            }
        });

        if (value != null) {
            buttonLayout.addComponent(uploadButton);
            buttonLayout.setComponentAlignment(uploadButton, Alignment.BOTTOM_CENTER);
        } else {
            wrapper.replaceComponent(textField, upload);
            wrapper.setComponentAlignment(upload, Alignment.MIDDLE_CENTER);
        }
    }

    private void buildDownloadButton(String title) {
        downloadButton = new Button("Download");
        final byte[] lobData = getLobData(title);
        if (lobData != null) {
            Resource resource = new StreamResource(new StreamSource() {

                private static final long serialVersionUID = 1L;

                public InputStream getStream() {
                    return new ByteArrayInputStream(lobData);
                }

            }, title);
            FileDownloader fileDownloader = new FileDownloader(resource);
            fileDownloader.extend(downloadButton);
            buttonLayout.addComponent(downloadButton);
            buttonLayout.setComponentAlignment(downloadButton, Alignment.BOTTOM_CENTER);

            long fileSize = lobData.length;
            String sizeText = fileSize + " Bytes";
            if (fileSize / 1024 > 0) {
                sizeText = Math.round(fileSize / 1024.0) + " kB";
                fileSize /= 1024;
            }
            if (fileSize / 1024 > 0) {
                sizeText = Math.round(fileSize / 1024.0) + " MB";
                fileSize /= 1024;
            }
            if (fileSize / 1024 > 0) {
                sizeText = Math.round(fileSize / 1024.0) + " GB";
            }
            Label sizeLabel = new Label(sizeText);
            buttonLayout.addComponent(sizeLabel);
            buttonLayout.setExpandRatio(sizeLabel, 1.0f);
            buttonLayout.setComponentAlignment(sizeLabel, Alignment.BOTTOM_CENTER);
        }
    }

    protected byte[] getLobData(String title) {
        ISqlTemplate sqlTemplate = platform.getSqlTemplate();
        String sql = buildLobSelect(table.getPrimaryKeyColumns());
        if (platform.isBlob(column.getMappedTypeCode())) {
            return sqlTemplate.queryForBlob(sql, column.getJdbcTypeCode(), column.getJdbcTypeName(), primaryKeys);
        } else {
            return sqlTemplate.queryForClob(sql, column.getJdbcTypeCode(), column.getJdbcTypeName(), primaryKeys)
                    .getBytes();
        }
    }

    protected String buildLobSelect(Column[] pkColumns) {
        StringBuilder sql = new StringBuilder("select ");
        DatabaseInfo dbInfo = platform.getDatabaseInfo();
        String quote = platform.getDdlBuilder().isDelimitedIdentifierModeOn() ? dbInfo.getDelimiterToken() : "";
        sql.append(quote);
        sql.append(column.getName());
        sql.append(quote);
        sql.append(" from ");
        sql.append(table.getQualifiedTableName(quote, dbInfo.getCatalogSeparator(), dbInfo.getSchemaSeparator()));
        sql.append(" where ");
        for (Column col : pkColumns) {
            sql.append(quote);
            sql.append(col.getName());
            sql.append(quote);
            sql.append("=? and ");
        }
        sql.delete(sql.length() - 5, sql.length());
        return sql.toString();
    }

    protected String buildLobUpdate(Column[] pkColumns) {
        StringBuilder sql = new StringBuilder("update ");
        DatabaseInfo dbInfo = platform.getDatabaseInfo();
        String quote = platform.getDdlBuilder().isDelimitedIdentifierModeOn() ? dbInfo.getDelimiterToken() : "";
        sql.append(table.getQualifiedTableName(quote, dbInfo.getCatalogSeparator(), dbInfo.getSchemaSeparator()));
        sql.append(" set ");
        sql.append(quote);
        sql.append(column.getName());
        sql.append(quote);
        sql.append("=? where ");
        for (Column col : pkColumns) {
            sql.append(quote);
            sql.append(col.getName());
            sql.append(quote);
            sql.append("=? and ");
        }
        sql.delete(sql.length() - 5, sql.length());
        return sql.toString();
    }

    public void selectAll() {
        textField.focus();
        textField.selectAll();
    }

    protected void updateTextField(String display, String value) {
        if (display.equals("Hex")) {
            textField.setValue(value);
        } else if (display.equals("Text")) {
            try {
                byte[] bytes = Hex.decodeHex(value.toCharArray());
                textField.setValue(new String(bytes));
            } catch (Exception e) {
                log.warn("Failed to decode hex string for display", e);
            }
        } else if (display.equals("Decimal")) {
            try {
                byte[] bytes = Hex.decodeHex(value.toCharArray());
                String newValue = "";
                ByteBuffer buffer = ByteBuffer.wrap(bytes);
                while (buffer.hasRemaining()) {
                    if (!newValue.equals("")) {
                        newValue += " ";
                    }
                    newValue += buffer.get() & 0xff;
                }
                textField.setValue(newValue);
            } catch (Exception e) {
                log.warn("Failed to decode hex string for display", e);
            }
        }
    }

    private class LobUploader implements Receiver, SucceededListener {

        private static final long serialVersionUID = 1L;

        File file;

        @Override
        public OutputStream receiveUpload(String filename, String mimeType) {
            FileOutputStream out = null;
            try {
                file = new File(System.getProperty("java.io.tmpdir"), filename);
                out = new FileOutputStream(file);
            } catch (FileNotFoundException e) {
                NotifyDialog.show("Upload Error",
                        "<b>The file could not be uploaded.</b><br>" + "Cause: the file could not be found.<br><br>"
                                + "To view the <b>Stack Trace</b>, click <b>\"Details\"</b>.",
                        e, Type.ERROR_MESSAGE);
                return new ByteArrayOutputStream();
            }
            return out;
        }

        public void uploadSucceeded(SucceededEvent event) {
            log.info("File received successfully. Updating database");
            String sql = buildLobUpdate(table.getPrimaryKeyColumns());
            Connection con = null;
            PreparedStatement ps = null;
            try {
                long startTime = System.nanoTime();
                con = ((DataSource) platform.getDataSource()).getConnection();
                con.setAutoCommit(false);
                ps = con.prepareStatement(sql);
                InputStream stream = new FileInputStream(file);
                ps.setBinaryStream(1, (InputStream) stream, (int) file.length());
                for (int i = 0; i < primaryKeys.length; i++) {
                    ps.setObject(i + 2, primaryKeys[i], table.getPrimaryKeyColumns()[i].getMappedTypeCode());
                }
                ps.executeUpdate();
                con.commit();
                long executionTime = System.nanoTime() - startTime;
                log.info("Upload succeeded in " + executionTime + " ms");
                ReadOnlyTextAreaDialog.this.close();
            } catch (SQLException e1) {
                NotifyDialog.show("Upload Error",
                        "<b>The file could not be uploaded.</b><br>"
                                + "Cause: the sql update statement failed.<br><br>"
                                + "To view the <b>Stack Trace</b>, click <b>\"Details\"</b>.",
                        e1, Type.ERROR_MESSAGE);
            } catch (FileNotFoundException e2) {
                // do nothing -- already notified
            } finally {
                if (ps != null) {
                    try {
                        ps.close();
                    } catch (SQLException e) {
                    }
                }
                if (con != null) {
                    try {
                        con.close();
                    } catch (SQLException e) {
                    }
                }
                FileUtils.deleteQuietly(file);
                log.info("Deleted uploaded file");
            }
        }
    }

    public static void show(String title, String value, boolean isEncodedInHex) {
        ReadOnlyTextAreaDialog dialog = new ReadOnlyTextAreaDialog(title, value, isEncodedInHex);
        dialog.showAtSize(.4);
    }

    public static void show(String title, String value, Table table, Object[] primaryKeys,
            IDatabasePlatform platform, boolean isEncodedInHex, boolean isLob) {
        ReadOnlyTextAreaDialog dialog = new ReadOnlyTextAreaDialog(title, value, table, primaryKeys, platform,
                isEncodedInHex, isLob);
        dialog.showAtSize(.45);
    }
}