I'm working on a proof of concept ColdFusion Builder Extension for work and it requires that I examine a CFC. That should be easy enough, right? We have the getComponentMetadata function which returns a nice structure of information about the CFC. However, there is one problem with this function. All CFC functions in ColdFusion require a "dot path". Unless the CFC is in the same folder you need to use a "dot path" location to tell ColdFusion how to load the CFC. Since this CFBuilder extension has to work with any CFC on the file system, it isn't really practical to figure out how to get path to that CFC. What follows is one solution to this issue - I'm not terribly happy with it but it seems to work.
To begin my CFBuilder extension, I created my ide_config.xml file. I won't go into full details about each line here - check the CFBuilder docs for a full explanation on how to build extensions.
<menucontributions>
<contribution target="projectview">
<menu name="Get CFC Metadata">
<filters>
<filter type="file" pattern=".+.cfc" />
</filters>
<action name="Do It" handlerid="getcfcmeta" showResponse="no" />
</menu>
</contribution>
</menucontributions> <handlers>
<handler id="getcfcmeta" type="cfm" filename="getcfcmeta.cfm" />
</handlers>
</application>
<application>
<name>CFC Test</name>
<author>Raymond Camden</author>
<version>1.0</version>
<email>ray@camdenfamily.com</email>
<description>Attempts to get metadata for a CFC.</description>
<license>Just Use It.</license>
There are two things I want to point out here. First - notice how I used a pattern on the menu. Thanks to Dan Vega for helping me realize that the value for pattern is a regex. I began with *.cfc which didn't work correctly. Secondly make note of getcfcmeta.cfm. That's the file that will contain the main code to handle my solution. Let's take a look at that next.
<cfset newName = replace(createUUID(), "-", "_", "all")>
<cfset newLocation = getDirectoryFromPath(getCurrentTemplatePath()) & newName & ".cfc"> <!--- Copy the file --->
<cffile action="copy" source="#myFile#" destination="#newLocation#"> <cfset meta = getComponentMetaData("#newName#")> <cfdump var="#meta#" output="c:\webroot\test.html" format="html"> <cffile action="delete" file="#newLocation#">
<cflog file="bolt" text="I'm done. Stored to #newlocation#">
<cfparam name="ideeventinfo">
<cfset data = xmlParse(ideeventinfo)>
<cfset myFile = data.event.ide.projectview.resource.xmlAttributes.path>
<cflog file="bolt" text="Working with #myFile#">
So we begin by parsing out the XML sent to the extension. This is all documented but while I was developing I made copious use of cflog to look at the XML. Just know that the myFile variable will contian the full path to the CFC that was selected in the Navigator.
Now it's time for the hack. I decided I'd simply copy the CFC to the same folder as the extension. I used a new name based on UUID. Once copied I was able to use getComponentMetaData. Note that newName is just the UUID, it doesn't include the path or the extension. Once I had it I confirmed it by using cfdump. (Don't forget ColdFusion 8 added the ability to dump to a file. It's useful for situations like this where I'm working with extensions.) Finally I delete the file.
That's it. So does it work? Yes and no. It does correctly reflect function metadata which for my case is all I need. However some values, specifically fullname, name, and path, reflect the temporary copy of the CFC. Here is an example: