net.xmind.share.jobs.UploadJob.java Source code

Java tutorial

Introduction

Here is the source code for net.xmind.share.jobs.UploadJob.java

Source

/*
 * Copyright (c) 2006-2012 XMind Ltd. and others.
 * 
 * This file is a part of XMind 3. XMind releases 3 and above are dual-licensed
 * under the Eclipse Public License (EPL), which is available at
 * http://www.eclipse.org/legal/epl-v10.html and the GNU Lesser General Public
 * License (LGPL), which is available at http://www.gnu.org/licenses/lgpl.html
 * See http://www.xmind.net/license.html for details.
 * 
 * Contributors: XMind Ltd. - initial API and implementation
 */
package net.xmind.share.jobs;

import java.io.File;
import java.io.IOException;

import net.xmind.share.Info;
import net.xmind.share.Messages;
import net.xmind.share.XmindSharePlugin;
import net.xmind.signin.IAccountInfo;
import net.xmind.signin.IAuthenticationListener;
import net.xmind.signin.XMindNet;

import org.apache.commons.httpclient.HttpStatus;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.xmind.core.CoreException;
import org.xmind.core.IMeta;
import org.xmind.core.IWorkbook;
import org.xmind.ui.dialogs.SimpleInfoPopupDialog;

public class UploadJob extends Job {

    private class TransferWorker implements Runnable {

        private Thread thread = null;

        public void start() {
            if (thread != null)
                return;
            thread = new Thread(this);
            thread.setName("Upload:" + info.getString(Info.TITLE)); //$NON-NLS-1$
            thread.setDaemon(false);
            thread.setPriority(Thread.NORM_PRIORITY);
            thread.start();
        }

        public void run() {
            session.transfer();
        }

    }

    private class ProgressWorker implements Runnable {

        private IProgressMonitor monitor;

        private int ticks;

        private Thread thread = null;

        private int ticksUploaded = 0;

        public ProgressWorker(IProgressMonitor monitor, int ticks) {
            this.monitor = monitor;
            this.ticks = ticks;
        }

        public void start() {
            if (thread != null)
                return;
            thread = new Thread(this);
            thread.setName("ProgressWorker:" + info.getString(Info.TITLE)); //$NON-NLS-1$
            thread.setDaemon(true);
            thread.setPriority(Thread.MIN_PRIORITY);
            thread.start();
        }

        public void cancel() {
            if (thread != null) {
                thread.interrupt();
                thread = null;
            }
        }

        public boolean isCompleted() {
            return session.getStatus() == UploadSession.COMPLETED;
        }

        public void run() {
            while (!monitor.isCanceled() && !session.hasError() && !isCompleted()) {

                session.retrieveProgress();
                if (monitor.isCanceled() || session.hasError())
                    return;

                if (isCompleted()) {
                    monitor.worked(ticks - ticksUploaded);
                    ticksUploaded = ticks;
                    return;
                }

                int newUploaded = (int) (session.getUploadProgress() * ticks);
                if (newUploaded > ticksUploaded) {
                    monitor.worked(newUploaded - ticksUploaded);
                    ticksUploaded = newUploaded;
                }

                try {
                    Thread.sleep(760);
                } catch (InterruptedException e) {
                    return;
                }
            }
        }

    }

    private Info info;

    private UploadSession session;

    private TransferWorker transferWorker;

    public UploadJob(Info info) {
        super(NLS.bind(Messages.UploadJob_name, info.getString(Info.TITLE)));
        this.info = info;
    }

    protected IStatus run(IProgressMonitor monitor) {
        IStatus status = doRun(monitor);

        // prompt completion information to user
        if (status.isOK()) {
            promptCompletion();
            return status;
        }

        if (status.matches(IStatus.ERROR)) {
            // show error dialog
            status = promptError(session.getStatus(), status);

            if (status.isOK() || !status.matches(IStatus.ERROR))
                return status;

            // log this error, but prevent system from prompting dialogs,
            // because we have shown our own dialogs above.
            XmindSharePlugin.getDefault().getLog().log(status);
            return new Status(IStatus.WARNING, status.getPlugin(), status.getCode(),
                    status.getMessage() == null || "".equals(status.getMessage()) ? //$NON-NLS-1$ 
                            Messages.UploadJob_Failure_message : status.getMessage(),
                    status.getException());
        }

        // other status
        return status;
    }

    private IStatus doRun(IProgressMonitor monitor) {
        monitor.beginTask(null, 100);
        session = new UploadSession(info);

        // retrieve session and url
        monitor.subTask(Messages.UploadJob_Task_Prepare);
        session.prepare();
        if (session.hasError())
            return session.getError();
        if (monitor.isCanceled())
            return Status.CANCEL_STATUS;
        monitor.worked(5);

        // save the permalink into file
        savePermalink();
        if (monitor.isCanceled())
            return Status.CANCEL_STATUS;
        monitor.worked(5);

        // start transfering file data up to XMind server
        monitor.subTask(Messages.UploadJob_Task_TransferFile);
        transferWorker = new TransferWorker();
        transferWorker.start();
        if (session.hasError())
            return session.getError();
        if (monitor.isCanceled())
            return Status.CANCEL_STATUS;

        // wait for processing completion, error or user canceling
        // while retrieving transfer progress
        ProgressWorker progressWorker = new ProgressWorker(monitor, 89);
        progressWorker.start();
        do {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                return Status.CANCEL_STATUS;
            }

            // uploading failed
            if (session.hasError())
                return session.getError();

            // cancel uploading
            if (monitor.isCanceled()) {
                monitor.subTask(Messages.UploadJob_Task_Cancel);
                session.cancel();
                progressWorker.cancel();
                if (session.hasError())
                    return session.getError();
                return Status.CANCEL_STATUS;
            }

        } while (!progressWorker.isCompleted());

        // uploading completed
        monitor.done();
        return Status.OK_STATUS;
    }

    private void savePermalink() {
        if (session.getPermalink() == null)
            return;

        IWorkbook workbook = (IWorkbook) info.getProperty(Info.WORKBOOK);
        if (workbook != null) {
            workbook.getMeta().setValue(Info.SHARE + IMeta.SEP + "SourceUrl", //$NON-NLS-1$
                    session.getPermalink());
            File file = (File) info.getProperty(Info.FILE);
            if (file != null) {
                try {
                    workbook.saveTemp();
                    workbook.save(file.getAbsolutePath());
                } catch (IOException ignore) {
                } catch (CoreException ignore) {
                }
            } else {
                try {
                    workbook.save();
                } catch (IOException ignore) {
                } catch (CoreException ignore) {
                }
            }
        }
    }

    private void promptCompletion() {
        final Display display = PlatformUI.getWorkbench().getDisplay();
        if (display == null || display.isDisposed())
            return;
        display.asyncExec(new Runnable() {
            public void run() {
                final SimpleInfoPopupDialog[] dialogs = new SimpleInfoPopupDialog[1];
                IAction viewAction = new Action() {
                    public void run() {
                        showUploadedMap(session.getViewLink());
                        if (dialogs[0] != null)
                            dialogs[0].close();
                    }
                };
                viewAction.setText(Messages.UploadJob_View_text);

                SimpleInfoPopupDialog dialog = new SimpleInfoPopupDialog(null, null,
                        Messages.UploadJob_OpenMap_message, 0, null, viewAction);
                dialog.setDuration(10000);
                dialog.setGroupId("org.xmind.notifications"); //$NON-NLS-1$
                dialog.popUp();
                dialogs[0] = dialog;
            }
        });
    }

    private void showUploadedMap(String url) {
        if (url != null) {
            XMindNet.gotoURL(true, url);
            return;
        }

        IAccountInfo accountInfo = XMindNet.getAccountInfo();
        if (accountInfo == null)
            return;

        String userId = accountInfo.getUser();
        String token = accountInfo.getAuthToken();
        XMindNet.gotoURL(String.format("http://www.xmind.net/xmind/account/%s/%s/", //$NON-NLS-1$
                userId, token), true);
    }

    private IStatus promptError(int uploadStatus, IStatus error) {
        int code = error.getCode();
        String message = null;
        boolean tryAgainAllowed = true;
        if (uploadStatus == UploadSession.PREPARING) {
            if (code > 0) {
                if (code == HttpStatus.SC_UNAUTHORIZED) {
                    resignin();
                    return Status.CANCEL_STATUS;
                }
            }
        } else if (uploadStatus == UploadSession.UPLOADING) {
            if (code > 0) {
                if (code == HttpStatus.SC_NOT_FOUND) {
                    return Status.CANCEL_STATUS;
                } else if (code == UploadSession.CODE_VERIFICATION_FAILURE) {
                    message = Messages.ErrorDialog_Unauthorized_message;
                    tryAgainAllowed = false;
                }
            }
        }

        if (message == null)
            message = Messages.ErrorDialog_message;

        promptErrorMessage(message, tryAgainAllowed);
        return error;
    }

    private void promptErrorMessage(final String message, final boolean tryAgainAllowed) {
        Display display = PlatformUI.getWorkbench().getDisplay();
        if (display == null || display.isDisposed())
            return;

        display.asyncExec(new Runnable() {
            public void run() {
                if (tryAgainAllowed) {
                    if (MessageDialog.openQuestion(null, Messages.ErrorDialog_title, message)) {
                        schedule();
                    }
                } else {
                    MessageDialog.openError(null, Messages.ErrorDialog_title, message);
                }
            }
        });
    }

    private void resignin() {
        XMindNet.signOut();
        XMindNet.signIn(new IAuthenticationListener() {

            public void postSignIn(IAccountInfo accountInfo) {
                info.setProperty(Info.USER_ID, accountInfo.getUser());
                info.setProperty(Info.TOKEN, accountInfo.getAuthToken());
                schedule();

            }

            public void postSignOut(IAccountInfo oldAccountInfo) {
            }
        }, false);
    }

    @Override
    protected void canceling() {
        if (session != null) {
            session.cancel();
        }
        super.canceling();
    }
}