##### Coverage Report - org.jbehave.core.io.JarFileScanner

Classes in this File | Line Coverage | Branch Coverage | Complexity
JarFileScanner |
95% | 39/41
100% | 24/24
| 3.0;3
JarFileScanner$1 |
100% | 3/3
100% | 2/2
| 3.0;3

1 |  |
     package org.jbehave.core.io;
2 |  |
3 |  |
     import java.io.File;
4 |  |
     import java.io.IOException;
5 |  |
     import java.net.URL;
6 |  |
     import java.util.ArrayList;
7 |  |
     import java.util.Arrays;
8 |  |
     import java.util.Enumeration;
9 |  |
     import java.util.List;
10 |  |
     import java.util.jar.JarEntry;
11 |  |
     import java.util.jar.JarFile;
12 |  |
13 |  |
     import org.apache.commons.collections.CollectionUtils;
14 |  |
     import org.apache.commons.collections.Transformer;
15 |  |
     import org.codehaus.plexus.util.SelectorUtils;
16 |  |
17 |  |
     import static java.util.Arrays.asList;
18 |  |
     import static org.apache.commons.lang.StringUtils.isBlank;
19 |  |
20 |  |
     /**
21 |  |
      * Find all matching file entries in a jar.
22 |  |
      */
23 |  |
     public class JarFileScanner {
24 |  |
25 |  |
         private URL jarURL;
26 |  |
         private List<String> includes;
27 |  |
         private List<String> excludes;
28 |  |
29 |  |
         public JarFileScanner(String jarPath, String includes, String excludes) {
30 | 6 |
             this(jarPath, asList(includes), asList(excludes));
31 | 6 |
         }
32 |  |
33 |  |
         public JarFileScanner(String jarPath, List<String> includes, List<String> excludes) {
34 | 9 |
             this(CodeLocations.codeLocationFromPath(jarPath), includes, excludes);
35 | 9 |
         }
36 |  |
37 |  |
         public JarFileScanner(URL jarURL, String includes, String excludes) {
38 | 0 |
             this(jarURL, asList(includes), asList(excludes));
39 | 0 |
         }
40 |  |
41 | 9 |
         public JarFileScanner(URL jarURL, List<String> includes, List<String> excludes) {
42 | 9 |
             this.jarURL = jarURL;
43 | 9 |
             this.includes = ( includes != null ? toLocalPath(includes) : Arrays.<String>asList() );
44 | 9 |
             this.excludes = ( excludes != null ? toLocalPath(excludes) : Arrays.<String>asList() );
45 | 9 |
         }
46 |  |
47 |  |
         /**
48 |  |
          * Scans the jar file and returns the paths that match the includes and excludes.
49 |  |
          *
50 |  |
          * @return A List of paths
51 |  |
          * @throws An IllegalStateException when an I/O error occurs in reading the jar file.
52 |  |
          */
53 |  |
         public List<String> scan() {
54 |  |
             try {
55 | 9 |
                 JarFile jar = new JarFile(jarURL.getFile());
56 |  |
                 try {
57 | 8 |
                     List<String> result = new ArrayList<String>();
58 | 8 |
                     Enumeration<JarEntry> en = jar.entries();
59 | 40 |
                     while (en.hasMoreElements()) {
60 | 32 |
                         JarEntry entry = en.nextElement();
61 | 32 |
                         String path = entry.getName();
62 | 32 |
                         boolean match = includes.size() == 0;
63 | 32 |
                         if (!match) {
64 | 28 |
                             for (String pattern : includes) {
65 | 28 |
                                 if ( patternMatches(pattern, path)) {
66 | 15 |
                                     match = true;
67 | 15 |
                                     break;
68 |  |
                                 }
69 |  |
                             }
70 |  |
                         }
71 | 32 |
                         if (match) {
72 | 19 |
                             for (String pattern : excludes) {
73 | 15 |
                                 if ( patternMatches(pattern, path)) {
74 | 3 |
                                     match = false;
75 | 3 |
                                     break;
76 |  |
                                 }
77 |  |
                             }
78 |  |
                         }
79 | 32 |
                         if (match) {
80 | 16 |
                             result.add(path);
81 |  |
                         }
82 | 32 |
                     }
83 | 8 |
                     return result;
84 |  |
                 } finally {
85 | 8 |
                     jar.close();
86 |  |
                 }
87 | 1 |
             } catch (IOException e) {
88 | 1 |
                 throw new IllegalStateException(e);
89 |  |
             }
90 |  |
         }
91 |  |
92 |  |
         private List<String> toLocalPath(List<String> patternList) {
93 | 16 |
             List<String> transformed = new ArrayList<String>(patternList);
94 | 16 |
             CollectionUtils.transform(transformed, new Transformer() {
95 |  |
                 public Object transform(Object input) {
96 | 16 |
                     String pattern=(String)input;
97 | 16 |
                     return pattern!=null ? pattern.replace('/', File.separatorChar) : null;
98 |  |
                 }
99 |  |
             });
100 | 16 |
             return transformed;
101 |  |
         }
102 |  |
103 |  |
         private boolean patternMatches(String pattern, String path) {
104 | 43 |
             if ( isBlank(pattern) ) return false;
105 |  |
             // SelectorUtils assumes local path separator for path and pattern
106 | 29 |
             String localPath = path.replace('/', File.separatorChar);
107 | 29 |
             return SelectorUtils.matchPath(pattern, localPath);
108 |  |
         }
109 |  |
110 |  |
     }