Re: Use LoginModuleProxy (was: Make Whiteboard accessible through ContentRepository)
On Thu, Feb 13, 2014 at 11:49 PM, Tobias Bocanegra tri...@apache.org wrote: this callback would rely on some sort of (non-osgi) list of pre-configured factories, right? eg some sort of LoginModuleFactoryRegistryImpl that is added to the authentication configuration? Sort of. As Jukka mentioned the code which configures Oak programatically in non OSGi env can also provide a list of LoginModuleFactory as part of Security setup. In OSGi env get them via DS this has one caveat, that you could register 1 factory per class (if you are using the factories class name as identifier). otherwise you would need to introduce some kind of factory pid. Yup. For completeness and to cover all cases you can have some factory property (similar to service property in OSGi). And that can be passed to LoginModuleFactory as argument so that it can instantiate right LM impl Chetan Mehrotra
Re: Make Whiteboard accessible through ContentRepository
On Thu, Feb 13, 2014 at 12:45 PM, Tobias Bocanegra tri...@apache.org wrote: I don't quite follow. can you give an example of what would be in the jaas.conf and where you instantiate the ProxyLoginModule ? A rough sketch would be ... jaas.config oakAuth { org.apache.jackrabbit.oak.security.ProxyLoginModule REQUIRED loginModuleFactoryClass=org.apache.jackrabbit.oak.security.LdapLoginModuleFactory authIdentity={USERNAME} useSSL=false debug=true; }; public class ProxyLoginModule implements LoginModule{ private LoginModule delegate; public void initialize(Subject subject, CallbackHandler callbackHandler, MapString, ? sharedState, MapString, ? options){ LMFactoryProviderCallBack lmfcb = new LMFactoryProviderCallBack() factory = callbackHandler.handle([lmfcb]); LoginModuleFactory factory = lmfcb.getLoginModuleFactoryProvider() .getFactory(options.get(loginModuleFactoryClass)); delegate = factory.createLoginModule(); delegate.initialize(subject, callbackHandler, sharedState, options); } ... //Use delegate for other operations } The flow would involve following steps 1. User mentions the ProxyLoginModule in jaas entry and provide the factory class name in the config. JAAS logic would be instantiating the Proxy LM 2. Oak provides a callback using which Proxy LM can obtain the factory 3. Upon init the proxy would initialize the delegate from factory 4. The delegate is used for later calls 5. LM if required can still use the config from jaas or ot is configured via factory itself Note here I preferred using the callback to get LM access the outer layer services instead of using a custom config. The custom config mode works fine in standalone case where the application is the sole user of JAAS system. Hence it works fine for Karaf/OSGi env But that might not work properly in App server env where app server itself uses jaas. So to avoid interfering in embedded mode callback should be preferred. Chetan Mehrotra
Re: Make Whiteboard accessible through ContentRepository
hi, On Thursday, February 13, 2014, Chetan Mehrotra chetan.mehro...@gmail.com wrote: On Thu, Feb 13, 2014 at 12:45 PM, Tobias Bocanegra tri...@apache.orgjavascript:; wrote: I don't quite follow. can you give an example of what would be in the jaas.conf and where you instantiate the ProxyLoginModule ? A rough sketch would be ... jaas.config oakAuth { org.apache.jackrabbit.oak.security.ProxyLoginModule REQUIRED loginModuleFactoryClass=org.apache.jackrabbit.oak.security.LdapLoginModuleFactory authIdentity={USERNAME} useSSL=false debug=true; }; public class ProxyLoginModule implements LoginModule{ private LoginModule delegate; public void initialize(Subject subject, CallbackHandler callbackHandler, MapString, ? sharedState, MapString, ? options){ LMFactoryProviderCallBack lmfcb = new LMFactoryProviderCallBack() factory = callbackHandler.handle([lmfcb]); LoginModuleFactory factory = lmfcb.getLoginModuleFactoryProvider() .getFactory(options.get(loginModuleFactoryClass)); delegate = factory.createLoginModule(); delegate.initialize(subject, callbackHandler, sharedState, options); } ... //Use delegate for other operations } The flow would involve following steps 1. User mentions the ProxyLoginModule in jaas entry and provide the factory class name in the config. JAAS logic would be instantiating the Proxy LM 2. Oak provides a callback using which Proxy LM can obtain the factory 3. Upon init the proxy would initialize the delegate from factory 4. The delegate is used for later calls 5. LM if required can still use the config from jaas or ot is configured via factory itself Note here I preferred using the callback to get LM access the outer layer services instead of using a custom config. The custom config mode works fine in standalone case where the application is the sole user of JAAS system. Hence it works fine for Karaf/OSGi env But that might not work properly in App server env where app server itself uses jaas. So to avoid interfering in embedded mode callback should be preferred. Chetan Mehrotra ok, that how I thought it would be. if we can live with the restriction that we need to use a proxy login module for our LMs, we're good. btw: if you look at the current ExternalLoginModule , I already used a LMF but only for the osgi case. if we could use a ProxyLM, that would simplify the code a lot. regards Toby
Re: Make Whiteboard accessible through ContentRepository
Hi, On Wed, Feb 12, 2014 at 10:15 AM, Tobias Bocanegra tri...@apache.org wrote: But this LoginBackend is in the end something similar like a specialized ServiceRegistry. So why not use the whiteboard instead? You're seeing service registries everywhere. :-) No, the idea of the LoginBackend is to be contain all the authentication logic that uses whatever dependencies that are needed. See the end of this message for a quick draft of how this could work. Or we could even use a delegate LoginModule like in the ProxyLoginModule case Chetan described. BR, Jukka Zitting // MyLoginModule.java public class MyLoginModule implements LoginModule { private Subject subject; private CallbackHandler callbackHandler; private LoginBackend backend; private boolean success; private final SetPrincipal principals = newHashSet(); private final SetObject credentials = newHashSet(); // can be overridden to work with LoginModuleFactory, or other binding mechanisms protected LoginBackend getLoginBackend(MapString, ? options) { return (LoginBackend) options.get(LoginBackend.class.getName()); } @Override public void initialize( Subject subject, CallbackHandler callbackHandler, MapString, ? sharedState, MapString, ? options) { this.subject = subject; this.callbackHandler = callbackHandler; this.backend = getLoginBackend(options); this.success = false; } @Override public boolean login() throws LoginException { if (backend == null) { return false; } // Perform login using credential information from callbackHandler. // Return authenticated principals and the used credentials in the // given sets. Throw LoginException if authentication fails. backend.login(callbackHandler, principals, credentials); success = true; return true; } @Override public boolean commit() throws LoginException { if (backend == null) { return false; } if (success) { // add login details to the subject subject.getPrincipals().addAll(principals); subject.getPublicCredentials().addAll(credentials); } else { // clear state principals.clear(); credentials.clear(); } return true; } @Override public boolean abort() throws LoginException { if (backend == null) { return false; } // clear state principals.clear(); credentials.clear(); success = false; return false; } @Override public boolean logout() throws LoginException { if (backend == null) { return false; } if (success) { // remove login details from the subject subject.getPrincipals().removeAll(principals); subject.getPublicCredentials().removeAll(credentials); } // clear state principals.clear(); credentials.clear(); success = false; return true; } }
Re: Make Whiteboard accessible through ContentRepository
Hi, On Thu, Feb 13, 2014 at 4:11 AM, Chetan Mehrotra chetan.mehro...@gmail.com wrote: Note here I preferred using the callback to get LM access the outer layer services instead of using a custom config. The custom config mode works fine in standalone case where the application is the sole user of JAAS system. Hence it works fine for Karaf/OSGi env But that might not work properly in App server env where app server itself uses jaas. So to avoid interfering in embedded mode callback should be preferred. The problem with using a CallbackHandler for such things is that it forces the client code (that controls the CallbackHandler) to understand about the LoginModule implementation. Thus you can't use such a LoginModule with a client that relies only on the standard JAAS API. As mentioned in a previous message, it's better to use the options map that comes from the runtime environment and can thus be controlled without touching the client code. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi, On Thu, Feb 13, 2014 at 8:34 AM, Jukka Zitting jukka.zitt...@gmail.com wrote: On Wed, Feb 12, 2014 at 10:15 AM, Tobias Bocanegra tri...@apache.org wrote: But this LoginBackend is in the end something similar like a specialized ServiceRegistry. So why not use the whiteboard instead? You're seeing service registries everywhere. :-) I'm having nightmares of them :-) ! No, the idea of the LoginBackend is to be contain all the authentication logic that uses whatever dependencies that are needed. See the end of this message for a quick draft of how this could work. Well, but the LoginBackend would be specific to the type of LoginModule. For LDAP its the LDAP backend, for repository users, its the OakUserLoginBackend, etc. How would you wire this to the specific LoginModule instance? Or we could even use a delegate LoginModule like in the ProxyLoginModule case Chetan described. (I'll fork that thread and respond there) Regards, Toby BR, Jukka Zitting // MyLoginModule.java public class MyLoginModule implements LoginModule { private Subject subject; private CallbackHandler callbackHandler; private LoginBackend backend; private boolean success; private final SetPrincipal principals = newHashSet(); private final SetObject credentials = newHashSet(); // can be overridden to work with LoginModuleFactory, or other binding mechanisms protected LoginBackend getLoginBackend(MapString, ? options) { return (LoginBackend) options.get(LoginBackend.class.getName()); } @Override public void initialize( Subject subject, CallbackHandler callbackHandler, MapString, ? sharedState, MapString, ? options) { this.subject = subject; this.callbackHandler = callbackHandler; this.backend = getLoginBackend(options); this.success = false; } @Override public boolean login() throws LoginException { if (backend == null) { return false; } // Perform login using credential information from callbackHandler. // Return authenticated principals and the used credentials in the // given sets. Throw LoginException if authentication fails. backend.login(callbackHandler, principals, credentials); success = true; return true; } @Override public boolean commit() throws LoginException { if (backend == null) { return false; } if (success) { // add login details to the subject subject.getPrincipals().addAll(principals); subject.getPublicCredentials().addAll(credentials); } else { // clear state principals.clear(); credentials.clear(); } return true; } @Override public boolean abort() throws LoginException { if (backend == null) { return false; } // clear state principals.clear(); credentials.clear(); success = false; return false; } @Override public boolean logout() throws LoginException { if (backend == null) { return false; } if (success) { // remove login details from the subject subject.getPrincipals().removeAll(principals); subject.getPublicCredentials().removeAll(credentials); } // clear state principals.clear(); credentials.clear(); success = false; return true; } }
Use LoginModuleProxy (was: Make Whiteboard accessible through ContentRepository)
Hi, On Thu, Feb 13, 2014 at 8:55 AM, Jukka Zitting jukka.zitt...@gmail.com wrote: Hi, On Thu, Feb 13, 2014 at 4:11 AM, Chetan Mehrotra chetan.mehro...@gmail.com wrote: Note here I preferred using the callback to get LM access the outer layer services instead of using a custom config. The custom config mode works fine in standalone case where the application is the sole user of JAAS system. Hence it works fine for Karaf/OSGi env But that might not work properly in App server env where app server itself uses jaas. So to avoid interfering in embedded mode callback should be preferred. The problem with using a CallbackHandler for such things is that it forces the client code (that controls the CallbackHandler) to understand about the LoginModule implementation. Thus you can't use such a LoginModule with a client that relies only on the standard JAAS API. well yes. but I think the LMs are never generic. They need to understand the host application they are running in; especially with more complex setup of different LMs. In reality, I don't think that a LM that doesn't extend from Oak's AbstractLoginModule really works great. As mentioned in a previous message, it's better to use the options map that comes from the runtime environment and can thus be controlled without touching the client code. I think both are needed. As I wrote above, I think tightly Oak coupled login modules even benefit from a fixed set of callback handlers. i.e. it is more robust to write: RepositoryCallback rcb = new RepositoryCallback(); callbackHandler.handle(new Callback[]{rcb}); securityProvider = rcb.getSecurityProvider(); than: securityProvider = options.get(SecurityProvider.class.getName()); It is more transparent to the developer what backend objects are retrievable, IMO.
Use LoginModuleProxy (was: Make Whiteboard accessible through ContentRepository)
Hi, On Thu, Feb 13, 2014 at 1:11 AM, Chetan Mehrotra chetan.mehro...@gmail.com wrote: On Thu, Feb 13, 2014 at 12:45 PM, Tobias Bocanegra tri...@apache.org wrote: I don't quite follow. can you give an example of what would be in the jaas.conf and where you instantiate the ProxyLoginModule ? A rough sketch would be ... jaas.config oakAuth { org.apache.jackrabbit.oak.security.ProxyLoginModule REQUIRED loginModuleFactoryClass=org.apache.jackrabbit.oak.security.LdapLoginModuleFactory authIdentity={USERNAME} useSSL=false debug=true; }; public class ProxyLoginModule implements LoginModule{ private LoginModule delegate; public void initialize(Subject subject, CallbackHandler callbackHandler, MapString, ? sharedState, MapString, ? options){ LMFactoryProviderCallBack lmfcb = new LMFactoryProviderCallBack() factory = callbackHandler.handle([lmfcb]); LoginModuleFactory factory = lmfcb.getLoginModuleFactoryProvider() .getFactory(options.get(loginModuleFactoryClass)); delegate = factory.createLoginModule(); delegate.initialize(subject, callbackHandler, sharedState, options); } ... //Use delegate for other operations } The flow would involve following steps 1. User mentions the ProxyLoginModule in jaas entry and provide the factory class name in the config. JAAS logic would be instantiating the Proxy LM 2. Oak provides a callback using which Proxy LM can obtain the factory this callback would rely on some sort of (non-osgi) list of pre-configured factories, right? eg some sort of LoginModuleFactoryRegistryImpl that is added to the authentication configuration? 3. Upon init the proxy would initialize the delegate from factory 4. The delegate is used for later calls 5. LM if required can still use the config from jaas or ot is configured via factory itself this has one caveat, that you could register 1 factory per class (if you are using the factories class name as identifier). otherwise you would need to introduce some kind of factory pid. Note here I preferred using the callback to get LM access the outer layer services instead of using a custom config. The custom config mode works fine in standalone case where the application is the sole user of JAAS system. Hence it works fine for Karaf/OSGi env But that might not work properly in App server env where app server itself uses jaas. So to avoid interfering in embedded mode callback should be preferred. regards, toby
Re: Make Whiteboard accessible through ContentRepository
Hi, On Wed, Feb 12, 2014 at 1:37 AM, Tobias Bocanegra tri...@apache.org wrote: On Tue, Feb 11, 2014 at 4:38 PM, Tobias Bocanegra tri...@apache.org wrote: but then, why does the Whiteboard interface has a register() method? This indicates to me, that there is a global service registry behind that can be used by all other users of the whiteboard. The whiteboard pattern requires mechanisms for registering services and tracking them. Note that the Whiteboard interface explicitly does not have a getService() method, only track() method used by event sources in the whiteboard pattern. Also, using the whiteboard in the tests make them very easy configurable and simulates a bit better how OSGi will work. for example in the ExternalLoginModuleTest, I can just do: This seems too complicated. Why not just pass the dependencies directly to the LoginModule component, using the pattern I suggested earlier? addendum: If I want to achieve the same without the whiteboard, I would need to: This also seems too complicated. The additional work is that I need to re-invent some sort of service registry for the LoginModuleServiceProviderConfigurationImpl and extend the SecurityProvider with another configuration. Also, I limit the interfaces to be used in the LoginModules to the ones implementing the LoginModuleService interface. you might say, this is more robust - I say, this is just more complicated and has tighter coupling. Not more robust, just way too complicated. :-) I don't see why stuff like LoginModuleServiceProviderConfigurationImpl or even SecurityProvider would need to be involved here. Just pass the required dependencies directly to the LoginModule implementation and forget the rest of the stack. There should be no need to route those dependencies through multiple layers of provider/configuration objects. The way I see it, the perceived need for a service registry is just a side-effect of trying to force things to such a pattern. This is all the wiring that we should need for Java-only environments: LoginBackend backend = new LoginBackend(dependency1, dependency2, ...); MapString, ? options = singletonMap( LoginBackend.class.getName(), backend); Configuration.setConfiguration(new ConfigurationExtender( Configuration.getConfiguration(), options)); Or in the OSGi case, make LoginBackend a service and use something like the LoginModuleFactory Chetan mentioned. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi, On Wed, Feb 12, 2014 at 2:00 AM, Jukka Zitting jukka.zitt...@gmail.com wrote: On Wed, Feb 12, 2014 at 1:37 AM, Tobias Bocanegra tri...@apache.org wrote: On Tue, Feb 11, 2014 at 4:38 PM, Tobias Bocanegra tri...@apache.org wrote: but then, why does the Whiteboard interface has a register() method? This indicates to me, that there is a global service registry behind that can be used by all other users of the whiteboard. The whiteboard pattern requires mechanisms for registering services and tracking them. Note that the Whiteboard interface explicitly does not have a getService() method, only track() method used by event sources in the whiteboard pattern. Also, using the whiteboard in the tests make them very easy configurable and simulates a bit better how OSGi will work. for example in the ExternalLoginModuleTest, I can just do: This seems too complicated. Why not just pass the dependencies directly to the LoginModule component, using the pattern I suggested earlier? addendum: If I want to achieve the same without the whiteboard, I would need to: This also seems too complicated. The additional work is that I need to re-invent some sort of service registry for the LoginModuleServiceProviderConfigurationImpl and extend the SecurityProvider with another configuration. Also, I limit the interfaces to be used in the LoginModules to the ones implementing the LoginModuleService interface. you might say, this is more robust - I say, this is just more complicated and has tighter coupling. Not more robust, just way too complicated. :-) I don't see why stuff like LoginModuleServiceProviderConfigurationImpl or even SecurityProvider would need to be involved here. Just pass the required dependencies directly to the LoginModule implementation and forget the rest of the stack. There should be no need to route those dependencies through multiple layers of provider/configuration objects. The way I see it, the perceived need for a service registry is just a side-effect of trying to force things to such a pattern. This is all the wiring that we should need for Java-only environments: LoginBackend backend = new LoginBackend(dependency1, dependency2, ...); MapString, ? options = singletonMap( LoginBackend.class.getName(), backend); Configuration.setConfiguration(new ConfigurationExtender( Configuration.getConfiguration(), options)); Or in the OSGi case, make LoginBackend a service and use something like the LoginModuleFactory Chetan mentioned. But this LoginBackend is in the end something similar like a specialized ServiceRegistry. So why not use the whiteboard instead? However, I give it a try refactoring it with a LoginBackend - even if only to avoid the callbacks. regards, toby
Re: Make Whiteboard accessible through ContentRepository
Hi, On Tue, Feb 11, 2014 at 11:56 PM, Chetan Mehrotra chetan.mehro...@gmail.com wrote: To address the same problem with Felix Jaas support one can make use of LoginModuleFactory [1]. Its job is to create LoginModule instances. One example of this is JdbcLoginModuleFactory [2]. It creates JdbcLoginModule and passes on the DataSource to the LoginModule instances. So instead of LoginModule _looking up_ the DataSource service it is provided with the DataSource instance. The factory itself was _provided_ with DataSource reference via DI (via Declarative Services) To implement a similar approach in non OSGi world following approach can be used 1. Have a ProxyLoginModule like [3]. The JAAS Config would refer to this class and would be able to create it 2. Have a LoginModuleFactory LMF (custom one) which is referred to in the JAAS Config. 3. One can register a custom LMF implementation with Oak and they would be passed on to SecurityProvider 3. ProxyLoginModule determines the type of LoginModuleFactory and obtains them via Callback 4. The LMF obtained is used to create the LoginModule instance Now same LoginModule (where most of the logic reside) can be shared between OSGi and non OSGi world. Further you can even share the LoginModuleFactory (if using non OSGi stuff only). For OSGi case the LMF would be managed via DS and its dependencies provided via DS For non OSGi case host application would wire up the LMF with its dependencies (via setters) and then register them with the Oak Interesting idea, but I think we should continue support the LM to be configured via the application container (eg. via jaas.conf). Regards, Toby Chetan Mehrotra [1] http://svn.apache.org/repos/asf/felix/trunk/jaas/src/main/java/org/apache/felix/jaas/LoginModuleFactory.java [2] http://svn.apache.org/repos/asf/felix/trunk/examples/jaas/lm-jdbc/src/main/java/org/apache/felix/example/jaas/jdbc/JdbcLoginModuleFactory.java [3] http://svn.apache.org/repos/asf/felix/trunk/jaas/src/main/java/org/apache/felix/jaas/boot/ProxyLoginModule.java On Wed, Feb 12, 2014 at 12:07 PM, Tobias Bocanegra tri...@apache.org wrote: Hi, On Tue, Feb 11, 2014 at 4:38 PM, Tobias Bocanegra tri...@apache.org wrote: On Tue, Feb 11, 2014 at 1:59 PM, Jukka Zitting jukka.zitt...@gmail.com wrote: On Mon, Feb 10, 2014 at 2:25 AM, Felix Meschberger fmesc...@adobe.com wrote: This thread indeed raises the question, why Oak has to come up with something (the Whiteboard) that is almost but not quite like OSGi instead of going all the way through ? This is a misunderstanding; we're not trying to reinvent OSGi. The Whiteboard interface is *only* an abstraction of the whiteboard pattern described in http://www.osgi.org/wiki/uploads/Links/whiteboard.pdf, and is used only for those cases in Oak where that pattern is useful. When running in an OSGi environment, the Whiteboard simply leverages the existing OSGi functionality. The Whiteboard in Oak is not a generic service registry, and is not supposed to become one. but then, why does the Whiteboard interface has a register() method? This indicates to me, that there is a global service registry behind that can be used by all other users of the whiteboard. Also, using the whiteboard in the tests make them very easy configurable and simulates a bit better how OSGi will work. for example in the ExternalLoginModuleTest, I can just do: whiteboard = oak.getWhiteboard(); whiteboard.register(SyncManager.class, new SyncManagerImpl(whiteboard), Collections.emptyMap()); whiteboard.register(ExternalIdentityProviderManager.class, new ExternalIDPManagerImpl(whiteboard), Collections.emptyMap()); If I need to register them with the login module, this would not work today, without hard wiring all possible services to the SecurityProvider. addendum: If I want to achieve the same without the whiteboard, I would need to: * Invent a new interface that allows to pass services/helpers to the login modules. eg a LoginModuleService interface * Create some sort of LoginModuleServiceProviderConfiguration * Create an implementation of the above that deals with OSGi but also can be used statically * Add the LoginModuleServiceProviderConfiguration to ServiceProvider.getConfiguration() * Add the interface to my ExternalIDPManagerImpl and SyncManagerImpl * in the login module, retrieve the LoginModuleServiceProviderConfiguration from the SecurityProvider, then find a service for SyncManager and ExternalIdentityProviderManager * in the non-osgi case, I would need to initialize the LoginModuleServiceProviderConfigurationImpl myself and add the 2 services and add the config to the securityprovider. The additional work is that I need to re-invent some sort of service registry for the LoginModuleServiceProviderConfigurationImpl and extend the SecurityProvider with another configuration. Also, I limit the interfaces to be used in
Re: Make Whiteboard accessible through ContentRepository
hi Interesting idea, but I think we should continue support the LM to be configured via the application container (eg. via jaas.conf). definitely! regards angela
Re: Make Whiteboard accessible through ContentRepository
hi all i tend to agree with tobi that this might end up with something that is really complicated without too much benefit. so, we may give it a try but i wouldn't not invest too much time. just my humble opinion... angela On 12/02/14 07:37, Tobias Bocanegra tri...@apache.org wrote: Hi, On Tue, Feb 11, 2014 at 4:38 PM, Tobias Bocanegra tri...@apache.org wrote: On Tue, Feb 11, 2014 at 1:59 PM, Jukka Zitting jukka.zitt...@gmail.com wrote: On Mon, Feb 10, 2014 at 2:25 AM, Felix Meschberger fmesc...@adobe.com wrote: This thread indeed raises the question, why Oak has to come up with something (the Whiteboard) that is almost but not quite like OSGi instead of going all the way through ? This is a misunderstanding; we're not trying to reinvent OSGi. The Whiteboard interface is *only* an abstraction of the whiteboard pattern described in http://www.osgi.org/wiki/uploads/Links/whiteboard.pdf, and is used only for those cases in Oak where that pattern is useful. When running in an OSGi environment, the Whiteboard simply leverages the existing OSGi functionality. The Whiteboard in Oak is not a generic service registry, and is not supposed to become one. but then, why does the Whiteboard interface has a register() method? This indicates to me, that there is a global service registry behind that can be used by all other users of the whiteboard. Also, using the whiteboard in the tests make them very easy configurable and simulates a bit better how OSGi will work. for example in the ExternalLoginModuleTest, I can just do: whiteboard = oak.getWhiteboard(); whiteboard.register(SyncManager.class, new SyncManagerImpl(whiteboard), Collections.emptyMap()); whiteboard.register(ExternalIdentityProviderManager.class, new ExternalIDPManagerImpl(whiteboard), Collections.emptyMap()); If I need to register them with the login module, this would not work today, without hard wiring all possible services to the SecurityProvider. addendum: If I want to achieve the same without the whiteboard, I would need to: * Invent a new interface that allows to pass services/helpers to the login modules. eg a LoginModuleService interface * Create some sort of LoginModuleServiceProviderConfiguration * Create an implementation of the above that deals with OSGi but also can be used statically * Add the LoginModuleServiceProviderConfiguration to ServiceProvider.getConfiguration() * Add the interface to my ExternalIDPManagerImpl and SyncManagerImpl * in the login module, retrieve the LoginModuleServiceProviderConfiguration from the SecurityProvider, then find a service for SyncManager and ExternalIdentityProviderManager * in the non-osgi case, I would need to initialize the LoginModuleServiceProviderConfigurationImpl myself and add the 2 services and add the config to the securityprovider. The additional work is that I need to re-invent some sort of service registry for the LoginModuleServiceProviderConfigurationImpl and extend the SecurityProvider with another configuration. Also, I limit the interfaces to be used in the LoginModules to the ones implementing the LoginModuleService interface. you might say, this is more robust - I say, this is just more complicated and has tighter coupling. regards, toby
Re: Make Whiteboard accessible through ContentRepository
Hi, On Wed, Feb 12, 2014 at 11:00 PM, Chetan Mehrotra chetan.mehro...@gmail.com wrote: The LM would be configured in normal way only just that instead of using actual LM it would be passed to ProxyLoginModule which in turn would pass it to actual LoginModule. I don't quite follow. can you give an example of what would be in the jaas.conf and where you instantiate the ProxyLoginModule ? The reason I prefer a factory approach is that any real life LoginModule implementation would probably be exposing some extension points say mapping LDAP name to User name, extracting extra properties etc. Supporting such extension points is quite easy within OSGi env without hard coupling. yes. If a LM _pull_ its dependencies then 1. It becomes hard to expose extension points which can be easily swapped/extended at runtime. I agree. 2. Further looking up services from OSGi Service Registry frequently is not performant. So a frequent operation like Login which triggers frequent lookups would cause issues and something which can be avoided good point. regards, Toby On Wed, Feb 12, 2014 at 9:01 PM, Tobias Bocanegra tri...@apache.org wrote: Hi, On Tue, Feb 11, 2014 at 11:56 PM, Chetan Mehrotra chetan.mehro...@gmail.com wrote: To address the same problem with Felix Jaas support one can make use of LoginModuleFactory [1]. Its job is to create LoginModule instances. One example of this is JdbcLoginModuleFactory [2]. It creates JdbcLoginModule and passes on the DataSource to the LoginModule instances. So instead of LoginModule _looking up_ the DataSource service it is provided with the DataSource instance. The factory itself was _provided_ with DataSource reference via DI (via Declarative Services) To implement a similar approach in non OSGi world following approach can be used 1. Have a ProxyLoginModule like [3]. The JAAS Config would refer to this class and would be able to create it 2. Have a LoginModuleFactory LMF (custom one) which is referred to in the JAAS Config. 3. One can register a custom LMF implementation with Oak and they would be passed on to SecurityProvider 3. ProxyLoginModule determines the type of LoginModuleFactory and obtains them via Callback 4. The LMF obtained is used to create the LoginModule instance Now same LoginModule (where most of the logic reside) can be shared between OSGi and non OSGi world. Further you can even share the LoginModuleFactory (if using non OSGi stuff only). For OSGi case the LMF would be managed via DS and its dependencies provided via DS For non OSGi case host application would wire up the LMF with its dependencies (via setters) and then register them with the Oak Interesting idea, but I think we should continue support the LM to be configured via the application container (eg. via jaas.conf). Regards, Toby Chetan Mehrotra [1] http://svn.apache.org/repos/asf/felix/trunk/jaas/src/main/java/org/apache/felix/jaas/LoginModuleFactory.java [2] http://svn.apache.org/repos/asf/felix/trunk/examples/jaas/lm-jdbc/src/main/java/org/apache/felix/example/jaas/jdbc/JdbcLoginModuleFactory.java [3] http://svn.apache.org/repos/asf/felix/trunk/jaas/src/main/java/org/apache/felix/jaas/boot/ProxyLoginModule.java On Wed, Feb 12, 2014 at 12:07 PM, Tobias Bocanegra tri...@apache.org wrote: Hi, On Tue, Feb 11, 2014 at 4:38 PM, Tobias Bocanegra tri...@apache.org wrote: On Tue, Feb 11, 2014 at 1:59 PM, Jukka Zitting jukka.zitt...@gmail.com wrote: On Mon, Feb 10, 2014 at 2:25 AM, Felix Meschberger fmesc...@adobe.com wrote: This thread indeed raises the question, why Oak has to come up with something (the Whiteboard) that is almost but not quite like OSGi instead of going all the way through ? This is a misunderstanding; we're not trying to reinvent OSGi. The Whiteboard interface is *only* an abstraction of the whiteboard pattern described in http://www.osgi.org/wiki/uploads/Links/whiteboard.pdf, and is used only for those cases in Oak where that pattern is useful. When running in an OSGi environment, the Whiteboard simply leverages the existing OSGi functionality. The Whiteboard in Oak is not a generic service registry, and is not supposed to become one. but then, why does the Whiteboard interface has a register() method? This indicates to me, that there is a global service registry behind that can be used by all other users of the whiteboard. Also, using the whiteboard in the tests make them very easy configurable and simulates a bit better how OSGi will work. for example in the ExternalLoginModuleTest, I can just do: whiteboard = oak.getWhiteboard(); whiteboard.register(SyncManager.class, new SyncManagerImpl(whiteboard), Collections.emptyMap()); whiteboard.register(ExternalIdentityProviderManager.class, new ExternalIDPManagerImpl(whiteboard), Collections.emptyMap()); If I need to register them with the login module, this would not work today, without hard
Re: Make Whiteboard accessible through ContentRepository
Hi, On Mon, Feb 10, 2014 at 8:35 PM, Tobias Bocanegra tri...@apache.org wrote: I'd rather offer it via a Callback. Callbacks are not really meant for such use. Their purpose is to allow the authentication component to interact with the application to retrieve specific authentication data, such as usernames and passwords, or to display certain information, such as error and warning messages, not to access the rest of the runtime environment. What we should do instead is to pass context information via the options map passed to LoginModule.initialize() method. For example the Karaf JAAS implementation passes the BundleContext through the options map. The LoginModule class would then look into the options map for any dependencies it has. Something like this: abstract class MyLoginModule implements LoginModule { private LoginBackend backend; protected abstract LoginBackend getLoginBackend(MapString, ? options); @Override public initialize(...,MapString,? options) { this.backend = getLoginBackend(options); } } Subclasses can specialize the lookup method to work with different runtime environments. For example in an OSGi/Karaf environment this could be (omitting error handling and details like handling of service reference counts): class MyOsgiLoginModule extends MyLoginModule { @Override protected LoginBackend getLoginBackend(MapString, ? options) { BundleContext context = (BundleContext) options.get(BundleContext.class.getName()); return getLoginBackend(context); // OSGi service lookup } } Or in a plain old Java environment: class MyJavaLoginModule extends MyLoginModule { @Override protected LoginBackend getLoginBackend(MapString, ? options) { return (LoginBackend) options.get(LoginBackend.class.getName()); } } ... with the following bootstrapping code: LoginBackend backend = new LoginBackend(...); MapString, ? options = singletonMap(LoginBackend.class.getName(), backend); Configuration.setConfiguration(new ConfigurationExtender(Configuration.getConfiguration(), options)); (The ConfigurationExtender class would decorate the given default configuration with the given extra options.) Note how none of this requires a dependency to the Whiteboard. We of course *can* depend on the Whiteboard if the login code needs stuff like dynamic service registration or lookups, but there's no inherent need for that dependency. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi, On Tue, Feb 11, 2014 at 1:14 AM, Jukka Zitting jukka.zitt...@gmail.com wrote: On Mon, Feb 10, 2014 at 8:35 PM, Tobias Bocanegra tri...@apache.org wrote: I'd rather offer it via a Callback. Callbacks are not really meant for such use. Their purpose is to allow the authentication component to interact with the application to retrieve specific authentication data, such as usernames and passwords, or to display certain information, such as error and warning messages, not to access the rest of the runtime environment. What we should do instead is to pass context information via the options map passed to LoginModule.initialize() method. Right, this might be better :-) I just followed the pattern already there with all the other callbacks :-) For example the Karaf JAAS implementation passes the BundleContext through the options map. The LoginModule class would then look into the options map for any dependencies it has. Something like this: abstract class MyLoginModule implements LoginModule { private LoginBackend backend; protected abstract LoginBackend getLoginBackend(MapString, ? options); @Override public initialize(...,MapString,? options) { this.backend = getLoginBackend(options); } } Subclasses can specialize the lookup method to work with different runtime environments. For example in an OSGi/Karaf environment this could be (omitting error handling and details like handling of service reference counts): class MyOsgiLoginModule extends MyLoginModule { @Override protected LoginBackend getLoginBackend(MapString, ? options) { BundleContext context = (BundleContext) options.get(BundleContext.class.getName()); return getLoginBackend(context); // OSGi service lookup } } Or in a plain old Java environment: class MyJavaLoginModule extends MyLoginModule { @Override protected LoginBackend getLoginBackend(MapString, ? options) { return (LoginBackend) options.get(LoginBackend.class.getName()); } } ... with the following bootstrapping code: LoginBackend backend = new LoginBackend(...); MapString, ? options = singletonMap(LoginBackend.class.getName(), backend); Configuration.setConfiguration(new ConfigurationExtender(Configuration.getConfiguration(), options)); (The ConfigurationExtender class would decorate the given default configuration with the given extra options.) Note how none of this requires a dependency to the Whiteboard. We of course *can* depend on the Whiteboard if the login code needs stuff like dynamic service registration or lookups, but there's no inherent need for that dependency. True, but if we want to write LoginModules what work in both worlds, then we need to offer a common interface to access to services - and that's currently the whiteboard. Regards, Toby
Re: Make Whiteboard accessible through ContentRepository
Hi, On Tue, Feb 11, 2014 at 11:59 AM, Tobias Bocanegra tri...@apache.org wrote: True, but if we want to write LoginModules what work in both worlds, then we need to offer a common interface to access to services - and that's currently the whiteboard. But it isn't. When running in plain old Java, the DefaultWhiteboard only contains a small subset of services that need the dynamic registration/lookup functionality of the whiteboard pattern. Normal components whose wiring can be achieved with direct object references are not kept in the Whiteboard, and can't be looked up through it. This is by design. We don't want to reinvent OSGi. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi, On Mon, Feb 10, 2014 at 2:25 AM, Felix Meschberger fmesc...@adobe.com wrote: This thread indeed raises the question, why Oak has to come up with something (the Whiteboard) that is almost but not quite like OSGi instead of going all the way through ? This is a misunderstanding; we're not trying to reinvent OSGi. The Whiteboard interface is *only* an abstraction of the whiteboard pattern described in http://www.osgi.org/wiki/uploads/Links/whiteboard.pdf, and is used only for those cases in Oak where that pattern is useful. When running in an OSGi environment, the Whiteboard simply leverages the existing OSGi functionality. The Whiteboard in Oak is not a generic service registry, and is not supposed to become one. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi, On Tue, Feb 11, 2014 at 1:48 PM, Jukka Zitting jukka.zitt...@gmail.com wrote: On Tue, Feb 11, 2014 at 11:59 AM, Tobias Bocanegra tri...@apache.org wrote: True, but if we want to write LoginModules what work in both worlds, then we need to offer a common interface to access to services - and that's currently the whiteboard. But it isn't. When running in plain old Java, the DefaultWhiteboard only contains a small subset of services that need the dynamic registration/lookup functionality of the whiteboard pattern. Normal components whose wiring can be achieved with direct object references are not kept in the Whiteboard, and can't be looked up through it. I think that this is a problem. In case of the LoginModule, it would be very difficult and clumsy to hard wire the respective providers for them to work. Unless we invent a specific LoginModuleServiceRegistry or similar, that is provided by the SecurityManager as configuration and can be used to statically add the services you wantbut we get this for free with OSGi and we should have a pendant for the non-osgi case. This is by design. We don't want to reinvent OSGi. sure. we should use OSGi. regards, toby
Re: Make Whiteboard accessible through ContentRepository
Hi, On Tue, Feb 11, 2014 at 1:59 PM, Jukka Zitting jukka.zitt...@gmail.com wrote: On Mon, Feb 10, 2014 at 2:25 AM, Felix Meschberger fmesc...@adobe.com wrote: This thread indeed raises the question, why Oak has to come up with something (the Whiteboard) that is almost but not quite like OSGi instead of going all the way through ? This is a misunderstanding; we're not trying to reinvent OSGi. The Whiteboard interface is *only* an abstraction of the whiteboard pattern described in http://www.osgi.org/wiki/uploads/Links/whiteboard.pdf, and is used only for those cases in Oak where that pattern is useful. When running in an OSGi environment, the Whiteboard simply leverages the existing OSGi functionality. The Whiteboard in Oak is not a generic service registry, and is not supposed to become one. but then, why does the Whiteboard interface has a register() method? This indicates to me, that there is a global service registry behind that can be used by all other users of the whiteboard. Also, using the whiteboard in the tests make them very easy configurable and simulates a bit better how OSGi will work. for example in the ExternalLoginModuleTest, I can just do: whiteboard = oak.getWhiteboard(); whiteboard.register(SyncManager.class, new SyncManagerImpl(whiteboard), Collections.emptyMap()); whiteboard.register(ExternalIdentityProviderManager.class, new ExternalIDPManagerImpl(whiteboard), Collections.emptyMap()); If I need to register them with the login module, this would not work today, without hard wiring all possible services to the SecurityProvider. Regards, Toby
Re: Make Whiteboard accessible through ContentRepository
To address the same problem with Felix Jaas support one can make use of LoginModuleFactory [1]. Its job is to create LoginModule instances. One example of this is JdbcLoginModuleFactory [2]. It creates JdbcLoginModule and passes on the DataSource to the LoginModule instances. So instead of LoginModule _looking up_ the DataSource service it is provided with the DataSource instance. The factory itself was _provided_ with DataSource reference via DI (via Declarative Services) To implement a similar approach in non OSGi world following approach can be used 1. Have a ProxyLoginModule like [3]. The JAAS Config would refer to this class and would be able to create it 2. Have a LoginModuleFactory LMF (custom one) which is referred to in the JAAS Config. 3. One can register a custom LMF implementation with Oak and they would be passed on to SecurityProvider 3. ProxyLoginModule determines the type of LoginModuleFactory and obtains them via Callback 4. The LMF obtained is used to create the LoginModule instance Now same LoginModule (where most of the logic reside) can be shared between OSGi and non OSGi world. Further you can even share the LoginModuleFactory (if using non OSGi stuff only). For OSGi case the LMF would be managed via DS and its dependencies provided via DS For non OSGi case host application would wire up the LMF with its dependencies (via setters) and then register them with the Oak Chetan Mehrotra [1] http://svn.apache.org/repos/asf/felix/trunk/jaas/src/main/java/org/apache/felix/jaas/LoginModuleFactory.java [2] http://svn.apache.org/repos/asf/felix/trunk/examples/jaas/lm-jdbc/src/main/java/org/apache/felix/example/jaas/jdbc/JdbcLoginModuleFactory.java [3] http://svn.apache.org/repos/asf/felix/trunk/jaas/src/main/java/org/apache/felix/jaas/boot/ProxyLoginModule.java On Wed, Feb 12, 2014 at 12:07 PM, Tobias Bocanegra tri...@apache.org wrote: Hi, On Tue, Feb 11, 2014 at 4:38 PM, Tobias Bocanegra tri...@apache.org wrote: On Tue, Feb 11, 2014 at 1:59 PM, Jukka Zitting jukka.zitt...@gmail.com wrote: On Mon, Feb 10, 2014 at 2:25 AM, Felix Meschberger fmesc...@adobe.com wrote: This thread indeed raises the question, why Oak has to come up with something (the Whiteboard) that is almost but not quite like OSGi instead of going all the way through ? This is a misunderstanding; we're not trying to reinvent OSGi. The Whiteboard interface is *only* an abstraction of the whiteboard pattern described in http://www.osgi.org/wiki/uploads/Links/whiteboard.pdf, and is used only for those cases in Oak where that pattern is useful. When running in an OSGi environment, the Whiteboard simply leverages the existing OSGi functionality. The Whiteboard in Oak is not a generic service registry, and is not supposed to become one. but then, why does the Whiteboard interface has a register() method? This indicates to me, that there is a global service registry behind that can be used by all other users of the whiteboard. Also, using the whiteboard in the tests make them very easy configurable and simulates a bit better how OSGi will work. for example in the ExternalLoginModuleTest, I can just do: whiteboard = oak.getWhiteboard(); whiteboard.register(SyncManager.class, new SyncManagerImpl(whiteboard), Collections.emptyMap()); whiteboard.register(ExternalIdentityProviderManager.class, new ExternalIDPManagerImpl(whiteboard), Collections.emptyMap()); If I need to register them with the login module, this would not work today, without hard wiring all possible services to the SecurityProvider. addendum: If I want to achieve the same without the whiteboard, I would need to: * Invent a new interface that allows to pass services/helpers to the login modules. eg a LoginModuleService interface * Create some sort of LoginModuleServiceProviderConfiguration * Create an implementation of the above that deals with OSGi but also can be used statically * Add the LoginModuleServiceProviderConfiguration to ServiceProvider.getConfiguration() * Add the interface to my ExternalIDPManagerImpl and SyncManagerImpl * in the login module, retrieve the LoginModuleServiceProviderConfiguration from the SecurityProvider, then find a service for SyncManager and ExternalIdentityProviderManager * in the non-osgi case, I would need to initialize the LoginModuleServiceProviderConfigurationImpl myself and add the 2 services and add the config to the securityprovider. The additional work is that I need to re-invent some sort of service registry for the LoginModuleServiceProviderConfigurationImpl and extend the SecurityProvider with another configuration. Also, I limit the interfaces to be used in the LoginModules to the ones implementing the LoginModuleService interface. you might say, this is more robust - I say, this is just more complicated and has tighter coupling. regards, toby
Re: Make Whiteboard accessible through ContentRepository
On 9.2.14 6:49 , Jukka Zitting wrote: Hi, On Sun, Feb 9, 2014 at 4:05 AM, Davide Giannella giannella.dav...@gmail.com wrote: It would make for example a lot easier to inject a CommitHook like a custom index. So far the only way to achieve so is to recompile the oak-run adding .with(new MyIndexProvider()) while I'd rather add a Service implementation the OSGi whiteboard. Some of us prefer to recompile the jar. :-) Because this usually works, while starting up an OSGi container and deploying bundles usually results in getting tied up in manual dependency analysis and class loader debugging, which is quite distracting if you just want to run a quick benchmark. Well that, my experience anyway. OTHO I agree that we should probably make an OSGi option available since this is our primary deployment scenario. Michael Of course that doesn't mean we couldn't do both. If someone's up to it, an OSGi-based runnable Oak jar would be a nice contribution. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi, On Mon, Feb 10, 2014 at 1:01 AM, Tobias Bocanegra tri...@apache.org wrote: ok...using Sling/Felix quite a lot, I'm used to the possibility to create a Service that can have references to any other exported Service via its ComponentContext, i.e. BundleContext, i.e underlying OSGi service registry. The same thing works also without OSGi, you just add a new component constructor argument or a setter and adjust the code that does the wiring to provide that dependency to a component. I admit that doing it this way does require changing code in two places, but it also achieves better decoupling of the service from the way it's wired up, i.e. the component itself doesn't have to worry about the mechanics of the service lookup. This simplifies also things like unit test fixtures as you can just mock the direct dependencies of a component instead of setting up a full runtime environment. Declarative Services in OSGi works similarly in decoupling the wiring of services from the services themselves. A DS-based component doesn't necessarily need to access the Component/BundleContext at all, as it can just declare direct dependencies to all the services it needs. Most Oak components should work the same way instead of requiring direct access to the Whiteboard. By making the DS bind methods explicit, you could even write a normal DS-based component that you can also wire up statically in places like oak-run. sure, in the end it is a specific service. but we don't want to limit the set of services a login module can use. IMO, it should have access to all the ones registered. So a login module (also in the non osgi world) should be able to retrieve the Whiteboard to get a service. See above; instead of going through the Whiteboard, I'd rather see a component declaring direct dependencies to the services it needs. The wiring should happen elsewhere. I think my problem is, that there are (were) several instances of the 'DefautlWhiteboard created, one in Oak.java, one by the SecurityProviderImpl. Hmm, I only see a DefaultWhiteboard instance being created in Oak.java. SecurityProviderImpl uses OsgiWhiteboard. Did this change in OAK-1377? And only allow to create Oak() with or without whiteboard, and remove the Oak.with(Whiteboard) method. So it's clear that either we use the external provided whiteboard, or the implicit internal one. We can do that, though one of the driving ideas behind Oak has been to keep things like new Oak().with(new SomeComponent()).createContentSession() as simple as possible. the problem is, that each plugin, that needs a whiteboard, should be able to get the default one. without some helper classes, the construction gets a bit awkward: Oak oak = new Oak(); SecurityProvider sp = new SecurityProvider(oak.getWhiteboard()); oak.with(sp); IMO it's better that Oak.with() pushes its whiteboard to the plugin. If this becomes a common need, i.e. there are many components that need access to the whiteboard (instead of just a more specific set of services, as suggested above), then I'd rather pull the whiteboard entirely out of the Oak class, like this: Whiteboard whiteboard = ...; new Oak(...) .with(new SecurityProvider(whiteboard)) .createContentRepository(whiteboard); But as said, I think only a small subset of our components should really need direct access to the whiteboard. For example the authorizable action and restriction providers in SecurityProviderImpl are composite services, that in an OSGi deployment can/should be dynamic through the whiteboard mechanism, but in a static deployment shouldn't need the whiteboard as we could just provide a static list of all the available component providers. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi, On Mon, Feb 10, 2014 at 4:31 AM, Jukka Zitting jukka.zitt...@gmail.com wrote: On Mon, Feb 10, 2014 at 1:01 AM, Tobias Bocanegra tri...@apache.org wrote: ok...using Sling/Felix quite a lot, I'm used to the possibility to create a Service that can have references to any other exported Service via its ComponentContext, i.e. BundleContext, i.e underlying OSGi service registry. The same thing works also without OSGi, you just add a new component constructor argument or a setter and adjust the code that does the wiring to provide that dependency to a component. I admit that doing it this way does require changing code in two places, but it also achieves better decoupling of the service from the way it's wired up, i.e. the component itself doesn't have to worry about the mechanics of the service lookup. This simplifies also things like unit test fixtures as you can just mock the direct dependencies of a component instead of setting up a full runtime environment. in case of the LoginModules, that's not possible. They need to retrieve their services from somewhere. Declarative Services in OSGi works similarly in decoupling the wiring of services from the services themselves. A DS-based component doesn't necessarily need to access the Component/BundleContext at all, as it can just declare direct dependencies to all the services it needs. Most Oak components should work the same way instead of requiring direct access to the Whiteboard. By making the DS bind methods explicit, you could even write a normal DS-based component that you can also wire up statically in places like oak-run. This is ok for unit tests etc, but there is currently no way of configuring Oak. So there is no ootb run.sh that will start your oak server. If we ever want to go there, we need to define how to get there. We can shift this problem to Sling and let them provide such a server, or we can start your own launchpad. currently, you need to compile classes in order to configure your server. if this is ok, we can stay with the current setup and hard-wire all dependencies. sure, in the end it is a specific service. but we don't want to limit the set of services a login module can use. IMO, it should have access to all the ones registered. So a login module (also in the non osgi world) should be able to retrieve the Whiteboard to get a service. See above; instead of going through the Whiteboard, I'd rather see a component declaring direct dependencies to the services it needs. The wiring should happen elsewhere. If you want to make this work generally w/o OSGi, then you also need to invent a DS management for oak...which is clearly not a goal. I think my problem is, that there are (were) several instances of the 'DefautlWhiteboard created, one in Oak.java, one by the SecurityProviderImpl. Hmm, I only see a DefaultWhiteboard instance being created in Oak.java. SecurityProviderImpl uses OsgiWhiteboard. Did this change in OAK-1377? got me :-) I overlooked that. And only allow to create Oak() with or without whiteboard, and remove the Oak.with(Whiteboard) method. So it's clear that either we use the external provided whiteboard, or the implicit internal one. We can do that, though one of the driving ideas behind Oak has been to keep things like new Oak().with(new SomeComponent()).createContentSession() as simple as possible. the problem is, that each plugin, that needs a whiteboard, should be able to get the default one. without some helper classes, the construction gets a bit awkward: Oak oak = new Oak(); SecurityProvider sp = new SecurityProvider(oak.getWhiteboard()); oak.with(sp); IMO it's better that Oak.with() pushes its whiteboard to the plugin. If this becomes a common need, i.e. there are many components that need access to the whiteboard (instead of just a more specific set of services, as suggested above), then I'd rather pull the whiteboard entirely out of the Oak class, like this: Whiteboard whiteboard = ...; new Oak(...) .with(new SecurityProvider(whiteboard)) .createContentRepository(whiteboard); But as said, I think only a small subset of our components should really need direct access to the whiteboard. The problem is, that the whiteboard that is initially initialized in Oak() already has some anonymous overrides for delaying stuff. So when passing a non-osgi one externally, this logic is lost, although it might be needed. For example the authorizable action and restriction providers in SecurityProviderImpl are composite services, that in an OSGi deployment can/should be dynamic through the whiteboard mechanism, but in a static deployment shouldn't need the whiteboard as we could just provide a static list of all the available component providers. well :-) regards, toby
Re: Make Whiteboard accessible through ContentRepository
Hi, On Mon, Feb 10, 2014 at 2:50 PM, Tobias Bocanegra tri...@apache.org wrote: in case of the LoginModules, that's not possible. But accessing the whiteboard is? I don't see what's special about the whiteboard, it's just a service dependency like any other. This is ok for unit tests etc, but there is currently no way of configuring Oak. So there is no ootb run.sh that will start your oak server. If we ever want to go there, we need to define how to get there. We can shift this problem to Sling and let them provide such a server, or we can start your own launchpad. currently, you need to compile classes in order to configure your server. if this is ok, we can stay with the current setup and hard-wire all dependencies. That is OK, at least that's been the plan so far. It doesn't make sense for Oak to reinvent a component framework like OSGi or Spring. Instead Oak components should be usable within any such framework, or even in plain old Java. The problem is, that the whiteboard that is initially initialized in Oak() already has some anonymous overrides for delaying stuff. So when passing a non-osgi one externally, this logic is lost, although it might be needed. Right. I guess we should refactor that part of the code to avoid the overrides. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi, On Mon, Feb 10, 2014 at 1:30 PM, Jukka Zitting jukka.zitt...@gmail.com wrote: On Mon, Feb 10, 2014 at 2:50 PM, Tobias Bocanegra tri...@apache.org wrote: in case of the LoginModules, that's not possible. But accessing the whiteboard is? I don't see what's special about the whiteboard, it's just a service dependency like any other. No, it's a piece of infrastructure, and part of the Oak SPI. I think that components should be able to rely on a system wide Whiteboard if they want. Also, the LoginModules are not 'services' in that sense. they get instantiated by JAAS and can only communicate via Callbacks with the login context. This is ok for unit tests etc, but there is currently no way of configuring Oak. So there is no ootb run.sh that will start your oak server. If we ever want to go there, we need to define how to get there. We can shift this problem to Sling and let them provide such a server, or we can start your own launchpad. currently, you need to compile classes in order to configure your server. if this is ok, we can stay with the current setup and hard-wire all dependencies. That is OK, at least that's been the plan so far. It doesn't make sense for Oak to reinvent a component framework like OSGi or Spring. Instead Oak components should be usable within any such framework, or even in plain old Java. The problem is, that the whiteboard that is initially initialized in Oak() already has some anonymous overrides for delaying stuff. So when passing a non-osgi one externally, this logic is lost, although it might be needed. Right. I guess we should refactor that part of the code to avoid the overrides. ok: https://issues.apache.org/jira/browse/OAK-1411 regards, toby
Re: Make Whiteboard accessible through ContentRepository
On Sat, Feb 8, 2014 at 6:58 PM, Tobias Bocanegra tri...@apache.org wrote: ... ps: I still think we should turn the problem around, and make everything OSGi services and start a small OSGi container for the runtime :-) I was thinking the same tonight. I was going to ask why (any historical decisions) Oak in the oak-run doesn't use a simple bundled-up OSGi container and runs the related jar, that are already OSGi bundles, in it. It would make for example a lot easier to inject a CommitHook like a custom index. So far the only way to achieve so is to recompile the oak-run adding .with(new MyIndexProvider()) while I'd rather add a Service implementation the OSGi whiteboard. D.
Re: Make Whiteboard accessible through ContentRepository
Hi, On Sat, Feb 8, 2014 at 1:58 PM, Tobias Bocanegra tri...@apache.org wrote: ok, then what we need it the pendant to the OSGi service registry, [...] s/the pendant/a dependency/? I'm not sure I understood this correctly. I.e. a mechanism where I can lookup any service. This sounds like an XY problem, i.e. you're proposing a solution without describing the problem you're trying to solve. You mentioned a LoginModule implementation. Why would it need to look up any service? Wouldn't a dependency to a specific service be enough/better? thats what I mean, add the whiteboard from 'Oak.class' to the constructor to ContentRepositoryImpl. You mean new ContentRepositoryImpl(..., whiteboard, ...);? Yes, we can do that. Though as mentioned above I'd like to understand why we need to do that instead of passing the whiteboard (or better, a more specific dependency) directly to whatever component that needs it. The problem at hand is, that users can provide a service that is used in one of the login modules. so eventually we need to pass the osgi whiteboard into the login module. which is easy. but otoh, in the non-osgi case, a unique whiteboard instance should be passed. which is not so easy. I don't see the problem: Whiteboard whiteboard = ...; new Oak(...) .with(whiteboard) .with(new SomeComponent(whiteboard)) ; Or perhaps I'm missing something here? one workaround idea I tested in [0] by introducing WhiteboardAware interface (better name welcome). when such a instance is added to the Oak instance via a with() method, it oak will push the whiteboard to it. Right, we can of course do that, but IMHO the above constructor argument pattern seems much simpler. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi, On Sun, Feb 9, 2014 at 4:05 AM, Davide Giannella giannella.dav...@gmail.com wrote: It would make for example a lot easier to inject a CommitHook like a custom index. So far the only way to achieve so is to recompile the oak-run adding .with(new MyIndexProvider()) while I'd rather add a Service implementation the OSGi whiteboard. Some of us prefer to recompile the jar. :-) Of course that doesn't mean we couldn't do both. If someone's up to it, an OSGi-based runnable Oak jar would be a nice contribution. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi, On Sun, Feb 9, 2014 at 9:40 AM, Jukka Zitting jukka.zitt...@gmail.com wrote: Hi, On Sat, Feb 8, 2014 at 1:58 PM, Tobias Bocanegra tri...@apache.org wrote: ok, then what we need it the pendant to the OSGi service registry, [...] s/the pendant/a dependency/? I'm not sure I understood this correctly. I.e. a mechanism where I can lookup any service. This sounds like an XY problem, i.e. you're proposing a solution without describing the problem you're trying to solve. ok...using Sling/Felix quite a lot, I'm used to the possibility to create a Service that can have references to any other exported Service via its ComponentContext, i.e. BundleContext, i.e underlying OSGi service registry. You mentioned a LoginModule implementation. Why would it need to look up any service? Wouldn't a dependency to a specific service be enough/better? sure, in the end it is a specific service. but we don't want to limit the set of services a login module can use. IMO, it should have access to all the ones registered. So a login module (also in the non osgi world) should be able to retrieve the Whiteboard to get a service. Either directly via a callback (probably the correct solution) or via one of the classes it already can access (ContentRepository or SecurityProvider). thats what I mean, add the whiteboard from 'Oak.class' to the constructor to ContentRepositoryImpl. You mean new ContentRepositoryImpl(..., whiteboard, ...);? Yes, we can do that. Though as mentioned above I'd like to understand why we need to do that instead of passing the whiteboard (or better, a more specific dependency) directly to whatever component that needs it. you might be right, it doesn't need it, if the services that needs it is created the correct way. The problem at hand is, that users can provide a service that is used in one of the login modules. so eventually we need to pass the osgi whiteboard into the login module. which is easy. but otoh, in the non-osgi case, a unique whiteboard instance should be passed. which is not so easy. I don't see the problem: Whiteboard whiteboard = ...; new Oak(...) .with(whiteboard) .with(new SomeComponent(whiteboard)) ; Or perhaps I'm missing something here? I think my problem is, that there are (were) several instances of the 'DefautlWhiteboard created, one in Oak.java, one by the SecurityProviderImpl. We should make the DefaultWhiteboard implementation private to Oak. And only allow to create Oak() with or without whiteboard, and remove the Oak.with(Whiteboard) method. So it's clear that either we use the external provided whiteboard, or the implicit internal one. one workaround idea I tested in [0] by introducing WhiteboardAware interface (better name welcome). when such a instance is added to the Oak instance via a with() method, it oak will push the whiteboard to it. Right, we can of course do that, but IMHO the above constructor argument pattern seems much simpler. the problem is, that each plugin, that needs a whiteboard, should be able to get the default one. without some helper classes, the construction gets a bit awkward: Oak oak = new Oak(); SecurityProvider sp = new SecurityProvider(oak.getWhiteboard()); oak.with(sp); IMO it's better that Oak.with() pushes its whiteboard to the plugin. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
On Sun, Feb 9, 2014 at 9:49 AM, Jukka Zitting jukka.zitt...@gmail.com wrote: Hi, On Sun, Feb 9, 2014 at 4:05 AM, Davide Giannella giannella.dav...@gmail.com wrote: It would make for example a lot easier to inject a CommitHook like a custom index. So far the only way to achieve so is to recompile the oak-run adding .with(new MyIndexProvider()) while I'd rather add a Service implementation the OSGi whiteboard. Some of us prefer to recompile the jar. :-) Of course that doesn't mean we couldn't do both. If someone's up to it, an OSGi-based runnable Oak jar would be a nice contribution. I played around with the felix runtime and gogo shell in [1] but didn't pursue this further. the problem is, that without a launchpad (eg [2]) the bootstrapping is tedious. regards, toby [1] https://github.com/tripodsan/jackrabbit-oak/tree/OAK-17/oak-felix [2] http://sling.apache.org/documentation/the-sling-engine/the-sling-launchpad.html On Sun, Feb 9, 2014 at 9:49 AM, Jukka Zitting jukka.zitt...@gmail.com wrote: Hi, On Sun, Feb 9, 2014 at 4:05 AM, Davide Giannella giannella.dav...@gmail.com wrote: It would make for example a lot easier to inject a CommitHook like a custom index. So far the only way to achieve so is to recompile the oak-run adding .with(new MyIndexProvider()) while I'd rather add a Service implementation the OSGi whiteboard. Some of us prefer to recompile the jar. :-) Of course that doesn't mean we couldn't do both. If someone's up to it, an OSGi-based runnable Oak jar would be a nice contribution. BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi This thread indeed raises the question, why Oak has to come up with something (the Whiteboard) that is almost but not quite like OSGi instead of going all the way through ? As a stop-gap measure, instead of going full-OSGi you could also just leverage the feature, that you really need: The service registry and base on something like Karl Pauls' µServices [2] and PojoSR [3] Interestingly, when I started with what became Apache Sling I worked on a thing called the Extension Frameworkg for JCR Repositories [1] until it turned out that it basically would be reinventing OSGi … and so Sling became an OSGi application. Regards Felix [1] http://svn.apache.org/repos/asf/jackrabbit/sandbox/inactive/extension-framework/ [2] http://www.pro-vision.de/content/medialib/pro-vision/production/adaptto/2013/adaptto2013-osgi--services-karl-pauls-pdf/_jcr_content/renditions/rendition.download_attachment.file/adaptto2013-osgi--services-karl-pauls.pdf [3] http://code.google.com/p/pojosr/ Am 09.02.2014 um 10:05 schrieb Davide Giannella giannella.dav...@gmail.com: On Sat, Feb 8, 2014 at 6:58 PM, Tobias Bocanegra tri...@apache.org wrote: ... ps: I still think we should turn the problem around, and make everything OSGi services and start a small OSGi container for the runtime :-) I was thinking the same tonight. I was going to ask why (any historical decisions) Oak in the oak-run doesn't use a simple bundled-up OSGi container and runs the related jar, that are already OSGi bundles, in it. It would make for example a lot easier to inject a CommitHook like a custom index. So far the only way to achieve so is to recompile the oak-run adding .with(new MyIndexProvider()) while I'd rather add a Service implementation the OSGi whiteboard. D.
Re: Make Whiteboard accessible through ContentRepository
+1 I think it makes sense, see also [1]. Regards, Tommaso [1] : http://markmail.org/message/4youjqpyjvajcttr 2014-02-08 Tobias Bocanegra tri...@apache.org: Hi, currently there is not way to access the whiteboard from within the content repository - only if it's added from the outside to the plugins. For example, I would need access to it from within a LoginModule. Right now, I got a private whiteboard just for the security provider, but this is not optimal. IMO there should only be 1 whiteboard for 1 Oak.class instance. Also note, that in case of OSGi, all the OSGi whiteboards would base on the same service registry anyways. WDYT? regards, toby
Re: Make Whiteboard accessible through ContentRepository
Hi, On Sat, Feb 8, 2014 at 2:42 AM, Tobias Bocanegra tri...@apache.org wrote: currently there is not way to access the whiteboard from within the content repository - only if it's added from the outside to the plugins. That's the intended design. The whiteboard mechanism is an abstraction of the OSGi BundleContext and works similarly; i.e. the code that instantiates/manages a component is expected to pass the whiteboard/context to that component if/when needed. For example, I would need access to it from within a LoginModule. If you already have access to a ContentRepository, then why not use the same mechanism to pass the Whiteboard instead of using a ContentRepository method for that? BR, Jukka Zitting
Re: Make Whiteboard accessible through ContentRepository
Hi, On Sat, Feb 8, 2014 at 7:26 AM, Jukka Zitting jukka.zitt...@gmail.com wrote: Hi, On Sat, Feb 8, 2014 at 2:42 AM, Tobias Bocanegra tri...@apache.org wrote: currently there is not way to access the whiteboard from within the content repository - only if it's added from the outside to the plugins. That's the intended design. The whiteboard mechanism is an abstraction of the OSGi BundleContext and works similarly; i.e. the code that instantiates/manages a component is expected to pass the whiteboard/context to that component if/when needed. ok, then what we need it the pendant to the OSGi service registry, or to the SlingHelper stuff. I.e. a mechanism where I can lookup any service. For example, I would need access to it from within a LoginModule. If you already have access to a ContentRepository, then why not use the same mechanism to pass the Whiteboard instead of using a ContentRepository method for that? thats what I mean, add the whiteboard from 'Oak.class' to the constructor to ContentRepositoryImpl. The problem at hand is, that users can provide a service that is used in one of the login modules. so eventually we need to pass the osgi whiteboard into the login module. which is easy. but otoh, in the non-osgi case, a unique whiteboard instance should be passed. which is not so easy. IMO there should only be 1 whiteboard instance per system (or it should base on a global service registry). for OSGi this is not a problem, because they all rely on the same service registry. but for the non-osgi usecase. one workaround idea I tested in [0] by introducing WhiteboardAware interface (better name welcome). when such a instance is added to the Oak instance via a with() method, it oak will push the whiteboard to it. regards, toby ps: I still think we should turn the problem around, and make everything OSGi services and start a small OSGi container for the runtime :-) [0] https://github.com/tripodsan/jackrabbit-oak/commit/8026bd44cf47879c67f7875bc08247a4eb7e501f BR, Jukka Zitting
Make Whiteboard accessible through ContentRepository
Hi, currently there is not way to access the whiteboard from within the content repository - only if it's added from the outside to the plugins. For example, I would need access to it from within a LoginModule. Right now, I got a private whiteboard just for the security provider, but this is not optimal. IMO there should only be 1 whiteboard for 1 Oak.class instance. Also note, that in case of OSGi, all the OSGi whiteboards would base on the same service registry anyways. WDYT? regards, toby