/* * JBoss, Home of Professional Open Source. * Copyright 2015, 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; import java.io.IOException; import java.util.Collections; import java.util.List; import org.jboss.as.cli.CommandContext; import org.jboss.as.cli.CommandFormatException; import org.jboss.as.cli.Util; import org.jboss.as.cli.impl.ArgumentWithValue; import org.jboss.as.cli.impl.DefaultCompleter; import org.jboss.as.cli.operation.CommandLineParser; import org.jboss.as.cli.operation.OperationRequestAddress; import org.jboss.as.cli.operation.OperationRequestCompleter; import org.jboss.as.cli.operation.ParsedCommandLine; import org.jboss.as.cli.operation.impl.DefaultCallbackHandler; import org.jboss.as.cli.operation.impl.DefaultOperationRequestAddress; import org.jboss.as.cli.util.SimpleTable; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.jboss.dmr.Property; /** * * @author Alexey Loubyansky */ public class ReadOperationHandler extends BaseOperationCommand { private final ArgumentWithValue node; private final ArgumentWithValue name; public ReadOperationHandler(CommandContext ctx) { super(ctx, "read-operation", true); node = new ArgumentWithValue(this, OperationRequestCompleter.ARG_VALUE_COMPLETER, "--node"); name = new ArgumentWithValue(this, new DefaultCompleter(new DefaultCompleter.CandidatesProvider() { @Override public List<String> getAllCandidates(CommandContext ctx) { try { final OperationRequestAddress address = getAddress(ctx); final ModelNode req = new ModelNode(); if(address.isEmpty()) { req.get(Util.ADDRESS).setEmptyList(); } else { if(address.endsOnType()) { return Collections.emptyList(); } final ModelNode addrNode = req.get(Util.ADDRESS); for(OperationRequestAddress.Node node : address) { addrNode.add(node.getType(), node.getName()); } } req.get(Util.OPERATION).set(Util.READ_OPERATION_NAMES); if(ctx.getConfig().isAccessControl()) { req.get(Util.ACCESS_CONTROL).set(true); } try { final ModelNode response = ctx.getModelControllerClient().execute(req); return Util.getList(response); } catch (IOException e) { e.printStackTrace(); } } catch (CommandFormatException e) { return Collections.emptyList(); } return Collections.emptyList(); }}), 0, "--name"); } /* (non-Javadoc) * @see org.jboss.as.cli.OperationCommand#buildRequest(org.jboss.as.cli.CommandContext) */ @Override public ModelNode buildRequestWithoutHeaders(CommandContext ctx) throws CommandFormatException { final ParsedCommandLine parsedCmd = ctx.getParsedCommandLine(); final String name = this.name.getValue(parsedCmd); if(name == null || name.isEmpty()) { final OperationRequestAddress address = getAddress(ctx); final ModelNode request = Util.buildRequest(ctx, address, Util.READ_OPERATION_NAMES); if(ctx.getConfig().isAccessControl()) { request.get(Util.ACCESS_CONTROL).set(true); } return request; } final OperationRequestAddress address = getAddress(ctx); ModelNode req = Util.buildRequest(ctx, address, Util.READ_OPERATION_DESCRIPTION); req.get(Util.NAME).set(name); return req; } protected void handleResponse(CommandContext ctx, ModelNode response, boolean composite) throws CommandFormatException { if (!Util.isSuccess(response)) { throw new CommandFormatException(Util.getFailureDescription(response)); } if(!response.hasDefined(Util.RESULT)) { return; } boolean opDescr; try { opDescr = name.isPresent(ctx.getParsedCommandLine()); } catch (CommandFormatException e) { throw new CommandFormatException("Failed to read argument " + name.getFullName() + ": " + e.getLocalizedMessage()); } if(opDescr) { final ModelNode result = response.get(Util.RESULT); if(result.has(Util.DESCRIPTION)) { ctx.printLine("\n\t" + result.get(Util.DESCRIPTION).asString()); } else { ctx.printLine("Operation description is not available."); } final StringBuilder buf = new StringBuilder(); buf.append("\n\nPARAMETERS\n"); if(result.has(Util.REQUEST_PROPERTIES)) { final List<Property> props = result.get(Util.REQUEST_PROPERTIES).asPropertyList(); if(props.isEmpty()) { buf.append("\n\tn/a\n"); } else { for(Property prop : props) { buf.append('\n'); buf.append(prop.getName()).append("\n\n"); final List<Property> propProps = prop.getValue().asPropertyList(); final SimpleTable table = new SimpleTable(2); for(Property propProp : propProps) { if(propProp.getName().equals(Util.DESCRIPTION)) { buf.append('\t').append(propProp.getValue().asString()).append("\n\n"); } else if(!propProp.getName().equals(Util.VALUE_TYPE)) { // TODO not detailing the value-type here, it's readability/formatting issue table.addLine(new String[]{'\t' + propProp.getName() + ':', propProp.getValue().asString()}); } } table.append(buf, false); buf.append('\n'); } } } else { buf.append("\n\tn/a\n"); } ctx.printLine(buf.toString()); buf.setLength(0); buf.append("\nRESPONSE\n"); if(result.has(Util.REPLY_PROPERTIES)) { final List<Property> props = result.get(Util.REPLY_PROPERTIES).asPropertyList(); if(props.isEmpty()) { buf.append("\n\tn/a\n"); } else { buf.append('\n'); final SimpleTable table = new SimpleTable(2); StringBuilder vtBuf = null; for(Property prop : props) { ModelType modelType = prop.getValue().getType(); if(prop.getName().equals(Util.DESCRIPTION)) { buf.append('\t').append(prop.getValue().asString()).append("\n\n"); } else if(prop.getName().equals(Util.VALUE_TYPE) && (prop.getValue().getType() == ModelType.OBJECT || prop.getValue().getType() == ModelType.LIST)) { final List<Property> vtProps = prop.getValue().asPropertyList(); if(!vtProps.isEmpty()) { vtBuf = new StringBuilder(); for(Property vtProp : vtProps) { vtBuf.append('\n').append(vtProp.getName()).append("\n\n"); final List<Property> vtPropProps = vtProp.getValue().asPropertyList(); final SimpleTable vtTable = new SimpleTable(2); for(Property vtPropProp : vtPropProps) { if(vtPropProp.getName().equals(Util.DESCRIPTION)) { vtBuf.append('\t').append(vtPropProp.getValue().asString()).append("\n\n"); } else if(!vtPropProp.getName().equals(Util.VALUE_TYPE)) { // TODO not detailing the value-type here, it's readability/formatting issue vtTable.addLine(new String[]{'\t' + vtPropProp.getName() + ':', vtPropProp.getValue().asString()}); } } vtTable.append(vtBuf, false); vtBuf.append('\n'); } } } else { table.addLine(new String[]{'\t' + prop.getName() + ':', prop.getValue().asString()}); } } table.append(buf, false); buf.append('\n'); if(vtBuf != null) { buf.append(vtBuf); } } } else { buf.append("\n\tn/a\n"); } ctx.printLine(buf.toString()); } else { ctx.printColumns(Util.getList(response)); } } protected OperationRequestAddress getAddress(CommandContext ctx) throws CommandFormatException { final ParsedCommandLine args = ctx.getParsedCommandLine(); final OperationRequestAddress address; if (node.isPresent(args)) { address = new DefaultOperationRequestAddress(ctx.getCurrentNodePath()); CommandLineParser.CallbackHandler handler = new DefaultCallbackHandler(address); // this is for correct parsing of escaped characters String nodePath = args.getOriginalLine(); int nodeArgInd = nodePath.indexOf(" --node="); if(nodeArgInd < 0) { throw new CommandFormatException("Couldn't locate ' --node=' in the line: '" + nodePath + "'"); } int nodeArgEndInd = nodeArgInd + 8; do { nodeArgEndInd = nodePath.indexOf(' ', nodeArgEndInd); if(nodeArgEndInd < 0) { nodeArgEndInd = nodePath.length(); } else if(nodePath.charAt(nodeArgEndInd - 1) == '\\') { ++nodeArgEndInd; } else { break; } } while(nodeArgEndInd < nodePath.length()); nodePath = nodePath.substring(nodeArgInd + 8, nodeArgEndInd); ctx.getCommandLineParser().parse(nodePath, handler); } else { address = new DefaultOperationRequestAddress(ctx.getCurrentNodePath()); } return address; } }