|
Glassfish example source code file (CommandRunnerImpl.java)
The Glassfish CommandRunnerImpl.java source code
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2008-2011 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.enterprise.v3.admin;
import com.sun.enterprise.admin.util.ClusterOperationUtil;
import com.sun.enterprise.admin.util.InstanceStateService;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.Cluster;
import com.sun.enterprise.module.common_impl.LogHelper;
import java.io.*;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.concurrent.locks.Lock;
import org.glassfish.admin.payload.PayloadFilesManager;
import org.glassfish.api.ActionReport;
import org.glassfish.api.Async;
import org.glassfish.api.Param;
import org.glassfish.api.admin.*;
import org.glassfish.common.util.admin.CommandModelImpl;
import org.glassfish.common.util.admin.MapInjectionResolver;
import org.glassfish.common.util.admin.UnacceptableValueException;
import org.glassfish.common.util.admin.ManPageFinder;
import org.glassfish.config.support.CommandTarget;
import org.glassfish.config.support.GenericCrudCommand;
import org.glassfish.config.support.TargetType;
import org.glassfish.internal.api.*;
import org.jvnet.hk2.annotations.Inject;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.annotations.Scoped;
import org.jvnet.hk2.component.*;
import com.sun.hk2.component.InjectionResolver;
import com.sun.enterprise.universal.collections.ManifestUtils;
import com.sun.enterprise.universal.glassfish.AdminCommandResponse;
import com.sun.enterprise.util.LocalStringManagerImpl;
import com.sun.enterprise.v3.common.XMLContentActionReporter;
import com.sun.logging.LogDomains;
/**
* Encapsulates the logic needed to execute a server-side command (for example,
* a descendant of AdminCommand) including injection of argument values into the
* command.
*
* @author dochez
* @author tjquinn
* @author Bill Shannon
*/
@Service
public class CommandRunnerImpl implements CommandRunner {
private final Logger logger = LogDomains.getLogger(CommandRunnerImpl.class,
LogDomains.ADMIN_LOGGER);
private final InjectionManager injectionMgr = new InjectionManager();
@Inject
private Habitat habitat;
@Inject
private ServerContext sc;
@Inject
private Domain domain;
@Inject
private ServerEnvironment serverEnv;
@Inject
private ProcessEnvironment processEnv;
@Inject
private InstanceStateService state;
@Inject
private AdminCommandLock adminLock;
private static final String ASADMIN_CMD_PREFIX = "AS_ADMIN_";
private static final LocalStringManagerImpl adminStrings =
new LocalStringManagerImpl(CommandRunnerImpl.class);
/**
* Returns an initialized ActionReport instance for the passed type or
* null if it cannot be found.
*
* @param name actiopn report type name
* @return uninitialized action report or null
*/
public ActionReport getActionReport(String name) {
return habitat.getComponent(ActionReport.class, name);
}
/**
* Retuns the command model for a command name.
*
* @param commandName command name
* @param logger logger to log any error messages
* @return model for this command (list of parameters,etc...),
* or null if command is not found
*/
public CommandModel getModel(String commandName, Logger logger) {
AdminCommand command = null;
try {
command = habitat.getComponent(AdminCommand.class, commandName);
} catch (ComponentException e) {
logger.log(Level.SEVERE, "Cannot instantiate " + commandName, e);
return null;
}
return command == null ? null : getModel(command);
}
/**
* Obtain and return the command implementation defined by
* the passed commandName.
*
* @param commandName command name as typed by users
* @param report report used to communicate command status back to the user
* @param logger logger to log
* @return command registered under commandName or null if not found
*/
public AdminCommand getCommand(String commandName, ActionReport report,
Logger logger) {
AdminCommand command = null;
try {
command = habitat.getComponent(AdminCommand.class, commandName);
} catch (ComponentException e) {
e.printStackTrace();
report.setFailureCause(e);
}
if (command == null) {
String msg;
if (!ok(commandName))
msg = adminStrings.getLocalString("adapter.command.nocommand",
"No command was specified.");
else {
// this means either a non-existent command or
// an ill-formed command
if (habitat.getInhabitant(AdminCommand.class, commandName) ==
null) // somehow it's in habitat
msg = adminStrings.getLocalString("adapter.command.notfound", "Command {0} not found", commandName);
else
msg = adminStrings.getLocalString("adapter.command.notcreated",
"Implementation for the command {0} exists in " +
"the system, but it has some errors, " +
"check server.log for details", commandName);
}
report.setMessage(msg);
report.setActionExitCode(ActionReport.ExitCode.FAILURE);
LogHelper.getDefaultLogger().info(msg);
return null;
}
Scoped scoped = command.getClass().getAnnotation(Scoped.class);
if (scoped == null) {
String msg = adminStrings.getLocalString("adapter.command.noscope",
"Implementation for the command {0} exists in the " +
"system,\nbut it has no @Scoped annotation", commandName);
report.setMessage(msg);
report.setActionExitCode(ActionReport.ExitCode.FAILURE);
LogHelper.getDefaultLogger().info(msg);
command = null;
} else if (scoped.value() == Singleton.class) {
// check that there are no parameters for this command
CommandModel model = getModel(command);
if (model.getParameters().size() > 0) {
String msg =
adminStrings.getLocalString("adapter.command.hasparams",
"Implementation for the command {0} exists in the " +
"system,\nbut it's a singleton that also has " +
"parameters", commandName);
report.setMessage(msg);
report.setActionExitCode(ActionReport.ExitCode.FAILURE);
LogHelper.getDefaultLogger().info(msg);
command = null;
}
}
return command;
}
/**
* Obtain a new command invocation object.
* Command invocations can be configured and used
* to trigger a command execution.
*
* @param name name of the requested command to invoke
* @param report where to place the status of the command execution
* @return a new command invocation for that command name
*/
public CommandInvocation getCommandInvocation(String name,
ActionReport report) {
return new ExecutionContext(name, report);
}
private ActionReport.ExitCode injectParameters(final CommandModel model, final AdminCommand command,
final InjectionResolver<Param> injector,
final AdminCommandContext context) {
ActionReport report = context.getActionReport();
report.setActionDescription(model.getCommandName() + " command");
report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
try {
GenericCrudCommand c = GenericCrudCommand.class.cast(command);
c.setInjectionResolver(injector);
} catch(ClassCastException e) {
// do nothing.
}
// inject
try {
injectionMgr.inject(command, injector);
} catch (UnsatisfiedDependencyException e) {
Param param = e.getAnnotation(Param.class);
CommandModel.ParamModel paramModel=null;
for (CommandModel.ParamModel pModel : model.getParameters()) {
if (pModel.getParam().equals(param)) {
paramModel = pModel;
break;
}
}
String errorMsg;
final String usage = getUsageText(command, model);
if (paramModel != null) {
String paramName = paramModel.getName();
String paramDesc = paramModel.getLocalizedDescription();
if (param.primary()) {
errorMsg = adminStrings.getLocalString("commandrunner.operand.required",
"Operand required.");
} else if (param.password()) {
errorMsg = adminStrings.getLocalString("adapter.param.missing.passwordfile",
"{0} command requires the passwordfile " +
"parameter containing {1} entry.",
model.getCommandName(), paramName);
} else if (paramDesc != null) {
errorMsg = adminStrings.getLocalString("admin.param.missing",
"{0} command requires the {1} parameter ({2})",
model.getCommandName(), paramName, paramDesc);
} else {
errorMsg = adminStrings.getLocalString("admin.param.missing.nodesc",
"{0} command requires the {1} parameter",
model.getCommandName(), paramName);
}
} else {
errorMsg = adminStrings.getLocalString("admin.param.missing.nofound",
"Cannot find {1} in {0} command model, file a bug",
model.getCommandName(), e.getUnsatisfiedName());
}
logger.severe(errorMsg);
report.setActionExitCode(ActionReport.ExitCode.FAILURE);
report.setMessage(errorMsg);
report.setFailureCause(e);
ActionReport.MessagePart childPart =
report.getTopMessagePart().addChild();
childPart.setMessage(usage);
return report.getActionExitCode();
} catch (ComponentException e) {
// If the cause is UnacceptableValueException -- we want the message
// from it. It is wrapped with a less useful Exception.
Exception exception = e;
Throwable cause = e.getCause();
if (cause != null &&
(cause instanceof UnacceptableValueException ||
cause instanceof IllegalArgumentException)) {
// throw away the wrapper.
exception = (Exception)cause;
}
logger.log(Level.SEVERE, "invocation.exception", exception);
report.setActionExitCode(ActionReport.ExitCode.FAILURE);
report.setMessage(exception.getMessage());
report.setFailureCause(exception);
ActionReport.MessagePart childPart =
report.getTopMessagePart().addChild();
childPart.setMessage(getUsageText(command, model));
return report.getActionExitCode();
}
return report.getActionExitCode();
}
/**
* Executes the provided command object.
*
* @param model model of the command (used for logging and reporting)
* @param command the command service to execute
* @param context the AdminCommandcontext that has the payload and report
*/
private ActionReport doCommand(
final CommandModel model,
final AdminCommand command,
final AdminCommandContext context) {
ActionReport report = context.getActionReport();
report.setActionDescription(model.getCommandName() + " AdminCommand");
// We need to set context CL to common CL before executing
// the command. See issue #5596
final AdminCommand wrappedComamnd = new AdminCommand() {
public void execute(AdminCommandContext context) {
Thread thread = Thread.currentThread();
ClassLoader origCL = thread.getContextClassLoader();
ClassLoader ccl = sc.getCommonClassLoader();
if (origCL != ccl) {
try {
thread.setContextClassLoader(ccl);
command.execute(context);
} finally {
thread.setContextClassLoader(origCL);
}
} else {
command.execute(context);
}
}
};
// the command may be an asynchronous command, so we need to check
// for the @Async annotation.
Async async = command.getClass().getAnnotation(Async.class);
if (async == null) {
try {
wrappedComamnd.execute(context);
} catch(Throwable e) {
logger.log(Level.SEVERE,
adminStrings.getLocalString("adapter.exception",
"Exception in command execution : ", e), e);
report.setMessage(e.toString());
report.setActionExitCode(ActionReport.ExitCode.FAILURE);
report.setFailureCause(e);
}
} else {
Thread t = new Thread() {
public void run() {
try {
wrappedComamnd.execute(context);
} catch (RuntimeException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
};
t.setPriority(async.priority());
t.start();
report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
report.setMessage(
adminStrings.getLocalString("adapter.command.launch",
"Command {0} was successfully initiated asynchronously.",
model.getCommandName()));
}
return context.getActionReport();
}
/**
* Get the usage-text of the command.
* Check if <command-name>.usagetext is defined in LocalString.properties.
* If defined, then use the usagetext from LocalString.properties else
* generate the usagetext from Param annotations in the command class.
*
* @param command class
* @param model command model
* @return usagetext
*/
static String getUsageText(AdminCommand command, CommandModel model) {
StringBuffer usageText = new StringBuffer();
String usage;
if (ok(usage = model.getUsageText())) {
usageText.append(
adminStrings.getLocalString("adapter.usage", "Usage: "));
usageText.append(usage);
return usageText.toString();
} else {
return generateUsageText(model);
}
}
/**
* Generate the usage-text from the annotated Param in the command class.
*
* @param model command model
* @return generated usagetext
*/
private static String generateUsageText(CommandModel model) {
StringBuffer usageText = new StringBuffer();
usageText.append(
adminStrings.getLocalString("adapter.usage", "Usage: "));
usageText.append(model.getCommandName());
usageText.append(" ");
StringBuffer operand = new StringBuffer();
for (CommandModel.ParamModel pModel : model.getParameters()) {
final Param param = pModel.getParam();
final String paramName =
pModel.getName().toLowerCase(Locale.ENGLISH);
// skip "hidden" options
if (paramName.startsWith("_"))
continue;
// do not want to display password as an option
if (param.password())
continue;
// do not want to display obsolete options
if (param.obsolete())
continue;
final boolean optional = param.optional();
final Class<?> ftype = pModel.getType();
Object fvalue = null;
String fvalueString = null;
try {
fvalue = param.defaultValue();
if (fvalue != null)
fvalueString = fvalue.toString();
} catch (Exception e) {
// just leave it as null...
}
// this is a param.
if (param.primary()) {
if (optional) {
operand.append("[").append(paramName).append("] ");
} else {
operand.append(paramName).append(" ");
}
continue;
}
if (optional)
usageText.append("[");
usageText.append("--").append(paramName);
if (ok(param.defaultValue())) {
usageText.append("=").append(param.defaultValue());
} else if (ftype.isAssignableFrom(String.class)) {
// check if there is a default value assigned
if (ok(fvalueString)) {
usageText.append("=").append(fvalueString);
} else {
usageText.append("=").append(paramName);
}
} else if (ftype.isAssignableFrom(Boolean.class)) {
// note: There is no defaultValue for this param. It might
// hava value -- but we don't care -- it isn't an official
// default value.
usageText.append("=").append("true|false");
} else {
usageText.append("=").append(paramName);
}
if (optional)
usageText.append("] ");
else
usageText.append(" ");
}
usageText.append(operand);
return usageText.toString();
}
public void getHelp(AdminCommand command, ActionReport report) {
CommandModel model = getModel(command);
report.setActionDescription(model.getCommandName() + " help");
// XXX - this is a hack for now. if the request mapped to an
// XMLContentActionReporter, that means we want the command metadata.
if (report instanceof XMLContentActionReporter) {
getMetadata(command, model, report);
} else {
report.setMessage(model.getCommandName() + " - " +
model.getLocalizedDescription());
report.getTopMessagePart().addProperty("SYNOPSIS",
encodeManPage(new BufferedReader(new StringReader(
getUsageText(command, model)))));
for (CommandModel.ParamModel param : model.getParameters()) {
addParamUsage(report, param);
}
report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
}
}
/**
* Return the metadata for the command. We translate the parameter
* and operand information to parts and properties of the ActionReport,
* which will be translated to XML elements and attributes by the
* XMLContentActionReporter.
*
* @param command the command
* @param model the CommandModel describing the command
* @param report the (assumed to be) XMLContentActionReporter
*/
private void getMetadata(AdminCommand command, CommandModel model,
ActionReport report) {
ActionReport.MessagePart top = report.getTopMessagePart();
ActionReport.MessagePart cmd = top.addChild();
// <command name="name">
cmd.setChildrenType("command");
cmd.addProperty("name", model.getCommandName());
if (model.unknownOptionsAreOperands())
cmd.addProperty("unknown-options-are-operands", "true");
String usage = model.getUsageText();
if (ok(usage))
cmd.addProperty("usage", usage);
CommandModel.ParamModel primary = null;
// for each parameter add
// <option name="name" type="type" short="s" default="default"
// acceptable-values="list"/>
for (CommandModel.ParamModel p : model.getParameters()) {
Param param = p.getParam();
if (param.primary()) {
primary = p;
continue;
}
ActionReport.MessagePart ppart = cmd.addChild();
ppart.setChildrenType("option");
ppart.addProperty("name", p.getName());
ppart.addProperty("type", typeOf(p));
ppart.addProperty("optional", Boolean.toString(param.optional()));
if (param.obsolete()) // don't include it if it's false
ppart.addProperty("obsolete", "true");
String paramDesc = p.getLocalizedDescription();
if (ok(paramDesc))
ppart.addProperty("description", paramDesc);
if (ok(param.shortName()))
ppart.addProperty("short", param.shortName());
if (ok(param.defaultValue()))
ppart.addProperty("default", param.defaultValue());
if (ok(param.acceptableValues()))
ppart.addProperty("acceptable-values", param.acceptableValues());
if (ok(param.alias()))
ppart.addProperty("alias", param.alias());
}
// are operands allowed?
if (primary != null) {
// for the operand(s), add
// <operand type="type" min="0/1" max="1"/>
ActionReport.MessagePart primpart = cmd.addChild();
primpart.setChildrenType("operand");
primpart.addProperty("name", primary.getName());
primpart.addProperty("type", typeOf(primary));
primpart.addProperty("min",
primary.getParam().optional() ? "0" : "1");
primpart.addProperty("max", primary.getParam().multiple() ?
"unlimited" : "1");
String desc = primary.getLocalizedDescription();
if (ok(desc))
primpart.addProperty("description", desc);
}
}
/**
* Map a Java type to one of the types supported by the asadmin client.
* Currently supported types are BOOLEAN, FILE, PROPERTIES, PASSWORD, and
* STRING. (All of which should be defined constants on some class.)
*
* @param p the Java type
* @return the string representation of the asadmin type
*/
private static String typeOf(CommandModel.ParamModel p) {
Class t = p.getType();
if (t == Boolean.class || t == boolean.class)
return "BOOLEAN";
else if (t == File.class)
return "FILE";
else if (t == Properties.class) // XXX - allow subclass?
return "PROPERTIES";
else if (p.getParam().password())
return "PASSWORD";
else
return "STRING";
}
// XXX - "logger" should be static and this should be removed
private static final Logger manpagelogger =
LogDomains.getLogger(CommandRunnerImpl.class, LogDomains.ADMIN_LOGGER);
/**
* Return an InputStream for the man page for the named command.
*/
public static BufferedReader getManPage(String commandName,
CommandModel model) {
Class clazz = model.getCommandClass();
if (clazz == null)
return null;
return ManPageFinder.getCommandManPage(commandName, clazz.getName(),
Locale.getDefault(), clazz.getClassLoader(), manpagelogger);
}
private void addParamUsage(
ActionReport report,
CommandModel.ParamModel model) {
Param param = model.getParam();
if (param!=null) {
// this is a param.
String paramName = model.getName().toLowerCase(Locale.ENGLISH);
// skip "hidden" options
if (paramName.startsWith("_"))
return;
// do not want to display password in the usage
if (param.password())
return;
// do not want to display obsolete options
if (param.obsolete())
return;
if (param.primary()) {
// if primary then it's an operand
report.getTopMessagePart().addProperty(paramName+"_operand",
model.getLocalizedDescription());
} else {
report.getTopMessagePart().addProperty(paramName,
model.getLocalizedDescription());
}
}
}
private static boolean ok(String s) {
return s != null && s.length() > 0;
}
/**
* Validate the paramters with the Param annotation. If parameter is
* not defined as a Param annotation then it's an invalid option.
* If parameter's key is "DEFAULT" then it's a operand.
*
* @param model command model
* @param parameters parameters from URL
* @throws ComponentException if option is invalid
*/
static void validateParameters(final CommandModel model,
final ParameterMap parameters) throws ComponentException {
// loop through parameters and make sure they are
// part of the Param declared field
for (Map.Entry<String,List
Other Glassfish examples (source code examples)Here is a short list of links related to this Glassfish CommandRunnerImpl.java source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.