Listing All Classes In A Jar File Using ColdFusion

Posted October 2, 2008 at 8:05 PM by Ben Nadel

Tags: ColdFusion

You'll probably never need to do this, but today, I needed to find out what Java classes were available in a given JAR file using ColdFusion. The reason - I was doing some work on my POI Utility ColdFusion custom tags and I needed to see if the version of the POI JAR that ships with ColdFusion supports certain classes. Turns out, this is a fairly straightforward task. I wrapped the functionality up in a ColdFusion user defined function that takes the expanded path to the target JAR file:

  • <cffunction
  • name="GetJarClasses"
  • access="public"
  • returntype="array"
  • output="false"
  • hint="I return an array of classes in the given JAR file (expanded path).">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="JarFilePath"
  • type="string"
  • required="true"
  • hint="I am the expanded path of the JAR file."
  • />
  •  
  • <!--- Define the local scope. --->
  • <cfset var LOCAL = {} />
  •  
  • <!--- Create a default array of classes. --->
  • <cfset LOCAL.Classes = [] />
  •  
  •  
  • <!---
  • Create a JAR input stream to read in the line items
  • from our target JAR file.
  • --->
  • <cfset LOCAL.JarFile = CreateObject(
  • "java",
  • "java.util.jar.JarInputStream"
  • ).Init(
  •  
  • CreateObject(
  • "java",
  • "java.io.FileInputStream"
  • ).Init(
  •  
  • JavaCast(
  • "string",
  • ARGUMENTS.JarFilePath
  • )
  • )
  • )
  • />
  •  
  •  
  • <!---
  • Now that we have our JAR file input stream, let's loop
  • over all the entries looking for CLASS files.
  • --->
  • <cfloop condition="true">
  •  
  • <!---
  • Get the next entry. This might return NULL if the
  • JAR file has no more classes.
  • --->
  • <cfset LOCAL.JarEntry = LOCAL.JarFile.GetNextJarEntry() />
  •  
  • <!---
  • Check to see if the entry variable exists. If it
  • does not, then it means the JAR file return NULL
  • and we are done finding classes.
  • --->
  • <cfif StructKeyExists( LOCAL, "JarEntry" )>
  •  
  • <!---
  • Check to make sure that this entry is not a
  • directory, but is, in fact a class.
  • --->
  • <cfif REFindNoCase( "\.class$", LOCAL.JarEntry.GetName() )>
  •  
  • <!---
  • Add this class to the array. Since the JAR
  • file really has a directory structure, let's
  • replace the path separators with dots.
  • --->
  • <cfset LOCAL.ClassName = REReplace(
  • LOCAL.JarEntry.GetName(),
  • "[\\/]",
  • ".",
  • "all"
  • ) />
  •  
  • <!--- Strip off the ".class" path item. --->
  • <cfset LOCAL.ClassName = REReplaceNoCase(
  • LOCAL.ClassName,
  • "\.class$",
  • "",
  • "one"
  • ) />
  •  
  • <!--- Add the formatted class name. --->
  • <cfset ArrayAppend(
  • LOCAL.Classes,
  • LOCAL.ClassName
  • ) />
  •  
  • </cfif>
  •  
  • <cfelse>
  •  
  • <cfbreak />
  •  
  • </cfif>
  •  
  • </cfloop>
  •  
  •  
  • <!--- Return the array of classes. --->
  • <cfreturn LOCAL.Classes />
  • </cffunction>

To call it, you just do this (I had a copy of the installed POI JAR file in the same directory as my test file):

  • <!--- Get file path to POI installed JAR file. --->
  • <cfset strJarFilePath = ExpandPath(
  • "./poi-2.5.1-final-20040804.jar"
  • ) />
  •  
  • <!--- Output the classes. --->
  • <cfdump
  • var="#GetJarClasses( strJarFilePath )#"
  • label="POI 2.5.1 Final Classes"
  • />

Running this, we get an array with the following values (abbreviated):

org.apache.poi.ddf.DefaultEscherRecordFactory
org.apache.poi.ddf.EscherArrayProperty
org.apache.poi.ddf.EscherBSERecord
org.apache.poi.ddf.EscherBlipRecord
..... several hundred classes .....
org.apache.poi.util.ShortList
org.apache.poi.util.StringUtil
org.apache.poi.util.SystemOutLogger

Anyway, just thought I would post that in case anyone ever needs this kind of functionality.




Reader Comments

Oct 3, 2008 at 9:09 AM // reply »
48 Comments

How is this different then just listing the JAR out with cfzip?


Oct 3, 2008 at 9:10 AM // reply »
32 Comments

I never really play around with JAR files much, so this comment could be totally off base, but, could you have not just used the cfzip tag? It accepts a JAR file and you could use the list action and just dumped that out, right? or am i missing the point? It's Friday so my brain has shut of ffor the weekend :-)


Oct 3, 2008 at 9:10 AM // reply »
32 Comments

@Todd - beat me to it :-)


Oct 3, 2008 at 9:13 AM // reply »
11,246 Comments

@Todd, @Simon,

Oh snap, I totally forgot that CFZip could read JAR files :)


Oct 3, 2008 at 9:30 AM // reply »
11,246 Comments

Thanks guys; amends have been made:

http://www.bennadel.com/index.cfm?dax=blog:1373.view


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 25, 2013 at 10:08 AM
Using "//" And ".//" Expressions In XPath XML Search Directives In ColdFusion
@Ben, my question is that i want the current node with its tag and its parent node. i just want only that data. So, give me the solution for that. and remember solution is working on " xpath 1.0 ... read »
May 25, 2013 at 10:01 AM
Using "//" And ".//" Expressions In XPath XML Search Directives In ColdFusion
hey ben, i want get my current node tag and also want the root node tag withing. So, how can i fix it.. ! ... read »
May 24, 2013 at 5:39 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
@Adam Oops! My mistake! I hadn't gotten that far in my testing - I'm still baby stepping my way through the process. ... read »
May 24, 2013 at 5:13 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
Hi Jason, Thanks for checking up on that, but I still stand firm on my position. :) There are actually two listLast()'s in use, and you're right that the one using a space as a delimiter is fine. ... read »
May 24, 2013 at 4:45 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
@Ben I have been lurking your site for quite some time, and haven't stepped up to comment until today. Thanks for all the great info - keep it up! @Adam I believe you are mistaken... as the commen ... read »
May 24, 2013 at 11:21 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@WebManWalking, Ha ha, let's us never speak of justifying "##" notation again :P ... read »
May 24, 2013 at 11:18 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, Ah, so it was indeed how I vaguely remembered it to be: A direct assignment value = users.id[ i ] causes value to retain the sticky datatype of the query column. Although unnecessary in ... read »
May 24, 2013 at 9:11 AM
Preventing Links In Standalone iPhone Applications From Opening In Mobile Safari
@Brandon, Hi, No, I haven't been able to do that. I have just kept it as it is. ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools