/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.
*/
/**
* @author Z.Paulovics
*/
package org.jboss.arquillian.container.glassfish.clientutils;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.multipart.FormDataMultiPart;
import org.jboss.arquillian.container.glassfish.CommonGlassFishConfiguration;
import org.jboss.arquillian.container.spi.client.protocol.metadata.HTTPContext;
import org.jboss.arquillian.container.spi.client.protocol.metadata.Servlet;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GlassFishClientService implements GlassFishClient {
private static final String WEBMODULE = "WebModule";
private static final String SERVLET = "Servlet";
private static final String RUNNING_STATUS = "RUNNING";
private String target = GlassFishClient.ADMINSERVER;
private String adminBaseUrl;
private String DASUrl;
CommonGlassFishConfiguration configuration;
private ServerStartegy serverInstance = null;
private GlassFishClientUtil clientUtil;
private NodeAddress nodeAddress = null;
private int majorVersion = 3;
private int minorVersion;
private static final Logger log = Logger.getLogger(GlassFishClientService.class.getName());
// GlassFish client service constructor
public GlassFishClientService(CommonGlassFishConfiguration configuration) {
this.configuration = configuration;
this.target = configuration.getTarget();
final StringBuilder adminUrlBuilder = new StringBuilder()
.append(NodeAddress.getHttpProtocolPrefix(this.configuration.isAdminHttps()))
.append(this.configuration.getAdminHost()).append(":")
.append(this.configuration.getAdminPort());
DASUrl = adminUrlBuilder.toString();
adminUrlBuilder.append("/management/domain");
this.adminBaseUrl = adminUrlBuilder.toString();
// Start up the jersey client layer
this.clientUtil = new GlassFishClientUtil(configuration, adminBaseUrl);
}
/**
* Start-up the server
* <p>
* - Get the node addresses list associated with the target
* - Pull the server instances status form mgm API
* - In case of cluster tries to fund an instance which has
* RUNNING status
*
* @return none
*/
public void startUp() throws GlassFishClientException {
Map<String, String> standaloneServers = new HashMap<String, String>();
Map<String, String> clusters = new HashMap<String, String>();
String message;
try {
standaloneServers = getServersList();
} catch (ClientHandlerException ch) {
message = "Could not connect to DAS on: " + getDASUrl() + " | "
+ ch.getCause().getMessage();
throw new GlassFishClientException(message);
}
if (GlassFishClient.ADMINSERVER.equals(getTarget())) {
// The "target" is the Admin Server Instance
serverInstance = new AdminServer();
} else if (standaloneServers.containsKey(getTarget())) {
// The "target" is an Standalone Server Instance
serverInstance = new StandaloneServer();
} else {
// The "target" shall be clustered instance(s)
clusters = getClustersList();
if (clusters != null && clusters.containsKey(getTarget())) {
// Now we have found the cluster specified by the Target attribute
serverInstance = new ClusterServer();
} else {
// The "target" attribute can be a domain or misspelled, but neither can be accepted
message = "The target property: " + getTarget() + " is not a valid target";
throw new GlassFishClientException(message);
}
}
setGlassFishVersion();
// Fetch the HOST address & HTTP port info from the DAS server
List<NodeAddress> nodeAddressList = (List<NodeAddress>) serverInstance.getNodeAddressList();
if (GlassFishClient.ADMINSERVER.equals(configuration.getTarget())) {
// Admin Server must running, otherwise we can not be here
this.nodeAddress = nodeAddressList.get(0);
} else {
// Returns the nodeAddress if the target instance status is RUNNING
// In case of cluster, returns the first RUNNING instance (if any) from the list
this.nodeAddress = runningInstanceFilter(nodeAddressList);
}
}
private static final String GLASSFISH_VERSION = "/version";
private void setGlassFishVersion() {
Map responseMap = getClientUtil().GETRequest(GLASSFISH_VERSION);
if (responseMap != null) {
Map extraProperties = (Map) responseMap.get("extraProperties");
if (extraProperties != null) {
Object versionNumberObj = extraProperties.get("version-number");
if (versionNumberObj != null && versionNumberObj instanceof String) {
String version = (String) versionNumberObj;
StringTokenizer tokenizer = new StringTokenizer(version, ".");
if (tokenizer.hasMoreElements()) {
try {
majorVersion = Integer.valueOf(tokenizer.nextToken());
} catch (NumberFormatException ignore) {
log.info("Exception getting major version for: " + version);
}
}
if (tokenizer.hasMoreElements()) {
try {
minorVersion = Integer.valueOf(tokenizer.nextToken());
} catch (NumberFormatException ignore) {
log.info("Exception getting minor version for: " + version);
}
}
}
}
}
}
/**
* Filtering on the status of the instances
* - If the standalone server instance status is RUNNING, returns the nodeAddress,
* but throws an exception otherwise.
* - In case of cluster, returns the first RUNNING instance from the list,
* but throws an exception if can not find any.
*
* @param nodeAddressList
* @return nodeAddress - if any has RUNNING status
*/
// the REST resource path template to retrieve the list of server instances
private static final String INSTACE_LIST = "/list-instances";
private NodeAddress runningInstanceFilter(List<NodeAddress> nodeAddressList) {
List<Map> instanceList = getClientUtil().getInstancesList(INSTACE_LIST);
String instanceStatus = null;
for (Map instance : instanceList) {
for (NodeAddress node : nodeAddressList) {
if (instance.get("name").equals(node.getServerName())) {
instanceStatus = (String) instance.get("status");
if (RUNNING_STATUS.equals(instanceStatus)) {
return node;
}
}
}
}
String message;
if (nodeAddressList.size() == 1) {
message = "The " + nodeAddressList.get(0).getServerName() + " server-instance status is: "
+ instanceStatus;
throw new GlassFishClientException(message);
} else {
message = "Could not fund any instance with RUNNING status in cluster: " + getTarget();
throw new GlassFishClientException(message);
}
}
/**
* Do deploy an application defined by a multipart form's fileds
* to a target server or a cluster of GlassFish 3.1
*
* @param name - name of the appliacation
* form - a form of MediaType.MULTIPART_FORM_DATA_TYPE
* @return subComponents - a map of SubComponents of the application
*/
// the REST resource path template to retrieve the list of server instances
private static final String APPLICATION = "/applications/application";
private static final String APPLICATION_RESOURCE = "/applications/application/{name}";
public HTTPContext doDeploy(String name, FormDataMultiPart form) {
String listSubComponents;
if (majorVersion >= 4) {
listSubComponents = "/applications/application/{application}/list-sub-components";
// listSubComponents = "/applications/application/{application}/list-sub-components?type=servlets";
} else {
listSubComponents = "/applications/application/list-sub-components?id={application}";
}
Map<String, String> SubComponents = new HashMap<String, String>();
// Deploy the application on the GlassFish server
getClientUtil().POSTMultiPartRequest(APPLICATION, form);
// Fetch the list of SubComponents of the application
String path = listSubComponents.replace("{application}", name);
Map subComponentsResponce = getClientUtil().GETRequest(path);
Map<String, String> subComponents = (Map<String, String>) subComponentsResponce.get("properties");
// Build up the HTTPContext object using the nodeAddress information
int port = nodeAddress.getHttpPort();
HTTPContext httpContext = new HTTPContext(nodeAddress.getHost(), port);
// Add the servlets to the HTTPContext
String componentName;
String contextRoot = getApplicationContextRoot(name);
if (subComponents != null) {
for (Map.Entry subComponent : subComponents.entrySet()) {
componentName = subComponent.getKey().toString();
if (WEBMODULE.equals(subComponent.getValue())) {
List<Map> children = (List<Map>) subComponentsResponce.get("children");
// Override the application contextRoot by the webmodul's contextRoot
contextRoot = resolveWebModuleContextRoot(componentName, children);
resolveWebModuleSubComponents(name, componentName, contextRoot, httpContext);
} else if (SERVLET.equals(subComponent.getValue())) {
httpContext.add(new Servlet(componentName, contextRoot));
}
}
}
return httpContext;
}
/**
* Undeploy the component
*
* @param name
* - application name
* form - form that include the target & operation fields
*
* @return resultMap
*/
public Map doUndeploy(String name, FormDataMultiPart form) {
String path = APPLICATION_RESOURCE.replace("{name}", name);
return getClientUtil().POSTMultiPartRequest(path, form);
}
/**
* Verify if the DAS is running or not.
*/
public boolean isDASRunning() {
try {
getClientUtil().GETRequest("");
} catch (ClientHandlerException clientEx) {
if (clientEx.getCause().getClass().equals(ConnectException.class)) {
// We were unable to connect to the DAS through Jersey
return false;
}
}
return true;
}
/**
* Get the standalone servers list associated with the DAS
*
* @param none
* @return map of standalone servers
*/
private static final String STANALONE_SERVER_INSTACES = "/servers/server";
private Map<String, String> getServersList() {
Map<String, String> standaloneServers = getClientUtil().getChildResources(STANALONE_SERVER_INSTACES);
return standaloneServers;
}
/**
* Get the list of clusters
*
* @param none
* @return map of clusters
*/
private static final String CLUSTERED_SERVER_INSTACES = "/clusters/cluster";
private Map<String, String> getClustersList() {
Map<String, String> clusters = getClientUtil().getChildResources(CLUSTERED_SERVER_INSTACES);
return clusters;
}
/**
* Get the contextroot associated with the application
*
* @param name
* - application name
*
* @return contextRoot attribute of the application
*/
private String getApplicationContextRoot(String name) {
String path = APPLICATION_RESOURCE.replace("{name}", name);
Map<String, String> applicationAttributes = getClientUtil().getAttributes(path);
// pull the contextRoot from the applicasion's attributes
String contextRoot = ((Object) applicationAttributes.get("contextRoot")).toString();
return contextRoot;
}
private String resolveWebModuleContextRoot(String componentName, List<Map> modules) {
String contextRoot = null;
for (Map module : modules) {
Map<String, String> moduleProperties = (Map<String, String>) module.get("properties");
if (moduleProperties != null && !moduleProperties.isEmpty()) {
String moduleInfo = moduleProperties.get("moduleInfo");
if (moduleInfo.startsWith(componentName)) {
// Get the webmodule's contextRoot
// The moduleInfo property has the format - moduleArchiveURI:moduleType:contextRoot
// The contextRoot is extracted, and removed of any prefixed slash.
String[] moduleInfoElements = moduleInfo.split(":");
contextRoot = moduleInfoElements[2];
contextRoot = contextRoot.indexOf("/") > -1 ? contextRoot.substring(contextRoot.indexOf("/"))
: contextRoot;
}
} else {
throw new GlassFishClientException("Cuold not resolve the web-module contextRoot");
}
}
return contextRoot;
}
/**
* Lookup the servlets of WebModule & putt them to the httpContext associated with the application
*
* @param name
* - application name
* @param module
* - webmodule name
* @param context
* - contextRoot of the web-module
* @param httpContext
* - httpContext to be updated
*/
private void resolveWebModuleSubComponents(String name, String module, String context, HTTPContext httpContext) {
String webmoduleResource = "";
if (majorVersion >= 4) {
webmoduleResource =
"/applications/application/{application}/list-sub-components?appname={application}&id={module}&type=servlets";
} else {
webmoduleResource =
"/applications/application/list-sub-components?appname={application}&id={module}&type=servlets";
}
// Fetch the list of SubComponents of the application
String applicationPath = webmoduleResource.replace("{application}", name);
String modulePath = applicationPath.replace("{module}", module);
Map subComponentsResponce = getClientUtil().GETRequest(modulePath);
Map<String, String> subComponents = (Map<String, String>) subComponentsResponce.get("properties");
String componentName;
for (Map.Entry subComponent : subComponents.entrySet()) {
componentName = subComponent.getKey().toString();
httpContext.add(new Servlet(componentName, context));
}
}
/**
* Get the list of server instances of the cluster
*
* @param target
* @return server instances map
*/
// the REST resource path template to retrieve the list of server instances
private static final String MEMBER_SERVERS_RESOURCE = "/clusters/cluster/{target}/server-ref";
protected Map<String, String> getServerInstances(String target) {
String path = MEMBER_SERVERS_RESOURCE.replace("{target}", target);
Map<String, String> serverInstances = getClientUtil().getChildResources(path);
return serverInstances;
}
/**
* Get the serverAttributes map of a server
*
* @param name of the server
* @return serverAttributes map
* nodeRef: - reference to the node object
* configRef: - reference to the server's configuration object
* ...
*/
// the REST resource path template for server attributes object
private static final String SERVER_RESOURCE = "/servers/server/{server}";
protected Map<String, String> getServerAttributes(String server) {
String path = SERVER_RESOURCE.replace("{server}", server);
return getClientUtil().getAttributes(path);
}
/**
* Get the clusterAttributes map of a cluster
*
* @param name of the cluster
* @return serverAttributes map
* configRef: - reference to the cluster's configuration object
* ...
*/
// the REST resource path template for cluster attributes object
private static final String CLUSTER_RESOURCE = "/clusters/cluster/{cluster}";
protected Map<String, String> getClusterAttributes(String cluster) {
String path = CLUSTER_RESOURCE.replace("{cluster}", cluster);
return getClientUtil().getAttributes(path);
}
/**
* Get the HOST address (IP or name) of the node associated with the server
*
* @param node name
* @return nodeAttributes map
*/
// the REST resource path template for the particular server object
private static final String NODE_RESOURCE = "/nodes/node/{node}";
protected String getHostAddress(Map<String, String> serverAttributes) {
String path = NODE_RESOURCE.replace("{node}", serverAttributes.get("nodeRef"));
String nodeHost = getClientUtil().getAttributes(path).get("nodeHost");
// If the host address returned by DAS was "localhost", it could be "localhost" in the context of DAS, but not Arquillian.
// This would result in Arquillian connecting to localhost, even though the DAS (and it's localhost) is on a separate machine.
// This is the case when the Glassfish installer or asadmin creates a localhost node with node-host set to "localhost" instead of a FQDN.
// Variants of "localhost" like "127.0.0.1" or ::1 are not addressed, as the installer/asadmin does not appear to set the node-host to such values.
// In such a scenario, the adminHost (DAS) known to Arquillian (from arquillian.xml) will be used as the nodeHost.
// All conditions are addressed:
// 1. If adminHost is "localhost", and the node-host registered in DAS is "localhost", then the node-host is set to "localhost". No harm done.
// 2. If adminHost is not "localhost", and the node-host registered in DAS is "localhost", then the node-host value will be set to the same as adminHost.
// Prevents Arquillian from connecting to a wrong address (localhost) to run the tests via ArquillianTestRunner.
// 3. If adminHost is "localhost" and the node-host registered in DAS is not "localhost", then the value from DAS will be used.
// 4. If adminHost is not "localhost" and the node-host registered in DAS is not "localhost", then the value from DAS will be used.
if (nodeHost.equals("localhost")) {
nodeHost = configuration.getAdminHost();
}
return nodeHost;
}
private static final String SYSTEM_PROPERTY = "/configs/config/{config}/system-property/{system-property}";
/**
* Get the port number defined as a system property in a configuration.
*
* @param attributes
* The attributes which references the configuration (server or
* cluster configuration)
* @param propertyName
* The name of the system property to resolve
*
* @return The port number stored in the system property
*/
private int getSystemProperty(Map<String, String> attributes, String propertyName) {
String propertyPath = SYSTEM_PROPERTY.replace("{config}", attributes.get("configRef"));
Map<String, String> listener = getClientUtil().getAttributes(
propertyPath.replace("{system-property}", propertyName));
return Integer.parseInt(listener.get("value"));
}
private static final String SERVER_PROPERTY = "/servers/server/{server}/system-property/{system-property}";
/**
* Get the port number defined as a system property in a configuration, and
* overridden at the level of the server instance.
*
* @param server
* The name of the server instance
* @param propertyName
* The name of the system property to resolve
* @param defaultValue
* The default port number to be used, in case the system
* property is not overridden
*
* @return The port number stored in the system property
*/
private int getServerSystemProperty(String server, String propertyName, int defaultValue) {
String listenerpath = SERVER_PROPERTY.replace("{server}", server);
Map<String, String> listener = getClientUtil().getAttributes(
listenerpath.replace("{system-property}", propertyName));
return (listener.get("value") != null) ? Integer.parseInt(listener.get("value")) : defaultValue;
}
/**
* Get the http/https port number of the server instance
* <p>
* The attribute is optional, It is generated by the Glassfish server
* if we have more then one server instance on the same node.
*
* @param server name
* secure: false - http port number, true - https port number
* @return http/https port number. If the attribute is not defined, gives back the default port
*/
// the REST resource path template for the Servers instance http-listener object
private static final String HTTP_LISTENER_INS = "/servers/server/{server}/system-property/{http-listener}";
protected int getServerInstanceHttpPort(String server, int default_port, boolean secure) {
String listenerpath = HTTP_LISTENER_INS.replace("{server}", server);
String httpListener = (!secure) ? "HTTP_LISTENER_PORT" : "HTTP_SSL_LISTENER_PORT";
Map<String, String> listener = getClientUtil().getAttributes(
listenerpath.replace("{http-listener}", httpListener));
return (listener.get("value") != null) ? Integer.parseInt(listener.get("value")) : default_port;
}
private static final String VIRTUAL_SERVERS =
"/configs/config/{config}/http-service/list-virtual-servers?target={target}";
/**
* Obtains the list of virtual servers associated with the deployment
* target. This method omits '__asadmin' in the result, as no deployments
* can target this virtual server.
*
* @param attributes
* The attributes which references the configuration (server or
* cluster configuration)
*
* @return A list of virtual server names that have been found in the
* server/cluster configuration
*/
private List<String> getVirtualServers(Map<String, String> attributes) {
String virtualServerPath = VIRTUAL_SERVERS.replace("{config}", attributes.get("configRef")).replace("{target}",
attributes.get("name"));
Map virtualServersResponse = getClientUtil().GETRequest(virtualServerPath);
List<Map> virtualServers = (List<Map>) virtualServersResponse.get("children");
List<String> virtualServerNames = new ArrayList<String>();
for (Map virtualServer : virtualServers) {
String virtualServerName = (String) virtualServer.get("message");
if (!virtualServerName.equals("__asadmin")) {
virtualServerNames.add(virtualServerName);
}
}
return virtualServerNames;
}
private static final String VIRTUAL_SERVER = "/configs/config/{config}/http-service/virtual-server/{virtualServer}";
/**
* Obtains the list of all network listeners associated with the list of
* provided virtual servers.
*
* @param attributes
* The attributes which references the configuration (server or
* cluster configuration)
* @param virtualServers
* The {@link List} of all virtual servers whose the listeners
* must be retrieved
*
* @return The list of all listener names associated with the provided list
* of virtual servers
*/
private List<String> getNetworkListeners(Map<String, String> attributes, List<String> virtualServers) {
List<String> networkListeners = new ArrayList<String>();
for (String virtualServer : virtualServers) {
String virtualServerPath = VIRTUAL_SERVER.replace("{config}", attributes.get("configRef")).replace(
"{virtualServer}", virtualServer);
Map<String, String> virtualServerAttributes = getClientUtil().getAttributes(virtualServerPath);
String listenerList = virtualServerAttributes.get("networkListeners");
String[] listeners = listenerList.split(",");
for (String listener : listeners) {
networkListeners.add(listener.trim());
}
}
return networkListeners;
}
private static final String LISTENER =
"/configs/config/{config}/network-config/network-listeners/network-listener/{listener}";
/**
* Obtains the value of a HTTP/HTTPS network listener, as stored in the
* GlassFish configuration.
*
* @param attributes
* The attributes which references the configuration (server or
* cluster configuration)
* @param networkListeners
* The {@link List} of network listeners among which one will be
* chosen
* @param secure
* Should a listener with a secure protocol be chosen?
*
* @return The value of the port number stored in the chosen listener
* configuration. This may be parseable as a number, but not
* necessarily so. Sometimes a system property might be returned.
*/
private String getActiveHttpPort(Map<String, String> attributes, List<String> networkListeners, boolean secure) {
for (String networkListener : networkListeners) {
String listenerPath = LISTENER.replace("{config}", attributes.get("configRef")).replace("{listener}",
networkListener);
Map<String, String> listenerAttributes = getClientUtil().getAttributes(listenerPath);
boolean enabled = Boolean.parseBoolean(listenerAttributes.get("enabled"));
if (!enabled) {
continue;
}
String port = listenerAttributes.get("port");
String protocolName = listenerAttributes.get("protocol");
boolean secureProtocol = isSecureProtocol(attributes, protocolName);
if (secure && secureProtocol) {
return port;
} else if (!secure && !secureProtocol) {
return port;
}
}
return null;
}
private static final String PROTOCOL = "/configs/config/{config}/network-config/protocols/protocol/{protocol}";
/**
* Determines whether the protocol associated with the listener is a secure
* protocol or not.
*
* @param attributes
* The attributes which references the configuration (server or
* cluster configuration)
* @param protocolName
* The name of the protocol
*
* @return A boolean value indicating whether a protocol is secure or not
*/
private boolean isSecureProtocol(Map<String, String> attributes, String protocolName) {
String protocolPath = PROTOCOL.replace("{config}", attributes.get("configRef")).replace("{protocol}",
protocolName);
Map<String, String> protocolAttributes = getClientUtil().getAttributes(protocolPath);
boolean isSecure = Boolean.parseBoolean(protocolAttributes.get("securityEnabled"));
return isSecure;
}
private static final String SYSTEM_PROPERTY_REGEX = "\\$\\{(.*)\\}";
/**
* Get the port number of a network listener. Firstly, this method parses
* the provided String as a number. If this fails, the provided String is
* parsed as a system property stored in the format -
* <blockquote>${systemProperty}</blockquote>. The value of the referenced
* system property is then read from the GlassFish configuration.
*
* @param attributes
* The attributes which references the configuration (server or
* cluster configuration)
* @param serverName
* The name of the server instance
* @param portNum
* The port number or a system property that stores the port
* number
*
* @return The port number as stored in the network listener configuration
* or in the system property
*/
private int getPortValue(Map<String, String> attributes, String serverName, String portNum) {
int portValue = -1;
try {
portValue = Integer.parseInt(portNum);
} catch (NumberFormatException formatEx) {
Pattern propertyRegex = Pattern.compile(SYSTEM_PROPERTY_REGEX);
Matcher matcher = propertyRegex.matcher(portNum);
if (matcher.find()) {
String propertyName = matcher.group(1);
portValue = getSystemProperty(attributes, propertyName);
portValue = getServerSystemProperty(serverName, propertyName, portValue);
}
}
return portValue;
}
private CommonGlassFishConfiguration getConfiguration() {
return configuration;
}
private String getTarget() {
return target;
}
private void setTarget(String target) {
this.target = target;
}
private GlassFishClientUtil getClientUtil() {
return clientUtil;
}
/**
* Get the URL of the DAS server
*
* @return URL
*/
private String getDASUrl() {
return DASUrl;
}
/**
* The GoF Strategy pattern is used to implement specific algorithm
* by server type (Admin, Standalone or Clustered server)
* <p>
* The attribute is optional, It is generated by the Glassfish server
* if we have more then one server instance on the same node or
* explicitly defined by the create command parameter.
*
* @param server
* name
* secure: false - http port number, true - https port number
*
* @return http/https port number. If the attribute is not defined, gives back the default port
*/
abstract class ServerStartegy {
/**
* Address list of the node(s) on GlassFish Appserver
*/
private List<NodeAddress> nodes = new ArrayList<NodeAddress>();
protected GlassFishClientService glassFishClient;
protected ServerStartegy() {
}
protected List<NodeAddress> getNodes() {
return nodes;
}
protected void setNodes(List<NodeAddress> nodes) {
this.nodes = nodes;
}
protected void addNode(NodeAddress node) {
nodes.add(node);
}
protected GlassFishClientService getGlassFishClient() {
return glassFishClient;
}
/**
* Get the the node address list associated with the target
*
* @return list of node address objects
*/
protected abstract List<NodeAddress> getNodeAddressList();
}
class AdminServer extends ServerStartegy {
public AdminServer() {
super();
}
@Override
public List<NodeAddress> getNodeAddressList() {
String nodeHost = "localhost"; // default host
setNodes(new ArrayList<NodeAddress>());
// getting the server attributes is happening too fast. The admin server hasn't started yet.
int count = 10;
Map<String, String> serverAttributes = getServerAttributes(GlassFishClient.ADMINSERVER);
while (serverAttributes.size() == 0 && count-- > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignore) {
}
serverAttributes = getServerAttributes(GlassFishClient.ADMINSERVER);
}
// Get the host address of the Admin Server
nodeHost = (String) getConfiguration().getAdminHost();
// Get the virtual servers and the associated network listeners for the DAS.
// We'll not verify if the listeners are bound to private IP
// addresses, or reachable from the Arquillian test client.
List<String> virtualServers = getVirtualServers(serverAttributes);
List<String> networkListeners = getNetworkListeners(serverAttributes, virtualServers);
String httpPortNum = getActiveHttpPort(serverAttributes, networkListeners, false);
String httpsPortNum = getActiveHttpPort(serverAttributes, networkListeners, true);
int httpPort = getPortValue(serverAttributes, getTarget(), httpPortNum);
// A HTTPS listener might not exist in the DAS config.
// And Arquillian requires a HTTP port for now.
// So, we'll parse the HTTPS config conditionally.
int httpsPort = -1;
if (httpsPortNum != null && !httpsPortNum.equals("")) {
httpsPort = getPortValue(serverAttributes, getTarget(), httpsPortNum);
}
addNode(new NodeAddress(GlassFishClient.ADMINSERVER, nodeHost, httpPort, httpsPort));
return getNodes();
}
}
class StandaloneServer extends ServerStartegy {
public StandaloneServer() {
super();
}
@Override
public List<NodeAddress> getNodeAddressList() {
String nodeHost = "localhost"; // default host
setNodes(new ArrayList<NodeAddress>());
Map<String, String> serverAttributes = getServerAttributes(getTarget());
// Get the host address of the Admin Server
nodeHost = getHostAddress(serverAttributes);
// Get the virtual servers and the associated network listeners for the DAS.
// We'll not verify if the listeners are bound to private IP addresses,
// or reachable from the Arquillian test client.
List<String> virtualServers = getVirtualServers(serverAttributes);
List<String> networkListeners = getNetworkListeners(serverAttributes, virtualServers);
String httpPortNum = getActiveHttpPort(serverAttributes, networkListeners, false);
String httpsPortNum = getActiveHttpPort(serverAttributes, networkListeners, true);
int httpPort = getPortValue(serverAttributes, getTarget(), httpPortNum);
// A HTTPS listener might not exist in the instance config.
// And Arquillian requires a HTTP port for now.
// So, we'll parse the HTTPS config conditionally.
int httpsPort = -1;
if (httpsPortNum != null && !httpsPortNum.equals("")) {
httpsPort = getPortValue(serverAttributes, getTarget(), httpsPortNum);
}
addNode(new NodeAddress(getTarget(), nodeHost, httpPort, httpsPort));
return getNodes();
}
}
class ClusterServer extends ServerStartegy {
public ClusterServer() {
super();
}
@Override
public List<NodeAddress> getNodeAddressList() {
String nodeHost = "localhost"; // default host
setNodes(new ArrayList<NodeAddress>());
Map<String, String> serverAttributes;
// Get the REST resource for the cluster attributes, to reference the config-ref later
Map<String, String> clusterAttributes = getClusterAttributes(getTarget());
// Fetch the list of server instances of the cluster
Map<String, String> serverInstances = getServerInstances(getTarget());
// Get the virtual servers and the associated network listeners for the cluster.
// GlassFish clusters are homogeneous and the virtual servers and network listeners
// will be present on every cluster instance; only port numbers for the listener may vary.
// We'll not verify if the listeners are bound to private IP addresses,
// or reachable from the Arquillian test client.
List<String> virtualServers = getVirtualServers(clusterAttributes);
List<String> networkListeners = getNetworkListeners(clusterAttributes, virtualServers);
// Obtain a HTTP and a HTTPS port that have been enabled on the
// virtual server.
String httpPortNum = getActiveHttpPort(clusterAttributes, networkListeners, false);
String httpsPortNum = getActiveHttpPort(clusterAttributes, networkListeners, true);
for (Map.Entry serverInstance : serverInstances.entrySet()) {
String serverName = serverInstance.getKey().toString();
serverAttributes = getServerAttributes(serverName);
nodeHost = getHostAddress(serverAttributes);
int httpPort = getPortValue(clusterAttributes, serverName, httpPortNum);
// A HTTPS listener might not exist in the cluster config.
// And Arquillian requires a HTTP port for now.
// So, we'll parse the HTTPS config conditionally.
int httpsPort = -1;
if (httpsPortNum != null && !httpsPortNum.equals("")) {
httpsPort = getPortValue(clusterAttributes, serverName, httpsPortNum);
}
addNode(new NodeAddress(serverName, nodeHost, httpPort, httpsPort));
}
return getNodes();
}
}
}