/******************************************************************************* * Copyright 2009 Google Inc. All Rights Reserved. * * 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 * * 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.google.gdt.eclipse.suite.update; import com.google.gdt.eclipse.core.CorePluginLog; import com.google.gdt.eclipse.core.extensions.ExtensionQuery; import com.google.gdt.eclipse.core.extensions.ExtensionQuery.Data; import com.google.gdt.eclipse.core.jobs.DownloadJob; import com.google.gdt.eclipse.core.update.internal.core.DailyUpdateCheckStrategy; import com.google.gdt.eclipse.core.update.internal.core.UpdateCheckStrategy; import com.google.gdt.eclipse.suite.preferences.GdtPreferences; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.IJobChangeListener; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.ui.progress.IProgressConstants; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * Handles update checks for the plugin. */ public class FeatureUpdateManager implements DownloadJobCreator { protected static File createTmpFile() throws IOException { File tempFile = File.createTempFile("site", "xml"); tempFile.deleteOnExit(); return tempFile; } protected final UpdateSiteURLGenerator urlGenerator; private final List<DownloadJob> downloadJobs; private IJobChangeListener removeJobOnCompleteListener = new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { synchronized (downloadJobs) { downloadJobs.remove(event.getJob()); } } }; private FeatureUpdateCheckersMap updateCheckersMap; private final UpdateCheckStrategy updateCheckStrategy = new DailyUpdateCheckStrategy(); /** * Constructs an instance with a generator for an update site URL, and a * {@link FeatureUpdateCheckersMap}. * * @param urlGenerator generates the URL for the update site * @param updateCheckersMap if the update site URL has the string provided by * the key of the UpdateSiteToken then the corresponding checker * scans the update site to determine if an update is available. */ public FeatureUpdateManager(UpdateSiteURLGenerator urlGenerator, FeatureUpdateCheckersMap updateCheckersMap) { this.updateCheckersMap = updateCheckersMap; this.urlGenerator = urlGenerator; downloadJobs = new ArrayList<DownloadJob>(); } /** * Terminates any update checks that are currently in progress. */ public void cancelPendingUpdates() { synchronized (downloadJobs) { for (DownloadJob dlj : downloadJobs) { dlj.cancel(); } downloadJobs.clear(); } } /** * Checks the update site to see if any updates are available. The check will * be aborted if update notifications are disabled, or an update check is * currently in progress, or, if according to the * <code>updateCheckStrategy</code>, it is not time for an update check as * yet. */ public void checkForUpdates() { if (!GdtPreferences.areUpdateNotificationsEnabled()) { // Update checks are disabled return; } synchronized (downloadJobs) { if (downloadJobs.size() > 0) { // Update check is in progress return; } } if (!updateCheckStrategy.shouldCheckForUpdates(GdtPreferences.getLastUpdateTimeMillis())) { // Still waiting to check again return; } // Assume that the update check will succeed. GdtPreferences.setLastUpdateTimeMillis(System.currentTimeMillis()); ExtensionQuery<DownloadJobCreator> extQuery = new ExtensionQuery<DownloadJobCreator>( GdtExtPlugin.PLUGIN_ID, "updatePing", "class"); List<ExtensionQuery.Data<DownloadJobCreator>> dlCreators = extQuery.getData(); // add this object too so that its download job gets run too, eg adding a // fake extension query result dlCreators.add(new Data<DownloadJobCreator>(this, null)); for (Data<DownloadJobCreator> datum : dlCreators) { try { File tempFile = createTmpFile(); DownloadJobCreator dljc = datum.getExtensionPointData(); DownloadJob downloadJob = dljc.createDownloadJob(tempFile, urlGenerator); addDownloadJob(downloadJob); } catch (Exception e) { CorePluginLog.logError(e); } } } @Override public DownloadJob createDownloadJob(final File tempFile, UpdateSiteURLGenerator generator) { URL updateSiteUrl; try { updateSiteUrl = generator.generateURL(); } catch (MalformedURLException e) { return null; } DownloadJob newDownloadJob = new DownloadJob( "Download compositeArtifacts.xml", updateSiteUrl, tempFile); CompositeArtifactsDowloadJobChangeListener compositeArtifactsDowloadJobChangeListener = new CompositeArtifactsDowloadJobChangeListener( tempFile, updateCheckersMap, this); newDownloadJob.addJobChangeListener(compositeArtifactsDowloadJobChangeListener); return newDownloadJob; } protected void addDownloadJob(DownloadJob downloadJob) { if (downloadJob != null) { // This is a non-user job, so make sure that it has no presence in the // Progress View downloadJob.setSystem(true); downloadJob.addJobChangeListener(removeJobOnCompleteListener); // If the job returns an ERROR status, make sure that it does not show // a modal dialog with the ERROR information; we want a silent failure downloadJob.setProperty( IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, true); synchronized (downloadJobs) { downloadJob.schedule(); downloadJobs.add(downloadJob); } } } }