blob: 15876162de534cc62ec2404d0d8c43cfa0064f9c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2015 EclipseSource Inc. and others.
* 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:
* EclipseSource Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.internal.ui.shared.target;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.core.target.ITargetDefinition;
import org.eclipse.pde.core.target.ITargetLocation;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.target.IUBundleContainer;
import org.eclipse.pde.ui.target.ITargetLocationUpdater;
/**
* Updates selected target locations using {@link ITargetLocationUpdater}s in an asynchronous job
* <p>
* If all calls to {@link ITargetLocationUpdater#update(org.eclipse.pde.core.target.ITargetDefinition, ITargetLocation, IProgressMonitor)}
* return an OK status with {@link ITargetLocationUpdater#STATUS_CODE_NO_CHANGE}, the returned status will also have that status code,
* indicating that no changes were made to the target.
*/
public class UpdateTargetJob extends Job {
public static final String JOB_FAMILY_ID = "UpdateTargetJob"; //$NON-NLS-1$
private Map<ITargetLocation, Set<Object>> toUpdate;
private ITargetDefinition fTarget;
/**
* Schedules a new update job that will update all target locations in the provided map. A target's selected
* children can be added as a set to the values of the map so that only certain portions of the target
* location get updated.
* <p>
* TODO The {@link ITargetLocationUpdater} does not currently support updating children
* </p><p>
* If all calls to {@link ITargetLocationUpdater#update(org.eclipse.pde.core.target.ITargetDefinition, ITargetLocation, IProgressMonitor)}
* return an OK status with {@link ITargetLocationUpdater#STATUS_CODE_NO_CHANGE}, the returned status will also have that status code,
* indicating that no changes were made to the target.
* </p>
* @param target the target being updated
* @param toUpdate maps {@link ITargetLocation}s to the {@link Set} of selected children items
* that should be updated. The sets may be empty, but not <code>null</code>
* @param listener job change listener that will be added to the created job, can be <code>null</code>
*/
public static void update(ITargetDefinition target, Map<ITargetLocation, Set<Object>> toUpdate, IJobChangeListener listener) {
Job.getJobManager().cancel(JOB_FAMILY_ID);
Job job = new UpdateTargetJob(toUpdate, target);
job.setUser(true);
if (listener != null) {
job.addJobChangeListener(listener);
}
job.schedule();
}
/**
* Use {@link #update(Map, IJobChangeListener)} instead
*/
private UpdateTargetJob(Map<ITargetLocation, Set<Object>> toUpdate, ITargetDefinition target) {
super(Messages.UpdateTargetJob_UpdateJobName);
this.toUpdate = toUpdate;
fTarget = target;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
SubMonitor progress = SubMonitor.convert(monitor, Messages.UpdateTargetJob_UpdatingTarget, toUpdate.size() * 100);
MultiStatus errors = new MultiStatus(PDECore.PLUGIN_ID, 0, Messages.UpdateTargetJob_TargetUpdateFailedStatus, null);
boolean noChange = true;
for (Iterator<Map.Entry<ITargetLocation, Set<Object>>> iterator = toUpdate.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<ITargetLocation, Set<Object>> entry = iterator.next();
ITargetLocation location = entry.getKey();
Set<Object> children = entry.getValue();
String path = null;
try {
path = location.getLocation(false);
} catch (CoreException e1) {
// Ignore as this is just for the subtask
}
progress.subTask(NLS.bind(Messages.UpdateTargetJob_UpdatingContainer, path));
// TODO Custom code for IUBundleContainers with children selected
if (location instanceof IUBundleContainer && !children.isEmpty()) {
try {
boolean result = ((IUBundleContainer) location).update(children, progress.split(100));
if (result) {
noChange = false;
}
} catch (CoreException e) {
errors.add(e.getStatus());
}
} else {
ITargetLocationUpdater provider = (ITargetLocationUpdater) Platform.getAdapterManager().getAdapter(location, ITargetLocationUpdater.class);
if (provider != null) {
if (provider.canUpdate(fTarget, location)) {
IStatus result = provider.update(fTarget, location, progress.split(100));
if (result.isOK() && result.getCode() != ITargetLocationUpdater.STATUS_CODE_NO_CHANGE) {
noChange = false;
} else if (!result.isOK()) {
noChange = false;
errors.add(result);
}
}
} else {
// If the button enablement is correct, this should not get hit
progress.worked(100);
}
}
}
progress.done();
if (noChange) {
return new Status(IStatus.OK, PDECore.PLUGIN_ID, ITargetLocationUpdater.STATUS_CODE_NO_CHANGE, Messages.UpdateTargetJob_TargetUpdateSuccessStatus, null);
} else if (!errors.isOK()) {
return errors;
} else {
return Status.OK_STATUS;
}
}
}