/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2012 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 org.glassfish.admin.rest.resources.admin;
import com.sun.enterprise.admin.remote.AdminCommandStateImpl;
import com.sun.enterprise.admin.remote.RemoteRestAdminCommand;
import com.sun.enterprise.admin.remote.RestPayloadImpl;
import com.sun.enterprise.admin.util.CachedCommandModel;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.universal.collections.ManifestUtils;
import com.sun.enterprise.util.LocalStringManagerImpl;
import com.sun.enterprise.util.StringUtils;
import com.sun.enterprise.util.uuid.UuidGenerator;
import com.sun.enterprise.util.uuid.UuidGeneratorImpl;
import com.sun.enterprise.v3.admin.JobManagerService;
import com.sun.enterprise.v3.common.ActionReporter;
import com.sun.enterprise.v3.common.PlainTextActionReporter;
import com.sun.enterprise.v3.common.PropsFileActionReporter;
import com.sun.logging.LogDomains;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.security.auth.Subject;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.core.Response.ResponseBuilder;
import org.glassfish.api.ActionReport;
import org.glassfish.api.admin.AdminCommandEventBroker.AdminCommandListener;
import org.glassfish.api.admin.*;
import org.glassfish.api.admin.AdminCommandEventBroker.BrokerListenerRegEvent;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.internal.api.Globals;
import org.glassfish.jersey.internal.util.collection.Ref;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.sse.EventChannel;
import org.glassfish.jersey.media.sse.OutboundEvent;
import org.glassfish.jersey.media.sse.EventChannel;
/**
*
* @author mmares
*/
@Path("/")
public class CommandResource {
private final static Logger logger =
LogDomains.getLogger(CommandResource.class, LogDomains.ADMIN_LOGGER);
private final static LocalStringManagerImpl strings = new LocalStringManagerImpl(CommandResource.class);
public static final String SESSION_COOKIE_NAME = "JSESSIONID";
public static final int MAX_AGE = 86400 ;
private static UuidGenerator uuidGenerator = new UuidGeneratorImpl();
private static volatile String serverName;
private CommandRunner commandRunner;
@Inject
protected Ref<Subject> subjectRef;
// @GET
// @Produces({MediaType.TEXT_PLAIN})
// public String emptyCallTxt() {
// logger.finest("emptyCallTxt()");
// return "command resource - Loaded";
// }
//
// @GET
// @Produces({MediaType.TEXT_HTML})
// public String emptyCallHtml() {
// logger.finest("emptyCallHtml()");
// return "<html><body><h1>command resource</h1>Loaded</body></html>";
// }
// -------- GET+OPTION: Get CommandModel
@GET
@Path("/{command:.*}/")
@Produces({MediaType.APPLICATION_JSON, "application/x-javascript"})
public Response getCommandModel(@PathParam("command") String command) throws WebApplicationException {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "getCommandModel({0})", commandName);
}
CommandModel model = getCommandModel(commandName);
String eTag = CachedCommandModel.computeETag(model);
return Response.ok(model).tag(new EntityTag(eTag, true)).build();
}
@OPTIONS
@Path("/{command:.*}/")
@Produces({MediaType.APPLICATION_JSON, "application/x-javascript"})
public Response optionsCommandModel(@PathParam("command") String commandName) throws WebApplicationException {
return getCommandModel(commandName);
}
// -------- GET: Manpage
@GET
@Path("/{command:.*}/manpage")
@Produces({MediaType.TEXT_HTML})
public String getManPageHtml(@PathParam("command") String command)
throws IOException, WebApplicationException {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "getManPageHtml({0})", commandName);
}
BufferedReader help = getManPageReader(commandName);
if (help == null) {
return null;
}
StringBuilder result = new StringBuilder();
result.append("<html><body>");
String line;
while ((line = help.readLine()) != null) {
result.append(leadingSpacesToNbsp(StringUtils.escapeForHtml(line))).append("<br/>\n");
}
result.append("</body></html>");
return result.toString();
}
@GET
@Path("/{command:.*}/manpage")
@Produces({MediaType.TEXT_PLAIN})
public String getManPageTxt(@PathParam("command") String command, @QueryParam("eol") String eol)
throws IOException, WebApplicationException {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "getManPageTxt({0}, {1})", new Object[]{commandName, eol});
}
BufferedReader help = getManPageReader(commandName);
if (help == null) {
return null;
}
if (!StringUtils.ok(eol)) {
eol = ManifestUtils.EOL;
}
StringBuilder result = new StringBuilder();
String line;
while ((line = help.readLine()) != null) {
result.append(line).append(eol);
}
return result.toString();
}
// -------- POST: Execute command [just ACTION-REPORT]
@POST
@Path("/{command:.*}/")
@Consumes({MediaType.APPLICATION_FORM_URLENCODED})
@Produces({MediaType.APPLICATION_JSON, "application/x-javascript"})
public Response execCommandSimpInSimpOut(@PathParam("command") String command,
@HeaderParam("X-Indent") String indent,
@HeaderParam(RemoteRestAdminCommand.COMMAND_MODEL_MATCH_HEADER) String modelETag,
@CookieParam(SESSION_COOKIE_NAME) Cookie jSessionId,
ParameterMap data) {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "execCommandSimpInSimpOut({0})", commandName);
}
return executeCommand(commandName, null, data, false, indent, modelETag, jSessionId);
}
@POST
@Path("/{command:.*}/")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces({MediaType.APPLICATION_JSON, "application/x-javascript"})
public Response execCommandMultInSimpOut(@PathParam("command") String command,
@HeaderParam("X-Indent") String indent,
@HeaderParam(RemoteRestAdminCommand.COMMAND_MODEL_MATCH_HEADER) String modelETag,
@CookieParam(SESSION_COOKIE_NAME) Cookie jSessionId,
FormDataMultiPart mp) {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "execCommandMultInSimpOut({0})", commandName);
}
ParameterMap data = new ParameterMap();
Payload.Inbound inbound = RestPayloadImpl.Inbound.parseFromFormDataMultipart(mp, data);
return executeCommand(commandName, inbound, data, false, indent, modelETag, jSessionId);
}
@POST
@Path("/{command:.*}/")
@Produces({MediaType.APPLICATION_JSON, "application/x-javascript"})
public Response execCommandEmptyInSimpOut(@PathParam("command") String command,
@HeaderParam("X-Indent") String indent,
@HeaderParam(RemoteRestAdminCommand.COMMAND_MODEL_MATCH_HEADER) String modelETag,
@CookieParam(SESSION_COOKIE_NAME) Cookie jSessionId) {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "execCommandEmptyInSimpOut({0})", commandName);
}
ParameterMap data = new ParameterMap();
return executeCommand(commandName, null, data, false, indent, modelETag, jSessionId);
}
// -------- POST: Execute command [MULTIPART result]
@POST
@Path("/{command:.*}/")
@Consumes({MediaType.APPLICATION_FORM_URLENCODED})
@Produces("multipart/mixed")
public Response execCommandSimpInMultOut(@PathParam("command") String command,
@HeaderParam("X-Indent") String indent,
@HeaderParam(RemoteRestAdminCommand.COMMAND_MODEL_MATCH_HEADER) String modelETag,
@CookieParam(SESSION_COOKIE_NAME) Cookie jSessionId,
ParameterMap data) {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "execCommandSimpInMultOut({0})", commandName);
}
return executeCommand(commandName, null, data, true, indent, modelETag, jSessionId);
}
@POST
@Path("/{command:.*}/")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces("multipart/mixed")
public Response execCommandMultInMultOut(@PathParam("command") String command,
@HeaderParam("X-Indent") String indent,
@HeaderParam(RemoteRestAdminCommand.COMMAND_MODEL_MATCH_HEADER) String modelETag,
@CookieParam(SESSION_COOKIE_NAME) Cookie jSessionId,
FormDataMultiPart mp) {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "execCommandMultInMultOut({0})", commandName);
}
ParameterMap data = new ParameterMap();
Payload.Inbound inbound = RestPayloadImpl.Inbound.parseFromFormDataMultipart(mp, data);
return executeCommand(commandName, inbound, data, true, indent, modelETag, jSessionId);
}
@POST
@Path("/{command:.*}/")
@Produces("multipart/mixed")
public Response execCommandEmptyInMultOut(@PathParam("command") String command,
@HeaderParam("X-Indent") String indent,
@HeaderParam(RemoteRestAdminCommand.COMMAND_MODEL_MATCH_HEADER) String modelETag,
@CookieParam(SESSION_COOKIE_NAME) Cookie jSessionId) {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "execCommandEmptyInMultOut({0})", commandName);
}
ParameterMap data = new ParameterMap();
return executeCommand(commandName, null, data, true, indent, modelETag, jSessionId);
}
// -------- POST: Execute command [SSE]
@POST
@Path("/{command:.*}/")
@Consumes({MediaType.APPLICATION_FORM_URLENCODED})
@Produces(EventChannel.SERVER_SENT_EVENTS)
public Response execCommandSimpInSseOut(@PathParam("command") String command,
@HeaderParam(RemoteRestAdminCommand.COMMAND_MODEL_MATCH_HEADER) String modelETag,
@CookieParam(SESSION_COOKIE_NAME) Cookie jSessionId,
ParameterMap data) {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "execCommandSimpInSseOut({0})", commandName);
}
return executeSseCommand(commandName, null, data, modelETag, jSessionId);
}
@POST
@Path("/{command:.*}/")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(EventChannel.SERVER_SENT_EVENTS)
public Response execCommandMultInSseOut(@PathParam("command") String command,
@HeaderParam(RemoteRestAdminCommand.COMMAND_MODEL_MATCH_HEADER) String modelETag,
@CookieParam(SESSION_COOKIE_NAME) Cookie jSessionId,
FormDataMultiPart mp) {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "execCommandMultInMultOut({0})", commandName);
}
ParameterMap data = new ParameterMap();
// Payload.Inbound inbound = RestPayloadImpl.Inbound.parseFromFormDataMultipart(mp, data);
return executeSseCommand(commandName, null, data, modelETag, jSessionId);
}
@POST
@Path("/{command:.*}/")
@Produces(EventChannel.SERVER_SENT_EVENTS)
public Response execCommandEmptyInSseOut(@PathParam("command") String command,
@HeaderParam(RemoteRestAdminCommand.COMMAND_MODEL_MATCH_HEADER) String modelETag,
@CookieParam(SESSION_COOKIE_NAME) Cookie jSessionId) {
CommandName commandName = new CommandName(normalizeCommandName(command));
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "execCommandEmptyInMultOut({0})", commandName);
}
ParameterMap data = new ParameterMap();
return executeSseCommand(commandName, null, data, modelETag, jSessionId);
}
// -------- private implementation
private String normalizeCommandName(String str) {
if (str == null) {
return null;
}
if (str.endsWith("/")) {
return str.substring(0, str.length() - 1);
} else {
return str;
}
}
private void checkCommandModelETag(CommandModel model, String modelETag) throws WebApplicationException {
CommandRunner cr = getCommandRunner();
if (StringUtils.ok(modelETag) && !cr.validateCommandModelETag(model, modelETag)) {
String message =
strings.getLocalString("commandmodel.etag.invalid",
"Cached command model for command {0} is invalid.", model.getCommandName());
throw new WebApplicationException(Response.status(Response.Status.PRECONDITION_FAILED)
.type(MediaType.TEXT_PLAIN)
.entity(message)
.build());
}
}
private Response executeSseCommand(CommandName commandName, Payload.Inbound inbound,
ParameterMap params, String modelETag, Cookie jSessionId) throws WebApplicationException {
//Scope support
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "executeSseCommand(): ", commandName);
}
//Check command model
CommandModel model = getCommandModel(commandName);
checkCommandModelETag(model, modelETag);
//Execute it
final CommandRunner.CommandInvocation commandInvocation =
getCommandRunner().getCommandInvocation(commandName.getScope(),
commandName.getName(), new PropsFileActionReporter());
if (inbound != null) {
commandInvocation.inbound(inbound);
}
commandInvocation
.outbound(new RestPayloadImpl.Outbound(false))
.subject(getSubject())
.managedJob()
.parameters(params);
final EventChannel ec = new EventChannel();
AdminCommandListener listener = new AdminCommandListener() {
private AdminCommandEventBroker broker;
private void unregister() {
if (broker != null) {
broker.unregisterListener(this);
}
}
@Override
public void onAdminCommandEvent(String name, Object event) {
if (name == null || event == null) {
return;
}
if (BrokerListenerRegEvent.EVENT_NAME_LISTENER_REG.equals(name)) {
BrokerListenerRegEvent blre = (BrokerListenerRegEvent) event;
broker = blre.getBroker();
return;
}
if (name.startsWith(AdminCommandEventBroker.LOCAL_EVENT_PREFIX)) {
return; //Prevent events from client to be send back to client
}
if (ec.isClosed()) {
unregister();
return;
}
if ((event instanceof Number) ||
(event instanceof CharSequence) ||
(event instanceof Boolean)) {
event = String.valueOf(event);
}
OutboundEvent outEvent = new OutboundEvent.Builder()
.name(name)
.mediaType(event instanceof String ?
MediaType.TEXT_PLAIN_TYPE :
MediaType.APPLICATION_JSON_TYPE)
.data(event.getClass(), event)
.build();
try {
ec.write(outEvent);
} catch (Exception ex) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, strings.getLocalString("sse.writeevent.exception",
"Can not write object as SSE (type = {0})",
event.getClass().getName()), ex);
}
if (ec.isClosed()) {
unregister();
}
}
}
};
commandInvocation.listener(".*", listener);
ResponseBuilder rb = Response.status(HttpURLConnection.HTTP_OK);
if ( isSingleInstanceCommand(model)) {
rb.cookie(getJSessionCookie(jSessionId));
}
rb.entity(ec);
executeCommandInvocationAsync(commandInvocation, ec, listener);
return rb.build();
}
private void executeCommandInvocationAsync(final CommandRunner.CommandInvocation ci,
final EventChannel ec,
final AdminCommandListener listener) {
JobManagerService jobManagerService = Globals.getDefaultHabitat().getService(JobManagerService.class);
ExecutorService pool = jobManagerService.getThreadPool();
pool.execute(new AsyncInvocationHandler(ci,ec,listener));
}
class AsyncInvocationHandler implements Runnable {
private CommandRunner.CommandInvocation commandInvocation;
private EventChannel eventChannel;
private AdminCommandListener listener;
AsyncInvocationHandler(CommandRunner.CommandInvocation inv, EventChannel channel, AdminCommandListener list) {
this.commandInvocation = inv;
this.eventChannel = channel;
this.listener = list;
}
@Override
public void run() {
try {
commandInvocation.execute();
} catch (Throwable thr) {
logger.log(Level.WARNING, strings.getLocalString("sse.commandexecution.unexpectedexception",
"Unexpected exception during command execution. {0}",
thr.toString()));
ActionReport actionReport = new PropsFileActionReporter(); //new RestActionReporter();
actionReport.setFailureCause(thr);
actionReport.setActionExitCode(ActionReport.ExitCode.FAILURE);
AdminCommandState acs = new AdminCommandStateImpl(AdminCommandState.State.COMPLETED, actionReport, true, "unknown");
listener.onAdminCommandEvent(AdminCommandStateImpl.EVENT_STATE_CHANGED, acs);
} finally {
try {
eventChannel.close();
} catch (IOException ex) {
logger.log(Level.WARNING, null, ex);
}
}
}
}
private Response executeCommand(CommandName commandName, Payload.Inbound inbound,
ParameterMap params, boolean supportsMultiparResult, String xIndentHeader,
String modelETag, Cookie jSessionId) throws WebApplicationException {
//Scope support
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "executeCommand(): ", commandName);
}
//Check command model
CommandModel model = getCommandModel(commandName);
checkCommandModelETag(model, modelETag);
//Execute it
ActionReporter ar = new PropsFileActionReporter(); //new RestActionReporter(); //Must use PropsFileActionReporter because some commands react diferently on it :-(
final RestPayloadImpl.Outbound outbound = new RestPayloadImpl.Outbound(false);
final CommandRunner.CommandInvocation commandInvocation =
getCommandRunner().getCommandInvocation(commandName.getScope(), commandName.getName(), ar);
if (inbound != null) {
commandInvocation.inbound(inbound);
}
commandInvocation
.outbound(outbound)
.parameters(params)
.subject(getSubject())
.execute();
ar = (ActionReporter) commandInvocation.report();
fixActionReporterSpecialCases(ar);
ActionReport.ExitCode exitCode = ar.getActionExitCode();
int status = HttpURLConnection.HTTP_OK; /*200 - ok*/
if (exitCode == ActionReport.ExitCode.FAILURE) {
status = HttpURLConnection.HTTP_INTERNAL_ERROR;
}
ResponseBuilder rb = Response.status(status);
if (xIndentHeader != null) {
rb.header("X-Indent", xIndentHeader);
}
if (supportsMultiparResult && outbound.size() > 0) {
MultiPart mp = new MultiPart();
mp.bodyPart(ar, MediaType.APPLICATION_JSON_TYPE);
if (outbound.size() > 0) {
outbound.addToMultipart(mp, logger);
}
rb.entity(mp);
} else {
rb.type(MediaType.APPLICATION_JSON_TYPE);
rb.entity(ar);
}
if ( isSingleInstanceCommand(model)) {
rb.cookie(getJSessionCookie(jSessionId));
}
return rb.build();
}
/** Some ActionReporters has special logic which must be reflected here
*/
private void fixActionReporterSpecialCases(ActionReporter ar) {
if (ar == null) {
return;
}
if (ar instanceof PlainTextActionReporter) {
PlainTextActionReporter par = (PlainTextActionReporter) ar;
StringBuilder finalOutput = new StringBuilder();
par.getCombinedMessages(par, finalOutput);
String outs = finalOutput.toString();
if (!StringUtils.ok(outs)) {
par.getTopMessagePart().setMessage(strings.getLocalString("get.mon.no.data", "No monitoring data to report.") + "\n");
}
}
}
/**
* This will create a unique SessionId, Max-Age,Version,Path to be added to the Set-Cookie header
*/
public NewCookie getJSessionCookie(Cookie jSessionId) {
String value;
// If the request has a Cookie header and
// there is no failover then send back the same
// JSESSIONID
if (jSessionId != null && isJSessionCookieOk(jSessionId.getValue())) {
value = jSessionId.getValue();
} else {
value = uuidGenerator.generateUuid() + '.' + getServerName();
}
NewCookie result = new NewCookie(SESSION_COOKIE_NAME, value, "/command", null, null, MAX_AGE, false);
return result;
}
private boolean isJSessionCookieOk(String value) {
if (!StringUtils.ok(value)) {
return false;
}
return value.endsWith("." + getServerName());
}
private static boolean isSingleInstanceCommand(CommandModel model) {
if (model != null ) {
ExecuteOn executeOn = model.getClusteringAttributes();
if ((executeOn != null) && (executeOn.value().length ==1) &&
executeOn.value()[0].equals(RuntimeType.SINGLE_INSTANCE)) {
return true;
}
}
return false;
}
private static String leadingSpacesToNbsp(String str) {
if (str == null) {
return null;
}
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) != ' ') {
StringBuilder sb = new StringBuilder((i * 6) + (str.length() - i));
for (int j = 0; j < i; j++) {
sb.append(" ");
}
sb.append(str.substring(i));
return sb.toString();
}
}
return str;
}
private CommandModel getCommandModel(CommandName commandName) throws WebApplicationException {
CommandRunner cr = getCommandRunner();
CommandModel model = cr.getModel(commandName.getScope(), commandName.getName(), logger);
if (model == null) {
throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND)
.type(MediaType.TEXT_PLAIN)
.entity(strings.getLocalString("adapter.command.notfound",
"Command {0} not found. \nCheck the entry of command name. This command may be provided by a package that is not installed.", commandName.getName()))
.build());
}
return model;
}
private BufferedReader getManPageReader(CommandName commandName) throws WebApplicationException {
CommandModel model = getCommandModel(commandName);
return getCommandRunner().getHelp(model);
}
private CommandRunner getCommandRunner() {
if (this.commandRunner == null) {
commandRunner = getHabitat().getService(CommandRunner.class);
}
return this.commandRunner;
}
private ServiceLocator getHabitat() {
return Globals.getDefaultHabitat();
}
private String getServerName() {
if (serverName == null) {
Server server = getHabitat().getService(Server.class, ServerEnvironment.DEFAULT_INSTANCE_NAME);
if (server != null) {
serverName = server.getName();
}
}
return serverName;
}
private Subject getSubject() {
return subjectRef.get();
}
private static class CommandName {
private String scope;
private String name;
public CommandName(String scope, String name) {
this.scope = scope;
this.name = name;
}
public CommandName(String fullName) {
if (fullName == null) {
return;
}
int ind = fullName.indexOf('/');
if (ind > 0) {
this.scope = fullName.substring(0, ind + 1);
this.name = fullName.substring(ind + 1);
} else {
this.name = fullName;
}
}
public String getName() {
return name;
}
public String getScope() {
return scope;
}
@Override
public String toString() {
if (this.scope == null) {
return "CommandName[" + name + "]";
} else {
return "CommandName[" + scope + name + "]";
}
}
}
}