removed spring security, replaced with lightweight configurable SecurityProvider interface. removed unnecessary transaction support. updated WebAppRunnerTest to use new security provider mechanism. overall reduces `mvn clean install` time from 1m15s for console to 1m, and from 1m20s to 45s for launcher, hurrah!
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/d3c8046e Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/d3c8046e Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/d3c8046e Branch: refs/heads/0.4.0 Commit: d3c8046ebded164853a91376eb5ed52142a92cc6 Parents: bce56d9 3ca81e1 Author: Alex Heneveld <[email protected]> Authored: Sat May 5 19:49:33 2012 +0300 Committer: Alex Heneveld <[email protected]> Committed: Sat May 5 20:28:17 2012 +0300 ---------------------------------------------------------------------- usage/web-console/application.properties | 5 +- .../grails-app/conf/BootStrap.groovy | 28 -- usage/web-console/grails-app/conf/Config.groovy | 18 +- .../grails-app/conf/SecurityFilters.groovy | 20 ++ .../grails-app/conf/UrlMappings.groovy | 10 + .../web/console/DashboardController.groovy | 2 +- .../web/console/EntityController.groovy | 3 +- .../brooklyn/web/console/LoginController.groovy | 153 ++++------ .../web/console/LogoutController.groovy | 7 +- .../brooklyn/web/console/SecurityRole.groovy | 14 - .../brooklyn/web/console/SecurityUser.groovy | 24 -- .../web/console/SecurityUserRole.groovy | 52 ---- .../web/console/ManagementContextService.groovy | 4 +- .../web/console/TestWebApplication.groovy | 276 ------------------- .../web/console/TestWebApplication.groovy | 276 +++++++++++++++++++ .../security/AnyoneSecurityProvider.java | 23 ++ .../security/BlackholeSecurityProvider.java | 23 ++ .../web/console/security/ConfigLoader.java | 36 +++ .../security/DelegatingSecurityProvider.java | 49 ++++ .../security/ExplicitUsersSecurityProvider.java | 98 +++++++ .../web/console/security/SecurityProvider.java | 12 + .../console/security/WebConsoleSecurity.java | 12 + .../web-console/grails-app/views/login/auth.gsp | 2 +- usage/web-console/pom.xml | 6 +- 24 files changed, 632 insertions(+), 521 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/application.properties ---------------------------------------------------------------------- diff --cc usage/web-console/application.properties index e271f9e,e271f9e..fb668c8 --- a/usage/web-console/application.properties +++ b/usage/web-console/application.properties @@@ -1,11 -1,11 +1,8 @@@ #Grails Metadata file --#Wed Aug 03 12:12:25 BST 2011 ++#Sat May 05 09:11:19 PDT 2012 app.grails.version=1.3.7 app.name=brooklyn-web-console app.servlet.version=2.4 --# BROOKLYN_VERSION_BELOW app.version=0.4.0-SNAPSHOT plugins.haml=0.3 --plugins.hibernate=1.3.7 --plugins.spring-security-core=1.1.3 plugins.tomcat=1.3.7 http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/conf/BootStrap.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/conf/BootStrap.groovy index dfc60da,dfc60da..760a1ef --- a/usage/web-console/grails-app/conf/BootStrap.groovy +++ b/usage/web-console/grails-app/conf/BootStrap.groovy @@@ -1,36 -1,36 +1,8 @@@ import org.codehaus.groovy.grails.web.context.ServletContextHolder; --import brooklyn.web.console.SecurityRole --import brooklyn.web.console.SecurityUser --import brooklyn.web.console.SecurityUserRole -- class BootStrap { -- def springSecurityService -- // TODO hard-coded admin/password account! (password can be passed in, but that's still far from ideal!) def init = { servletContext -> -- String password = ServletContextHolder.servletContext?.getAttribute("brooklynbrooklynWeb") ?: -- 'password' -- -- def adminRole = SecurityRole.findByAuthority('ROLE_ADMIN') ?: new SecurityRole(authority: 'ROLE_ADMIN').save(failOnError: true) -- def adminUser = SecurityUser.findByUsername('admin') ?: new SecurityUser( -- username: 'admin', -- password: springSecurityService.encodePassword(password), -- enabled: true).save(failOnError: true) -- -- if (!adminUser.authorities.contains(adminRole)) { -- SecurityUserRole.create adminUser, adminRole -- } -- -- def userRole = SecurityRole.findByAuthority('ROLE_USER') ?: new SecurityRole(authority: 'ROLE_USER').save(failOnError: true) -- def user = SecurityUser.findByUsername('user') ?: new SecurityUser( -- username: 'user', -- password: springSecurityService.encodePassword(password), -- enabled: true).save(failOnError: true) -- -- if (!user.authorities.contains(userRole)) { -- SecurityUserRole.create user, userRole -- } } def destroy = { http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/conf/Config.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/conf/Config.groovy index 6e7d1b0,6e7d1b0..32e89c6 --- a/usage/web-console/grails-app/conf/Config.groovy +++ b/usage/web-console/grails-app/conf/Config.groovy @@@ -87,20 -87,20 +87,6 @@@ log4j = 'net.sf.ehcache.hibernate' warn 'org.mortbay.log' --} -- --// Added by the Spring Security Core plugin: --grails.plugins.springsecurity.userLookup.userDomainClassName = 'brooklyn.web.console.SecurityUser' --grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'brooklyn.web.console.SecurityUserRole' --grails.plugins.springsecurity.authority.className = 'brooklyn.web.console.SecurityRole' -- --grails.plugins.springsecurity.useBasicAuth = true --grails.plugins.springsecurity.basic.realmName = "Brooklyn Web Console" --grails.plugins.springsecurity.successHandler.defaultTargetUrl = "/dashboard" -- --grails.plugins.springsecurity.controllerAnnotations.staticRules = [ -- '/dashboard/**': ['ROLE_ADMIN'], -- '/detail/**': ['ROLE_ADMIN'], -- '/entity/**': ['ROLE_ADMIN'] --] ++ info 'brooklyn' ++} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/conf/SecurityFilters.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/conf/SecurityFilters.groovy index 0000000,0000000..07ee733 new file mode 100644 --- /dev/null +++ b/usage/web-console/grails-app/conf/SecurityFilters.groovy @@@ -1,0 -1,0 +1,20 @@@ ++import org.slf4j.Logger ++import org.slf4j.LoggerFactory ++ ++import brooklyn.web.console.security.WebConsoleSecurity ++ ++class SecurityFilters { ++ public static final Logger log = LoggerFactory.getLogger(SecurityFilters.class); ++ ++ def filters = { ++ loginCheck(controller:'*', action:'*') { ++ before = { ++ if (!WebConsoleSecurity.getInstance().isAuthenticated(session) && !controllerName.equals('login')) { ++ log.info("redirecting ${session} from ${controllerName} to login page") ++ redirect(controller:'login') ++ return false ++ } ++ } ++ } ++ } ++} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/conf/UrlMappings.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/conf/UrlMappings.groovy index a194184,a194184..f8bd80b --- a/usage/web-console/grails-app/conf/UrlMappings.groovy +++ b/usage/web-console/grails-app/conf/UrlMappings.groovy @@@ -17,4 -17,4 +17,14 @@@ class UrlMappings "500"(view:'/error') } ++ ++ def beforeInterceptor = [action: this.&auth, except: 'login'] ++ // defined with private scope, so it's not considered an action ++ private auth() { ++ if (!session.user) { ++ redirect(action: 'login') ++ return false ++ } ++ } ++ } http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/controllers/brooklyn/web/console/DashboardController.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/controllers/brooklyn/web/console/DashboardController.groovy index 5089a00,5089a00..56bcd2c --- a/usage/web-console/grails-app/controllers/brooklyn/web/console/DashboardController.groovy +++ b/usage/web-console/grails-app/controllers/brooklyn/web/console/DashboardController.groovy @@@ -8,7 -8,7 +8,7 @@@ class DashboardController public static final Logger LOG = LoggerFactory.getLogger(this); def index = { -- LOG.info("loading dashboard for "+session) ++ LOG.debug("loading dashboard for {}", session) } } http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/controllers/brooklyn/web/console/EntityController.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/controllers/brooklyn/web/console/EntityController.groovy index d3e2709,d3e2709..ed119cc --- a/usage/web-console/grails-app/controllers/brooklyn/web/console/EntityController.groovy +++ b/usage/web-console/grails-app/controllers/brooklyn/web/console/EntityController.groovy @@@ -1,7 -1,7 +1,6 @@@ package brooklyn.web.console import grails.converters.JSON --import grails.plugins.springsecurity.Secured import brooklyn.entity.Entity import brooklyn.web.console.entity.EntitySummary @@@ -20,7 -20,7 +19,7 @@@ import brooklyn.entity.Group import brooklyn.entity.ParameterType import brooklyn.entity.basic.BasicParameterType --@Secured(['ROLE_ADMIN']) ++ class EntityController { // Injected http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/controllers/brooklyn/web/console/LoginController.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/controllers/brooklyn/web/console/LoginController.groovy index 8d411fb,8d411fb..a6170a4 --- a/usage/web-console/grails-app/controllers/brooklyn/web/console/LoginController.groovy +++ b/usage/web-console/grails-app/controllers/brooklyn/web/console/LoginController.groovy @@@ -2,94 -2,94 +2,57 @@@ package brooklyn.web.consol import grails.converters.JSON --import javax.security.auth.login.AccountExpiredException import javax.servlet.http.HttpServletResponse --import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils --import org.codehaus.groovy.grails.web.context.ServletContextHolder --import org.springframework.security.authentication.CredentialsExpiredException --import org.springframework.security.authentication.DisabledException --import org.springframework.security.authentication.LockedException --import org.springframework.security.authentication.UsernamePasswordAuthenticationToken --import org.springframework.security.core.authority.GrantedAuthorityImpl --import org.springframework.security.core.context.SecurityContextHolder --import org.springframework.security.web.WebAttributes --import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter -- --import brooklyn.config.BrooklynServiceAttributes; ++import brooklyn.web.console.security.WebConsoleSecurity class LoginController { -- /** -- * Dependency injection for the authenticationTrustResolver. -- */ -- def authenticationTrustResolver -- -- /** -- * Dependency injection for the springSecurityService. -- */ -- def springSecurityService -- ++ private String getRedirectTarget(boolean includePrefix) { ++ String result = "/dashboard/"; ++ if (includePrefix) result = createLinkTo(dir:result) ++ return result; ++ } ++ /** * Default action; redirects to 'defaultTargetUrl' if logged in, /login/auth otherwise. */ def index = { -- if (springSecurityService.isLoggedIn()) { -- redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl -- } -- else { ++ if (WebConsoleSecurity.getInstance().isAuthenticated(session) || tryAuthenticate()) { ++ redirect uri: getRedirectTarget(false); ++ } else { redirect action: auth, params: params } } -- //logs the given user in -- private void autoLogin(username) { -- def user = SecurityUser.findByUsername(username) -- List auths = user.authorities.collect { -- new GrantedAuthorityImpl(it.authority) ++ private boolean tryAuthenticate() { ++ if (params.j_username) { ++ return WebConsoleSecurity.getInstance().authenticate(session, params.j_username, params.j_password) } -- def grailsUser = new org.springframework.security.core.userdetails.User( -- user.username, // String username, String password, -- "", -- true, true, // boolean enabled, boolean accountNonExpired, -- true, true, // boolean credentialsNonExpired, boolean accountNonLocked, -- auths //Collection<? extends GrantedAuthority> authorities); -- ); -- def authToken = new UsernamePasswordAuthenticationToken(grailsUser, '', auths) -- SecurityContextHolder.context.authentication = authToken ++ return false; } -- /** * Show the login page. */ def auth = { -- def config = SpringSecurityUtils.securityConfig -- //ideally we'd do this on start of any new session, but not clear how to do it -- //(this probably isn't the best workaround to allow tests to access in any case!) -- if (!springSecurityService.isLoggedIn()) { -- //for unit tests -- def autologinUser = ServletContextHolder.servletContext?.getAttribute(BrooklynServiceAttributes.BROOKLYN_AUTOLOGIN_USERNAME); -- if (autologinUser) { -- autoLogin(autologinUser) -- } -- } -- -- if (springSecurityService.isLoggedIn()) { -- redirect uri: config.successHandler.defaultTargetUrl ++ if (WebConsoleSecurity.getInstance().isAuthenticated(session)) { ++ redirect uri: getRedirectTarget(false) return } String view = 'auth' -- String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}" ++ String postUrl = createLinkTo(dir:"login") ++ //TODO support following to the originally requested URL ++ String postAfterUrl = getRedirectTarget(true) render view: view, model: [postUrl: postUrl, -- rememberMeParameter: config.rememberMe.parameter] ++ rememberMeParameter: true] } /** * The redirect action for Ajax requests. */ def authAjax = { -- response.setHeader 'Location', SpringSecurityUtils.securityConfig.auth.ajaxLoginFormUrl ++// response.setHeader 'Location', SpringSecurityUtils.securityConfig.auth.ajaxLoginFormUrl response.sendError HttpServletResponse.SC_UNAUTHORIZED } @@@ -97,63 -97,63 +60,63 @@@ * Show denied page. */ def denied = { -- if (springSecurityService.isLoggedIn() && -- authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) { -- // have cookie but the page is guarded with IS_AUTHENTICATED_FULLY -- redirect action: full, params: params -- } ++// if (springSecurityService.isLoggedIn() && ++// authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) { ++// // have cookie but the page is guarded with IS_AUTHENTICATED_FULLY ++// redirect action: full, params: params ++// } } /** * Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page. */ def full = { -- def config = SpringSecurityUtils.securityConfig -- render view: 'auth', params: params, -- model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication), -- postUrl: "${request.contextPath}${config.apf.filterProcessesUrl}"] ++// def config = SpringSecurityUtils.securityConfig ++// render view: 'auth', params: params, ++// model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication), ++// postUrl: "${request.contextPath}${config.apf.filterProcessesUrl}"] } /** * Callback after a failed login. Redirects to the auth page with a warning message. */ def authfail = { -- -- def username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY] -- String msg = '' -- def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION] -- if (exception) { -- if (exception instanceof AccountExpiredException) { -- msg = SpringSecurityUtils.securityConfig.errors.login.expired -- } -- else if (exception instanceof CredentialsExpiredException) { -- msg = SpringSecurityUtils.securityConfig.errors.login.passwordExpired -- } -- else if (exception instanceof DisabledException) { -- msg = SpringSecurityUtils.securityConfig.errors.login.disabled -- } -- else if (exception instanceof LockedException) { -- msg = SpringSecurityUtils.securityConfig.errors.login.locked -- } -- else { -- msg = SpringSecurityUtils.securityConfig.errors.login.fail -- } -- } -- -- if (springSecurityService.isAjax(request)) { -- render([error: msg] as JSON) -- } -- else { ++// ++// def username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY] ++// String msg = '' ++// def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION] ++// if (exception) { ++// if (exception instanceof AccountExpiredException) { ++// msg = SpringSecurityUtils.securityConfig.errors.login.expired ++// } ++// else if (exception instanceof CredentialsExpiredException) { ++// msg = SpringSecurityUtils.securityConfig.errors.login.passwordExpired ++// } ++// else if (exception instanceof DisabledException) { ++// msg = SpringSecurityUtils.securityConfig.errors.login.disabled ++// } ++// else if (exception instanceof LockedException) { ++// msg = SpringSecurityUtils.securityConfig.errors.login.locked ++// } ++// else { ++// msg = SpringSecurityUtils.securityConfig.errors.login.fail ++// } ++// } ++// ++// if (springSecurityService.isAjax(request)) { ++// render([error: msg] as JSON) ++// } ++// else { flash.message = msg redirect action: auth, params: params -- } ++// } } /** * The Ajax success redirect url. */ def ajaxSuccess = { -- render([success: true, username: springSecurityService.authentication.name] as JSON) ++ render([success: true] as JSON) } /** http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/controllers/brooklyn/web/console/LogoutController.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/controllers/brooklyn/web/console/LogoutController.groovy index 2ff87f0,2ff87f0..3b39365 --- a/usage/web-console/grails-app/controllers/brooklyn/web/console/LogoutController.groovy +++ b/usage/web-console/grails-app/controllers/brooklyn/web/console/LogoutController.groovy @@@ -1,6 -1,6 +1,6 @@@ package brooklyn.web.console --import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils ++import brooklyn.web.console.security.WebConsoleSecurity class LogoutController { @@@ -8,7 -8,7 +8,8 @@@ * Index action. Redirects to the Spring security logout uri. */ def index = { -- // TODO put any pre-logout code here -- redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout' ++ WebConsoleSecurity.getInstance().logout(session) ++ redirect controller: 'login'; } ++ } http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/domain/brooklyn/web/console/SecurityRole.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/domain/brooklyn/web/console/SecurityRole.groovy index 57cd47c,57cd47c..0000000 deleted file mode 100644,100644 --- a/usage/web-console/grails-app/domain/brooklyn/web/console/SecurityRole.groovy +++ /dev/null @@@ -1,14 -1,14 +1,0 @@@ --package brooklyn.web.console -- --class SecurityRole { -- -- String authority -- -- static mapping = { -- cache true -- } -- -- static constraints = { -- authority blank: false, unique: true -- } --} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/domain/brooklyn/web/console/SecurityUser.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/domain/brooklyn/web/console/SecurityUser.groovy index 7130f04,7130f04..0000000 deleted file mode 100644,100644 --- a/usage/web-console/grails-app/domain/brooklyn/web/console/SecurityUser.groovy +++ /dev/null @@@ -1,24 -1,24 +1,0 @@@ --package brooklyn.web.console -- --class SecurityUser { -- -- String username -- String password -- boolean enabled -- boolean accountExpired -- boolean accountLocked -- boolean passwordExpired -- -- static constraints = { -- username blank: false, unique: true -- password blank: false -- } -- -- static mapping = { -- password column: '`password`' -- } -- -- Set<SecurityRole> getAuthorities() { -- SecurityUserRole.findAllBySecurityUser(this).collect { it.securityRole } as Set -- } --} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/domain/brooklyn/web/console/SecurityUserRole.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/domain/brooklyn/web/console/SecurityUserRole.groovy index b7cf771,b7cf771..0000000 deleted file mode 100644,100644 --- a/usage/web-console/grails-app/domain/brooklyn/web/console/SecurityUserRole.groovy +++ /dev/null @@@ -1,52 -1,52 +1,0 @@@ --package brooklyn.web.console -- --import org.apache.commons.lang.builder.HashCodeBuilder -- --class SecurityUserRole implements Serializable { -- -- SecurityUser securityUser -- SecurityRole securityRole -- -- boolean equals(other) { -- if (!(other instanceof SecurityUserRole)) { -- return false -- } -- -- other.securityUser?.id == securityUser?.id && -- other.securityRole?.id == securityRole?.id -- } -- -- int hashCode() { -- def builder = new HashCodeBuilder() -- if (securityUser) builder.append(securityUser.id) -- if (securityRole) builder.append(securityRole.id) -- builder.toHashCode() -- } -- -- static SecurityUserRole get(long securityUserId, long securityRoleId) { -- find 'from SecurityUserRole where securityUser.id=:securityUserId and securityRole.id=:securityRoleId', -- [securityUserId: securityUserId, securityRoleId: securityRoleId] -- } -- -- static SecurityUserRole create(SecurityUser securityUser, SecurityRole securityRole, boolean flush = false) { -- new SecurityUserRole(securityUser: securityUser, securityRole: securityRole).save(flush: flush, insert: true) -- } -- -- static boolean remove(SecurityUser securityUser, SecurityRole securityRole, boolean flush = false) { -- SecurityUserRole instance = SecurityUserRole.findBySecurityUserAndSecurityRole(securityUser, securityRole) -- instance ? instance.delete(flush: flush) : false -- } -- -- static void removeAll(SecurityUser securityUser) { -- executeUpdate 'DELETE FROM SecurityUserRole WHERE securityUser=:securityUser', [securityUser: securityUser] -- } -- -- static void removeAll(SecurityRole securityRole) { -- executeUpdate 'DELETE FROM SecurityUserRole WHERE securityRole=:securityRole', [securityRole: securityRole] -- } -- -- static mapping = { -- id composite: ['securityRole', 'securityUser'] -- version false -- } --} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/services/brooklyn/web/console/ManagementContextService.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/services/brooklyn/web/console/ManagementContextService.groovy index bb3be3e,bb3be3e..bd1f2ca --- a/usage/web-console/grails-app/services/brooklyn/web/console/ManagementContextService.groovy +++ b/usage/web-console/grails-app/services/brooklyn/web/console/ManagementContextService.groovy @@@ -11,6 -11,6 +11,8 @@@ import java.util.concurrent.atomic.Atom import org.codehaus.groovy.grails.web.context.ServletContextHolder class ManagementContextService { ++ static transactional = false ++ private ManagementContext managementContext protected static AtomicLong ID_GENERATOR = new AtomicLong(0L) @@@ -27,7 -27,7 +29,7 @@@ managementContext = (ManagementContext) ServletContextHolder.servletContext?. getAttribute(BrooklynServiceAttributes.BROOKLYN_MANAGEMENT_CONTEXT) } -- // TODO remove this test code as soon as the group agrees it's unnecessary! ++ // TODO use a different mechanism for specifying test-app if (!managementContext) { managementContext = new LocalManagementContext(); managementContext.manage(new TestWebApplication()) http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/services/brooklyn/web/console/TestWebApplication.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/services/brooklyn/web/console/TestWebApplication.groovy index db196f7,db196f7..0000000 deleted file mode 100644,100644 --- a/usage/web-console/grails-app/services/brooklyn/web/console/TestWebApplication.groovy +++ /dev/null @@@ -1,276 -1,276 +1,0 @@@ --package brooklyn.web.console -- --import brooklyn.entity.Effector --import brooklyn.entity.Entity --import brooklyn.entity.ParameterType --import brooklyn.entity.basic.AbstractApplication --import brooklyn.entity.basic.AbstractEntity --import brooklyn.entity.basic.AbstractGroup --import brooklyn.entity.basic.BasicParameterType --import brooklyn.entity.basic.EntityLocal; --import brooklyn.entity.webapp.tomcat.TomcatServer --import brooklyn.event.basic.BasicAttributeSensor --import brooklyn.location.Location --import brooklyn.location.basic.SimulatedLocation --import brooklyn.policy.Policy --import brooklyn.policy.basic.GeneralPurposePolicy --import brooklyn.management.Task --import brooklyn.web.console.entity.TestEffector --import grails.converters.JSON --import brooklyn.event.basic.BasicSensor --import brooklyn.event.Sensor --import brooklyn.event.AttributeSensor -- --// TODO remove these test classes as soon as the group agrees they're unnecessary! --private class TestWebApplication extends AbstractApplication { -- TestWebApplication(Map props=[:]) { -- super(props) -- displayName = "Application"; -- -- locations = [ -- new SimulatedLocation([id: "us-east-1", name:"US-East-1", iso3166: "US-CA", displayName:"US-East-1", streetAddress:"Northern Virginia, USA", description:"Northern Virginia (approx)", -- latitude:38.0,longitude:-76.0]), -- new SimulatedLocation([id: "us-west-1", name:"US-West-1", iso3166: "US-VA", displayName:"US-West-1", streetAddress:"Northern California, USA", description:"Northern California", -- latitude:40.0,longitude:-120.0]), -- new SimulatedLocation([id: "eu-west-1", name:"EU-West-1", iso3166: "IE", displayName:"EU-West-1", streetAddress:"Dublin, Ireland", description:"Dublin, Ireland", -- latitude:53.34778,longitude:-6.25972]), -- new SimulatedLocation([id: "fruitcake", name:"Unused location in cakeland", iso3166: "IE", displayName:"Unused location in cakeland", streetAddress:"Nowhere, cakeland", description:"Nowhere", -- latitude:0,longitude:0]) -- ]; -- -- List<Policy> testPolicies = [ -- new GeneralPurposePolicy([id: 'CTS1', name: 'chase-the-sun', displayName: 'Chase the Sun', policyStatus: 'Suspended']), -- new GeneralPurposePolicy([id: 'CTM1', name: 'chase-the-moon', displayName: 'Chase the Moon', policyStatus: 'Active']), -- new GeneralPurposePolicy([id: 'FTM1', name: 'follow-the-money', displayName: 'Follow the Money', policyStatus: 'Suspended']), -- new GeneralPurposePolicy([id: 'FTA1', name: 'follow-the-action', displayName: 'Follow the Action', policyStatus: 'Active']) -- ]; -- -- -- Entity testExtraGroup = new TestGroupEntity(this, "Another group for testing"); -- setupChangingEntity(this); -- -- for(String tierName : ["tomcat tier 1", "tomcat tier 2", "data tier 1"]) { -- Entity tier = new TestGroupEntity(this, tierName); -- for(String clusterName : ["1a", "1b"]) { -- Entity cluster = new TestGroupEntity(tier, tierName.substring(0, tierName.indexOf(" ")) + -- " cluster " + clusterName) -- for(int i=1; i<4; i++) { -- if (tierName =~ /^tomcat/) { -- Entity testTomcat = new TestTomcatEntity(cluster, "tomcat node " + clusterName + "." + i) -- testTomcat.addGroup(testExtraGroup); -- cluster.addOwnedChild(testTomcat) -- setUpAddingSensor(testTomcat) -- } else { -- cluster.addOwnedChild(new TestDataEntity(cluster, "data node " + clusterName + "." + i)) -- } -- -- } -- tier.addOwnedChild(cluster) -- } -- addOwnedChild(tier) -- } -- -- sensors.putAll([ -- Children: new BasicAttributeSensor<Integer>(Integer.class, "Children", -- "Owned children of this application"), -- DataRate: new BasicAttributeSensor<String>(String.class, "DataRate")]) -- setAttribute(getSensor("Children"), getOwnedChildren().size()) -- } -- -- public <T> Task<T> invoke(Effector<T> eff, Map<String, ?> parameters) { -- return null //To change body of implemented methods use File | Settings | File Templates. -- } -- -- /** -- * Sets up an entity that is added and removed every 20s. -- * @param application -- */ -- private void setupChangingEntity(final AbstractApplication application) { -- Runnable r = new Runnable() { -- Entity e; -- void run() { -- while (true) { -- if (e != null) { -- application.removeOwnedChild(e) -- e = null; -- Thread.sleep(20*1000L); -- } else { -- e = new TestGroupEntity(application, "Now you see me"); -- Thread.sleep(20*1000L); -- } -- } -- } -- -- }; -- -- new Thread(r).start(); -- } -- -- private void setUpAddingSensor(AbstractEntity entity) { -- Runnable r = new Runnable() { -- void run() { -- while (true) { -- Sensor sensor = new BasicAttributeSensor(Sensor.class, "test.sensor", "Added and removed every 20s") -- entity.addSensor(sensor) -- Thread.sleep(20*1000L) -- entity.removeSensor(sensor.name) -- Thread.sleep(20*1000L) -- } -- } -- -- }; -- new Thread(r).start(); -- } -- -- private class TestGroupEntity extends AbstractGroup { -- TestGroupEntity(Entity owner, String displayName) { -- super([:], owner) -- this.displayName = displayName -- sensors.putAll([Children: new BasicAttributeSensor<Integer>(Integer.class, "Children", -- "Direct children of this group"), DataRate: new BasicAttributeSensor<String>(String.class, "DataRate")]) -- } -- -- TestGroupEntity addOwnedChild(Entity child) { -- super.addOwnedChild(child) -- setAttribute(getSensor("Children"), ownedChildren.size()) -- return this -- } -- -- public <T> Task<T> invoke(Effector<T> eff, Map<String, ?> parameters) { -- return null -- } -- } -- -- -- private class TestDataEntity extends AbstractEntity { -- private List<Location> testLocations = [ -- new SimulatedLocation([id: "us-east-1", name:"US-East-1", iso3166: "US-CA", displayName:"US-East-1", streetAddress:"Northern Virginia, USA", description:"Northern Virginia (approx)", -- latitude:38.0,longitude:-76.0]), -- new SimulatedLocation([id: "us-west-1", name:"US-West-1", iso3166: "US-VA", displayName:"US-West-1", streetAddress:"Northern California, USA", description:"Northern California", -- latitude:40.0,longitude:-120.0]), -- new SimulatedLocation([id: "eu-west-1", name:"EU-West-1", iso3166: "IE", displayName:"EU-West-1", streetAddress:"Dublin, Ireland", description:"Dublin, Ireland", -- latitude:53.34778,longitude:-6.25972]) -- ]; -- private List<Policy> testPolicies = [ -- new GeneralPurposePolicy([id: 'CTS1', name: 'chase-the-sun', displayName: 'Chase the Sun', policyStatus: 'Suspended', description: 'Chasing the sun, meaning chase the activity when certain parts of the earth are awake']), -- new GeneralPurposePolicy([id: 'CTM1', name: 'chase-the-moon', displayName: 'Chase the Moon', policyStatus: 'Active']) -- ]; -- TestDataEntity(Entity owner, String displayName) { -- super([:], owner) -- -- this.displayName = displayName -- this.locations = testLocations; -- this.policies = testPolicies; -- TestEffector startDB = new TestEffector("Start DB", "This will start the database", -- new ArrayList<ParameterType<?>>()) -- TestEffector stopDB = new TestEffector("Stop DB", "This will stop the database", -- new ArrayList<ParameterType<?>>()) -- TestEffector restartDB = new TestEffector("Restart DB", "This will restart the DB", -- new ArrayList<ParameterType<?>>()) -- -- this.effectors.putAll(["Start DB": startDB, "Stop DB": stopDB, "Restart DB": restartDB]) -- -- this.sensors.putAll( -- [Happiness: new BasicAttributeSensor<String>(String.class, "Happiness"), -- Cache: new BasicAttributeSensor<String>(String.class, "Cache", "Some cache metric"), -- Sync: new BasicAttributeSensor<String>(String.class, "Sync", "Synchronization strategy")] -- ) -- -- setAttribute(getSensor("Happiness"), 50) -- setAttribute(getSensor("Cache"), 200) -- setAttribute(getSensor("Sync"), "Moop") -- } -- -- public <T> Task<T> invoke(Effector<T> eff, Map<String, ?> parameters) { -- return null -- } -- } -- -- private class TestTomcatEntity extends AbstractEntity { -- //FIXME should use typed keys not strings -- private Map hackMeIn = [ -- "http.port": 8080, -- "webapp.tomcat.shutdownPort": 666, -- "jmx.port": 1000, -- "webapp.reqs.processing.time": 100, -- "test.sensor": 17 -- ] -- -- private List<Location> testLocations = [ -- new SimulatedLocation([id: "us-east-1", name:"US-East-1", iso3166: "US-VA", displayName:"US-East-1", streetAddress:"Northern Virginia, USA", description:"Northern Virginia (approx)", -- latitude:38.0,longitude:-76.0]) -- ]; -- private List<Policy> testPolicies = [ -- new GeneralPurposePolicy([id: 'FTM1', name: 'follow-the-money', displayName: 'Follow the Money', policyStatus: 'Suspended']), -- new GeneralPurposePolicy([id: 'FTA1', name: 'follow-the-action', displayName: 'Follow the Action', policyStatus: 'Active']) -- ]; -- -- -- public TestTomcatEntity(Entity owner, String displayName) { -- super([:], owner) -- this.displayName = displayName -- this.locations = testLocations; -- this.policies = testPolicies; -- -- // Stealing the sensors from TomcatNode -- this.sensors.putAll(new TomcatServer().sensors) -- -- List<ParameterType<?>> parameterTypeList = new ArrayList<ParameterType<?>>() -- ParameterType tomcatStartLocation = new BasicParameterType("Location", new ArrayList<String>().class) -- ParameterType actionDate = new BasicParameterType("Date", Date.class) -- parameterTypeList.add(tomcatStartLocation) -- parameterTypeList.add(actionDate) -- -- -- // Don't appear to be any effectors in TomcatServer -- TestEffector startTomcat = new TestEffector("Start Tomcat", -- "This will start Tomcat at a specified location", -- parameterTypeList) -- TestEffector stopTomcat = new TestEffector("Stop Tomcat", -- "This will stop tomcat at its current location", -- new Collections.SingletonList(actionDate)) -- TestEffector restartTomcat = new TestEffector("Restart Tomcat", -- "This will restart tomcat in its current location", -- new ArrayList<ParameterType<?>>()) -- -- this.effectors.putAll([ "Start Tomcat": startTomcat, -- "Stop Tomcat": stopTomcat, -- "Restart Tomcat": restartTomcat]) -- -- for (def i = 0; i < 10; ++i) { -- this.getExecutionContext().submit([ -- tags:["EFFECTOR"], -- tag:this, -- displayName: "Update values (test " + i + ")", -- description: "This updates sensor values"], -- new MyRunnable(this)); -- } -- } -- -- public <T> Task<T> invoke(Effector<T> eff, Map<String, ?> parameters) { -- System.out.println(parameters as JSON) -- return null -- } -- -- protected class MyRunnable implements Runnable { -- EntityLocal entity -- protected MyRunnable(Entity e) { -- this.entity = e -- } -- void run() { -- while (true) { -- Map ss = entity.getSensors() -- for (String key: hackMeIn.keySet()) { -- def s = ss[key] -- if (s != null){ -- entity.setAttribute(s, -- hackMeIn[key] + ManagementContextService.ID_GENERATOR + -- ((int) 1000 * Math.random())) -- } -- } -- Thread.sleep(5000) -- } -- } -- } -- } --} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/utils/brooklyn/web/console/TestWebApplication.groovy ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/utils/brooklyn/web/console/TestWebApplication.groovy index 0000000,0000000..db196f7 new file mode 100644 --- /dev/null +++ b/usage/web-console/grails-app/utils/brooklyn/web/console/TestWebApplication.groovy @@@ -1,0 -1,0 +1,276 @@@ ++package brooklyn.web.console ++ ++import brooklyn.entity.Effector ++import brooklyn.entity.Entity ++import brooklyn.entity.ParameterType ++import brooklyn.entity.basic.AbstractApplication ++import brooklyn.entity.basic.AbstractEntity ++import brooklyn.entity.basic.AbstractGroup ++import brooklyn.entity.basic.BasicParameterType ++import brooklyn.entity.basic.EntityLocal; ++import brooklyn.entity.webapp.tomcat.TomcatServer ++import brooklyn.event.basic.BasicAttributeSensor ++import brooklyn.location.Location ++import brooklyn.location.basic.SimulatedLocation ++import brooklyn.policy.Policy ++import brooklyn.policy.basic.GeneralPurposePolicy ++import brooklyn.management.Task ++import brooklyn.web.console.entity.TestEffector ++import grails.converters.JSON ++import brooklyn.event.basic.BasicSensor ++import brooklyn.event.Sensor ++import brooklyn.event.AttributeSensor ++ ++// TODO remove these test classes as soon as the group agrees they're unnecessary! ++private class TestWebApplication extends AbstractApplication { ++ TestWebApplication(Map props=[:]) { ++ super(props) ++ displayName = "Application"; ++ ++ locations = [ ++ new SimulatedLocation([id: "us-east-1", name:"US-East-1", iso3166: "US-CA", displayName:"US-East-1", streetAddress:"Northern Virginia, USA", description:"Northern Virginia (approx)", ++ latitude:38.0,longitude:-76.0]), ++ new SimulatedLocation([id: "us-west-1", name:"US-West-1", iso3166: "US-VA", displayName:"US-West-1", streetAddress:"Northern California, USA", description:"Northern California", ++ latitude:40.0,longitude:-120.0]), ++ new SimulatedLocation([id: "eu-west-1", name:"EU-West-1", iso3166: "IE", displayName:"EU-West-1", streetAddress:"Dublin, Ireland", description:"Dublin, Ireland", ++ latitude:53.34778,longitude:-6.25972]), ++ new SimulatedLocation([id: "fruitcake", name:"Unused location in cakeland", iso3166: "IE", displayName:"Unused location in cakeland", streetAddress:"Nowhere, cakeland", description:"Nowhere", ++ latitude:0,longitude:0]) ++ ]; ++ ++ List<Policy> testPolicies = [ ++ new GeneralPurposePolicy([id: 'CTS1', name: 'chase-the-sun', displayName: 'Chase the Sun', policyStatus: 'Suspended']), ++ new GeneralPurposePolicy([id: 'CTM1', name: 'chase-the-moon', displayName: 'Chase the Moon', policyStatus: 'Active']), ++ new GeneralPurposePolicy([id: 'FTM1', name: 'follow-the-money', displayName: 'Follow the Money', policyStatus: 'Suspended']), ++ new GeneralPurposePolicy([id: 'FTA1', name: 'follow-the-action', displayName: 'Follow the Action', policyStatus: 'Active']) ++ ]; ++ ++ ++ Entity testExtraGroup = new TestGroupEntity(this, "Another group for testing"); ++ setupChangingEntity(this); ++ ++ for(String tierName : ["tomcat tier 1", "tomcat tier 2", "data tier 1"]) { ++ Entity tier = new TestGroupEntity(this, tierName); ++ for(String clusterName : ["1a", "1b"]) { ++ Entity cluster = new TestGroupEntity(tier, tierName.substring(0, tierName.indexOf(" ")) + ++ " cluster " + clusterName) ++ for(int i=1; i<4; i++) { ++ if (tierName =~ /^tomcat/) { ++ Entity testTomcat = new TestTomcatEntity(cluster, "tomcat node " + clusterName + "." + i) ++ testTomcat.addGroup(testExtraGroup); ++ cluster.addOwnedChild(testTomcat) ++ setUpAddingSensor(testTomcat) ++ } else { ++ cluster.addOwnedChild(new TestDataEntity(cluster, "data node " + clusterName + "." + i)) ++ } ++ ++ } ++ tier.addOwnedChild(cluster) ++ } ++ addOwnedChild(tier) ++ } ++ ++ sensors.putAll([ ++ Children: new BasicAttributeSensor<Integer>(Integer.class, "Children", ++ "Owned children of this application"), ++ DataRate: new BasicAttributeSensor<String>(String.class, "DataRate")]) ++ setAttribute(getSensor("Children"), getOwnedChildren().size()) ++ } ++ ++ public <T> Task<T> invoke(Effector<T> eff, Map<String, ?> parameters) { ++ return null //To change body of implemented methods use File | Settings | File Templates. ++ } ++ ++ /** ++ * Sets up an entity that is added and removed every 20s. ++ * @param application ++ */ ++ private void setupChangingEntity(final AbstractApplication application) { ++ Runnable r = new Runnable() { ++ Entity e; ++ void run() { ++ while (true) { ++ if (e != null) { ++ application.removeOwnedChild(e) ++ e = null; ++ Thread.sleep(20*1000L); ++ } else { ++ e = new TestGroupEntity(application, "Now you see me"); ++ Thread.sleep(20*1000L); ++ } ++ } ++ } ++ ++ }; ++ ++ new Thread(r).start(); ++ } ++ ++ private void setUpAddingSensor(AbstractEntity entity) { ++ Runnable r = new Runnable() { ++ void run() { ++ while (true) { ++ Sensor sensor = new BasicAttributeSensor(Sensor.class, "test.sensor", "Added and removed every 20s") ++ entity.addSensor(sensor) ++ Thread.sleep(20*1000L) ++ entity.removeSensor(sensor.name) ++ Thread.sleep(20*1000L) ++ } ++ } ++ ++ }; ++ new Thread(r).start(); ++ } ++ ++ private class TestGroupEntity extends AbstractGroup { ++ TestGroupEntity(Entity owner, String displayName) { ++ super([:], owner) ++ this.displayName = displayName ++ sensors.putAll([Children: new BasicAttributeSensor<Integer>(Integer.class, "Children", ++ "Direct children of this group"), DataRate: new BasicAttributeSensor<String>(String.class, "DataRate")]) ++ } ++ ++ TestGroupEntity addOwnedChild(Entity child) { ++ super.addOwnedChild(child) ++ setAttribute(getSensor("Children"), ownedChildren.size()) ++ return this ++ } ++ ++ public <T> Task<T> invoke(Effector<T> eff, Map<String, ?> parameters) { ++ return null ++ } ++ } ++ ++ ++ private class TestDataEntity extends AbstractEntity { ++ private List<Location> testLocations = [ ++ new SimulatedLocation([id: "us-east-1", name:"US-East-1", iso3166: "US-CA", displayName:"US-East-1", streetAddress:"Northern Virginia, USA", description:"Northern Virginia (approx)", ++ latitude:38.0,longitude:-76.0]), ++ new SimulatedLocation([id: "us-west-1", name:"US-West-1", iso3166: "US-VA", displayName:"US-West-1", streetAddress:"Northern California, USA", description:"Northern California", ++ latitude:40.0,longitude:-120.0]), ++ new SimulatedLocation([id: "eu-west-1", name:"EU-West-1", iso3166: "IE", displayName:"EU-West-1", streetAddress:"Dublin, Ireland", description:"Dublin, Ireland", ++ latitude:53.34778,longitude:-6.25972]) ++ ]; ++ private List<Policy> testPolicies = [ ++ new GeneralPurposePolicy([id: 'CTS1', name: 'chase-the-sun', displayName: 'Chase the Sun', policyStatus: 'Suspended', description: 'Chasing the sun, meaning chase the activity when certain parts of the earth are awake']), ++ new GeneralPurposePolicy([id: 'CTM1', name: 'chase-the-moon', displayName: 'Chase the Moon', policyStatus: 'Active']) ++ ]; ++ TestDataEntity(Entity owner, String displayName) { ++ super([:], owner) ++ ++ this.displayName = displayName ++ this.locations = testLocations; ++ this.policies = testPolicies; ++ TestEffector startDB = new TestEffector("Start DB", "This will start the database", ++ new ArrayList<ParameterType<?>>()) ++ TestEffector stopDB = new TestEffector("Stop DB", "This will stop the database", ++ new ArrayList<ParameterType<?>>()) ++ TestEffector restartDB = new TestEffector("Restart DB", "This will restart the DB", ++ new ArrayList<ParameterType<?>>()) ++ ++ this.effectors.putAll(["Start DB": startDB, "Stop DB": stopDB, "Restart DB": restartDB]) ++ ++ this.sensors.putAll( ++ [Happiness: new BasicAttributeSensor<String>(String.class, "Happiness"), ++ Cache: new BasicAttributeSensor<String>(String.class, "Cache", "Some cache metric"), ++ Sync: new BasicAttributeSensor<String>(String.class, "Sync", "Synchronization strategy")] ++ ) ++ ++ setAttribute(getSensor("Happiness"), 50) ++ setAttribute(getSensor("Cache"), 200) ++ setAttribute(getSensor("Sync"), "Moop") ++ } ++ ++ public <T> Task<T> invoke(Effector<T> eff, Map<String, ?> parameters) { ++ return null ++ } ++ } ++ ++ private class TestTomcatEntity extends AbstractEntity { ++ //FIXME should use typed keys not strings ++ private Map hackMeIn = [ ++ "http.port": 8080, ++ "webapp.tomcat.shutdownPort": 666, ++ "jmx.port": 1000, ++ "webapp.reqs.processing.time": 100, ++ "test.sensor": 17 ++ ] ++ ++ private List<Location> testLocations = [ ++ new SimulatedLocation([id: "us-east-1", name:"US-East-1", iso3166: "US-VA", displayName:"US-East-1", streetAddress:"Northern Virginia, USA", description:"Northern Virginia (approx)", ++ latitude:38.0,longitude:-76.0]) ++ ]; ++ private List<Policy> testPolicies = [ ++ new GeneralPurposePolicy([id: 'FTM1', name: 'follow-the-money', displayName: 'Follow the Money', policyStatus: 'Suspended']), ++ new GeneralPurposePolicy([id: 'FTA1', name: 'follow-the-action', displayName: 'Follow the Action', policyStatus: 'Active']) ++ ]; ++ ++ ++ public TestTomcatEntity(Entity owner, String displayName) { ++ super([:], owner) ++ this.displayName = displayName ++ this.locations = testLocations; ++ this.policies = testPolicies; ++ ++ // Stealing the sensors from TomcatNode ++ this.sensors.putAll(new TomcatServer().sensors) ++ ++ List<ParameterType<?>> parameterTypeList = new ArrayList<ParameterType<?>>() ++ ParameterType tomcatStartLocation = new BasicParameterType("Location", new ArrayList<String>().class) ++ ParameterType actionDate = new BasicParameterType("Date", Date.class) ++ parameterTypeList.add(tomcatStartLocation) ++ parameterTypeList.add(actionDate) ++ ++ ++ // Don't appear to be any effectors in TomcatServer ++ TestEffector startTomcat = new TestEffector("Start Tomcat", ++ "This will start Tomcat at a specified location", ++ parameterTypeList) ++ TestEffector stopTomcat = new TestEffector("Stop Tomcat", ++ "This will stop tomcat at its current location", ++ new Collections.SingletonList(actionDate)) ++ TestEffector restartTomcat = new TestEffector("Restart Tomcat", ++ "This will restart tomcat in its current location", ++ new ArrayList<ParameterType<?>>()) ++ ++ this.effectors.putAll([ "Start Tomcat": startTomcat, ++ "Stop Tomcat": stopTomcat, ++ "Restart Tomcat": restartTomcat]) ++ ++ for (def i = 0; i < 10; ++i) { ++ this.getExecutionContext().submit([ ++ tags:["EFFECTOR"], ++ tag:this, ++ displayName: "Update values (test " + i + ")", ++ description: "This updates sensor values"], ++ new MyRunnable(this)); ++ } ++ } ++ ++ public <T> Task<T> invoke(Effector<T> eff, Map<String, ?> parameters) { ++ System.out.println(parameters as JSON) ++ return null ++ } ++ ++ protected class MyRunnable implements Runnable { ++ EntityLocal entity ++ protected MyRunnable(Entity e) { ++ this.entity = e ++ } ++ void run() { ++ while (true) { ++ Map ss = entity.getSensors() ++ for (String key: hackMeIn.keySet()) { ++ def s = ss[key] ++ if (s != null){ ++ entity.setAttribute(s, ++ hackMeIn[key] + ManagementContextService.ID_GENERATOR + ++ ((int) 1000 * Math.random())) ++ } ++ } ++ Thread.sleep(5000) ++ } ++ } ++ } ++ } ++} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/utils/brooklyn/web/console/security/AnyoneSecurityProvider.java ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/utils/brooklyn/web/console/security/AnyoneSecurityProvider.java index 0000000,0000000..ae5685d new file mode 100644 --- /dev/null +++ b/usage/web-console/grails-app/utils/brooklyn/web/console/security/AnyoneSecurityProvider.java @@@ -1,0 -1,0 +1,23 @@@ ++package brooklyn.web.console.security; ++ ++import javax.servlet.http.HttpSession; ++ ++/** provider who allows everyone */ ++public class AnyoneSecurityProvider implements SecurityProvider { ++ ++ @Override ++ public boolean isAuthenticated(HttpSession session) { ++ return true; ++ } ++ ++ @Override ++ public boolean authenticate(HttpSession session, String user, String password) { ++ return true; ++ } ++ ++ @Override ++ public boolean logout(HttpSession session) { ++ return true; ++ } ++ ++} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/utils/brooklyn/web/console/security/BlackholeSecurityProvider.java ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/utils/brooklyn/web/console/security/BlackholeSecurityProvider.java index 0000000,0000000..6b46e99 new file mode 100644 --- /dev/null +++ b/usage/web-console/grails-app/utils/brooklyn/web/console/security/BlackholeSecurityProvider.java @@@ -1,0 -1,0 +1,23 @@@ ++package brooklyn.web.console.security; ++ ++import javax.servlet.http.HttpSession; ++ ++/** provider who disallows everyone */ ++public class BlackholeSecurityProvider implements SecurityProvider { ++ ++ @Override ++ public boolean isAuthenticated(HttpSession session) { ++ return false; ++ } ++ ++ @Override ++ public boolean authenticate(HttpSession session, String user, String password) { ++ return false; ++ } ++ ++ @Override ++ public boolean logout(HttpSession session) { ++ return true; ++ } ++ ++} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/utils/brooklyn/web/console/security/ConfigLoader.java ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/utils/brooklyn/web/console/security/ConfigLoader.java index 0000000,0000000..e103cf1 new file mode 100644 --- /dev/null +++ b/usage/web-console/grails-app/utils/brooklyn/web/console/security/ConfigLoader.java @@@ -1,0 -1,0 +1,36 @@@ ++package brooklyn.web.console.security; ++ ++import java.util.Enumeration; ++ ++import org.codehaus.groovy.grails.web.context.ServletContextHolder; ++ ++import brooklyn.config.BrooklynProperties; ++import brooklyn.util.internal.BrooklynSystemProperties; ++ ++/** convenience class for accessing system properties, ++ * currently reading from brooklyn.properties ++ * but ideally reading from the management context ++ * <p> ++ * see {@link BrooklynSystemProperties} for list of keys ++ * (those starting brooklyn.security are relevant) ++ */ ++public class ConfigLoader { ++ ++ static BrooklynProperties _props; ++ ++ static synchronized BrooklynProperties getProps() { ++ if (_props!=null) return _props; ++ _props = BrooklynProperties.Factory.newWithSystemAndEnvironment(); ++ ++ Enumeration ae = ServletContextHolder.getServletContext().getAttributeNames(); ++ while (ae.hasMoreElements()) { ++ String k = (String)ae.nextElement(); ++ Object v = ServletContextHolder.getServletContext().getAttribute(k); ++ _props.put(k, v); ++ } ++ return _props; ++ } ++ ++ public static Object getConfig(String key) { return getProps().getFirst(key); } ++ ++} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/utils/brooklyn/web/console/security/DelegatingSecurityProvider.java ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/utils/brooklyn/web/console/security/DelegatingSecurityProvider.java index 0000000,0000000..23ae10e new file mode 100644 --- /dev/null +++ b/usage/web-console/grails-app/utils/brooklyn/web/console/security/DelegatingSecurityProvider.java @@@ -1,0 -1,0 +1,49 @@@ ++package brooklyn.web.console.security; ++ ++import javax.servlet.http.HttpSession; ++ ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++import brooklyn.util.internal.BrooklynSystemProperties; ++ ++public class DelegatingSecurityProvider implements SecurityProvider { ++ ++ public static final Logger log = LoggerFactory.getLogger(DelegatingSecurityProvider.class); ++ ++ private SecurityProvider targetProvider; ++ ++ public synchronized SecurityProvider getTargetProvider() { ++ if (this.targetProvider!=null) return targetProvider; ++ Object className = ConfigLoader.getConfig(BrooklynSystemProperties.SECURITY_PROVIDER.getPropertyName()); ++ if (className==null) { ++ className = ExplicitUsersSecurityProvider.class.getCanonicalName(); ++ log.info("Web console using default security provider: "+className); ++ } else { ++ log.info("Web console using specified security provider: "+className); ++ } ++ try { ++ targetProvider = (SecurityProvider) Class.forName(""+className).newInstance(); ++ } catch (Exception e) { ++ log.warn("Web console unable to instantiate security provider "+className+"; all logins are being disallowed"); ++ targetProvider = new BlackholeSecurityProvider(); ++ } ++ return targetProvider; ++ } ++ ++ @Override ++ public boolean isAuthenticated(HttpSession session) { ++ return getTargetProvider().isAuthenticated(session); ++ } ++ ++ @Override ++ public boolean authenticate(HttpSession session, String user, String password) { ++ return getTargetProvider().authenticate(session, user, password); ++ } ++ ++ @Override ++ public boolean logout(HttpSession session) { ++ return getTargetProvider().logout(session); ++ } ++ ++} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/utils/brooklyn/web/console/security/ExplicitUsersSecurityProvider.java ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/utils/brooklyn/web/console/security/ExplicitUsersSecurityProvider.java index 0000000,0000000..a4da6ca new file mode 100644 --- /dev/null +++ b/usage/web-console/grails-app/utils/brooklyn/web/console/security/ExplicitUsersSecurityProvider.java @@@ -1,0 -1,0 +1,98 @@@ ++package brooklyn.web.console.security; ++ ++import java.util.LinkedHashSet; ++import java.util.Set; ++import java.util.StringTokenizer; ++ ++import javax.servlet.http.HttpSession; ++ ++import org.codehaus.groovy.grails.web.context.ServletContextHolder; ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++import brooklyn.config.BrooklynServiceAttributes; ++import brooklyn.util.internal.BrooklynSystemProperties; ++ ++public class ExplicitUsersSecurityProvider implements SecurityProvider { ++ ++ public static final Logger LOG = LoggerFactory.getLogger(ExplicitUsersSecurityProvider.class); ++ ++ public static final String AUTHENTICATION_KEY = ExplicitUsersSecurityProvider.class.getCanonicalName()+"."+"AUTHENTICATED"; ++ ++ @Override ++ public boolean isAuthenticated(HttpSession session) { ++ if (session==null) return false; ++ if (allowAnyUser) return true; ++ Object value = session.getAttribute(AUTHENTICATION_KEY); ++ return (value!=null); ++ } ++ ++ private boolean allowAnyUserWithValidPass = false; ++ private boolean allowDefaultUsers = false; ++ private boolean allowAnyUser = false; ++ ++ private Set<String> allowedUsers = null; ++ private synchronized void initialize() { ++ if (allowedUsers!=null) return; ++ allowedUsers = new LinkedHashSet<String>(); ++ Object users = ConfigLoader.getConfig(BrooklynSystemProperties.SECURITY_PROVIDER_EXPLICIT__USERS.getPropertyName()); ++ if (users==null) { ++ allowDefaultUsers = true; ++ } else if ("*".equals(users)) { ++ allowAnyUserWithValidPass = true; ++ } else { ++ StringTokenizer t = new StringTokenizer(""+users, ","); ++ while (t.hasMoreElements()) { ++ allowedUsers.add((""+t.nextElement()).trim()); ++ } ++ } ++ ++ if (ServletContextHolder.getServletContext().getAttribute(BrooklynServiceAttributes.BROOKLYN_AUTOLOGIN_USERNAME)!=null) { ++ LOG.warn("Use of legacy AUTOLOGIN; replace with setting BrooklynSystemProperties.SECURITY_PROVIDER to "+AnyoneSecurityProvider.class.getCanonicalName()); ++ allowAnyUser = true; ++ } ++ } ++ ++ @Override ++ public boolean authenticate(HttpSession session, String user, String password) { ++ if (session==null) return false; ++ if (allowAnyUser) return true; ++ initialize(); ++ if (!allowAnyUserWithValidPass) { ++ if (allowDefaultUsers) { ++ if (user.equals("admin") && password.equals("password")) { ++ return allow(session, user); ++ } ++ } ++ if (!allowedUsers.contains(user)) { ++ LOG.info("Web console rejecting unknown user "+user); ++ return false; ++ } ++ } ++ Object actualP = ConfigLoader.getConfig(BrooklynSystemProperties.SECURITY_PROVIDER_EXPLICIT__PASSWORD(user).getPropertyName()); ++ if (actualP==null) { ++ LOG.info("Web console rejecting passwordless user "+user); ++ return false; ++ } else if (!actualP.equals(password)){ ++ LOG.info("Web console rejecting bad password for user "+user); ++ return false; ++ } else { ++ //password is good ++ return allow(session, user); ++ } ++ } ++ ++ private boolean allow(HttpSession session, String user) { ++ LOG.info("Web console "+getClass().getSimpleName()+" authenticated user "+user); ++ session.setAttribute(AUTHENTICATION_KEY, user); ++ return true; ++ } ++ ++ @Override ++ public boolean logout(HttpSession session) { ++ if (session==null) return false; ++ session.removeAttribute(AUTHENTICATION_KEY); ++ return true; ++ } ++ ++} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/utils/brooklyn/web/console/security/SecurityProvider.java ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/utils/brooklyn/web/console/security/SecurityProvider.java index 0000000,0000000..9dcfaf6 new file mode 100644 --- /dev/null +++ b/usage/web-console/grails-app/utils/brooklyn/web/console/security/SecurityProvider.java @@@ -1,0 -1,0 +1,12 @@@ ++package brooklyn.web.console.security; ++ ++import javax.servlet.http.HttpSession; ++ ++public interface SecurityProvider { ++ ++ public boolean isAuthenticated(HttpSession session); ++ ++ public boolean authenticate(HttpSession session, String user, String password); ++ ++ public boolean logout(HttpSession session); ++} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/utils/brooklyn/web/console/security/WebConsoleSecurity.java ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/utils/brooklyn/web/console/security/WebConsoleSecurity.java index 0000000,0000000..185ddc4 new file mode 100644 --- /dev/null +++ b/usage/web-console/grails-app/utils/brooklyn/web/console/security/WebConsoleSecurity.java @@@ -1,0 -1,0 +1,12 @@@ ++package brooklyn.web.console.security; ++ ++public class WebConsoleSecurity { ++ ++ static SecurityProvider instance; ++ ++ public static synchronized SecurityProvider getInstance() { ++ if (instance==null) instance = new DelegatingSecurityProvider(); ++ return instance; ++ } ++ ++} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/grails-app/views/login/auth.gsp ---------------------------------------------------------------------- diff --cc usage/web-console/grails-app/views/login/auth.gsp index 854d606,854d606..5690413 --- a/usage/web-console/grails-app/views/login/auth.gsp +++ b/usage/web-console/grails-app/views/login/auth.gsp @@@ -48,7 -48,7 +48,7 @@@ <g:if test='${flash.message}'> <div class='login_message'>${flash.message}</div> </g:if> -- <div class='fheader'>Please Login..</div> ++ <div class='fheader'>Please Login</div> <form action='${postUrl}' method='POST' id='loginForm' class='cssform' autocomplete='off'> <p> <label for='username'>Login ID</label> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/d3c8046e/usage/web-console/pom.xml ---------------------------------------------------------------------- diff --cc usage/web-console/pom.xml index 5639933,5639933..d3bb766 --- a/usage/web-console/pom.xml +++ b/usage/web-console/pom.xml @@@ -241,13 -241,13 +241,12 @@@ <version>1.1.2</version> </dependency> -- <!-- Grails defaults to Ehache for the second-level Hibernate cache. --> ++<!-- don't user hibernate <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>3.3.1.GA</version> <exclusions> -- <!-- We are pulling in ehcache-core below --> <exclusion> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> @@@ -261,13 -261,13 +260,12 @@@ <version>1.7.1</version> </dependency> -- <!-- For ease of development and testing, we include the HSQLDB database. --> ++--> <dependency> <groupId>hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>1.8.0.10</version> </dependency> -- <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId>
