Created
February 23, 2012 05:09
-
-
Save isapir/1890454 to your computer and use it in GitHub Desktop.
this component scans a folder of CFML and compares it with the /WEB-INF/railo/cfclasses to detect files that are in the source folder but were not compiled to a Java class, essentially showing old / obsolete / seldomly used cf source files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfcomponent output="false" | |
hint="this component scans a folder of CFML and compares it with the /WEB-INF/railo/cfclasses to detect files that are in the source folder but were not compiled to a Java class, essentially showing old / obsolete / seldomly used cf source files"> | |
<!--- requires: Railo 3.x | |
/** Attention: this component Does Not delete any files; it merely points out | |
* which files were not compiled so that you can inspect them and | |
* decide if they can be safely removed. | |
* | |
* Warning: be sure to back up all of your source files before you make any | |
* chages. check source code for references of files before removing | |
* them in case they were not triggered by any calls but will be used | |
* by your system at a later time */ | |
usage: | |
delete old (or all) *.class files from /WEB-INF/railo/cfclasses | |
let the application run for a while to allow all of the CF files to be compiled to Java class files | |
create a file to use this component, e.g.: | |
<cfset ufd = CreateObject( 'component', 'UnusedCfFilesDetector' )> | |
<cfset unused.Root = ufd.ScanFolderForUnusedCfFiles( '/' )> | |
<cfset unused.CFC = ufd.ScanFolderForUnusedCfFiles( '/cfc' )> | |
<cfset unused.Test = ufd.ScanFolderForUnusedCfFiles( '/test' )> | |
<cfdump var="#unused#"> | |
---> | |
<cfset this.CFCLASSES_FOLDER = ExpandPath( '/WEB-INF/railo/cfclasses' )> | |
<cfset this.IgnoreList = "/|\\WEB-INF/|\\railo"> | |
<cfset this.init()> | |
<cffunction name="init"> | |
<cfset this.Mappings = getMappings()> | |
<cfreturn this> | |
</cffunction> | |
<cffunction name="ScanFolderForUnusedCfFiles" output="false" | |
hint="scans the folder at a given CF path and returns an array of all the files that don't have a corresponding Java class file"> | |
<cfargument name="path"> | |
<cfargument name="filter" default="*.cf?|*.cfml"> | |
<cfargument name="recurse" default="#false#"> | |
<cfset Local.result = []> | |
<cfdirectory name="Local.qFiles" action="list" directory="#ExpandPath( path )#" recurse="#recurse#" filter="#filter#"> | |
<cfloop query="Local.qFiles"> | |
<cfset Local.folder = resolveFolder( directory )> | |
<cfset Local.vpath = listFirst( this.Mappings.physical[ Local.folder ], ';' )> | |
<cfif right( Local.vpath, 1 ) NEQ '/'> | |
<cfset Local.vpath &= '/'> | |
</cfif> | |
<cfset Local.pathInfo = replace( ReplaceNoCase( directory, Local.folder, '' ), '\', '/', 'all' )> | |
<cfif len( Local.pathInfo )> | |
<cfset Local.pathInfo = mid( Local.pathInfo, 2, 256 ) & '/'> | |
</cfif> | |
<cfset Local.fullVPath = Local.vpath & Local.pathInfo & name> | |
<cfif !isCfclassFileExist( Local.fullVPath )> | |
<cfset ArrayAppend( Local.result, "#directory#\#name#" )> | |
</cfif> | |
</cfloop> | |
<cfreturn Local.result> | |
</cffunction> | |
<cffunction name="resolveFolder" output="false" | |
hint="loops through the path's parents in an attempt to find one that exists in the mapping struct"> | |
<cfargument name="path"> | |
<cfset Local.result = path> | |
<cfloop condition="#len( Local.result )#"> | |
<cfif StructKeyExists( this.Mappings.physical, Local.result )> | |
<cfreturn Local.result> | |
</cfif> | |
<cfset Local.result = getParentFolder( Local.result )> | |
</cfloop> | |
</cffunction> | |
<cffunction name="getParentFolder" output="false" | |
hint="returns the parent folder of a given path, e.g. C:\folder1\folder2 from C:\folder1\folder2\folder3"> | |
<cfargument name="path"> | |
<cfset Local.result = path> | |
<cfset Local.len = len( Local.result )> | |
<cfloop from="#Local.len#" to="1" step="-1" index="Local.ii"> | |
<cfif "\/" contains mid( Local.result, Local.ii, 1 )> | |
<cfset Local.result = left( Local.result, Local.ii - 1 )> | |
<cfbreak> | |
</cfif> | |
</cfloop> | |
<cfif Local.result IS path> | |
<cfset Local.result = ""> | |
</cfif> | |
<cfreturn Local.result> | |
</cffunction> | |
<cffunction name="isCfclassFileExist" output="false" | |
hint="calls getCfclassFilePath and returns true if a file in that path exists"> | |
<cfargument name="CfFilePath"> | |
<cfset Local.path = getCfclassFilePath( CfFilePath )> | |
<cfset Local.result = FileExists( Local.path )> | |
<cfreturn Local.result> | |
</cffunction> | |
<cffunction name="getCfclassFilePath" output="false" | |
hint="takes a CF file path and returns the Java class file's path for it"> | |
<cfargument name="CfFilePath"> | |
<cfset Local.pc = getPageContext()> | |
<cfset Local.vPath = contractPath( CfFilePath )> | |
<cfset Local.pageSource = Local.pc.getPageSource( Local.vPath )> | |
<cfset Local.mapping = Local.pageSource.getMapping()> | |
<cfset Local.classRoot = Local.mapping.getClassRootDirectory()> | |
<cfset Local.result = Local.classRoot.getReal( Local.pageSource.getJavaName() )> | |
<cfif right( Local.result, 3 ) IS '$cf'> | |
<cfset Local.result &= '.class'> | |
</cfif> | |
<cfreturn Local.result> | |
</cffunction> | |
<cffunction name="getMappings" output="false" | |
hint="returns a struct with three sub-structs that contain the mappings defined in Railo and the Application, as well as the safe folder names in the cfclasses folder. the values are lists separated by semi-colons;"> | |
<cfset var Local = {}> | |
<cfset Local.result = {}> | |
<cfset Local.result.virtual = {}> | |
<cfset Local.result.physical = {}> | |
<cfset Local.mappings = []> | |
<cfset Local.mappings = ArrayMerge( Local.mappings, GetPageContext().getServletConfig().getMappings() )> | |
<cfset Local.mappings = ArrayMerge( Local.mappings, GetPageContext().getServletConfig().getComponentMappings() )> | |
<cfset Local.mappings = ArrayMerge( Local.mappings, GetPageContext().getServletConfig().getCustomTagMappings() )> | |
<cfset Local.appObject = CreateObject( 'component', 'Application' )> | |
<cfif IsDefined( "Local.appObject.Mappings" ) && isStruct( Local.appObject.Mappings )> | |
<cfloop collection="#Local.appObject.Mappings#" item="Local.key"> | |
<cfset ArrayAppend( Local.mappings, GetPageContext().getServletConfig().getApplicationMapping( Local.key, expandPath( Local.key ) ) )> | |
</cfloop> | |
</cfif> | |
<cfloop array="#Local.mappings#" index="Local.ai"> | |
<cfset Local.virtual = Local.ai.virtual> | |
<cfset Local.physical = Local.ai.physical> | |
<cfif IsNumeric( mid( Local.virtual, 2, 256 ) )> | |
<cfset Local.virtual = '/'> <!--- custom tags folder ---> | |
</cfif> | |
<cfif Local.physical contains '{'> | |
<cfset Local.physical = ExpandPath( Local.ai.physical )> | |
</cfif> | |
<cfif !REFindNoCase( this.IgnoreList, Local.physical )> | |
<!--- physical ---> | |
<cfif StructKeyExists( Local.result.physical, Local.physical )> | |
<cfset Local.value = Local.result.physical[ Local.physical ]> | |
<cfelse> | |
<cfset Local.value = ""> | |
</cfif> | |
<cfif !ListFind( Local.value, Local.virtual, ';' )> | |
<cfset Local.value = ListAppend( Local.value, Local.virtual, ';' )> | |
</cfif> | |
<cfset Local.result.physical[ Local.physical ] = Local.value> | |
<!--- virtual ---> | |
<cfif StructKeyExists( Local.result.virtual, Local.virtual )> | |
<cfset Local.value = Local.result.virtual[ Local.virtual ]> | |
<cfelse> | |
<cfset Local.value = ""> | |
</cfif> | |
<cfif !ListFind ( Local.value, Local.physical, ';' )> | |
<cfset Local.value = ListAppend( Local.value, Local.physical, ';' )> | |
</cfif> | |
<cfset Local.result.virtual[ Local.virtual ] = Local.value> | |
</cfif> | |
</cfloop> | |
<!--- cfclasses ---> | |
<cfdirectory action="list" directory="#this.CFCLASSES_FOLDER#" name="Local.qCfClassesDir"> | |
<cfset Local.result.cfclasses = {}> | |
<cfloop collection="#Local.result.physical#" item="Local.physicalPath"> | |
<cfset Local.safeName = getSafeName( Local.physicalPath )> | |
<cfquery name="Local.qTemp" dbtype="query"> | |
SELECT name | |
FROM Local.qCfClassesDir | |
WHERE name like '#Local.safeName#%' | |
and type = 'Dir' | |
</cfquery> | |
<cfloop query="Local.qTemp"> | |
<cfif IsNumeric( ReplaceNoCase( Local.qTemp.name, Local.safeName, '' ) )> | |
<cfset Local.result.cfclasses[ Local.physicalPath ] = Local.qTemp.name> | |
<cfbreak> | |
</cfif> | |
</cfloop> | |
</cfloop> | |
<cfreturn Local.result> | |
</cffunction> | |
<cffunction name="getSafeName" output="false" | |
hint="converts a filename from something like C:\folder\file.cfm to CFC__folder_file_cfm"> | |
<cfargument name="filename"> | |
<cfset Local.len = len( filename )> | |
<cfset Local.sb = CreateObject( 'java', 'java.lang.StringBuilder' ).init( JavaCast( "int", Local.len + 2 ) )> | |
<cfset Local.sb.append( 'CF' )> | |
<cfloop from="1" to="#Local.len#" index="Local.ii"> | |
<cfset Local.char = mid( filename, Local.ii, 1 )> | |
<cfif "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" contains Local.char> | |
<cfset Local.sb.append( Local.char )> | |
<cfelse> | |
<cfset Local.sb.append( '_' )> | |
</cfif> | |
</cfloop> | |
<cfreturn Local.sb.toString()> | |
</cffunction> | |
</cfcomponent> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment