/
BuildUpdateSiteStep.java
282 lines (246 loc) · 14.1 KB
/
BuildUpdateSiteStep.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/*******************************************************************************
* Copyright (c) 2006-2013
* Software Technology Group, Dresden University of Technology
* DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026
*
* 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:
* Software Technology Group - TU Dresden, Germany;
* DevBoost GmbH - Berlin, Germany
* - initial API and implementation
******************************************************************************/
package de.devboost.buildboost.genext.updatesite.steps;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import de.devboost.buildboost.BuildException;
import de.devboost.buildboost.ant.AbstractAntTargetGenerator;
import de.devboost.buildboost.ant.AntTarget;
import de.devboost.buildboost.artifacts.EclipseFeature;
import de.devboost.buildboost.artifacts.Plugin;
import de.devboost.buildboost.genext.updatesite.artifacts.EclipseUpdateSite;
import de.devboost.buildboost.genext.updatesite.artifacts.EclipseUpdateSiteDeploymentSpec;
import de.devboost.buildboost.model.IDependable;
import de.devboost.buildboost.util.XMLContent;
public class BuildUpdateSiteStep extends AbstractAntTargetGenerator {
private EclipseUpdateSiteDeploymentSpec updateSiteSpec;
private File targetDir;
private String usernameProperty = null;
private String passwordProperty = null;
public BuildUpdateSiteStep(EclipseUpdateSiteDeploymentSpec updateSiteSpec, File targetDir) {
super();
this.updateSiteSpec = updateSiteSpec;
this.targetDir = targetDir;
}
@Override
public Collection<AntTarget> generateAntTargets() throws BuildException {
if (usernameProperty == null) {
usernameProperty = updateSiteSpec.getValue("site", "usernameProperty");
}
if (passwordProperty == null) {
passwordProperty = updateSiteSpec.getValue("site", "passwordProperty");
}
AntTarget updateSiteTarget = generateUpdateSiteAntTarget();
return Collections.singletonList(updateSiteTarget);
}
protected AntTarget generateUpdateSiteAntTarget() throws BuildException {
EclipseUpdateSite updateSite = updateSiteSpec.getUpdateSite();
if (updateSite == null) {
throw new BuildException("Can't find update site for update site specification.");
}
String distDir = targetDir.getAbsolutePath() + File.separator + "dist";
XMLContent content = new XMLContent();
String updateSiteID = updateSite.getIdentifier();
File updateSiteFile = updateSite.getFile();
String updateSiteDir = distDir + File.separator + "updatesites" + File.separator + updateSiteID;
content.append("<property environment=\"env\"/>");
content.append("<!-- Get BUILD_ID from environment -->");
content.append("<condition property=\"buildid\" value=\"${env.BUILD_ID}\">");
content.append("<isset property=\"env.BUILD_ID\" />");
content.append("</condition>");
content.appendLineBreak();
content.append("<!-- fallback if env.BUILD_ID is not set -->");
content.append("<tstamp/>");
content.append("<property name=\"buildid\" value=\"${DSTAMP}${TSTAMP}\" />");
content.appendLineBreak();
content.append("<echo message=\"Copying update site descriptor for update site '" + updateSiteID + "'\"/>");
content.append("<mkdir dir=\"" + updateSiteDir + "\" />");
content.append("<mkdir dir=\"" + updateSiteDir + "/plugins\" />");
content.append("<mkdir dir=\"" + updateSiteDir + "/features\" />");
content.append("<copy file=\"" + updateSiteFile.getAbsolutePath() + "\" tofile=\"" + updateSiteDir + "/site.xml\"/>");
File associatedSitesXML = new File(updateSiteFile.getParent(), "associateSites.xml");
if (associatedSitesXML.exists()) {
content.append("<copy file=\"" + associatedSitesXML.getAbsolutePath() + "\" tofile=\"" + updateSiteDir + "/associateSites.xml\"/>");
}
content.appendLineBreak();
String updateSiteVendor = updateSiteSpec.getValue("site", "vendor");
if (updateSiteVendor == null) {
updateSiteVendor = "Unknown vendor";
}
String excludeSrc = updateSiteSpec.getValue("site", "excludeSources");
if (excludeSrc == null) {
excludeSrc = "false";
}
Collection<EclipseFeature> features = updateSite.getFeatures();
for (EclipseFeature feature : features) {
String featureID = feature.getIdentifier();
File featureFile = feature.getFile();
boolean isFeatureJAR = featureFile.isFile();
String tempDir = distDir + File.separator + "temp_features";
String tempFeatureDir = tempDir + "/" + featureID;
String featureVersion = feature.getVersion();
String featureVendor = updateSiteSpec.getFeatureVendor(featureID);
if (isFeatureJAR) {
// the feature is already packaged, we can just copy it
content.append("<copy file=\"" + featureFile.getAbsolutePath() + "\" todir=\"" + updateSiteDir + "/features\"/>");
content.append("<!-- set correct reference in site.xml -->");
content.append("<replaceregexp file=\"" + updateSiteDir + "/site.xml\" match='feature url=\"features/" + featureID + "_[0-9]*.[0-9]*.[0-9]*.v[0-9]*.jar\" id=\"" + featureID + "\" version=\"[0-9]*.[0-9]*.[0-9]*.v[0-9]*\"' replace='feature url=\"features/" + featureFile.getName() + "\" id=\"" + featureID + "\" version=\"" + featureVersion + "\"'/>");
content.appendLineBreak();
} else {
// the feature is not packaged yet, we need to create a JAR file
content.append("<echo message=\"Building feature '" + featureID + "' for update site '" + updateSiteID + "'\"/>");
content.append("<!-- update version numbers in feature.xml -->");
content.append("<!-- copy to be modified -->");
content.append("<mkdir dir=\"" + tempFeatureDir + "\" />");
content.append("<copy file=\"" + featureFile.getAbsolutePath() + "\" tofile=\"" + tempFeatureDir + "/feature.xml\"/>");
content.append("<!-- set version in copy -->");
content.append("<replace file=\"" + tempFeatureDir + "/feature.xml\" token='\"0.0.0\"' value='\"" + featureVersion + ".v${buildid}\"'/>");
content.append("<replace file=\"" + tempFeatureDir + "/feature.xml\" token='\"" + featureVersion + "\"' value='\"" + featureVersion + ".v${buildid}\"'/>");
content.append("<replace file=\"" + tempFeatureDir + "/feature.xml\" token=\".qualifier\" value=\".v${buildid}\"/>");
Collection<IDependable> dependencies = feature.getDependencies();
for (IDependable dependency : dependencies) {
if (dependency instanceof EclipseFeature) {
EclipseFeature requiredFeature = (EclipseFeature) dependency;
if (requiredFeature.isTargetPlatformFeature()) {
// for target platform features we do not set a minimum
// version
continue;
}
content.append("<replaceregexp file=\"" + tempFeatureDir + "/feature.xml\" match='<import feature=\"" + requiredFeature.getIdentifier() + "\"' replace='<import feature=\"" + requiredFeature.getIdentifier() + "\" version=\"" + requiredFeature.getVersion() + "\" match=\"greaterOrEqual\"' />");
}
}
content.append("<!-- create empty file 'feature.properties' -->");
content.append("<touch file=\"feature.properties\"/>");
content.append("<!-- create feature JAR -->");
content.append("<jar basedir=\"" + tempFeatureDir + "\" includes=\"feature.xml\" destfile=\"" + updateSiteDir + "/features/" + featureID + "_" + featureVersion + ".v${buildid}.jar\">");
content.append("<fileset dir=\".\" includes=\"feature.properties\" />");
content.append("</jar>");
content.append("<!-- delete temporary directory -->");
content.append("<delete dir=\"" + tempDir + "\"/>");
content.append("<!-- set version in site.xml -->");
content.append("<replaceregexp file=\"" + updateSiteDir + "/site.xml\" match='feature url=\"features/" + featureID + "_[0-9]*.[0-9]*.[0-9]*.v[0-9]*.jar\" id=\"" + featureID + "\" version=\"[0-9]*.[0-9]*.[0-9]*.v[0-9]*\"' replace='feature url=\"features/" + featureID + "_" + featureVersion + ".v${buildid}.jar\" id=\"" + featureID + "\" version=\"" + featureVersion + ".v${buildid}\"'/>");
content.appendLineBreak();
}
Collection<Plugin> plugins = feature.getPlugins();
for (Plugin plugin : plugins) {
addPackagePluginTasks(content, updateSiteID, updateSiteDir,
excludeSrc, featureVersion, featureVendor, plugin);
}
}
addCreateCompleteZipTask(content, updateSiteID, updateSiteDir);
String targetPath = updateSiteSpec.getValue("site", "uploadPath");
if (targetPath != null) {
addUploadTasks(content, updateSiteID, updateSiteDir, targetPath);
}
AntTarget target = new AntTarget("build-update-site-" + updateSiteID, content);
return target;
}
private void addCreateCompleteZipTask(XMLContent content,
String updateSiteID, String updateSiteDir) {
String zipFilePath = updateSiteDir + "/" + getUpdateSiteCompleteFileName(updateSiteID);
content.append("<!-- Create zipped version of update site -->");
content.append("<zip destfile=\"" + zipFilePath + "\" basedir=\"" + updateSiteDir + "\" />");
content.append("<checksum file=\"" + zipFilePath + "\"/>");
}
private void addUploadTasks(XMLContent content, String updateSiteID,
String updateSiteDir, String targetPath) {
// TODO this requires that jsch-0.1.48.jar is in ANTs classpath. we
// should figure out a way to provide this JAR together with BuildBoost.
content.append("<!-- Copy new version of update site to server -->");
content.append("<scp todir=\"${env." + usernameProperty + "}:${env." + passwordProperty + "}@" + targetPath + "\" port=\"22\" sftp=\"true\" trust=\"true\">");
content.append("<fileset dir=\"" + updateSiteDir + "\">");
content.append("<include name=\"features/**\"/>");
content.append("<include name=\"plugins/**\"/>");
content.append("<include name=\"associateSites.xml\"/>");
content.append("<include name=\"digest.zip\"/>");
content.append("<include name=\"COPYING\"/>");
content.append("</fileset>");
content.append("</scp>");
content.appendLineBreak();
content.append("<!-- We copy the site.xml, artifacts.jar and content.jar separately to make sure these");
content.append("are the last files that are replaced. Otherwise the files might point to JARs that ");
content.append("have not been uploaded yet. -->");
content.append("<scp todir=\"${env." + usernameProperty + "}:${env." + passwordProperty + "}@" + targetPath + "\" port=\"22\" sftp=\"true\" trust=\"true\">");
content.append("<fileset dir=\"" + updateSiteDir + "\">");
content.append("<include name=\"artifacts.jar\"/>");
content.append("<include name=\"content.jar\"/>");
content.append("<include name=\"site.xml\"/>");
content.append("</fileset>");
content.append("</scp>");
content.appendLineBreak();
content.append("<!-- Copy zipped version of update site to server (used by downstream builds) -->");
content.append("<scp todir=\"${env." + usernameProperty + "}:${env." + passwordProperty + "}@" + targetPath + "\" port=\"22\" sftp=\"true\" trust=\"true\">");
content.append("<fileset dir=\"" + updateSiteDir + "\">");
content.append("<include name=\"" + getUpdateSiteCompleteFileName(updateSiteID) + "\"/>");
content.append("<include name=\"" + getUpdateSiteCompleteFileName(updateSiteID) + ".MD5\"/>");
content.append("</fileset>");
content.append("</scp>");
content.appendLineBreak();
}
private String getUpdateSiteCompleteFileName(String updateSiteID) {
return updateSiteID + "-complete.zip";
}
private void addPackagePluginTasks(XMLContent content, String updateSiteID,
String updateSiteDir, String excludeSrc, String featureVersion,
String featureVendor, Plugin plugin) {
String pluginID = plugin.getIdentifier();
File pluginDirectory = plugin.getFile();
String pluginPath = pluginDirectory.getAbsolutePath();
String pluginVersion = updateSiteSpec.getValue("plugin", pluginID, "version");
if (pluginVersion == null) {
pluginVersion = featureVersion;
}
String pluginVendor = updateSiteSpec.getValue("plugin", pluginID, "vendor");
if (pluginVendor == null) {
pluginVendor = featureVendor;
}
String pluginName = updateSiteSpec.getValue("plugin", pluginID, "name");
addManifestTask(content, updateSiteID, pluginID, pluginPath,
pluginVersion, pluginVendor, pluginName);
content.append("<jar destfile=\"" + updateSiteDir + "/plugins/" + pluginID + "_" + pluginVersion + ".v${buildid}.jar\" manifest=\"" + pluginPath + "/META-INF/MANIFEST.MF\">");
content.append("<fileset dir=\"" + pluginPath + "\">");
// TODO make this configurable or read the build.properties file for this
content.append("<exclude name=\"**/.*/**\"/>");
if (Boolean.parseBoolean(excludeSrc)) {
content.append("<exclude name=\"**/src*/**\"/>");
}
content.append("</fileset>");
content.append("</jar>");
content.appendLineBreak();
}
private void addManifestTask(XMLContent content, String updateSiteID,
String pluginID, String pluginPath, String pluginVersion,
String pluginVendor, String pluginName) {
// package plugin(s)
content.append("<echo message=\"Packaging plug-in '" + pluginID + "' for update site '" + updateSiteID + "'\"/>");
content.append("<manifest file=\"" + pluginPath + "/META-INF/MANIFEST.MF\" mode=\"update\">");
content.append("<attribute name=\"Bundle-Version\" value=\"" + pluginVersion + ".v${buildid}\"/>");
// only replace vendor if one is specified in the update site
// specification
if (pluginVendor != null) {
content.append("<attribute name=\"Bundle-Vendor\" value=\"" + pluginVendor + "\"/>");
}
content.append("<attribute name=\"Bundle-SymbolicName\" value=\"" + pluginID + "; singleton:=true\"/>");
// only replace plug-in name if one is specified in the update
// site specification
if (pluginName != null) {
content.append("<attribute name=\"Bundle-Name\" value=\"" + pluginName + "\"/>");
}
content.append("</manifest>");
content.appendLineBreak();
}
}