/*
* Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @author tags. All rights reserved.
*
* 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.AttributeDefinition;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationDefinition;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.OperationStepHandler;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
/**
* This operation provides a migration path from keycloak-server.json to
* standalone.xml or domain.xml.
*
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/
public class MigrateJsonOperation implements OperationStepHandler {
public static final String OPERATION_NAME = "migrate-json";
private static final String CONFIG_DIR = System.getProperty("jboss.server.config.dir");
private static final Path DEFAULT_CONFIG_FILE = Paths.get(CONFIG_DIR, "keycloak-server.json");
private static final AttributeDefinition FILE_ATTRIBUTE = SimpleAttributeDefinitionBuilder.create("file", ModelType.BYTES, true).build();
public static final OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OPERATION_NAME, KeycloakExtension.getResourceDescriptionResolver())
.setRuntimeOnly()
.setReadOnly()
.setReplyType(ModelType.STRING)
.setParameters(FILE_ATTRIBUTE)
.build();
private String localConfig() throws IOException {
if (Files.notExists(DEFAULT_CONFIG_FILE)) return null;
return new String(Files.readAllBytes(DEFAULT_CONFIG_FILE));
}
private String readConfig(ModelNode operation) throws IOException {
ModelNode file = operation.get(FILE_ATTRIBUTE.getName());
if (file.isDefined() && file.asBytes().length > 0) {
return new String(file.asBytes());
}
String localConfig = localConfig();
if (localConfig != null) return localConfig;
throw new IOException("Can not find json file to migrate");
}
@Override
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
List<ModelNode> ops = null;
try {
PathAddress currentAddr = context.getCurrentAddress();
ops = JsonConfigConverter.convertJsonConfig(readConfig(operation), currentAddr);
} catch (IOException ioe) {
throw new OperationFailedException(ioe);
}
for (ModelNode op : ops) {
PathAddress addr = PathAddress.pathAddress(op.get(ADDRESS));
String opName = op.get(OP).asString();
context.addStep(op,
context.getRootResourceRegistration().getOperationHandler(addr, opName),
OperationContext.Stage.MODEL);
}
context.completeStep(OperationContext.RollbackHandler.NOOP_ROLLBACK_HANDLER);
}
}