/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.isis.core.runtime.systemusinginstallers;
import java.util.List;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.isis.applib.AppManifest;
import org.apache.isis.core.commons.components.ApplicationScopedComponent;
import org.apache.isis.core.commons.components.Installer;
import org.apache.isis.core.commons.config.IsisConfiguration;
import org.apache.isis.core.commons.config.IsisConfigurationDefault;
import org.apache.isis.core.commons.ensure.Assert;
import org.apache.isis.core.commons.factory.InstanceCreationClassException;
import org.apache.isis.core.commons.factory.InstanceCreationException;
import org.apache.isis.core.commons.factory.InstanceUtil;
import org.apache.isis.core.commons.factory.UnavailableClassException;
import org.apache.isis.core.commons.lang.ObjectExtensions;
import org.apache.isis.core.runtime.authentication.AuthenticationManager;
import org.apache.isis.core.runtime.authentication.AuthenticationManagerInstaller;
import org.apache.isis.core.runtime.authorization.AuthorizationManager;
import org.apache.isis.core.runtime.authorization.AuthorizationManagerInstaller;
import org.apache.isis.core.runtime.system.session.IsisSessionFactoryBuilder;
import org.apache.isis.core.runtime.system.SystemConstants;
public class IsisComponentProviderUsingInstallers extends IsisComponentProvider {
//region > constructors
public IsisComponentProviderUsingInstallers(
final AppManifest appManifestIfAny,
final IsisConfiguration configuration) {
this(appManifestFrom(appManifestIfAny, configuration),
(IsisConfigurationDefault) configuration, // REVIEW: HACKY
new InstallerLookup(configuration));
}
private IsisComponentProviderUsingInstallers(
final AppManifest appManifest,
final IsisConfigurationDefault configuration,
final InstallerLookup installerLookup) {
this(configuration, appManifest,
lookupAuthenticationManager(appManifest, installerLookup, configuration),
lookupAuthorizationManager(appManifest, installerLookup, configuration));
}
private IsisComponentProviderUsingInstallers(
final IsisConfiguration configuration,
final AppManifest appManifest,
final AuthenticationManager authenticationManager,
final AuthorizationManager authorizationManager){
super(appManifest, configuration, authenticationManager, authorizationManager);
}
//endregion
//region > constructor helpers (factories)
/**
* If an {@link AppManifest} was explicitly provided (eg from the Guice <tt>IsisWicketModule</tt> when running
* unde the Wicket viewer) then use that; otherwise read the <tt>isis.properties</tt> config file and look
* for an <tt>isis.appManifest</tt> entry instead.
*/
private static AppManifest appManifestFrom(
final AppManifest appManifestFromConstructor,
final IsisConfiguration configuration) {
if(appManifestFromConstructor != null) {
return appManifestFromConstructor;
}
final String appManifestFromConfiguration = configuration.getString(SystemConstants.APP_MANIFEST_KEY);
return appManifestFromConfiguration != null
? InstanceUtil.createInstance(appManifestFromConfiguration, AppManifest.class)
: null;
}
private static AuthenticationManager lookupAuthenticationManager(
final AppManifest appManifest, final InstallerLookup installerLookup,
final IsisConfigurationDefault configuration) {
final String authenticationMechanism = appManifest.getAuthenticationMechanism();
final AuthenticationManagerInstaller authenticationInstaller =
installerLookup.authenticationManagerInstaller(authenticationMechanism);
// no longer used, could probably remove
configuration.put(SystemConstants.AUTHENTICATION_INSTALLER_KEY, authenticationMechanism);
return authenticationInstaller.createAuthenticationManager();
}
private static AuthorizationManager lookupAuthorizationManager(
final AppManifest appManifest, final InstallerLookup installerLookup,
final IsisConfigurationDefault configuration) {
final String authorizationMechanism = appManifest.getAuthorizationMechanism();
AuthorizationManagerInstaller authorizationInstaller =
installerLookup.authorizationManagerInstaller(authorizationMechanism);
// no longer used, could probably remove
configuration.put(SystemConstants.AUTHORIZATION_INSTALLER_KEY, authorizationMechanism);
return authorizationInstaller.createAuthorizationManager();
}
//endregion
/**
* Looks up authorization and authentication implementations.
*
* Previously this class was used to lookup the top-level components of
* {@link IsisSessionFactoryBuilder} (persistence, authentication, authorization, reflector and so on),
* each being looked up from a file called <tt>installer-registry.properties</tt>.
* Of these responsibilities, only the support for authentication and authorization remains,
* the remainder have only a single implementation. The implementation has been
* substantially simplified.
*
* Note that it <i>is</i> possible to use other {@link Installer} implementations;
* just specify the {@link Installer}'s fully qualified class name.
*
* @deprecated - intention is to replace in future using CDI
*/
@Deprecated
static class InstallerLookup implements ApplicationScopedComponent {
private static final Logger LOG = LoggerFactory.getLogger(InstallerLookup.class);
//region > constructor, fields
private final IsisConfiguration isisConfiguration;
private final List<Installer> installerList = Lists.newArrayList();
public InstallerLookup(final IsisConfiguration isisConfiguration) throws InstanceCreationException {
this.isisConfiguration = isisConfiguration;
final List<String> installerClassNames = Lists.newArrayList(
"org.apache.isis.core.security.authentication.BypassAuthenticationManagerInstaller", // bypass
"org.apache.isis.security.shiro.authentication.ShiroAuthenticationManagerInstaller", // shiro
"org.apache.isis.core.security.authorization.BypassAuthorizationManagerInstaller", // bypass
"org.apache.isis.security.shiro.authorization.ShiroAuthorizationManagerInstaller" // shiro
);
for (String className : installerClassNames) {
if (className.length() == 0 || className.startsWith("#")) {
continue;
}
try {
final Installer object = (Installer) InstanceUtil.createInstance(className, isisConfiguration);
LOG.debug("created component installer: " + object.getName() + " - " + className);
installerList.add(object);
} catch (final UnavailableClassException e) {
LOG.info("component installer not found; it will not be available: " + className);
} catch (final InstanceCreationClassException e) {
LOG.info("instance creation exception: " + e.getMessage());
} catch (final InstanceCreationException e) {
try {
final Installer object = (Installer) InstanceUtil.createInstance(className);
LOG.debug("created component installer: " + object.getName() + " - " + className);
installerList.add(object);
} catch (final UnavailableClassException e2) {
LOG.info("component installer not found; it will not be available: " + className);
} catch (final InstanceCreationClassException e2) {
LOG.info("instance creation exception: " + e2.getMessage());
}
}
}
}
//endregion
//region > framework
public AuthenticationManagerInstaller authenticationManagerInstaller(final String requested) {
return getInstaller(
AuthenticationManagerInstaller.class,
requested,
SystemConstants.AUTHENTICATION_INSTALLER_KEY,
SystemConstants.AUTHENTICATION_DEFAULT);
}
public AuthorizationManagerInstaller authorizationManagerInstaller(final String requested) {
return getInstaller(
AuthorizationManagerInstaller.class, requested,
SystemConstants.AUTHORIZATION_INSTALLER_KEY,
SystemConstants.AUTHORIZATION_DEFAULT);
}
//endregion
//region > helpers
@SuppressWarnings("unchecked")
private <T extends Installer> T getInstaller(final Class<T> cls, final String implName) {
Assert.assertNotNull("No name specified", implName);
for (final Installer installer : installerList) {
if (cls.isAssignableFrom(installer.getClass()) && installer.getName().equals(implName)) {
return (T) installer;
}
}
return (T) getInstaller(implName);
}
@SuppressWarnings("unchecked")
public Installer getInstaller(final String implClassName) {
try {
return ObjectExtensions.asT(InstanceUtil.createInstance(implClassName));
} catch (final UnavailableClassException e) {
return null;
}
}
private <T extends Installer> T getInstaller(
final Class<T> requiredType,
String reqImpl,
final String key,
final String defaultImpl) {
if (reqImpl == null) {
reqImpl = isisConfiguration.getString(key, defaultImpl);
}
if (reqImpl == null) {
return null;
}
final T installer = getInstaller(requiredType, reqImpl);
if (installer == null) {
throw new InstanceCreationException(
"Failed to load installer; named/class:'" + reqImpl + "' (of type " + requiredType.getName() + ")");
}
return installer;
}
//endregion
}
}