Skip to content

Instantly share code, notes, and snippets.

@dajester2013
Last active December 5, 2018 17:53
Show Gist options
  • Save dajester2013/59c008c53d524b51eb9219508b6dbbdd to your computer and use it in GitHub Desktop.
Save dajester2013/59c008c53d524b51eb9219508b6dbbdd to your computer and use it in GitHub Desktop.
/**
* Copyright 2018 Jesse Shaffer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
component {
/**
* Discovers service meta locations in all available Lucee mappings/custom tag paths.
* @returns {Struct[]} array of location information
*/
private array function getLuceeMappingLocations() {
var mappings = [];
// get the application mappings
mappings.addAll(getApplicationMetaData().componentPaths);
mappings.addAll(getApplicationMetaData().customTagPaths);
// get the named mappings
mappings.addAll(getPageContext().getConfig().getMappings());
// and the custom tag mappings
mappings.addAll(getPageContext().getConfig().getCustomTagMappings());
// and the component mappings
mappings.addAll(getPageContext().getConfig().getComponentMappings());
// convert mappings to paths
return mappings.map(function(mapping) {
if (isSimpleValue(mapping)) return {
path: mapping
};
if (mapping.hasPhysical() || mapping.hasArchive()) {
var mask = 0;
mask = bitor(mask, mapping.isPhysicalFirst() ? 4 : 0);
mask = bitor(mask, mapping.hasPhysical() ? 2 : 0);
mask = bitor(mask, mapping.hasArchive() ? 1 : 0);
var config = {
componentPrefix : (
mapping.ignoreVirtual()
? ""
: mapping.getVirtual().replaceAll("^\/","").replaceAll("\/",".")
)
};
if (config.componentPrefix.len()) config.componentPrefix &= ".";
if (mask > 5) {
config.path = mapping.getPhysical() & "/";
} else if (mask > 0) {
config.path = "zip://" & mapping.getArchive() & "!/";
}
return config;
}
// gather only service locations that actually exist
}).reduce(function(locations=[], location) {
if (DirectoryExists(location.path)) {
locations.add(location);
}
return locations;
});
}
/**
* Discovers service meta locations in all available Adobe ColdFusion mappings/custom tag paths.
*/
private array function getAdobeMappingLocations() {
var locations = [];
// get application settings first
var appMeta = getApplicationMetadata();
for (var m in appMeta.mappings) {
locations.add({
componentPrefix: m.replaceAll("^\/","").replaceAll("\/",".") & "."
,path: expandPath(m) & "/"
});
}
for (var p in appMeta.customTagPaths.split(",")) {
locations.add({
componentPrefix=""
,path: p & "/"
});
}
// get server settings next
try {
var rs = CreateObject("java","coldfusion.server.ServiceFactory").getRuntimeService();
for (var m in rs.getMappings()) {
locations.add({
componentPrefix: m.replaceAll("^\/","").replaceAll("\/",".") & "."
,path: expandPath(m) & "/"
});
}
for (var p in rs.getCustomtags()) {
locations.add({
componentPrefix=""
,path: rs.getCustomtags()[p] & "/"
});
}
} catch(any e) {
// ignore
}
return locations.reduce(function(exists=[], location) {
if(DirectoryExists(location.path)) {
exists.add(location);
}
return exists;
});
}
/**
* Scans all available component mappings
*/
public array function scanMappings(boolean forceRescan=false) {
if (forceRescan || !variables.keyExists("$mappings")) {
if (server.keyExists("lucee")) {
variables.$mappings = getLuceeMappingLocations();
} else {
variables.$mappings = getAdobeMappingLocations();
}
}
return variables.$mappings;
}
variables.scanCache = {};
public function find(string component, boolean ignoreCache=false) {
if (ignoreCache || !scanCache.keyExists(component)) {
scanCache[component] = {};
var mappings = this.scanMappings();
var componentFile = "/" & component.replaceAll("\.","/") & ".cfc";
var classFile = "/" & component.replaceAll("\.","/") & "_cfc$cf.class";
var expandedComponentPath = expandPath(componentFile);
if (fileExists(expandedComponentPath)) {
scanCache[component].discovered = {
component: component
,path: expandedComponentPath
};
} else {
mappings.every(function(mapping) {
if (fileExists(mapping.path & componentFile)) {
scanCache[component].discovered = {
component: component
,path: mapping.path & componentFile
};
} else if (fileExists(mapping.path & classFile)) {
scanCache[component].discovered = {
component: component
,path: mapping.path & classFile
};
}
return !scanCache[component].keyExists("discovered");
});
}
}
if (scanCache[component].keyExists("discovered"))
return scanCache[component].discovered;
}
}
<cfscript>
scanner = new ComponentScanner();
result = scanner.find("some.type");
if (!isNull(result)) {
// found a component!
writeoutput("found component #result.component# at #result.path#");
}
</cfscript>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment