Files

195 lines
6.1 KiB
Plaintext

component output="false" {
// bean cache
this.beans = {};
this.transients = {};
public function init(externalBeanFactory) {
if (structKeyExists(arguments, "externalBeanFactory")) {
this.externalBeanFactory = arguments.externalBeanFactory;
}
return this;
}
// Proxy to beanExists to provide similar interface to ColdSpring
public function containsBean(beanName) {
return beanExists(arguments.beanName);
}
public function transientExists(beanName) {
return structKeyExists(this.transients, arguments.beanName);
}
public function getBean(beanName) {
var b = 0;
var meta = 0;
if (beanExists(arguments.beanName, false, false)) {
return this.beans[arguments.beanName];
} else if (transientExists(arguments.beanName)) {
b = createObject('component', this.transients[arguments.beanName]);
meta = getMetadata(b);
_recurse_ResolveDependencies(b, meta);
return b;
} else if (externalBeanExists(arguments.beanName)) {
return this.externalBeanFactory.getBean(arguments.beanName);
} else {
throwError(message="Bean name '#arguments.beanName#' not found.", type="Taffy.Factory.BeanNotFound");
}
}
public function getBeanList() {
var combined = structKeyList(this.beans);
var trans = structKeyList(this.transients);
if (len(combined) and len(trans)) {
combined = combined & ",";
}
combined = combined & trans;
return combined;
}
public function beanExists(required beanName, includeTransients=true, includeExternal=false) output="false" {
return structKeyExists(this.beans, arguments.beanName) or (arguments.includeTransients and transientExists(arguments.beanName)) or
(arguments.includeExternal and externalBeanExists(arguments.beanName));
}
private boolean function externalBeanExists(required beanName) output="false" {
return structKeyExists(this, "externalBeanFactory") and this.externalBeanFactory.containsBean(arguments.beanName);
}
public void function loadBeansFromPath(
required string beanPath hint="Absolute path to folder containing beans",
string resourcesPath="resources",
string resourcesBasePath="",
boolean isFullReload=false,
taffyRef={}
) output="false" {
var local = {};
// cache all of the beans
if (isFullReload) {
this.beans = {};
arguments.taffyRef.status.skippedResources = []; // empty out the array on factory reloads
arguments.taffyRef.beanList = "";
}
// if the folder doesn't exist, do nothing
if (!directoryExists(arguments.beanPath)) {
return;
}
// get list of beans to load
local.beanQuery = directoryList(arguments.beanPath, true, "query", "*.cfc");
for (var row in local.beanQuery) {
local.beanName = filePathToBeanName(row.directory, row.name, arguments.resourcesBasePath);
local.beanPath = filePathToBeanPath(row.directory, row.name, arguments.resourcesPath, arguments.resourcesBasePath);
try {
local.objBean = createObject("component", local.beanPath);
if (isSerializerInstance(local.objBean)) {
this.transients[local.beanName] = local.beanPath;
} else {
this.beans[local.beanName] = local.objBean;
}
} catch (any e) {
// skip cfc's with errors, but save info about them for display in the dashboard
local.err = {};
local.err.resource = local.beanName;
local.err.exception = e;
arrayAppend(arguments.taffyRef.status.skippedResources, local.err);
}
}
// resolve dependencies
for (local.b in this.beans) {
local.bean = this.beans[local.b];
local.beanMeta = getMetadata(local.bean);
_recurse_ResolveDependencies(local.bean, local.beanMeta);
}
}
private function filePathToBeanPath(path, filename, resourcesPath, resourcesBasePath) {
var beanPath = "";
if (len(resourcesBasePath) eq 0) {
arguments.resourcesBasePath = "!@$%^&*()";
}
beanPath =
resourcesPath
& "."
& replaceList(
replace(path, resourcesBasePath, ""),
"/,\",
".,."
)
& "."
& replace(
filename,
".cfc",
""
);
beanPath = replace(beanPath, "..", ".", "ALL");
if (left(beanPath, 1) eq ".") {
beanPath = right(beanPath, len(beanPath)-1);
}
return beanPath;
}
private function filePathToBeanName(path, filename, basepath) {
if (len(basepath) eq 0) {
arguments.basePath = "!@$%^&*()";
}
return
replaceList(
replace(path, basepath, ""),
"/,\",
","
)
& replace(
filename,
".cfc",
""
);
}
private function _recurse_ResolveDependencies(required bean, required struct metaData) {
var local = {};
if (structKeyExists(arguments.metaData, "functions") and isArray(arguments.metaData.functions)) {
for (local.f = 1; local.f <= arrayLen(arguments.metaData.functions); local.f++) {
local.fname = arguments.metaData.functions[local.f].name;
if (len(local.fname) gt 3) {
local.propName = right(local.fname, len(local.fname)-3);
if (left(local.fname, 3) eq "set" and beanExists(local.propName, true, true)) {
invoke(arguments.bean, local.fname, [getBean(local.propName)]);
}
}
}
}
if (structKeyExists(arguments.metaData, "properties") and isArray(arguments.metaData.properties)) {
for (local.p = 1; local.p <= arrayLen(arguments.metaData.properties); local.p++) {
local.propName = arguments.metaData.properties[local.p].name;
if (beanExists(local.propName, true, true)) {
arguments.bean[local.propName] = getBean(local.propName);
}
}
}
if (structKeyExists(arguments.metaData, "extends") and isStruct(arguments.metaData.extends)) {
_recurse_ResolveDependencies(arguments.bean, arguments.metaData.extends);
}
}
/**
* Walks the inheritance chain to check if obj extends baseSerializer.
* Replaces isInstanceOf() which fails on Lucee when extends resolves
* to a relative path instead of a mapping-prefixed path.
*/
private boolean function isSerializerInstance(required any obj) output="false" {
if (!isObject(arguments.obj)) return false;
var meta = getMetadata(arguments.obj);
while (structKeyExists(meta, "name")) {
if (listLast(meta.name, ".") == "baseSerializer") return true;
if (!structKeyExists(meta, "extends")) break;
meta = meta.extends;
}
return false;
}
private function throwError() {
cfthrow(attributecollection=arguments);
}
}