/* * Copyright 2016 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * Licensed 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.keycloak.subsystem.server.extension; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.dmr.ModelNode; import org.jboss.dmr.Property; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS; /** * This service keeps track of the entire Keycloak management model so as to provide * configuration to the Keycloak Server. * * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc. */ public final class KeycloakAdapterConfigService { static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService(); static final String DEPLOYMENT_NAME = "keycloak-server.war"; static ModelNode fullConfig = new ModelNode(); private String webContext; private KeycloakAdapterConfigService() { } void updateConfig(ModelNode operation, ModelNode config) { PathAddress address = PathAddress.pathAddress(operation.get(ADDRESS)); address = address.subAddress(1); // remove root (subsystem=keycloak-server) ModelNode newConfig = fullConfig.clone(); ModelNode subNode = newConfig; for (PathElement pathElement : address) { subNode = subNode.get(pathElement.getKey(), pathElement.getValue()); } subNode.set(config.clone()); // remove undefined properties for (Property prop : subNode.asPropertyList()) { if (!prop.getValue().isDefined()) { subNode.remove(prop.getName()); } } fullConfig = newConfig; } ModelNode getConfig() { ModelNode copy = fullConfig.clone(); //System.out.println("******** BEFORE *************"); //System.out.println(copy); //System.out.println("*****************************"); copy.remove("web-context"); massageScheduledTaskInterval(copy); massageMasterRealm(copy); massageTheme(copy); massageSpis(copy); //System.out.println("******** JSON *************"); //System.out.println(copy.resolve().toJSONString(false)); //System.out.println("**********************"); return copy; } // The "massage" methods rearrange the model so that everything will // be where the Keycloak server's Config interface expects it to be. private void massageScheduledTaskInterval(ModelNode copy) { if (!copy.hasDefined("scheduled-task-interval")) return; ModelNode taskInterval = copy.remove("scheduled-task-interval"); copy.get("scheduled", "interval").set(taskInterval); } private void massageMasterRealm(ModelNode copy) { if (!copy.hasDefined("master-realm-name")) return; ModelNode master = copy.remove("master-realm-name"); copy.get("admin", "realm").set(master); } private void massageTheme(ModelNode copy) { if (!copy.hasDefined("theme")) return; if (!copy.get("theme").hasDefined("defaults")) return; ModelNode themeDefaults = copy.get("theme", "defaults"); copy.get("theme").set(themeDefaults); if (copy.has("theme", "dir")) { ModelNode dir = copy.get("theme", "dir"); copy.get("theme", "folder", "dir").set(dir); copy.get("theme").remove("dir"); } if (copy.has("theme", "modules")) { ModelNode modules = copy.get("theme").remove("modules"); copy.get("theme", "module", "modules").set(modules); } } private void massageSpis(ModelNode copy) { if (!copy.hasDefined("spi")) return; ModelNode spis = copy.remove("spi"); for (Property prop : spis.asPropertyList()) { ModelNode spi = prop.getValue(); if (spi.has("provider")) { massageProviders(spi); } if (spi.has("default-provider")) { ModelNode defaultProvider = spi.remove("default-provider"); spi.get("provider").set(defaultProvider); } copy.get(prop.getName()).set(spi); } } private void massageProviders(ModelNode spi) { if (!spi.hasDefined("provider")) return; ModelNode providers = spi.remove("provider"); for (Property prop : providers.asPropertyList()) { ModelNode provider = prop.getValue(); if (provider.has("properties")) { massageProviderProps(provider); } spi.get(prop.getName()).set(provider); } } private void massageProviderProps(ModelNode provider) { if (!provider.hasDefined("properties")) return; ModelNode providerProps = provider.remove("properties"); for (Property prop : providerProps.asPropertyList()) { ModelNode value = prop.getValue(); if (isArray(value.asString().trim())) { provider.get(prop.getName()).set(ModelNode.fromString(value.asString()).asList()); } else { provider.get(prop.getName()).set(value); } } } private boolean isArray(String value) { return value.startsWith("[") && value.endsWith("]"); } void setWebContext(String webContext) { this.webContext = webContext; } String getWebContext() { return webContext; } boolean isKeycloakServerDeployment(String deploymentName) { return DEPLOYMENT_NAME.equals(deploymentName); } }