/* * JBoss, Home of Professional Open Source. * Copyright 2016, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.as.cli.handlers.ifelse; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.jboss.as.cli.CommandContext; import org.jboss.as.cli.CommandContext.Scope; import org.jboss.as.cli.CommandLineException; import org.jboss.as.cli.CommandLineRedirection; import org.jboss.as.cli.batch.BatchManager; import org.jboss.as.cli.operation.ParsedCommandLine; import org.jboss.as.cli.parsing.command.CommandFormat; import org.jboss.as.controller.client.ModelControllerClient; import org.jboss.dmr.ModelNode; /** * Handles the if/else/end-if control flow. * * @author Alexey Loubyansky */ class IfElseControlFlow implements CommandLineRedirection { private static final String CTX_KEY = "IF"; static IfElseControlFlow get(CommandContext ctx) { return (IfElseControlFlow) ctx.get(Scope.CONTEXT, CTX_KEY); } private Registration registration; private final Operation ifCondition; private final ModelNode ifRequest; private List<String> ifBlock; private List<String> elseBlock; private boolean inElse; IfElseControlFlow(CommandContext ctx, Operation ifCondition, String ifRequest) throws CommandLineException { if(ifCondition == null) { throw new IllegalArgumentException("Condition is null"); } if(ifRequest == null) { throw new IllegalArgumentException("Condition request is null"); } this.ifCondition = ifCondition; this.ifRequest = ctx.buildRequest(ifRequest); ctx.set(Scope.CONTEXT, CTX_KEY, this); } @Override public void set(Registration registration) { this.registration = registration; } @Override public void handle(CommandContext ctx) throws CommandLineException { final ParsedCommandLine line = ctx.getParsedCommandLine(); if(line.getFormat() == CommandFormat.INSTANCE) { // let the help through if(line.hasProperty("--help") || line.hasProperty("-h")) { registration.handle(line); return; } final String cmd = line.getOperationName(); if("else".equals(cmd) || "end-if".equals(cmd)) { registration.handle(line); } else { addLine(line); } } else { addLine(line); } } void run(CommandContext ctx) throws CommandLineException { try { final ModelControllerClient client = ctx.getModelControllerClient(); if(client == null) { throw new CommandLineException("The connection to the controller has not been established."); } ModelNode targetValue; try { targetValue = ctx.execute(ifRequest, "if condition"); } catch (IOException e) { throw new CommandLineException("condition request failed", e); } final Object value = ifCondition.resolveValue(ctx, targetValue); if(value == null) { throw new CommandLineException("if expression resolved to a null"); } registration.unregister(); if(Boolean.TRUE.equals(value)) { executeBlock(ctx, ifBlock, "if"); } else if(inElse) { executeBlock(ctx, elseBlock, "else"); } } finally { if(registration.isActive()) { registration.unregister(); } ctx.remove(Scope.CONTEXT, CTX_KEY); } } boolean isInIf() { return !inElse; } void moveToElse() { this.inElse = true; } private void executeBlock(CommandContext ctx, List<String> block, String blockName) throws CommandLineException { if(block != null && !block.isEmpty()) { final BatchManager batchManager = ctx.getBatchManager(); // this is to discard a batch started by the block in case the block fails // as the cli remains in the batch mode in case run-batch resulted in an error final boolean discardActivatedBatch = !batchManager.isBatchActive(); try { for (String l : block) { ctx.handle(l); } } finally { if(discardActivatedBatch && batchManager.isBatchActive()) { batchManager.discardActiveBatch(); } } } } private void addLine(final ParsedCommandLine line) { if(inElse) { if(elseBlock == null) { elseBlock = new ArrayList<String>(); } elseBlock.add(line.getOriginalLine()); } else { if(ifBlock == null) { ifBlock = new ArrayList<String>(); } ifBlock.add(line.getOriginalLine()); } } }