2626import java .util .Arrays ;
2727import java .util .LinkedHashSet ;
2828import java .util .List ;
29+ import java .util .Locale ;
2930import java .util .Optional ;
3031import java .util .Set ;
3132import java .util .StringTokenizer ;
@@ -37,6 +38,7 @@ public class Analyzer {
3738 private static final Logger logger = LoggingUtil .getLogger (Analyzer .class );
3839
3940 private final File [] archives ;
41+ private final List <File > additionalLibraries ;
4042 private final File outputDir ;
4143 private final TableBuilderConfiguration config ;
4244 private final ApplicationProcessor ap ;
@@ -59,13 +61,27 @@ public Analyzer(File[] archives, File outputDir) {
5961 }
6062
6163 public Analyzer (File [] archives , File outputDir , TableBuilderConfiguration config ) {
64+ this (archives , outputDir , config , null );
65+ }
66+
67+ public Analyzer (File [] archives , File outputDir , File [] additionalLibs ) {
68+ this (archives , outputDir , TableBuilderConfiguration .ALL , additionalLibs );
69+ }
70+
71+ public Analyzer (File [] archives , File outputDir , TableBuilderConfiguration config , File [] additionalLibs ) {
6272 if (archives == null || Arrays .stream (archives ).anyMatch (x -> x == null ) || outputDir == null ) {
6373 throw new NullPointerException ();
6474 }
6575 this .archives = archives ;
6676 this .outputDir = outputDir ;
6777 this .config = (config != null ) ? config : TableBuilderConfiguration .NONE ;
6878 this .ap = new TableBuilder (outputDir , config );
79+ this .additionalLibraries = new ArrayList <File >();
80+
81+ if (additionalLibs != null ) {
82+ addExtraLibraries (additionalLibs );
83+ }
84+
6985 }
7086
7187 public Analyzer setPackageRestrictions (Set <String > packages , boolean isPackageIncludeList ) {
@@ -95,6 +111,37 @@ public Analyzer setCallGraphBuilder(CallGraphBuilderType type) throws IOExceptio
95111 ap .setCallGraphBuilder (type != null ? new CallGraphBuilder (type ) : null );
96112 return this ;
97113 }
114+
115+ public void addExtraLibrary (File extraLib ) {
116+ if (extraLib != null ) {
117+ final String name = extraLib .getName ().toLowerCase (Locale .ENGLISH );
118+ final BinaryType bt = BinaryType .getBinaryType (name );
119+ if (bt == BinaryType .JAR ) {
120+ this .additionalLibraries .add (extraLib );
121+ }
122+ else {
123+ logger .finest (() -> formatMessage ("CallGraphFileIsNotJAR" , extraLib .getAbsolutePath ()));
124+ }
125+ }
126+ }
127+
128+ public void addExtraLibraries (File [] extraLibs ) {
129+ // Add extra user provided JARS to scope (i.e., JEE libraries)
130+ if (extraLibs != null ) {
131+ for (File extraLib : extraLibs ) {
132+ // if is a directory, try to add any JAR inside the path as an extra library
133+ if (extraLib .isDirectory ()) {
134+ File [] listOfExtraLibs = extraLib .listFiles ();
135+ for (File e : listOfExtraLibs ) {
136+ addExtraLibrary (e );
137+ }
138+ }
139+ else {
140+ addExtraLibrary (extraLib );
141+ }
142+ }
143+ }
144+ }
98145
99146 public void run () throws IOException {
100147 try {
@@ -118,6 +165,11 @@ public void run() throws IOException {
118165 logger .info (() -> formatMessage ("AnalyzingArchive" , archive ));
119166 archiveProcessor .processBinaryFile (archive );
120167 }
168+
169+ // Add extra libraries, if is there any
170+ if (additionalLibraries != null && additionalLibraries .size () > 0 ) {
171+ archiveProcessor .processExtraLibs (additionalLibraries .toArray (new File [additionalLibraries .size ()]));
172+ }
121173 }
122174 ap .write ();
123175 }
@@ -133,45 +185,54 @@ public static void setLoggingLevel(Level level) {
133185
134186 // [0] : archive path(s)
135187 // [1] : output directory
136- // [2] : package exclusion list
137- // [3] : build call graph (true|false|<algorithm-name>)
188+ // [2] : additional libraries (especially JEE libraries)
189+ // [3] : package exclusion list
190+ // [4] : build call graph (true|false|<algorithm-name>)
138191 public static void main (String [] args ) {
139192 if (args .length > 1 ) {
140193 final Analyzer analyzer ;
141- if (!args [0 ].contains (File .pathSeparator )) {
142- analyzer = new Analyzer (new File (args [0 ]), new File (args [1 ]));
194+ final List <File > archives = new ArrayList <>();
195+ final List <File > extraLibs = new ArrayList <>();
196+
197+ final StringTokenizer st = new StringTokenizer (args [0 ], File .pathSeparator );
198+ while (st .hasMoreTokens ()) {
199+ final String file = st .nextToken ().trim ();
200+ if (!file .isEmpty ()) {
201+ archives .add (new File (file ));
202+ }
143203 }
144- else {
145- final List <File > archives = new ArrayList <>();
146- final StringTokenizer st = new StringTokenizer (args [0 ], File .pathSeparator );
147- while (st .hasMoreTokens ()) {
148- final String file = st .nextToken ().trim ();
204+ if (args .length > 2 ) {
205+ final StringTokenizer st2 = new StringTokenizer (args [2 ], File .pathSeparator );
206+ while (st2 .hasMoreTokens ()) {
207+ final String file = st2 .nextToken ().trim ();
149208 if (!file .isEmpty ()) {
150- archives .add (new File (file ));
209+ extraLibs .add (new File (file ));
151210 }
152211 }
153- analyzer = new Analyzer (archives .toArray (new File [archives .size ()]), new File (args [1 ]));
154212 }
155- if (args .length > 2 ) {
213+
214+ analyzer = new Analyzer (archives .toArray (new File [archives .size ()]), new File (args [1 ]), extraLibs .toArray (new File [extraLibs .size ()]));
215+
216+ if (args .length > 3 ) {
156217 final Set <String > packages = new LinkedHashSet <>();
157- final StringTokenizer st = new StringTokenizer (args [2 ], "," );
158- while (st .hasMoreTokens ()) {
159- final String token = st .nextToken ().trim ();
218+ final StringTokenizer st3 = new StringTokenizer (args [3 ], "," );
219+ while (st3 .hasMoreTokens ()) {
220+ final String token = st3 .nextToken ().trim ();
160221 if (!token .isEmpty ()) {
161222 packages .add (token );
162223 }
163224 }
164225 analyzer .setPackageRestrictions (packages , false );
165226 }
166227 try {
167- if (args .length > 3 ) {
168- final boolean generateCallGraph = Boolean .parseBoolean (args [3 ]);
228+ if (args .length > 4 ) {
229+ final boolean generateCallGraph = Boolean .parseBoolean (args [4 ]);
169230 if (generateCallGraph ) {
170231 analyzer .setCallGraphBuilder (generateCallGraph );
171232 }
172233 else {
173234 // Try to match the name of one of the CallGraphBuilderType enum values.
174- Optional <CallGraphBuilderType > o = CallGraphBuilderType .find (args [3 ]);
235+ Optional <CallGraphBuilderType > o = CallGraphBuilderType .find (args [4 ]);
175236 if (o .isPresent ()) {
176237 analyzer .setCallGraphBuilder (o .get ());
177238 }
0 commit comments