From c1d95dfbc3062336ce96ca3d4743cfa2f67fd43c Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 27 Mar 2018 10:58:30 -0700 Subject: [PATCH 01/19] Start 4.3.0-SNAPSHOT on develop branch --- box.json | 6 +++--- framework/Application.cfc | 2 +- framework/MyApplication.cfc | 2 +- framework/WireBoxAdapter.cfc | 2 +- framework/aop.cfc | 2 +- framework/beanProxy.cfc | 2 +- framework/facade.cfc | 2 +- framework/ioc.cfc | 2 +- framework/methodProxy.cfc | 2 +- framework/one.cfc | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/box.json b/box.json index 20c0e1dd..e99eb470 100644 --- a/box.json +++ b/box.json @@ -1,9 +1,9 @@ { "name":"Framework One", "slug":"fw1", - "version":"4.2.0", + "version":"4.3.0-SNAPSHOT", "author":"Sean Corfield, Marcin Szczepanski, Ryan Cogswell", - "location":"framework-one/fw1#master", + "location":"framework-one/fw1#develop", "createPackageDirectory":true, "packageDirectory":"framework", "Homepage":"http://framework-one.github.io/", @@ -16,7 +16,7 @@ "shortDescription":"FW/1 - Framework One - is a family of small, lightweight, convention-over-configuration frameworks, primarily for CFML.", "description":"FW/1 - Framework One - is a family of small, lightweight, convention-over-configuration frameworks, primarily for CFML. FW/1 itself provides MVC, DI/1 provides dependency injection (a.k.a. inversion of control), and AOP/1 provides aspect-oriented programming features on top of DI/1.", "instructions":"http://framework-one.github.io/documentation/", - "changelog":"https://github.com/framework-one/fw1/commits/master", + "changelog":"https://github.com/framework-one/fw1/commits/develop", "type":"mvc", "keywords":[ "fw1", diff --git a/framework/Application.cfc b/framework/Application.cfc index ca615b05..68e5d17b 100644 --- a/framework/Application.cfc +++ b/framework/Application.cfc @@ -1,5 +1,5 @@ component { - // Version: FW/1 4.2.0 + // Version: FW/1 4.3.0-SNAPSHOT // copy this to your application root to use as your Application.cfc // or incorporate the logic below into your existing Application.cfc diff --git a/framework/MyApplication.cfc b/framework/MyApplication.cfc index d32f1cbc..460c5198 100644 --- a/framework/MyApplication.cfc +++ b/framework/MyApplication.cfc @@ -1,5 +1,5 @@ component extends="framework.one" { - // Version: FW/1 4.2.0 + // Version: FW/1 4.3.0-SNAPSHOT // if you need to provide extension points, copy this to // your web root, next to your Application.cfc, and add diff --git a/framework/WireBoxAdapter.cfc b/framework/WireBoxAdapter.cfc index 4738a5aa..4b20da18 100644 --- a/framework/WireBoxAdapter.cfc +++ b/framework/WireBoxAdapter.cfc @@ -1,5 +1,5 @@ component extends="wirebox.system.ioc.Injector" { - variables._fw1_version = "4.2.0"; + variables._fw1_version = "4.3.0-SNAPSHOT"; /* Copyright (c) 2010-2018, Sean Corfield diff --git a/framework/aop.cfc b/framework/aop.cfc index b3910da8..95991adf 100644 --- a/framework/aop.cfc +++ b/framework/aop.cfc @@ -1,5 +1,5 @@ component extends="framework.ioc" { - variables._fw1_version = "4.2.0"; + variables._fw1_version = "4.3.0-SNAPSHOT"; variables._aop1_version = variables._fw1_version; /* Copyright (c) 2013-2018, Mark Drew, Sean Corfield, Daniel Budde diff --git a/framework/beanProxy.cfc b/framework/beanProxy.cfc index 00cffb56..b180906c 100644 --- a/framework/beanProxy.cfc +++ b/framework/beanProxy.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.2.0"; + variables._fw1_version = "4.3.0-SNAPSHOT"; variables._aop1_version = variables._fw1_version; /* Copyright (c) 2013-2018, Mark Drew, Sean Corfield, Daniel Budde diff --git a/framework/facade.cfc b/framework/facade.cfc index a2228a3e..f3387c88 100644 --- a/framework/facade.cfc +++ b/framework/facade.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.2.0"; + variables._fw1_version = "4.3.0-SNAPSHOT"; /* Copyright (c) 2016-2018, Sean Corfield diff --git a/framework/ioc.cfc b/framework/ioc.cfc index 767559e9..0e945631 100644 --- a/framework/ioc.cfc +++ b/framework/ioc.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.2.0"; + variables._fw1_version = "4.3.0-SNAPSHOT"; variables._di1_version = variables._fw1_version; /* Copyright (c) 2010-2018, Sean Corfield diff --git a/framework/methodProxy.cfc b/framework/methodProxy.cfc index 905d362a..618d46db 100644 --- a/framework/methodProxy.cfc +++ b/framework/methodProxy.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.2.0"; + variables._fw1_version = "4.3.0-SNAPSHOT"; /* Copyright (c) 2018, Sean Corfield diff --git a/framework/one.cfc b/framework/one.cfc index f2354f5d..46130b61 100644 --- a/framework/one.cfc +++ b/framework/one.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.2.0"; + variables._fw1_version = "4.3.0-SNAPSHOT"; /* Copyright (c) 2009-2018, Sean Corfield, Marcin Szczepanski, Ryan Cogswell From 0ee40a0af8d84dc42ab1dd2e0e722e4e9da12158 Mon Sep 17 00:00:00 2001 From: Carl Von Stetten Date: Wed, 23 May 2018 13:45:10 -0700 Subject: [PATCH 02/19] Adds getSubsystemSection function Provides parity with the getSection function, but for subsystems. --- framework/one.cfc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/framework/one.cfc b/framework/one.cfc index 46130b61..13e11eb0 100644 --- a/framework/one.cfc +++ b/framework/one.cfc @@ -520,7 +520,6 @@ component { return listFirst( getSectionAndItem( action ), '.' ); } - /* * return the action without the subsystem */ @@ -592,6 +591,13 @@ component { return { }; } + /* + * return the subsytem and section part of the action + */ + public string function getSubsystemSection( string action = request.action ) { + return listFirst( getSubsystemSectionAndItem( action ), '.' ); + } + /* * return an action with all applicable parts (subsystem, section, and item) specified * using defaults from the configuration or request where appropriate From ebca7e773238ad8aa5ccd6559d536dbc2b29baf0 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 23 May 2018 14:17:33 -0700 Subject: [PATCH 03/19] Add first coreFunctions expectations --- tests/coreFunctions.cfc | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/coreFunctions.cfc diff --git a/tests/coreFunctions.cfc b/tests/coreFunctions.cfc new file mode 100644 index 00000000..3e2e9185 --- /dev/null +++ b/tests/coreFunctions.cfc @@ -0,0 +1,52 @@ +component extends=testbox.system.BaseSpec { + + function beforeAll() { + variables.fw = new framework.one(); + variables.fw.__config = __config; + } + + function afterAll() { + } + + function run( testResults, testBox ) { + + describe( "getDefaultSubsystem", function(){ + beforeEach(function(){ + structDelete( request, "subsystem" ); + structDelete( request, "section" ); + structAppend( variables.fw.__config(), { + usingSubsystems : false, + subsystemDelimiter : "@", + defaultSubsystem : "", + defaultSection : "section", + defaultItem : "item" + }); + }); + it( "should return empty string without subsystems", function(){ + expect( fw.getDefaultSubsystem() ).toBeEmpty(); + }); + it( "should return request subsystem, if present", function(){ + fw.__config().usingSubsystems = true; + request.subsystem = "requested"; + expect( fw.getDefaultSubsystem() ).toBe( "requested" ); + }); + it( "should return default subsystem, if request not present", function(){ + fw.__config().usingSubsystems = true; + fw.__config().defaultSubsystem = "subsystem"; + expect( fw.getDefaultSubsystem() ).toBe( "subsystem" ); + }); + it( "should throw an exception, if no default", function(){ + fw.__config().usingSubsystems = true; + expect(function(){ + return fw.getDefaultSubsystem() + }).toThrow( type = "FW1.subsystemNotSpecified" ); + }); + }); + + } + + function __config() { + return variables.framework; + } + +} From e64726d2d6adb6b05031515742e9bbed49e3d307 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 23 May 2018 14:39:12 -0700 Subject: [PATCH 04/19] Add ; that ACF requires --- tests/coreFunctions.cfc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/coreFunctions.cfc b/tests/coreFunctions.cfc index 3e2e9185..8f352cab 100644 --- a/tests/coreFunctions.cfc +++ b/tests/coreFunctions.cfc @@ -38,7 +38,7 @@ component extends=testbox.system.BaseSpec { it( "should throw an exception, if no default", function(){ fw.__config().usingSubsystems = true; expect(function(){ - return fw.getDefaultSubsystem() + return fw.getDefaultSubsystem(); }).toThrow( type = "FW1.subsystemNotSpecified" ); }); }); From 2ffa8afb96cfa5511c73f86d41769851af484ee5 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 23 May 2018 14:50:08 -0700 Subject: [PATCH 05/19] Pin on old version of TestBox until we can verify a later version runs on our matrix --- box.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/box.json b/box.json index e99eb470..98be81d1 100644 --- a/box.json +++ b/box.json @@ -55,7 +55,7 @@ ], "devDependencies":{ - "testbox":"^2.5.0+107" + "testbox":"2.5.0+107" }, "installPaths":{ "testbox":"testbox" From 4717d4e5f4f3fe1b758ed5d8e4e1e94378394672 Mon Sep 17 00:00:00 2001 From: Matthew J Clemente Date: Wed, 26 Sep 2018 09:09:52 -0400 Subject: [PATCH 06/19] Update decodeRequestBody to account for non-struct JSON --- framework/one.cfc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/framework/one.cfc b/framework/one.cfc index 13e11eb0..83f98c7d 100644 --- a/framework/one.cfc +++ b/framework/one.cfc @@ -2907,7 +2907,11 @@ component { case "text/json": try { var bodyStruct = read_json( body ); - structAppend( request.context, bodyStruct ); + if ( isStruct( bodyStruct ) ) { + structAppend( request.context, bodyStruct ); + } else { + request.context[ 'body' ] = bodyStruct; + } } catch ( any e ) { throw( type = "FW1.JSONPOST", message = "Content-Type implies JSON but could not deserialize body: " & e.message ); From fcdf1aa7df8c217f99d9803d45847ea93841c30b Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 15 Mar 2019 15:28:26 -0700 Subject: [PATCH 07/19] Remove waffle.io badge Waffle.io is closing down. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 30ccc2ef..e0e1ad4f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# FW/1 (Framework One) [![Build Status](https://travis-ci.org/framework-one/fw1.png)](https://travis-ci.org/framework-one/fw1) [![Stories in Ready](https://badge.waffle.io/framework-one/fw1.png?label=ready&title=Ready)](http://waffle.io/framework-one/fw1) [![Join the chat at https://gitter.im/framework-one/fw1](https://badges.gitter.im/framework-one/fw1.svg)](https://gitter.im/framework-one/fw1?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +# FW/1 (Framework One) [![Build Status](https://travis-ci.org/framework-one/fw1.png)](https://travis-ci.org/framework-one/fw1) [![Join the chat at https://gitter.im/framework-one/fw1](https://badges.gitter.im/framework-one/fw1.svg)](https://gitter.im/framework-one/fw1?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) This FW/1 directory is a complete web application and expects to live in its own webroot if you plan to run the applications within it. To use FW/1 in a separate From 05c52309920a2b72c790df6951a8cb3cc4b68a24 Mon Sep 17 00:00:00 2001 From: Joe Rinehart Date: Mon, 15 Apr 2019 08:42:24 -0400 Subject: [PATCH 08/19] Fixing lock check in setupSubsystemWrapper --- framework/one.cfc | 92 ++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/framework/one.cfc b/framework/one.cfc index 83f98c7d..0da4e64b 100644 --- a/framework/one.cfc +++ b/framework/one.cfc @@ -2989,52 +2989,54 @@ component { private void function setupSubsystemWrapper( string subsystem ) { if ( !len( subsystem ) ) return; - lock name="fw1_#application.applicationName#_#variables.framework.applicationKey#_subsysteminit_#subsystem#" type="exclusive" timeout="30" { - if ( !isSubsystemInitialized( subsystem ) ) { - getFw1App().subsystems[ subsystem ] = now(); - // Application.cfc does not get a subsystem bean factory! - if ( subsystem != variables.magicApplicationSubsystem ) { - var subsystemConfig = getSubsystemConfig( subsystem ); - var diEngine = structKeyExists( subsystemConfig, 'diEngine' ) ? subsystemConfig.diEngine : variables.framework.diEngine; - if ( diEngine == "di1" || diEngine == "aop1" ) { - // we can only reliably automate D/I engine setup for DI/1 / AOP/1 - var diLocations = structKeyExists( subsystemConfig, 'diLocations' ) ? subsystemConfig.diLocations : variables.framework.diLocations; - var locations = isSimpleValue( diLocations ) ? listToArray( diLocations ) : diLocations; - var subLocations = ""; - for ( var loc in locations ) { - var relLoc = trim( loc ); - // make a relative location: - if ( len( relLoc ) > 2 && left( relLoc, 2 ) == "./" ) { - relLoc = right( relLoc, len( relLoc ) - 2 ); - } else if ( len( relLoc ) > 1 && left( relLoc, 1 ) == "/" ) { - relLoc = right( relLoc, len( relLoc ) - 1 ); - } - if ( usingSubsystems() ) { - subLocations = listAppend( subLocations, variables.framework.base & subsystem & "/" & relLoc ); - } else { - subLocations = listAppend( subLocations, variables.framework.base & variables.framework.subsystemsFolder & "/" & subsystem & "/" & relLoc ); - } - } - if ( len( sublocations ) ) { - var diComponent = structKeyExists( subsystemConfig, 'diComponent' ) ? subsystemConfig : variables.framework.diComponent; - var cfg = { }; - if ( structKeyExists( subsystemConfig, 'diConfig' ) ) { - cfg = subsystemConfig.diConfig; - } else { - cfg = structCopy( variables.framework.diConfig ); - structDelete( cfg, 'loadListener' ); - } - cfg.noClojure = true; - var ioc = new "#diComponent#"( subLocations, cfg ); - ioc.setParent( getDefaultBeanFactory() ); - setSubsystemBeanFactory( subsystem, ioc ); - } - } - } + if ( !isSubsystemInitialized( subsystem ) ) { + lock name="fw1_#application.applicationName#_#variables.framework.applicationKey#_subsysteminit_#subsystem#" type="exclusive" timeout="30" { + if ( !isSubsystemInitialized( subsystem ) ) { + getFw1App().subsystems[ subsystem ] = now(); + // Application.cfc does not get a subsystem bean factory! + if ( subsystem != variables.magicApplicationSubsystem ) { + var subsystemConfig = getSubsystemConfig( subsystem ); + var diEngine = structKeyExists( subsystemConfig, 'diEngine' ) ? subsystemConfig.diEngine : variables.framework.diEngine; + if ( diEngine == "di1" || diEngine == "aop1" ) { + // we can only reliably automate D/I engine setup for DI/1 / AOP/1 + var diLocations = structKeyExists( subsystemConfig, 'diLocations' ) ? subsystemConfig.diLocations : variables.framework.diLocations; + var locations = isSimpleValue( diLocations ) ? listToArray( diLocations ) : diLocations; + var subLocations = ""; + for ( var loc in locations ) { + var relLoc = trim( loc ); + // make a relative location: + if ( len( relLoc ) > 2 && left( relLoc, 2 ) == "./" ) { + relLoc = right( relLoc, len( relLoc ) - 2 ); + } else if ( len( relLoc ) > 1 && left( relLoc, 1 ) == "/" ) { + relLoc = right( relLoc, len( relLoc ) - 1 ); + } + if ( usingSubsystems() ) { + subLocations = listAppend( subLocations, variables.framework.base & subsystem & "/" & relLoc ); + } else { + subLocations = listAppend( subLocations, variables.framework.base & variables.framework.subsystemsFolder & "/" & subsystem & "/" & relLoc ); + } + } + if ( len( sublocations ) ) { + var diComponent = structKeyExists( subsystemConfig, 'diComponent' ) ? subsystemConfig : variables.framework.diComponent; + var cfg = { }; + if ( structKeyExists( subsystemConfig, 'diConfig' ) ) { + cfg = subsystemConfig.diConfig; + } else { + cfg = structCopy( variables.framework.diConfig ); + structDelete( cfg, 'loadListener' ); + } + cfg.noClojure = true; + var ioc = new "#diComponent#"( subLocations, cfg ); + ioc.setParent( getDefaultBeanFactory() ); + setSubsystemBeanFactory( subsystem, ioc ); + } + } + } - internalFrameworkTrace( 'setupSubsystem() called', subsystem ); - setupSubsystem( subsystem ); - } + internalFrameworkTrace( 'setupSubsystem() called', subsystem ); + setupSubsystem( subsystem ); + } + } } } From 0a9cddc866b3f51bd5271bf73036a41d16fe569d Mon Sep 17 00:00:00 2001 From: Joe Rinehart Date: Mon, 15 Apr 2019 08:45:13 -0400 Subject: [PATCH 09/19] Fixing tabs to be spaces --- framework/one.cfc | 92 +++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/framework/one.cfc b/framework/one.cfc index 0da4e64b..82097739 100644 --- a/framework/one.cfc +++ b/framework/one.cfc @@ -2990,53 +2990,53 @@ component { private void function setupSubsystemWrapper( string subsystem ) { if ( !len( subsystem ) ) return; if ( !isSubsystemInitialized( subsystem ) ) { - lock name="fw1_#application.applicationName#_#variables.framework.applicationKey#_subsysteminit_#subsystem#" type="exclusive" timeout="30" { - if ( !isSubsystemInitialized( subsystem ) ) { - getFw1App().subsystems[ subsystem ] = now(); - // Application.cfc does not get a subsystem bean factory! - if ( subsystem != variables.magicApplicationSubsystem ) { - var subsystemConfig = getSubsystemConfig( subsystem ); - var diEngine = structKeyExists( subsystemConfig, 'diEngine' ) ? subsystemConfig.diEngine : variables.framework.diEngine; - if ( diEngine == "di1" || diEngine == "aop1" ) { - // we can only reliably automate D/I engine setup for DI/1 / AOP/1 - var diLocations = structKeyExists( subsystemConfig, 'diLocations' ) ? subsystemConfig.diLocations : variables.framework.diLocations; - var locations = isSimpleValue( diLocations ) ? listToArray( diLocations ) : diLocations; - var subLocations = ""; - for ( var loc in locations ) { - var relLoc = trim( loc ); - // make a relative location: - if ( len( relLoc ) > 2 && left( relLoc, 2 ) == "./" ) { - relLoc = right( relLoc, len( relLoc ) - 2 ); - } else if ( len( relLoc ) > 1 && left( relLoc, 1 ) == "/" ) { - relLoc = right( relLoc, len( relLoc ) - 1 ); - } - if ( usingSubsystems() ) { - subLocations = listAppend( subLocations, variables.framework.base & subsystem & "/" & relLoc ); - } else { - subLocations = listAppend( subLocations, variables.framework.base & variables.framework.subsystemsFolder & "/" & subsystem & "/" & relLoc ); - } - } - if ( len( sublocations ) ) { - var diComponent = structKeyExists( subsystemConfig, 'diComponent' ) ? subsystemConfig : variables.framework.diComponent; - var cfg = { }; - if ( structKeyExists( subsystemConfig, 'diConfig' ) ) { - cfg = subsystemConfig.diConfig; - } else { - cfg = structCopy( variables.framework.diConfig ); - structDelete( cfg, 'loadListener' ); - } - cfg.noClojure = true; - var ioc = new "#diComponent#"( subLocations, cfg ); - ioc.setParent( getDefaultBeanFactory() ); - setSubsystemBeanFactory( subsystem, ioc ); - } - } - } + lock name="fw1_#application.applicationName#_#variables.framework.applicationKey#_subsysteminit_#subsystem#" type="exclusive" timeout="30" { + if ( !isSubsystemInitialized( subsystem ) ) { + getFw1App().subsystems[ subsystem ] = now(); + // Application.cfc does not get a subsystem bean factory! + if ( subsystem != variables.magicApplicationSubsystem ) { + var subsystemConfig = getSubsystemConfig( subsystem ); + var diEngine = structKeyExists( subsystemConfig, 'diEngine' ) ? subsystemConfig.diEngine : variables.framework.diEngine; + if ( diEngine == "di1" || diEngine == "aop1" ) { + // we can only reliably automate D/I engine setup for DI/1 / AOP/1 + var diLocations = structKeyExists( subsystemConfig, 'diLocations' ) ? subsystemConfig.diLocations : variables.framework.diLocations; + var locations = isSimpleValue( diLocations ) ? listToArray( diLocations ) : diLocations; + var subLocations = ""; + for ( var loc in locations ) { + var relLoc = trim( loc ); + // make a relative location: + if ( len( relLoc ) > 2 && left( relLoc, 2 ) == "./" ) { + relLoc = right( relLoc, len( relLoc ) - 2 ); + } else if ( len( relLoc ) > 1 && left( relLoc, 1 ) == "/" ) { + relLoc = right( relLoc, len( relLoc ) - 1 ); + } + if ( usingSubsystems() ) { + subLocations = listAppend( subLocations, variables.framework.base & subsystem & "/" & relLoc ); + } else { + subLocations = listAppend( subLocations, variables.framework.base & variables.framework.subsystemsFolder & "/" & subsystem & "/" & relLoc ); + } + } + if ( len( sublocations ) ) { + var diComponent = structKeyExists( subsystemConfig, 'diComponent' ) ? subsystemConfig : variables.framework.diComponent; + var cfg = { }; + if ( structKeyExists( subsystemConfig, 'diConfig' ) ) { + cfg = subsystemConfig.diConfig; + } else { + cfg = structCopy( variables.framework.diConfig ); + structDelete( cfg, 'loadListener' ); + } + cfg.noClojure = true; + var ioc = new "#diComponent#"( subLocations, cfg ); + ioc.setParent( getDefaultBeanFactory() ); + setSubsystemBeanFactory( subsystem, ioc ); + } + } + } - internalFrameworkTrace( 'setupSubsystem() called', subsystem ); - setupSubsystem( subsystem ); - } - } + internalFrameworkTrace( 'setupSubsystem() called', subsystem ); + setupSubsystem( subsystem ); + } + } } } From f5f6d855168f03f3ea95f22bb1bc3831f313852a Mon Sep 17 00:00:00 2001 From: Steven Neiland Date: Sun, 19 May 2019 15:15:39 -0400 Subject: [PATCH 10/19] Issue-509: Add option to ignore missing bean properties on injection --- framework/ioc.cfc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/framework/ioc.cfc b/framework/ioc.cfc index 0e945631..5316427a 100644 --- a/framework/ioc.cfc +++ b/framework/ioc.cfc @@ -291,18 +291,20 @@ component { } - // given a bean (by name, by type or by value), call the named - // setters with the specified property values - public any function injectProperties( any bean, struct properties ) { + /* + * @hint Given a bean (by name, by type or by value), call the named setters with the specified property values + * @ignoreMissing When set verify that the setter to be called exists and skip if missing, otherwise throws an error + */ + public any function injectProperties( any bean, struct properties, boolean ignoreMissing=false ) { if ( isSimpleValue( bean ) ) { if ( containsBean( bean ) ) bean = getBean( bean ); else bean = construct( bean ); } for ( var property in properties ) { - if ( !isNull( properties[ property ] ) ) { + if ( !isNull( properties[ property ] ) && (!ignoreMissing || structKeyExists( bean, "set#property#" ) ) ){ var args = { }; args[ property ] = properties[ property ]; - invoke( bean, "set#property#", args ); + evaluate( 'bean.set#property#( argumentCollection = args )' ); } } return bean; From a75b9bfb47ee9a36e007939e210ad4f686055740 Mon Sep 17 00:00:00 2001 From: John Berquist Date: Wed, 15 Jan 2020 12:31:54 -0800 Subject: [PATCH 11/19] Remove locking from framework one global controller retrieval --- framework/one.cfc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/framework/one.cfc b/framework/one.cfc index 82097739..93064c25 100644 --- a/framework/one.cfc +++ b/framework/one.cfc @@ -1831,18 +1831,21 @@ component { var controllersSlash = variables.framework.controllersFolder & '/'; var controllersDot = variables.framework.controllersFolder & '.'; // per #310 we no longer cache the Application controller since it is new on each request - if ( !structKeyExists( cache.controllers, componentKey ) || section == variables.magicApplicationController ) { + if ( section == variables.magicApplicationController ) { + if ( hasDefaultBeanFactory() ) { + autowire( this, getDefaultBeanFactory() ); + } + return this; + } + if ( !structKeyExists( cache.controllers, componentKey ) ) { lock name="fw1_#application.applicationName#_#variables.framework.applicationKey#_#componentKey#" type="exclusive" timeout="30" { - if ( !structKeyExists( cache.controllers, componentKey ) || section == variables.magicApplicationController ) { + if ( !structKeyExists( cache.controllers, componentKey ) ) { if ( hasSubsystemBeanFactory( subsystem ) && getSubsystemBeanFactory( subsystem ).containsBean( beanName ) ) { cfc = getSubsystemBeanFactory( subsystem ).getBean( beanName ); } else if ( !usingSubsystems() && hasDefaultBeanFactory() && getDefaultBeanFactory().containsBean( beanName ) ) { cfc = getDefaultBeanFactory().getBean( beanName ); } else { - if ( section == variables.magicApplicationController ) { - // treat this (Application.cfc) as a controller: - cfc = this; - } else if ( cachedFileExists( cfcFilePath( request.cfcbase ) & subsystemDir & controllersSlash & section & '.cfc' ) ) { + if ( cachedFileExists( cfcFilePath( request.cfcbase ) & subsystemDir & controllersSlash & section & '.cfc' ) ) { // we call createObject() rather than new so we can control initialization: if ( request.cfcbase == '' ) { cfc = createObject( 'component', subsystemDot & controllersDot & section ); From b781ad2811699fd06791a3e59bcce15fa51579b7 Mon Sep 17 00:00:00 2001 From: Steven Neiland Date: Sun, 9 Feb 2020 13:18:10 -0500 Subject: [PATCH 12/19] Revert to using invoke, add tests --- framework/ioc.cfc | 2 +- tests/model/beans/person.cfc | 9 ++++++++ tests/specs/injectPropertiesTest.cfc | 31 ++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/model/beans/person.cfc create mode 100644 tests/specs/injectPropertiesTest.cfc diff --git a/framework/ioc.cfc b/framework/ioc.cfc index 5316427a..11e73eff 100644 --- a/framework/ioc.cfc +++ b/framework/ioc.cfc @@ -304,7 +304,7 @@ component { if ( !isNull( properties[ property ] ) && (!ignoreMissing || structKeyExists( bean, "set#property#" ) ) ){ var args = { }; args[ property ] = properties[ property ]; - evaluate( 'bean.set#property#( argumentCollection = args )' ); + invoke( bean, "set#property#", args ); } } return bean; diff --git a/tests/model/beans/person.cfc b/tests/model/beans/person.cfc new file mode 100644 index 00000000..7e83e014 --- /dev/null +++ b/tests/model/beans/person.cfc @@ -0,0 +1,9 @@ +component accessors="true" { + + property name="firstname" default=""; + property name="lastname" default=""; + + function init(){ + return this; + } +} \ No newline at end of file diff --git a/tests/specs/injectPropertiesTest.cfc b/tests/specs/injectPropertiesTest.cfc new file mode 100644 index 00000000..c91d5b06 --- /dev/null +++ b/tests/specs/injectPropertiesTest.cfc @@ -0,0 +1,31 @@ +component extends="testbox.system.BaseSpec" { + // executes before all suites + function beforeAll(){ + ioc = new framework.ioc( "" ); + ioc2 = new framework.ioc( "/tests/model" ); + } + + // executes after all suites + function afterAll(){} + + // All suites go in here + function run( testResults, testBox ){ + describe("A bean injected with properties", function(){ + it("errors on undefined properties in the bean", function(){ + var bean = new tests.model.beans.person(); + + expect( function(){ + ioc.injectProperties( bean=bean, properties= { firstName="steven", thirdName="fail"} ); + }).toThrow(); + }); + + it("does not error on undefined properties in the bean when ignoreMissing is specified", function(){ + var bean = new tests.model.beans.person(); + + ioc.injectProperties( bean=bean, properties= { firstName="steven", thirdName="fail"}, ignoreMissing=true); + expect( bean.getFirstName() ).toBe("steven"); + }); + + }); + } +} From e160e75ac05b9a02f93de1451ed26e9d2566acc9 Mon Sep 17 00:00:00 2001 From: Steven Neiland Date: Sun, 9 Feb 2020 14:31:18 -0500 Subject: [PATCH 13/19] Add adobe 2018 and specify distribution --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 21bf0d45..79a3d6fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,12 @@ language: java - sudo: required +dist: trusty env: matrix: - - ENGINE=lucee@4.5 - ENGINE=lucee@5 + - ENGINE=lucee@4.5 + - ENGINE=adobe@2018 - ENGINE=adobe@2016 - ENGINE=adobe@11 - ENGINE=adobe@10 From ef81c474bc57d8f7b5ef0771551792c34adb9c76 Mon Sep 17 00:00:00 2001 From: Nate Mills Date: Mon, 20 Jul 2020 18:06:05 -0700 Subject: [PATCH 14/19] Fix for #518 (#519) * Adding TestBox tests for issue 518 * Updating aop.getAliases function to use dottedPath instead of beanName. * Updating ioc.variables.beanInfo to not include the beanName, if there are 2 different beans with the same name. * Removing duplicate beans from beanNames array. * Removing whitespace changes in file with only whitespace changes. --- framework/aop.cfc | 30 +- framework/ioc.cfc | 25 +- tests/CombinedInterceptorsTestIssue518.cfc | 289 ++++++++++++++++++ tests/issue518/Log.cfc | 11 + tests/issue518/daos/advReverse.cfc | 46 +++ .../interceptors/BasicInterceptor.cfc.test | 39 +++ .../interceptors/aop/AfterInterceptor.cfc | 18 ++ .../interceptors/aop/AroundInterceptor.cfc | 27 ++ .../interceptors/aop/BeforeInterceptor.cfc | 20 ++ .../interceptors/aop/ErrorInterceptor.cfc | 12 + .../issue518/interceptors/aop/interceptor.cfc | 8 + .../issue518/interceptors/example/Logger.cfc | 14 + tests/issue518/service.cfc | 15 + tests/issue518/services/Reverse.cfc | 22 ++ tests/issue518/services/advReverse.cfc | 46 +++ tests/issue518/services/array.cfc | 9 + tests/issue518/stackLog.cfc | 17 ++ tests/issue518/string.cfc | 10 + 18 files changed, 632 insertions(+), 26 deletions(-) create mode 100644 tests/CombinedInterceptorsTestIssue518.cfc create mode 100644 tests/issue518/Log.cfc create mode 100644 tests/issue518/daos/advReverse.cfc create mode 100644 tests/issue518/interceptors/BasicInterceptor.cfc.test create mode 100644 tests/issue518/interceptors/aop/AfterInterceptor.cfc create mode 100644 tests/issue518/interceptors/aop/AroundInterceptor.cfc create mode 100644 tests/issue518/interceptors/aop/BeforeInterceptor.cfc create mode 100644 tests/issue518/interceptors/aop/ErrorInterceptor.cfc create mode 100644 tests/issue518/interceptors/aop/interceptor.cfc create mode 100644 tests/issue518/interceptors/example/Logger.cfc create mode 100644 tests/issue518/service.cfc create mode 100644 tests/issue518/services/Reverse.cfc create mode 100644 tests/issue518/services/advReverse.cfc create mode 100644 tests/issue518/services/array.cfc create mode 100644 tests/issue518/stackLog.cfc create mode 100644 tests/issue518/string.cfc diff --git a/framework/aop.cfc b/framework/aop.cfc index 95991adf..6653124a 100644 --- a/framework/aop.cfc +++ b/framework/aop.cfc @@ -119,7 +119,7 @@ component extends="framework.ioc" { { // build the interceptor array: var beanName = listLast(arguments.dottedPath, "."); - var beanNames = getAliases(beanName); + var beanNames = getAliases(arguments.dottedPath); var beanTypes = ""; var interceptDefinition = ""; var interceptedBeanName = ""; @@ -128,6 +128,8 @@ component extends="framework.ioc" { arrayPrepend(beanNames, beanName); + // Removing duplicate beanNames + beanNames = listToArray(listRemoveDuplicates(arrayToList(beanNames),",",true) ); // Grab all name based interceptors that match. for (interceptedBeanName in beanNames) @@ -185,7 +187,7 @@ component extends="framework.ioc" { var interceptedBeanName = ""; var interceptorDefinition = {}; var beanName = listLast(arguments.dottedPath, "."); - var beanNames = getAliases(beanName); + var beanNames = getAliases(arguments.dottedPath); var beanTypes = ""; @@ -234,29 +236,21 @@ component extends="framework.ioc" { } - /** Finds all aliases for the given beanName. */ - private array function getAliases(string beanName) + /** Finds all aliases for the given dottedPath. */ + private array function getAliases(string dottedPath) { var aliases = []; var beanData = ""; var key = ""; - - if (structKeyExists(variables.beanInfo, arguments.beanName)) + for (key in variables.beanInfo) { - beanData = variables.beanInfo[arguments.beanName]; - - for (key in variables.beanInfo) + // Same cfc dotted path, must be an alias. + if ( + structKeyExists(variables.beanInfo[key], "cfc") && + variables.beanInfo[key].cfc == arguments.dottedPath) { - // Same cfc dotted path, must be an alias. - if ( - key != arguments.beanName && - structKeyExists(variables.beanInfo[key], "cfc") && - structKeyExists(variables.beanInfo[arguments.beanName], "cfc") && - variables.beanInfo[key].cfc == variables.beanInfo[arguments.beanName].cfc) - { - arrayAppend(aliases, key); - } + arrayAppend(aliases, key); } } diff --git a/framework/ioc.cfc b/framework/ioc.cfc index 11e73eff..e995e756 100644 --- a/framework/ioc.cfc +++ b/framework/ioc.cfc @@ -535,6 +535,7 @@ component { } catch ( any e ) { // assume bad path - ignore it, cfcs is empty list } + local.beansWithDuplicates = ""; for ( var cfcOSPath in cfcs ) { var cfcPath = replace( cfcOSPath, chr(92), '/', 'all' ); // watch out for excluded paths: @@ -561,18 +562,26 @@ component { if ( structKeyExists( metadata.metadata, "type" ) && metadata.metadata.type == "interface" ) { continue; } - if ( structKeyExists( variables.beanInfo, beanName ) ) { - if ( variables.config.omitDirectoryAliases ) { - throw '#beanName# is not unique (and omitDirectoryAliases is true)'; + + if ( variables.config.omitDirectoryAliases ) { + if ( structKeyExists( variables.beanInfo, beanName ) ) { + throw '#beanName# is not unique'; } - structDelete( variables.beanInfo, beanName ); - variables.beanInfo[ beanName & singleDir ] = metadata; - } else { variables.beanInfo[ beanName ] = metadata; - if ( !variables.config.omitDirectoryAliases ) { - variables.beanInfo[ beanName & singleDir ] = metadata; + } else { + if ( listFindNoCase(local.beansWithDuplicates, beanName) ) {} + else if ( structKeyExists( variables.beanInfo, beanName ) ) { + structDelete( variables.beanInfo, beanName ); + local.beansWithDuplicates = listAppend(local.beansWithDuplicates, beanName); + } else { + variables.beanInfo[ beanName ] = metadata; + } + if ( structKeyExists( variables.beanInfo, beanName & singleDir ) ) { + throw '#beanName & singleDir# is not unique'; } + variables.beanInfo[ beanName & singleDir ] = metadata; } + } catch ( any e ) { // wrap the exception so we can add bean name for debugging // this trades off any stack trace information for the bean name but diff --git a/tests/CombinedInterceptorsTestIssue518.cfc b/tests/CombinedInterceptorsTestIssue518.cfc new file mode 100644 index 00000000..789c8f26 --- /dev/null +++ b/tests/CombinedInterceptorsTestIssue518.cfc @@ -0,0 +1,289 @@ +component extends="mxunit.framework.TestCase" { + + function TestBeforeAroundAfterInterception() { + //Putting it all together What happens when you call all of them? + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {}); + //add an Interceptor + + bf.intercept("ReverseService", "BeforeInterceptor"); + bf.intercept("ReverseService", "AroundInterceptor"); + bf.intercept("ReverseService", "AfterInterceptor"); + + rs = bf.getBean("ReverseService"); + result = rs.doReverse("Hello!"); + + + AssertEquals("around," & Reverse("beforeHello!") & ",around", result); + AssertEquals(4, arrayLen(request.callstack)); + AssertEquals("before,around,doReverse,after", arrayToList(request.callstack)); + } + + + function TestInitMethods() { + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {initMethod = "configure"}); + + bf.intercept("advReverse", "BeforeInterceptor"); + + rs = bf.getBean("advReverseService"); + result = rs.doWrap("Hello!"); + + // First test does not intercept the (init, set..., or initMethod) methods. + AssertEquals(9, arrayLen(request.callstack)); + AssertEquals( "init,setStackLog,configure,before,dowrap,before,dofront,before,dorear", + arrayToList(request.callstack), + "This test shows that the (init, set..., and configure) methods are by default ignored."); + + + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {initMethod = "configure"}); + + bf.intercept("advReverse", "BeforeInterceptor", "init,configure,setStackLog,doWrap"); + + rs = bf.getBean("advReverseService"); + result = rs.doWrap("Hello!"); + + // Explicitly intercept the (init, set..., or initMethod) methods. + AssertEquals(10, arrayLen(request.callstack)); + AssertEquals( "before,init,before,setStackLog,before,configure,before,dowrap,dofront,dorear", + arrayToList(request.callstack), + "This test shows that the (init, set..., and configure) methods can be explicitly intercepted."); + } + + + function TestInterceptOnRegex() { + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {initMethod = "configure"}); + + //add an Interceptor + bf.intercept("/^reverse.*$/", "BeforeInterceptor"); + + ars = bf.getBean("advReverseService"); + rs = bf.getBean("reverse"); + as = bf.getBean("array"); + + + result = ars.doWrap("Hello!"); + result2 = rs.doReverse("Hello!"); + result3 = as.doListToArray("dog,cat,mouse"); + + + AssertEquals("front-Hello!-rear", result); + AssertEquals("!olleHerofeb", result2); + AssertTrue(isArray(result3)); + AssertEquals("dog,cat,mouse", arrayToList(result3)); + + AssertEquals(9, arrayLen(request.callstack)); + AssertEquals("init,setStackLog,configure,doWrap,doFront,doRear,before,doReverse,doListToArray", arrayToList(request.callstack)); + } + + + function TestInterceptOnType() { + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {initMethod = "configure"}); + + //add an Interceptor + bf.interceptByType("string", "BeforeInterceptor", "doReverse,doForward,doWrap"); + + ars = bf.getBean("advReverseService"); + rs = bf.getBean("reverse"); + as = bf.getBean("array"); + + + result = ars.doWrap("Hello!"); + result2 = rs.doReverse("Hello!"); + result3 = as.doListToArray("dog,cat,mouse"); + + + AssertEquals("front-beforeHello!-rear", result); + AssertEquals("!olleHerofeb", result2); + AssertTrue(isArray(result3)); + AssertEquals("dog,cat,mouse", arrayToList(result3)); + + AssertEquals(10, arrayLen(request.callstack)); + AssertEquals("init,setStackLog,configure,before,doWrap,doFront,doRear,before,doReverse,doListToArray", arrayToList(request.callstack)); + } + + + function TestMultipleBeforeInterceptions() { + //Multiple Before Advisors + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {}); + + //Need to create different Before interceptors + bf.declareBean("BeforeInterceptorA", "tests.issue518.interceptors.aop.BeforeInterceptor", true, {name = "beforeA"}); + bf.declareBean("BeforeInterceptorB", "tests.issue518.interceptors.aop.BeforeInterceptor", true, {name = "beforeB"}); + bf.declareBean("BeforeInterceptorC", "tests.issue518.interceptors.aop.BeforeInterceptor", true, {name = "beforeC"}); + + bf.intercept("ReverseService", "BeforeInterceptorA"); + bf.intercept("ReverseService", "BeforeInterceptorB"); + bf.intercept("ReverseService", "BeforeInterceptorC"); + + rs = bf.getBean("ReverseService"); + result = rs.doReverse("Hello!"); + + AssertEquals(reverse("beforebeforebeforeHello!"), result); + AssertEquals(4, arrayLen(request.callstack)); + AssertEquals("beforeA,beforeB,beforeC,doReverse", arrayToList(request.callstack)); + } + + + function TestMultipleAfterInterceptors() { + //Multiple After Advisors + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {}); + + //Need to create different After interceptors + bf.declareBean("AfterInterceptorA", "tests.issue518.interceptors.aop.AfterInterceptor", true, {name = "afterA"}); + bf.declareBean("AfterInterceptorB", "tests.issue518.interceptors.aop.AfterInterceptor", true, {name = "afterAlterResultB"}); + bf.declareBean("AfterInterceptorC", "tests.issue518.interceptors.aop.AfterInterceptor", true, {name = "afterC"}); + + + bf.intercept("ReverseService", "AfterInterceptorA"); + bf.intercept("ReverseService", "AfterInterceptorB"); + bf.intercept("ReverseService", "AfterInterceptorC"); + + + rs = bf.getBean("ReverseService"); + result = rs.doReverse("Hello!"); + + AssertEquals(reverse("Hello!") & ",afterAlterResultB", result); + AssertEquals(4, arrayLen(request.callstack)); + AssertEquals("doReverse,afterA,afterAlterResultB,afterC", arrayToList(request.callstack)); + } + + + function TestMultipleAroundInterceptors() { + //Multiple Around Advisors + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {}); + + + //Need to create different After interceptors + bf.declareBean("AroundInterceptorA", "tests.issue518.interceptors.aop.AroundInterceptor", true, {name = "aroundA"}); + bf.declareBean("AroundInterceptorB", "tests.issue518.interceptors.aop.AroundInterceptor", true, {name = "aroundB"}); + bf.declareBean("AroundInterceptorC", "tests.issue518.interceptors.aop.AroundInterceptor", true, {name = "aroundC"}); + + + bf.intercept("ReverseService", "AroundInterceptorA"); + bf.intercept("ReverseService", "AroundInterceptorB"); + bf.intercept("ReverseService", "AroundInterceptorC"); + rs = bf.getBean("ReverseService"); + + result = rs.doReverse("Hello!"); + + AssertEquals("aroundA,aroundB,aroundC," & reverse("Hello!") & ",aroundC,aroundB,aroundA", result); + AssertEquals(4, arrayLen(request.callstack)); + AssertEquals("aroundA,aroundB,aroundC,doReverse", arrayToList(request.callstack)); + } + + + function TestMethodMatches() { + bf = new framework.ioc('/tests/issue518', {}); + rs = bf.getBean("Reverse"); + + proxy = new framework.beanProxy(rs, [], {}); + makePublic( proxy, "methodMatches" ); + + AssertFalse(proxy.methodMatches("doForward", "doReverse")); + AssertTrue(proxy.methodMatches("doForward", "")); + AssertTrue(proxy.methodMatches("doForward", "*")); + AssertFalse(proxy.methodMatches("doForward", "doReverse,")); + AssertTrue(proxy.methodMatches("doForward", "doReverse,doForward")); + } + + + function TestNamedMethodInterceptions() { + //Named Method Interceptions + + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {}); + //add an Interceptor + bf.intercept("ReverseService", "BeforeInterceptor", "doReverse"); + + rs = bf.getBean("ReverseService"); + + // This should be intercepted. + result = rs.doReverse("Hello!"); + + // This shoud not be intercepted. + result2 = rs.doForward("Hello!"); + + + // This should be intercepted. + result3 = rs.doReverse("Hello!"); + + AssertEquals(reverse("beforeHello!"), result); + AssertEquals("hello!", result2); + AssertEquals(reverse("beforeHello!"), result3); + AssertEquals(5, arrayLen(request.callstack)); + AssertEquals("before,doReverse,doForward,before,doReverse", arrayToList(request.callstack)); + } + + + function TestOnErrorInterceptors() { + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {}); + rs = bf.getBean("ReverseService"); + result2 = rs.doForward("Hello!"); + + + AssertEquals("Hello!", result2); + AssertEquals(1, arrayLen(request.callstack)); + AssertEquals("doForward", arrayToList(request.callstack)); + + + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {}); + //add an Interceptor + bf.intercept("ReverseService", "ErrorInterceptor", "throwError"); + + rs = bf.getBean("ReverseService"); + rs.throwError(); + + AssertEquals(2, arrayLen(request.callstack)); + AssertEquals("throwError,onError", arrayToList(request.callstack)); + } + + + function TestPrivateMethodInterceptors() { + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {initMethod = "configure"}); + + //add an Interceptor + bf.intercept("advReverseService", "BeforeInterceptor", "doFront"); + + rs = bf.getBean("advReverseService"); + + result = rs.doWrap("Hello!"); + + AssertEquals("front-beforeHello!-rear", result); + AssertEquals(7, arrayLen(request.callstack)); + AssertEquals("init,setStackLog,configure,doWrap,before,doFront,doRear", arrayToList(request.callstack)); + } + + + function TestSingleInterceptorOnMultipleObjects() { + //Multiple Around Advisors + request.callstack = []; //reset + bf = new framework.aop('/tests/issue518', {}); + + + //Need to create different After interceptors + bf.declareBean("AroundInterceptorA", "tests.issue518.interceptors.aop.AroundInterceptor", true, {name = "aroundA"}); + + + bf.intercept("advReverse", "AroundInterceptorA", "doWrap"); + bf.intercept("ReverseService", "AroundInterceptorA", "doReverse"); + + rs = bf.getBean("ReverseService"); + ars = bf.getBean("advReverseService"); + + result = ars.doWrap(rs.doReverse("Hello!")); + + AssertEquals("aroundA,front-aroundA," & reverse("Hello!") & ",aroundA-rear,aroundA", result); + AssertEquals(8, arrayLen(request.callstack)); + AssertEquals("init,setStackLog,aroundA,doReverse,aroundA,doWrap,doFront,doRear", arrayToList(request.callstack)); + } +} diff --git a/tests/issue518/Log.cfc b/tests/issue518/Log.cfc new file mode 100644 index 00000000..92f22c9d --- /dev/null +++ b/tests/issue518/Log.cfc @@ -0,0 +1,11 @@ +component{ + + function init(){ + return this; + } + + function logMessage(message, severity="information"){ + writelog(message, severity); + } + +} \ No newline at end of file diff --git a/tests/issue518/daos/advReverse.cfc b/tests/issue518/daos/advReverse.cfc new file mode 100644 index 00000000..cfe9c8b5 --- /dev/null +++ b/tests/issue518/daos/advReverse.cfc @@ -0,0 +1,46 @@ +component displayname="advReverseService" extends="tests.issue518.services.Reverse" accessors="true" output="false" { + + + // PUBLIC METHODS + public function configure() { + getStackLog().log("wrong-configure"); + return this; + } + + + public function doWrap(string input) { + getStackLog().log("wrong-doWrap"); + return doRear(doFront(arguments.input)); + } + + + public function init() { + // stackLog does not exist at this point. + arrayAppend(request.callStack, "wrong-init"); + + return super.init(); + } + + + public function setStackLog(any stackLog) { + // stackLog does not exist at this point. + arrayAppend(request.callStack, "wrong-setStackLog"); + + variables.stackLog = arguments.stackLog; + } + + + + + // PRIVATE METHODS + private function doFront(string input) { + getStackLog().log("wrong-doFront"); + return "front-" & arguments.input; + } + + + private function doRear(string input) { + getStackLog().log("wrong-doRear"); + return arguments.input & "-rear"; + } +} diff --git a/tests/issue518/interceptors/BasicInterceptor.cfc.test b/tests/issue518/interceptors/BasicInterceptor.cfc.test new file mode 100644 index 00000000..9573ff5c --- /dev/null +++ b/tests/issue518/interceptors/BasicInterceptor.cfc.test @@ -0,0 +1,39 @@ +/** +* +* @author @markdrew +* @description This is a demo interceptor +* +*/ +component output="false" displayname="BasicInterceptor" { + + this.name = "A"; + + public function init(name="A"){ + this.name = name; + return this; + } + + + //basically it's onMissingMethod! + function before(method, args, target){ + param name="request.callstack" default="#[]#"; + + arguments.args.1 = "before" & arguments.args.1 + } + + function after(){ + param name="request.callstack" default="#[]#"; + arguments.result = arguments.result & "after"; + + } + + function onMethod(){ + param name="request.callstack" default="#[]#"; + dump(var=arguments, label="onMethod"); + } + + function onError(){ + param name="request.callstack" default="#[]#"; + dump(var=arguments, label="onError"); + } +} \ No newline at end of file diff --git a/tests/issue518/interceptors/aop/AfterInterceptor.cfc b/tests/issue518/interceptors/aop/AfterInterceptor.cfc new file mode 100644 index 00000000..1afc9395 --- /dev/null +++ b/tests/issue518/interceptors/aop/AfterInterceptor.cfc @@ -0,0 +1,18 @@ +component displayname="AfterInterceptor" extends="interceptor" accessors="true" output="false" { + + + function init(name="after") { + this.name=name; + } + + + function after(target, method, args, result) { + getStackLog().log(this.name); + + // Demonstrate that we can alter the result. + if (findNoCase("alter", this.name) && structKeyExists(arguments, "result") && !isNull(arguments.result)) + { + return arguments.result & "," & this.name; + } + } +} \ No newline at end of file diff --git a/tests/issue518/interceptors/aop/AroundInterceptor.cfc b/tests/issue518/interceptors/aop/AroundInterceptor.cfc new file mode 100644 index 00000000..e4ad95fa --- /dev/null +++ b/tests/issue518/interceptors/aop/AroundInterceptor.cfc @@ -0,0 +1,27 @@ +component displayname="AroundInterceptor" extends="interceptor" accessors="true" output="false" { + + + function init(name="around") { + this.name=name; + } + + + function around(target, method, args) { + getStackLog().log(this.name); + + local.result = proceed(arguments.target, arguments.method, arguments.args); + + // This runs on 'set...' methods as well for properties. Limit to simple result calls. + if (structKeyExists(local, "result") && !isNull(local.result) && isSimpleValue(local.result)) + { + return this.name & "," & local.result & "," & this.name; + } + else + { + writeDump(var = isNull(arguments.target)); + writeDump(var = isNull(arguments.target.getStackLog())); + writeDump(var = arguments.method); + writeDump(var = structKeyList(arguments.target), abort = true); + } + } +} diff --git a/tests/issue518/interceptors/aop/BeforeInterceptor.cfc b/tests/issue518/interceptors/aop/BeforeInterceptor.cfc new file mode 100644 index 00000000..f3099685 --- /dev/null +++ b/tests/issue518/interceptors/aop/BeforeInterceptor.cfc @@ -0,0 +1,20 @@ +component displayname="BeforeInterceptor" extends="interceptor" accessors="true" output="false" { + + + function init(name="before") { + this.name=name; + } + + + function before(target, method, args) { + getStackLog().log(this.name); + + translateArgs(target, method, args, true); + + // Demonstrate that we can alter the arguments before the method call. + if (structKeyExists(arguments.args, "input")) + { + arguments.args.input = "before" & arguments.args.input; + } + } +} \ No newline at end of file diff --git a/tests/issue518/interceptors/aop/ErrorInterceptor.cfc b/tests/issue518/interceptors/aop/ErrorInterceptor.cfc new file mode 100644 index 00000000..f51908db --- /dev/null +++ b/tests/issue518/interceptors/aop/ErrorInterceptor.cfc @@ -0,0 +1,12 @@ +component output="false" { + + this.name = "onError"; + function init(name="onError"){ + this.name=name; + } + + function onError(method,args,target, error){ + ArrayAppend(request.callstack, this.name); + + } +} \ No newline at end of file diff --git a/tests/issue518/interceptors/aop/interceptor.cfc b/tests/issue518/interceptors/aop/interceptor.cfc new file mode 100644 index 00000000..a1f987a0 --- /dev/null +++ b/tests/issue518/interceptors/aop/interceptor.cfc @@ -0,0 +1,8 @@ +component displayname="interceptor" accessors="true" output="false" { + + + property name="stackLog"; + + + this.name = ""; +} diff --git a/tests/issue518/interceptors/example/Logger.cfc b/tests/issue518/interceptors/example/Logger.cfc new file mode 100644 index 00000000..098be17e --- /dev/null +++ b/tests/issue518/interceptors/example/Logger.cfc @@ -0,0 +1,14 @@ +component { + + function init(LogService){ + this.logService = logService; + return this; + } + function before(methodname, args, target){ + this.logService.logMessage("Before:" & arguments.args.input); + + } + function after(result, methodname, args, target){ + this.logService.logMessage("After:" & arguments.result); + } +} \ No newline at end of file diff --git a/tests/issue518/service.cfc b/tests/issue518/service.cfc new file mode 100644 index 00000000..97465f72 --- /dev/null +++ b/tests/issue518/service.cfc @@ -0,0 +1,15 @@ +component displayname="service" accessors="true" output="false" { + + + property name="stackLog"; + + + public function getServiceName() { + return listLast(getMetadata(this)); + } + + + public function init() { + return this; + } +} diff --git a/tests/issue518/services/Reverse.cfc b/tests/issue518/services/Reverse.cfc new file mode 100644 index 00000000..06c2b3b5 --- /dev/null +++ b/tests/issue518/services/Reverse.cfc @@ -0,0 +1,22 @@ +component displayname="reverseService" extends="tests.issue518.string" accessors="true" output="false" { + + + public function doForward(string input) { + //I double reverse a string... i.e. do nothing! + getStackLog().log("doForward"); + return reverse(reverse(arguments.input)); + } + + + public function doReverse(string input) { + getStackLog().log("doReverse"); + return reverse(arguments.input); + } + + + public function throwError() { + //This is just to throw an error + getStackLog().log("throwError"); + throw "I AM AN EVIL ERROR YOU WANT TO TRAP!"; + } +} diff --git a/tests/issue518/services/advReverse.cfc b/tests/issue518/services/advReverse.cfc new file mode 100644 index 00000000..21bd3d4d --- /dev/null +++ b/tests/issue518/services/advReverse.cfc @@ -0,0 +1,46 @@ +component displayname="advReverseService" extends="Reverse" accessors="true" output="false" { + + + // PUBLIC METHODS + public function configure() { + getStackLog().log("configure"); + return this; + } + + + public function doWrap(string input) { + getStackLog().log("doWrap"); + return doRear(doFront(arguments.input)); + } + + + public function init() { + // stackLog does not exist at this point. + arrayAppend(request.callStack, "init"); + + return super.init(); + } + + + public function setStackLog(any stackLog) { + // stackLog does not exist at this point. + arrayAppend(request.callStack, "setStackLog"); + + variables.stackLog = arguments.stackLog; + } + + + + + // PRIVATE METHODS + private function doFront(string input) { + getStackLog().log("doFront"); + return "front-" & arguments.input; + } + + + private function doRear(string input) { + getStackLog().log("doRear"); + return arguments.input & "-rear"; + } +} diff --git a/tests/issue518/services/array.cfc b/tests/issue518/services/array.cfc new file mode 100644 index 00000000..2e6a4880 --- /dev/null +++ b/tests/issue518/services/array.cfc @@ -0,0 +1,9 @@ +component displayname="arrayService" extends="tests.issue518.service" accessors="true" output="false" { + + + public array function doListToArray(string list) { + //I double reverse a string... i.e. do nothing! + getStackLog().log("doListToArray"); + return listToArray(arguments.list); + } +} diff --git a/tests/issue518/stackLog.cfc b/tests/issue518/stackLog.cfc new file mode 100644 index 00000000..a9232aef --- /dev/null +++ b/tests/issue518/stackLog.cfc @@ -0,0 +1,17 @@ +component displayname="stackLog" extends="service" output="false" { + + + public function init() { + if (!structKeyExists(request, "callStack")) + { + request["callStack"] = []; + } + + return super.init(); + } + + + public function log(string message) { + arrayAppend(request.callStack, message); + } +} diff --git a/tests/issue518/string.cfc b/tests/issue518/string.cfc new file mode 100644 index 00000000..e7bdf787 --- /dev/null +++ b/tests/issue518/string.cfc @@ -0,0 +1,10 @@ +component displayname="string" extends="service" accessors="true" output="false" { + + + property name="stackLog"; + + + public function init() { + return this; + } +} From 0c3e0ccd974a295208ca59d10ab42fc85bf9f137 Mon Sep 17 00:00:00 2001 From: Steven Neiland Date: Mon, 20 Jul 2020 21:10:44 -0400 Subject: [PATCH 15/19] Updated version number to 4.3.0-beta1 --- framework/ioc.cfc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/ioc.cfc b/framework/ioc.cfc index e995e756..37ecf2fa 100644 --- a/framework/ioc.cfc +++ b/framework/ioc.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.3.0-SNAPSHOT"; + variables._fw1_version = "4.3.0-Beta1"; variables._di1_version = variables._fw1_version; /* Copyright (c) 2010-2018, Sean Corfield From 94a64e0b3f52582052f342e10cedcc74ceb6de79 Mon Sep 17 00:00:00 2001 From: Tony Junkes Date: Thu, 21 Jan 2021 17:38:06 -0500 Subject: [PATCH 16/19] Fixes PreserveKey not being passed from a redirect (#522) (#526) * Fix for #522 * Fix for #522 * Fix for #522 --- framework/one.cfc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/one.cfc b/framework/one.cfc index 93064c25..9022a3e4 100644 --- a/framework/one.cfc +++ b/framework/one.cfc @@ -1893,7 +1893,7 @@ component { var nextPreserveKey = ''; var oldKeyToPurge = ''; try { - sessionLock(function(){ + sessionLock(function() localmode = "classic" { if ( variables.framework.maxNumContextsPreserved > 1 ) { sessionDefault( '__fw1NextPreserveKey', 1 ); nextPreserveKey = sessionRead( '__fw1NextPreserveKey' ); @@ -2992,7 +2992,7 @@ component { private void function setupSubsystemWrapper( string subsystem ) { if ( !len( subsystem ) ) return; - if ( !isSubsystemInitialized( subsystem ) ) { + if ( !isSubsystemInitialized( subsystem ) ) { lock name="fw1_#application.applicationName#_#variables.framework.applicationKey#_subsysteminit_#subsystem#" type="exclusive" timeout="30" { if ( !isSubsystemInitialized( subsystem ) ) { getFw1App().subsystems[ subsystem ] = now(); From 93dad96aa9e0f8fd7fd121f9cd735dbbb12481f4 Mon Sep 17 00:00:00 2001 From: Steven Neiland Date: Thu, 21 Jan 2021 17:43:18 -0500 Subject: [PATCH 17/19] Update version tags --- box.json | 2 +- framework/Application.cfc | 2 +- framework/WireBoxAdapter.cfc | 2 +- framework/aop.cfc | 2 +- framework/beanProxy.cfc | 2 +- framework/facade.cfc | 2 +- framework/ioc.cfc | 2 +- framework/methodProxy.cfc | 2 +- framework/one.cfc | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/box.json b/box.json index 98be81d1..f568e09f 100644 --- a/box.json +++ b/box.json @@ -1,7 +1,7 @@ { "name":"Framework One", "slug":"fw1", - "version":"4.3.0-SNAPSHOT", + "version":"4.3.0-Beta2", "author":"Sean Corfield, Marcin Szczepanski, Ryan Cogswell", "location":"framework-one/fw1#develop", "createPackageDirectory":true, diff --git a/framework/Application.cfc b/framework/Application.cfc index 68e5d17b..f5727b2e 100644 --- a/framework/Application.cfc +++ b/framework/Application.cfc @@ -1,5 +1,5 @@ component { - // Version: FW/1 4.3.0-SNAPSHOT + // Version: FW/1 4.3.0-Beta2 // copy this to your application root to use as your Application.cfc // or incorporate the logic below into your existing Application.cfc diff --git a/framework/WireBoxAdapter.cfc b/framework/WireBoxAdapter.cfc index 4b20da18..108987a7 100644 --- a/framework/WireBoxAdapter.cfc +++ b/framework/WireBoxAdapter.cfc @@ -1,5 +1,5 @@ component extends="wirebox.system.ioc.Injector" { - variables._fw1_version = "4.3.0-SNAPSHOT"; + variables._fw1_version = "4.3.0-Beta2"; /* Copyright (c) 2010-2018, Sean Corfield diff --git a/framework/aop.cfc b/framework/aop.cfc index 6653124a..53056d2d 100644 --- a/framework/aop.cfc +++ b/framework/aop.cfc @@ -1,5 +1,5 @@ component extends="framework.ioc" { - variables._fw1_version = "4.3.0-SNAPSHOT"; + variables._fw1_version = "4.3.0-Beta2"; variables._aop1_version = variables._fw1_version; /* Copyright (c) 2013-2018, Mark Drew, Sean Corfield, Daniel Budde diff --git a/framework/beanProxy.cfc b/framework/beanProxy.cfc index b180906c..292d6fbe 100644 --- a/framework/beanProxy.cfc +++ b/framework/beanProxy.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.3.0-SNAPSHOT"; + variables._fw1_version = "4.3.0-Beta2"; variables._aop1_version = variables._fw1_version; /* Copyright (c) 2013-2018, Mark Drew, Sean Corfield, Daniel Budde diff --git a/framework/facade.cfc b/framework/facade.cfc index f3387c88..d6e0d04c 100644 --- a/framework/facade.cfc +++ b/framework/facade.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.3.0-SNAPSHOT"; + variables._fw1_version = "4.3.0-Beta2"; /* Copyright (c) 2016-2018, Sean Corfield diff --git a/framework/ioc.cfc b/framework/ioc.cfc index 37ecf2fa..b823ed77 100644 --- a/framework/ioc.cfc +++ b/framework/ioc.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.3.0-Beta1"; + variables._fw1_version = "4.3.0-Beta2"; variables._di1_version = variables._fw1_version; /* Copyright (c) 2010-2018, Sean Corfield diff --git a/framework/methodProxy.cfc b/framework/methodProxy.cfc index 618d46db..3bd7f7a9 100644 --- a/framework/methodProxy.cfc +++ b/framework/methodProxy.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.3.0-SNAPSHOT"; + variables._fw1_version = "4.3.0-Beta2"; /* Copyright (c) 2018, Sean Corfield diff --git a/framework/one.cfc b/framework/one.cfc index 9022a3e4..02e62c4f 100644 --- a/framework/one.cfc +++ b/framework/one.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.3.0-SNAPSHOT"; + variables._fw1_version = "4.3.0-Beta2"; /* Copyright (c) 2009-2018, Sean Corfield, Marcin Szczepanski, Ryan Cogswell From 5679e6032db1a9cd97c9d812b6df7173b7327923 Mon Sep 17 00:00:00 2001 From: Steven Neiland Date: Sun, 9 May 2021 18:41:12 -0400 Subject: [PATCH 18/19] Change travis dist from trust to bionic --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 79a3d6fc..702941e6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: java sudo: required -dist: trusty +dist: bionic env: matrix: From 3a9d2506ca81a20449dc8d6688f54b72e918d7c4 Mon Sep 17 00:00:00 2001 From: Steven Neiland Date: Sun, 13 Jun 2021 12:41:17 -0400 Subject: [PATCH 19/19] Mark 4.3.0 as final --- box.json | 2 +- framework/Application.cfc | 2 +- framework/WireBoxAdapter.cfc | 2 +- framework/aop.cfc | 2 +- framework/beanProxy.cfc | 2 +- framework/facade.cfc | 2 +- framework/ioc.cfc | 2 +- framework/methodProxy.cfc | 2 +- framework/one.cfc | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/box.json b/box.json index f568e09f..6bcf7115 100644 --- a/box.json +++ b/box.json @@ -1,7 +1,7 @@ { "name":"Framework One", "slug":"fw1", - "version":"4.3.0-Beta2", + "version":"4.3.0", "author":"Sean Corfield, Marcin Szczepanski, Ryan Cogswell", "location":"framework-one/fw1#develop", "createPackageDirectory":true, diff --git a/framework/Application.cfc b/framework/Application.cfc index f5727b2e..4a88ffdb 100644 --- a/framework/Application.cfc +++ b/framework/Application.cfc @@ -1,5 +1,5 @@ component { - // Version: FW/1 4.3.0-Beta2 + // Version: FW/1 4.3.0 // copy this to your application root to use as your Application.cfc // or incorporate the logic below into your existing Application.cfc diff --git a/framework/WireBoxAdapter.cfc b/framework/WireBoxAdapter.cfc index 108987a7..10ba0ab7 100644 --- a/framework/WireBoxAdapter.cfc +++ b/framework/WireBoxAdapter.cfc @@ -1,5 +1,5 @@ component extends="wirebox.system.ioc.Injector" { - variables._fw1_version = "4.3.0-Beta2"; + variables._fw1_version = "4.3.0"; /* Copyright (c) 2010-2018, Sean Corfield diff --git a/framework/aop.cfc b/framework/aop.cfc index 53056d2d..33e75afd 100644 --- a/framework/aop.cfc +++ b/framework/aop.cfc @@ -1,5 +1,5 @@ component extends="framework.ioc" { - variables._fw1_version = "4.3.0-Beta2"; + variables._fw1_version = "4.3.0"; variables._aop1_version = variables._fw1_version; /* Copyright (c) 2013-2018, Mark Drew, Sean Corfield, Daniel Budde diff --git a/framework/beanProxy.cfc b/framework/beanProxy.cfc index 292d6fbe..dce63b25 100644 --- a/framework/beanProxy.cfc +++ b/framework/beanProxy.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.3.0-Beta2"; + variables._fw1_version = "4.3.0"; variables._aop1_version = variables._fw1_version; /* Copyright (c) 2013-2018, Mark Drew, Sean Corfield, Daniel Budde diff --git a/framework/facade.cfc b/framework/facade.cfc index d6e0d04c..795c2d43 100644 --- a/framework/facade.cfc +++ b/framework/facade.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.3.0-Beta2"; + variables._fw1_version = "4.3.0"; /* Copyright (c) 2016-2018, Sean Corfield diff --git a/framework/ioc.cfc b/framework/ioc.cfc index b823ed77..989460e1 100644 --- a/framework/ioc.cfc +++ b/framework/ioc.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.3.0-Beta2"; + variables._fw1_version = "4.3.0"; variables._di1_version = variables._fw1_version; /* Copyright (c) 2010-2018, Sean Corfield diff --git a/framework/methodProxy.cfc b/framework/methodProxy.cfc index 3bd7f7a9..4a84abb6 100644 --- a/framework/methodProxy.cfc +++ b/framework/methodProxy.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.3.0-Beta2"; + variables._fw1_version = "4.3.0"; /* Copyright (c) 2018, Sean Corfield diff --git a/framework/one.cfc b/framework/one.cfc index 02e62c4f..04c51f07 100644 --- a/framework/one.cfc +++ b/framework/one.cfc @@ -1,5 +1,5 @@ component { - variables._fw1_version = "4.3.0-Beta2"; + variables._fw1_version = "4.3.0"; /* Copyright (c) 2009-2018, Sean Corfield, Marcin Szczepanski, Ryan Cogswell