ch.elexis.core.ui.util.SqlWithUiRunner.java Source code

Java tutorial

Introduction

Here is the source code for ch.elexis.core.ui.util.SqlWithUiRunner.java

Source

/*******************************************************************************
 * Copyright (c) 2007-2011, G. Weirich and Elexis
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     G. Weirich - initial API and implementation
 ******************************************************************************/
package ch.elexis.core.ui.util;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.AssertionFailedException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.statushandlers.StatusManager;

import ch.elexis.core.data.status.ElexisStatus;
import ch.elexis.data.PersistentObject;
import ch.rgw.tools.JdbcLink;
import ch.rgw.tools.JdbcLink.Stm;
import ch.rgw.tools.JdbcLinkException;

public class SqlWithUiRunner {
    static Log log = Log.get("SqlWithUiRunner");

    enum SqlStatus {
        NONE, EXECUTE, SUCCESS, FAIL
    };

    private List<String> sqlStrings;
    private List<UpdateDbSql> sql;
    private String pluginId;

    public SqlWithUiRunner(String[] sql, String pluginId) {
        sqlStrings = new ArrayList<String>();
        for (int i = 0; i < sql.length; i++) {
            sqlStrings.add(sql[i]);
        }
        this.pluginId = pluginId;
    }

    public boolean runSql() {
        sql = new ArrayList<UpdateDbSql>();
        // create UpdateDbSql objects from input list
        for (String sqlString : sqlStrings) {
            sql.add(new UpdateDbSql(sqlString));
        }
        // run the update with progress in the UI Thread if a Display is available ...
        if (isDisplayAvailable()) {
            Display.getDefault().syncExec(new Runnable() {
                @Override
                public void run() {
                    Shell parent = null;
                    try {
                        parent = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
                    } catch (IllegalStateException e) {
                        // the workbench has not been created yet ... create a dummy Shell on the
                        // display
                        parent = new Shell(Display.getDefault());
                    } catch (NullPointerException e) {
                        // the workbench has not been created yet ... create a dummy Shell on the
                        // display
                        parent = new Shell(Display.getDefault());
                    }
                    ProgressMonitorDialog dialog = new ProgressMonitorDialog(parent);
                    try {
                        dialog.run(true, false, new IRunnableWithProgress() {
                            @Override
                            public void run(IProgressMonitor monitor) {
                                monitor.beginTask("Running DB Script", sql.size());
                                for (UpdateDbSql update : sql) {
                                    monitor.subTask(update.getSql());
                                    update.run();
                                    // worked increates the monitor, the values is added to the
                                    // existing ones
                                    monitor.worked(1);
                                }
                                monitor.done();
                            }
                        });
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        } else {
            // this code should only be reached during tests!
            for (UpdateDbSql update : sql) {
                update.run();
            }
        }
        // determine if all updates were successful
        for (UpdateDbSql update : sql) {
            if (update.getStatus() == SqlStatus.FAIL)
                return false;
        }
        return true;
    }

    /**
     * Class holding information about one sql and its execution
     * 
     * @author thomas
     */
    protected class UpdateDbSql implements Runnable {
        private String sql;
        private SqlStatus status;

        protected UpdateDbSql(String sql) {
            this.sql = sql;
            status = SqlStatus.NONE;
        }

        @Override
        public void run() {
            JdbcLink link = null;
            Stm statement = null;
            try {
                link = PersistentObject.getConnection();
                statement = link.getStatement();
                setStatus(SqlStatus.EXECUTE);
                // do not use execScript method here as it will catch the exceptions
                ByteArrayInputStream scriptStream = new ByteArrayInputStream(this.sql.getBytes("UTF-8"));
                String sqlString;
                while ((sqlString = JdbcLink.readStatement(scriptStream)) != null) {
                    try {
                        statement.exec(link.translateFlavor(sqlString));
                    } catch (JdbcLinkException e) {
                        setStatus(SqlStatus.FAIL);
                        log.log(e, "Error " + e.getMessage() + " during db update", Log.ERRORS);
                        try {
                            StatusManager.getManager().handle(new ElexisStatus(ElexisStatus.ERROR, pluginId,
                                    ElexisStatus.CODE_NONE, "Error " + e.getMessage() + " during db update", e));
                        } catch (AssertionFailedException appnotinit) {

                        }
                    }
                }
            } catch (UnsupportedEncodingException e) {
                setStatus(SqlStatus.FAIL);
                try {
                    StatusManager.getManager().handle(new ElexisStatus(ElexisStatus.ERROR, pluginId,
                            ElexisStatus.CODE_NONE, "Error " + e.getMessage() + " during db update", e));
                } catch (AssertionFailedException appnotinit) {
                    log.log(e, "Error " + e.getMessage() + " during db update", Log.ERRORS);
                }
                return;
            } finally {
                if (link != null && statement != null)
                    link.releaseStatement(statement);
            }
            if (getStatus() == SqlStatus.EXECUTE)
                setStatus(SqlStatus.SUCCESS);
        }

        public void setStatus(SqlStatus status) {
            this.status = status;
        }

        public SqlStatus getStatus() {
            return status;
        }

        public String getSql() {
            return sql;
        }
    }

    protected boolean isDisplayAvailable() {
        try {
            Class.forName("org.eclipse.swt.widgets.Display");
        } catch (ClassNotFoundException e) {
            return false;
        } catch (NoClassDefFoundError e) {
            return false;
        }
        if (Display.getDefault() == null)
            return false;
        else
            return true;
    }
}