// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.dataprofiler.core.ui.action.actions;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.talend.commons.exception.ExceptionHandler;
import org.talend.dataprofiler.core.CorePlugin;
import org.talend.dataprofiler.core.ImageLib;
import org.talend.dataprofiler.core.PluginConstant;
import org.talend.dataprofiler.core.helper.EEcosCategory;
import org.talend.dataprofiler.core.i18n.internal.DefaultMessagesImpl;
import org.talend.dataprofiler.core.pattern.ImportFactory;
import org.talend.dataprofiler.core.ui.dialog.message.ImportInfoDialog;
import org.talend.dataprofiler.ecos.EcosConstants;
import org.talend.dataprofiler.ecos.jobs.ComponentDownloader;
import org.talend.dataprofiler.ecos.jobs.DownloadListener;
import org.talend.dataprofiler.ecos.model.IEcosComponent;
import org.talend.dataprofiler.ecos.model.IRevision;
import org.talend.dataprofiler.ecos.service.JobService;
import org.talend.resource.EResourceConstant;
import org.talend.resource.ResourceManager;
import org.talend.utils.sugars.ReturnCode;
/**
* DOC bZhou class global comment. Detailled comment
*/
public class ImportRemotePatternAction extends Action {
private IEcosComponent[] components;
private int fExtensionDownloaded;
private List<IEcosComponent> fInstalledComponents;
public ImportRemotePatternAction(IEcosComponent[] components) {
super(DefaultMessagesImpl.getString("ImportRemotePatternAction.ImportDqRepository")); //$NON-NLS-1$
setImageDescriptor(ImageLib.getImageDescriptor(ImageLib.IMPORT));
this.components = components;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
setEnabled(false);
try {
Job job = new DownloadJob(components);
fExtensionDownloaded = 0;
fInstalledComponents = new ArrayList<IEcosComponent>();
job.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(final IJobChangeEvent event) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
doImportAfterDownload(event);
}
});
}
});
JobService.scheduleUserJob(job);
} catch (Throwable e) {
ExceptionHandler.process(e);
}
}
private void doImportAfterDownload(IJobChangeEvent event) {
final List<ReturnCode> information = new ArrayList<ReturnCode>();
setEnabled(true);
if (fExtensionDownloaded > 0) {
String csvFormat = System.getProperty("talend.exchange.csv"); //$NON-NLS-1$
if ("true".equals(csvFormat)) { //$NON-NLS-1$
for (IEcosComponent componet : fInstalledComponents) {
List<ImportObject> validImportObject = ImportObject.extractImportObject(componet, information);
if (!validImportObject.isEmpty()) {
String categoryName = componet.getCategry().getName();
EEcosCategory ecosCategory = EEcosCategory.getEcosCategory(categoryName);
if (ecosCategory != null) {
EResourceConstant resourceType = ecosCategory.getResource();
for (ImportObject importObject : validImportObject) {
information.addAll(ImportFactory.doImport(resourceType, importObject, componet.getName()));
}
}
}
}
// MOD qiongli 2011-11-28 TDQ-4038,give the message when there is nothing to import.
if (information.isEmpty()) {
information.add(new ReturnCode(
DefaultMessagesImpl.getString("ImportRemotePatternAction.NothingImport"), false)); //$NON-NLS-1$
}
ImportInfoDialog
.openImportInformation(
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
DefaultMessagesImpl.getString("ImportRemotePatternAction.ImportFinish"), information.toArray(new ReturnCode[0])); //$NON-NLS-1$
CorePlugin.getDefault().refreshDQView();
} else {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
for (IEcosComponent componet : fInstalledComponents) {
try {
ImportFactory.importFromExchange(componet);
} catch (Exception e) {
ExceptionHandler.process(e);
}
}
}
});
}
}
}
/**
* Notify after download complete.
*
* @param extension
*/
void extensionDownloadCompleted(IEcosComponent extension) {
fExtensionDownloaded++;
fInstalledComponents.add(extension);
}
/**
* DOC bZhou ImportRemotePatternAction class global comment. Detailled comment
*/
class DownloadJob extends Job implements DownloadListener {
private IProgressMonitor fMonitor = null;
private String fProgressLabel;
private int fBytesDownloaded;
private IEcosComponent[] fExtensions;
public DownloadJob(IEcosComponent[] extensions) {
super(EcosConstants.DOWNLOAD_TASK_TITLE);
fExtensions = extensions;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
SubMonitor progress = SubMonitor.convert(monitor, fExtensions.length * 10 + 5);
progress.setTaskName(this.getName());
for (IEcosComponent extension : fExtensions) {
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
fMonitor = progress.newChild(10);
downloadExtension(extension, fMonitor);
}
progress.setTaskName(EcosConstants.RELOAD_PALETTE);
// progress.done();
return Status.OK_STATUS;
}
private void downloadExtension(final IEcosComponent extension, final IProgressMonitor monitor) {
// get the revision
try {
IRevision revision = getRevision(extension);
if (revision == null) {
return;
}
String componentUrl = revision.getUrl();
monitor.setTaskName(EcosConstants.DOWNLOAD_TASK_NAME + PluginConstant.SPACE_STRING + componentUrl);
String targetFolder = ResourceManager.getExchangeFolder().getLocation().toOSString();
String fileName = revision.getFileName();
File localZipFile = new File(targetFolder, fileName);
if (extension.getInstalledLocation() != null && extension.getInstalledRevision() != null) {
// if already install the latest revision, ignore
if (extension.getInstalledRevision().getName().equals(revision.getName())) {
if (localZipFile.exists() && checkIfExisted(extension.getInstalledLocation())) {
// if the file size is same, this means the file has been downloaded already
if (isSameSize(localZipFile, componentUrl)) {
monitor.done();
extensionDownloadCompleted(extension);
return;
}
}
} else {
// before installing the new revision, delete the older
// revision that has been installed
File installedFile = new File(extension.getInstalledLocation());
if (installedFile.exists()) {
if (installedFile.isDirectory()) {
FileUtils.deleteDirectory(installedFile);
} else if (installedFile.isFile()) {
installedFile.delete();
}
}
extension.setInstalledLocation(null);
extension.setInstalledRevision(null);
}
}
URL url = new URL(componentUrl);
monitor.setTaskName(EcosConstants.DOWNLOAD_TASK_NAME + url.toString());
ComponentDownloader downloader = new ComponentDownloader();
downloader.addDownloadListener(DownloadJob.this);
// block until download complete
downloader.download(url, localZipFile);
// check if the job is cancelled
if (!monitor.isCanceled()) {
// update extesion status
extension.setInstalledRevision(revision);
extension.setInstalledLocation(localZipFile.getAbsolutePath());
monitor.done();
extensionDownloadCompleted(extension);
}
} catch (Exception e) {
ExceptionHandler.process(e);
}
}
/**
* DOC xqliu Comment method "isSameSize".
*
* @param localFile local file
* @param urlFile url file
* @throws IOException
*/
private boolean isSameSize(File localFile, String urlFile) throws IOException {
boolean sameSize = false;
if (localFile.exists() && localFile.isFile()) {
HttpURLConnection httpConnection = (HttpURLConnection) new URL(urlFile).openConnection();
if (localFile.length() == httpConnection.getContentLength()) {
sameSize = true;
}
}
return sameSize;
}
/**
* get the revision of the IEcosComponent, if there exist more than one, show a dialog for user to select.
*
* @param extension
* @return
* @throws InterruptedException
*/
private IRevision getRevision(IEcosComponent extension) throws InterruptedException {
IRevision revision = null;
final List<IRevision> revisions = extension.getRevisions();
if (revisions != null && !revisions.isEmpty()) {
if (revisions.size() == 1) {
revision = revisions.get(0);
} else {
SelectRevisionDialogThread thread = new SelectRevisionDialogThread(new SelectRevisionDialog(null, revisions));
Display.getDefault().syncExec(thread);
revision = thread.getRevision();
}
}
return revision;
}
/**
* Check if the component folder really exist, as the user may delete the folder from filesystem.
*
* @param installedLocation
* @return
*/
private boolean checkIfExisted(String installedLocation) {
try {
File dir = new File(installedLocation);
if (dir.exists()) {
return true;
}
} catch (Throwable e) {
// do nothing;
}
return false;
}
public void downloadComplete() {
}
public void downloadProgress(ComponentDownloader downloader, int bytesRead) {
if (fMonitor.isCanceled()) {
// cancel download
downloader.setCancel(true);
return;
}
fBytesDownloaded += bytesRead;
fMonitor.setTaskName(toKbFormat(fBytesDownloaded) + fProgressLabel);
fMonitor.worked(bytesRead);
}
public void downloadStart(int totalSize) {
fProgressLabel = "/" + toKbFormat(totalSize); //$NON-NLS-1$
fBytesDownloaded = 0;
fMonitor.beginTask("0 KB" + fProgressLabel, totalSize); //$NON-NLS-1$
}
private String toKbFormat(int size) {
return String.format("%1$s KB", size >> 10); //$NON-NLS-1$
}
}
/**
* created by xqliu on Sep 25, 2012 Detailled comment
*/
class SelectRevisionDialogThread extends Thread {
private SelectRevisionDialog selectRevisionDialog;
private IRevision revision;
public IRevision getRevision() {
return this.revision;
}
public SelectRevisionDialogThread(SelectRevisionDialog selectRevisionDialog) {
this.selectRevisionDialog = selectRevisionDialog;
}
@Override
public void run() {
if (this.selectRevisionDialog != null) {
if (this.selectRevisionDialog.open() == Window.OK) {
this.revision = this.selectRevisionDialog.getRevision();
}
}
}
}
/**
* created by xqliu on Sep 25, 2012 Detailled comment
*/
class SelectRevisionDialog extends Dialog {
private List<IRevision> revisions;
public List<IRevision> getRevisions() {
if (this.revisions == null) {
this.revisions = new ArrayList<IRevision>();
}
return this.revisions;
}
public void setRevisions(List<IRevision> revisions) {
this.revisions = revisions;
}
private IRevision revision;
public IRevision getRevision() {
return this.revision;
}
public void setRevision(IRevision revision) {
this.revision = revision;
}
/**
* DOC xqliu SelectRevisionDialog constructor comment.
*
* @param parentShell
* @param revisions
*/
protected SelectRevisionDialog(Shell parentShell, List<IRevision> revisions) {
super(parentShell);
this.setRevisions(revisions);
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(DefaultMessagesImpl.getString("SelectRevisionDialog.title")); //$NON-NLS-1$
}
@Override
protected Control createDialogArea(Composite parent) {
Composite comp = new Composite(parent, SWT.NONE);
comp.setLayout(new GridLayout(2, true));
comp.setLayoutData(new GridData(GridData.FILL_BOTH));
Label label = new Label(comp, SWT.NONE);
label.setText(DefaultMessagesImpl.getString("SelectRevisionDialog.revisions")); //$NON-NLS-1$
final CCombo revisionsCombo = new CCombo(comp, SWT.BORDER);
revisionsCombo.setEditable(false);
revisionsCombo.setItems(getRevisionItems());
revisionsCombo.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
String revisionName = revisionsCombo.getText();
for (IRevision rev : getRevisions()) {
if (revisionName.equals(rev.getName())) {
setRevision(rev);
break;
}
}
}
});
if (revisionsCombo.getItemCount() > 0) {
revisionsCombo.select(0);
}
return comp;
}
private String[] getRevisionItems() {
String[] items = new String[this.getRevisions().size()];
int i = 0;
for (IRevision rev : this.getRevisions()) {
items[i] = rev.getName();
i++;
}
return items;
}
}
}