1 package eu
.etaxonomy
.taxeditor
.update
;
4 import java
.net
.URISyntaxException
;
5 import java
.util
.ArrayList
;
8 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
9 import org
.eclipse
.core
.runtime
.IStatus
;
10 import org
.eclipse
.core
.runtime
.OperationCanceledException
;
11 import org
.eclipse
.core
.runtime
.Status
;
12 import org
.eclipse
.core
.runtime
.jobs
.IJobChangeEvent
;
13 import org
.eclipse
.core
.runtime
.jobs
.Job
;
14 import org
.eclipse
.core
.runtime
.jobs
.JobChangeAdapter
;
15 import org
.eclipse
.equinox
.internal
.p2
.ui
.ProvUI
;
16 import org
.eclipse
.equinox
.internal
.p2
.ui
.model
.ElementUtils
;
17 import org
.eclipse
.equinox
.internal
.p2
.ui
.model
.MetadataRepositoryElement
;
18 import org
.eclipse
.equinox
.p2
.core
.IProvisioningAgent
;
19 import org
.eclipse
.equinox
.p2
.core
.ProvisionException
;
20 import org
.eclipse
.equinox
.p2
.operations
.ProvisioningJob
;
21 import org
.eclipse
.equinox
.p2
.operations
.ProvisioningSession
;
22 import org
.eclipse
.equinox
.p2
.operations
.Update
;
23 import org
.eclipse
.equinox
.p2
.operations
.UpdateOperation
;
24 import org
.eclipse
.equinox
.p2
.repository
.IRepository
;
25 import org
.eclipse
.equinox
.p2
.repository
.IRepositoryManager
;
26 import org
.eclipse
.equinox
.p2
.repository
.metadata
.IMetadataRepositoryManager
;
27 import org
.eclipse
.equinox
.p2
.ui
.ProvisioningUI
;
28 import org
.eclipse
.swt
.widgets
.Display
;
29 import org
.eclipse
.ui
.PlatformUI
;
30 import org
.osgi
.framework
.BundleContext
;
31 import org
.osgi
.framework
.ServiceReference
;
33 import eu
.etaxonomy
.taxeditor
.TaxonomicEditorPlugin
;
34 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
35 import eu
.etaxonomy
.taxeditor
.preference
.PreferencesUtil
;
36 import eu
.etaxonomy
.taxeditor
.util
.ApplicationUtil
;
39 * This class is a utility class for updating the editor from a p2 update site,
40 * greatly inspired by the links given below.
44 * - Allow configurable update sites
49 * @see http://wiki.eclipse.org/Equinox/p2/Adding_Self-Update_to_an_RCP_Application
50 * @see http://bugs.eclipse.org/281226
51 * @see http://www.vogella.com/tutorials/EclipseP2Update/article.html
55 //private static String LOCAL_UPDATE_SITE = "file:///path/.../to/Development/EDIT/taxeditor/eu.etaxonomy.taxeditor/target/repository/";
57 private static String EDIT_NIGHTLY_UPDATE_SITE
= "http://cybertaxonomy.eu/download/taxeditor/update/nightly/";
58 private static String EDIT_NIGHTLY_UPDATE_SITE_NAME
= "Taxonomic Editor Nightly";
60 private static String EDIT_SNAPSHOT_UPDATE_SITE
= "http://cybertaxonomy.eu/download/taxeditor/update/snapshot/";
61 private static String EDIT_SNAPSHOT_UPDATE_SITE_NAME
= "Taxonomic Editor Snapshot";
63 private static String EDIT_STABLE_UPDATE_SITE
= "http://cybertaxonomy.eu/download/taxeditor/update/stable/";
64 private static String EDIT_STABLE_UPDATE_SITE_NAME
= "Taxonomic Editor Stable";
67 * Retrieve and load the saved list of repositories from the preference store,
68 * making sure that at least the default repository is always loaded.
70 @SuppressWarnings("restriction")
71 public static void setP2UpdateRepositories() {
72 String updateSite
= EDIT_NIGHTLY_UPDATE_SITE
;
73 String updateSiteName
= EDIT_NIGHTLY_UPDATE_SITE_NAME
;
75 if(ApplicationUtil
.isStable()) {
76 updateSite
= EDIT_STABLE_UPDATE_SITE
;
77 updateSiteName
= EDIT_STABLE_UPDATE_SITE_NAME
;
79 List
<MetadataRepositoryElement
> repoElements
= new ArrayList
<MetadataRepositoryElement
>();
80 List
<MetadataRepositoryElement
> savedRepoElements
= PreferencesUtil
.getP2Repositories();
81 if(savedRepoElements
.isEmpty()) {
82 // we always need an update site, so we add the default one
84 MetadataRepositoryElement element
= new MetadataRepositoryElement(null, new URI(updateSite
), true);
85 element
.setNickname(updateSiteName
);
86 repoElements
.add(element
);
87 } catch (URISyntaxException e
) {
88 MessagingUtils
.errorDialog("Invalid update site URI",
90 "The update site URI has an invalid syntax",
91 TaxonomicEditorPlugin
.PLUGIN_ID
,
96 repoElements
.addAll(savedRepoElements
);
98 ElementUtils
.updateRepositoryUsingElements(ProvisioningUI
.getDefaultUI(),repoElements
99 .toArray(new MetadataRepositoryElement
[]{} ), null);
104 * {@link org.eclipse.equinox.p2.ui.RepositoryManipulationPage} which handles the repsitory site list
105 * in preferences does not create a preference store and hence the changes are not saved. This means
106 * that we need to save it ourselves.
108 * This method saves the list of current repositories in the preference store as a string with
109 * specific delimiters.
112 public static void saveP2RepositoryPreferences() {
114 IMetadataRepositoryManager metaManager
= ProvUI
.getMetadataRepositoryManager(ProvisioningUI
.getDefaultUI().getSession());
116 URI
[] currentlyEnabled
= metaManager
.getKnownRepositories(IRepositoryManager
.REPOSITORIES_ALL
);
117 URI
[] currentlyDisabled
= metaManager
.getKnownRepositories(IRepositoryManager
.REPOSITORIES_DISABLED
);
119 List
<MetadataRepositoryElement
> repoElements
= new ArrayList
<MetadataRepositoryElement
>();
121 for(URI repo
: currentlyEnabled
) {
122 boolean enabled
= true;
123 String nickname
= metaManager
.getRepositoryProperty(repo
, IRepository
.PROP_NICKNAME
);
124 MetadataRepositoryElement element
= new MetadataRepositoryElement(null, repo
, true);
125 element
.setNickname(nickname
);
126 element
.setEnabled(enabled
);
127 repoElements
.add(element
);
130 for(URI repo
: currentlyDisabled
) {
131 boolean enabled
= false;
132 String nickname
= metaManager
.getRepositoryProperty(repo
, IRepository
.PROP_NICKNAME
);
133 MetadataRepositoryElement element
= new MetadataRepositoryElement(null, repo
, true);
134 element
.setNickname(nickname
);
135 element
.setEnabled(enabled
);
136 repoElements
.add(element
);
138 PreferencesUtil
.setP2Repositories(repoElements
);
145 public static void checkForUpdates() {
147 Job updateJob
= new Job("Update Job") {
149 public IStatus
run(IProgressMonitor monitor
) {
150 return doCheckForUpdates(monitor
);
153 updateJob
.schedule();
160 private static IStatus
doCheckForUpdates(IProgressMonitor monitor
) {
162 // force refresh all the caches before
163 IMetadataRepositoryManager metaManager
= ProvUI
.getMetadataRepositoryManager(ProvisioningUI
.getDefaultUI().getSession());
164 URI
[] repos
= metaManager
.getKnownRepositories(IRepositoryManager
.REPOSITORIES_ALL
);
165 for(URI repo
: repos
) {
167 metaManager
.refreshRepository(repo
, monitor
);
168 } catch (ProvisionException pe
) {
169 IStatus errorStatus
= new Status(IStatus
.ERROR
, TaxonomicEditorPlugin
.PLUGIN_ID
,
170 "Error occured while reloading cache.", pe
);
172 } catch (OperationCanceledException oce
) {
173 IStatus errorStatus
= new Status(IStatus
.ERROR
, TaxonomicEditorPlugin
.PLUGIN_ID
,
174 "Error occured while reloading cache.", oce
);
177 BundleContext bundleContext
= TaxonomicEditorPlugin
.getContext();
178 ServiceReference reference
= bundleContext
.getServiceReference(IProvisioningAgent
.SERVICE_NAME
);
179 if (reference
== null) {
180 IStatus errorStatus
= new Status(IStatus
.ERROR
, TaxonomicEditorPlugin
.PLUGIN_ID
,
181 "No provisioning agent found. This application is not set up for updates.");
185 final IProvisioningAgent agent
= (IProvisioningAgent
) bundleContext
.getService(reference
);
186 IStatus updateStatus
;
188 updateStatus
= P2Util
.checkForUpdates(agent
, monitor
);
189 MessagingUtils
.info(updateStatus
);
191 bundleContext
.ungetService(reference
);
200 * @throws OperationCanceledException
202 static IStatus
checkForUpdates(IProvisioningAgent agent
, final IProgressMonitor monitor
) {
203 ProvisioningSession session
= new ProvisioningSession(agent
);
204 // the default update operation looks for updates to the currently
205 // running profile, using the default profile root marker. To change
206 // which installable units are being updated, use the more detailed
208 final UpdateOperation operation
= new UpdateOperation(session
);
210 // setUpdateRepositories(operation);
211 // } catch (URISyntaxException e) {
212 // MessagingUtils.errorDialog("Invalid update site URI",
214 // "The update site URI has an invalid syntax",
215 // TaxonomicEditorPlugin.PLUGIN_ID,
221 final IStatus status
= operation
.resolveModal(monitor
);
223 if (status
.getCode() == UpdateOperation
.STATUS_NOTHING_TO_UPDATE
) {
227 if (status
.isOK() && status
.getSeverity() != IStatus
.ERROR
) {
228 // We need this block of code to be in async execution
229 // since the confirm dialogs work only on the UI thread
230 Display
.getDefault().asyncExec(new Runnable() {
234 Update
[] possibleUpdates
= operation
235 .getPossibleUpdates();
236 for (Update update
: possibleUpdates
) {
237 updates
+= update
+ "\n";
240 boolean doInstall
= MessagingUtils
.confirmDialog("Updates available", "Do you want to install the available updates ?");
241 // We may need to think whether we still run in async mode once
242 // the user agrees to update. Maybe be reasonable to change to blocking
243 // from this point until the update is complete.
245 // More complex status handling might include showing the user what
246 // updates are available if there are multiples, differentiating
247 // patches vs. updates, etc. In this example, we simply update as
248 // suggested by the operation.
250 ProvisioningJob provisioningJob
= operation
.getProvisioningJob(monitor
);
251 if (provisioningJob
== null) {
252 MessagingUtils
.messageDialog("Error in performing update",
254 "ProvisioningJob could not be created." + System
.getProperty("line.separator") +
255 "Either this application does not support p2 software installation or this application has been launched from within the Eclipse IDE",
260 // register a job change listener to track
261 // installation progress and notify user upon success
263 .addJobChangeListener(new JobChangeAdapter() {
265 public void done(IJobChangeEvent event
) {
266 if (event
.getResult().isOK()) {
267 // We need this block of code to be in async execution
268 // since the confirm dialogs work only on the UI thread
269 Display
.getDefault().asyncExec(new Runnable() {
272 boolean restart
= MessagingUtils
.confirmDialog(
273 "Updates installed, restart?",
274 "Updates have been installed successfully, do you want to restart?");
276 PlatformUI
.getWorkbench().restart();
284 provisioningJob
.schedule();