adding signing of jars to maven package phase
[taxeditor.git] / eu.etaxonomy.taxeditor.application / src / main / java / eu / etaxonomy / taxeditor / update / P2Util.java
1 package eu.etaxonomy.taxeditor.update;
2
3 import java.net.URI;
4 import java.net.URISyntaxException;
5
6 import org.eclipse.core.runtime.IProgressMonitor;
7 import org.eclipse.core.runtime.IStatus;
8 import org.eclipse.core.runtime.OperationCanceledException;
9 import org.eclipse.core.runtime.Status;
10 import org.eclipse.core.runtime.jobs.IJobChangeEvent;
11 import org.eclipse.core.runtime.jobs.Job;
12 import org.eclipse.core.runtime.jobs.JobChangeAdapter;
13 import org.eclipse.equinox.p2.core.IProvisioningAgent;
14 import org.eclipse.equinox.p2.operations.ProvisioningJob;
15 import org.eclipse.equinox.p2.operations.ProvisioningSession;
16 import org.eclipse.equinox.p2.operations.Update;
17 import org.eclipse.equinox.p2.operations.UpdateOperation;
18 import org.eclipse.swt.widgets.Display;
19 import org.eclipse.ui.PlatformUI;
20 import org.osgi.framework.BundleContext;
21 import org.osgi.framework.ServiceReference;
22
23 import eu.etaxonomy.taxeditor.ApplicationUtil;
24 import eu.etaxonomy.taxeditor.TaxonomicEditorPlugin;
25 import eu.etaxonomy.taxeditor.model.MessagingUtils;
26
27 /**
28 * This class is a utility class for updating the editor from a p2 update site,
29 * greatly inspired by the links given below.
30 *
31 *
32 * To Do :
33 * - Allow configurable update sites
34 *
35 * Notes :
36 * - tried to get rid of the popup dialog which warns about unsigned jars using
37 * -Declipse.p2.unsignedPolicy=allow but this does not work due to
38 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=391399, so the only solution
39 * is to sign the jars with an official certificate.
40 *
41 * @see http://wiki.eclipse.org/Equinox/p2/Adding_Self-Update_to_an_RCP_Application
42 * @see http://bugs.eclipse.org/281226
43 * @see http://www.vogella.com/tutorials/EclipseP2Update/article.html
44 */
45 public class P2Util {
46
47 //private static String LOCAL_UPDATE_SITE = "file:///path/.../to/Development/EDIT/taxeditor/eu.etaxonomy.taxeditor/target/repository/";
48 private static String EDIT_NIGHTLY_UPDATE_SITE = "http://cybertaxonomy.eu/download/taxeditor/update/nightly/";
49 private static String EDIT_SNAPSHOT_UPDATE_SITE = "http://cybertaxonomy.eu/download/taxeditor/update/snapshot/";
50 private static String EDIT_STABLE_UPDATE_SITE = "http://cybertaxonomy.eu/download/taxeditor/update/stable/";
51
52 public static void setUpdateRepositories(UpdateOperation operation) throws URISyntaxException {
53 String updateSite = EDIT_NIGHTLY_UPDATE_SITE;
54 if(ApplicationUtil.isStable()) {
55 updateSite = EDIT_STABLE_UPDATE_SITE;
56 }
57 operation.getProvisioningContext().setMetadataRepositories(new URI[]{new URI(updateSite)});
58 operation.getProvisioningContext().setArtifactRepositories(new URI[]{new URI(updateSite)});
59 }
60 /**
61 *
62 *
63 */
64 public static void checkForUpdates() {
65 // the main job which performs the update
66 Job updateJob = new Job("Update Job") {
67 @Override
68 public IStatus run(IProgressMonitor monitor) {
69 return doCheckForUpdates(monitor);
70 }
71 };
72 updateJob.schedule();
73 }
74
75 /**
76 * @param monitor
77 * @return
78 */
79 private static IStatus doCheckForUpdates(IProgressMonitor monitor) {
80
81 BundleContext bundleContext = TaxonomicEditorPlugin.getContext();
82 ServiceReference reference = bundleContext.getServiceReference(IProvisioningAgent.SERVICE_NAME);
83 if (reference == null) {
84 IStatus errorStatus = new Status(IStatus.ERROR, TaxonomicEditorPlugin.PLUGIN_ID,
85 "No provisioning agent found. This application is not set up for updates.");
86 return errorStatus;
87 }
88
89 final IProvisioningAgent agent = (IProvisioningAgent) bundleContext.getService(reference);
90 IStatus updateStatus;
91 try {
92 updateStatus = P2Util.checkForUpdates(agent, monitor);
93 MessagingUtils.info(updateStatus);
94 } finally {
95 bundleContext.ungetService(reference);
96 }
97 return updateStatus;
98 }
99
100 /**
101 * @param agent
102 * @param monitor
103 * @return
104 * @throws OperationCanceledException
105 */
106 static IStatus checkForUpdates(IProvisioningAgent agent, final IProgressMonitor monitor) {
107 ProvisioningSession session = new ProvisioningSession(agent);
108 // the default update operation looks for updates to the currently
109 // running profile, using the default profile root marker. To change
110 // which installable units are being updated, use the more detailed
111 // constructors.
112 final UpdateOperation operation = new UpdateOperation(session);
113 try {
114 setUpdateRepositories(operation);
115 } catch (URISyntaxException e) {
116 MessagingUtils.errorDialog("Invalid update site URI",
117 operation,
118 "The update site URI has an invalid syntax",
119 TaxonomicEditorPlugin.PLUGIN_ID,
120 e,
121 false);
122 return null;
123 }
124
125 final IStatus status = operation.resolveModal(monitor);
126
127 if (status.getCode() == UpdateOperation.STATUS_NOTHING_TO_UPDATE) {
128 return status;
129 }
130
131 if (status.isOK() && status.getSeverity() != IStatus.ERROR) {
132 // We need this block of code to be in async execution
133 // since the confirm dialogs work only on the UI thread
134 Display.getDefault().asyncExec(new Runnable() {
135 @Override
136 public void run() {
137 String updates = "";
138 Update[] possibleUpdates = operation
139 .getPossibleUpdates();
140 for (Update update : possibleUpdates) {
141 updates += update + "\n";
142 }
143
144 boolean doInstall = MessagingUtils.confirmDialog("Updates available", "Do you want to install the available updates ?");
145 // We may need to think whether we still run in async mode once
146 // the user agrees to update. Maybe be reasonable to change to blocking
147 // from this point until the update is complete.
148
149 // More complex status handling might include showing the user what
150 // updates are available if there are multiples, differentiating
151 // patches vs. updates, etc. In this example, we simply update as
152 // suggested by the operation.
153 if(doInstall) {
154 ProvisioningJob provisioningJob = operation.getProvisioningJob(monitor);
155 if (provisioningJob == null) {
156 MessagingUtils.messageDialog("Error in performing update",
157 operation,
158 "ProvisioningJob could not be created." + System.getProperty("line.separator") +
159 "Either this application does not support p2 software installation or this application has been launched from within the Eclipse IDE",
160 null,
161 false);
162
163 } else {
164 // register a job change listener to track
165 // installation progress and notify user upon success
166 provisioningJob
167 .addJobChangeListener(new JobChangeAdapter() {
168 @Override
169 public void done(IJobChangeEvent event) {
170 if (event.getResult().isOK()) {
171 // We need this block of code to be in async execution
172 // since the confirm dialogs work only on the UI thread
173 Display.getDefault().asyncExec(new Runnable() {
174 @Override
175 public void run() {
176 boolean restart = MessagingUtils.confirmDialog(
177 "Updates installed, restart?",
178 "Updates have been installed successfully, do you want to restart?");
179 if (restart) {
180 PlatformUI.getWorkbench().restart();
181 }
182 }
183 });
184 }
185 super.done(event);
186 }
187 });
188 provisioningJob.schedule();
189 }
190 }
191 }
192 });
193 }
194 return status;
195 }
196 }