/*
* � Copyright IBM Corp. 2015
*
* Licensed 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 com.ibm.xsp.extlib.designer.bluemix.job;
import java.io.File;
import lotus.domino.Database;
import lotus.domino.NotesException;
import lotus.domino.Session;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.statushandlers.IStatusAdapterConstants;
import org.eclipse.ui.statushandlers.StatusAdapter;
import org.eclipse.ui.statushandlers.StatusManager;
import com.ibm.commons.util.StringUtil;
import com.ibm.designer.domino.ide.resources.DominoResourcesPlugin;
import com.ibm.designer.domino.ide.resources.extensions.NotesPlatform;
import com.ibm.designer.domino.ide.resources.ipc.NsfDbInfo;
import com.ibm.designer.domino.ide.resources.project.DominoDesignerProject;
import com.ibm.designer.domino.navigator.actions.DeleteResourceAction;
import com.ibm.xsp.extlib.designer.bluemix.BluemixLogger;
import com.ibm.xsp.extlib.designer.bluemix.BluemixPlugin;
import com.ibm.xsp.extlib.designer.bluemix.config.BluemixConfig;
import com.ibm.xsp.extlib.designer.bluemix.config.ConfigManager;
import com.ibm.xsp.extlib.designer.bluemix.job.DeployJob.MutexRule;
import com.ibm.xsp.extlib.designer.bluemix.util.BluemixUtil;
import com.ibm.xsp.extlib.designer.bluemix.util.BluemixZipUtil;
/**
* @author Gary Marjoram
*
*/
@SuppressWarnings("restriction") // $NON-NLS-1$
public class ImportJob extends Job {
private static MutexRule _jobRule = new MutexRule();
private Throwable _threadException;
private final BluemixConfig _config;
private final String _zipFileName;
private final String _importCopyMethod;
public ImportJob(BluemixConfig config, String zipFileName, String importCopyMethod) {
super(BluemixUtil.productizeString("Import %BM_PRODUCT% Starter Code")); // $NLX-ImportJob.ImportIBMBluemixStarterCode-1$
_config = config;
_zipFileName = zipFileName;
_importCopyMethod = importCopyMethod;
}
@Override
protected IStatus run(final IProgressMonitor monitor) {
monitor.beginTask("Importing starter code", IProgressMonitor.UNKNOWN); // $NLX-ImportJob.ImportingStarterCode-1$
try {
// Get the NSF name from the zip file
final String nsfName = BluemixZipUtil.getNsfFromZipFile(new File(_zipFileName));
if (StringUtil.isEmpty(nsfName)) {
throw new Exception("There is no NSF in the starter code zip file"); // $NLX-ImportJob.ThereisnoNSFintheStarterCodeZIPFi-1$
}
// Construct the target NSF name - c:\notes\data\xxx.nsf
final String targetNsfName = BluemixUtil.getNotesDataDir() + File.separator + nsfName;
// Check if the target NSF is open in Designer
DominoDesignerProject ddp = BluemixUtil.getDesignerProjectFromWorkspace(nsfName);
if (ddp != null) {
// Delete the project and NSF
final DeleteResourceAction delAction = new DeleteResourceAction(true, new File(targetNsfName).exists());
delAction.selectionChanged(new StructuredSelection(ddp));
Display.getDefault().syncExec(new Runnable(){
public void run() {
delAction.run();
}
});
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
// Wait on the delete jobs to complete before continuing
IJobManager jobManager = Job.getJobManager();
jobManager.join(IDEWorkbenchMessages.DeleteResourceAction_checkJobName, new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));
jobManager.join(IDEWorkbenchMessages.DeleteResourceAction_jobName, new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
// Is everything clean (Project and NSF should be gone) ???
// User may have cancelled or there was an error
if ((BluemixUtil.getDesignerProjectFromWorkspace(nsfName) != null) || (new File(targetNsfName).exists())) {
// Just finish - can't do anything else
return Status.CANCEL_STATUS;
}
}
// If the target NSF still exists at this point then it wasn't
// open in Designer - Delete it now
if (new File(targetNsfName).exists()) {
// Ask the user for confirmation
final boolean[] continueJob = new boolean[1];
PlatformUI.getWorkbench().getDisplay().syncExec (new Runnable () {
public void run () {
String msg = StringUtil.format("\"{0}\" will be overwritten, do you want to continue with this import?", targetNsfName); // $NLX-ImportJob.0willbeoverwrittendoyouwanttocont-1$
continueJob[0] = MessageDialog.openQuestion(null, "Importing Starter Code", msg); // $NLX-ImportJob.ImportingStarterCode.1-1$
}
});
if (!continueJob[0]) {
// User has cancelled
return Status.CANCEL_STATUS;
}
_threadException = null;
NotesPlatform.getInstance().syncExec(new Runnable() {
public void run() {
Database db = null;
try {
// Delete the existing NSF
monitor.subTask("Deleting database..."); // $NLX-ImportJob.Deletingdatabase-1$
Session sess = NotesPlatform.getInstance().getSession();
db = sess.getDatabase(null, nsfName);
db.remove();
} catch (Throwable e) {
// Record the Exception
_threadException = e;
} finally {
if (db != null) {
try {
db.recycle();
} catch (NotesException e) {
if (BluemixLogger.BLUEMIX_LOGGER.isErrorEnabled()) {
BluemixLogger.BLUEMIX_LOGGER.errorp(this, "run", e, "Failed to recycle db"); // $NON-NLS-1$ $NLE-ImportJob.Failedtorecycledb-2$
}
}
}
}
}
});
if (_threadException != null) {
throw new Exception("Could not delete database", _threadException); // $NLX-ImportJob.Couldnotdeletedatabase-1$
}
}
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
monitor.subTask("Unzipping the starter code zip file..."); // $NLX-ImportJob.UnzippingtheStarterCodeZIPfile-1$
BluemixZipUtil.unzipFile(_zipFileName, _config.directory);
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
// Copy the DB to the data directory
monitor.subTask("Copying NSF to data directory"); // $NLX-ImportJob.CopyingNSFtodatadirectory-1$
// Make a copy or use the actual NSF ?
if (StringUtil.equalsIgnoreCase(_importCopyMethod, "copy") || StringUtil.equalsIgnoreCase(_importCopyMethod, "replica")) { // $NON-NLS-1$ $NON-NLS-2$
// We need a thread for this
_threadException = null;
NotesPlatform.getInstance().syncExec(new Runnable() {
public void run() {
Database db = null;
try {
Session sess = NotesPlatform.getInstance().getSession();
db = sess.getDatabase(null, BluemixUtil.getNsfFromDirectory(_config.directory).getPath());
if(StringUtil.equalsIgnoreCase(_importCopyMethod, "copy")) { // $NON-NLS-1$
BluemixUtil.createLocalDatabaseCopy(db, nsfName);
} else {
BluemixUtil.createLocalDatabaseReplica(db, nsfName);
}
} catch (Throwable e) {
// Record the Exception
_threadException = e;
} finally {
if (db != null) {
try {
db.remove();
db.recycle();
} catch (NotesException e) {
if (BluemixLogger.BLUEMIX_LOGGER.isErrorEnabled()) {
BluemixLogger.BLUEMIX_LOGGER.errorp(this, "run", e, "Failed to remove/recycle db"); // $NON-NLS-1$ $NLE-ImportJob.Failedtorecycledb.1-2$
}
}
}
}
}
});
if (_threadException != null) {
throw new Exception("Could not copy database", _threadException); // $NLX-ImportJob.Couldnotcopydatabase-1$
}
} else {
// Use the actual database from the ZIP file
// It will have the same replicaID
BluemixUtil.copyFile(BluemixUtil.getNsfFromDirectory(_config.directory), new File(targetNsfName));
}
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
// Open the newly copied NSF in Designer
_threadException = null;
Display.getDefault().syncExec(new Runnable(){
public void run() {
try {
if (DominoResourcesPlugin.canEditDbWithError("Local", nsfName)) { // $NON-NLS-1$
final NsfDbInfo info = DominoResourcesPlugin.addToNotesWorkspace("Local", nsfName); // $NON-NLS-1$
if (info != null) {
DominoResourcesPlugin.createDominoDesignerProject(info, new JobChangeAdapter(){
public void done(IJobChangeEvent event) {
super.done(event);
// Create the link to the deployment directory
DominoDesignerProject ddp = BluemixUtil.getDesignerProjectFromWorkspace(info.getFullPath());
if (ddp != null) {
ConfigManager.getInstance().setConfig(ddp, _config, false, null);
}
}
});
} else {
throw new Exception("addToNotesWorkspace returned null"); // $NLX-ImportJob.addToNotesWorkspacereturnednull-1$
}
} else {
throw new Exception("canEditDbWithError returned false"); // $NLX-ImportJob.canEditDbWithErrorreturnedfalse-1$
}
} catch (Throwable e) {
// Record the Exception
_threadException = e;
}
}
});
// Did the NSF open successfully?
if (_threadException != null) {
// No throw exception
throw new Exception("Error opening starter code project", _threadException); // $NLX-ImportJob.ErroropeningStarterCodeproject-1$
}
} catch (Throwable e) {
StatusAdapter status = new StatusAdapter(new Status(IStatus.ERROR, BluemixPlugin.PLUGIN_ID, 0, BluemixUtil.getErrorText(e), null));
status.setProperty(IStatusAdapterConstants.TITLE_PROPERTY, e.getMessage());
StatusManager.getManager().handle(status, StatusManager.BLOCK);
if (BluemixLogger.BLUEMIX_LOGGER.isErrorEnabled()) {
BluemixLogger.BLUEMIX_LOGGER.errorp(this, "run", BluemixUtil.getRootCause(e), "Error importing starter code"); // $NON-NLS-1$ $NLE-ImportJob.ErrorimportingStarterCode-2$
}
}
return Status.OK_STATUS;
}
public void start() {
setPriority(Job.BUILD);
setUser(true);
setRule(_jobRule);
schedule();
}
}