Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at Scotch On The Rocks (SOTR) 2011 (Edinburgh) with: Cyril Hanquez and Hugo Sombreireiro and Reto Aeberli and Steven Peeters and Guust Nieuwenhuis and Aurélien Deleusière and Damien Bruyndonckx
Ben Nadel at Scotch On The Rocks (SOTR) 2011 (Edinburgh) with: Cyril Hanquez@Fitzchev ) , Hugo Sombreireiro@hsombreireiro ) , Reto Aeberli@aeberli ) , Steven Peeters@aikisteve ) , Guust Nieuwenhuis@Lagaffe ) , Aurélien Deleusière@adeleusiere ) , and Damien Bruyndonckx ( @damienbkx )

Listing All Classes In A Jar File Using ColdFusion

By Ben Nadel on
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

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 :-)