5050import java .util .logging .Logger ;
5151import edu .umd .cs .findbugs .annotations .CheckForNull ;
5252import edu .umd .cs .findbugs .annotations .NonNull ;
53+ import java .util .jar .JarFile ;
54+ import java .util .regex .Matcher ;
5355import java .util .regex .Pattern ;
5456import org .apache .commons .io .IOUtils ;
5557import org .jenkinsci .plugins .workflow .cps .CpsFlowExecution ;
9799 if (action != null ) {
98100 // Resuming a build, so just look up what we loaded before.
99101 for (LibraryRecord record : action .getLibraries ()) {
102+ // TODO call LibraryRetriever.dir2Jar as needed
100103 FilePath libDir = new FilePath (execution .getOwner ().getRootDir ()).child ("libs/" + record .getDirectoryName ());
101104 for (String root : new String [] {"src" , "vars" }) {
102105 FilePath dir = libDir .child (root );
147150 // Now actually try to retrieve the libraries.
148151 for (LibraryRecord record : librariesAdded .values ()) {
149152 listener .getLogger ().println ("Loading library " + record .name + "@" + record .version );
150- for (URL u : retrieve (record , retrievers .get (record .name ), listener , build , execution )) {
151- additions .add (new Addition (u , record .trusted ));
152- }
153+ additions .add (new Addition (retrieve (record , retrievers .get (record .name ), listener , build , execution ), record .trusted ));
153154 }
154155 return additions ;
155156 }
@@ -169,14 +170,14 @@ private enum CacheStatus {
169170 EXPIRED ;
170171 }
171172
172- private static CacheStatus getCacheStatus (@ NonNull LibraryCachingConfiguration cachingConfiguration , @ NonNull final FilePath versionCacheDir )
173+ private static CacheStatus getCacheStatus (@ NonNull LibraryCachingConfiguration cachingConfiguration , @ NonNull final FilePath versionCacheJar )
173174 throws IOException , InterruptedException
174175 {
175176 if (cachingConfiguration .isRefreshEnabled ()) {
176177 final long cachingMilliseconds = cachingConfiguration .getRefreshTimeMilliseconds ();
177178
178- if (versionCacheDir .exists ()) {
179- if ((versionCacheDir .lastModified () + cachingMilliseconds ) > System .currentTimeMillis ()) {
179+ if (versionCacheJar .exists ()) {
180+ if ((versionCacheJar .lastModified () + cachingMilliseconds ) > System .currentTimeMillis ()) {
180181 return CacheStatus .VALID ;
181182 } else {
182183 return CacheStatus .EXPIRED ;
@@ -185,7 +186,7 @@ private static CacheStatus getCacheStatus(@NonNull LibraryCachingConfiguration c
185186 return CacheStatus .DOES_NOT_EXIST ;
186187 }
187188 } else {
188- if (versionCacheDir .exists ()) {
189+ if (versionCacheJar .exists ()) {
189190 return CacheStatus .VALID ;
190191 } else {
191192 return CacheStatus .DOES_NOT_EXIST ;
@@ -194,16 +195,16 @@ private static CacheStatus getCacheStatus(@NonNull LibraryCachingConfiguration c
194195 }
195196
196197 /** Retrieve library files. */
197- static List < URL > retrieve (@ NonNull LibraryRecord record , @ NonNull LibraryRetriever retriever , @ NonNull TaskListener listener , @ NonNull Run <?,?> run , @ NonNull CpsFlowExecution execution ) throws Exception {
198+ static URL retrieve (@ NonNull LibraryRecord record , @ NonNull LibraryRetriever retriever , @ NonNull TaskListener listener , @ NonNull Run <?,?> run , @ NonNull CpsFlowExecution execution ) throws Exception {
198199 String name = record .name ;
199200 String version = record .version ;
200201 boolean changelog = record .changelog ;
201202 LibraryCachingConfiguration cachingConfiguration = record .cachingConfiguration ;
202- FilePath libDir = new FilePath (execution .getOwner ().getRootDir ()).child ("libs/" + record .getDirectoryName ());
203+ FilePath libJar = new FilePath (execution .getOwner ().getRootDir ()).child ("libs/" + record .getDirectoryName () + ".jar" );
203204 Boolean shouldCache = cachingConfiguration != null ;
204- final FilePath versionCacheDir = new FilePath (LibraryCachingConfiguration .getGlobalLibrariesCacheDir (), record .getDirectoryName ());
205+ final FilePath versionCacheJar = new FilePath (LibraryCachingConfiguration .getGlobalLibrariesCacheDir (), record .getDirectoryName () + ".jar" );
205206 ReentrantReadWriteLock retrieveLock = getReadWriteLockFor (record .getDirectoryName ());
206- final FilePath lastReadFile = new FilePath ( versionCacheDir , LibraryCachingConfiguration .LAST_READ_FILE );
207+ final FilePath lastReadFile = versionCacheJar . sibling ( record . getDirectoryName () + "." + LibraryCachingConfiguration .LAST_READ_FILE );
207208
208209 if (shouldCache && cachingConfiguration .isExcluded (version )) {
209210 listener .getLogger ().println ("Library " + name + "@" + version + " is excluded from caching." );
@@ -213,13 +214,13 @@ static List<URL> retrieve(@NonNull LibraryRecord record, @NonNull LibraryRetriev
213214 if (shouldCache ) {
214215 retrieveLock .readLock ().lockInterruptibly ();
215216 try {
216- CacheStatus cacheStatus = getCacheStatus (cachingConfiguration , versionCacheDir );
217+ CacheStatus cacheStatus = getCacheStatus (cachingConfiguration , versionCacheJar );
217218 if (cacheStatus == CacheStatus .DOES_NOT_EXIST || cacheStatus == CacheStatus .EXPIRED ) {
218219 retrieveLock .readLock ().unlock ();
219220 retrieveLock .writeLock ().lockInterruptibly ();
220221 try {
221222 boolean retrieve = false ;
222- switch (getCacheStatus (cachingConfiguration , versionCacheDir )) {
223+ switch (getCacheStatus (cachingConfiguration , versionCacheJar )) {
223224 case VALID :
224225 listener .getLogger ().println ("Library " + name + "@" + version + " is cached. Copying from home." );
225226 break ;
@@ -229,18 +230,17 @@ static List<URL> retrieve(@NonNull LibraryRecord record, @NonNull LibraryRetriev
229230 case EXPIRED :
230231 long cachingMinutes = cachingConfiguration .getRefreshTimeMinutes ();
231232 listener .getLogger ().println ("Library " + name + "@" + version + " is due for a refresh after " + cachingMinutes + " minutes, clearing." );
232- if (versionCacheDir .exists ()) {
233- versionCacheDir . deleteRecursive ();
234- versionCacheDir . withSuffix ( "-name.txt" ).delete ();
233+ if (versionCacheJar .exists ()) {
234+ versionCacheJar . delete ();
235+ versionCacheJar . sibling ( record . getDirectoryName () + "-name.txt" ).delete ();
235236 }
236237 retrieve = true ;
237238 break ;
238239 }
239240
240241 if (retrieve ) {
241242 listener .getLogger ().println ("Caching library " + name + "@" + version );
242- versionCacheDir .mkdirs ();
243- retriever .retrieve (name , version , changelog , versionCacheDir , run , listener );
243+ retriever .retrieveJar (name , version , changelog , versionCacheJar , run , listener );
244244 }
245245 retrieveLock .readLock ().lock ();
246246 } finally {
@@ -251,50 +251,44 @@ static List<URL> retrieve(@NonNull LibraryRecord record, @NonNull LibraryRetriev
251251 }
252252
253253 lastReadFile .touch (System .currentTimeMillis ());
254- versionCacheDir . withSuffix ( "-name.txt" ).write (name , "UTF-8" );
255- versionCacheDir . copyRecursiveTo ( libDir );
254+ versionCacheJar . sibling ( record . getDirectoryName () + "-name.txt" ).write (name , "UTF-8" );
255+ versionCacheJar . copyTo ( libJar );
256256 } finally {
257257 retrieveLock .readLock ().unlock ();
258258 }
259259 } else {
260- retriever .retrieve (name , version , changelog , libDir , run , listener );
260+ retriever .retrieveJar (name , version , changelog , libJar , run , listener );
261261 }
262262 // Write the user-provided name to a file as a debugging aid.
263- libDir . withSuffix ( "-name.txt" ).write (name , "UTF-8" );
263+ libJar . sibling ( record . getDirectoryName () + "-name.txt" ).write (name , "UTF-8" );
264264
265265 // Replace any classes requested for replay:
266266 if (!record .trusted ) {
267267 for (String clazz : ReplayAction .replacementsIn (execution )) {
268- for (String root : new String [] {"src" , "vars" }) {
269- String rel = root + "/" + clazz .replace ('.' , '/' ) + ".groovy" ;
270- FilePath f = libDir .child (rel );
271- if (f .exists ()) {
272- String replacement = ReplayAction .replace (execution , clazz );
273- if (replacement != null ) {
274- listener .getLogger ().println ("Replacing contents of " + rel );
275- f .write (replacement , null ); // TODO as below, unsure of encoding used by Groovy compiler
276- }
268+ String rel = clazz .replace ('.' , '/' ) + ".groovy" ;
269+ /* TODO need to unpack & repack I guess
270+ FilePath f = libDir.child(rel);
271+ if (f.exists()) {
272+ String replacement = ReplayAction.replace(execution, clazz);
273+ if (replacement != null) {
274+ listener.getLogger().println("Replacing contents of " + rel);
275+ f.write(replacement, null); // TODO as below, unsure of encoding used by Groovy compiler
277276 }
278277 }
278+ */
279279 }
280280 }
281- List <URL > urls = new ArrayList <>();
282- FilePath srcDir = libDir .child ("src" );
283- if (srcDir .isDirectory ()) {
284- urls .add (srcDir .toURI ().toURL ());
285- }
286- FilePath varsDir = libDir .child ("vars" );
287- if (varsDir .isDirectory ()) {
288- urls .add (varsDir .toURI ().toURL ());
289- for (FilePath var : varsDir .list ("*.groovy" )) {
290- record .variables .add (var .getBaseName ());
291- }
292- }
293- if (urls .isEmpty ()) {
294- throw new AbortException ("Library " + name + " expected to contain at least one of src or vars directories" );
281+ try (JarFile jf = new JarFile (libJar .getRemote ())) {
282+ jf .stream ().forEach (entry -> {
283+ Matcher m = ROOT_GROOVY_SOURCE .matcher (entry .getName ());
284+ if (m .matches ()) {
285+ record .variables .add (m .group (1 ));
286+ }
287+ });
295288 }
296- return urls ;
289+ return libJar . toURI (). toURL () ;
297290 }
291+ private static final Pattern ROOT_GROOVY_SOURCE = Pattern .compile ("([^/]+)[.]groovy" );
298292
299293 /**
300294 * Loads resources for {@link ResourceStep}.
@@ -309,6 +303,7 @@ static List<URL> retrieve(@NonNull LibraryRecord record, @NonNull LibraryRetriev
309303 Run <?,?> run = (Run ) executable ;
310304 LibrariesAction action = run .getAction (LibrariesAction .class );
311305 if (action != null ) {
306+ // TODO handle *.jar
312307 FilePath libs = new FilePath (run .getRootDir ()).child ("libs" );
313308 for (LibraryRecord library : action .getLibraries ()) {
314309 FilePath libResources = libs .child (library .getDirectoryName () + "/resources/" );
@@ -347,6 +342,7 @@ private static String readResource(FilePath file, @CheckForNull String encoding)
347342 List <GlobalVariable > vars = new ArrayList <>();
348343 for (LibraryRecord library : action .getLibraries ()) {
349344 for (String variable : library .variables ) {
345+ // TODO pass URL of *.jar!/$variable.txt
350346 vars .add (new UserDefinedGlobalVariable (variable , new File (run .getRootDir (), "libs/" + library .getDirectoryName () + "/vars/" + variable + ".txt" )));
351347 }
352348 }
@@ -367,6 +363,7 @@ private static String readResource(FilePath file, @CheckForNull String encoding)
367363 Run <?,?> run = (Run ) executable ;
368364 LibrariesAction action = run .getAction (LibrariesAction .class );
369365 if (action != null ) {
366+ // TODO handle *.jar
370367 FilePath libs = new FilePath (run .getRootDir ()).child ("libs" );
371368 for (LibraryRecord library : action .getLibraries ()) {
372369 if (library .trusted ) {
0 commit comments