All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.webswing.server.services.security.api.WebswingSecurityConfig Maven / Gradle / Ivy

The newest version!
package org.webswing.server.services.security.api;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.stream.Stream;

import org.webswing.server.common.model.Config;
import org.webswing.server.common.model.meta.ConfigField;
import org.webswing.server.common.model.meta.ConfigFieldDefaultValueObject;
import org.webswing.server.common.model.meta.ConfigFieldDefaultValueString;
import org.webswing.server.common.model.meta.ConfigFieldDiscriminator;
import org.webswing.server.common.model.meta.ConfigFieldEditorType;
import org.webswing.server.common.model.meta.ConfigFieldEditorType.EditorType;
import org.webswing.server.common.model.meta.ConfigFieldOrder;
import org.webswing.server.common.model.meta.ConfigFieldPresets;
import org.webswing.server.common.model.meta.ConfigFieldVariables;
import org.webswing.server.common.model.meta.ConfigType;
import org.webswing.server.common.model.meta.MetaObject;
import org.webswing.server.common.model.meta.MetadataGenerator;
import org.webswing.server.common.model.meta.VariableSetName;
import org.webswing.server.common.util.CommonUtil;
import org.webswing.server.services.security.api.WebswingSecurityConfig.WebswingSecurityMetadataGenerator;
import org.webswing.util.ClasspathUtil;
import org.webswing.Constants;

@ConfigType(metadataGenerator = WebswingSecurityMetadataGenerator.class)
@ConfigFieldOrder({ "classPath", "module", "config", "authorizationConfig" })
public interface WebswingSecurityConfig extends Config {

	@ConfigField(label = "Security Module Class Path", description = "Additional classpath for built-in Security module or for defining custom security module. ")
	@ConfigFieldVariables(VariableSetName.SwingApp)
	@ConfigFieldDiscriminator
	public List getClassPath();

	@ConfigField(label = "Security Module Name", description = "Select one of built-in modules or enter full class name of custom security module (has to implement org.webswing.server.services.security.api.WebswingSecurityModule interface). Note the class and its dependencies has to be on classpath defined above.")
	@ConfigFieldPresets(enumClass = BuiltInModules.class)
	@ConfigFieldDefaultValueString("INHERITED")
	@ConfigFieldDiscriminator
	public String getModule();

	@ConfigField(label = "Security Module Config", description = "Security module specific configuration.")
	@ConfigFieldEditorType(editor = EditorType.Object)
	@ConfigFieldDefaultValueObject(HashMap.class)
	public Map getConfig();

	@ConfigField(label = "Authorization Config", description = "Define users and roles authorized to access this application")
	@ConfigFieldDefaultValueObject(AuthorizationConfig.class)
	public AuthorizationConfig getAuthorizationConfig();

	public static class WebswingSecurityMetadataGenerator extends MetadataGenerator {

		private Object parent;

		@Override
		public MetaObject getMetadata(WebswingSecurityConfig config, ClassLoader cl, Object parent) throws Exception {
			this.parent = parent;
			if (config.getClassPath() != null && config.getClassPath().size() > 0) {
				//need to create temporary classloader with configured classpath
				//1.resolve base dir for classpath
				File homeFile = getContext().resolveFile(".");
				String home = homeFile == null ? "." : homeFile.getCanonicalPath();
				//2. construct the class loader 
				String classPath = CommonUtil.generateClassPathString(config.getClassPath());
				classPath = getContext().replaceVariables(classPath);
				URL[] urls = ClasspathUtil.populateClassPath(classPath, home);
				URLClassLoader customCL = new URLClassLoader(urls, cl);
				try {
					return super.getMetadata(config, customCL, parent);
				} finally {
					customCL.close();
					this.parent = null;
				}
			} else {
				MetaObject metadata = super.getMetadata(config, cl, parent);
				this.parent = null;
				return metadata;
			}
		}

		@Override
		protected String[] getPresets(WebswingSecurityConfig config, ClassLoader cl, String propertyName, Method readMethod) {
			if (propertyName.equals("classPath")) {
				try {
					String securityRootString = "${" + Constants.ROOT_DIR_PATH + "}/security/";
					File securityRoot = new File(getContext().replaceVariables("${" + Constants.ROOT_DIR_PATH + "}/security"));
					if (securityRoot.exists() && securityRoot.isDirectory()) {
						return Arrays.stream(securityRoot.list()).map(f -> securityRootString + f + "/*").toArray(String[]::new);
					} else {
						return new String[] {};
					}
				} catch (Exception e) {
					//do nothing
				}
			} else if (propertyName.equals("module")) {
				ArrayList discovered = new ArrayList<>();
				ServiceLoader loader = ServiceLoader.load(WebswingSecurityModuleProvider.class, cl);
				for (Iterator i = loader.iterator(); i.hasNext(); ) {
					discovered.addAll(i.next().getSecurityModuleClassNames());
				}
				Stream builtin = Arrays.stream(super.getPresets(config, cl, propertyName, readMethod)).filter(sm -> !(isRootPath() && sm.equals(BuiltInModules.INHERITED.name())));
				return Stream.concat(builtin, discovered.stream()).toArray(String[]::new);
			}
			return super.getPresets(config, cl, propertyName, readMethod);
		}

		@Override
		public Class getExplicitType(WebswingSecurityConfig config, ClassLoader cl, String propertyName, Method readMethod, Object value) throws ClassNotFoundException {
			if (propertyName.equals("config")) {
				String securityModuleClassName = BuiltInModules.getSecurityModuleClassName(config.getModule());
				if (securityModuleClassName != null) {
					Class configClass;
					try {
						Class moduleClass = cl.loadClass(securityModuleClassName);
						configClass = getConfigTypeFromConstructor(moduleClass);
						if (configClass != null) {
							return configClass;
						}
					} catch (Throwable e) {
						return null;
					}
				}
			}
			return super.getExplicitType(config, cl, propertyName, readMethod, value);
		}

		@Override
		protected LinkedHashSet getPropertyNames(WebswingSecurityConfig config, ClassLoader cl) throws Exception {
			LinkedHashSet names = super.getPropertyNames(config, cl);
			if (isRootPath()) {
				names.remove("authorizationConfig");
			}
			return names;
		}

		private boolean isRootPath() {
			if (parent instanceof Config) {
				Object path = ((Config) parent).asMap().get("path");
				if ("/".equals(path) || "".equals(path)) {
					return true;
				}
			}
			return false;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy