forked from tada/pljava
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.xml
More file actions
387 lines (364 loc) · 14.6 KB
/
Copy pathbuild.xml
File metadata and controls
387 lines (364 loc) · 14.6 KB
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
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
<?xml version="1.0"?>
<project name="project" default="init" basedir=".">
<target name="init">
<fileset dir="../pljava-so/target/nar" id="narloc">
<include name="**/history.xml"/>
</fileset>
<pathconvert property="narpath" refid="narloc" dirsep="/"/>
<loadresource property="naraol">
<string value="${narpath}" />
<filterchain>
<tokenfilter>
<!--containsregex pattern=".*SNAPSHOT-(.*)-shared.*$" replace="\1" /-->
<containsregex pattern=".*/lib/(.*)/plugin/.*$" replace="\1" />
</tokenfilter>
<striplinebreaks/>
</filterchain>
</loadresource>
<loadproperties srcFile="../pljava-so/target/pgsql.properties"/>
<property name="suffix" value="${PGSQL_VER_CLASSIFIER}-${naraol}"/>
</target>
<target name="package" depends="init">
<!--
Create a new ant task <jarxbuild> for building a jar that self-
extracts by including org/gjt/cuspy/JarX.class. <jarxbuild> takes
one attribute, destfile= (which should be absolute, consider
specifying ${basedir} at the front). To specify what goes IN the
jar, supply nested zipfileset elements; that class was chosen
because it already supports prefix=, fullpath=, and filemode=
attributes to control the stored path and permission info, as well
as all the scanning/inclusion/exclusion rules you could want. But by
itself, it isn't enough to tell JarX which files are binary or text,
or the encodings of the text files. That is conveyed by which alias
is used for each zipfileset. That is, you don't literally use
nested <zipfileset> elements, but instead <binary>, <ascii>, or
<utf8> elements, which all are zipfilesets behind the scenes and
have all the same attributes and elements. Any files supplied in
a <binary> element will be archived and unarchived unchanged.
Files supplied in an <ascii> or <utf8> element will be treated as
text and have their line endings converted to local conventions on
extraction; they won't be transcoded, but will be stored in and
extracted from the jar in the specified encoding (and verified to
be well-formed in it). That obviously isn't a fully-general way to
specify the text handling, but it gets the job done, and if you have
another case to handle, just add another zipfileset <element> with
another name, and edit the javascript below to know what to do
with it.
To emphasize, files given in an <ascii> or <utf8> element are
extracted in exactly that encoding on any target platform regardless
of the platform's default encoding. That's appropriate for an
extension .control file (which must be <ascii> because PostgreSQL
assumes it), and any extension .sql scripts we supply (which must
be <utf8> because the .control file says so). It's possible that
for some other text files we might include (general docs or
what not), it would be nicer to let them be extracted into the
platform's default encoding (achieved by specifying a fixed value
such as UTF-8 for _JarX_CharsetInArchive while entirely omitting
_JarX_CharsetWhenUnpacked). But at the moment no such files are
being included, so I haven't provided another element name to give
that behavior.
There has to be a <binary> element supplying JarX.class itself.
The <jarxbuild> task also accepts nested text, which will be treated
as a path-resolver script (the language is assumed to be
application/javascript; I'm lazy). It will be stuffed into the
manifest in a form that survives manifest line-wrapping, and JarX
will use it at extraction time to rewrite pathnames. In this case,
that script (see further below) will use pg_config or system
properties to determine the extraction paths.
-->
<scriptdef name='jarxbuild' language='javascript'>
<attribute name='destfile'/>
<element type='zipfileset' name='binary'/>
<element type='zipfileset' name='ascii'/>
<element type='zipfileset' name='utf8'/>
<classpath>
<pathelement path='${classpath}'/>
<pathelement location='target/classes'/> <!-- JarX is there -->
</classpath>
<![CDATA[
var manifest = new java.util.jar.Manifest();
var sections = manifest.getEntries();
var mainsect = manifest.getMainAttributes();
mainsect.putValue('Manifest-Version', '1.0');
mainsect.putValue('Created-By', project.getProperty('project.name') + ' ' +
project.getProperty('project.version'));
mainsect.putValue('Main-Class', 'org.gjt.cuspy.JarX');
/* Declare default permissions for entries that don't have their own.
*/
mainsect.putValue('_JarX_Permissions', 'read=all,write=none,execute=none');
/* Declare a function pathxfrm(p) if needed to convert from this platform's
file separator to the / used in the jar (just an identity function
if they are the same). The overcomplicated look is mostly to avoid using
replace(), which is a method (with different behavior) on both Java and
JavaScript strings, and Rhino and Nashorn have different rules about which
one you get.
*/
var filesep = project.getProperty('file.separator');
if ( filesep == '/' ) {
function pathxfrm(p) {
return p;
}
} else {
var fseprx = java.util.regex.Pattern.quote(filesep);
function pathxfrm(p) {
return p.replaceAll(fseprx, '/');
}
}
/* Munge a name (obtained directly from a resource in a fileset) according to
the prefix or fullpath given for the fileset itself.
*/
function munge(rsrc, fileset) {
var fullpath = fileset.getFullpath(project);
var prefix = fileset.getPrefix(project);
var n = pathxfrm(rsrc.getName());
/*
* The fullpath or prefix parts do not need to be pathxfrm()d; they are
* defined here in build.xml with / as the separator already.
*/
if ( !(null === fullpath || '' == fullpath) )
n = fullpath;
else if ( !(null === prefix) )
n = prefix + n;
return n;
}
/* Given one fileset, compute a set of manifest per-entry attributes from the
specified charset (caller supplied according to the alias name that was used
for the fileset) and file mode specified on the fileset, if any, then enter
a manifest section with those attributes for every resource name in the
fileset. Caller supplies charset === null for a fileset to be treated as
binary.
*/
function mksections(charset, fileset) {
var atts = new java.util.jar.Attributes();
if ( !(null === charset) ) {
atts.putValue('Content-Type', 'text/plain');
atts.putValue('_JarX_CharsetInArchive', charset);
atts.putValue('_JarX_CharsetWhenUnpacked', charset);
}
if ( fileset.hasFileModeBeenSet() ) {
var m = fileset.getFileMode(project) - 32768; /* don't ask me why */
if ( 0444 == m )
atts.putValue('_JarX_Permissions',
'read=all,write=none,execute=none');
else if ( 0555 == m )
atts.putValue('_JarX_Permissions',
'read=all,write=none,execute=all');
else
self.fail('File mode '+m+' not covered in script.');
}
var it = fileset.iterator();
while ( it.hasNext() ) {
var rsrc = it.next();
sections.put(munge(rsrc, fileset), atts);
}
}
/* Given a fileset and JarOutputStream, for each resource look up the manifest
per-entry section earlier created, pass that to builder.classify() to set
how shovel() will handle the contents, then make the next jar entry and
shovel the resource contents in.
*/
function storeset(fileset, jos) {
var it = fileset.iterator();
while ( it.hasNext() ) {
var rsrc = it.next();
var n = munge(rsrc, fileset);
var atts = sections.get(n);
builder.classify(atts, true);
var je = new java.util.jar.JarEntry(n);
jos.putNextEntry(je);
var instream = rsrc.getInputStream();
print(n+' ');
builder.shovel(instream, jos);
jos.closeEntry();
}
}
/* If there is text nested in the <jarxbuild> element, it is a path-resolver
script. Munge it to the manifest-attribute-linewrap-resistant style JarX
expects (first \-escape every \ and " then turn every line ending to the
three characters "/" then add " at start and end), and place into the main
manifest section as _JarX_PathResolver, with the language tag
application/javascript (hardcoded here, you weren't thinking of using
a different script language anyway).
*/
var pathresolver = self.text.trim();
if ( !(null === pathresolver || '' == pathresolver) ) {
pathresolver = new String(pathresolver).replace(/["\\]/g, "\\$&");
pathresolver = pathresolver.replace(/\r\n?|\n/g, '"/"');
pathresolver = '"' + pathresolver + '"';
mainsect.putValue('_JarX_PathResolver',
'application/javascript' + pathresolver);
}
/* For each element name that can be used to supply a zipfileset, get all the
zipfilesets supplied under that name and pass them to mksections with the
appropriate charset parameter according to the element name.
*/
var binary = elements.get("binary");
for ( i = 0; i < binary.size(); ++i ) {
var fset = binary.get(i);
mksections(null, fset);
}
var ascii = elements.get("ascii");
for ( i = 0; i < ascii.size(); ++i ) {
var fset = ascii.get(i);
mksections('US-ASCII', fset);
}
var utf = elements.get("utf8");
for ( i = 0; i < utf.size(); ++i ) {
var fset = utf.get(i);
mksections('UTF-8', fset);
}
/* Set up the output archive...
*/
var builder = new org.gjt.cuspy.JarX.Build();
builder.setDefaults(mainsect);
var destf = attributes.get('destfile');
var fos = new java.io.FileOutputStream(destf);
var jos = new java.util.jar.JarOutputStream(fos, manifest);
/* Go through the supplied filesets once again, passing them to storeset...
*/
for ( i = 0; i < binary.size(); ++i ) {
var fset = binary.get(i);
storeset(fset, jos);
}
for ( i = 0; i < ascii.size(); ++i ) {
var fset = ascii.get(i);
storeset(fset, jos);
}
for ( i = 0; i < utf.size(); ++i ) {
var fset = utf.get(i);
storeset(fset, jos);
}
/* And finalize the output.
*/
jos.close();
]]>
</scriptdef>
<!-- Now build the jar using the <jarxbuild> task just created. -->
<jarxbuild destfile="${basedir}/target/pljava-${suffix}.jar">
<binary dir="target/classes" includes="**/JarX.class"/>
<binary prefix="pljava/pkglibdir/" filemode="555" dir=
"../pljava-so/target/nar/pljava-so-${project.version}-${naraol}-plugin/lib/${naraol}/plugin"
includes="**/*pljava-so*"/>
<binary dir="../pljava/target" includes="pljava*.jar"
prefix="pljava/sharedir/pljava/"/>
<binary dir="../pljava-api/target" includes="pljava-api*.jar"
prefix="pljava/sharedir/pljava/"/>
<binary dir="../pljava-examples/target"
includes="pljava-examples*.jar"
prefix="pljava/sharedir/pljava/"/>
<ascii dir="target/classes" includes="pljava.control"
prefix="pljava/sharedir/extension/"/>
<utf8 dir="target/classes" includes="pljava.sql"
fullpath="pljava/sharedir/pljava/pljava--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--unpackaged.sql"
fullpath=
"pljava/sharedir/pljava/pljava--unpackaged--${project.version}.sql"
/>
<!-- For any past version that has been released from which a
simple update is possible, just repeat the next entry, with
the from-version changed.
-->
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.5--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.4--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.3--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.2--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.1--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.1-BETA3--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.1-BETA2--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.1-BETA1--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.0--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.0-BETA3--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.0-BETA2--${project.version}.sql"
/>
<utf8 dir="target/classes" includes="pljava--.sql"
fullpath=
"pljava/sharedir/pljava/pljava--1.5.0-BETA1--${project.version}.sql"
/>
<utf8 dir="target/classes" prefix="pljava/sharedir/pljava/"
includes="*.sql"
excludes="pljava.sql pljava--.sql pljava--unpackaged.sql"/>
<!-- If editing the script below, expand tabs to spaces (at 4 columns, and only
for the lines of the script) before saving. Line-wrapped into the manifest,
it looks horrible with tabs.
-->
<![CDATA[
/*
At extraction time, JarX invokes this for each entry, with these bindings:
properties - the Java system properties object
storedPath - the full path of the archive member as stored
in the archive
platformPath - the name after changing only file.separator
for the platform (if different from /)
computedPath - initially the same as platformPath
If the script updates computedPath, that is where the member
will be extracted.
*/
var re = new RegExp('^pljava/([^/]+dir)(?![^/])');
var found = re.exec(storedPath);
if (found) {
var prefix = found[0];
var key = found[1];
var propkey = 'pgconfig.' + key;
var replacement = properties.getProperty(propkey);
if ( null === replacement ) {
var pgc = properties.getProperty('pgconfig');
if ( null === pgc )
pgc = 'pg_config';
var pb = new java.lang.ProcessBuilder(pgc, '--'+key);
pb.redirectErrorStream(true);
var proc = pb.start();
var instream = proc.getInputStream();
var scanner =
new java.util.Scanner(instream).useDelimiter('\\A');
var output = scanner.next();
var status = proc.waitFor();
if ( 0 != status ) {
java.lang.System.err.println(
'ERROR: pg_config status is '+status+':\n'+output);
java.lang.System.exit(1);
}
replacement = output.trim();
properties.setProperty(propkey, replacement);
}
var fsep = properties.getProperty('file.separator');
var plen = fsep.length() - 1; /* original separator had length 1 */
plen += prefix.length;
computedPath = String(replacement + computedPath.slice(plen));
}
]]>
</jarxbuild>
</target>
</project>